diff --git a/DEPS b/DEPS index ec0e074..4f3f84b 100644 --- a/DEPS +++ b/DEPS
@@ -121,11 +121,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': '31c4bcb210bd1232ce8c15ff659b6807b9437466', + 'skia_revision': '5820b0c3f3ceba23b9d80415e77a9db124b409b8', # 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': 'eb3331670c3b1d42ba2e79623a56b50df08b4094', + 'v8_revision': '686bde10b4672f2a67745b692f281d61ae0d9d5c', # 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. @@ -133,7 +133,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': '9fa54eab259042ac7040d0ff0b633bdd993ecf89', + 'angle_revision': '225f08bf85a368f905362cdd1366e4795680452c', # 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. @@ -169,7 +169,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': '1e2123822ca7424ac63ecdf241af0da87d3ec740', + 'nacl_revision': '202ccbd707ded4002aa402b9da0ea4e4026f3a1d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -181,7 +181,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': '35caab8b839f1e5d3713ff6ed84fbc1b3b4a1970', + 'catapult_revision': 'ebf0d23ee62ec1b476cc8a0c8616b6d295271680', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -229,7 +229,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': '241644a5a398ef9686ce95aa3411aa1593a54301', + 'spv_tools_revision': 'a900bacb58c359419db80ec0bf8c44c66ae4c61f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -245,7 +245,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '74ec15010f8a3cc14854ceba15b7fe0b78f3a0b1', + 'dawn_revision': '0b364067d04c49fa2f828905300bd7eb56dd3b9b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -679,7 +679,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'b5f346a1b0b49908f52d918b1b6f849a11937dda', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c48496fe54a9ff1850b2b718697d29d4a1264ff4', 'condition': 'checkout_linux', }, @@ -694,7 +694,7 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '44b6331b895d29946fa5f8f4e39f2128e58294f7', + 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '825055dd83837f1bb88332a0bad712e95651eb67', 'condition': 'checkout_linux', }, @@ -704,7 +704,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'db0055dc786a71fe81e720bad2b1acb0e133a291', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '4ad409510d23a438265bf225b544d010e5b5f678', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1199,7 +1199,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a2b35635aaef3e9301d69f77f9a0a3fd99291b08', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'c63ddb2a3f9abbeeeebe16c00231fd2014973cbe', + Var('webrtc_git') + '/src.git' + '@' + '3f2b9aad4a054c7b07957c9064083c71276291e9', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1230,7 +1230,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@943e9fdb7885fbe8b428348d4df7820b583fe2ca', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@447d7854291eb3325cbc58c413f4a3f7b3faf263', 'condition': 'checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index a9b33574..fde1d16 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -779,6 +779,9 @@ 'components_deps': { 'filepath': 'components/([^/]*/)*DEPS', }, + 'compositor_animator': { + 'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/compositor/animation/', + }, 'content_bluetooth': { 'filepath': 'content/.*bluetooth' }, @@ -2149,6 +2152,7 @@ 'components_deps': ['blundell+watchlist@chromium.org', 'droger+watchlist@chromium.org', 'sdefresne+watchlist@chromium.org'], + 'compositor_animator': ['mdjones+watch@chromium.org'], 'content_bluetooth': ['mattreynolds+watch@chromium.org', 'ortuno+watch@chromium.org'], 'content_loader': ['loading-reviews@chromium.org'],
diff --git a/android_webview/docs/commandline-flags.md b/android_webview/docs/commandline-flags.md new file mode 100644 index 0000000..6bbad875 --- /dev/null +++ b/android_webview/docs/commandline-flags.md
@@ -0,0 +1,62 @@ +# Commandline flags + +## Applying flags + +**Note:** this requires either a `userdebug` or `eng` Android build (you can +check with `adb shell getprop ro.build.type`). Flags cannot be enabled on +production builds of Android. + +WebView reads flags from a specific file during startup. To enable flags, write +to the file with: + +```sh +$ # Overwrites all flags (and prints the new flag state): +$ build/android/adb_system_webview_command_line \ + --show-composited-layer-borders \ + --log-net-log=foo.json # Supports multiple flags +$ # Simply prints the existing flag state): +$ build/android/adb_system_webview_command_line +$ # Passing empty string clears all flags: +$ build/android/adb_system_webview_command_line "" +``` + +Or, you can use the `adb` in your `$PATH` like so: + +```sh +$ FLAG_FILE=/data/local/tmp/webview-command-line +$ adb shell "echo '_ --show-composited-layer-borders' > ${FLAG_FILE}" +$ # The first token is ignored. We use '_' as a convenient placeholder, but any +$ # token is acceptable. +``` + +**Note:** either set of commands will overwrite existing flags. + +### Applying Features with flags + +WebView supports the same `--enable-features=feature1,feature2` and +`--disable-features=feature3,feature4` syntax as the rest of Chromium. You can +use these like any other flag. Please consult +[`base/feature_list.h`](https://cs.chromium.org/chromium/src/base/feature_list.h) +for details. + +## Interesting flags + +WebView supports any flags supported in any layer we depend on (ex. content). +Some interesting flags and Features: + + * `--show-composited-layer-borders` + * `--enable-features=NetworkService,NetworkServiceInProcess` + * `--log-net-log=<filename.json>` + +WebView also defines its own flags and Features: + + * [AwSwitches.java](https://cs.chromium.org/chromium/src/android_webview/java/src/org/chromium/android_webview/AwSwitches.java) + (and its [native + counterpart](https://cs.chromium.org/chromium/src/android_webview/common/aw_switches.h)) + * [AwFeatureList.java](https://cs.chromium.org/chromium/src/android_webview/java/src/org/chromium/android_webview/AwFeatureList.java) + (and its [native + counterpart](https://cs.chromium.org/chromium/src/android_webview/browser/aw_feature_list.h)) + +## Implementation + +See [CommandLineUtil.java](https://cs.chromium.org/chromium/src/android_webview/java/src/org/chromium/android_webview/command_line/CommandLineUtil.java).
diff --git a/android_webview/tools/system_webview_shell/apk/res/menu/main_menu.xml b/android_webview/tools/system_webview_shell/apk/res/menu/main_menu.xml index ba7c79eb..cc94cf2 100644 --- a/android_webview/tools/system_webview_shell/apk/res/menu/main_menu.xml +++ b/android_webview/tools/system_webview_shell/apk/res/menu/main_menu.xml
@@ -11,6 +11,8 @@ <item android:id="@+id/menu_enable_tracing" android:checkable="true" android:title="@string/menu_enable_tracing"/> + <item android:id="@+id/menu_print" + android:title="@string/menu_print"/> <item android:id="@+id/menu_about" android:title="@string/menu_about"/> </menu>
diff --git a/android_webview/tools/system_webview_shell/apk/res/values/strings.xml b/android_webview/tools/system_webview_shell/apk/res/values/strings.xml index 066c150..7d74335 100644 --- a/android_webview/tools/system_webview_shell/apk/res/values/strings.xml +++ b/android_webview/tools/system_webview_shell/apk/res/values/strings.xml
@@ -17,6 +17,7 @@ <string name="menu_reset_webview">Destroy and create new WebView</string> <string name="menu_clear_cache">Clear cache</string> <string name="menu_enable_tracing">Enable tracing</string> + <string name="menu_print">Print</string> <string name="menu_about">About WebView</string> <string name="load_url">Load URL</string> </resources>
diff --git a/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java b/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java index c3b0a7e..9bcf425 100644 --- a/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java +++ b/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java
@@ -21,6 +21,9 @@ import android.os.Build; import android.os.Bundle; import android.os.StrictMode; +import android.print.PrintAttributes; +import android.print.PrintDocumentAdapter; +import android.print.PrintManager; import android.provider.Browser; import android.util.SparseArray; import android.view.Gravity; @@ -547,6 +550,12 @@ } } return true; + case R.id.menu_print: + PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE); + String jobName = "WebViewShell document"; + PrintDocumentAdapter printAdapter = mWebView.createPrintDocumentAdapter(jobName); + printManager.print(jobName, printAdapter, new PrintAttributes.Builder().build()); + return true; case R.id.menu_about: about(); hideKeyboard(mUrlBar);
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index d4c892d..6de80608 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1836,6 +1836,7 @@ "wm/overlay_event_filter_unittest.cc", "wm/overlay_layout_manager_unittest.cc", "wm/overview/cleanup_animation_observer_unittest.cc", + "wm/overview/scoped_transform_overview_window_unittest.cc", "wm/overview/start_animation_observer_unittest.cc", "wm/overview/window_selector_controller_unittest.cc", "wm/overview/window_selector_unittest.cc",
diff --git a/ash/app_list/views/contents_view.cc b/ash/app_list/views/contents_view.cc index e45c7242..7660a12 100644 --- a/ash/app_list/views/contents_view.cc +++ b/ash/app_list/views/contents_view.cc
@@ -569,7 +569,8 @@ apps_container_view->GetSearchBoxExpectedBounds()))); search_results_page_view()->SetBoundsRect( - apps_container_view->GetSearchBoxExpectedBounds()); + search_results_page_view()->AddShadowBorderToBounds( + apps_container_view->GetSearchBoxExpectedBounds())); apps_container_view->UpdateYPositionAndOpacity(); }
diff --git a/ash/app_list/views/search_box_view.cc b/ash/app_list/views/search_box_view.cc index c839005..200d7f6 100644 --- a/ash/app_list/views/search_box_view.cc +++ b/ash/app_list/views/search_box_view.cc
@@ -60,7 +60,6 @@ constexpr SkColor kSearchBoxBorderColor = SkColorSetARGB(0x3D, 0xFF, 0xFF, 0xFF); -constexpr int kSearchBoxBorderCornerRadiusSearchResult = 4; constexpr int kAssistantIconSize = 24; constexpr int kCloseIconSize = 24; constexpr int kSearchBoxFocusBorderCornerRadius = 28; @@ -304,7 +303,7 @@ ash::AppListState state) const { if (state == ash::AppListState::kStateSearchResults && !app_list_view_->is_in_drag()) { - return kSearchBoxBorderCornerRadiusSearchResult; + return search_box::kSearchBoxBorderCornerRadiusSearchResult; } return search_box::kSearchBoxBorderCornerRadius; }
diff --git a/ash/app_list/views/search_result_page_view.cc b/ash/app_list/views/search_result_page_view.cc index 03162232..9ff0afb 100644 --- a/ash/app_list/views/search_result_page_view.cc +++ b/ash/app_list/views/search_result_page_view.cc
@@ -24,6 +24,7 @@ #include "ui/gfx/geometry/insets.h" #include "ui/gfx/shadow_value.h" #include "ui/views/background.h" +#include "ui/views/bubble/bubble_border.h" #include "ui/views/controls/scroll_view.h" #include "ui/views/controls/scrollbar/overlay_scroll_bar.h" #include "ui/views/controls/textfield/textfield.h" @@ -48,6 +49,9 @@ constexpr SkColor kSeparatorColor = SkColorSetA(gfx::kGoogleGrey900, 0x24); +// The shadow elevation value for the shadow of the expanded search box. +constexpr int kSearchBoxSearchResultShadowElevation = 12; + // A container view that ensures the card background and the shadow are painted // in the correct order. class SearchCardView : public views::View { @@ -82,8 +86,12 @@ class SearchResultPageBackground : public views::Background { public: - SearchResultPageBackground(SkColor color, int corner_radius) - : color_(color), corner_radius_(corner_radius) {} + SearchResultPageBackground(SkColor color, + int corner_radius, + int shadow_inset_top) + : color_(color), + corner_radius_(corner_radius), + shadow_inset_top_(shadow_inset_top) {} ~SearchResultPageBackground() override {} private: @@ -98,13 +106,14 @@ if (bounds.height() <= kSearchBoxHeight) return; // Draw a separator between SearchBoxView and SearchResultPageView. - bounds.set_y(kSearchBoxHeight); + bounds.set_y(kSearchBoxHeight + shadow_inset_top_); bounds.set_height(kSeparatorThickness); canvas->FillRect(bounds, kSeparatorColor); } const SkColor color_; const int corner_radius_; + const int shadow_inset_top_; DISALLOW_COPY_AND_ASSIGN(SearchResultPageBackground); }; @@ -146,11 +155,21 @@ contents_view_->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kVertical, gfx::Insets(), 0)); + // Create and set a shadow to be displayed as a border for this view. + auto shadow_border = std::make_unique<views::BubbleBorder>( + views::BubbleBorder::NONE, views::BubbleBorder::SMALL_SHADOW, + SK_ColorWHITE); + shadow_border->SetCornerRadius( + search_box::kSearchBoxBorderCornerRadiusSearchResult); + shadow_border->set_md_shadow_elevation(kSearchBoxSearchResultShadowElevation); + SetBorder(std::move(shadow_border)); + // Hides this view behind the search box by using the same color and // background border corner radius. All child views' background should be // set transparent so that the rounded corner is not overwritten. SetBackground(std::make_unique<SearchResultPageBackground>( - kCardBackgroundColor, search_box::kSearchBoxBorderCornerRadius)); + kCardBackgroundColor, search_box::kSearchBoxBorderCornerRadius, + border()->GetInsets().top())); views::ScrollView* const scroller = new views::ScrollView; // Leaves a placeholder area for the search box and the separator below it. scroller->SetBorder(views::CreateEmptyBorder( @@ -306,14 +325,20 @@ gfx::Rect SearchResultPageView::GetPageBoundsForState( ash::AppListState state) const { + gfx::Rect onscreen_bounds; + if (state != ash::AppListState::kStateSearchResults) { // Hides this view behind the search box by using the same bounds. - return AppListPage::contents_view()->GetSearchBoxBoundsForState(state); + onscreen_bounds = + AppListPage::contents_view()->GetSearchBoxBoundsForState(state); + } else { + onscreen_bounds = AppListPage::GetSearchBoxBounds(); + onscreen_bounds.Offset((onscreen_bounds.width() - kWidth) / 2, 0); + onscreen_bounds.set_size(GetPreferredSize()); } - gfx::Rect onscreen_bounds(AppListPage::GetSearchBoxBounds()); - onscreen_bounds.Offset((onscreen_bounds.width() - kWidth) / 2, 0); - onscreen_bounds.set_size(GetPreferredSize()); + onscreen_bounds = AddShadowBorderToBounds(onscreen_bounds); + return onscreen_bounds; } @@ -337,7 +362,8 @@ gfx::Tween::LinearIntValueBetween( progress, search_box->GetSearchBoxBorderCornerRadiusForState(from_state), - search_box->GetSearchBoxBorderCornerRadiusForState(to_state)))); + search_box->GetSearchBoxBorderCornerRadiusForState(to_state)), + border()->GetInsets().top())); gfx::Rect onscreen_bounds( GetPageBoundsForState(ash::AppListState::kStateSearchResults)); @@ -366,4 +392,11 @@ this, GetWidget(), true /* reverse */, false /* dont_loop */); } +gfx::Rect SearchResultPageView::AddShadowBorderToBounds( + const gfx::Rect& bounds) const { + gfx::Rect new_bounds(bounds); + new_bounds.Inset(-border()->GetInsets()); + return new_bounds; +} + } // namespace app_list
diff --git a/ash/app_list/views/search_result_page_view.h b/ash/app_list/views/search_result_page_view.h index 4986d62..1f4bbb01 100644 --- a/ash/app_list/views/search_result_page_view.h +++ b/ash/app_list/views/search_result_page_view.h
@@ -56,6 +56,10 @@ SearchResultBaseView* first_result_view() const { return first_result_view_; } + // Offset/add the size of the shadow border to the bounds + // for proper sizing/placement with shadow included. + gfx::Rect AddShadowBorderToBounds(const gfx::Rect& bounds) const; + private: // Separator between SearchResultContainerView. class HorizontalSeparator;
diff --git a/ash/ash_service.cc b/ash/ash_service.cc index 1e7699f..4bb72ea 100644 --- a/ash/ash_service.cc +++ b/ash/ash_service.cc
@@ -69,7 +69,7 @@ : service_binding_(this, std::move(request)) {} AshService::~AshService() { - if (!base::FeatureList::IsEnabled(features::kMash)) + if (!::features::IsMultiProcessMash()) return; // Shutdown part of GpuHost before deleting Shell. This is necessary to @@ -175,7 +175,7 @@ registry_.AddInterface(base::BindRepeating(&AshService::BindServiceFactory, base::Unretained(this))); - if (base::FeatureList::IsEnabled(features::kMash)) + if (::features::IsMultiProcessMash()) InitForMash(); } @@ -192,7 +192,7 @@ service_manager::mojom::PIDReceiverPtr pid_receiver) { DCHECK_EQ(name, ws::mojom::kServiceName); Shell::Get()->window_service_owner()->BindWindowService(std::move(service)); - if (base::FeatureList::IsEnabled(features::kMash)) { + if (::features::IsMultiProcessMash()) { ws::WindowService* window_service = Shell::Get()->window_service_owner()->window_service(); input_device_controller_ = std::make_unique<ws::InputDeviceController>();
diff --git a/ash/host/ash_window_tree_host_platform.cc b/ash/host/ash_window_tree_host_platform.cc index 4c2611c4..fb6924f8 100644 --- a/ash/host/ash_window_tree_host_platform.cc +++ b/ash/host/ash_window_tree_host_platform.cc
@@ -187,7 +187,7 @@ event_queue_ = Shell::Get()->window_service_owner()->window_service()->event_queue(); - if (!base::FeatureList::IsEnabled(features::kMash)) + if (!::features::IsMultiProcessMash()) return; input_method_ = std::make_unique<aura::InputMethodMus>(this, this);
diff --git a/ash/public/cpp/app_list/app_list_constants.cc b/ash/public/cpp/app_list/app_list_constants.cc index bfd8716..8eeaec83 100644 --- a/ash/public/cpp/app_list/app_list_constants.cc +++ b/ash/public/cpp/app_list/app_list_constants.cc
@@ -42,7 +42,7 @@ const SkColor kFolderShadowColor = SkColorSetRGB(0xBF, 0xBF, 0xBF); const float kFolderBubbleOpacity = 0.12f; -const SkColor kCardBackgroundColor = SkColorSetRGB(0xFA, 0xFA, 0xFC); +const SkColor kCardBackgroundColor = SK_ColorWHITE; // Duration in milliseconds for page transition. const int kPageTransitionDurationInMs = 250;
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index b52e294..a72ba8f27 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -487,6 +487,11 @@ visible_shelf_item_bounds_union_.SetRect(0, 0, 0, 0); for (int i = first_visible_index_; i <= last_visible_index_; ++i) { const views::View* child = view_model_->view_at(i); + // Since shelf items are centered, we don't want to include the app list + // button, otherwise tooltips will show when hovering a potentially large + // amount of white space between the app list button and the first item. + if (child == GetAppListButton()) + continue; if (!IsTabletModeEnabled() && child == GetBackButton()) continue; if (ShouldShowTooltipForView(child)) @@ -495,20 +500,22 @@ } bool ShelfView::ShouldHideTooltip(const gfx::Point& cursor_location) const { - // Hide the tooltip if this is the app list button and the list is showing. + // If this is the app list button, only show the tooltip if the app list is + // not already showing. const AppListButton* app_list_button = GetAppListButton(); if (app_list_button && - app_list_button->GetMirroredBounds().Contains(cursor_location) && - app_list_button->is_showing_app_list()) { - return true; + app_list_button->GetMirroredBounds().Contains(cursor_location)) { + return app_list_button->is_showing_app_list(); } return !visible_shelf_item_bounds_union_.Contains(cursor_location); } bool ShelfView::ShouldShowTooltipForView(const views::View* view) const { // TODO(msw): Push this app list state into ShelfItem::shows_tooltip. - if (view == GetAppListButton() && GetAppListButton()->is_showing_app_list()) - return false; + // If this is the app list button, only show the tooltip if the app list is + // not already showing. + if (view == GetAppListButton()) + return !GetAppListButton()->is_showing_app_list(); // Don't show a tooltip for a view that's currently being dragged. if (view == drag_view_) return false;
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index 94989525..4870ff4 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -1373,20 +1373,46 @@ TEST_F(ShelfViewTest, ShouldHideTooltipTest) { ShelfID app_button_id = AddAppShortcut(); ShelfID platform_button_id = AddApp(); + // TODO(manucornet): It should not be necessary to call this manually. The + // |AddItem| call seems to sometimes be missing some re-layout steps. We + // should find out what's going on there. + shelf_view_->UpdateVisibleShelfItemBoundsUnion(); + const AppListButton* app_list_button = shelf_view_->GetAppListButton(); + + // Make sure we're not showing the app list. + EXPECT_FALSE(app_list_button->is_showing_app_list()) + << "We should not be showing the app list"; // The tooltip shouldn't hide if the mouse is on normal buttons. for (int i = 0; i < test_api_->GetButtonCount(); i++) { ShelfButton* button = test_api_->GetButton(i); if (!button) continue; - EXPECT_FALSE(shelf_view_->ShouldHideTooltip( button->GetMirroredBounds().CenterPoint())) << "ShelfView tries to hide on button " << i; } + // The tooltip should hide if placed in between the app list button and the + // first shelf button. + const int left = app_list_button->bounds().right(); + // Find the first shelf button that's to the right of the app list button. + int right = 0; + for (int i = 0; i < test_api_->GetButtonCount(); ++i) { + ShelfButton* button = test_api_->GetButton(i); + if (!button) + continue; + right = button->bounds().x(); + if (right > left) + break; + } + const int center_x = + shelf_view_->GetMirroredXInView(left + (right - left) / 2); + EXPECT_TRUE(shelf_view_->ShouldHideTooltip(gfx::Point( + center_x, app_list_button->GetMirroredBounds().left_center().y()))) + << "Tooltip should hide between app list button and first shelf item"; + // The tooltip should not hide on the app-list button. - AppListButton* app_list_button = shelf_view_->GetAppListButton(); EXPECT_FALSE(shelf_view_->ShouldHideTooltip( app_list_button->GetMirroredBounds().CenterPoint())); @@ -1462,13 +1488,12 @@ EXPECT_TRUE(tooltip_manager->IsVisible()); // Move the mouse cursor slightly to the right of the item. The tooltip should - // stay open. + // now close. generator->MoveMouseBy(bounds.width() / 2 + 5, 0); - // Make sure there is no delayed close. base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(tooltip_manager->IsVisible()); + EXPECT_FALSE(tooltip_manager->IsVisible()); - // Move back - it should still stay open. + // Move back - it should appear again. generator->MoveMouseBy(-(bounds.width() / 2 + 5), 0); // Make sure there is no delayed close. base::RunLoop().RunUntilIdle();
diff --git a/ash/system/flag_warning/flag_warning_tray_unittest.cc b/ash/system/flag_warning/flag_warning_tray_unittest.cc index b8f5b5d..0c015221 100644 --- a/ash/system/flag_warning/flag_warning_tray_unittest.cc +++ b/ash/system/flag_warning/flag_warning_tray_unittest.cc
@@ -4,38 +4,30 @@ #include "ash/system/flag_warning/flag_warning_tray.h" -#include "ash/root_window_controller.h" +#include "ash/public/cpp/shell_window_ids.h" #include "ash/shell.h" #include "ash/system/status_area_widget.h" #include "ash/test/ash_test_base.h" -#include "base/macros.h" #include "base/test/scoped_feature_list.h" #include "ui/base/ui_base_features.h" namespace ash { namespace { -class FlagWarningTrayTest : public AshTestBase { - public: - FlagWarningTrayTest() = default; - ~FlagWarningTrayTest() override = default; - - // testing::Test: - void SetUp() override { - scoped_feature_list_.InitAndEnableFeature(::features::kMash); - AshTestBase::SetUp(); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; - - DISALLOW_COPY_AND_ASSIGN(FlagWarningTrayTest); -}; +using FlagWarningTrayTest = AshTestBase; TEST_F(FlagWarningTrayTest, VisibleForMash) { - FlagWarningTray* tray = Shell::GetPrimaryRootWindowController() - ->GetStatusAreaWidget() - ->flag_warning_tray_for_testing(); + // Simulate enabling Mash. + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + {::features::kMash} /* enabled */, + {::features::kSingleProcessMash} /* disabled */); + + StatusAreaWidget widget(Shell::GetContainer(Shell::GetPrimaryRootWindow(), + kShellWindowId_StatusContainer), + GetPrimaryShelf()); + widget.Initialize(); + FlagWarningTray* tray = widget.flag_warning_tray_for_testing(); ASSERT_TRUE(tray); EXPECT_TRUE(tray->visible()); }
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc index 1d2628a..9b5b5d0 100644 --- a/ash/wallpaper/wallpaper_controller.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -25,6 +25,7 @@ #include "ash/wallpaper/wallpaper_view.h" #include "ash/wallpaper/wallpaper_widget_controller.h" #include "ash/wallpaper/wallpaper_window_state_manager.h" +#include "ash/wm/overview/overview_constants.h" #include "ash/wm/overview/window_selector_controller.h" #include "base/bind.h" #include "base/command_line.h" @@ -1467,8 +1468,7 @@ const int container_id = GetWallpaperContainerId(locked_); float blur = login_constants::kClearBlurSigma; if (is_wallpaper_blurred) { - blur = session_blocked ? login_constants::kBlurSigma - : WindowSelectorController::kWallpaperBlurSigma; + blur = session_blocked ? login_constants::kBlurSigma : kWallpaperBlurSigma; } RootWindowController::ForWindow(root_window) ->wallpaper_widget_controller()
diff --git a/ash/wm/overview/drop_target_view.cc b/ash/wm/overview/drop_target_view.cc index ea16da4..a07aae2 100644 --- a/ash/wm/overview/drop_target_view.cc +++ b/ash/wm/overview/drop_target_view.cc
@@ -5,6 +5,7 @@ #include "ash/wm/overview/drop_target_view.h" #include "ash/resources/vector_icons/vector_icons.h" +#include "ash/wm/overview/overview_constants.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/views/border.h" #include "ui/views/controls/image_view.h"
diff --git a/ash/wm/overview/drop_target_view.h b/ash/wm/overview/drop_target_view.h index 326886df..7babc8f 100644 --- a/ash/wm/overview/drop_target_view.h +++ b/ash/wm/overview/drop_target_view.h
@@ -15,9 +15,6 @@ // be dragged into it and then dropped into overview. class DropTargetView : public views::View { public: - // The amount of rounding on window edges in overview mode. - static constexpr int kOverviewWindowRoundingDp = 4; - explicit DropTargetView(bool has_plus_icon); ~DropTargetView() override = default;
diff --git a/ash/wm/overview/overview_constants.h b/ash/wm/overview/overview_constants.h index fc93245..e4a8d06 100644 --- a/ash/wm/overview/overview_constants.h +++ b/ash/wm/overview/overview_constants.h
@@ -22,6 +22,18 @@ // Height of an item header. constexpr int kHeaderHeightDp = 40; +// The opacity of the shield widget that is used to darken the background of +// the grid. +constexpr float kShieldOpacity = 0.4f; + +// The amount of rounding on window edges in overview mode. +constexpr int kOverviewWindowRoundingDp = 4; + +// Amount of blur to apply on the wallpaper when we enter or exit overview +// mode. +constexpr float kWallpaperBlurSigma = 10.f; +constexpr float kWallpaperClearBlurSigma = 0.f; + } // namespace ash -#endif // ASH_WM_OVERVIEW_OVERVIEW_CONSTANTS_H_ \ No newline at end of file +#endif // ASH_WM_OVERVIEW_OVERVIEW_CONSTANTS_H_
diff --git a/ash/wm/overview/scoped_transform_overview_window.cc b/ash/wm/overview/scoped_transform_overview_window.cc index c218c0e..bac5bff8f 100644 --- a/ash/wm/overview/scoped_transform_overview_window.cc +++ b/ash/wm/overview/scoped_transform_overview_window.cc
@@ -10,7 +10,7 @@ #include "ash/public/cpp/window_properties.h" #include "ash/shell.h" #include "ash/wm/overview/cleanup_animation_observer.h" -#include "ash/wm/overview/drop_target_view.h" +#include "ash/wm/overview/overview_constants.h" #include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/scoped_overview_animation_settings.h" #include "ash/wm/overview/start_animation_observer.h" @@ -130,10 +130,10 @@ // transformed, so reverse the transform so the final scaled round matches // |kOverviewWindowRoundingDp|. const gfx::Vector2dF scale = window_->transform().Scale2d(); - const SkScalar r_x = SkIntToScalar( - std::round(DropTargetView::kOverviewWindowRoundingDp / scale.x())); - const SkScalar r_y = SkIntToScalar( - std::round(DropTargetView::kOverviewWindowRoundingDp / scale.y())); + const SkScalar r_x = + SkIntToScalar(std::round(kOverviewWindowRoundingDp / scale.x())); + const SkScalar r_y = + SkIntToScalar(std::round(kOverviewWindowRoundingDp / scale.y())); SkPath path; SkScalar radii[8] = {r_x, r_y, r_x, r_y, r_x, r_y, r_x, r_y}; @@ -397,12 +397,6 @@ return new_bounds; } -gfx::Rect ScopedTransformOverviewWindow::GetMaskBoundsForTesting() const { - if (!mask_) - return gfx::Rect(); - return mask_->layer()->bounds(); -} - void ScopedTransformOverviewWindow::Close() { if (immediate_close_for_tests) { CloseWidget(); @@ -524,6 +518,12 @@ selector_item_->OnDragAnimationCompleted(); } +gfx::Rect ScopedTransformOverviewWindow::GetMaskBoundsForTesting() const { + if (!mask_) + return gfx::Rect(); + return mask_->layer()->bounds(); +} + void ScopedTransformOverviewWindow::CreateMirrorWindowForMinimizedState() { DCHECK(!minimized_widget_.get()); views::Widget::InitParams params;
diff --git a/ash/wm/overview/scoped_transform_overview_window.h b/ash/wm/overview/scoped_transform_overview_window.h index 2bd8e85..f15b28b 100644 --- a/ash/wm/overview/scoped_transform_overview_window.h +++ b/ash/wm/overview/scoped_transform_overview_window.h
@@ -145,8 +145,6 @@ return window_selector_bounds_; } - gfx::Rect GetMaskBoundsForTesting() const; - // Closes the transient root of the window managed by |this|. void Close(); @@ -184,10 +182,14 @@ // ui::ImplicitAnimationObserver: void OnImplicitAnimationsCompleted() override; + gfx::Rect GetMaskBoundsForTesting() const; + private: friend class WindowSelectorTest; class LayerCachingAndFilteringObserver; class WindowMask; + FRIEND_TEST_ALL_PREFIXES(ScopedTransformOverviewWindowTest, + WindowBoundsChangeTest); // Closes the window managed by |this|. void CloseWidget();
diff --git a/ash/wm/overview/scoped_transform_overview_window_unittest.cc b/ash/wm/overview/scoped_transform_overview_window_unittest.cc new file mode 100644 index 0000000..e0f7dec --- /dev/null +++ b/ash/wm/overview/scoped_transform_overview_window_unittest.cc
@@ -0,0 +1,264 @@ +// Copyright 2019 The Chromium 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/wm/overview/scoped_transform_overview_window.h" + +#include "ash/test/ash_test_base.h" +#include "ash/wm/window_state.h" +#include "ui/aura/window.h" +#include "ui/display/display.h" +#include "ui/display/manager/display_manager.h" +#include "ui/display/screen.h" + +namespace ash { + +namespace { + +float GetItemScale(const gfx::Rect& source, + const gfx::Rect& target, + int top_view_inset, + int title_height) { + return ScopedTransformOverviewWindow::GetItemScale( + source.size(), target.size(), top_view_inset, title_height); +} + +} // namespace + +using ScopedTransformOverviewWindowTest = AshTestBase; + +// Tests that transformed Rect scaling preserves its aspect ratio. The window +// scale is determined by the target height and so the test is actually testing +// that the width is calculated correctly. Since all calculations are done with +// floating point values and then safely converted to integers (using ceiled and +// floored values where appropriate), the expectations are forgiving (use +// *_NEAR) within a single pixel. +TEST_F(ScopedTransformOverviewWindowTest, TransformedRectMaintainsAspect) { + std::unique_ptr<aura::Window> window = + CreateTestWindow(gfx::Rect(10, 10, 100, 100)); + ScopedTransformOverviewWindow transform_window(nullptr, window.get()); + + gfx::Rect rect(50, 50, 200, 400); + gfx::Rect bounds(100, 100, 50, 50); + gfx::Rect transformed_rect = + transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, 0, 0); + float scale = GetItemScale(rect, bounds, 0, 0); + EXPECT_NEAR(scale * rect.width(), transformed_rect.width(), 1); + EXPECT_NEAR(scale * rect.height(), transformed_rect.height(), 1); + + rect = gfx::Rect(50, 50, 400, 200); + scale = GetItemScale(rect, bounds, 0, 0); + transformed_rect = + transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, 0, 0); + EXPECT_NEAR(scale * rect.width(), transformed_rect.width(), 1); + EXPECT_NEAR(scale * rect.height(), transformed_rect.height(), 1); + + rect = gfx::Rect(50, 50, 25, 25); + scale = GetItemScale(rect, bounds, 0, 0); + transformed_rect = + transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, 0, 0); + EXPECT_NEAR(scale * rect.width(), transformed_rect.width(), 1); + EXPECT_NEAR(scale * rect.height(), transformed_rect.height(), 1); + + rect = gfx::Rect(50, 50, 25, 50); + scale = GetItemScale(rect, bounds, 0, 0); + transformed_rect = + transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, 0, 0); + EXPECT_NEAR(scale * rect.width(), transformed_rect.width(), 1); + EXPECT_NEAR(scale * rect.height(), transformed_rect.height(), 1); + + rect = gfx::Rect(50, 50, 50, 25); + scale = GetItemScale(rect, bounds, 0, 0); + transformed_rect = + transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, 0, 0); + EXPECT_NEAR(scale * rect.width(), transformed_rect.width(), 1); + EXPECT_NEAR(scale * rect.height(), transformed_rect.height(), 1); +} + +// Tests that transformed Rect fits in target bounds and is vertically centered. +TEST_F(ScopedTransformOverviewWindowTest, TransformedRectIsCentered) { + std::unique_ptr<aura::Window> window = + CreateTestWindow(gfx::Rect(10, 10, 100, 100)); + ScopedTransformOverviewWindow transform_window(nullptr, window.get()); + gfx::Rect rect(50, 50, 200, 400); + gfx::Rect bounds(100, 100, 50, 50); + gfx::Rect transformed_rect = + transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, 0, 0); + EXPECT_GE(transformed_rect.x(), bounds.x()); + EXPECT_LE(transformed_rect.right(), bounds.right()); + EXPECT_GE(transformed_rect.y(), bounds.y()); + EXPECT_LE(transformed_rect.bottom(), bounds.bottom()); + EXPECT_NEAR(transformed_rect.x() - bounds.x(), + bounds.right() - transformed_rect.right(), 1); + EXPECT_NEAR(transformed_rect.y() - bounds.y(), + bounds.bottom() - transformed_rect.bottom(), 1); +} + +// Tests that transformed Rect fits in target bounds and is vertically centered +// when inset and header height are specified. +TEST_F(ScopedTransformOverviewWindowTest, TransformedRectIsCenteredWithInset) { + std::unique_ptr<aura::Window> window = + CreateTestWindow(gfx::Rect(10, 10, 100, 100)); + ScopedTransformOverviewWindow transform_window(nullptr, window.get()); + gfx::Rect rect(50, 50, 400, 200); + gfx::Rect bounds(100, 100, 50, 50); + const int inset = 20; + const int header_height = 10; + const float scale = GetItemScale(rect, bounds, inset, header_height); + gfx::Rect transformed_rect = + transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, inset, + header_height); + // The |rect| width does not fit and therefore it gets centered outside + // |bounds| starting before |bounds.x()| and ending after |bounds.right()|. + EXPECT_LE(transformed_rect.x(), bounds.x()); + EXPECT_GE(transformed_rect.right(), bounds.right()); + EXPECT_GE( + transformed_rect.y() + gfx::ToCeiledInt(scale * inset) - header_height, + bounds.y()); + EXPECT_LE(transformed_rect.bottom(), bounds.bottom()); + EXPECT_NEAR(transformed_rect.x() - bounds.x(), + bounds.right() - transformed_rect.right(), 1); + EXPECT_NEAR( + transformed_rect.y() + (int)(scale * inset) - header_height - bounds.y(), + bounds.bottom() - transformed_rect.bottom(), 1); +} + +// Verify that a window which will be displayed like a letter box on the window +// grid has the correct bounds. +TEST_F(ScopedTransformOverviewWindowTest, TransformingLetteredRect) { + // Create a window whose width is more than twice the height. + const gfx::Rect original_bounds(10, 10, 300, 100); + const int scale = 3; + std::unique_ptr<aura::Window> window = CreateTestWindow(original_bounds); + ScopedTransformOverviewWindow transform_window(nullptr, window.get()); + EXPECT_EQ(ScopedTransformOverviewWindow::GridWindowFillMode::kLetterBoxed, + transform_window.type()); + + // Without any headers, the width should match the target, and the height + // should be such that the aspect ratio of |original_bounds| is maintained. + const gfx::Rect overview_bounds(0, 0, 100, 100); + gfx::Rect transformed_rect = + transform_window.ShrinkRectToFitPreservingAspectRatio( + original_bounds, overview_bounds, 0, 0); + EXPECT_EQ(overview_bounds.width(), transformed_rect.width()); + EXPECT_NEAR(overview_bounds.height() / scale, transformed_rect.height(), 1); + + // With headers, the width should still match the target. The height should + // still be such that the aspect ratio is maintained, but the original header + // which is hidden in overview needs to be accounted for. + const int original_header = 10; + const int overview_header = 20; + transformed_rect = transform_window.ShrinkRectToFitPreservingAspectRatio( + original_bounds, overview_bounds, original_header, overview_header); + EXPECT_EQ(overview_bounds.width(), transformed_rect.width()); + EXPECT_NEAR((overview_bounds.height() - original_header) / scale, + transformed_rect.height() - original_header / scale, 1); + EXPECT_TRUE(overview_bounds.Contains(transformed_rect)); + + // Verify that for an extreme window, the transform window stores the + // original window selector bounds, minus the header. + gfx::Rect selector_bounds = overview_bounds; + selector_bounds.Inset(0, overview_header, 0, 0); + ASSERT_TRUE(transform_window.window_selector_bounds().has_value()); + EXPECT_EQ(transform_window.window_selector_bounds().value(), selector_bounds); +} + +// Verify that a window which will be displayed like a pillar box on the window +// grid has the correct bounds. +TEST_F(ScopedTransformOverviewWindowTest, TransformingPillaredRect) { + // Create a window whose height is more than twice the width. + const gfx::Rect original_bounds(10, 10, 100, 300); + const int scale = 3; + std::unique_ptr<aura::Window> window = CreateTestWindow(original_bounds); + ScopedTransformOverviewWindow transform_window(nullptr, window.get()); + EXPECT_EQ(ScopedTransformOverviewWindow::GridWindowFillMode::kPillarBoxed, + transform_window.type()); + + // Without any headers, the height should match the target, and the width + // should be such that the aspect ratio of |original_bounds| is maintained. + const gfx::Rect overview_bounds(0, 0, 100, 100); + gfx::Rect transformed_rect = + transform_window.ShrinkRectToFitPreservingAspectRatio( + original_bounds, overview_bounds, 0, 0); + EXPECT_EQ(overview_bounds.height(), transformed_rect.height()); + EXPECT_NEAR(overview_bounds.width() / scale, transformed_rect.width(), 1); + + // With headers, the height should not include the area reserved for the + // overview window title. It also needs to account for the original header + // which will become hidden in overview mode. + const int original_header = 10; + const int overview_header = 20; + transformed_rect = transform_window.ShrinkRectToFitPreservingAspectRatio( + original_bounds, overview_bounds, original_header, overview_header); + EXPECT_NEAR(overview_bounds.height() - overview_header, + transformed_rect.height() - original_header / scale, 1); + EXPECT_TRUE(overview_bounds.Contains(transformed_rect)); + + // Verify that for an extreme window, the transform window stores the + // original window selector bounds, minus the header. + gfx::Rect selector_bounds = overview_bounds; + selector_bounds.Inset(0, overview_header, 0, 0); + ASSERT_TRUE(transform_window.window_selector_bounds().has_value()); + EXPECT_EQ(transform_window.window_selector_bounds().value(), selector_bounds); +} + +// Tests the cases when very wide or tall windows enter overview mode. +TEST_F(ScopedTransformOverviewWindowTest, ExtremeWindowBounds) { + // Add three windows which in overview mode will be considered wide, tall and + // normal. Window |wide|, with size (400, 160) will be resized to (200, 160) + // when the 400x200 is rotated to 200x400, and should be considered a normal + // overview window after display change. + UpdateDisplay("400x200"); + std::unique_ptr<aura::Window> wide = + CreateTestWindow(gfx::Rect(10, 10, 400, 160)); + std::unique_ptr<aura::Window> tall = + CreateTestWindow(gfx::Rect(10, 10, 50, 200)); + std::unique_ptr<aura::Window> normal = + CreateTestWindow(gfx::Rect(10, 10, 200, 200)); + + ScopedTransformOverviewWindow scoped_wide(nullptr, wide.get()); + ScopedTransformOverviewWindow scoped_tall(nullptr, tall.get()); + ScopedTransformOverviewWindow scoped_normal(nullptr, normal.get()); + + // Verify the window dimension type is as expected after entering overview + // mode. + using GridWindowFillMode = ScopedTransformOverviewWindow::GridWindowFillMode; + EXPECT_EQ(GridWindowFillMode::kLetterBoxed, scoped_wide.type()); + EXPECT_EQ(GridWindowFillMode::kPillarBoxed, scoped_tall.type()); + EXPECT_EQ(GridWindowFillMode::kNormal, scoped_normal.type()); + + display::Screen* screen = display::Screen::GetScreen(); + const display::Display& display = screen->GetPrimaryDisplay(); + display_manager()->SetDisplayRotation( + display.id(), display::Display::ROTATE_90, + display::Display::RotationSource::ACTIVE); + scoped_wide.UpdateWindowDimensionsType(); + scoped_tall.UpdateWindowDimensionsType(); + scoped_normal.UpdateWindowDimensionsType(); + + // Verify that |wide| has its window dimension type updated after the display + // change. + EXPECT_EQ(GridWindowFillMode::kNormal, scoped_wide.type()); + EXPECT_EQ(GridWindowFillMode::kPillarBoxed, scoped_tall.type()); + EXPECT_EQ(GridWindowFillMode::kNormal, scoped_normal.type()); +} + +// Verify that if the window's bounds are changed while it's in overview mode, +// the rounded edge mask's bounds are also changed accordingly. +TEST_F(ScopedTransformOverviewWindowTest, WindowBoundsChangeTest) { + UpdateDisplay("400x400"); + const gfx::Rect bounds(10, 10, 200, 200); + std::unique_ptr<aura::Window> window = CreateTestWindow(bounds); + ScopedTransformOverviewWindow scoped_window(nullptr, window.get()); + scoped_window.UpdateMask(true); + + EXPECT_TRUE(scoped_window.mask_); + EXPECT_EQ(window->bounds(), scoped_window.GetMaskBoundsForTesting()); + EXPECT_EQ(bounds, scoped_window.GetMaskBoundsForTesting()); + + wm::GetWindowState(window.get())->Maximize(); + EXPECT_EQ(window->bounds(), scoped_window.GetMaskBoundsForTesting()); + EXPECT_NE(bounds, scoped_window.GetMaskBoundsForTesting()); +} + +} // namespace ash
diff --git a/ash/wm/overview/window_grid.cc b/ash/wm/overview/window_grid.cc index abdf7fb..6f9d934 100644 --- a/ash/wm/overview/window_grid.cc +++ b/ash/wm/overview/window_grid.cc
@@ -26,6 +26,7 @@ #include "ash/wallpaper/wallpaper_widget_controller.h" #include "ash/wm/overview/cleanup_animation_observer.h" #include "ash/wm/overview/drop_target_view.h" +#include "ash/wm/overview/overview_constants.h" #include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/rounded_rect_view.h" #include "ash/wm/overview/scoped_overview_animation_settings.h" @@ -84,11 +85,6 @@ // form the shield widgets color. constexpr SkColor kShieldBaseColor = SkColorSetARGB(179, 0, 0, 0); -// In the conceptual overview table, the window margin is the space reserved -// around the window within the cell. This margin does not overlap so the -// closest distance between adjacent windows will be twice this amount. -constexpr int kWindowMargin = 5; - // Windows are not allowed to get taller than this. constexpr int kMaxHeight = 512;
diff --git a/ash/wm/overview/window_grid.h b/ash/wm/overview/window_grid.h index 7170f7a..12775a2 100644 --- a/ash/wm/overview/window_grid.h +++ b/ash/wm/overview/window_grid.h
@@ -58,10 +58,6 @@ const gfx::Rect& bounds_in_screen); ~WindowGrid() override; - // The opacity of the shield widget that is used to darken the background of - // the grid. - static constexpr float kShieldOpacity = 0.4f; - // Returns the shield color that is used to darken the background of the grid. static SkColor GetShieldColor();
diff --git a/ash/wm/overview/window_selector_controller.cc b/ash/wm/overview/window_selector_controller.cc index 5221840..b6ef8c27a 100644 --- a/ash/wm/overview/window_selector_controller.cc +++ b/ash/wm/overview/window_selector_controller.cc
@@ -15,6 +15,7 @@ #include "ash/wallpaper/wallpaper_controller.h" #include "ash/wallpaper/wallpaper_widget_controller.h" #include "ash/wm/mru_window_tracker.h" +#include "ash/wm/overview/overview_constants.h" #include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/window_grid.h" #include "ash/wm/overview/window_selector.h"
diff --git a/ash/wm/overview/window_selector_controller.h b/ash/wm/overview/window_selector_controller.h index 0900abb..13e75cb2 100644 --- a/ash/wm/overview/window_selector_controller.h +++ b/ash/wm/overview/window_selector_controller.h
@@ -34,11 +34,6 @@ WindowSelectorController(); ~WindowSelectorController() override; - // Amount of blur to apply on the wallpaper when we enter or exit overview - // mode. - static constexpr float kWallpaperBlurSigma = 10.f; - static constexpr float kWallpaperClearBlurSigma = 0.f; - // Returns true if selecting windows in an overview is enabled. This is false // at certain times, such as when the lock screen is visible. static bool CanSelect();
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc index c5aa8d9..5fe90ab 100644 --- a/ash/wm/overview/window_selector_unittest.cc +++ b/ash/wm/overview/window_selector_unittest.cc
@@ -29,6 +29,7 @@ #include "ash/test/ash_test_base.h" #include "ash/wm/overview/caption_container_view.h" #include "ash/wm/overview/cleanup_animation_observer.h" +#include "ash/wm/overview/overview_constants.h" #include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/overview_window_drag_controller.h" #include "ash/wm/overview/window_grid.h" @@ -79,14 +80,6 @@ namespace ash { namespace { -// The label covers selector item windows with a padding in order to prevent -// them from receiving user input events while in overview. -constexpr int kWindowMargin = 5; - -// The overview mode header overlaps original window header. This value is used -// to set top inset property on the windows. -constexpr int kHeaderHeight = 32; - constexpr const char kActiveWindowChangedFromOverview[] = "WindowSelector_ActiveWindowChanged"; @@ -104,14 +97,6 @@ DISALLOW_COPY_AND_ASSIGN(TestDragWindowDelegate); }; -float GetItemScale(const gfx::Rect& source, - const gfx::Rect& target, - int top_view_inset, - int title_height) { - return ScopedTransformOverviewWindow::GetItemScale( - source.size(), target.size(), top_view_inset, title_height); -} - // Helper function to get the index of |child|, given its parent window // |parent|. int IndexOf(aura::Window* child, aura::Window* parent) { @@ -178,14 +163,14 @@ aura::Window* CreateWindow(const gfx::Rect& bounds) { aura::Window* window = CreateTestWindowInShellWithDelegate(&delegate_, -1, bounds); - window->SetProperty(aura::client::kTopViewInset, kHeaderHeight); + window->SetProperty(aura::client::kTopViewInset, kHeaderHeightDp); return window; } aura::Window* CreateWindowWithId(const gfx::Rect& bounds, int id) { aura::Window* window = CreateTestWindowInShellWithDelegate(&delegate_, id, bounds); - window->SetProperty(aura::client::kTopViewInset, kHeaderHeight); + window->SetProperty(aura::client::kTopViewInset, kHeaderHeightDp); return window; } @@ -203,7 +188,7 @@ widget->Init(params); widget->Show(); aura::Window* window = widget->GetNativeWindow(); - window->SetProperty(aura::client::kTopViewInset, kHeaderHeight); + window->SetProperty(aura::client::kTopViewInset, kHeaderHeightDp); return widget; } @@ -398,10 +383,6 @@ return !!item->transform_window_.mask_; } - gfx::Rect GetMaskBoundsForItem(WindowSelectorItem* item) const { - return item->transform_window_.GetMaskBoundsForTesting(); - } - private: aura::test::TestWindowDelegate delegate_; std::unique_ptr<ShelfViewTestAPI> shelf_view_test_api_; @@ -920,7 +901,7 @@ widget->Init(params); widget->Show(); aura::Window* window = widget->GetNativeWindow(); - window->SetProperty(aura::client::kTopViewInset, kHeaderHeight); + window->SetProperty(aura::client::kTopViewInset, kHeaderHeightDp); ASSERT_EQ(root_windows[1], window1->GetRootWindow()); @@ -1781,181 +1762,6 @@ EXPECT_FALSE(IsSelecting()); } -// Tests that transformed Rect scaling preserves its aspect ratio. -// The window scale is determined by the target height and so the test is -// actually testing that the width is calculated correctly. Since all -// calculations are done with floating point values and then safely converted to -// integers (using ceiled and floored values where appropriate), the -// expectations are forgiving (use *_NEAR) within a single pixel. -TEST_F(WindowSelectorTest, TransformedRectMaintainsAspect) { - std::unique_ptr<aura::Window> window( - CreateWindow(gfx::Rect(10, 10, 100, 100))); - ScopedTransformOverviewWindow transform_window(nullptr, window.get()); - - gfx::Rect rect(50, 50, 200, 400); - gfx::Rect bounds(100, 100, 50, 50); - gfx::Rect transformed_rect = - transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, 0, 0); - float scale = GetItemScale(rect, bounds, 0, 0); - EXPECT_NEAR(scale * rect.width(), transformed_rect.width(), 1); - EXPECT_NEAR(scale * rect.height(), transformed_rect.height(), 1); - - rect = gfx::Rect(50, 50, 400, 200); - scale = GetItemScale(rect, bounds, 0, 0); - transformed_rect = - transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, 0, 0); - EXPECT_NEAR(scale * rect.width(), transformed_rect.width(), 1); - EXPECT_NEAR(scale * rect.height(), transformed_rect.height(), 1); - - rect = gfx::Rect(50, 50, 25, 25); - scale = GetItemScale(rect, bounds, 0, 0); - transformed_rect = - transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, 0, 0); - EXPECT_NEAR(scale * rect.width(), transformed_rect.width(), 1); - EXPECT_NEAR(scale * rect.height(), transformed_rect.height(), 1); - - rect = gfx::Rect(50, 50, 25, 50); - scale = GetItemScale(rect, bounds, 0, 0); - transformed_rect = - transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, 0, 0); - EXPECT_NEAR(scale * rect.width(), transformed_rect.width(), 1); - EXPECT_NEAR(scale * rect.height(), transformed_rect.height(), 1); - - rect = gfx::Rect(50, 50, 50, 25); - scale = GetItemScale(rect, bounds, 0, 0); - transformed_rect = - transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, 0, 0); - EXPECT_NEAR(scale * rect.width(), transformed_rect.width(), 1); - EXPECT_NEAR(scale * rect.height(), transformed_rect.height(), 1); -} - -// Tests that transformed Rect fits in target bounds and is vertically centered. -TEST_F(WindowSelectorTest, TransformedRectIsCentered) { - std::unique_ptr<aura::Window> window( - CreateWindow(gfx::Rect(10, 10, 100, 100))); - ScopedTransformOverviewWindow transform_window(nullptr, window.get()); - gfx::Rect rect(50, 50, 200, 400); - gfx::Rect bounds(100, 100, 50, 50); - gfx::Rect transformed_rect = - transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, 0, 0); - EXPECT_GE(transformed_rect.x(), bounds.x()); - EXPECT_LE(transformed_rect.right(), bounds.right()); - EXPECT_GE(transformed_rect.y(), bounds.y()); - EXPECT_LE(transformed_rect.bottom(), bounds.bottom()); - EXPECT_NEAR(transformed_rect.x() - bounds.x(), - bounds.right() - transformed_rect.right(), 1); - EXPECT_NEAR(transformed_rect.y() - bounds.y(), - bounds.bottom() - transformed_rect.bottom(), 1); -} - -// Tests that transformed Rect fits in target bounds and is vertically centered -// when inset and header height are specified. -TEST_F(WindowSelectorTest, TransformedRectIsCenteredWithInset) { - std::unique_ptr<aura::Window> window( - CreateWindow(gfx::Rect(10, 10, 100, 100))); - ScopedTransformOverviewWindow transform_window(nullptr, window.get()); - gfx::Rect rect(50, 50, 400, 200); - gfx::Rect bounds(100, 100, 50, 50); - const int inset = 20; - const int header_height = 10; - const float scale = GetItemScale(rect, bounds, inset, header_height); - gfx::Rect transformed_rect = - transform_window.ShrinkRectToFitPreservingAspectRatio(rect, bounds, inset, - header_height); - // The |rect| width does not fit and therefore it gets centered outside - // |bounds| starting before |bounds.x()| and ending after |bounds.right()|. - EXPECT_LE(transformed_rect.x(), bounds.x()); - EXPECT_GE(transformed_rect.right(), bounds.right()); - EXPECT_GE( - transformed_rect.y() + gfx::ToCeiledInt(scale * inset) - header_height, - bounds.y()); - EXPECT_LE(transformed_rect.bottom(), bounds.bottom()); - EXPECT_NEAR(transformed_rect.x() - bounds.x(), - bounds.right() - transformed_rect.right(), 1); - EXPECT_NEAR( - transformed_rect.y() + (int)(scale * inset) - header_height - bounds.y(), - bounds.bottom() - transformed_rect.bottom(), 1); -} - -// Verify that a window which will be displayed like a letter box on the window -// grid has the correct bounds. -TEST_F(WindowSelectorTest, TransformingLetteredRect) { - // Create a window whose width is more than twice the height. - const gfx::Rect original_bounds(10, 10, 300, 100); - const int scale = 3; - std::unique_ptr<aura::Window> window(CreateWindow(original_bounds)); - ScopedTransformOverviewWindow transform_window(nullptr, window.get()); - EXPECT_EQ(ScopedTransformOverviewWindow::GridWindowFillMode::kLetterBoxed, - transform_window.type()); - - // Without any headers, the width should match the target, and the height - // should be such that the aspect ratio of |original_bounds| is maintained. - const gfx::Rect overview_bounds(0, 0, 100, 100); - gfx::Rect transformed_rect = - transform_window.ShrinkRectToFitPreservingAspectRatio( - original_bounds, overview_bounds, 0, 0); - EXPECT_EQ(overview_bounds.width(), transformed_rect.width()); - EXPECT_NEAR(overview_bounds.height() / scale, transformed_rect.height(), 1); - - // With headers, the width should still match the target. The height should - // still be such that the aspect ratio is maintained, but the original header - // which is hidden in overview needs to be accounted for. - const int original_header = 10; - const int overview_header = 20; - transformed_rect = transform_window.ShrinkRectToFitPreservingAspectRatio( - original_bounds, overview_bounds, original_header, overview_header); - EXPECT_EQ(overview_bounds.width(), transformed_rect.width()); - EXPECT_NEAR((overview_bounds.height() - original_header) / scale, - transformed_rect.height() - original_header / scale, 1); - EXPECT_TRUE(overview_bounds.Contains(transformed_rect)); - - // Verify that for an extreme window, the transform window stores the - // original window selector bounds, minus the header. - gfx::Rect selector_bounds = overview_bounds; - selector_bounds.Inset(0, overview_header, 0, 0); - ASSERT_TRUE(transform_window.window_selector_bounds().has_value()); - EXPECT_EQ(transform_window.window_selector_bounds().value(), selector_bounds); -} - -// Verify that a window which will be displayed like a pillar box on the window -// grid has the correct bounds. -TEST_F(WindowSelectorTest, TransformingPillaredRect) { - // Create a window whose height is more than twice the width. - const gfx::Rect original_bounds(10, 10, 100, 300); - const int scale = 3; - std::unique_ptr<aura::Window> window(CreateWindow(original_bounds)); - ScopedTransformOverviewWindow transform_window(nullptr, window.get()); - EXPECT_EQ(ScopedTransformOverviewWindow::GridWindowFillMode::kPillarBoxed, - transform_window.type()); - - // Without any headers, the height should match the target, and the width - // should be such that the aspect ratio of |original_bounds| is maintained. - const gfx::Rect overview_bounds(0, 0, 100, 100); - gfx::Rect transformed_rect = - transform_window.ShrinkRectToFitPreservingAspectRatio( - original_bounds, overview_bounds, 0, 0); - EXPECT_EQ(overview_bounds.height(), transformed_rect.height()); - EXPECT_NEAR(overview_bounds.width() / scale, transformed_rect.width(), 1); - - // With headers, the height should not include the area reserved for the - // overview window title. It also needs to account for the original header - // which will become hidden in overview mode. - const int original_header = 10; - const int overview_header = 20; - transformed_rect = transform_window.ShrinkRectToFitPreservingAspectRatio( - original_bounds, overview_bounds, original_header, overview_header); - EXPECT_NEAR(overview_bounds.height() - overview_header, - transformed_rect.height() - original_header / scale, 1); - EXPECT_TRUE(overview_bounds.Contains(transformed_rect)); - - // Verify that for an extreme window, the transform window stores the - // original window selector bounds, minus the header. - gfx::Rect selector_bounds = overview_bounds; - selector_bounds.Inset(0, overview_header, 0, 0); - ASSERT_TRUE(transform_window.window_selector_bounds().has_value()); - EXPECT_EQ(transform_window.window_selector_bounds().value(), selector_bounds); -} - // Start dragging a window and activate overview mode. This test should not // crash or DCHECK inside aura::Window::StackChildRelativeTo(). TEST_F(WindowSelectorTest, OverviewWhileDragging) { @@ -2112,47 +1918,6 @@ EXPECT_FALSE(showing_filter_widget()); } -// Tests the cases when very wide or tall windows enter overview mode. -TEST_F(WindowSelectorTest, ExtremeWindowBounds) { - // Add three windows which in overview mode will be considered wide, tall and - // normal. Window |wide|, with size (400, 160) will be resized to (200, 160) - // when the 400x200 is rotated to 200x400, and should be considered a normal - // overview window after display change. - UpdateDisplay("400x200"); - std::unique_ptr<aura::Window> wide(CreateWindow(gfx::Rect(10, 10, 400, 160))); - std::unique_ptr<aura::Window> tall(CreateWindow(gfx::Rect(10, 10, 50, 200))); - std::unique_ptr<aura::Window> normal( - CreateWindow(gfx::Rect(10, 10, 200, 200))); - - ToggleOverview(); - WindowSelectorItem* wide_item = GetWindowItemForWindow(0, wide.get()); - WindowSelectorItem* tall_item = GetWindowItemForWindow(0, tall.get()); - WindowSelectorItem* normal_item = GetWindowItemForWindow(0, normal.get()); - - // Verify the window dimension type is as expected after entering overview - // mode. - EXPECT_EQ(ScopedTransformOverviewWindow::GridWindowFillMode::kLetterBoxed, - wide_item->GetWindowDimensionsType()); - EXPECT_EQ(ScopedTransformOverviewWindow::GridWindowFillMode::kPillarBoxed, - tall_item->GetWindowDimensionsType()); - EXPECT_EQ(ScopedTransformOverviewWindow::GridWindowFillMode::kNormal, - normal_item->GetWindowDimensionsType()); - - display::Screen* screen = display::Screen::GetScreen(); - const display::Display& display = screen->GetPrimaryDisplay(); - display_manager()->SetDisplayRotation( - display.id(), display::Display::ROTATE_90, - display::Display::RotationSource::ACTIVE); - // Verify that |wide| has its window dimension type updated after the display - // change. - EXPECT_EQ(ScopedTransformOverviewWindow::GridWindowFillMode::kNormal, - wide_item->GetWindowDimensionsType()); - EXPECT_EQ(ScopedTransformOverviewWindow::GridWindowFillMode::kPillarBoxed, - tall_item->GetWindowDimensionsType()); - EXPECT_EQ(ScopedTransformOverviewWindow::GridWindowFillMode::kNormal, - normal_item->GetWindowDimensionsType()); -} - // Tests window list animation states are correctly updated. TEST_F(WindowSelectorTest, SetWindowListAnimationStates) { const gfx::Rect bounds(400, 400); @@ -2833,24 +2598,6 @@ ToggleOverview(); } -// Verify that if the window's bounds are changed while it's in overview mode, -// the rounded edge mask's bounds are also changed accordingly. -TEST_F(WindowSelectorTest, WindowBoundsChangeTest) { - UpdateDisplay("400x400"); - const gfx::Rect bounds(0, 0, 200, 200); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - - ToggleOverview(); - WindowSelectorItem* item1 = GetWindowItemForWindow(0, window1.get()); - EXPECT_TRUE(HasMaskForItem(item1)); - EXPECT_EQ(GetMaskBoundsForItem(item1), window1->bounds()); - EXPECT_EQ(GetMaskBoundsForItem(item1), bounds); - - wm::GetWindowState(window1.get())->Maximize(); - EXPECT_EQ(GetMaskBoundsForItem(item1), window1->bounds()); - EXPECT_NE(GetMaskBoundsForItem(item1), bounds); -} - // Verify that the system does not crash when exiting overview mode after // pressing CTRL+SHIFT+U. TEST_F(WindowSelectorTest, ExitInUnderlineMode) {
diff --git a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc index 72f32ce..7d2bd0d 100644 --- a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc +++ b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc
@@ -12,6 +12,7 @@ #include "ash/shell.h" #include "ash/wallpaper/wallpaper_widget_controller.h" #include "ash/wm/mru_window_tracker.h" +#include "ash/wm/overview/overview_constants.h" #include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/window_grid.h" #include "ash/wm/overview/window_selector_controller.h" @@ -152,8 +153,7 @@ // Blurs the wallpaper background. RootWindowController::ForWindow(root_window) ->wallpaper_widget_controller() - ->SetWallpaperBlur( - static_cast<float>(WindowSelectorController::kWallpaperBlurSigma)); + ->SetWallpaperBlur(kWallpaperBlurSigma); // Darken the background. shield_widget_ = CreateBackgroundWidget( @@ -166,7 +166,7 @@ views::View* shield_view = new views::View(); shield_view->SetPaintToLayer(ui::LAYER_SOLID_COLOR); shield_view->layer()->SetColor(WindowGrid::GetShieldColor()); - shield_view->layer()->SetOpacity(WindowGrid::kShieldOpacity); + shield_view->layer()->SetOpacity(kShieldOpacity); shield_widget_->SetContentsView(shield_view); } @@ -194,7 +194,7 @@ // Clears the background wallpaper blur. RootWindowController::ForWindow(dragged_window_->GetRootWindow()) ->wallpaper_widget_controller() - ->SetWallpaperBlur(WindowSelectorController::kWallpaperClearBlurSigma); + ->SetWallpaperBlur(kWallpaperClearBlurSigma); // Clears the background darken widget. shield_widget_.reset();
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java index 197bdeb..c2f8d895 100644 --- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java +++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -40,11 +40,14 @@ import android.support.v4.widget.ImageViewCompat; import android.text.Html; import android.text.Spanned; +import android.text.TextUtils; import android.view.View; import android.view.Window; import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodSubtype; import android.view.textclassifier.TextClassifier; +import android.widget.EditText; import android.widget.ImageView; import android.widget.PopupWindow; import android.widget.TextView; @@ -768,6 +771,31 @@ return new TransitionDrawable(layers); } + /** + * Adds a content description to the provided EditText password field on versions of Android + * where the hint text is not used for accessibility. Does nothing if the EditText field does + * not have a password input type or the hint text is empty. See https://crbug.com/911762. + * + * @param view The EditText password field. + */ + public static void setPasswordEditTextContentDescription(EditText view) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) return; + + if (isPasswordInputType(view.getInputType()) && !TextUtils.isEmpty(view.getHint())) { + view.setContentDescription(view.getHint()); + } + } + + private static boolean isPasswordInputType(int inputType) { + final int variation = + inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION); + return variation == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD) + || variation + == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD) + || variation + == (EditorInfo.TYPE_CLASS_NUMBER | EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD); + } + private static class LayerDrawableCompat extends LayerDrawable { private boolean mMutated;
diff --git a/base/time/time_win_unittest.cc b/base/time/time_win_unittest.cc index 1e3001f..3255888 100644 --- a/base/time/time_win_unittest.cc +++ b/base/time/time_win_unittest.cc
@@ -66,15 +66,23 @@ return 0; } -// Measure the performance of __rdtsc so that we can compare it to the overhead -// of QueryPerformanceCounter. A hard-coded frequency is used because we don't -// care about the accuracy of the results, we just need to do the work. -// The amount of work is not exactly the same as in TimeTicks::Now (some steps -// are skipped) but that doesn't seem to materially affect the results. +#if defined(_M_ARM64) && defined(__clang__) +#define ReadCycleCounter() _ReadStatusReg(ARM64_PMCCNTR_EL0) +#else +#define ReadCycleCounter() __rdtsc() +#endif + +// Measure the performance of the CPU cycle counter so that we can compare it to +// the overhead of QueryPerformanceCounter. A hard-coded frequency is used +// because we don't care about the accuracy of the results, we just need to do +// the work. The amount of work is not exactly the same as in TimeTicks::Now +// (some steps are skipped) but that doesn't seem to materially affect the +// results. TimeTicks GetTSC() { - // Using a fake QPC frequency for test purposes. - return TimeTicks() + TimeDelta::FromMicroseconds( - __rdtsc() * Time::kMicrosecondsPerSecond / 10000000); + // Using a fake cycle counter frequency for test purposes. + return TimeTicks() + + TimeDelta::FromMicroseconds(ReadCycleCounter() * + Time::kMicrosecondsPerSecond / 10000000); } } // namespace @@ -202,7 +210,7 @@ std::vector<TestCase> cases; cases.push_back({reinterpret_cast<TestFunc>(&Time::Now), "Time::Now"}); cases.push_back({&TimeTicks::Now, "TimeTicks::Now"}); - cases.push_back({&GetTSC, "rdtsc"}); + cases.push_back({&GetTSC, "CPUCycleCounter"}); if (ThreadTicks::IsSupported()) { ThreadTicks::WaitUntilInitialized();
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 21f782e..91e3033e 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -1483,9 +1483,6 @@ cflags += [ # TODO(thakis): https://crbug.com/604888 "-Wno-undefined-var-template", - - # TODO(hans): https://crbug.com/766891 - "-Wno-null-pointer-arithmetic", ] if (is_win) {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index f3f2fa45..a7d219f 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -072566dd661883ce907cdbdbdc88c12521e622f6 \ No newline at end of file +b70000e57fb5c6799740dd62149bbc415401495d \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 9ba6613dd..84493d1b 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -56990592edd6f4928ff1ba5a176669ed095ac358 \ No newline at end of file +1587c7b87a57c49aa71c92e04fd7a884a7a8e1f5 \ No newline at end of file
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 1a4685c..3cb29d4 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -31,8 +31,8 @@ default_chrome_public_jinja_variables = [ "channel=$android_channel", - "enable_arcore=$enable_arcore", "enable_vr=$enable_vr", + "include_arcore_manifest_flag=$enable_arcore", ] if (android_64bit_browser) {
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedAppLifecycle.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedAppLifecycle.java index 3ea039e24..2a0439f 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedAppLifecycle.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedAppLifecycle.java
@@ -36,7 +36,11 @@ int ENTER_BACKGROUND = 1; int CLEAR_ALL = 2; int INITIALIZE = 3; - int NUM_ENTRIES = 4; + int SIGN_IN = 4; + int SIGN_OUT = 5; + int HISTORY_DELETED = 6; + int CACHED_DATA_CLEARED = 7; + int NUM_ENTRIES = 8; } private AppLifecycleListener mAppLifecycleListener; @@ -102,6 +106,7 @@ * We call onClearAll to avoid presenting personalized suggestions based on deleted history. */ public void onHistoryDeleted() { + reportEvent(AppLifecycleEvent.HISTORY_DELETED); onClearAll(/*suppressRefreshes*/ true); } @@ -110,6 +115,7 @@ * Feed deletes its cached browsing data. */ public void onCachedDataCleared() { + reportEvent(AppLifecycleEvent.CACHED_DATA_CLEARED); onClearAll(/*suppressRefreshes*/ false); } @@ -152,11 +158,13 @@ @Override public void onSignedIn() { + reportEvent(AppLifecycleEvent.SIGN_IN); onClearAll(/*suppressRefreshes*/ false); } @Override public void onSignedOut() { + reportEvent(AppLifecycleEvent.SIGN_OUT); onClearAll(/*suppressRefreshes*/ false); }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java index db81ad9..f90a139 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
@@ -238,7 +238,7 @@ mNewTabPageLayout.initialize(mNewTabPageManager, mTab, mTileGroupDelegate, mSearchProviderHasLogo, TemplateUrlService.getInstance().isDefaultSearchEngineGoogle(), mMediator, - mContextMenuManager, mUiConfig); + mContextMenuManager, mUiConfig, mConstructedTimeNs); } @Override
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 17c4693..9ecd3b90 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -165,7 +165,7 @@ <meta-data android:name="android.content.APP_RESTRICTIONS" android:resource="@xml/app_restrictions"/> - {% if enable_arcore %} + {% if include_arcore_manifest_flag == 'true' %} <!-- ARCore APK integration --> <!-- This tag indicates that this application optionally uses ARCore. --> <meta-data android:name="com.google.ar.core" android:value="optional" />
diff --git a/chrome/android/java/res/layout/sync_enter_passphrase.xml b/chrome/android/java/res/layout/sync_enter_passphrase.xml index f3c97c5..0387499 100644 --- a/chrome/android/java/res/layout/sync_enter_passphrase.xml +++ b/chrome/android/java/res/layout/sync_enter_passphrase.xml
@@ -20,6 +20,7 @@ android:id="@+id/passphrase" android:layout_width="match_parent" android:layout_height="wrap_content" + android:hint="@string/sync_enter_custom_passphrase_hint" android:inputType="textPassword" android:singleLine="true" android:imeOptions="actionNext" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/NoTouchActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/NoTouchActivity.java index 39d6b77..d24b5e6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/NoTouchActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/NoTouchActivity.java
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabRedirectHandler; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tab.TabUma.TabCreationState; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.content_public.browser.LoadUrlParams;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabCreatorManager.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabCreatorManager.java index 0a7a0cdc..b6c5ea7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabCreatorManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabCreatorManager.java
@@ -7,9 +7,9 @@ import android.content.Context; import org.chromium.base.ContextUtils; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabDelegateFactory; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabCreatorManager; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimator.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimator.java index 05ece2d..4402ee6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimator.java
@@ -45,6 +45,8 @@ /** The list of frame update listeners for this animation. */ private final ArrayList<AnimatorUpdateListener> mAnimatorUpdateListeners = new ArrayList<>(); + private FloatProperty mFloatProperty; + /** * A cached copy of the list of {@link AnimatorUpdateListener}s to prevent allocating a new list * every update. @@ -135,6 +137,7 @@ animator.setDuration(durationMs); animator.addUpdateListener( (CompositorAnimator a) -> property.setValue(target, a.getAnimatedValue())); + animator.setFloatProperty(property); animator.setInterpolator(interpolator); return animator; } @@ -229,6 +232,17 @@ mAnimatorUpdateListeners.add(listener); } + private void setFloatProperty(FloatProperty property) { + mFloatProperty = property; + } + + /** + * @return Whether this animation is of the given FloatProperty. + */ + public boolean isOfFloatProperty(FloatProperty property) { + return mFloatProperty == property; + } + /** * @return Whether or not the animation has ended after being started. If the animation is * started after ending, this value will be reset to true. @@ -270,6 +284,7 @@ public void removeAllListeners() { mListeners.clear(); mAnimatorUpdateListeners.clear(); + mFloatProperty = null; } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java index 10654f5..0fe3d76 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
@@ -4,8 +4,8 @@ package org.chromium.chrome.browser.compositor.layouts.phone; -import static org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.AnimatableAnimation.createAnimation; - +import android.animation.Animator; +import android.animation.AnimatorSet; import android.content.Context; import android.graphics.Rect; import android.graphics.RectF; @@ -22,8 +22,7 @@ import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.compositor.LayerTitleCache; import org.chromium.chrome.browser.compositor.animation.CompositorAnimator; -import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation; -import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable; +import org.chromium.chrome.browser.compositor.animation.FloatProperty; import org.chromium.chrome.browser.compositor.layouts.Layout; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost; @@ -63,14 +62,45 @@ /** * Base class for layouts that show one or more stacks of tabs. */ -public abstract class StackLayoutBase extends Layout implements Animatable { - @IntDef({Property.INNER_MARGIN_PERCENT, Property.STACK_SNAP, Property.STACK_OFFSET_Y_PERCENT}) - @Retention(RetentionPolicy.SOURCE) - public @interface Property { - int INNER_MARGIN_PERCENT = 0; - int STACK_SNAP = 1; - int STACK_OFFSET_Y_PERCENT = 2; - } +public abstract class StackLayoutBase extends Layout { + private static final FloatProperty<StackLayoutBase> INNER_MARGIN_PERCENT = + new FloatProperty<StackLayoutBase>("") { + @Override + public void setValue(StackLayoutBase layoutBase, float v) { + layoutBase.setInnerMarginPercent(v); + } + + @Override + public Float get(StackLayoutBase layoutTab) { + return null; + } + }; + + private static final FloatProperty<StackLayoutBase> STACK_OFFSET_Y_PERCENT = + new FloatProperty<StackLayoutBase>("") { + @Override + public void setValue(StackLayoutBase layoutBase, float v) { + layoutBase.setStackOffsetYPercent(v); + } + + @Override + public Float get(StackLayoutBase layoutTab) { + return null; + } + }; + + private static final FloatProperty<StackLayoutBase> STACK_SNAP = + new FloatProperty<StackLayoutBase>("") { + @Override + public void setValue(StackLayoutBase layoutBase, float v) { + layoutBase.setStackSnap(v); + } + + @Override + public Float get(StackLayoutBase layoutTab) { + return null; + } + }; @IntDef({DragDirection.NONE, DragDirection.HORIZONTAL, DragDirection.VERTICAL}) @Retention(RetentionPolicy.SOURCE) @@ -194,7 +224,7 @@ private StackLayoutGestureHandler mGestureHandler; - private ChromeAnimation<Animatable> mLayoutAnimations; + private AnimatorSet mLayoutAnimations; private class StackLayoutGestureHandler implements GestureHandler { @Override @@ -349,6 +379,34 @@ } /** + * Sets the stack offset percent for vertical axis. + * + * @param v Value to set. + */ + public void setStackOffsetYPercent(float v) { + mStackOffsetYPercent = v; + } + + /** + * Sets the inner margin percent. + * + * @param v Value to set. + */ + public void setInnerMarginPercent(float v) { + mInnerMarginPercent = v; + } + + /** + * Sets the stack stap value. + * + * @param v Value to set. + */ + public void setStackSnap(float v) { + mRenderedScrollOffset = v; + mScrollIndexOffset = v; + } + + /** * Whether or not the HorizontalTabSwitcherAndroid flag (which enables the new horizontal tab * switcher in both portrait and landscape mode) is enabled. */ @@ -648,10 +706,9 @@ boolean animationsWasDone = true; if (mLayoutAnimations != null) { if (jumpToEnd) { - animationsWasDone = mLayoutAnimations.finished(); - mLayoutAnimations.updateAndFinish(); + mLayoutAnimations.end(); } else { - animationsWasDone = mLayoutAnimations.update(time); + animationsWasDone = !mLayoutAnimations.isRunning(); } if (animationsWasDone || jumpToEnd) { @@ -775,23 +832,23 @@ protected void startMarginAnimation(boolean enter, boolean showMargin) { // Any outstanding animations must be cancelled to avoid race condition. - cancelAnimation(this, Property.INNER_MARGIN_PERCENT); + cancelAnimation(INNER_MARGIN_PERCENT); float start = mInnerMarginPercent; float end = enter && showMargin ? 1.0f : 0.0f; if (start != end) { - addToAnimation(this, Property.INNER_MARGIN_PERCENT, start, end, 200, 0); + addToAnimation(INNER_MARGIN_PERCENT, start, end, 200, 0); } } private void startYOffsetAnimation(boolean enter) { // Any outstanding animations must be cancelled to avoid race condition. - cancelAnimation(this, Property.STACK_OFFSET_Y_PERCENT); + cancelAnimation(STACK_OFFSET_Y_PERCENT); float start = mStackOffsetYPercent; float end = enter ? 1.f : 0.f; if (start != end) { - addToAnimation(this, Property.STACK_OFFSET_Y_PERCENT, start, end, 300, 0); + addToAnimation(STACK_OFFSET_Y_PERCENT, start, end, 300, 0); } } @@ -1132,7 +1189,7 @@ * @param delta The amount to scroll by. */ private void scrollStacks(float delta) { - cancelAnimation(this, Property.STACK_SNAP); + cancelAnimation(STACK_SNAP); float fullDistance = getFullScrollDistance(); mScrollIndexOffset += MathUtils.flipSignIf(delta / fullDistance, !isUsingHorizontalLayout() && LocalizationUtils.isLayoutRtl()); @@ -1160,16 +1217,16 @@ * incognito to non-incognito, which leaves the up event in the incognito side. */ private void finishScrollStacks() { - cancelAnimation(this, Property.STACK_SNAP); + cancelAnimation(STACK_SNAP); final int currentModelIndex = getTabStackIndex(); float delta = Math.abs(currentModelIndex + mRenderedScrollOffset); float target = -currentModelIndex; if (delta != 0) { long duration = FLING_MIN_DURATION + (long) Math.abs(delta * getFullScrollDistance() / mFlingSpeed); - addToAnimation(this, Property.STACK_SNAP, mRenderedScrollOffset, target, duration, 0); + addToAnimation(STACK_SNAP, mRenderedScrollOffset, target, duration, 0); } else { - setProperty(Property.STACK_SNAP, target); + setStackSnap(target); onAnimationFinished(); } } @@ -1488,30 +1545,6 @@ } /** - * Sets properties for animations. - * @param prop The property to update - * @param p New value of the property - */ - @Override - public void setProperty(@Property int prop, float p) { - switch (prop) { - case Property.STACK_SNAP: - mRenderedScrollOffset = p; - mScrollIndexOffset = p; - break; - case Property.INNER_MARGIN_PERCENT: - mInnerMarginPercent = p; - break; - case Property.STACK_OFFSET_Y_PERCENT: - mStackOffsetYPercent = p; - break; - } - } - - @Override - public void onPropertyAnimationFinished(@Property int prop) {} - - /** * Called by the stacks whenever they start an animation. */ public void onStackAnimationStarted() { @@ -1548,20 +1581,20 @@ } /** - * Creates an {@link org.chromium.chrome.browser.compositor.layouts.ChromeAnimation - * .AnimatableAnimation} and adds it to the animation. + * Creates an {@link CompositorAnimator} and adds it to the animation. * Automatically sets the start value at the beginning of the animation. */ - protected void addToAnimation( - Animatable object, int prop, float start, float end, long duration, long startTime) { - ChromeAnimation.Animation<Animatable> component = createAnimation(object, prop, start, end, - duration, startTime, false, CompositorAnimator.DECELERATE_INTERPOLATOR); - if (mLayoutAnimations == null || mLayoutAnimations.finished()) { - mLayoutAnimations = new ChromeAnimation<Animatable>(); - mLayoutAnimations.start(); - } - component.start(); - mLayoutAnimations.add(component); + protected void addToAnimation(FloatProperty<StackLayoutBase> property, float start, float end, + long duration, long startTime) { + if (mLayoutAnimations == null) mLayoutAnimations = new AnimatorSet(); + + CompositorAnimator compositorAnimator = CompositorAnimator.ofFloatProperty( + getAnimationHandler(), this, property, start, end, duration); + compositorAnimator.setStartDelay(startTime); + + mLayoutAnimations.playTogether(compositorAnimator); + mLayoutAnimations.start(); + requestUpdate(); } @@ -1569,7 +1602,7 @@ protected void forceAnimationToFinish() { super.forceAnimationToFinish(); if (mLayoutAnimations != null) { - mLayoutAnimations.updateAndFinish(); + mLayoutAnimations.end(); mLayoutAnimations = null; } } @@ -1579,13 +1612,18 @@ * @param object The object being animated. * @param prop The property to search for. */ - protected void cancelAnimation(Animatable object, int prop) { - if (mLayoutAnimations != null) mLayoutAnimations.cancel(object, prop); + protected void cancelAnimation(FloatProperty<StackLayoutBase> property) { + if (mLayoutAnimations == null) return; + + for (Animator animator : mLayoutAnimations.getChildAnimations()) { + CompositorAnimator a = (CompositorAnimator) animator; + if (a.isOfFloatProperty(property)) a.cancel(); + } } @Override @VisibleForTesting public boolean isLayoutAnimating() { - return mLayoutAnimations != null && !mLayoutAnimations.finished(); + return mLayoutAnimations != null && mLayoutAnimations.isRunning(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicy.java index 547dd12..4172d49 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicy.java
@@ -17,8 +17,8 @@ import org.chromium.base.StreamUtil; import org.chromium.base.ThreadUtils; import org.chromium.base.task.AsyncTask; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabPersistencePolicy;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegate.java index 173be9e..1a7cda5c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegate.java
@@ -42,7 +42,7 @@ * Returns the number of specialized intent handlers in {@params infos}. Specialized intent * handlers are intent handlers which handle only a few URLs (e.g. google maps or youtube). */ - int countSpecializedHandlers(List<ResolveInfo> infos, Intent intent); + int countSpecializedHandlers(List<ResolveInfo> infos); /** * Returns the package name of the first valid WebAPK in {@link infos}.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java index 25553af0..163fb551 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
@@ -269,20 +269,20 @@ } @Override - public int countSpecializedHandlers(List<ResolveInfo> infos, Intent intent) { - return getSpecializedHandlersWithFilter(infos, null, intent).size(); + public int countSpecializedHandlers(List<ResolveInfo> infos) { + return getSpecializedHandlersWithFilter(infos, null).size(); } @VisibleForTesting public static ArrayList<String> getSpecializedHandlersWithFilter( - List<ResolveInfo> infos, String filterPackageName, Intent intent) { + List<ResolveInfo> infos, String filterPackageName) { ArrayList<String> result = new ArrayList<>(); if (infos == null) { return result; } for (ResolveInfo info : infos) { - if (!matchResolveInfoExceptWildCardHost(info, filterPackageName, intent)) { + if (!matchResolveInfoExceptWildCardHost(info, filterPackageName)) { continue; } @@ -301,7 +301,7 @@ } private static boolean matchResolveInfoExceptWildCardHost( - ResolveInfo info, String filterPackageName, Intent intent) { + ResolveInfo info, String filterPackageName) { IntentFilter intentFilter = info.filter; if (intentFilter == null) { // Error on the side of classifying ResolveInfo as generic. @@ -311,19 +311,17 @@ // Don't count generic handlers. return false; } - if (intent != null) { - boolean isWildCardHost = false; - Iterator<IntentFilter.AuthorityEntry> it = intentFilter.authoritiesIterator(); - while (it != null && it.hasNext()) { - IntentFilter.AuthorityEntry entry = it.next(); - if ("*".equals(entry.getHost())) { - isWildCardHost = true; - break; - } + boolean isWildCardHost = false; + Iterator<IntentFilter.AuthorityEntry> it = intentFilter.authoritiesIterator(); + while (it != null && it.hasNext()) { + IntentFilter.AuthorityEntry entry = it.next(); + if ("*".equals(entry.getHost())) { + isWildCardHost = true; + break; } - if (isWildCardHost) { - return false; - } + } + if (isWildCardHost) { + return false; } if (!TextUtils.isEmpty(filterPackageName) && (info.activityInfo == null @@ -348,7 +346,7 @@ try (StrictModeContext unused = StrictModeContext.allowDiskReads()){ List<ResolveInfo> handlers = context.getPackageManager().queryIntentActivities( intent, PackageManager.GET_RESOLVED_FILTER); - return getSpecializedHandlersWithFilter(handlers, packageName, intent).size() > 0; + return getSpecializedHandlersWithFilter(handlers, packageName).size() > 0; } catch (RuntimeException e) { IntentUtils.logTransactionTooLargeOrRethrow(e, intent); } @@ -618,7 +616,7 @@ @Override public void maybeRecordAppHandlersInIntent(Intent intent, List<ResolveInfo> infos) { intent.putExtra(IntentHandler.EXTRA_EXTERNAL_NAV_PACKAGES, - getSpecializedHandlersWithFilter(infos, null, intent)); + getSpecializedHandlersWithFilter(infos, null)); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java index c6d8929..1a25f45 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
@@ -484,7 +484,7 @@ // handlers. If webkit can't handle it internally, we need to call // startActivityIfNeeded or startActivity. if (!isExternalProtocol) { - if (mDelegate.countSpecializedHandlers(resolvingInfos, intent) == 0) { + if (mDelegate.countSpecializedHandlers(resolvingInfos) == 0) { if (incomingIntentRedirect && mDelegate.maybeLaunchInstantApp( params.getUrl(), params.getReferrerUrl(), true)) { @@ -624,7 +624,7 @@ } if (targetWebApkPackageName != null - && mDelegate.countSpecializedHandlers(resolvingInfos, null) == 1) { + && mDelegate.countSpecializedHandlers(resolvingInfos) == 1) { intent.setPackage(targetWebApkPackageName); } @@ -806,8 +806,7 @@ } catch (URISyntaxException ex) { return false; } - return ExternalNavigationDelegateImpl - .getSpecializedHandlersWithFilter(handlers, appId, null) + return ExternalNavigationDelegateImpl.getSpecializedHandlersWithFilter(handlers, appId) .size() > 0; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java index 28babadb..742975c1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java
@@ -15,9 +15,9 @@ import org.chromium.base.ApplicationStatus; import org.chromium.base.ContextUtils; import org.chromium.chrome.browser.ChromeTabbedActivity; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.document.DocumentUtils; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabbedModeTabPersistencePolicy; import java.io.File;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index c7d6fa92..99a3bdd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -101,7 +101,7 @@ private LocationBarVoiceRecognitionHandler mVoiceRecognitionHandler; // The timestamp at which the constructor was called. - private final long mConstructedTimeNs; + protected final long mConstructedTimeNs; // The timestamp at which this NTP was last shown to the user. private long mLastShownTimeNs; @@ -360,7 +360,7 @@ mNewTabPageView.initialize(mNewTabPageManager, mTab, mTileGroupDelegate, mSearchProviderHasLogo, TemplateUrlService.getInstance().isDefaultSearchEngineGoogle(), - getScrollPositionFromNavigationEntry()); + getScrollPositionFromNavigationEntry(), mConstructedTimeNs); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java index d603f58..8fdc97d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
@@ -20,12 +20,15 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; +import android.view.ViewTreeObserver; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import org.chromium.base.Log; import org.chromium.base.TraceEvent; import org.chromium.base.VisibleForTesting; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; @@ -64,6 +67,8 @@ import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.widget.ViewRectProvider; +import java.util.concurrent.TimeUnit; + /** * Layout for the new tab page. This positions the page elements in the correct vertical positions. * There are no separate phone and tablet UIs; this layout adapts based on the available space. @@ -215,11 +220,12 @@ * @param scrollDelegate The delegate used to obtain information about scroll state. * @param contextMenuManager The manager for long-press context menus. * @param uiConfig UiConfig that provides display information about this view. + * @param constructedTimeNs The timestamp at which the new tab page's construction started. */ public void initialize(NewTabPageManager manager, Tab tab, TileGroup.Delegate tileGroupDelegate, boolean searchProviderHasLogo, boolean searchProviderIsGoogle, - ScrollDelegate scrollDelegate, ContextMenuManager contextMenuManager, - UiConfig uiConfig) { + ScrollDelegate scrollDelegate, ContextMenuManager contextMenuManager, UiConfig uiConfig, + long constructedTimeNs) { TraceEvent.begin(TAG + ".initialize()"); mScrollDelegate = scrollDelegate; mTab = tab; @@ -293,6 +299,22 @@ } } + // Use preDraw instead of draw because api level 25 and earlier doesn't seem to call the + // onDraw listener. Also, the onDraw version cannot be removed inside of the notification, + // which complicates this. + getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + Log.e(TAG, "SKYM onPreDraw()"); + long timeToFirstDrawMs = + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - constructedTimeNs); + RecordHistogram.recordTimesHistogram( + "NewTabPage.TimeToFirstDraw", timeToFirstDrawMs, TimeUnit.MILLISECONDS); + getViewTreeObserver().removeOnPreDrawListener(this); + return true; + } + }); + manager.addDestructionObserver(NewTabPageLayout.this::onDestroy); mInitialized = true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java index 230416a3a..84e4f7a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -106,9 +106,11 @@ * @param searchProviderHasLogo Whether the search provider has a logo. * @param searchProviderIsGoogle Whether the search provider is Google. * @param scrollPosition The adapter scroll position to initialize to. + * @param constructedTimeNs The timestamp at which the new tab page's construction started. */ public void initialize(NewTabPageManager manager, Tab tab, TileGroup.Delegate tileGroupDelegate, - boolean searchProviderHasLogo, boolean searchProviderIsGoogle, int scrollPosition) { + boolean searchProviderHasLogo, boolean searchProviderIsGoogle, int scrollPosition, + long constructedTimeNs) { TraceEvent.begin(TAG + ".initialize()"); mTab = tab; mManager = manager; @@ -125,7 +127,8 @@ mTab.getWindowAndroid().addContextMenuCloseListener(mContextMenuManager); mNewTabPageLayout.initialize(manager, tab, tileGroupDelegate, searchProviderHasLogo, - searchProviderIsGoogle, mRecyclerView, mContextMenuManager, mUiConfig); + searchProviderIsGoogle, mRecyclerView, mContextMenuManager, mUiConfig, + constructedTimeNs); mSnapScrollHelper = new SnapScrollHelper(mManager, mNewTabPageLayout); mSnapScrollHelper.setView(mRecyclerView);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java index ba72b66..b015b7a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java
@@ -107,7 +107,6 @@ mVerifyingTextView = (TextView) v.findViewById(R.id.verifying); mPassphraseEditText = (EditText) v.findViewById(R.id.passphrase); - mPassphraseEditText.setHint(R.string.sync_enter_custom_passphrase_hint); mPassphraseEditText.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java index 8db344ce..0ba9b488 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -49,8 +49,6 @@ import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.IntentHandler.TabOpenType; import org.chromium.chrome.browser.SwipeRefreshHandler; -import org.chromium.chrome.browser.TabState; -import org.chromium.chrome.browser.TabState.WebContentsState; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.WarmupManager; import org.chromium.chrome.browser.WebContentsFactory; @@ -80,6 +78,7 @@ import org.chromium.chrome.browser.rlz.RevenueStats; import org.chromium.chrome.browser.snackbar.SnackbarManager; import org.chromium.chrome.browser.ssl.SecurityStateModel; +import org.chromium.chrome.browser.tab.TabState.WebContentsState; import org.chromium.chrome.browser.tab.TabUma.TabCreationState; import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager; import org.chromium.chrome.browser.tabmodel.TabModel;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TabState.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java similarity index 95% rename from chrome/android/java/src/org/chromium/chrome/browser/TabState.java rename to chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java index bdf70d14..6c5857f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/TabState.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java
@@ -2,20 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser; +package org.chromium.chrome.browser.tab; import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.support.annotation.Nullable; -import android.util.Log; import android.util.Pair; +import org.chromium.base.Log; import org.chromium.base.StreamUtil; import org.chromium.base.VisibleForTesting; +import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.crypto.CipherFactory; -import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.content_public.browser.WebContents; @@ -282,8 +282,9 @@ // Skip ahead to avoid re-reading data that mmap'd. long skipped = input.skip(size); if (skipped != size) { - Log.e(TAG, "Only skipped " + skipped + " bytes when " + size + " should've " - + "been skipped. Tab restore may fail."); + Log.e(TAG, + "Only skipped " + skipped + " bytes when " + size + " should've " + + "been skipped. Tab restore may fail."); } } tabState.parentId = stream.readInt(); @@ -303,8 +304,9 @@ // Could happen if reading a version of a TabState that does not include the // version id. - Log.w(TAG, "Failed to read saved state version id from tab state. Assuming " - + "version " + tabState.contentsState.version()); + Log.w(TAG, + "Failed to read saved state version id from tab state. Assuming " + + "version " + tabState.contentsState.version()); } try { // Skip obsolete sync ID. @@ -316,8 +318,9 @@ } catch (EOFException eof) { // Could happen if reading a version of TabState without this flag set. tabState.shouldPreserve = false; - Log.w(TAG, "Failed to read shouldPreserve flag from tab state. " - + "Assuming shouldPreserve is false"); + Log.w(TAG, + "Failed to read shouldPreserve flag from tab state. " + + "Assuming shouldPreserve is false"); } tabState.mIsIncognito = encrypted; try { @@ -327,8 +330,9 @@ // Could happen if reading a version of TabState without a theme color. tabState.themeColor = Color.WHITE; tabState.mHasThemeColor = false; - Log.w(TAG, "Failed to read theme color from tab state. " - + "Assuming theme color is white"); + Log.w(TAG, + "Failed to read theme color from tab state. " + + "Assuming theme color is white"); } try { tabState.tabLaunchTypeAtCreation = stream.readInt(); @@ -536,8 +540,7 @@ name.substring(SAVED_TAB_STATE_FILE_PREFIX_INCOGNITO.length())); return Pair.create(id, true); } else if (name.startsWith(SAVED_TAB_STATE_FILE_PREFIX)) { - int id = Integer.parseInt( - name.substring(SAVED_TAB_STATE_FILE_PREFIX.length())); + int id = Integer.parseInt(name.substring(SAVED_TAB_STATE_FILE_PREFIX.length())); return Pair.create(id, false); } } catch (NumberFormatException ex) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java index 73bf7de..aee1e2d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java
@@ -10,7 +10,6 @@ import org.chromium.base.UserData; import org.chromium.base.VisibleForTesting; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.components.security_state.ConnectionSecurityLevel;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java index 68abaf4b..99b1a91 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
@@ -12,12 +12,12 @@ import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.ServiceTabLauncher; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabDelegateFactory; import org.chromium.chrome.browser.tab.TabRedirectHandler; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.components.url_formatter.UrlFormatter;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassin.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassin.java index 4175aa4..5823988 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassin.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassin.java
@@ -19,12 +19,12 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; import org.chromium.base.task.AsyncTask; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.document.DocumentActivity; import org.chromium.chrome.browser.document.DocumentUtils; import org.chromium.chrome.browser.document.IncognitoDocumentActivity; import org.chromium.chrome.browser.incognito.IncognitoNotificationManager; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabModelMetadata; import org.chromium.chrome.browser.tabmodel.document.ActivityDelegate; import org.chromium.chrome.browser.tabmodel.document.ActivityDelegateImpl;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java index 55d9168..a8dcd60 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java
@@ -7,9 +7,9 @@ import android.support.annotation.Nullable; import org.chromium.base.TraceEvent; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.WebContents;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java index 5072d65..5e4cad8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -26,12 +26,12 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.task.AsyncTask; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabIdManager; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.content_public.browser.LoadUrlParams; import java.io.BufferedInputStream;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersister.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersister.java index 7da0d9b..9f1798a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersister.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersister.java
@@ -6,7 +6,7 @@ import android.util.Log; -import org.chromium.chrome.browser.TabState; +import org.chromium.chrome.browser.tab.TabState; import java.io.File;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabbedModeTabPersistencePolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabbedModeTabPersistencePolicy.java index c5111e3..a5568ea5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabbedModeTabPersistencePolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabbedModeTabPersistencePolicy.java
@@ -20,10 +20,10 @@ import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.task.AsyncTask; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.browseractions.BrowserActionsTabModelSelector; import org.chromium.chrome.browser.browseractions.BrowserActionsTabPersistencePolicy; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.util.FeatureUtilities; import java.io.BufferedInputStream;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModel.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModel.java index 17df81d..eab65e0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModel.java
@@ -4,8 +4,8 @@ package org.chromium.chrome.browser.tabmodel.document; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabModel; /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/StorageDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/StorageDelegate.java index caf0bd98..9476f86 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/StorageDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/StorageDelegate.java
@@ -11,8 +11,8 @@ import org.chromium.base.Log; import org.chromium.base.StreamUtil; import org.chromium.base.task.AsyncTask; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabPersister; import org.chromium.chrome.browser.tabmodel.document.DocumentTabModel.Entry; import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelInfo.DocumentEntry;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java index a6b87639..0b9e482 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java
@@ -16,11 +16,11 @@ import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.ServiceTabLauncher; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabIdManager; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager; import org.chromium.chrome.browser.tabmodel.TabCreatorManager.TabCreator; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index 710c498..a443f175 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -34,7 +34,6 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.SingleTabActivity; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.WarmupManager; import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; @@ -48,6 +47,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabDelegateFactory; import org.chromium.chrome.browser.tab.TabObserver; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tab.TabUma.TabCreationState; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java index 7227ad3e..e03bfbc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java
@@ -84,7 +84,7 @@ boolean foundSpecializedHandler = false; for (String result : ExternalNavigationDelegateImpl.getSpecializedHandlersWithFilter( - handlers, null, null)) { + handlers, null)) { if (result.equals(mApkPackageName)) { // Current WebAPK matches and this is a HTTP(s) link. Don't intercept so that we // can launch a CCT. See http://crbug.com/831806 for more context.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/AlertDialogEditText.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/AlertDialogEditText.java index 7b16ec5b..b73b2b9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/AlertDialogEditText.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/AlertDialogEditText.java
@@ -13,13 +13,19 @@ import android.view.ActionMode; import android.view.Menu; import android.view.MenuItem; +import android.widget.EditText; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; /** - * EditText to use in AlertDialog needed due to b/20882793. This class should be removed - * when we roll to AppCompat with a fix. + * EditText to use in AlertDialog needed due to b/20882793 and b/122113958. This class should be + * removed when we roll to AppCompat with a fix for both issues. + * + * Note that for password fields the hint text is expected to be set in XML so that it is available + * during inflation. If the hint text or content description is changed programatically, consider + * calling {@link ApiCompatibilityUtils#setPasswordEditTextContentDescription(EditText)} after + * the change. */ public class AlertDialogEditText extends AppCompatEditText { @@ -30,7 +36,11 @@ @Override protected void onFinishInflate() { super.onFinishInflate(); + + ApiCompatibilityUtils.setPasswordEditTextContentDescription(this); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) return; + setCustomSelectionActionModeCallback(new ActionMode.Callback() { @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { @@ -60,5 +70,4 @@ } }); } - }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 2006e10..52c084bc 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -71,7 +71,6 @@ "java/src/org/chromium/chrome/browser/SnackbarActivity.java", "java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java", "java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java", - "java/src/org/chromium/chrome/browser/TabState.java", "java/src/org/chromium/chrome/browser/UrlConstants.java", "java/src/org/chromium/chrome/browser/UsbChooserDialog.java", "java/src/org/chromium/chrome/browser/WarmupManager.java", @@ -1538,6 +1537,7 @@ "java/src/org/chromium/chrome/browser/tab/TabIdManager.java", "java/src/org/chromium/chrome/browser/tab/TabObserver.java", "java/src/org/chromium/chrome/browser/tab/TabRedirectHandler.java", + "java/src/org/chromium/chrome/browser/tab/TabState.java", "java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java", "java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java", "java/src/org/chromium/chrome/browser/tab/TabUma.java", @@ -1892,7 +1892,6 @@ "javatests/src/org/chromium/chrome/browser/SubresourceFilterTest.java", "javatests/src/org/chromium/chrome/browser/TabCountLabelTest.java", "javatests/src/org/chromium/chrome/browser/TabObserverTest.java", - "javatests/src/org/chromium/chrome/browser/TabStateTest.java", "javatests/src/org/chromium/chrome/browser/TabTest.java", "javatests/src/org/chromium/chrome/browser/TabThemeTest.java", "javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java", @@ -2283,6 +2282,7 @@ "javatests/src/org/chromium/chrome/browser/tab/SadTabTest.java", "javatests/src/org/chromium/chrome/browser/tab/TabIdManagerTest.java", "javatests/src/org/chromium/chrome/browser/tab/TabRedirectHandlerTest.java", + "javatests/src/org/chromium/chrome/browser/tab/TabStateTest.java", "javatests/src/org/chromium/chrome/browser/tab/TabTestUtils.java", "javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java", "javatests/src/org/chromium/chrome/browser/tab/UndoIntegrationTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java index e082777c..aa0d5d4 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
@@ -58,6 +58,7 @@ import org.chromium.chrome.browser.modelutil.PropertyModel; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistenceIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistenceIntegrationTest.java index 52ea461..4c83692 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistenceIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistenceIntegrationTest.java
@@ -14,8 +14,8 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.chrome.browser.ChromeSwitches; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java index d2849202..f90d6fa 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java
@@ -30,9 +30,9 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.ChromeTabbedActivity; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl; import org.chromium.chrome.browser.tabmodel.TabPersistencePolicy;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java index ac8a6bb..108e43f6b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java
@@ -4,11 +4,9 @@ package org.chromium.chrome.browser.externalnav; -import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ResolveInfo; -import android.net.Uri; import android.os.Build; import android.support.test.filters.SmallTest; @@ -50,7 +48,7 @@ List<ResolveInfo> resolveInfos = new ArrayList<ResolveInfo>(); Assert.assertEquals(0, ExternalNavigationDelegateImpl - .getSpecializedHandlersWithFilter(resolveInfos, packageName, null) + .getSpecializedHandlersWithFilter(resolveInfos, packageName) .size()); } @@ -63,7 +61,7 @@ List<ResolveInfo> resolveInfos = makeResolveInfos(info); Assert.assertEquals(0, ExternalNavigationDelegateImpl - .getSpecializedHandlersWithFilter(resolveInfos, packageName, null) + .getSpecializedHandlersWithFilter(resolveInfos, packageName) .size()); } @@ -77,7 +75,7 @@ List<ResolveInfo> resolveInfos = makeResolveInfos(info); Assert.assertEquals(1, ExternalNavigationDelegateImpl - .getSpecializedHandlersWithFilter(resolveInfos, packageName, null) + .getSpecializedHandlersWithFilter(resolveInfos, packageName) .size()); } @@ -91,7 +89,7 @@ List<ResolveInfo> resolveInfos = makeResolveInfos(info); Assert.assertEquals(1, ExternalNavigationDelegateImpl - .getSpecializedHandlersWithFilter(resolveInfos, packageName, null) + .getSpecializedHandlersWithFilter(resolveInfos, packageName) .size()); } @@ -103,37 +101,19 @@ info.filter = new IntentFilter(); info.filter.addDataAuthority("*", null); List<ResolveInfo> resolveInfos = makeResolveInfos(info); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com")); Assert.assertEquals(0, ExternalNavigationDelegateImpl - .getSpecializedHandlersWithFilter(resolveInfos, packageName, intent) - .size()); - - Intent intentWildcardHost = - new Intent(Intent.ACTION_VIEW, Uri.parse("https://*.google.com")); - Assert.assertEquals(0, - ExternalNavigationDelegateImpl - .getSpecializedHandlersWithFilter( - resolveInfos, packageName, intentWildcardHost) + .getSpecializedHandlersWithFilter(resolveInfos, packageName) .size()); ResolveInfo infoWildcardSubDomain = new ResolveInfo(); infoWildcardSubDomain.filter = new IntentFilter(); infoWildcardSubDomain.filter.addDataAuthority("http://*.google.com", "80"); List<ResolveInfo> resolveInfosWildcardSubDomain = makeResolveInfos(infoWildcardSubDomain); - Intent intentSubDomain1 = new Intent(Intent.ACTION_VIEW, Uri.parse("https://google.com")); Assert.assertEquals(1, ExternalNavigationDelegateImpl .getSpecializedHandlersWithFilter( - resolveInfosWildcardSubDomain, packageName, intentSubDomain1) - .size()); - - Intent intentSubDomain2 = - new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com")); - Assert.assertEquals(1, - ExternalNavigationDelegateImpl - .getSpecializedHandlersWithFilter( - resolveInfosWildcardSubDomain, packageName, intentSubDomain2) + resolveInfosWildcardSubDomain, packageName) .size()); } @@ -149,7 +129,7 @@ List<ResolveInfo> resolveInfos = makeResolveInfos(info); Assert.assertEquals(1, ExternalNavigationDelegateImpl - .getSpecializedHandlersWithFilter(resolveInfos, packageName, null) + .getSpecializedHandlersWithFilter(resolveInfos, packageName) .size()); } @@ -165,7 +145,7 @@ List<ResolveInfo> resolveInfos = makeResolveInfos(info); Assert.assertEquals(0, ExternalNavigationDelegateImpl - .getSpecializedHandlersWithFilter(resolveInfos, packageName, null) + .getSpecializedHandlersWithFilter(resolveInfos, packageName) .size()); } @@ -189,7 +169,7 @@ // Ephemeral resolver is not counted as a specialized handler. Assert.assertEquals(0, ExternalNavigationDelegateImpl - .getSpecializedHandlersWithFilter(resolveInfos, packageName, null) + .getSpecializedHandlersWithFilter(resolveInfos, packageName) .size()); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java index 3e1cd34..e7f7bfb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
@@ -1602,7 +1602,7 @@ } @Override - public int countSpecializedHandlers(List<ResolveInfo> infos, Intent intent) { + public int countSpecializedHandlers(List<ResolveInfo> infos) { int count = 0; List<IntentActivity> matchingIntentActivities = findMatchingIntentActivities(infos); for (IntentActivity intentActivity : matchingIntentActivities) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceTest.java index cc9bb45..6425fe5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceTest.java
@@ -22,8 +22,8 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.ChromeSwitches; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabPersistentStore; import org.chromium.chrome.browser.tabmodel.TestTabModelDirectory;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java index f39bfe1..0144f059 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
@@ -39,7 +39,6 @@ import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ShortcutHelper; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.browsing_data.ClearBrowsingDataTab; import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.preferences.Preferences; @@ -47,6 +46,7 @@ import org.chromium.chrome.browser.preferences.website.ContentSettingValues; import org.chromium.chrome.browser.preferences.website.PermissionInfo; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.webapps.TestFetchStorageCallback; import org.chromium.chrome.browser.webapps.WebappDataStorage; import org.chromium.chrome.browser.webapps.WebappRegistry;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabStateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabStateTest.java similarity index 97% rename from chrome/android/javatests/src/org/chromium/chrome/browser/TabStateTest.java rename to chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabStateTest.java index b53966f..49d8ab0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabStateTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabStateTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser; +package org.chromium.chrome.browser.tab; import android.graphics.Color; import android.os.Bundle; @@ -17,7 +17,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.BaseJUnit4ClassRunner; -import org.chromium.chrome.browser.TabState.WebContentsState; +import org.chromium.chrome.browser.tab.TabState.WebContentsState; import org.chromium.chrome.browser.tabmodel.TestTabModelDirectory; import org.chromium.chrome.browser.test.ChromeBrowserTestRule;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassinTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassinTest.java index c7aefa2..b64d756 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassinTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassinTest.java
@@ -27,8 +27,8 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.RetryOnFailure; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.DocumentModeAssassin.DocumentModeAssassinForTesting; import org.chromium.chrome.browser.tabmodel.DocumentModeAssassin.DocumentModeAssassinObserver; import org.chromium.chrome.browser.tabmodel.TabPersistentStoreTest.MockTabPersistentStoreObserver;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/MultiInstanceMigrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/MultiInstanceMigrationTest.java index d354afd..c13d227 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/MultiInstanceMigrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/MultiInstanceMigrationTest.java
@@ -18,7 +18,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.base.test.util.Feature; -import org.chromium.chrome.browser.TabState; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ApplicationData; import org.chromium.chrome.test.util.browser.tabmodel.MockTabModelSelector;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java index 404a93d..80c0c55 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java
@@ -23,9 +23,9 @@ import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabIdManager; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ApplicationData; import org.chromium.chrome.test.util.browser.tabmodel.MockTabModelSelector;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java index ad575bd..5da6c08 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
@@ -29,11 +29,11 @@ import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.ChromeActivity; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelper; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.snackbar.undo.UndoBarController; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabCreatorManager.TabCreator; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java index 81f3f44..4ca67930 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java
@@ -30,9 +30,9 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.Feature; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabCreatorManager.TabCreator; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabPersistentStoreObserver;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java index 6df4284..e41c07d6 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java
@@ -16,7 +16,7 @@ import org.chromium.base.StreamUtil; import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.chrome.browser.TabState; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabModel; import java.io.DataOutputStream;
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 5bd63ba..53011cca 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4688,7 +4688,6 @@ "../android/java/src/org/chromium/chrome/browser/SearchGeolocationDisclosureTabHelper.java", "../android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java", "../android/java/src/org/chromium/chrome/browser/ShortcutHelper.java", - "../android/java/src/org/chromium/chrome/browser/TabState.java", "../android/java/src/org/chromium/chrome/browser/UsbChooserDialog.java", "../android/java/src/org/chromium/chrome/browser/WarmupManager.java", "../android/java/src/org/chromium/chrome/browser/WebContentsFactory.java", @@ -4909,6 +4908,7 @@ "../android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsEventReporterBridge.java", "../android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java", "../android/java/src/org/chromium/chrome/browser/tab/Tab.java", + "../android/java/src/org/chromium/chrome/browser/tab/TabState.java", "../android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java", "../android/java/src/org/chromium/chrome/browser/tabmodel/SingleTabModel.java", "../android/java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 0bc5843..86950e0 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3655,14 +3655,6 @@ FEATURE_VALUE_TYPE(features::kViewsCastDialog)}, #endif // defined(TOOLKIT_VIEWS) -#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_CHROMEOS) - {"enable-emoji-context-menu", - flag_descriptions::kEnableEmojiContextMenuName, - flag_descriptions::kEnableEmojiContextMenuDescription, - kOsMac | kOsWin | kOsCrOS, - FEATURE_VALUE_TYPE(features::kEnableEmojiContextMenu)}, -#endif // OS_MACOSX || OS_WIN || OS_CHROMEOS - {"SupervisedUserCommittedInterstitials", flag_descriptions::kSupervisedUserCommittedInterstitialsName, flag_descriptions::kSupervisedUserCommittedInterstitialsDescription,
diff --git a/chrome/browser/android/feed/feed_lifecycle_bridge.cc b/chrome/browser/android/feed/feed_lifecycle_bridge.cc index 752a1824..dd38b29 100644 --- a/chrome/browser/android/feed/feed_lifecycle_bridge.cc +++ b/chrome/browser/android/feed/feed_lifecycle_bridge.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/android/feed/feed_lifecycle_bridge.h" #include "base/android/jni_android.h" +#include "base/metrics/histogram_macros.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" @@ -55,6 +56,12 @@ } if (deletion_info.IsAllHistory() || deletion_info.deleted_rows().size() > 0) { + if (!deletion_info.IsAllHistory()) { + UMA_HISTOGRAM_EXACT_LINEAR( + "ContentSuggestions.Feed.AppLifecycle.NumRowsForDeletion", + deletion_info.deleted_rows().size(), 50); + } + JNIEnv* env = base::android::AttachCurrentThread(); Java_FeedLifecycleBridge_onHistoryDeleted(env); }
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index 465f2a4..bcba28f 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -3343,14 +3343,7 @@ TestHelper("testFindAPI_findupdate", "web_view/shim", NO_TEST_SERVER); } -// TODO(crbug.com/892085): Disabled on Windows due to flakiness. Re-enable. -#if defined(OS_WIN) -#define MAYBE_Shim_testFindInMultipleWebViews \ - DISABLED_Shim_testFindInMultipleWebViews -#else -#define MAYBE_Shim_testFindInMultipleWebViews Shim_testFindInMultipleWebViews -#endif -IN_PROC_BROWSER_TEST_F(WebViewTest, MAYBE_Shim_testFindInMultipleWebViews) { +IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_testFindInMultipleWebViews) { TestHelper("testFindInMultipleWebViews", "web_view/shim", NO_TEST_SERVER); }
diff --git a/chrome/browser/autofill/autofill_server_browsertest.cc b/chrome/browser/autofill/autofill_server_browsertest.cc index d7262149..0b696f1e 100644 --- a/chrome/browser/autofill/autofill_server_browsertest.cc +++ b/chrome/browser/autofill/autofill_server_browsertest.cc
@@ -216,6 +216,7 @@ upload.set_passwords_revealed(false); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_HTML_FORM_SUBMISSION); + upload.set_has_form_tag(true); test::FillUploadField(upload.add_field(), 2594484045U, "one", "text", nullptr, 2U);
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc index f97ded67..78fac09 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -27,6 +27,8 @@ #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/crostini/crostini_pref_names.h" +#include "chrome/browser/chromeos/crostini/crostini_registry_service.h" +#include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/login/lock/screen_locker.h" #include "chrome/browser/chromeos/printing/cups_printers_manager.h" @@ -1281,6 +1283,36 @@ } /////////////////////////////////////////////////////////////////////////////// +// AutotestPrivateSetCrostiniAppScaledFunction +/////////////////////////////////////////////////////////////////////////////// + +AutotestPrivateSetCrostiniAppScaledFunction:: + ~AutotestPrivateSetCrostiniAppScaledFunction() = default; + +ExtensionFunction::ResponseAction +AutotestPrivateSetCrostiniAppScaledFunction::Run() { + std::unique_ptr<api::autotest_private::SetCrostiniAppScaled::Params> params( + api::autotest_private::SetCrostiniAppScaled::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); + DVLOG(1) << "AutotestPrivateSetCrostiniAppScaledFunction " << params->app_id + << " " << params->scaled; + + ChromeLauncherController* const controller = + ChromeLauncherController::instance(); + if (!controller) + return RespondNow(Error("Controller not available")); + + crostini::CrostiniRegistryService* registry_service = + crostini::CrostiniRegistryServiceFactory::GetForProfile( + controller->profile()); + if (!registry_service) + return RespondNow(Error("Crostini registry not available")); + + registry_service->SetAppScaled(params->app_id, params->scaled); + return RespondNow(NoArguments()); +} + +/////////////////////////////////////////////////////////////////////////////// // AutotestPrivateAPI ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h index 89d14e6..e773614 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
@@ -492,6 +492,18 @@ std::unique_ptr<base::DictionaryValue> result_; }; +// Enable/disable a Crostini app's "scaled" property. +// When an app is "scaled", it will use low display density. +class AutotestPrivateSetCrostiniAppScaledFunction + : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("autotestPrivate.setCrostiniAppScaled", + AUTOTESTPRIVATE_SETCROSTINIAPPSCALED) + private: + ~AutotestPrivateSetCrostiniAppScaledFunction() override; + ResponseAction Run() override; +}; + // The profile-keyed service that manages the autotestPrivate extension API. class AutotestPrivateAPI : public BrowserContextKeyedAPI { public:
diff --git a/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl.cc b/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl.cc index 2284baff..a72bfef9 100644 --- a/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl.cc +++ b/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl.cc
@@ -38,11 +38,12 @@ } void OnAppUninstallResult(const GURL& app_url, bool succeeded) { + UMA_HISTOGRAM_BOOLEAN("AndroidSms.PWAUninstallationResult", succeeded); + if (succeeded) return; PA_LOG(ERROR) << "Failed to uninstall messages app; URL: " << app_url; - // TODO(khorimoto): Add metrics for failed uninstallations. } } // namespace
diff --git a/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl_unittest.cc b/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl_unittest.cc index 7189b642..316c778f 100644 --- a/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl_unittest.cc +++ b/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl_unittest.cc
@@ -248,6 +248,8 @@ TEST_F(AndroidSmsAppHelperDelegateImplTest, TestInstallMessagesApp_UninstallsOldApp) { + base::HistogramTester histogram_tester; + // Simulate a PWA having already been installed at the old URL. test_pwa_fetcher_delegate()->SetHasPwa( android_sms::GetAndroidMessagesURLOld(), true /* has_pwa */); @@ -258,6 +260,8 @@ ASSERT_EQ(1u, test_pending_app_manager()->uninstall_requests().size()); EXPECT_EQ(android_sms::GetAndroidMessagesURLOld(), test_pending_app_manager()->uninstall_requests()[0]); + histogram_tester.ExpectBucketCount("AndroidSms.PWAUninstallationResult", + true /* success */, 1); // The old app's cookie should have been deleted. VerifyCookieDeletedForUrl(android_sms::GetAndroidMessagesURLOld());
diff --git a/chrome/browser/chromeos/smb_client/smb_service.cc b/chrome/browser/chromeos/smb_client/smb_service.cc index eeecbad..09e7910 100644 --- a/chrome/browser/chromeos/smb_client/smb_service.cc +++ b/chrome/browser/chromeos/smb_client/smb_service.cc
@@ -190,6 +190,10 @@ } } + // TODO(jimmyxgong): Remove once authenticated dormant shares are + // implemented. + const bool has_credentials = !username.empty() || !password.empty(); + SmbUrl parsed_url(share_path.value()); if (!parsed_url.IsValid()) { FireMountCallback( @@ -210,8 +214,8 @@ temp_file_manager_->WritePasswordToFile(password), base::BindOnce(&SmbService::OnMountResponse, AsWeakPtr(), base::Passed(&callback), options, share_path, - use_chromad_kerberos, - should_open_file_manager_after_mount)); + use_chromad_kerberos, should_open_file_manager_after_mount, + has_credentials)); profile_->GetPrefs()->SetString(prefs::kMostRecentlyUsedNetworkFileShareURL, share_path.value()); @@ -223,6 +227,7 @@ const base::FilePath& share_path, bool is_kerberos_chromad, bool should_open_file_manager_after_mount, + bool has_credentials, smbprovider::ErrorType error, int32_t mount_id) { if (error != smbprovider::ERROR_OK) { @@ -236,6 +241,11 @@ mount_options.file_system_id = CreateFileSystemId(mount_id, share_path, is_kerberos_chromad); + // Do not remount shares that have credentials since there is not yet a way + // to reprompt users for credentials. + // TODO(jimmyxgong): Remove once authenticated dormant shares are implemented. + mount_options.persistent = !has_credentials; + base::File::Error result = GetProviderService()->MountFileSystem(provider_id_, mount_options);
diff --git a/chrome/browser/chromeos/smb_client/smb_service.h b/chrome/browser/chromeos/smb_client/smb_service.h index 08a335866..8a1e437b 100644 --- a/chrome/browser/chromeos/smb_client/smb_service.h +++ b/chrome/browser/chromeos/smb_client/smb_service.h
@@ -73,6 +73,7 @@ const base::FilePath& share_path, bool is_kerberos_chromad, bool should_open_file_manager_after_mount, + bool has_credentials, smbprovider::ErrorType error, int32_t mount_id);
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc index b0a9949..b0f731cd 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -1157,8 +1157,8 @@ scoped_refptr<UnpackedInstaller> installer( UnpackedInstaller::Create(GetExtensionService(browser_context()))); installer->set_be_noisy_on_failure(!fail_quietly_); - installer->set_completion_callback( - base::Bind(&DeveloperPrivateLoadUnpackedFunction::OnLoadComplete, this)); + installer->set_completion_callback(base::BindOnce( + &DeveloperPrivateLoadUnpackedFunction::OnLoadComplete, this)); installer->Load(path); retry_guid_ = DeveloperPrivateAPI::Get(browser_context())
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc index 064cc24..9345ac2 100644 --- a/chrome/browser/extensions/api/tabs/tabs_api.cc +++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -1681,10 +1681,6 @@ : chrome_details_(this) { } -bool TabsCaptureVisibleTabFunction::HasPermission() { - return true; -} - bool TabsCaptureVisibleTabFunction::IsScreenshotEnabled() const { PrefService* service = chrome_details_.GetProfile()->GetPrefs(); if (service->GetBoolean(prefs::kDisableScreenshots)) {
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.h b/chrome/browser/extensions/api/tabs/tabs_api.h index 7300832..2c8f067 100644 --- a/chrome/browser/extensions/api/tabs/tabs_api.h +++ b/chrome/browser/extensions/api/tabs/tabs_api.h
@@ -202,7 +202,6 @@ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); // ExtensionFunction implementation. - bool HasPermission() override; ResponseAction Run() override; protected:
diff --git a/chrome/browser/extensions/content_verifier_test_utils.cc b/chrome/browser/extensions/content_verifier_test_utils.cc index d5c7f4c4..90d6bbf 100644 --- a/chrome/browser/extensions/content_verifier_test_utils.cc +++ b/chrome/browser/extensions/content_verifier_test_utils.cc
@@ -4,6 +4,10 @@ #include "chrome/browser/extensions/content_verifier_test_utils.h" +#include <utility> + +#include "base/bind.h" +#include "base/callback.h" #include "base/run_loop.h" #include "content/public/test/test_utils.h" #include "extensions/browser/external_install_info.h" @@ -86,9 +90,9 @@ return calls_; } -void DelayTracker::ReinstallAction(const base::RepeatingClosure& callback, +void DelayTracker::ReinstallAction(base::OnceClosure callback, base::TimeDelta delay) { - saved_callback_ = callback; + saved_callback_ = std::move(callback); calls_.push_back(delay); } @@ -96,9 +100,9 @@ ASSERT_TRUE(saved_callback_); ASSERT_TRUE(!saved_callback_->is_null()); // Run() will set |saved_callback_| again, so use a temporary: |callback|. - base::RepeatingClosure callback = saved_callback_.value(); + base::OnceClosure callback = std::move(saved_callback_.value()); saved_callback_.reset(); - callback.Run(); + std::move(callback).Run(); } void DelayTracker::StopWatching() {
diff --git a/chrome/browser/extensions/content_verifier_test_utils.h b/chrome/browser/extensions/content_verifier_test_utils.h index b5560e5..d999d84 100644 --- a/chrome/browser/extensions/content_verifier_test_utils.h +++ b/chrome/browser/extensions/content_verifier_test_utils.h
@@ -93,14 +93,13 @@ ~DelayTracker(); const std::vector<base::TimeDelta>& calls(); - void ReinstallAction(const base::RepeatingClosure& callback, - base::TimeDelta delay); + void ReinstallAction(base::OnceClosure callback, base::TimeDelta delay); void Proceed(); void StopWatching(); private: std::vector<base::TimeDelta> calls_; - base::Optional<base::RepeatingClosure> saved_callback_; + base::Optional<base::OnceClosure> saved_callback_; PolicyExtensionReinstaller::ReinstallCallback action_; DISALLOW_COPY_AND_ASSIGN(DelayTracker);
diff --git a/chrome/browser/extensions/install_signer.cc b/chrome/browser/extensions/install_signer.cc index d0aa12d..57125cb6 100644 --- a/chrome/browser/extensions/install_signer.cc +++ b/chrome/browser/extensions/install_signer.cc
@@ -316,17 +316,17 @@ } // namespace -void InstallSigner::GetSignature(const SignatureCallback& callback) { +void InstallSigner::GetSignature(SignatureCallback callback) { CHECK(!simple_loader_.get()); CHECK(callback_.is_null()); CHECK(salt_.empty()); - callback_ = callback; + callback_ = std::move(callback); // If the set of ids is empty, just return an empty signature and skip the // call to the server. if (ids_.empty()) { if (!callback_.is_null()) - callback_.Run(std::unique_ptr<InstallSignature>(new InstallSignature())); + std::move(callback_).Run(std::make_unique<InstallSignature>()); return; } @@ -417,9 +417,8 @@ } void InstallSigner::ReportErrorViaCallback() { - InstallSignature* null_signature = NULL; if (!callback_.is_null()) - callback_.Run(std::unique_ptr<InstallSignature>(null_signature)); + std::move(callback_).Run(nullptr); } void InstallSigner::ParseFetchResponse( @@ -513,7 +512,7 @@ } if (!callback_.is_null()) - callback_.Run(std::move(result)); + std::move(callback_).Run(std::move(result)); }
diff --git a/chrome/browser/extensions/install_signer.h b/chrome/browser/extensions/install_signer.h index 3ea004e0..88e3b74 100644 --- a/chrome/browser/extensions/install_signer.h +++ b/chrome/browser/extensions/install_signer.h
@@ -61,8 +61,8 @@ // that a set of ids are hosted in the webstore. class InstallSigner { public: - typedef base::Callback<void(std::unique_ptr<InstallSignature>)> - SignatureCallback; + using SignatureCallback = + base::OnceCallback<void(std::unique_ptr<InstallSignature>)>; // IMPORTANT NOTE: It is possible that only some, but not all, of the entries // in |ids| will be successfully signed by the backend. Callers should always @@ -80,7 +80,7 @@ // Begins the process of fetching a signature from the backend. This should // only be called once! If you want to get another signature, make another // instance of this class. - void GetSignature(const SignatureCallback& callback); + void GetSignature(SignatureCallback callback); // Returns whether the signature in InstallSignature is properly signed with a // known public key.
diff --git a/chrome/browser/extensions/install_verifier.cc b/chrome/browser/extensions/install_verifier.cc index 8fd766c..1f4e4f2 100644 --- a/chrome/browser/extensions/install_verifier.cc +++ b/chrome/browser/extensions/install_verifier.cc
@@ -583,8 +583,8 @@ content::BrowserContext::GetDefaultStoragePartition(context_) ->GetURLLoaderFactoryForBrowserProcess(); signer_ = std::make_unique<InstallSigner>(url_loader_factory, ids_to_sign); - signer_->GetSignature(base::Bind(&InstallVerifier::SignatureCallback, - weak_factory_.GetWeakPtr())); + signer_->GetSignature(base::BindOnce(&InstallVerifier::SignatureCallback, + weak_factory_.GetWeakPtr())); } void InstallVerifier::SaveToPrefs() {
diff --git a/chrome/browser/extensions/policy_extension_reinstaller.cc b/chrome/browser/extensions/policy_extension_reinstaller.cc index 72789a4..bef8e014 100644 --- a/chrome/browser/extensions/policy_extension_reinstaller.cc +++ b/chrome/browser/extensions/policy_extension_reinstaller.cc
@@ -86,13 +86,13 @@ scheduled_fire_pending_ = true; base::TimeDelta reinstall_delay = GetNextFireDelay(); - base::Closure callback = - base::Bind(&PolicyExtensionReinstaller::Fire, weak_factory_.GetWeakPtr()); + base::OnceClosure callback = base::BindOnce(&PolicyExtensionReinstaller::Fire, + weak_factory_.GetWeakPtr()); if (g_reinstall_action_for_test) { - g_reinstall_action_for_test->Run(callback, reinstall_delay); + g_reinstall_action_for_test->Run(std::move(callback), reinstall_delay); } else { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, callback, - reinstall_delay); + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, std::move(callback), reinstall_delay); } }
diff --git a/chrome/browser/extensions/policy_extension_reinstaller.h b/chrome/browser/extensions/policy_extension_reinstaller.h index 8845747..dbcdf6e 100644 --- a/chrome/browser/extensions/policy_extension_reinstaller.h +++ b/chrome/browser/extensions/policy_extension_reinstaller.h
@@ -24,8 +24,9 @@ // it will retry reinstallation with backoff. class PolicyExtensionReinstaller { public: - using ReinstallCallback = base::Callback<void(const base::Closure& callback, - base::TimeDelta delay)>; + using ReinstallCallback = + base::RepeatingCallback<void(base::OnceClosure callback, + base::TimeDelta delay)>; explicit PolicyExtensionReinstaller(content::BrowserContext* context); ~PolicyExtensionReinstaller();
diff --git a/chrome/browser/extensions/policy_extension_reinstaller_unittest.cc b/chrome/browser/extensions/policy_extension_reinstaller_unittest.cc index 8d842434..5bf416be 100644 --- a/chrome/browser/extensions/policy_extension_reinstaller_unittest.cc +++ b/chrome/browser/extensions/policy_extension_reinstaller_unittest.cc
@@ -4,6 +4,10 @@ #include "chrome/browser/extensions/policy_extension_reinstaller.h" +#include <utility> + +#include "base/bind.h" +#include "base/callback.h" #include "base/test/simple_test_tick_clock.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/extensions/extension_service.h" @@ -19,31 +23,31 @@ class TestReinstallerTracker { public: TestReinstallerTracker() - : action_(base::Bind(&TestReinstallerTracker::ReinstallAction, - base::Unretained(this))) { + : action_(base::BindRepeating(&TestReinstallerTracker::ReinstallAction, + base::Unretained(this))) { PolicyExtensionReinstaller::set_policy_reinstall_action_for_test(&action_); } ~TestReinstallerTracker() { PolicyExtensionReinstaller::set_policy_reinstall_action_for_test(nullptr); } - void ReinstallAction(const base::Closure& callback, + void ReinstallAction(base::OnceClosure callback, base::TimeDelta reinstall_delay) { ++call_count_; - saved_callback_ = callback; + saved_callback_ = std::move(callback); } void Proceed() { DCHECK(saved_callback_); DCHECK(!saved_callback_->is_null()); // Run() will set |saved_callback_| again, so use a temporary. - base::Closure callback = saved_callback_.value(); + base::OnceClosure callback = std::move(saved_callback_.value()); saved_callback_.reset(); - callback.Run(); + std::move(callback).Run(); } int call_count() { return call_count_; } private: int call_count_ = 0; - base::Optional<base::Closure> saved_callback_; + base::Optional<base::OnceClosure> saved_callback_; PolicyExtensionReinstaller::ReinstallCallback action_; DISALLOW_COPY_AND_ASSIGN(TestReinstallerTracker);
diff --git a/chrome/browser/extensions/unpacked_installer.cc b/chrome/browser/extensions/unpacked_installer.cc index f6143c5e..20acd30 100644 --- a/chrome/browser/extensions/unpacked_installer.cc +++ b/chrome/browser/extensions/unpacked_installer.cc
@@ -342,10 +342,8 @@ extension_path_, error, service_weak_->profile(), be_noisy_on_failure_); } - if (!callback_.is_null()) { - callback_.Run(nullptr, extension_path_, error); - callback_.Reset(); - } + if (!callback_.is_null()) + std::move(callback_).Run(nullptr, extension_path_, error); } void UnpackedInstaller::InstallExtension() { @@ -364,10 +362,8 @@ kInstallFlagInstallImmediately, dnr_ruleset_checksum_); - if (!callback_.is_null()) { - callback_.Run(extension(), extension_path_, std::string()); - callback_.Reset(); - } + if (!callback_.is_null()) + std::move(callback_).Run(extension(), extension_path_, std::string()); } } // namespace extensions
diff --git a/chrome/browser/extensions/unpacked_installer.h b/chrome/browser/extensions/unpacked_installer.h index 510904b..5964376 100644 --- a/chrome/browser/extensions/unpacked_installer.h +++ b/chrome/browser/extensions/unpacked_installer.h
@@ -7,6 +7,7 @@ #include <memory> #include <string> +#include <utility> #include <vector> #include "base/bind.h" @@ -34,9 +35,9 @@ class UnpackedInstaller : public base::RefCountedThreadSafe<UnpackedInstaller> { public: - using CompletionCallback = base::Callback<void(const Extension* extension, - const base::FilePath&, - const std::string&)>; + using CompletionCallback = base::OnceCallback<void(const Extension* extension, + const base::FilePath&, + const std::string&)>; static scoped_refptr<UnpackedInstaller> Create( ExtensionService* extension_service); @@ -72,8 +73,8 @@ be_noisy_on_failure_ = be_noisy_on_failure; } - void set_completion_callback(const CompletionCallback& callback) { - callback_ = callback; + void set_completion_callback(CompletionCallback callback) { + callback_ = std::move(callback); } private:
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 3ada28ad..e108f37 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -529,11 +529,6 @@ const char kEnableDockedMagnifierDescription[] = "Enables the Docked Magnifier (a.k.a. picture-in-picture magnifier)."; -const char kEnableEmojiContextMenuName[] = "Emoji Context Menu"; -const char kEnableEmojiContextMenuDescription[] = - "Enables the Emoji picker item in context menus for editable text areas, if" - " supported by the operating system."; - const char kEnforceTLS13DowngradeName[] = "TLS 1.3 downgrade hardening"; const char kEnforceTLS13DowngradeDescription[] = "This option enables the TLS 1.3 downgrade hardening mechanism. This "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index e658eb0..f6d436e5 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -351,9 +351,6 @@ extern const char kEnableDockedMagnifierName[]; extern const char kEnableDockedMagnifierDescription[]; -extern const char kEnableEmojiContextMenuName[]; -extern const char kEnableEmojiContextMenuDescription[]; - extern const char kEnforceTLS13DowngradeName[]; extern const char kEnforceTLS13DowngradeDescription[];
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn index e707d0b3..8e50856c 100644 --- a/chrome/browser/media/router/BUILD.gn +++ b/chrome/browser/media/router/BUILD.gn
@@ -103,6 +103,8 @@ "providers/cast/cast_media_route_provider.h", "providers/cast/cast_media_route_provider_metrics.cc", "providers/cast/cast_media_route_provider_metrics.h", + "providers/cast/cast_session_tracker.cc", + "providers/cast/cast_session_tracker.h", "providers/cast/chrome_cast_message_handler.cc", "providers/cast/chrome_cast_message_handler.h", "providers/cast/dual_media_sink_service.cc",
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager.cc b/chrome/browser/media/router/providers/cast/cast_activity_manager.cc index d17d376..1d65e3d 100644 --- a/chrome/browser/media/router/providers/cast/cast_activity_manager.cc +++ b/chrome/browser/media/router/providers/cast/cast_activity_manager.cc
@@ -116,12 +116,16 @@ CastActivityRecord::CastActivityRecord( const MediaRoute& route, + const std::string& app_id, MediaSinkServiceBase* media_sink_service, cast_channel::CastMessageHandler* message_handler, + CastSessionTracker* session_tracker, DataDecoder* data_decoder) : route_(route), + app_id_(app_id), media_sink_service_(media_sink_service), message_handler_(message_handler), + session_tracker_(session_tracker), data_decoder_(data_decoder) {} CastActivityRecord::~CastActivityRecord() {} @@ -138,9 +142,20 @@ return presentation_connection; } -void CastActivityRecord::SetSession(std::unique_ptr<CastSession> session) { - session_ = std::move(session); - route_.set_description(CastSession::GetRouteDescription(*session_)); +void CastActivityRecord::SetOrUpdateSession(const CastSession& session, + const MediaSinkInternal& sink, + const std::string& hash_token) { + DVLOG(2) << "CastActivityRecord::SetOrUpdateSession old session_id = " + << session_id_ << ", new session_id = " << session.session_id(); + if (session_id_.empty()) { + session_id_ = session.session_id(); + } else { + DCHECK_EQ(session_id_, session.session_id()); + for (auto& client : connected_clients_) + client.second->SendMessageToClient( + CreateUpdateSessionMessage(session, client.first, sink, hash_token)); + } + route_.set_description(session.GetRouteDescription()); } bool CastActivityRecord::SendAppMessageToReceiver( @@ -150,28 +165,32 @@ const MediaSink::Id& sink_id = route_.media_sink_id(); const MediaSinkInternal* sink = media_sink_service_->GetSinkById(sink_id); if (!sink) { + // TODO(crbug.com/905002): Add UMA metrics for this and other error + // conditions. DVLOG(2) << "Sink not found"; return false; } - if (!session_ || - session_->session_id != cast_message.app_message_session_id) { - DVLOG(2) << "Session not found: " << cast_message.app_message_session_id; + if (session_id_ != cast_message.app_message_session_id) { + DVLOG(2) << "Session ID mismatch: " << cast_message.app_message_session_id; return false; } - + const CastSession* session = session_tracker_->GetSessionById(session_id_); + if (!session) { + DVLOG(2) << "Session not found: " << session_id_; + return false; + } const std::string& message_namespace = cast_message.app_message_namespace; - if (!base::ContainsKey(session_->message_namespaces, message_namespace)) { + if (!base::ContainsKey(session->message_namespaces(), message_namespace)) { DVLOG(2) << "Disallowed message namespace: " << message_namespace; // TODO(imcheng): Send error code back to SDK client. return false; } - message_handler_->SendAppMessage( sink->cast_data().cast_channel_id, cast_channel::CreateCastMessage( message_namespace, cast_message.app_message_body, - cast_message.client_id, session_->transport_id)); + cast_message.client_id, session->transport_id())); return true; } @@ -199,11 +218,13 @@ CastActivityManager::CastActivityManager( MediaSinkServiceBase* media_sink_service, + CastSessionTracker* session_tracker, cast_channel::CastMessageHandler* message_handler, mojom::MediaRouter* media_router, std::unique_ptr<DataDecoder> data_decoder, const std::string& hash_token) : media_sink_service_(media_sink_service), + session_tracker_(session_tracker), message_handler_(message_handler), media_router_(media_router), data_decoder_(std::move(data_decoder)), @@ -212,12 +233,22 @@ DCHECK(media_sink_service_); DCHECK(message_handler_); DCHECK(media_router_); + DCHECK(session_tracker_); message_handler_->AddObserver(this); + for (const auto& sink_id_session : session_tracker_->sessions_by_sink_id()) { + const MediaSinkInternal* sink = + media_sink_service_->GetSinkById(sink_id_session.first); + if (!sink) + break; + AddNonLocalActivityRecord(*sink, *sink_id_session.second); + } + session_tracker_->AddObserver(this); } CastActivityManager::~CastActivityManager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); message_handler_->RemoveObserver(this); + session_tracker_->RemoveObserver(this); } void CastActivityManager::AddRouteQuery(const MediaSource::Id& source) { @@ -249,25 +280,52 @@ const MediaSink::Id& sink_id = sink.sink().id(); MediaRoute::Id route_id = MediaRoute::GetMediaRouteId(presentation_id, sink_id, source); - - // We will preemptively add the route to the list while the session launch - // request is pending. This way we can report back to Media Router that a - // route is added without waiting for the response. - // Route description will be filled in later with session data returned by - // the Cast receiver. MediaRoute route(route_id, source, sink_id, /* description */ std::string(), /* is_local */ true, /* for_display */ true); route.set_incognito(incognito); + DoLaunchSessionParams params(route, cast_source, sink, origin, tab_id, + std::move(callback)); + // If there is currently a session on the sink, it must be terminated before + // the new session can be launched. + auto it = std::find_if( + activities_.begin(), activities_.end(), [&sink_id](const auto& activity) { + return activity.second->route().media_sink_id() == sink_id; + }); + if (it == activities_.end()) { + DoLaunchSession(std::move(params)); + } else { + const MediaRoute::Id& existing_route_id = + it->second->route().media_route_id(); + TerminateSession( + existing_route_id, + base::BindOnce( + &CastActivityManager::LaunchSessionAfterTerminatingExisting, + weak_ptr_factory_.GetWeakPtr(), existing_route_id, + std::move(params))); + } +} + +void CastActivityManager::DoLaunchSession(DoLaunchSessionParams params) { + const MediaRoute& route = params.route; + const CastMediaSource& cast_source = params.cast_source; + const MediaRoute::Id& route_id = route.media_route_id(); + const MediaSinkInternal& sink = params.sink; + // TODO(crbug.com/904995): In the case of multiple app IDs (e.g. mirroring), + // we need to choose an appropriate app ID to launch based on capabilities. + std::string app_id = cast_source.GetAppIds()[0]; + + DVLOG(2) << "Launching session with route ID = " << route_id + << ", source ID = " << cast_source.source_id() + << ", sink ID = " << sink.sink().id() << ", app ID = " << app_id + << ", origin = " << params.origin << ", tab ID = " << params.tab_id; auto activity = std::make_unique<CastActivityRecord>( - route, media_sink_service_, message_handler_, data_decoder_.get()); - CastActivityRecord* activity_ptr = activity.get(); + route, app_id, media_sink_service_, message_handler_, session_tracker_, + data_decoder_.get()); + auto* activity_ptr = activity.get(); activities_.emplace(route_id, std::move(activity)); NotifyAllOnRoutesUpdated(); - // TODO(imcheng): In the case of multiple app IDs (e.g. mirroring), we need to - // choose an appropriate app ID to launch based on capabilities. - std::string app_id = cast_source.GetAppIds()[0]; base::TimeDelta launch_timeout = cast_source.launch_timeout(); message_handler_->LaunchSession( sink.cast_data().cast_channel_id, app_id, launch_timeout, @@ -279,20 +337,39 @@ const std::string& client_id = cast_source.client_id(); if (!client_id.empty()) { presentation_connection = - activity_ptr->AddClient(client_id, origin, tab_id); + activity_ptr->AddClient(client_id, params.origin, params.tab_id); activity_ptr->SendMessageToClient( client_id, CreateReceiverActionCastMessage(client_id, sink, hash_token_)); } - std::move(callback).Run(route, std::move(presentation_connection), - /* error_text */ base::nullopt, - RouteRequestResult::ResultCode::OK); + std::move(params.callback) + .Run(route, std::move(presentation_connection), + /* error_text */ base::nullopt, RouteRequestResult::ResultCode::OK); +} + +void CastActivityManager::LaunchSessionAfterTerminatingExisting( + const MediaRoute::Id& existing_route_id, + DoLaunchSessionParams params, + const base::Optional<std::string>& error_string, + RouteRequestResult::ResultCode result) { + // NOTE(mfoltz): I don't recall if an explicit STOP request is required by + // Cast V2 before launching a new session. I think in the Javascript MRP + // session termination is a fire and forget operation. In which case we could + // rely on RECEIVER_STATUS to clean up the state from the just-removed + // session, versus having to stop then wait for a response. + DLOG_IF(ERROR, error_string) + << "Failed to terminate existing session before launching new " + << "session! New session may not operate correctly. Error: " + << *error_string; + activities_.erase(existing_route_id); + DoLaunchSession(std::move(params)); } void CastActivityManager::RemoveActivity( ActivityMap::iterator activity_it, - blink::mojom::PresentationConnectionState state) { + blink::mojom::PresentationConnectionState state, + bool notify) { DCHECK(state == blink::mojom::PresentationConnectionState::CLOSED || state == blink::mojom::PresentationConnectionState::TERMINATED); if (state == blink::mojom::PresentationConnectionState::CLOSED) @@ -301,7 +378,8 @@ activity_it->second->TerminatePresentationConnections(); activities_.erase(activity_it); - NotifyAllOnRoutesUpdated(); + if (notify) + NotifyAllOnRoutesUpdated(); } void CastActivityManager::TerminateSession( @@ -315,13 +393,16 @@ return; } + DVLOG(2) << "Terminating session with route ID: " << route_id; + const auto& activity = activity_it->second; - const CastSession* session = activity->session(); + const std::string& session_id = activity->session_id(); const MediaRoute& route = activity->route(); // There is no session associated with the route, e.g. the launch request is // still pending. - if (!session) { + if (session_id.empty()) { + DVLOG(2) << "Terminated route has no session ID."; RemoveActivity(activity_it); std::move(callback).Run(base::nullopt, RouteRequestResult::OK); return; @@ -341,7 +422,7 @@ } message_handler_->StopSession( - sink->cast_data().cast_channel_id, session->session_id, + sink->cast_data().cast_channel_id, session_id, base::BindOnce(&CastActivityManager::HandleStopSessionResponse, weak_ptr_factory_.GetWeakPtr(), route_id, std::move(callback))); @@ -364,24 +445,117 @@ // Note: app messages are received only after session is created. DVLOG(2) << "Received app message on cast channel " << channel_id; auto it = GetActivityByChannelId(channel_id); - if (it == activities_.end() || !it->second->session()) + if (it == activities_.end()) { + DVLOG(2) << "No activity associated with channel!"; return; + } CastActivityRecord* activity = it->second.get(); - const CastSession* session = activity->session(); + const std::string& session_id = activity->session_id(); + if (session_id.empty()) { + DVLOG(2) << "No session associated with activity!"; + return; + } + if (message.destination_id() == "*") { for (const auto& client : activity->connected_clients()) { activity->SendMessageToClient( - client.first, - CreateAppMessage(session->session_id, client.first, message)); + client.first, CreateAppMessage(session_id, client.first, message)); } } else { const std::string& client_id = message.destination_id(); activity->SendMessageToClient( - client_id, CreateAppMessage(session->session_id, client_id, message)); + client_id, CreateAppMessage(session_id, client_id, message)); } } +void CastActivityManager::OnSessionAddedOrUpdated(const MediaSinkInternal& sink, + const CastSession& session) { + const MediaSink::Id& sink_id = sink.sink().id(); + auto activity_it = GetActivityByChannelId(sink.cast_data().cast_channel_id); + CastActivityRecord* activity = + activity_it == activities_.end() ? nullptr : activity_it->second.get(); + DCHECK(!activity || activity->route().media_sink_id() == sink_id); + + // If |activity| is null, we have discovered a non-local activity. + if (!activity) { + AddNonLocalActivityRecord(sink, session); + NotifyAllOnRoutesUpdated(); + return; + } + + DVLOG(2) << "Receiver status: update/replace activity: " + << activity->route().media_route_id(); + const std::string& existing_session_id = activity->session_id(); + + // This condition seems to always be true in practice, but if it's not, we + // still try to handle them gracefully below. TODO(jrw): Replace DCHECK with + // an UMA metric. + DCHECK(!existing_session_id.empty()); + + // If |existing_session_id| is empty, then most likely it's due to a pending + // launch. Check the app ID to see if the existing activity should be updated + // or replaced. Otherwise, check the session ID to see if the existing + // activity should be updated or replaced. + if (existing_session_id.empty() + ? activity->app_id() == session.app_id() + : existing_session_id == session.session_id()) { + activity->SetOrUpdateSession(session, sink, hash_token_); + } else { + // NOTE(jrw): This happens if a receiver switches to a new session (or app), + // causing the activity associated with the old session to be considered + // remote. This scenario is tested in the unit tests, but it's unclear + // whether it even happens in practice; I haven't been able to trigger it. + // + // TODO(jrw): Try to come up with a test to exercise this code. + RemoveActivity(activity_it, + blink::mojom::PresentationConnectionState::TERMINATED, + /* notify */ false); + AddNonLocalActivityRecord(sink, session); + } + NotifyAllOnRoutesUpdated(); +} + +void CastActivityManager::OnSessionRemoved(const MediaSinkInternal& sink) { + const MediaSink::Id& sink_id = sink.sink().id(); + auto it = std::find_if( + activities_.begin(), activities_.end(), [&sink_id](const auto& activity) { + return activity.second->route().media_sink_id() == sink_id; + }); + if (it != activities_.end()) + RemoveActivity(it); +} + +void CastActivityManager::AddNonLocalActivityRecord( + const MediaSinkInternal& sink, + const CastSession& session) { + const MediaSink::Id& sink_id = sink.sink().id(); + + // We derive the MediaSource from a session using the app ID. + const std::string& app_id = session.app_id(); + std::unique_ptr<CastMediaSource> cast_source = + CastMediaSource::FromAppId(app_id); + MediaSource source(cast_source->source_id()); + + // The session ID is used instead of presentation ID in determining the + // route ID. + MediaRoute::Id route_id = + MediaRoute::GetMediaRouteId(session.session_id(), sink_id, source); + DVLOG(2) << "Adding non-local route " << route_id + << " with sink ID = " << sink_id + << ", session ID = " << session.session_id() + << ", app ID = " << app_id; + // Route description is set in SetOrUpdateSession(). + MediaRoute route(route_id, source, sink_id, /* description */ std::string(), + /* is_local */ false, /* for_display */ true); + + auto record = std::make_unique<CastActivityRecord>( + route, app_id, media_sink_service_, message_handler_, session_tracker_, + data_decoder_.get()); + record->SetOrUpdateSession(session, sink, hash_token_); + activities_.emplace(route_id, std::move(record)); +} + const MediaRoute* CastActivityManager::GetRoute( const MediaRoute::Id& route_id) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -432,8 +606,7 @@ return; } - auto session = - CastSession::From(sink, hash_token_, *response.receiver_status); + auto session = CastSession::From(sink, *response.receiver_status); if (!session) { DVLOG(2) << "Unable to get session from launch response"; RemoveActivity(activity_it); @@ -446,15 +619,16 @@ DVLOG(2) << "Sending new_session message for route " << route_id << ", client_id: " << client_id; activity_it->second->SendMessageToClient( - client_id, CreateNewSessionMessage(*session, cast_source.client_id())); + client_id, CreateNewSessionMessage(*session, cast_source.client_id(), + sink, hash_token_)); // TODO(imcheng): Query media status. message_handler_->EnsureConnection(sink.cast_data().cast_channel_id, cast_source.client_id(), - session->transport_id); + session->transport_id()); } - activity_it->second->SetSession(std::move(session)); + activity_it->second->SetOrUpdateSession(*session, sink, hash_token_); NotifyAllOnRoutesUpdated(); } @@ -465,8 +639,8 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto activity_it = activities_.find(route_id); if (activity_it == activities_.end()) { - std::move(callback).Run("Activity not found", - RouteRequestResult::ROUTE_NOT_FOUND); + // The activity could've been removed via RECEIVER_STATUS message. + std::move(callback).Run(base::nullopt, RouteRequestResult::OK); return; } @@ -490,4 +664,23 @@ media_router_->OnIssue(info); } +CastActivityManager::DoLaunchSessionParams::DoLaunchSessionParams( + const MediaRoute& route, + const CastMediaSource& cast_source, + const MediaSinkInternal& sink, + const url::Origin& origin, + int tab_id, + mojom::MediaRouteProvider::CreateRouteCallback callback) + : route(route), + cast_source(cast_source), + sink(sink), + origin(origin), + tab_id(tab_id), + callback(std::move(callback)) {} + +CastActivityManager::DoLaunchSessionParams::DoLaunchSessionParams( + DoLaunchSessionParams&& other) noexcept = default; + +CastActivityManager::DoLaunchSessionParams::~DoLaunchSessionParams() = default; + } // namespace media_router
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager.h b/chrome/browser/media/router/providers/cast/cast_activity_manager.h index 2251f41..1268b4f 100644 --- a/chrome/browser/media/router/providers/cast/cast_activity_manager.h +++ b/chrome/browser/media/router/providers/cast/cast_activity_manager.h
@@ -13,9 +13,12 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "chrome/browser/media/router/providers/cast/cast_internal_message_util.h" +#include "chrome/browser/media/router/providers/cast/cast_session_tracker.h" #include "chrome/common/media_router/discovery/media_sink_internal.h" +#include "chrome/common/media_router/discovery/media_sink_service_base.h" #include "chrome/common/media_router/media_route.h" #include "chrome/common/media_router/mojo/media_router.mojom.h" +#include "chrome/common/media_router/providers/cast/cast_media_source.h" #include "components/cast_channel/cast_message_handler.h" #include "components/cast_channel/cast_message_util.h" #include "mojo/public/cpp/bindings/binding.h" @@ -27,7 +30,6 @@ class CastActivityRecord; class CastMediaSource; class DataDecoder; -class MediaSinkServiceBase; // Represents a Cast SDK client connection to a Cast session. This class // contains PresentationConnection Mojo pipes to send and receive messages @@ -101,20 +103,28 @@ // It keeps track of the set of Cast SDK clients connected to the application. // Note that we do not keep track of 1-UA mode presentations here. Instead, they // are handled by LocalPresentationManager. +// +// Instances of this class are associated with a specific session and app. class CastActivityRecord { public: CastActivityRecord(const MediaRoute& route, + const std::string& app_id, MediaSinkServiceBase* media_sink_service, cast_channel::CastMessageHandler* message_handler, + CastSessionTracker* session_tracker, DataDecoder* data_decoder); ~CastActivityRecord(); const MediaRoute& route() const { return route_; } + const std::string& app_id() const { return app_id_; } const base::flat_map<std::string, std::unique_ptr<CastSessionClient>>& connected_clients() { return connected_clients_; } - const CastSession* session() { return session_.get(); } + const std::string& session_id() const { return session_id_; } + + bool pending() const { return pending_; } + void set_pending(bool pending) { pending_ = pending; } // Sends |cast_message|, which must be of type kAppMessage, to the receiver // hosting this session. Returns true if the message is sent successfully. @@ -127,8 +137,16 @@ const url::Origin& origin, int tab_id); - // Also updates the description on |route_|. - void SetSession(std::unique_ptr<CastSession> session); + // On the first call, saves the ID of |session|. On subsequent calls, + // notifies all connected clients that the session has been updated. In both + // cases, the stored route description is updated to match the session + // description. + // + // The |hash_token| parameter is used for hashing receiver IDs in messages + // sent to the Cast SDK, and |sink| is the sink associated with |session|. + void SetOrUpdateSession(const CastSession& session, + const MediaSinkInternal& sink, + const std::string& hash_token); // Sends |message| to the client given by |client_id|. void SendMessageToClient( @@ -144,30 +162,29 @@ friend class CastSessionClient; MediaRoute route_; + const std::string app_id_; base::flat_map<std::string, std::unique_ptr<CastSessionClient>> connected_clients_; // Set by CastActivityManager after the session is launched successfully. - // TODO(imcheng): Change this to a session ID when sessions are tracked - // by the CastSessionTracker singleton. - std::unique_ptr<CastSession> session_; + std::string session_id_; MediaSinkServiceBase* const media_sink_service_; // TODO(https://crbug.com/809249): Consider wrapping CastMessageHandler with // known parameters (sink, client ID, session transport ID) and passing them // to objects that need to send messges to the receiver. cast_channel::CastMessageHandler* const message_handler_; + CastSessionTracker* const session_tracker_; DataDecoder* const data_decoder_; + bool pending_ = true; DISALLOW_COPY_AND_ASSIGN(CastActivityRecord); }; // Handles launching and terminating Cast application on a Cast receiver, and // acts as the source of truth for Cast activities and MediaRoutes. -// TODO(imcheng): CastActivityManager should listen for RECEIVER_STATUS and -// MEDIA_STATUS messages to generate non-local routes and update existing -// routes. -class CastActivityManager : public cast_channel::CastMessageHandler::Observer { +class CastActivityManager : public cast_channel::CastMessageHandler::Observer, + public CastSessionTracker::Observer { public: // |media_sink_service|: Provides Cast MediaSinks. // |message_handler|: Used for sending and receiving messages to Cast @@ -178,6 +195,7 @@ // |hash_token|: Used for hashing receiver IDs in messages sent to the Cast // SDK. CastActivityManager(MediaSinkServiceBase* media_sink_service, + CastSessionTracker* session_tracker, cast_channel::CastMessageHandler* message_handler, mojom::MediaRouter* media_router, std::unique_ptr<DataDecoder> data_decoder, @@ -213,15 +231,61 @@ void OnAppMessage(int channel_id, const cast_channel::CastMessage& message) override; + // CastSessionTracker::Observer implementation. + void OnSessionAddedOrUpdated(const MediaSinkInternal& sink, + const CastSession& session) override; + void OnSessionRemoved(const MediaSinkInternal& sink) override; + private: - friend class CastActivityRecord; using ActivityMap = base::flat_map<MediaRoute::Id, std::unique_ptr<CastActivityRecord>>; - void RemoveActivity( - ActivityMap::iterator activity_it, - blink::mojom::PresentationConnectionState state = - blink::mojom::PresentationConnectionState::TERMINATED); + // Bundle of parameters for DoLaunchSession(). + struct DoLaunchSessionParams { + // Note: The compiler-generated constructors and destructor would be + // sufficient here, but the style guide requires them to be defined + // explicitly. + DoLaunchSessionParams( + const MediaRoute& route, + const CastMediaSource& cast_source, + const MediaSinkInternal& sink, + const url::Origin& origin, + int tab_id, + mojom::MediaRouteProvider::CreateRouteCallback callback); + DoLaunchSessionParams(DoLaunchSessionParams&& other) noexcept; + ~DoLaunchSessionParams(); + DoLaunchSessionParams& operator=(DoLaunchSessionParams&&) = delete; + + // The route for which a session is being launched. + MediaRoute route; + + // The media source for which a session is being launched. + CastMediaSource cast_source; + + // The sink for which a session is being launched. + MediaSinkInternal sink; + + // The origin of the Cast SDK client. Used for auto-join. + url::Origin origin; + + // The tab ID of the Cast SDK client. Used for auto-join. + int tab_id; + + // Callback to execute after the launch request has been sent. + mojom::MediaRouteProvider::CreateRouteCallback callback; + }; + + void DoLaunchSession(DoLaunchSessionParams params); + void LaunchSessionAfterTerminatingExisting( + const MediaRoute::Id& existing_route_id, + DoLaunchSessionParams params, + const base::Optional<std::string>& error_string, + RouteRequestResult::ResultCode result); + + void RemoveActivity(ActivityMap::iterator activity_it, + blink::mojom::PresentationConnectionState state = + blink::mojom::PresentationConnectionState::TERMINATED, + bool notify = true); void NotifyAllOnRoutesUpdated(); void NotifyOnRoutesUpdated(const MediaSource::Id& source_id, const std::vector<MediaRoute>& routes); @@ -236,6 +300,10 @@ mojom::MediaRouteProvider::TerminateRouteCallback callback, bool success); + // Creates and stores a CastActivityRecord representing a non-local activity. + void AddNonLocalActivityRecord(const MediaSinkInternal& sink, + const CastSession& session); + void SendFailedToCastIssue(const MediaSink::Id& sink_id, const MediaRoute::Id& route_id); @@ -246,6 +314,7 @@ // The following raw pointer fields are assumed to outlive |this|. MediaSinkServiceBase* const media_sink_service_; + CastSessionTracker* const session_tracker_; cast_channel::CastMessageHandler* const message_handler_; mojom::MediaRouter* const media_router_;
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc b/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc index 7f34cb6..545c9897 100644 --- a/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc +++ b/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc
@@ -16,6 +16,7 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/test/test_browser_thread_bundle.h" #include "services/data_decoder/data_decoder_service.h" +#include "services/data_decoder/public/cpp/testing_json_parser.h" #include "services/data_decoder/public/mojom/constants.mojom.h" #include "services/service_manager/public/cpp/test/test_connector_factory.h" #include "testing/gmock/include/gmock/gmock.h" @@ -30,6 +31,47 @@ namespace { constexpr char kOrigin[] = "https://google.com"; constexpr int kTabId = 1; +constexpr char kSource1[] = "cast:ABCDEFGH?clientId=12345"; +constexpr char kSource2[] = "cast:BBBBBBBB?clientId=12345"; +constexpr char kReceiverStatus[] = R"({ + "applications": [{ + "appId": "ABCDEFGH", + "displayName": "App display name", + "namespaces": [ + {"name": "urn:x-cast:com.google.cast.media"}, + {"name": "urn:x-cast:com.google.foo"} + ], + "sessionId": "sessionId", + "statusText":"App status", + "transportId":"transportId" + }] + })"; +constexpr char kReceiverStatus2[] = R"({ + "applications": [{ + "appId": "ABCDEFGH", + "displayName": "Updated display name", + "namespaces": [ + {"name": "urn:x-cast:com.google.cast.media"}, + {"name": "urn:x-cast:com.google.foo"} + ], + "sessionId": "sessionId", + "statusText":"App status", + "transportId":"transportId" + }] + })"; +constexpr char kReceiverStatus3[] = R"({ + "applications": [{ + "appId": "BBBBBBBB", + "displayName": "Another app", + "namespaces": [ + {"name": "urn:x-cast:com.google.cast.media"}, + {"name": "urn:x-cast:com.google.foo"} + ], + "sessionId": "sessionId2", + "statusText":"App status", + "transportId":"transportId" + }] + })"; } // namespace class ClientPresentationConnection @@ -75,18 +117,34 @@ router_binding_ = std::make_unique<mojo::Binding<mojom::MediaRouter>>( &mock_router_, mojo::MakeRequest(&router_ptr_)); + delete session_tracker_; + session_tracker_ = new CastSessionTracker( + &media_sink_service_, &message_handler_, socket_service_.task_runner()); manager_ = std::make_unique<CastActivityManager>( - &media_sink_service_, &message_handler_, router_ptr_.get(), + &media_sink_service_, session_tracker_, &message_handler_, + router_ptr_.get(), std::make_unique<DataDecoder>(connector_factory_.GetDefaultConnector()), "hash-token"); + RunUntilIdle(); + // Make sure we get route updates. manager_->AddRouteQuery(MediaSource::Id()); } - void TearDown() override { manager_.reset(); } + void TearDown() override { + // This is a no-op for many tests, but it serves as a good sanity check in + // any case. + RunUntilIdle(); - void VerifyAndClearExpectations() { + manager_.reset(); + } + + // Run any pending events and verify expectations associated with them. This + // method is sometimes called when there are clearly no pending events simply + // to check expectations for code executed synchronously. + void RunUntilIdle() { + thread_bundle_.RunUntilIdle(); ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&message_handler_)); ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&mock_router_)); } @@ -108,48 +166,33 @@ } void LaunchSession() { - auto source = CastMediaSource::From("cast:ABCDEFGH?clientId=12345"); - ASSERT_TRUE(source); - // MediaRouter is notified of new route. - EXPECT_CALL(mock_router_, OnRoutesUpdated(MediaRouteProviderId::CAST, - Not(IsEmpty()), _, _)); + ExpectSingleRouteUpdate(); // A launch session request is sent to the sink. EXPECT_CALL(message_handler_, LaunchSession(sink_.cast_data().cast_channel_id, "ABCDEFGH", kDefaultLaunchTimeout, _)) - .WillOnce([this](int, const std::string&, base::TimeDelta, - cast_channel::LaunchSessionCallback callback) { - launch_session_callback_ = std::move(callback); - }); + .WillOnce( + [this](auto chanel_id, auto app_id, auto timeout, auto callback) { + launch_session_callback_ = std::move(callback); + }); + + auto source = CastMediaSource::FromMediaSourceId(kSource1); + ASSERT_TRUE(source); // Callback will be invoked synchronously. manager_->LaunchSession( - *source, sink_, "presentationId", url::Origin::Create(GURL(kOrigin)), - kTabId, + *source, sink_, "presentationId", origin_, kTabId, /*incognito*/ false, base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionSuccess, base::Unretained(this))); - thread_bundle_.RunUntilIdle(); - VerifyAndClearExpectations(); + + RunUntilIdle(); } cast_channel::LaunchSessionResponse GetSuccessLaunchResponse() { - std::string receiver_status_str = R"({ - "applications": [{ - "appId": "ABCDEFGH", - "displayName": "App display name", - "namespaces": [ - {"name": "urn:x-cast:com.google.cast.media"}, - {"name": "urn:x-cast:com.google.foo"} - ], - "sessionId": "sessionId", - "statusText":"App status", - "transportId":"transportId" - }] - })"; - auto receiver_status = base::JSONReader::Read(receiver_status_str); + auto receiver_status = base::JSONReader::Read(kReceiverStatus); cast_channel::LaunchSessionResponse response; response.result = cast_channel::LaunchSessionResponse::Result::kOk; response.receiver_status = std::move(*receiver_status); @@ -165,13 +208,15 @@ EXPECT_CALL(message_handler_, EnsureConnection(sink_.cast_data().cast_channel_id, "12345", "transportId")); - std::move(launch_session_callback_).Run(GetSuccessLaunchResponse()); + auto response = GetSuccessLaunchResponse(); + session_tracker_->SetSessionForTest( + route_->media_sink_id(), + CastSession::From(sink_, *response.receiver_status)); + std::move(launch_session_callback_).Run(std::move(response)); EXPECT_CALL(*client_connection_, OnMessage(_)); - EXPECT_CALL(mock_router_, OnRoutesUpdated(MediaRouteProviderId::CAST, - Not(IsEmpty()), _, _)); - thread_bundle_.RunUntilIdle(); - VerifyAndClearExpectations(); + ExpectSingleRouteUpdate(); + RunUntilIdle(); } // Precondition: |LaunchSession()| must be called first. @@ -184,13 +229,11 @@ std::move(launch_session_callback_).Run(std::move(response)); EXPECT_CALL(mock_router_, OnIssue(_)); - EXPECT_CALL(mock_router_, - OnRoutesUpdated(MediaRouteProviderId::CAST, IsEmpty(), _, _)); + ExpectEmptyRouteUpdate(); EXPECT_CALL( *client_connection_, DidChangeState(blink::mojom::PresentationConnectionState::TERMINATED)); - thread_bundle_.RunUntilIdle(); - VerifyAndClearExpectations(); + RunUntilIdle(); } // Precondition: |LaunchSession()| must be called first. @@ -199,9 +242,7 @@ EXPECT_CALL(message_handler_, StopSession(sink_.cast_data().cast_channel_id, "sessionId", _)) - .WillOnce([&stop_session_callback]( - int, const std::string&, - cast_channel::StopSessionCallback callback) { + .WillOnce([&](auto channel_id, auto session_id, auto callback) { stop_session_callback = std::move(callback); }); manager_->TerminateSession( @@ -212,8 +253,7 @@ base::Unretained(this))); // Receiver action stop message is sent to SDK client. EXPECT_CALL(*client_connection_, OnMessage(_)); - thread_bundle_.RunUntilIdle(); - VerifyAndClearExpectations(); + RunUntilIdle(); std::move(stop_session_callback).Run(success); } @@ -227,36 +267,57 @@ route_->media_route_id(), base::BindOnce(&CastActivityManagerTest::ExpectTerminateResultSuccess, base::Unretained(this))); - thread_bundle_.RunUntilIdle(); - VerifyAndClearExpectations(); + RunUntilIdle(); } void ExpectTerminateResultSuccess( const base::Optional<std::string>& error_text, RouteRequestResult::ResultCode result_code) { EXPECT_EQ(RouteRequestResult::OK, result_code); - EXPECT_CALL(mock_router_, - OnRoutesUpdated(MediaRouteProviderId::CAST, IsEmpty(), _, _)); + ExpectEmptyRouteUpdate(); EXPECT_CALL( *client_connection_, DidChangeState(blink::mojom::PresentationConnectionState::TERMINATED)); - thread_bundle_.RunUntilIdle(); - VerifyAndClearExpectations(); + RunUntilIdle(); } void ExpectTerminateResultFailure( const base::Optional<std::string>& error_text, RouteRequestResult::ResultCode result_code) { EXPECT_NE(RouteRequestResult::OK, result_code); + ExpectNoRouteUpdate(); + RunUntilIdle(); + } + + // Expect a call to OnRoutesUpdated() with a single route, which will + // optionally be saved in the variable pointed to by |route_ptr|. + void ExpectSingleRouteUpdate(MediaRoute* route_ptr = nullptr) { + EXPECT_CALL(mock_router_, OnRoutesUpdated(MediaRouteProviderId::CAST, + Not(IsEmpty()), _, _)) + .WillOnce([=](auto provider_id, auto routes, auto media_source, + auto joinable_route_ids) { + EXPECT_EQ(1u, routes.size()); + if (route_ptr) { + *route_ptr = routes[0]; + } + }); + } + + // Expect a call to OnRoutesUpdated() with no routes. + void ExpectEmptyRouteUpdate() { EXPECT_CALL(mock_router_, - OnRoutesUpdated(MediaRouteProviderId::CAST, _, _, _)) - .Times(0); - thread_bundle_.RunUntilIdle(); - VerifyAndClearExpectations(); + OnRoutesUpdated(MediaRouteProviderId::CAST, IsEmpty(), _, _)) + .Times(1); + } + + // Expect that OnRoutesUpdated() will not be called. + void ExpectNoRouteUpdate() { + EXPECT_CALL(mock_router_, OnRoutesUpdated(_, _, _, _)).Times(0); } protected: content::TestBrowserThreadBundle thread_bundle_; + data_decoder::TestingJsonParser::ScopedFactoryOverride parser_override_; service_manager::TestConnectorFactory connector_factory_; data_decoder::DataDecoderService data_decoder_service_; @@ -276,6 +337,12 @@ TestMediaSinkService media_sink_service_; MockCastAppDiscoveryService app_discovery_service_; std::unique_ptr<CastActivityManager> manager_; + + // We mus use a raw pointer instead of a smart pointer because + // CastSessionTracker's constructor and destructor are private. + CastSessionTracker* session_tracker_ = nullptr; + + const url::Origin origin_ = url::Origin::Create(GURL(kOrigin)); }; TEST_F(CastActivityManagerTest, LaunchSession) { @@ -288,6 +355,143 @@ LaunchSessionResponseFailure(); } +TEST_F(CastActivityManagerTest, LaunchSessionTerminatesExistingSessionOnSink) { + LaunchSession(); + LaunchSessionResponseSuccess(); + + // Receiver action stop message is sent to SDK client. + EXPECT_CALL(*client_connection_, OnMessage(_)); + + // Existing session will be terminated. + cast_channel::StopSessionCallback stop_session_callback; + EXPECT_CALL(message_handler_, + StopSession(sink_.cast_data().cast_channel_id, "sessionId", _)) + .WillOnce([&](auto channel_id, auto session_id, auto callback) { + stop_session_callback = std::move(callback); + }); + + // Launch a new session on the same sink. + auto source = CastMediaSource::FromMediaSourceId(kSource2); + ASSERT_TRUE(source); + manager_->LaunchSession( + *source, sink_, "presentationId2", origin_, kTabId, /*incognito*/ + false, + base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionSuccess, + base::Unretained(this))); + RunUntilIdle(); + + { + testing::InSequence dummy; + + // Existing route is terminated before new route is created. + // MediaRouter is notified of terminated route. + ExpectEmptyRouteUpdate(); + + // After existing route is terminated, new route is created. + // MediaRouter is notified of new route. + ExpectSingleRouteUpdate(); + } + + // A launch session request is sent to the sink. + EXPECT_CALL(message_handler_, + LaunchSession(sink_.cast_data().cast_channel_id, "BBBBBBBB", + kDefaultLaunchTimeout, _)); + + std::move(stop_session_callback).Run(true); +} + +TEST_F(CastActivityManagerTest, AddRemoveNonLocalActivity) { + auto receiver_status_value = base::JSONReader::Read(kReceiverStatus); + ASSERT_TRUE(receiver_status_value); + auto session = CastSession::From(sink_, *receiver_status_value); + ASSERT_TRUE(session); + + MediaRoute route; + ExpectSingleRouteUpdate(&route); + manager_->OnSessionAddedOrUpdated(sink_, *session); + RunUntilIdle(); + + EXPECT_FALSE(route.is_local()); + + ExpectEmptyRouteUpdate(); + manager_->OnSessionRemoved(sink_); +} + +TEST_F(CastActivityManagerTest, UpdateNewlyCreatedSession) { + LaunchSession(); + LaunchSessionResponseSuccess(); + + auto receiver_status_value = base::JSONReader::Read(kReceiverStatus); + ASSERT_TRUE(receiver_status_value); + auto session = CastSession::From(sink_, *receiver_status_value); + ASSERT_TRUE(session); + + MediaRoute route; + ExpectSingleRouteUpdate(&route); + EXPECT_CALL(*client_connection_, OnMessage(_)); + + manager_->OnSessionAddedOrUpdated(sink_, *session); + RunUntilIdle(); + + EXPECT_TRUE(route.is_local()); + EXPECT_EQ(route.description(), session->GetRouteDescription()); +} + +TEST_F(CastActivityManagerTest, UpdateExistingSession) { + // Create and add the session to be updated, and verify it was added. + auto receiver_status_value = base::JSONReader::Read(kReceiverStatus); + ASSERT_TRUE(receiver_status_value); + auto session = CastSession::From(sink_, *receiver_status_value); + ASSERT_TRUE(session); + MediaRoute route; + ExpectSingleRouteUpdate(&route); + manager_->OnSessionAddedOrUpdated(sink_, *session); + RunUntilIdle(); + EXPECT_EQ(route.description(), session->GetRouteDescription()); + auto old_route_id = route.media_route_id(); + + // Description change should be reflect in route update. + auto updated_receiver_status = base::JSONReader::Read(kReceiverStatus2); + ASSERT_TRUE(updated_receiver_status); + auto updated_session = CastSession::From(sink_, *updated_receiver_status); + ASSERT_TRUE(updated_session); + + ExpectSingleRouteUpdate(&route); + + manager_->OnSessionAddedOrUpdated(sink_, *updated_session); + RunUntilIdle(); + + EXPECT_EQ(route.description(), updated_session->GetRouteDescription()); + EXPECT_EQ(old_route_id, route.media_route_id()); +} + +TEST_F(CastActivityManagerTest, ReplaceExistingSession) { + // Create and add the session to be replaced, and verify it was added. + auto receiver_status_value = base::JSONReader::Read(kReceiverStatus); + ASSERT_TRUE(receiver_status_value); + auto session = CastSession::From(sink_, *receiver_status_value); + ASSERT_TRUE(session); + MediaRoute route; + ExpectSingleRouteUpdate(&route); + manager_->OnSessionAddedOrUpdated(sink_, *session); + RunUntilIdle(); + auto old_route_id = route.media_route_id(); + EXPECT_EQ(route.description(), session->GetRouteDescription()); + + // Different session. + auto new_receiver_status = base::JSONReader::Read(kReceiverStatus3); + ASSERT_TRUE(new_receiver_status); + auto new_session = CastSession::From(sink_, *new_receiver_status); + ASSERT_TRUE(new_session); + + ExpectSingleRouteUpdate(&route); + manager_->OnSessionAddedOrUpdated(sink_, *new_session); + RunUntilIdle(); + + EXPECT_EQ(route.description(), new_session->GetRouteDescription()); + EXPECT_NE(old_route_id, route.media_route_id()); +} + TEST_F(CastActivityManagerTest, TerminateSession) { LaunchSession(); LaunchSessionResponseSuccess(); @@ -306,10 +510,7 @@ // Route already terminated, so no-op when handling launch response. std::move(launch_session_callback_).Run(GetSuccessLaunchResponse()); - EXPECT_CALL(mock_router_, - OnRoutesUpdated(MediaRouteProviderId::CAST, _, _, _)) - .Times(0); - thread_bundle_.RunUntilIdle(); + ExpectNoRouteUpdate(); } TEST_F(CastActivityManagerTest, AppMessageFromReceiver) { @@ -322,7 +523,6 @@ "sourceId", "12345"); message_handler_.OnMessage(socket_, message); EXPECT_CALL(*client_connection_, OnMessage(_)); - thread_bundle_.RunUntilIdle(); } TEST_F(CastActivityManagerTest, AppMessageFromReceiverAllDestinations) { @@ -335,7 +535,6 @@ "sourceId", "*"); message_handler_.OnMessage(socket_, message); EXPECT_CALL(*client_connection_, OnMessage(_)); - thread_bundle_.RunUntilIdle(); } TEST_F(CastActivityManagerTest, AppMessageFromReceiverUnknownDestination) { @@ -348,7 +547,6 @@ "sourceId", "99999"); message_handler_.OnMessage(socket_, message); EXPECT_CALL(*client_connection_, OnMessage(_)).Times(0); - thread_bundle_.RunUntilIdle(); } TEST_F(CastActivityManagerTest, AppMessageFromClient) { @@ -371,7 +569,6 @@ // An ACK message is sent back to client. EXPECT_CALL(*client_connection_, OnMessage(_)); - thread_bundle_.RunUntilIdle(); } TEST_F(CastActivityManagerTest, AppMessageFromClientInvalidNamespace) {
diff --git a/chrome/browser/media/router/providers/cast/cast_app_availability_tracker_unittest.cc b/chrome/browser/media/router/providers/cast/cast_app_availability_tracker_unittest.cc index f2fd454..f142f5c 100644 --- a/chrome/browser/media/router/providers/cast/cast_app_availability_tracker_unittest.cc +++ b/chrome/browser/media/router/providers/cast/cast_app_availability_tracker_unittest.cc
@@ -44,9 +44,9 @@ }; TEST_F(CastAppAvailabilityTrackerTest, RegisterSource) { - auto source1 = CastMediaSource::From("cast:AAAAAAAA?clientId=1"); + auto source1 = CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=1"); ASSERT_TRUE(source1); - auto source2 = CastMediaSource::From("cast:AAAAAAAA?clientId=2"); + auto source2 = CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=2"); ASSERT_TRUE(source2); base::flat_set<std::string> expected_app_ids = {"AAAAAAAA"}; @@ -65,7 +65,8 @@ } TEST_F(CastAppAvailabilityTrackerTest, RegisterSourceReturnsMultipleAppIds) { - auto source1 = CastMediaSource::From("urn:x-org.chromium.media:source:tab:1"); + auto source1 = CastMediaSource::FromMediaSourceId( + "urn:x-org.chromium.media:source:tab:1"); ASSERT_TRUE(source1); // Mirorring app ids. @@ -76,7 +77,8 @@ TEST_F(CastAppAvailabilityTrackerTest, MultipleAppIdsAlreadyTrackingOne) { // One of the mirroring app IDs. - auto source1 = CastMediaSource::From("cast:0F5096E8?clientId=123"); + auto source1 = + CastMediaSource::FromMediaSourceId("cast:0F5096E8?clientId=123"); ASSERT_TRUE(source1); base::flat_set<std::string> new_app_ids = {"0F5096E8"}; @@ -84,7 +86,8 @@ EXPECT_EQ(new_app_ids, tracker_.RegisterSource(*source1)); EXPECT_EQ(registered_app_ids, tracker_.GetRegisteredApps()); - auto source2 = CastMediaSource::From("urn:x-org.chromium.media:source:tab:1"); + auto source2 = CastMediaSource::FromMediaSourceId( + "urn:x-org.chromium.media:source:tab:1"); ASSERT_TRUE(source2); new_app_ids = {"85CDB22F"}; @@ -95,11 +98,11 @@ } TEST_F(CastAppAvailabilityTrackerTest, UpdateAppAvailability) { - auto source1 = CastMediaSource::From("cast:AAAAAAAA?clientId=1"); + auto source1 = CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=1"); ASSERT_TRUE(source1); - auto source2 = CastMediaSource::From("cast:AAAAAAAA?clientId=2"); + auto source2 = CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=2"); ASSERT_TRUE(source2); - auto source3 = CastMediaSource::From("cast:BBBBBBBB?clientId=3"); + auto source3 = CastMediaSource::FromMediaSourceId("cast:BBBBBBBB?clientId=3"); ASSERT_TRUE(source3); tracker_.RegisterSource(*source3); @@ -141,7 +144,7 @@ } TEST_F(CastAppAvailabilityTrackerTest, RemoveResultsForSink) { - auto source1 = CastMediaSource::From("cast:AAAAAAAA?clientId=1"); + auto source1 = CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=1"); ASSERT_TRUE(source1); tracker_.UpdateAppAvailability("sinkId1", "AAAAAAAA",
diff --git a/chrome/browser/media/router/providers/cast/cast_app_discovery_service_unittest.cc b/chrome/browser/media/router/providers/cast/cast_app_discovery_service_unittest.cc index 4a8174c..1bbfa79 100644 --- a/chrome/browser/media/router/providers/cast/cast_app_discovery_service_unittest.cc +++ b/chrome/browser/media/router/providers/cast/cast_app_discovery_service_unittest.cc
@@ -33,9 +33,12 @@ &socket_service_, &media_sink_service_, &clock_)), - source_a_1_(*CastMediaSource::From("cast:AAAAAAAA?clientId=1")), - source_a_2_(*CastMediaSource::From("cast:AAAAAAAA?clientId=2")), - source_b_1_(*CastMediaSource::From("cast:BBBBBBBB?clientId=1")) { + source_a_1_( + *CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=1")), + source_a_2_( + *CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=2")), + source_b_1_( + *CastMediaSource::FromMediaSourceId("cast:BBBBBBBB?clientId=1")) { ON_CALL(socket_service_, GetSocket(_)) .WillByDefault(testing::Return(&socket_)); task_runner_->RunPendingTasks(); @@ -273,7 +276,7 @@ base::Unretained(this))); // Same source as |source_a_1_|. The callback will be invoked. - auto source3 = CastMediaSource::From("cast:AAAAAAAA?clientId=1"); + auto source3 = CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=1"); ASSERT_TRUE(source3); EXPECT_CALL(message_handler_, RequestAppAvailability(_, _, _)).Times(0); EXPECT_CALL(*this, OnSinkQueryUpdated(source_a_1_.source_id(), sinks_1));
diff --git a/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc b/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc index 175bbbe..3409732 100644 --- a/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc +++ b/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc
@@ -18,10 +18,15 @@ namespace { +// The ID for the backdrop app. Cast devices running the backdrop app is +// considered idle, and an active session should not be reported. +constexpr char kBackdropAppId[] = "E8C28D3C"; + constexpr char kClientConnect[] = "client_connect"; constexpr char kAppMessage[] = "app_message"; constexpr char kReceiverAction[] = "receiver_action"; constexpr char kNewSession[] = "new_session"; +constexpr char kUpdateSession[] = "update_session"; bool GetString(const base::Value& value, const std::string& key, @@ -61,6 +66,8 @@ return CastInternalMessage::Type::kReceiverAction; if (type == kNewSession) return CastInternalMessage::Type::kNewSession; + if (type == kUpdateSession) + return CastInternalMessage::Type::kUpdateSession; return CastInternalMessage::Type::kOther; } @@ -75,6 +82,8 @@ return kReceiverAction; case CastInternalMessage::Type::kNewSession: return kNewSession; + case CastInternalMessage::Type::kUpdateSession: + return kUpdateSession; case CastInternalMessage::Type::kOther: NOTREACHED(); return ""; @@ -103,14 +112,21 @@ return value; } +std::string GetReceiverLabel(const MediaSinkInternal& sink, + const std::string& hash_token) { + std::string label = base::SHA1HashString(sink.sink().id() + hash_token); + base::Base64UrlEncode(label, base::Base64UrlEncodePolicy::OMIT_PADDING, + &label); + return label; +} + base::Value CreateReceiver(const MediaSinkInternal& sink, const std::string& hash_token) { base::Value receiver(base::Value::Type::DICTIONARY); - std::string label = base::SHA1HashString(sink.sink().id() + hash_token); - base::Base64UrlEncode(label, base::Base64UrlEncodePolicy::OMIT_PADDING, - &label); - receiver.SetKey("label", base::Value(label)); + if (!hash_token.empty()) { + receiver.SetKey("label", base::Value(GetReceiverLabel(sink, hash_token))); + } receiver.SetKey("friendlyName", base::Value(net::EscapeForHTML(sink.sink().name()))); @@ -170,6 +186,36 @@ return message; } +blink::mojom::PresentationConnectionMessagePtr CreatePresentationMessage( + const base::Value& message) { + std::string message_str; + CHECK(base::JSONWriter::Write(message, &message_str)); + return blink::mojom::PresentationConnectionMessage::NewMessage(message_str); +} + +// Creates a message with a session value in the "message" field. |type| must +// be either kNewSession or kUpdateSession. +blink::mojom::PresentationConnectionMessagePtr CreateSessionMessage( + const CastSession& session, + const std::string& client_id, + const MediaSinkInternal& sink, + const std::string& hash_token, + CastInternalMessage::Type type) { + DCHECK(type == CastInternalMessage::Type::kNewSession || + type == CastInternalMessage::Type::kUpdateSession); + base::Value message(base::Value::Type::DICTIONARY); + message.SetKey("type", base::Value(CastInternalMessageTypeToString(type))); + base::Value session_with_receiver_label = session.value().Clone(); + DCHECK(!session_with_receiver_label.FindPath({"receiver", "label"})); + session_with_receiver_label.SetPath( + {"receiver", "label"}, base::Value(GetReceiverLabel(sink, hash_token))); + message.SetKey("message", std::move(session_with_receiver_label)); + message.SetKey("sequenceNumber", base::Value(-1)); + message.SetKey("timeoutMillis", base::Value(0)); + message.SetKey("clientId", base::Value(client_id)); + return CreatePresentationMessage(message); +} + } // namespace // static @@ -245,13 +291,6 @@ CastInternalMessage::~CastInternalMessage() = default; -blink::mojom::PresentationConnectionMessagePtr CreatePresentationMessage( - const base::Value& message) { - std::string str; - CHECK(base::JSONWriter::Write(message, &str)); - return blink::mojom::PresentationConnectionMessage::NewMessage(str); -} - blink::mojom::PresentationConnectionMessagePtr CreateReceiverActionCastMessage( const std::string& client_id, const MediaSinkInternal& sink, @@ -271,7 +310,6 @@ // static std::unique_ptr<CastSession> CastSession::From( const MediaSinkInternal& sink, - const std::string& hash_token, const base::Value& receiver_status) { // There should be only 1 app on |receiver_status|. const base::Value* app_list_value = @@ -286,27 +324,34 @@ // Fill in mandatory Session fields. const base::Value& app_value = app_list_value->GetList()[0]; - if (!GetString(app_value, "sessionId", &session->session_id) || - !GetString(app_value, "appId", &session->app_id) || - !GetString(app_value, "transportId", &session->transport_id) || - !GetString(app_value, "displayName", &session->display_name)) { + if (!GetString(app_value, "sessionId", &session->session_id_) || + !GetString(app_value, "appId", &session->app_id_) || + !GetString(app_value, "transportId", &session->transport_id_) || + !GetString(app_value, "displayName", &session->display_name_)) { DVLOG(2) << "app_value missing mandatory fields: " << app_value; return nullptr; } - // Optional Session fields. - GetString(app_value, "statusText", &session->status); + if (session->app_id_ == kBackdropAppId) { + DVLOG(2) << sink.sink().id() << " is running the backdrop app"; + return nullptr; + } - base::Value receiver_value = CreateReceiver(sink, hash_token); + // Optional Session fields. + GetString(app_value, "statusText", &session->status_); + + // The receiver label will be populated by each profile using + // |session->value|. + base::Value receiver_value = CreateReceiver(sink, std::string()); CopyValue(receiver_status, "volume", &receiver_value); CopyValue(receiver_status, "isActiveInput", &receiver_value); // Create |session->value|. - session->value = base::Value(base::Value::Type::DICTIONARY); - auto& session_value = session->value; - session_value.SetKey("sessionId", base::Value(session->session_id)); - session_value.SetKey("appId", base::Value(session->app_id)); - session_value.SetKey("transportId", base::Value(session->transport_id)); + session->value_ = base::Value(base::Value::Type::DICTIONARY); + auto& session_value = session->value_; + session_value.SetKey("sessionId", base::Value(session->session_id())); + session_value.SetKey("appId", base::Value(session->app_id())); + session_value.SetKey("transportId", base::Value(session->transport_id())); session_value.SetKey("receiver", std::move(receiver_value)); CopyValueWithDefault(app_value, "displayName", base::Value(""), @@ -316,14 +361,12 @@ CopyValueWithDefault(app_value, "statusText", base::Value(), &session_value); CopyValueWithDefault(app_value, "appImages", base::ListValue(), &session_value); - CopyValueWithDefault(app_value, "namespaces", base::ListValue(), - &session_value); const base::Value* namespaces_value = app_value.FindKeyOfType("namespaces", base::Value::Type::LIST); if (!namespaces_value || namespaces_value->GetList().empty()) { // A session without namespaces is invalid, except for a multizone leader. - if (session->app_id != kMultizoneLeaderAppId) + if (session->app_id() != kMultizoneLeaderAppId) return nullptr; } else { for (const auto& namespace_value : namespaces_value->GetList()) { @@ -332,36 +375,53 @@ !GetString(namespace_value, "name", &message_namespace)) return nullptr; - session->message_namespaces.insert(std::move(message_namespace)); + session->message_namespaces_.insert(std::move(message_namespace)); } } - session_value.SetKey("namespaces", namespaces_value ? namespaces_value->Clone() : base::Value(base::Value::Type::LIST)); - return session; } CastSession::CastSession() = default; CastSession::~CastSession() = default; -// static -std::string CastSession::GetRouteDescription(const CastSession& session) { - return !session.status.empty() ? session.status : session.display_name; +std::string CastSession::GetRouteDescription() const { + return !status_.empty() ? status_ : display_name_; +} + +void CastSession::UpdateSession(std::unique_ptr<CastSession> from) { + status_ = std::move(from->status_); + message_namespaces_ = std::move(from->message_namespaces_); + + auto* status_text_value = from->value_.FindKey("statusText"); + DCHECK(status_text_value); + value_.SetKey("statusText", std::move(*status_text_value)); + auto* namespaces_value = from->value_.FindKey("namespaces"); + DCHECK(namespaces_value); + value_.SetKey("namespaces", std::move(*namespaces_value)); + auto* receiver_volume_value = from->value_.FindPath({"receiver", "volume"}); + DCHECK(receiver_volume_value); + value_.SetPath({"receiver", "volume"}, std::move(*receiver_volume_value)); } blink::mojom::PresentationConnectionMessagePtr CreateNewSessionMessage( const CastSession& session, - const std::string& client_id) { - base::Value message(base::Value::Type::DICTIONARY); - message.SetKey("type", base::Value(CastInternalMessageTypeToString( - CastInternalMessage::Type::kNewSession))); - message.SetKey("message", session.value.Clone()); - message.SetKey("sequenceNumber", base::Value(-1)); - message.SetKey("timeoutMillis", base::Value(0)); - message.SetKey("clientId", base::Value(client_id)); - return CreatePresentationMessage(message); + const std::string& client_id, + const MediaSinkInternal& sink, + const std::string& hash_token) { + return CreateSessionMessage(session, client_id, sink, hash_token, + CastInternalMessage::Type::kNewSession); +} + +blink::mojom::PresentationConnectionMessagePtr CreateUpdateSessionMessage( + const CastSession& session, + const std::string& client_id, + const MediaSinkInternal& sink, + const std::string& hash_token) { + return CreateSessionMessage(session, client_id, sink, hash_token, + CastInternalMessage::Type::kUpdateSession); } blink::mojom::PresentationConnectionMessagePtr CreateAppMessageAck(
diff --git a/chrome/browser/media/router/providers/cast/cast_internal_message_util.h b/chrome/browser/media/router/providers/cast/cast_internal_message_util.h index 849d2348..d9bbd01 100644 --- a/chrome/browser/media/router/providers/cast/cast_internal_message_util.h +++ b/chrome/browser/media/router/providers/cast/cast_internal_message_util.h
@@ -29,6 +29,8 @@ kReceiverAction, // Message sent by MRP to inform SDK client of action. kNewSession, // Message sent by MRP to inform SDK client of new // session. + kUpdateSession, // Message sent by MRP to inform SDK client of updated + // session. kOther // All other types of messages which are not considered // part of communication with Cast SDK. }; @@ -58,43 +60,53 @@ public: // Returns a CastSession from |receiver_status| message sent by |sink|, or // nullptr if |receiver_status| is not a valid RECEIVER_STATUS message. - // |hash_token| is a per-profile value that is used to hash the sink ID. static std::unique_ptr<CastSession> From(const MediaSinkInternal& sink, - const std::string& hash_token, const base::Value& receiver_status); - // Returns a string that can be used as the description of the MediaRoute - // associated with this session. - static std::string GetRouteDescription(const CastSession& session); - CastSession(); ~CastSession(); + // Returns a string that can be used as the description of the MediaRoute + // associated with this session. + std::string GetRouteDescription() const; + + // Partially updates the contents of this object using data in |from|. + void UpdateSession(std::unique_ptr<CastSession> from); + // ID of the session. - std::string session_id; + const std::string& session_id() const { return session_id_; } // ID of the app in the session. - std::string app_id; + const std::string& app_id() const { return app_id_; } // ID used for communicating with the session over the Cast channel. - std::string transport_id; + const std::string& transport_id() const { return transport_id_; } // The set of accepted message namespaces. Must be non-empty, unless the // session represents a multizone leader. - base::flat_set<std::string> message_namespaces; - - // The human-readable name of the Cast application, for example, "YouTube". - // Mandatory. - std::string display_name; - - // Descriptive text for the current application content, for example “My - // Wedding Slideshow”. May be empty. - std::string status; + const base::flat_set<std::string>& message_namespaces() const { + return message_namespaces_; + } // The dictionary representing this session, derived from |receiver_status|. // For convenience, this is used for generating messages sent to the SDK that // include the session value. - base::Value value; + const base::Value& value() const { return value_; } + + private: + std::string session_id_; + std::string app_id_; + std::string transport_id_; + base::flat_set<std::string> message_namespaces_; + base::Value value_; + + // The human-readable name of the Cast application, for example, "YouTube". + // Mandatory. + std::string display_name_; + + // Descriptive text for the current application content, for example “My + // Wedding Slideshow”. May be empty. + std::string status_; }; // Utility methods for generating messages sent to the SDK. @@ -109,7 +121,14 @@ const std::string& hash_token); blink::mojom::PresentationConnectionMessagePtr CreateNewSessionMessage( const CastSession& session, - const std::string& client_id); + const std::string& client_id, + const MediaSinkInternal& sink, + const std::string& hash_token); +blink::mojom::PresentationConnectionMessagePtr CreateUpdateSessionMessage( + const CastSession& session, + const std::string& client_id, + const MediaSinkInternal& sink, + const std::string& hash_token); blink::mojom::PresentationConnectionMessagePtr CreateAppMessageAck( const std::string& client_id, int sequence_number);
diff --git a/chrome/browser/media/router/providers/cast/cast_internal_message_util_unittest.cc b/chrome/browser/media/router/providers/cast/cast_internal_message_util_unittest.cc index ceed43cf..6dc9479 100644 --- a/chrome/browser/media/router/providers/cast/cast_internal_message_util_unittest.cc +++ b/chrome/browser/media/router/providers/cast/cast_internal_message_util_unittest.cc
@@ -38,7 +38,7 @@ const std::string& reason) { auto receiver_status = base::JSONReader::Read(receiver_status_str); ASSERT_TRUE(receiver_status); - auto session = CastSession::From(sink, kReceiverIdToken, *receiver_status); + auto session = CastSession::From(sink, *receiver_status); EXPECT_FALSE(session) << "Shouldn't have created session because of " << reason; } @@ -182,16 +182,16 @@ })"; auto receiver_status = base::JSONReader::Read(receiver_status_str); ASSERT_TRUE(receiver_status); - auto session = CastSession::From(sink, kReceiverIdToken, *receiver_status); + auto session = CastSession::From(sink, *receiver_status); ASSERT_TRUE(session); - EXPECT_EQ("sessionId", session->session_id); - EXPECT_EQ("ABCDEFGH", session->app_id); - EXPECT_EQ("transportId", session->transport_id); + EXPECT_EQ("sessionId", session->session_id()); + EXPECT_EQ("ABCDEFGH", session->app_id()); + EXPECT_EQ("transportId", session->transport_id()); base::flat_set<std::string> message_namespaces = { "urn:x-cast:com.google.cast.media", "urn:x-cast:com.google.foo"}; - EXPECT_EQ(message_namespaces, session->message_namespaces); - EXPECT_TRUE(session->value.is_dict()); - EXPECT_EQ("App display name", CastSession::GetRouteDescription(*session)); + EXPECT_EQ(message_namespaces, session->message_namespaces()); + EXPECT_TRUE(session->value().is_dict()); + EXPECT_EQ("App display name", session->GetRouteDescription()); } TEST(CastInternalMessageUtilTest, CastSessionFromInvalidReceiverStatuses) { @@ -324,7 +324,7 @@ std::string client_id = "clientId"; auto receiver_status = ReceiverStatus(); ASSERT_TRUE(receiver_status); - auto session = CastSession::From(sink, kReceiverIdToken, *receiver_status); + auto session = CastSession::From(sink, *receiver_status); ASSERT_TRUE(session); std::string expected_message = R"({ @@ -357,7 +357,51 @@ "type": "new_session" })"; - auto message = CreateNewSessionMessage(*session, client_id); + auto message = + CreateNewSessionMessage(*session, client_id, sink, kReceiverIdToken); + ExpectJSONMessagesEqual(expected_message, message->get_message()); +} + +TEST(CastInternalMessageUtilTest, CreateUpdateSessionMessage) { + MediaSinkInternal sink = CreateCastSink(1); + std::string client_id = "clientId"; + auto receiver_status = ReceiverStatus(); + ASSERT_TRUE(receiver_status); + auto session = CastSession::From(sink, *receiver_status); + ASSERT_TRUE(session); + + std::string expected_message = R"({ + "clientId": "clientId", + "message": { + "appId": "ABCDEFGH", + "appImages": [ ], + "displayName": "App display name", + "namespaces": [ { + "name": "urn:x-cast:com.google.cast.media" + }, { + "name": "urn:x-cast:com.google.foo" + } ], + "receiver": { + "capabilities": [ "video_out", "audio_out" ], + "displayStatus": null, + "friendlyName": "friendly name 1", + "isActiveInput": null, + "label": "yYH_HCL9CKJFmvKJ9m3Une2cS8s", + "receiverType": "cast", + "volume": null + }, + "senderApps": [ ], + "sessionId": "sessionId", + "statusText": "App status", + "transportId": "transportId" + }, + "sequenceNumber": -1, + "timeoutMillis": 0, + "type": "update_session" + })"; + + auto message = + CreateUpdateSessionMessage(*session, client_id, sink, kReceiverIdToken); ExpectJSONMessagesEqual(expected_message, message->get_message()); }
diff --git a/chrome/browser/media/router/providers/cast/cast_media_route_provider.cc b/chrome/browser/media/router/providers/cast/cast_media_route_provider.cc index fc34f0b..87b6feb 100644 --- a/chrome/browser/media/router/providers/cast/cast_media_route_provider.cc +++ b/chrome/browser/media/router/providers/cast/cast_media_route_provider.cc
@@ -56,11 +56,13 @@ FROM_HERE, base::BindOnce(&CastMediaRouteProvider::Init, base::Unretained(this), std::move(request), std::move(media_router), + CastSessionTracker::GetInstance(), std::make_unique<DataDecoder>(connector), hash_token)); } void CastMediaRouteProvider::Init(mojom::MediaRouteProviderRequest request, mojom::MediaRouterPtrInfo media_router, + CastSessionTracker* session_tracker, std::unique_ptr<DataDecoder> data_decoder, const std::string& hash_token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -69,8 +71,8 @@ media_router_.Bind(std::move(media_router)); activity_manager_ = std::make_unique<CastActivityManager>( - media_sink_service_, message_handler_, media_router_.get(), - std::move(data_decoder), hash_token); + media_sink_service_, session_tracker, message_handler_, + media_router_.get(), std::move(data_decoder), hash_token); // TODO(crbug.com/816702): This needs to be set properly according to sinks // discovered. @@ -104,7 +106,7 @@ } std::unique_ptr<CastMediaSource> cast_source = - CastMediaSource::From(media_source); + CastMediaSource::FromMediaSourceId(media_source); if (!cast_source) { std::move(callback).Run( base::nullopt, nullptr, std::string("Invalid source"), @@ -169,7 +171,7 @@ return; std::unique_ptr<CastMediaSource> cast_source = - CastMediaSource::From(media_source); + CastMediaSource::FromMediaSourceId(media_source); if (!cast_source) return;
diff --git a/chrome/browser/media/router/providers/cast/cast_media_route_provider.h b/chrome/browser/media/router/providers/cast/cast_media_route_provider.h index d36d8f8..502c5b5 100644 --- a/chrome/browser/media/router/providers/cast/cast_media_route_provider.h +++ b/chrome/browser/media/router/providers/cast/cast_media_route_provider.h
@@ -23,6 +23,7 @@ namespace media_router { class CastActivityManager; +class CastSessionTracker; // MediaRouteProvider for Cast sinks. This class may be created on any sequence. // All other methods, however, must be called on the task runner provided @@ -95,6 +96,7 @@ private: void Init(mojom::MediaRouteProviderRequest request, mojom::MediaRouterPtrInfo media_router, + CastSessionTracker* session_tracker, std::unique_ptr<DataDecoder> data_decoder, const std::string& hash_token); @@ -112,7 +114,7 @@ // Mojo pointer to the Media Router. mojom::MediaRouterPtr media_router_; - // Non-owned pointer to the Cast MediaSinkServiceBase. + // Non-owned pointer to the Cast MediaSinkServiceBase instance. MediaSinkServiceBase* const media_sink_service_; // Non-owned pointer to the CastAppDiscoveryService instance.
diff --git a/chrome/browser/media/router/providers/cast/cast_media_route_provider_unittest.cc b/chrome/browser/media/router/providers/cast/cast_media_route_provider_unittest.cc index 329547a..3cd222ad 100644 --- a/chrome/browser/media/router/providers/cast/cast_media_route_provider_unittest.cc +++ b/chrome/browser/media/router/providers/cast/cast_media_route_provider_unittest.cc
@@ -7,10 +7,12 @@ #include "base/run_loop.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/sequenced_task_runner_handle.h" +#include "chrome/browser/media/router/providers/cast/cast_session_tracker.h" #include "chrome/browser/media/router/test/mock_mojo_media_router.h" #include "chrome/browser/media/router/test/test_helper.h" #include "chrome/common/media_router/test/test_helper.h" #include "components/cast_channel/cast_test_util.h" +#include "content/public/browser/browser_task_traits.h" #include "content/public/test/test_browser_thread_bundle.h" #include "services/data_decoder/data_decoder_service.h" #include "services/data_decoder/public/mojom/constants.mojom.h" @@ -37,7 +39,8 @@ CastMediaRouteProviderTest() : data_decoder_service_(connector_factory_.RegisterInstance( data_decoder::mojom::kServiceName)), - socket_service_(new base::TestSimpleTaskRunner()), + socket_service_(base::CreateSingleThreadTaskRunnerWithTraits( + {content::BrowserThread::UI})), message_handler_(&socket_service_) {} ~CastMediaRouteProviderTest() override = default; @@ -46,6 +49,10 @@ router_binding_ = std::make_unique<mojo::Binding<mojom::MediaRouter>>( &mock_router_, mojo::MakeRequest(&router_ptr)); + CastSessionTracker::SetInstanceForTest( + new CastSessionTracker(&media_sink_service_, &message_handler_, + socket_service_.task_runner())); + EXPECT_CALL(mock_router_, OnSinkAvailabilityUpdated(_, _)); provider_ = std::make_unique<CastMediaRouteProvider>( mojo::MakeRequest(&provider_ptr_), router_ptr.PassInterface(), @@ -56,18 +63,9 @@ base::RunLoop().RunUntilIdle(); } - void TearDown() override { provider_.reset(); } - - void ExpectCreateRouteFailure( - RouteRequestResult::ResultCode expected_result, - const base::Optional<MediaRoute>& route, - mojom::RoutePresentationConnectionPtr presentation_connections, - const base::Optional<std::string>& error, - RouteRequestResult::ResultCode result) { - EXPECT_FALSE(route); - EXPECT_FALSE(presentation_connections); - EXPECT_TRUE(error); - EXPECT_EQ(expected_result, result); + void TearDown() override { + provider_.reset(); + CastSessionTracker::SetInstanceForTest(nullptr); } void ExpectCreateRouteSuccessAndSetRoute( @@ -82,6 +80,18 @@ route_ = std::make_unique<MediaRoute>(*route); } + void ExpectCreateRouteFailure( + RouteRequestResult::ResultCode expected_result, + const base::Optional<MediaRoute>& route, + mojom::RoutePresentationConnectionPtr presentation_connections, + const base::Optional<std::string>& error, + RouteRequestResult::ResultCode result) { + EXPECT_FALSE(route); + EXPECT_FALSE(presentation_connections); + EXPECT_TRUE(error); + EXPECT_EQ(expected_result, result); + } + void ExpectTerminateRouteSuccess(const base::Optional<std::string>& error, RouteRequestResult::ResultCode result) { EXPECT_FALSE(error);
diff --git a/chrome/browser/media/router/providers/cast/cast_session_tracker.cc b/chrome/browser/media/router/providers/cast/cast_session_tracker.cc new file mode 100644 index 0000000..a24cc31 --- /dev/null +++ b/chrome/browser/media/router/providers/cast/cast_session_tracker.cc
@@ -0,0 +1,162 @@ +// 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/media/router/providers/cast/cast_session_tracker.h" + +#include "base/stl_util.h" +#include "chrome/browser/media/router/providers/cast/chrome_cast_message_handler.h" +#include "chrome/browser/media/router/providers/cast/dual_media_sink_service.h" +#include "components/cast_channel/cast_socket_service.h" + +namespace media_router { + +CastSessionTracker::Observer::~Observer() = default; + +// static +CastSessionTracker* CastSessionTracker::GetInstance() { + if (instance_for_test_) + return instance_for_test_; + + static CastSessionTracker* instance = new CastSessionTracker( + DualMediaSinkService::GetInstance()->GetCastMediaSinkServiceImpl(), + GetCastMessageHandler(), + cast_channel::CastSocketService::GetInstance()->task_runner()); + return instance; +} + +void CastSessionTracker::AddObserver(CastSessionTracker::Observer* observer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + observers_.AddObserver(observer); +} + +void CastSessionTracker::RemoveObserver( + CastSessionTracker::Observer* observer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + observers_.RemoveObserver(observer); +} + +const CastSessionTracker::SessionMap& CastSessionTracker::sessions_by_sink_id() + const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return sessions_by_sink_id_; +} + +CastSession* CastSessionTracker::GetSessionById( + const std::string& session_id) const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + auto it = + std::find_if(sessions_by_sink_id_.begin(), sessions_by_sink_id_.end(), + [&session_id](const auto& entry) { + return entry.second->session_id() == session_id; + }); + return it != sessions_by_sink_id_.end() ? it->second.get() : nullptr; +} + +CastSessionTracker::CastSessionTracker( + MediaSinkServiceBase* media_sink_service, + cast_channel::CastMessageHandler* message_handler, + const scoped_refptr<base::SequencedTaskRunner>& task_runner) + : media_sink_service_(media_sink_service), + message_handler_(message_handler) { + DETACH_FROM_SEQUENCE(sequence_checker_); + // This is safe because |this| will never be destroyed (except in unit tests). + task_runner->PostTask(FROM_HERE, + base::BindOnce(&CastSessionTracker::InitOnIoThread, + base::Unretained(this))); +} + +CastSessionTracker::~CastSessionTracker() = default; + +// This method needs to be separate from the constructor because the constructor +// needs to be called from the UI thread, but observers can only be added in an +// IO thread. +void CastSessionTracker::InitOnIoThread() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + media_sink_service_->AddObserver(this); + message_handler_->AddObserver(this); +} + +void CastSessionTracker::HandleReceiverStatusMessage( + const MediaSinkInternal& sink, + const base::Value& message) { + const base::Value* status = + message.FindKeyOfType("status", base::Value::Type::DICTIONARY); + auto session = status ? CastSession::From(sink, *status) : nullptr; + const MediaSink::Id& sink_id = sink.sink().id(); + if (!session) { + if (sessions_by_sink_id_.erase(sink_id)) { + for (auto& observer : observers_) + observer.OnSessionRemoved(sink); + } + return; + } + + auto it = sessions_by_sink_id_.find(sink_id); + if (it == sessions_by_sink_id_.end()) { + it = sessions_by_sink_id_.emplace(sink_id, std::move(session)).first; + } else { + it->second->UpdateSession(std::move(session)); + } + + for (auto& observer : observers_) + observer.OnSessionAddedOrUpdated(sink, *it->second); +} + +const MediaSinkInternal* CastSessionTracker::GetSinkByChannelId( + int channel_id) const { + for (const auto& sink : media_sink_service_->GetSinks()) { + if (sink.second.cast_data().cast_channel_id == channel_id) + return &sink.second; + } + return nullptr; +} + +void CastSessionTracker::OnSinkAddedOrUpdated(const MediaSinkInternal& sink) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + message_handler_->RequestReceiverStatus(sink.cast_data().cast_channel_id); +} + +void CastSessionTracker::OnSinkRemoved(const MediaSinkInternal& sink) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (sessions_by_sink_id_.erase(sink.sink().id())) { + for (auto& observer : observers_) + observer.OnSessionRemoved(sink); + } +} + +void CastSessionTracker::OnInternalMessage( + int channel_id, + const cast_channel::InternalMessage& message) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // It's possible for a session to have been started/discovered on a different + // channel_id than the one we got the latest RECEIVER_STATUS on, but this + // should be okay, since we are mapping everything back to the sink_id, which + // should be constant. + const MediaSinkInternal* sink = GetSinkByChannelId(channel_id); + if (!sink) { + DVLOG(2) << "Received message from channel without sink: " << channel_id; + return; + } + + if (message.type == cast_channel::CastMessageType::kReceiverStatus) + HandleReceiverStatusMessage(*sink, message.message); +} + +// static +void CastSessionTracker::SetInstanceForTest( + CastSessionTracker* session_tracker) { + instance_for_test_ = session_tracker; +} + +void CastSessionTracker::SetSessionForTest( + const MediaSink::Id& sink_id, + std::unique_ptr<CastSession> session) { + DCHECK(session); + sessions_by_sink_id_[sink_id] = std::move(session); +} + +// static +CastSessionTracker* CastSessionTracker::instance_for_test_ = nullptr; + +} // namespace media_router
diff --git a/chrome/browser/media/router/providers/cast/cast_session_tracker.h b/chrome/browser/media/router/providers/cast/cast_session_tracker.h new file mode 100644 index 0000000..477a6e4 --- /dev/null +++ b/chrome/browser/media/router/providers/cast/cast_session_tracker.h
@@ -0,0 +1,101 @@ +// 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_MEDIA_ROUTER_PROVIDERS_CAST_CAST_SESSION_TRACKER_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_SESSION_TRACKER_H_ + +#include "base/macros.h" +#include "base/observer_list.h" +#include "base/sequence_checker.h" +#include "base/values.h" +#include "chrome/browser/media/router/providers/cast/cast_internal_message_util.h" +#include "chrome/common/media_router/discovery/media_sink_internal.h" +#include "chrome/common/media_router/discovery/media_sink_service_base.h" +#include "components/cast_channel/cast_message_handler.h" +#include "components/cast_channel/cast_message_util.h" + +namespace media_router { + +// Tracks active sessions on Cast MediaSinks. Listens for RECEIVER_STATUS +// messages from Cast channels and notifies observers of changes to sessions. +// GetInstance() must be called on the UI thread while all other methods must be +// called on the IO thread. +class CastSessionTracker : public MediaSinkServiceBase::Observer, + public cast_channel::CastMessageHandler::Observer { + public: + typedef base::flat_map<MediaSink::Id, std::unique_ptr<CastSession>> + SessionMap; + + class Observer : public base::CheckedObserver { + public: + ~Observer() override; + virtual void OnSessionAddedOrUpdated(const MediaSinkInternal& sink, + const CastSession& session) = 0; + virtual void OnSessionRemoved(const MediaSinkInternal& sink) = 0; + }; + + // Must be called on UI thread. + // TODO(https://crbug.com/904016): The UI/IO thread split makes this class + // confusing to use. If we can directly access CastMediaSinkServiceImpl + // without going through DualMediaSinkService, then it will no longer be + // necessary for this method to be run on UI thread. + static CastSessionTracker* GetInstance(); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + const SessionMap& sessions_by_sink_id() const; + + // Returns nullptr if there is no session with the specified ID. + CastSession* GetSessionById(const std::string& session_id) const; + + private: + friend class CastSessionTrackerTest; + friend class CastActivityManagerTest; + friend class CastMediaRouteProviderTest; + + // Use |GetInstance()| instead. + CastSessionTracker( + MediaSinkServiceBase* media_sink_service, + cast_channel::CastMessageHandler* message_handler, + const scoped_refptr<base::SequencedTaskRunner>& task_runner); + + ~CastSessionTracker() override; + + void InitOnIoThread(); + void HandleReceiverStatusMessage(const MediaSinkInternal& sink, + const base::Value& message); + const MediaSinkInternal* GetSinkByChannelId(int channel_id) const; + + // MediaSinkServiceBase::Observer implementation + void OnSinkAddedOrUpdated(const MediaSinkInternal& sink) override; + void OnSinkRemoved(const MediaSinkInternal& sink) override; + + // cast_channel::CastMessageHandler::Observer implementation + void OnInternalMessage(int channel_id, + const cast_channel::InternalMessage& message) override; + + static void SetInstanceForTest(CastSessionTracker* session_tracker); + void SetSessionForTest(const MediaSink::Id& sink_id, + std::unique_ptr<CastSession> session); + + // Tests may override the value returned via |GetInstance()| by calling + // |SetInstanceForTest()|. + static CastSessionTracker* instance_for_test_; + + MediaSinkServiceBase* const media_sink_service_; + cast_channel::CastMessageHandler* const message_handler_; + + SessionMap sessions_by_sink_id_; + + base::ObserverList<Observer> observers_; + + SEQUENCE_CHECKER(sequence_checker_); + DISALLOW_COPY_AND_ASSIGN(CastSessionTracker); + FRIEND_TEST_ALL_PREFIXES(CastSessionTrackerTest, RemoveSession); +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_SESSION_TRACKER_H_
diff --git a/chrome/browser/media/router/providers/cast/cast_session_tracker_unittest.cc b/chrome/browser/media/router/providers/cast/cast_session_tracker_unittest.cc new file mode 100644 index 0000000..a4296e30 --- /dev/null +++ b/chrome/browser/media/router/providers/cast/cast_session_tracker_unittest.cc
@@ -0,0 +1,161 @@ +// 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/media/router/providers/cast/cast_session_tracker.h" + +#include "base/json/json_reader.h" +#include "chrome/browser/media/router/test/test_helper.h" +#include "chrome/common/media_router/test/test_helper.h" +#include "components/cast_channel/cast_test_util.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; + +namespace media_router { + +namespace { + +constexpr char kSessionId[] = "sessionId"; + +constexpr char kReceiverStatus[] = R"({ + "status": { + "applications": [{ + "appId": "ABCDEFGH", + "displayName": "App display name", + "namespaces": [ + {"name": "urn:x-cast:com.google.cast.media"}, + {"name": "urn:x-cast:com.google.foo"} + ], + "sessionId": "sessionId", + "statusText":"App status", + "transportId":"transportId" + }] + } +})"; + +// Receiver status for the backdrop (idle) app. +constexpr char kIdleReceiverStatus[] = R"({ + "status": { + "applications": [{ + "appId": "E8C28D3C", + "displayName": "Backdrop", + "namespaces": [ + {"name": "urn:x-cast:com.google.cast.media"}, + {"name": "urn:x-cast:com.google.foo"} + ], + "sessionId": "sessionId", + "statusText":"App status", + "transportId":"transportId" + }] + } +})"; + +} // namespace + +class MockCastSessionObserver : public CastSessionTracker::Observer { + public: + MockCastSessionObserver() = default; + ~MockCastSessionObserver() override = default; + + MOCK_METHOD2(OnSessionAddedOrUpdated, + void(const MediaSinkInternal& sink, const CastSession& session)); + MOCK_METHOD1(OnSessionRemoved, void(const MediaSinkInternal& sink)); +}; + +class CastSessionTrackerTest : public testing::Test { + public: + CastSessionTrackerTest() + : socket_service_(base::CreateSingleThreadTaskRunnerWithTraits( + {content::BrowserThread::UI})), + message_handler_(&socket_service_), + session_tracker_(&media_sink_service_, + &message_handler_, + socket_service_.task_runner()) { + base::RunLoop().RunUntilIdle(); + } + + void SetUp() override { session_tracker_.AddObserver(&observer_); } + + void TearDown() override { session_tracker_.RemoveObserver(&observer_); } + + void AddSinkAndSendReceiverStatusResponse() { + EXPECT_CALL(message_handler_, + RequestReceiverStatus(sink_.cast_data().cast_channel_id)); + media_sink_service_.AddOrUpdateSink(sink_); + + auto receiver_status = base::JSONReader::Read(kReceiverStatus); + ASSERT_TRUE(receiver_status); + cast_channel::InternalMessage receiver_status_message( + cast_channel::CastMessageType::kReceiverStatus, + std::move(*receiver_status)); + + EXPECT_CALL(observer_, OnSessionAddedOrUpdated(sink_, _)); + session_tracker_.OnInternalMessage(sink_.cast_data().cast_channel_id, + receiver_status_message); + } + + protected: + content::TestBrowserThreadBundle thread_bundle_; + + cast_channel::MockCastSocketService socket_service_; + cast_channel::MockCastMessageHandler message_handler_; + + TestMediaSinkService media_sink_service_; + CastSessionTracker session_tracker_; + + MockCastSessionObserver observer_; + + MediaSinkInternal sink_ = CreateCastSink(1); +}; + +TEST_F(CastSessionTrackerTest, QueryReceiverOnSinkAdded) { + AddSinkAndSendReceiverStatusResponse(); + + // Receiver status is sent again when sinks is updated. + sink_.cast_data().cast_channel_id = 2; + EXPECT_CALL(message_handler_, + RequestReceiverStatus(sink_.cast_data().cast_channel_id)); + media_sink_service_.AddOrUpdateSink(sink_); +} + +TEST_F(CastSessionTrackerTest, RemoveSessionOnSinkRemoved) { + AddSinkAndSendReceiverStatusResponse(); + + EXPECT_CALL(observer_, OnSessionRemoved(sink_)); + media_sink_service_.RemoveSink(sink_); +} + +TEST_F(CastSessionTrackerTest, RemoveSession) { + AddSinkAndSendReceiverStatusResponse(); + + auto receiver_status = base::JSONReader::Read(kIdleReceiverStatus); + ASSERT_TRUE(receiver_status); + cast_channel::InternalMessage receiver_status_message( + cast_channel::CastMessageType::kReceiverStatus, + std::move(*receiver_status)); + + EXPECT_CALL(observer_, OnSessionRemoved(sink_)); + session_tracker_.OnInternalMessage(sink_.cast_data().cast_channel_id, + receiver_status_message); +} + +TEST_F(CastSessionTrackerTest, sessions_by_sink_id) { + EXPECT_TRUE(session_tracker_.sessions_by_sink_id().empty()); + + AddSinkAndSendReceiverStatusResponse(); + + const auto& sessions = session_tracker_.sessions_by_sink_id(); + EXPECT_EQ(1u, sessions.size()); + auto it = sessions.find(sink_.sink().id()); + ASSERT_TRUE(it != sessions.end()); + EXPECT_EQ(kSessionId, it->second->session_id()); + + EXPECT_TRUE(session_tracker_.GetSessionById(kSessionId)); +} + +} // namespace media_router
diff --git a/chrome/browser/metrics/perf/metric_collector.cc b/chrome/browser/metrics/perf/metric_collector.cc index cb3929c..7cd69c5 100644 --- a/chrome/browser/metrics/perf/metric_collector.cc +++ b/chrome/browser/metrics/perf/metric_collector.cc
@@ -4,7 +4,9 @@ #include "chrome/browser/metrics/perf/metric_collector.h" +#include "base/metrics/histogram_functions.h" #include "base/rand_util.h" +#include "base/system/sys_info.h" #include "third_party/metrics_proto/sampled_profile.pb.h" namespace metrics { @@ -24,21 +26,62 @@ base::RandGenerator(max.InMicroseconds())); } +// PerfDataProto is defined elsewhere with more fields than the definition in +// Chromium's copy of perf_data.proto. During deserialization, the protobuf +// data could contain fields that are defined elsewhere but not in +// perf_data.proto, resulting in some data in |unknown_fields| for the message +// types within PerfDataProto. +// +// This function deletes those dangling unknown fields if they are in messages +// containing strings. See comments in perf_data.proto describing the fields +// that have been intentionally left out. Note that all unknown fields will be +// removed from those messages, not just unknown string fields. +void RemoveUnknownFieldsFromMessagesWithStrings(PerfDataProto* proto) { + // Clean up PerfEvent::MMapEvent and PerfEvent::CommEvent. + for (PerfDataProto::PerfEvent& event : *proto->mutable_events()) { + if (event.has_comm_event()) + event.mutable_comm_event()->mutable_unknown_fields()->clear(); + if (event.has_mmap_event()) + event.mutable_mmap_event()->mutable_unknown_fields()->clear(); + } + // Clean up PerfBuildID. + for (PerfDataProto::PerfBuildID& build_id : *proto->mutable_build_ids()) { + build_id.mutable_unknown_fields()->clear(); + } + // Clean up StringMetadata and StringMetadata::StringAndMd5sumPrefix. + if (proto->has_string_metadata()) { + proto->mutable_string_metadata()->mutable_unknown_fields()->clear(); + if (proto->string_metadata().has_perf_command_line_whole()) { + proto->mutable_string_metadata() + ->mutable_perf_command_line_whole() + ->mutable_unknown_fields() + ->clear(); + } + } +} + } // namespace -MetricCollector::MetricCollector() {} +MetricCollector::MetricCollector(const std::string& uma_histogram) + : uma_histogram_(uma_histogram) {} -MetricCollector::MetricCollector(const CollectionParams& collection_params) - : collection_params_(collection_params) {} +MetricCollector::MetricCollector(const std::string& uma_histogram, + const CollectionParams& collection_params) + : collection_params_(collection_params), uma_histogram_(uma_histogram) {} MetricCollector::~MetricCollector() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } +void MetricCollector::AddToUmaHistogram(CollectionAttemptStatus outcome) const { + base::UmaHistogramEnumeration(uma_histogram_, outcome, + CollectionAttemptStatus::NUM_OUTCOMES); +} + bool MetricCollector::GetSampledProfiles( std::vector<SampledProfile>* sampled_profiles) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!ShouldUpload() || cached_profile_data_.empty()) + if (!ShouldUpload()) return false; sampled_profiles->insert( @@ -50,6 +93,12 @@ } bool MetricCollector::ShouldUpload() const { + if (cached_profile_data_.empty()) { + AddToUmaHistogram(CollectionAttemptStatus::NOT_READY_TO_UPLOAD); + return false; + } + + AddToUmaHistogram(CollectionAttemptStatus::SUCCESS); return true; } @@ -204,4 +253,56 @@ timer_.Stop(); } +void MetricCollector::SaveSerializedPerfProto( + std::unique_ptr<SampledProfile> sampled_profile, + PerfProtoType type, + const std::string& serialized_proto) { + if (serialized_proto.empty()) { + AddToUmaHistogram(CollectionAttemptStatus::ILLEGAL_DATA_RETURNED); + return; + } + + switch (type) { + case PerfProtoType::PERF_TYPE_DATA: { + PerfDataProto perf_data_proto; + if (!perf_data_proto.ParseFromString(serialized_proto)) { + AddToUmaHistogram(CollectionAttemptStatus::PROTOBUF_NOT_PARSED); + return; + } + RemoveUnknownFieldsFromMessagesWithStrings(&perf_data_proto); + sampled_profile->mutable_perf_data()->Swap(&perf_data_proto); + break; + } + case PerfProtoType::PERF_TYPE_STAT: { + PerfStatProto perf_stat_proto; + if (!perf_stat_proto.ParseFromString(serialized_proto)) { + AddToUmaHistogram(CollectionAttemptStatus::PROTOBUF_NOT_PARSED); + return; + } + sampled_profile->mutable_perf_stat()->Swap(&perf_stat_proto); + break; + } + case PerfProtoType::PERF_TYPE_UNSUPPORTED: + AddToUmaHistogram(CollectionAttemptStatus::PROTOBUF_NOT_PARSED); + return; + } + + sampled_profile->set_ms_after_boot(base::SysInfo::Uptime().InMilliseconds()); + DCHECK(!login_time_.is_null()); + sampled_profile->set_ms_after_login( + (base::TimeTicks::Now() - login_time_).InMilliseconds()); + + // Add the collected data to the container of collected SampledProfiles. + cached_profile_data_.resize(cached_profile_data_.size() + 1); + cached_profile_data_.back().Swap(sampled_profile.get()); +} + +size_t MetricCollector::cached_profile_data_size() const { + size_t data_size = 0; + for (size_t i = 0; i < cached_profile_data_.size(); ++i) { + data_size += cached_profile_data_[i].ByteSize(); + } + return data_size; +} + } // namespace metrics
diff --git a/chrome/browser/metrics/perf/metric_collector.h b/chrome/browser/metrics/perf/metric_collector.h index f5950a2..55d5f133 100644 --- a/chrome/browser/metrics/perf/metric_collector.h +++ b/chrome/browser/metrics/perf/metric_collector.h
@@ -25,8 +25,9 @@ // pointer across threads safely. class MetricCollector : public base::SupportsWeakPtr<MetricCollector> { public: - MetricCollector(); - explicit MetricCollector(const CollectionParams& collection_params); + explicit MetricCollector(const std::string& uma_histogram); + explicit MetricCollector(const std::string& uma_histogram, + const CollectionParams& collection_params); virtual ~MetricCollector(); // Collector specific initialization. @@ -52,12 +53,38 @@ void OnSessionRestoreDone(int num_tabs_restored); protected: + // Perf proto type. + enum class PerfProtoType { + PERF_TYPE_DATA, + PERF_TYPE_STAT, + PERF_TYPE_UNSUPPORTED, + }; + + // Enumeration representing success and various failure modes for collecting + // and sending perf data. + enum class CollectionAttemptStatus { + SUCCESS, + NOT_READY_TO_UPLOAD, + NOT_READY_TO_COLLECT, + INCOGNITO_ACTIVE, + INCOGNITO_LAUNCHED, + PROTOBUF_NOT_PARSED, + ILLEGAL_DATA_RETURNED, + ALREADY_COLLECTING, + NUM_OUTCOMES + }; + + // Saves the given outcome to the uma histogram associated with the collector. + void AddToUmaHistogram(CollectionAttemptStatus outcome) const; + const CollectionParams& collection_params() const { return collection_params_; } const base::OneShotTimer& timer() const { return timer_; } + base::TimeTicks login_time() const { return login_time_; } + // Collects perf data after a resume. |sleep_duration| is the duration the // system was suspended before resuming. |time_after_resume_ms| is how long // ago the system resumed. @@ -94,27 +121,41 @@ // implementation can override this logic. virtual bool ShouldUpload() const; + // Parses the given serialized perf proto of the given type (data or stat). + // If valid, it adds it to the given sampled_profile and stores it in the + // local profile data cache. + void SaveSerializedPerfProto(std::unique_ptr<SampledProfile> sampled_profile, + PerfProtoType type, + const std::string& serialized_proto); + + // Returns the size of the cached profile data. + size_t cached_profile_data_size() const; + // Parameters controlling how profiles are collected. CollectionParams collection_params_; - // Vector of SampledProfile protobufs containing perf profiles. - std::vector<SampledProfile> cached_profile_data_; - - // Record of the last login time. - base::TimeTicks login_time_; - SEQUENCE_CHECKER(sequence_checker_); private: // For scheduling collection of profile data. base::OneShotTimer timer_; + // Vector of SampledProfile protobufs containing perf profiles. + std::vector<SampledProfile> cached_profile_data_; + + // Record of the last login time. + base::TimeTicks login_time_; + // Record of the start of the upcoming profiling interval. base::TimeTicks next_profiling_interval_start_; // Tracks the last time a session restore was collected. base::TimeTicks last_session_restore_collection_time_; + // Name of the histogram that represents the success and various failure modes + // for a collector. + std::string uma_histogram_; + DISALLOW_COPY_AND_ASSIGN(MetricCollector); };
diff --git a/chrome/browser/metrics/perf/metric_collector_unittest.cc b/chrome/browser/metrics/perf/metric_collector_unittest.cc index 020114a..6f902ac4 100644 --- a/chrome/browser/metrics/perf/metric_collector_unittest.cc +++ b/chrome/browser/metrics/perf/metric_collector_unittest.cc
@@ -16,14 +16,14 @@ #include "base/threading/thread_task_runner_handle.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/metrics_proto/sampled_profile.pb.h" +#include "third_party/protobuf/src/google/protobuf/io/coded_stream.h" +#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h" +#include "third_party/protobuf/src/google/protobuf/wire_format_lite_inl.h" namespace metrics { namespace { -const long kMsAfterBoot = 10000; -const long kMsAfterLogin = 2000; - // Returns an example PerfDataProto. The contents don't have to make sense. They // just need to constitute a semantically valid protobuf. // |proto| is an output parameter that will contain the created protobuf. @@ -53,27 +53,66 @@ return proto; } +// Returns an example PerfStatProto. The contents don't have to make sense. They +// just need to constitute a semantically valid protobuf. +// |result| is an output parameter that will contain the created protobuf. +PerfStatProto GetExamplePerfStatProto() { + PerfStatProto proto; + proto.set_command_line( + "perf stat -a -e cycles -e instructions -e branches -- sleep 2"); + + PerfStatProto_PerfStatLine* line1 = proto.add_line(); + line1->set_time_ms(1000); + line1->set_count(2000); + line1->set_event_name("cycles"); + + PerfStatProto_PerfStatLine* line2 = proto.add_line(); + line2->set_time_ms(2000); + line2->set_count(5678); + line2->set_event_name("instructions"); + + PerfStatProto_PerfStatLine* line3 = proto.add_line(); + line3->set_time_ms(3000); + line3->set_count(9999); + line3->set_event_name("branches"); + + return proto; +} + +// Creates a serialized data stream containing a string with a field tag number. +std::string SerializeStringFieldWithTag(int field, const std::string& value) { + std::string result; + google::protobuf::io::StringOutputStream string_stream(&result); + google::protobuf::io::CodedOutputStream output(&string_stream); + + using google::protobuf::internal::WireFormatLite; + WireFormatLite::WriteTag(field, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + &output); + output.WriteVarint32(value.size()); + output.WriteString(value); + + return result; +} + // Allows access to some private methods for testing. class TestMetricCollector : public MetricCollector { public: - TestMetricCollector() {} + TestMetricCollector() : MetricCollector("UMA.CWP.TestData") {} explicit TestMetricCollector(const CollectionParams& collection_params) - : MetricCollector(collection_params) {} + : MetricCollector("UMA.CWP.TestData", collection_params) {} void CollectProfile( std::unique_ptr<SampledProfile> sampled_profile) override { PerfDataProto perf_data_proto = GetExamplePerfDataProto(); - sampled_profile->set_ms_after_boot(kMsAfterBoot); - sampled_profile->set_ms_after_login(kMsAfterLogin); - sampled_profile->mutable_perf_data()->Swap(&perf_data_proto); - - // Add the collected data to the container of collected SampledProfiles. - cached_profile_data_.resize(cached_profile_data_.size() + 1); - cached_profile_data_.back().Swap(sampled_profile.get()); + SaveSerializedPerfProto(std::move(sampled_profile), + PerfProtoType::PERF_TYPE_DATA, + perf_data_proto.SerializeAsString()); } using MetricCollector::collection_params; - using MetricCollector::login_time_; + using MetricCollector::login_time; + using MetricCollector::PerfProtoType; + using MetricCollector::SaveSerializedPerfProto; using MetricCollector::ScheduleIntervalCollection; using MetricCollector::timer; @@ -90,7 +129,8 @@ MetricCollectorTest() : task_runner_(base::MakeRefCounted<base::TestSimpleTaskRunner>()), task_runner_handle_(task_runner_), - perf_data_proto_(GetExamplePerfDataProto()) {} + perf_data_proto_(GetExamplePerfDataProto()), + perf_stat_proto_(GetExamplePerfStatProto()) {} void SetUp() override { CollectionParams test_params; @@ -101,6 +141,9 @@ metric_collector_ = std::make_unique<TestMetricCollector>(test_params); metric_collector_->Init(); + + // MetricCollector requires the user to be logged in. + metric_collector_->OnUserLoggedIn(); } void TearDown() override { metric_collector_.reset(); } @@ -111,19 +154,22 @@ scoped_refptr<base::TestSimpleTaskRunner> task_runner_; base::ThreadTaskRunnerHandle task_runner_handle_; - // Store a sample perf data protobuf for testing. + // Store sample perf data/stat protobufs for testing. PerfDataProto perf_data_proto_; + PerfStatProto perf_stat_proto_; DISALLOW_COPY_AND_ASSIGN(MetricCollectorTest); }; TEST_F(MetricCollectorTest, CheckSetup) { EXPECT_GT(perf_data_proto_.ByteSize(), 0); + EXPECT_GT(perf_stat_proto_.ByteSize(), 0); - // Timer is not active before user logs in. - EXPECT_FALSE(metric_collector_->timer().IsRunning()); - EXPECT_TRUE(metric_collector_->login_time_.is_null()); + // Timer is active after user logs in. + EXPECT_TRUE(metric_collector_->timer().IsRunning()); + EXPECT_FALSE(metric_collector_->login_time().is_null()); + // There are no cached profiles at start. std::vector<SampledProfile> stored_profiles; EXPECT_FALSE(metric_collector_->GetSampledProfiles(&stored_profiles)); EXPECT_TRUE(stored_profiles.empty()); @@ -132,7 +178,256 @@ TEST_F(MetricCollectorTest, EnabledOnLogin) { metric_collector_->OnUserLoggedIn(); EXPECT_TRUE(metric_collector_->timer().IsRunning()); - EXPECT_FALSE(metric_collector_->login_time_.is_null()); + EXPECT_FALSE(metric_collector_->login_time().is_null()); +} + +TEST_F(MetricCollectorTest, EmptyProtosAreNotSaved) { + auto sampled_profile = std::make_unique<SampledProfile>(); + sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); + + metric_collector_->SaveSerializedPerfProto( + std::move(sampled_profile), + TestMetricCollector::PerfProtoType::PERF_TYPE_DATA, std::string()); + + std::vector<SampledProfile> stored_profiles; + EXPECT_FALSE(metric_collector_->GetSampledProfiles(&stored_profiles)); +} + +TEST_F(MetricCollectorTest, PerfDataProto) { + auto sampled_profile = std::make_unique<SampledProfile>(); + sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); + + metric_collector_->SaveSerializedPerfProto( + std::move(sampled_profile), + TestMetricCollector::PerfProtoType::PERF_TYPE_DATA, + perf_data_proto_.SerializeAsString()); + + std::vector<SampledProfile> stored_profiles; + EXPECT_TRUE(metric_collector_->GetSampledProfiles(&stored_profiles)); + ASSERT_EQ(1U, stored_profiles.size()); + + const SampledProfile& profile = stored_profiles[0]; + EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event()); + EXPECT_TRUE(profile.has_ms_after_boot()); + EXPECT_TRUE(profile.has_ms_after_login()); + + ASSERT_TRUE(profile.has_perf_data()); + EXPECT_FALSE(profile.has_perf_stat()); + EXPECT_EQ(perf_data_proto_.SerializeAsString(), + profile.perf_data().SerializeAsString()); +} + +TEST_F(MetricCollectorTest, PerfDataProto_UnknownFieldsDiscarded) { + // First add some unknown fields to MMapEvent, CommEvent, PerfBuildID, and + // StringAndMd5sumPrefix. The known field values don't have to make sense for + // perf data. They are just padding to avoid having an otherwise empty proto. + // The unknown field string contents don't have to make sense as serialized + // data as the test is to discard them. + + // MMapEvent + PerfDataProto_PerfEvent* event1 = perf_data_proto_.add_events(); + event1->mutable_header()->set_type(1); + event1->mutable_mmap_event()->set_pid(1234); + event1->mutable_mmap_event()->set_filename_md5_prefix(0xdeadbeef); + // Missing field |MMapEvent::filename| has tag=6. + *event1->mutable_mmap_event()->mutable_unknown_fields() = + SerializeStringFieldWithTag(6, "/opt/google/chrome/chrome"); + + // CommEvent + PerfDataProto_PerfEvent* event2 = perf_data_proto_.add_events(); + event2->mutable_header()->set_type(2); + event2->mutable_comm_event()->set_pid(5678); + event2->mutable_comm_event()->set_comm_md5_prefix(0x900df00d); + // Missing field |CommEvent::comm| has tag=3. + *event2->mutable_comm_event()->mutable_unknown_fields() = + SerializeStringFieldWithTag(3, "chrome"); + + // PerfBuildID + PerfDataProto_PerfBuildID* build_id = perf_data_proto_.add_build_ids(); + build_id->set_misc(3); + build_id->set_pid(1337); + build_id->set_filename_md5_prefix(0x9876543210); + // Missing field |PerfBuildID::filename| has tag=4. + *build_id->mutable_unknown_fields() = + SerializeStringFieldWithTag(4, "/opt/google/chrome/chrome"); + + // StringAndMd5sumPrefix + PerfDataProto_StringMetadata* metadata = + perf_data_proto_.mutable_string_metadata(); + metadata->mutable_perf_command_line_whole()->set_value_md5_prefix( + 0x123456789); + // Missing field |StringAndMd5sumPrefix::value| has tag=1. + *metadata->mutable_perf_command_line_whole()->mutable_unknown_fields() = + SerializeStringFieldWithTag(1, "perf record -a -- sleep 1"); + + // Serialize to string and make sure it can be deserialized. + std::string perf_data_string = perf_data_proto_.SerializeAsString(); + PerfDataProto temp_proto; + EXPECT_TRUE(temp_proto.ParseFromString(perf_data_string)); + + // Now pass it to |metric_collector_|. + auto sampled_profile = std::make_unique<SampledProfile>(); + sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); + + metric_collector_->SaveSerializedPerfProto( + std::move(sampled_profile), + TestMetricCollector::PerfProtoType::PERF_TYPE_DATA, perf_data_string); + + std::vector<SampledProfile> stored_profiles; + EXPECT_TRUE(metric_collector_->GetSampledProfiles(&stored_profiles)); + ASSERT_EQ(1U, stored_profiles.size()); + + const SampledProfile& profile = stored_profiles[0]; + EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event()); + EXPECT_TRUE(profile.has_perf_data()); + + // The serialized form should be different because the unknown fields have + // have been removed. + EXPECT_NE(perf_data_string, profile.perf_data().SerializeAsString()); + + // Check contents of stored protobuf. + const PerfDataProto& stored_proto = profile.perf_data(); + ASSERT_EQ(2, stored_proto.events_size()); + + // MMapEvent + const PerfDataProto_PerfEvent& stored_event1 = stored_proto.events(0); + EXPECT_EQ(1U, stored_event1.header().type()); + EXPECT_EQ(1234U, stored_event1.mmap_event().pid()); + EXPECT_EQ(0xdeadbeef, stored_event1.mmap_event().filename_md5_prefix()); + EXPECT_EQ(0U, stored_event1.mmap_event().unknown_fields().size()); + + // CommEvent + const PerfDataProto_PerfEvent& stored_event2 = stored_proto.events(1); + EXPECT_EQ(2U, stored_event2.header().type()); + EXPECT_EQ(5678U, stored_event2.comm_event().pid()); + EXPECT_EQ(0x900df00d, stored_event2.comm_event().comm_md5_prefix()); + EXPECT_EQ(0U, stored_event2.comm_event().unknown_fields().size()); + + // PerfBuildID + ASSERT_EQ(1, stored_proto.build_ids_size()); + const PerfDataProto_PerfBuildID& stored_build_id = stored_proto.build_ids(0); + EXPECT_EQ(3U, stored_build_id.misc()); + EXPECT_EQ(1337U, stored_build_id.pid()); + EXPECT_EQ(0x9876543210U, stored_build_id.filename_md5_prefix()); + EXPECT_EQ(0U, stored_build_id.unknown_fields().size()); + + // StringAndMd5sumPrefix + const PerfDataProto_StringMetadata& stored_metadata = + stored_proto.string_metadata(); + EXPECT_EQ(0x123456789U, + stored_metadata.perf_command_line_whole().value_md5_prefix()); + EXPECT_EQ(0U, + stored_metadata.perf_command_line_whole().unknown_fields().size()); +} + +TEST_F(MetricCollectorTest, PerfStatProto) { + auto sampled_profile = std::make_unique<SampledProfile>(); + sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); + + metric_collector_->SaveSerializedPerfProto( + std::move(sampled_profile), + TestMetricCollector::PerfProtoType::PERF_TYPE_STAT, + perf_stat_proto_.SerializeAsString()); + + std::vector<SampledProfile> stored_profiles; + EXPECT_TRUE(metric_collector_->GetSampledProfiles(&stored_profiles)); + ASSERT_EQ(1U, stored_profiles.size()); + + const SampledProfile& profile = stored_profiles[0]; + EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event()); + EXPECT_TRUE(profile.has_ms_after_boot()); + EXPECT_TRUE(profile.has_ms_after_login()); + + EXPECT_FALSE(profile.has_perf_data()); + ASSERT_TRUE(profile.has_perf_stat()); + EXPECT_EQ(perf_stat_proto_.SerializeAsString(), + profile.perf_stat().SerializeAsString()); +} + +// Change |sampled_profile| between calls to SaveSerializedPerfProto(). +TEST_F(MetricCollectorTest, MultipleCalls) { + auto sampled_profile = std::make_unique<SampledProfile>(); + sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); + + metric_collector_->SaveSerializedPerfProto( + std::move(sampled_profile), + TestMetricCollector::PerfProtoType::PERF_TYPE_DATA, + perf_data_proto_.SerializeAsString()); + + sampled_profile = std::make_unique<SampledProfile>(); + sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION); + sampled_profile->set_ms_after_restore(3000); + metric_collector_->SaveSerializedPerfProto( + std::move(sampled_profile), + TestMetricCollector::PerfProtoType::PERF_TYPE_STAT, + perf_stat_proto_.SerializeAsString()); + + sampled_profile = std::make_unique<SampledProfile>(); + sampled_profile->set_trigger_event(SampledProfile::RESUME_FROM_SUSPEND); + sampled_profile->set_suspend_duration_ms(60000); + sampled_profile->set_ms_after_resume(1500); + metric_collector_->SaveSerializedPerfProto( + std::move(sampled_profile), + TestMetricCollector::PerfProtoType::PERF_TYPE_DATA, + perf_data_proto_.SerializeAsString()); + + sampled_profile = std::make_unique<SampledProfile>(); + sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); + metric_collector_->SaveSerializedPerfProto( + std::move(sampled_profile), + TestMetricCollector::PerfProtoType::PERF_TYPE_STAT, + perf_stat_proto_.SerializeAsString()); + + std::vector<SampledProfile> stored_profiles; + EXPECT_TRUE(metric_collector_->GetSampledProfiles(&stored_profiles)); + ASSERT_EQ(4U, stored_profiles.size()); + + { + const SampledProfile& profile = stored_profiles[0]; + EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event()); + EXPECT_TRUE(profile.has_ms_after_boot()); + EXPECT_TRUE(profile.has_ms_after_login()); + ASSERT_TRUE(profile.has_perf_data()); + EXPECT_FALSE(profile.has_perf_stat()); + EXPECT_EQ(perf_data_proto_.SerializeAsString(), + profile.perf_data().SerializeAsString()); + } + + { + const SampledProfile& profile = stored_profiles[1]; + EXPECT_EQ(SampledProfile::RESTORE_SESSION, profile.trigger_event()); + EXPECT_TRUE(profile.has_ms_after_boot()); + EXPECT_TRUE(profile.has_ms_after_login()); + EXPECT_EQ(3000, profile.ms_after_restore()); + EXPECT_FALSE(profile.has_perf_data()); + ASSERT_TRUE(profile.has_perf_stat()); + EXPECT_EQ(perf_stat_proto_.SerializeAsString(), + profile.perf_stat().SerializeAsString()); + } + + { + const SampledProfile& profile = stored_profiles[2]; + EXPECT_EQ(SampledProfile::RESUME_FROM_SUSPEND, profile.trigger_event()); + EXPECT_TRUE(profile.has_ms_after_boot()); + EXPECT_TRUE(profile.has_ms_after_login()); + EXPECT_EQ(60000, profile.suspend_duration_ms()); + EXPECT_EQ(1500, profile.ms_after_resume()); + ASSERT_TRUE(profile.has_perf_data()); + EXPECT_FALSE(profile.has_perf_stat()); + EXPECT_EQ(perf_data_proto_.SerializeAsString(), + profile.perf_data().SerializeAsString()); + } + + { + const SampledProfile& profile = stored_profiles[3]; + EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event()); + EXPECT_TRUE(profile.has_ms_after_boot()); + EXPECT_TRUE(profile.has_ms_after_login()); + EXPECT_FALSE(profile.has_perf_data()); + ASSERT_TRUE(profile.has_perf_stat()); + EXPECT_EQ(perf_stat_proto_.SerializeAsString(), + profile.perf_stat().SerializeAsString()); + } } TEST_F(MetricCollectorTest, Deactivate) { @@ -143,12 +438,12 @@ metric_collector_->OnUserLoggedIn(); EXPECT_TRUE(metric_collector_->timer().IsRunning()); - EXPECT_FALSE(metric_collector_->login_time_.is_null()); + EXPECT_FALSE(metric_collector_->login_time().is_null()); // Timer is stopped by Deactivate(), but login time and cached profiles stay. metric_collector_->Deactivate(); EXPECT_FALSE(metric_collector_->timer().IsRunning()); - EXPECT_FALSE(metric_collector_->login_time_.is_null()); + EXPECT_FALSE(metric_collector_->login_time().is_null()); std::vector<SampledProfile> stored_profiles; EXPECT_TRUE(metric_collector_->GetSampledProfiles(&stored_profiles)); @@ -157,11 +452,9 @@ TEST_F(MetricCollectorTest, SuspendDone) { const auto kSuspendDuration = base::TimeDelta::FromMinutes(3); - // Timer is not active before user logs in. - EXPECT_FALSE(metric_collector_->timer().IsRunning()); metric_collector_->SuspendDone(kSuspendDuration); - // Timer is activated by the SuspendDone call. + // Timer is active after the SuspendDone call. EXPECT_TRUE(metric_collector_->timer().IsRunning()); // Run all pending tasks. This will run all the tasks already queued, but not @@ -182,8 +475,8 @@ EXPECT_EQ(SampledProfile::RESUME_FROM_SUSPEND, profile.trigger_event()); EXPECT_EQ(kSuspendDuration.InMilliseconds(), profile.suspend_duration_ms()); EXPECT_TRUE(profile.has_ms_after_resume()); - EXPECT_EQ(kMsAfterLogin, profile.ms_after_login()); - EXPECT_EQ(kMsAfterBoot, profile.ms_after_boot()); + EXPECT_TRUE(profile.has_ms_after_login()); + EXPECT_TRUE(profile.has_ms_after_boot()); // Run all new pending tasks. This will run a periodic collection that was // scheduled by the previous collection event. @@ -199,11 +492,9 @@ TEST_F(MetricCollectorTest, OnSessionRestoreDone) { const int kRestoredTabs = 7; - // Timer is not active before user logs in. - EXPECT_FALSE(metric_collector_->timer().IsRunning()); metric_collector_->OnSessionRestoreDone(kRestoredTabs); - // Timer is activated by the OnSessionRestoreDone call. + // Timer is active after the OnSessionRestoreDone call. EXPECT_TRUE(metric_collector_->timer().IsRunning()); // Run all pending tasks. @@ -220,8 +511,8 @@ EXPECT_EQ(SampledProfile::RESTORE_SESSION, profile.trigger_event()); EXPECT_EQ(kRestoredTabs, profile.num_tabs_restored()); EXPECT_FALSE(profile.has_ms_after_resume()); - EXPECT_EQ(kMsAfterLogin, profile.ms_after_login()); - EXPECT_EQ(kMsAfterBoot, profile.ms_after_boot()); + EXPECT_TRUE(profile.has_ms_after_login()); + EXPECT_TRUE(profile.has_ms_after_boot()); // A second SessionRestoreDone call is throttled. metric_collector_->OnSessionRestoreDone(1); @@ -247,11 +538,7 @@ } TEST_F(MetricCollectorTest, ScheduleIntervalCollection) { - // Timer is not active before user logs in. - EXPECT_FALSE(metric_collector_->timer().IsRunning()); - metric_collector_->ScheduleIntervalCollection(); - - // Timer is activated by the ScheduleIntervalCollection call. + // Timer is active after login and a periodic collection is scheduled. EXPECT_TRUE(metric_collector_->timer().IsRunning()); // Run all pending tasks. @@ -268,8 +555,8 @@ EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event()); EXPECT_FALSE(profile.has_suspend_duration_ms()); EXPECT_FALSE(profile.has_ms_after_resume()); - EXPECT_EQ(kMsAfterLogin, profile.ms_after_login()); - EXPECT_EQ(kMsAfterBoot, profile.ms_after_boot()); + EXPECT_TRUE(profile.has_ms_after_login()); + EXPECT_TRUE(profile.has_ms_after_boot()); ASSERT_TRUE(profile.has_perf_data()); EXPECT_FALSE(profile.has_perf_stat());
diff --git a/chrome/browser/metrics/perf/perf_events_collector.cc b/chrome/browser/metrics/perf/perf_events_collector.cc index 48698e8..40f17bf8 100644 --- a/chrome/browser/metrics/perf/perf_events_collector.cc +++ b/chrome/browser/metrics/perf/perf_events_collector.cc
@@ -4,11 +4,9 @@ #include "chrome/browser/metrics/perf/perf_events_collector.h" -#include "base/metrics/histogram_macros.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" -#include "base/system/sys_info.h" #include "chrome/browser/metrics/perf/cpu_identity.h" #include "chrome/browser/metrics/perf/perf_output.h" #include "chrome/browser/metrics/perf/windowed_incognito_observer.h" @@ -27,28 +25,9 @@ // collecting further perf data. The current value is 4 MB. const size_t kCachedPerfDataProtobufSizeThreshold = 4 * 1024 * 1024; -// Enumeration representing success and various failure modes for collecting and -// sending perf data. -enum GetPerfDataOutcome { - SUCCESS, - NOT_READY_TO_UPLOAD, - NOT_READY_TO_COLLECT, - INCOGNITO_ACTIVE, - INCOGNITO_LAUNCHED, - PROTOBUF_NOT_PARSED, - ILLEGAL_DATA_RETURNED, - ALREADY_COLLECTING, - NUM_OUTCOMES -}; - // Name of the histogram that represents the success and various failure modes -// for collecting and sending perf data. -const char kGetPerfDataOutcomeHistogram[] = "UMA.Perf.GetData"; - -void AddToPerfHistogram(GetPerfDataOutcome outcome) { - UMA_HISTOGRAM_ENUMERATION(kGetPerfDataOutcomeHistogram, outcome, - NUM_OUTCOMES); -} +// for the perf collector. +const char kPerfCollectorOutcomeHistogram[] = "UMA.Perf.GetData"; // Gets parameter named by |key| from the map. If it is present and is an // integer, stores the result in |out| and return true. Otherwise return false. @@ -193,40 +172,6 @@ return cmds; } -// PerfDataProto is defined elsewhere with more fields than the definition in -// Chromium's copy of perf_data.proto. During deserialization, the protobuf -// data could contain fields that are defined elsewhere but not in -// perf_data.proto, resulting in some data in |unknown_fields| for the message -// types within PerfDataProto. -// -// This function deletes those dangling unknown fields if they are in messages -// containing strings. See comments in perf_data.proto describing the fields -// that have been intentionally left out. Note that all unknown fields will be -// removed from those messages, not just unknown string fields. -void RemoveUnknownFieldsFromMessagesWithStrings(PerfDataProto* proto) { - // Clean up PerfEvent::MMapEvent and PerfEvent::CommEvent. - for (PerfDataProto::PerfEvent& event : *proto->mutable_events()) { - if (event.has_comm_event()) - event.mutable_comm_event()->mutable_unknown_fields()->clear(); - if (event.has_mmap_event()) - event.mutable_mmap_event()->mutable_unknown_fields()->clear(); - } - // Clean up PerfBuildID. - for (PerfDataProto::PerfBuildID& build_id : *proto->mutable_build_ids()) { - build_id.mutable_unknown_fields()->clear(); - } - // Clean up StringMetadata and StringMetadata::StringAndMd5sumPrefix. - if (proto->has_string_metadata()) { - proto->mutable_string_metadata()->mutable_unknown_fields()->clear(); - if (proto->string_metadata().has_perf_command_line_whole()) { - proto->mutable_string_metadata() - ->mutable_perf_command_line_whole() - ->mutable_unknown_fields() - ->clear(); - } - } -} - } // namespace namespace internal { @@ -253,7 +198,8 @@ } // namespace internal -PerfCollector::PerfCollector() {} +PerfCollector::PerfCollector() + : MetricCollector(kPerfCollectorOutcomeHistogram) {} PerfCollector::~PerfCollector() {} @@ -267,16 +213,6 @@ MetricCollector::Init(); } -bool PerfCollector::ShouldUpload() const { - if (cached_profile_data_.empty()) { - AddToPerfHistogram(NOT_READY_TO_UPLOAD); - return false; - } - - AddToPerfHistogram(SUCCESS); - return true; -} - namespace internal { std::string FindBestCpuSpecifierFromParams( @@ -387,24 +323,22 @@ command_selector_.SetOdds(commands); } -PerfCollector::PerfSubcommand PerfCollector::GetPerfSubcommandType( +MetricCollector::PerfProtoType PerfCollector::GetPerfProtoType( const std::vector<std::string>& args) { if (args.size() > 1 && args[0] == "perf") { - if (args[1] == "record") - return PerfSubcommand::PERF_COMMAND_RECORD; + if (args[1] == "record" || args[1] == "mem") + return PerfProtoType::PERF_TYPE_DATA; if (args[1] == "stat") - return PerfSubcommand::PERF_COMMAND_STAT; - if (args[1] == "mem") - return PerfSubcommand::PERF_COMMAND_MEM; + return PerfProtoType::PERF_TYPE_STAT; } - return PerfSubcommand::PERF_COMMAND_UNSUPPORTED; + return PerfProtoType::PERF_TYPE_UNSUPPORTED; } void PerfCollector::ParseOutputProtoIfValid( std::unique_ptr<WindowedIncognitoObserver> incognito_observer, std::unique_ptr<SampledProfile> sampled_profile, - PerfSubcommand subcommand, + PerfProtoType type, const std::string& perf_stdout) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -413,74 +347,30 @@ std::unique_ptr<PerfOutputCall> call_deleter(std::move(perf_output_call_)); if (incognito_observer->incognito_launched()) { - AddToPerfHistogram(INCOGNITO_LAUNCHED); + AddToUmaHistogram(CollectionAttemptStatus::INCOGNITO_LAUNCHED); return; } - - if (perf_stdout.empty()) { - AddToPerfHistogram(ILLEGAL_DATA_RETURNED); - return; - } - - switch (subcommand) { - case PerfSubcommand::PERF_COMMAND_RECORD: - case PerfSubcommand::PERF_COMMAND_MEM: { - PerfDataProto perf_data_proto; - if (!perf_data_proto.ParseFromString(perf_stdout)) { - AddToPerfHistogram(PROTOBUF_NOT_PARSED); - return; - } - RemoveUnknownFieldsFromMessagesWithStrings(&perf_data_proto); - sampled_profile->set_ms_after_boot( - base::SysInfo::Uptime().InMilliseconds()); - sampled_profile->mutable_perf_data()->Swap(&perf_data_proto); - break; - } - case PerfSubcommand::PERF_COMMAND_STAT: { - PerfStatProto perf_stat_proto; - if (!perf_stat_proto.ParseFromString(perf_stdout)) { - AddToPerfHistogram(PROTOBUF_NOT_PARSED); - return; - } - sampled_profile->mutable_perf_stat()->Swap(&perf_stat_proto); - break; - } - case PerfSubcommand::PERF_COMMAND_UNSUPPORTED: - AddToPerfHistogram(PROTOBUF_NOT_PARSED); - return; - } - - DCHECK(!login_time_.is_null()); - sampled_profile->set_ms_after_login( - (base::TimeTicks::Now() - login_time_).InMilliseconds()); - - // Add the collected data to the container of collected SampledProfiles. - cached_profile_data_.resize(cached_profile_data_.size() + 1); - cached_profile_data_.back().Swap(sampled_profile.get()); + SaveSerializedPerfProto(std::move(sampled_profile), type, perf_stdout); } bool PerfCollector::ShouldCollect() const { // Only allow one active collection. if (perf_output_call_) { - AddToPerfHistogram(ALREADY_COLLECTING); + AddToUmaHistogram(CollectionAttemptStatus::ALREADY_COLLECTING); return false; } // Do not collect further data if we've already collected a substantial amount // of data, as indicated by |kCachedPerfDataProtobufSizeThreshold|. - size_t cached_perf_data_size = 0; - for (size_t i = 0; i < cached_profile_data_.size(); ++i) { - cached_perf_data_size += cached_profile_data_[i].ByteSize(); - } - if (cached_perf_data_size >= kCachedPerfDataProtobufSizeThreshold) { - AddToPerfHistogram(NOT_READY_TO_COLLECT); + if (cached_profile_data_size() >= kCachedPerfDataProtobufSizeThreshold) { + AddToUmaHistogram(CollectionAttemptStatus::NOT_READY_TO_COLLECT); return false; } // For privacy reasons, Chrome should only collect perf data if there is no // incognito session active (or gets spawned during the collection). if (BrowserList::IsIncognitoSessionActive()) { - AddToPerfHistogram(INCOGNITO_ACTIVE); + AddToUmaHistogram(CollectionAttemptStatus::INCOGNITO_ACTIVE); return false; } @@ -495,14 +385,14 @@ std::vector<std::string> command = base::SplitString(command_selector_.Select(), kPerfCommandDelimiter, base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); - PerfSubcommand subcommand = GetPerfSubcommandType(command); + PerfProtoType type = GetPerfProtoType(command); perf_output_call_ = std::make_unique<PerfOutputCall>( collection_params_.collection_duration, command, base::BindOnce(&PerfCollector::ParseOutputProtoIfValid, base::AsWeakPtr<PerfCollector>(this), base::Passed(&incognito_observer), - base::Passed(&sampled_profile), subcommand)); + base::Passed(&sampled_profile), type)); } } // namespace metrics
diff --git a/chrome/browser/metrics/perf/perf_events_collector.h b/chrome/browser/metrics/perf/perf_events_collector.h index bd59e88f..860487ee 100644 --- a/chrome/browser/metrics/perf/perf_events_collector.h +++ b/chrome/browser/metrics/perf/perf_events_collector.h
@@ -27,18 +27,9 @@ void Init() override; protected: - // Perf events collection subcommands. - enum PerfSubcommand { - PERF_COMMAND_RECORD, - PERF_COMMAND_STAT, - PERF_COMMAND_MEM, - PERF_COMMAND_UNSUPPORTED, - }; - - // Returns one of the above enums given an vector of perf arguments, starting - // with "perf" itself in |args[0]|. - static PerfSubcommand GetPerfSubcommandType( - const std::vector<std::string>& args); + // Returns the perf proto type associated with the given vector of perf + // arguments, starting with "perf" itself in |args[0]|. + static PerfProtoType GetPerfProtoType(const std::vector<std::string>& args); // Parses a PerfDataProto or PerfStatProto from serialized data |perf_stdout|, // if non-empty. Which proto to use depends on |subcommand|. If |perf_stdout| @@ -48,11 +39,10 @@ void ParseOutputProtoIfValid( std::unique_ptr<WindowedIncognitoObserver> incognito_observer, std::unique_ptr<SampledProfile> sampled_profile, - PerfSubcommand subcommand, + PerfProtoType type, const std::string& perf_stdout); // MetricCollector: - bool ShouldUpload() const override; bool ShouldCollect() const override; void CollectProfile(std::unique_ptr<SampledProfile> sampled_profile) override;
diff --git a/chrome/browser/metrics/perf/perf_events_collector_unittest.cc b/chrome/browser/metrics/perf/perf_events_collector_unittest.cc index 44e271a..83f9652 100644 --- a/chrome/browser/metrics/perf/perf_events_collector_unittest.cc +++ b/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
@@ -22,9 +22,6 @@ #include "components/variations/variations_associated_data.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/metrics_proto/sampled_profile.pb.h" -#include "third_party/protobuf/src/google/protobuf/io/coded_stream.h" -#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h" -#include "third_party/protobuf/src/google/protobuf/wire_format_lite_inl.h" namespace metrics { @@ -104,21 +101,6 @@ return proto; } -// Creates a serialized data stream containing a string with a field tag number. -std::string SerializeStringFieldWithTag(int field, const std::string& value) { - std::string result; - google::protobuf::io::StringOutputStream string_stream(&result); - google::protobuf::io::CodedOutputStream output(&string_stream); - - using google::protobuf::internal::WireFormatLite; - WireFormatLite::WriteTag(field, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, - &output); - output.WriteVarint32(value.size()); - output.WriteString(value); - - return result; -} - // Allows testing of PerfCollector behavior when an incognito window is opened. class TestIncognitoObserver : public WindowedIncognitoObserver { public: @@ -144,13 +126,10 @@ public: TestPerfCollector() {} + using MetricCollector::PerfProtoType; using PerfCollector::collection_params; using PerfCollector::command_selector; - using PerfCollector::Deactivate; - using PerfCollector::OnSessionRestoreDone; using PerfCollector::ParseOutputProtoIfValid; - using PerfCollector::PerfSubcommand; - using PerfCollector::timer; private: DISALLOW_COPY_AND_ASSIGN(TestPerfCollector); @@ -162,9 +141,7 @@ public: PerfCollectorTest() : task_runner_(base::MakeRefCounted<base::TestSimpleTaskRunner>()), - task_runner_handle_(task_runner_), - perf_data_proto_(GetExamplePerfDataProto()), - perf_stat_proto_(GetExamplePerfStatProto()) {} + task_runner_handle_(task_runner_) {} void SetUp() override { // PerfCollector requires chromeos::LoginState and @@ -191,17 +168,10 @@ scoped_refptr<base::TestSimpleTaskRunner> task_runner_; base::ThreadTaskRunnerHandle task_runner_handle_; - // These store example perf data/stat protobufs for testing. - PerfDataProto perf_data_proto_; - PerfStatProto perf_stat_proto_; - DISALLOW_COPY_AND_ASSIGN(PerfCollectorTest); }; TEST_F(PerfCollectorTest, CheckSetup) { - EXPECT_GT(perf_data_proto_.ByteSize(), 0); - EXPECT_GT(perf_stat_proto_.ByteSize(), 0); - std::vector<SampledProfile> stored_profiles; EXPECT_FALSE(perf_collector_->GetSampledProfiles(&stored_profiles)); EXPECT_TRUE(stored_profiles.empty()); @@ -212,261 +182,22 @@ ->incognito_launched()); } -// If quipper fails, or the DBus call fails, no data will be returned. -TEST_F(PerfCollectorTest, NoPerfData) { - auto sampled_profile = std::make_unique<SampledProfile>(); - sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); - - perf_collector_->ParseOutputProtoIfValid( - TestIncognitoObserver::CreateWithIncognitoLaunched(false), - std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_RECORD, std::string()); - - std::vector<SampledProfile> stored_profiles; - EXPECT_FALSE(perf_collector_->GetSampledProfiles(&stored_profiles)); -} - -TEST_F(PerfCollectorTest, PerfDataProto) { - auto sampled_profile = std::make_unique<SampledProfile>(); - sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); - - perf_collector_->ParseOutputProtoIfValid( - TestIncognitoObserver::CreateWithIncognitoLaunched(false), - std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_RECORD, - perf_data_proto_.SerializeAsString()); - - std::vector<SampledProfile> stored_profiles; - EXPECT_TRUE(perf_collector_->GetSampledProfiles(&stored_profiles)); - ASSERT_EQ(1U, stored_profiles.size()); - - const SampledProfile& profile = stored_profiles[0]; - EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event()); - EXPECT_TRUE(profile.has_ms_after_login()); - - ASSERT_TRUE(profile.has_perf_data()); - EXPECT_FALSE(profile.has_perf_stat()); - EXPECT_EQ(SerializeMessageToVector(perf_data_proto_), - SerializeMessageToVector(profile.perf_data())); -} - -TEST_F(PerfCollectorTest, PerfDataProto_UnknownFieldsDiscarded) { - // First add some unknown fields to MMapEvent, CommEvent, PerfBuildID, and - // StringAndMd5sumPrefix. The known field values don't have to make sense for - // perf data. They are just padding to avoid having an otherwise empty proto. - // The unknown field string contents don't have to make sense as serialized - // data as the test is to discard them. - - // MMapEvent - PerfDataProto_PerfEvent* event1 = perf_data_proto_.add_events(); - event1->mutable_header()->set_type(1); - event1->mutable_mmap_event()->set_pid(1234); - event1->mutable_mmap_event()->set_filename_md5_prefix(0xdeadbeef); - // Missing field |MMapEvent::filename| has tag=6. - *event1->mutable_mmap_event()->mutable_unknown_fields() = - SerializeStringFieldWithTag(6, "/opt/google/chrome/chrome"); - - // CommEvent - PerfDataProto_PerfEvent* event2 = perf_data_proto_.add_events(); - event2->mutable_header()->set_type(2); - event2->mutable_comm_event()->set_pid(5678); - event2->mutable_comm_event()->set_comm_md5_prefix(0x900df00d); - // Missing field |CommEvent::comm| has tag=3. - *event2->mutable_comm_event()->mutable_unknown_fields() = - SerializeStringFieldWithTag(3, "chrome"); - - // PerfBuildID - PerfDataProto_PerfBuildID* build_id = perf_data_proto_.add_build_ids(); - build_id->set_misc(3); - build_id->set_pid(1337); - build_id->set_filename_md5_prefix(0x9876543210); - // Missing field |PerfBuildID::filename| has tag=4. - *build_id->mutable_unknown_fields() = - SerializeStringFieldWithTag(4, "/opt/google/chrome/chrome"); - - // StringAndMd5sumPrefix - PerfDataProto_StringMetadata* metadata = - perf_data_proto_.mutable_string_metadata(); - metadata->mutable_perf_command_line_whole()->set_value_md5_prefix( - 0x123456789); - // Missing field |StringAndMd5sumPrefix::value| has tag=1. - *metadata->mutable_perf_command_line_whole()->mutable_unknown_fields() = - SerializeStringFieldWithTag(1, "perf record -a -- sleep 1"); - - // Serialize to string and make sure it can be deserialized. - std::string perf_data_string = perf_data_proto_.SerializeAsString(); - PerfDataProto temp_proto; - EXPECT_TRUE(temp_proto.ParseFromString(perf_data_string)); - - // Now pass it to |perf_collector_|. - auto sampled_profile = std::make_unique<SampledProfile>(); - sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); - - perf_collector_->ParseOutputProtoIfValid( - TestIncognitoObserver::CreateWithIncognitoLaunched(false), - std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_RECORD, perf_data_string); - - std::vector<SampledProfile> stored_profiles; - EXPECT_TRUE(perf_collector_->GetSampledProfiles(&stored_profiles)); - ASSERT_EQ(1U, stored_profiles.size()); - - const SampledProfile& profile = stored_profiles[0]; - EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event()); - EXPECT_TRUE(profile.has_perf_data()); - - // The serialized form should be different because the unknown fields have - // have been removed. - EXPECT_NE(perf_data_string, profile.perf_data().SerializeAsString()); - - // Check contents of stored protobuf. - const PerfDataProto& stored_proto = profile.perf_data(); - ASSERT_EQ(2, stored_proto.events_size()); - - // MMapEvent - const PerfDataProto_PerfEvent& stored_event1 = stored_proto.events(0); - EXPECT_EQ(1U, stored_event1.header().type()); - EXPECT_EQ(1234U, stored_event1.mmap_event().pid()); - EXPECT_EQ(0xdeadbeef, stored_event1.mmap_event().filename_md5_prefix()); - EXPECT_EQ(0U, stored_event1.mmap_event().unknown_fields().size()); - - // CommEvent - const PerfDataProto_PerfEvent& stored_event2 = stored_proto.events(1); - EXPECT_EQ(2U, stored_event2.header().type()); - EXPECT_EQ(5678U, stored_event2.comm_event().pid()); - EXPECT_EQ(0x900df00d, stored_event2.comm_event().comm_md5_prefix()); - EXPECT_EQ(0U, stored_event2.comm_event().unknown_fields().size()); - - // PerfBuildID - ASSERT_EQ(1, stored_proto.build_ids_size()); - const PerfDataProto_PerfBuildID& stored_build_id = stored_proto.build_ids(0); - EXPECT_EQ(3U, stored_build_id.misc()); - EXPECT_EQ(1337U, stored_build_id.pid()); - EXPECT_EQ(0x9876543210U, stored_build_id.filename_md5_prefix()); - EXPECT_EQ(0U, stored_build_id.unknown_fields().size()); - - // StringAndMd5sumPrefix - const PerfDataProto_StringMetadata& stored_metadata = - stored_proto.string_metadata(); - EXPECT_EQ(0x123456789U, - stored_metadata.perf_command_line_whole().value_md5_prefix()); - EXPECT_EQ(0U, - stored_metadata.perf_command_line_whole().unknown_fields().size()); -} - -TEST_F(PerfCollectorTest, PerfStatProto) { - auto sampled_profile = std::make_unique<SampledProfile>(); - sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); - - perf_collector_->ParseOutputProtoIfValid( - TestIncognitoObserver::CreateWithIncognitoLaunched(false), - std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_STAT, - perf_stat_proto_.SerializeAsString()); - - std::vector<SampledProfile> stored_profiles; - EXPECT_TRUE(perf_collector_->GetSampledProfiles(&stored_profiles)); - ASSERT_EQ(1U, stored_profiles.size()); - - const SampledProfile& profile = stored_profiles[0]; - EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event()); - EXPECT_TRUE(profile.has_ms_after_login()); - - EXPECT_FALSE(profile.has_perf_data()); - ASSERT_TRUE(profile.has_perf_stat()); - EXPECT_EQ(SerializeMessageToVector(perf_stat_proto_), - SerializeMessageToVector(profile.perf_stat())); -} - -// Change |sampled_profile| between calls to ParseOutputProtoIfValid(). -TEST_F(PerfCollectorTest, MultipleCalls) { - auto sampled_profile = std::make_unique<SampledProfile>(); - sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); - - perf_collector_->ParseOutputProtoIfValid( - TestIncognitoObserver::CreateWithIncognitoLaunched(false), - std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_RECORD, - perf_data_proto_.SerializeAsString()); - - sampled_profile = std::make_unique<SampledProfile>(); - sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION); - sampled_profile->set_ms_after_restore(3000); - perf_collector_->ParseOutputProtoIfValid( - TestIncognitoObserver::CreateWithIncognitoLaunched(false), - std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_STAT, - perf_stat_proto_.SerializeAsString()); - - sampled_profile = std::make_unique<SampledProfile>(); - sampled_profile->set_trigger_event(SampledProfile::RESUME_FROM_SUSPEND); - sampled_profile->set_suspend_duration_ms(60000); - sampled_profile->set_ms_after_resume(1500); - perf_collector_->ParseOutputProtoIfValid( - TestIncognitoObserver::CreateWithIncognitoLaunched(false), - std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_RECORD, - perf_data_proto_.SerializeAsString()); - - sampled_profile = std::make_unique<SampledProfile>(); - sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); - perf_collector_->ParseOutputProtoIfValid( - TestIncognitoObserver::CreateWithIncognitoLaunched(false), - std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_STAT, - perf_stat_proto_.SerializeAsString()); - - std::vector<SampledProfile> stored_profiles; - EXPECT_TRUE(perf_collector_->GetSampledProfiles(&stored_profiles)); - ASSERT_EQ(4U, stored_profiles.size()); - - const SampledProfile& profile1 = stored_profiles[0]; - EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile1.trigger_event()); - EXPECT_TRUE(profile1.has_ms_after_login()); - ASSERT_TRUE(profile1.has_perf_data()); - EXPECT_FALSE(profile1.has_perf_stat()); - EXPECT_EQ(SerializeMessageToVector(perf_data_proto_), - SerializeMessageToVector(profile1.perf_data())); - - const SampledProfile& profile2 = stored_profiles[1]; - EXPECT_EQ(SampledProfile::RESTORE_SESSION, profile2.trigger_event()); - EXPECT_TRUE(profile2.has_ms_after_login()); - EXPECT_EQ(3000, profile2.ms_after_restore()); - EXPECT_FALSE(profile2.has_perf_data()); - ASSERT_TRUE(profile2.has_perf_stat()); - EXPECT_EQ(SerializeMessageToVector(perf_stat_proto_), - SerializeMessageToVector(profile2.perf_stat())); - - const SampledProfile& profile3 = stored_profiles[2]; - EXPECT_EQ(SampledProfile::RESUME_FROM_SUSPEND, profile3.trigger_event()); - EXPECT_TRUE(profile3.has_ms_after_login()); - EXPECT_EQ(60000, profile3.suspend_duration_ms()); - EXPECT_EQ(1500, profile3.ms_after_resume()); - ASSERT_TRUE(profile3.has_perf_data()); - EXPECT_FALSE(profile3.has_perf_stat()); - EXPECT_EQ(SerializeMessageToVector(perf_data_proto_), - SerializeMessageToVector(profile3.perf_data())); - - const SampledProfile& profile4 = stored_profiles[3]; - EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile4.trigger_event()); - EXPECT_TRUE(profile4.has_ms_after_login()); - EXPECT_FALSE(profile4.has_perf_data()); - ASSERT_TRUE(profile4.has_perf_stat()); - EXPECT_EQ(SerializeMessageToVector(perf_stat_proto_), - SerializeMessageToVector(profile4.perf_stat())); -} - // Simulate opening and closing of incognito window in between calls to // ParseOutputProtoIfValid(). TEST_F(PerfCollectorTest, IncognitoWindowOpened) { + PerfDataProto perf_data_proto = GetExamplePerfDataProto(); + PerfStatProto perf_stat_proto = GetExamplePerfStatProto(); + EXPECT_GT(perf_data_proto.ByteSize(), 0); + EXPECT_GT(perf_stat_proto.ByteSize(), 0); + auto sampled_profile = std::make_unique<SampledProfile>(); sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); perf_collector_->ParseOutputProtoIfValid( TestIncognitoObserver::CreateWithIncognitoLaunched(false), std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_RECORD, - perf_data_proto_.SerializeAsString()); + TestPerfCollector::PerfProtoType::PERF_TYPE_DATA, + perf_data_proto.SerializeAsString()); std::vector<SampledProfile> stored_profiles1; EXPECT_TRUE(perf_collector_->GetSampledProfiles(&stored_profiles1)); @@ -477,7 +208,7 @@ EXPECT_TRUE(profile1.has_ms_after_login()); ASSERT_TRUE(profile1.has_perf_data()); EXPECT_FALSE(profile1.has_perf_stat()); - EXPECT_EQ(SerializeMessageToVector(perf_data_proto_), + EXPECT_EQ(SerializeMessageToVector(perf_data_proto), SerializeMessageToVector(profile1.perf_data())); sampled_profile = std::make_unique<SampledProfile>(); @@ -486,8 +217,8 @@ perf_collector_->ParseOutputProtoIfValid( TestIncognitoObserver::CreateWithIncognitoLaunched(false), std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_STAT, - perf_stat_proto_.SerializeAsString()); + TestPerfCollector::PerfProtoType::PERF_TYPE_STAT, + perf_stat_proto.SerializeAsString()); std::vector<SampledProfile> stored_profiles2; EXPECT_TRUE(perf_collector_->GetSampledProfiles(&stored_profiles2)); @@ -499,7 +230,7 @@ EXPECT_EQ(3000, profile2.ms_after_restore()); EXPECT_FALSE(profile2.has_perf_data()); ASSERT_TRUE(profile2.has_perf_stat()); - EXPECT_EQ(SerializeMessageToVector(perf_stat_proto_), + EXPECT_EQ(SerializeMessageToVector(perf_stat_proto), SerializeMessageToVector(profile2.perf_stat())); sampled_profile = std::make_unique<SampledProfile>(); @@ -508,8 +239,8 @@ perf_collector_->ParseOutputProtoIfValid( TestIncognitoObserver::CreateWithIncognitoLaunched(true), std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_RECORD, - perf_data_proto_.SerializeAsString()); + TestPerfCollector::PerfProtoType::PERF_TYPE_DATA, + perf_data_proto.SerializeAsString()); std::vector<SampledProfile> stored_profiles_empty; EXPECT_FALSE(perf_collector_->GetSampledProfiles(&stored_profiles_empty)); @@ -520,8 +251,8 @@ perf_collector_->ParseOutputProtoIfValid( TestIncognitoObserver::CreateWithIncognitoLaunched(true), std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_STAT, - perf_stat_proto_.SerializeAsString()); + TestPerfCollector::PerfProtoType::PERF_TYPE_STAT, + perf_stat_proto.SerializeAsString()); EXPECT_FALSE(perf_collector_->GetSampledProfiles(&stored_profiles_empty)); @@ -533,8 +264,8 @@ perf_collector_->ParseOutputProtoIfValid( TestIncognitoObserver::CreateWithIncognitoLaunched(false), std::move(sampled_profile), - TestPerfCollector::PerfSubcommand::PERF_COMMAND_RECORD, - perf_data_proto_.SerializeAsString()); + TestPerfCollector::PerfProtoType::PERF_TYPE_DATA, + perf_data_proto.SerializeAsString()); std::vector<SampledProfile> stored_profiles3; EXPECT_TRUE(perf_collector_->GetSampledProfiles(&stored_profiles3)); @@ -547,7 +278,7 @@ EXPECT_EQ(1500, profile3.ms_after_resume()); ASSERT_TRUE(profile3.has_perf_data()); EXPECT_FALSE(profile3.has_perf_stat()); - EXPECT_EQ(SerializeMessageToVector(perf_data_proto_), + EXPECT_EQ(SerializeMessageToVector(perf_data_proto), SerializeMessageToVector(profile3.perf_data())); }
diff --git a/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc b/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc index b45fc8d..a1b38583 100644 --- a/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc +++ b/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
@@ -24,9 +24,6 @@ namespace { -const long kMsAfterBoot = 10000; -const long kMsAfterLogin = 2000; - // Returns sample PerfDataProtos with custom timestamps. The contents don't have // to make sense. They just need to constitute a semantically valid protobuf. // |proto| is an output parameter that will contain the created protobuf. @@ -62,18 +59,14 @@ public: TestMetricCollector() {} explicit TestMetricCollector(const CollectionParams& collection_params) - : MetricCollector(collection_params) {} + : MetricCollector("UMA.CWP.TestData", collection_params) {} void CollectProfile( std::unique_ptr<SampledProfile> sampled_profile) override { PerfDataProto perf_data_proto = GetExamplePerfDataProto(TSTAMP); - sampled_profile->set_ms_after_boot(kMsAfterBoot); - sampled_profile->set_ms_after_login(kMsAfterLogin); - sampled_profile->mutable_perf_data()->Swap(&perf_data_proto); - - // Add the collected data to the container of collected SampledProfiles. - cached_profile_data_.resize(cached_profile_data_.size() + 1); - cached_profile_data_.back().Swap(sampled_profile.get()); + SaveSerializedPerfProto(std::move(sampled_profile), + PerfProtoType::PERF_TYPE_DATA, + perf_data_proto.SerializeAsString()); } private:
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc index 1a6c0243..d523c3f 100644 --- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc +++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc
@@ -57,6 +57,10 @@ lite_page_seen_ = true; } if (previews_state && previews::GetMainFramePreviewsType(previews_state) == + previews::PreviewsType::LITE_PAGE_REDIRECT) { + lite_page_redirect_seen_ = true; + } + if (previews_state && previews::GetMainFramePreviewsType(previews_state) == previews::PreviewsType::NOSCRIPT) { noscript_seen_ = true; } @@ -68,6 +72,11 @@ previews_user_data->cache_control_no_transform_directive()) { origin_opt_out_occurred_ = true; } + if (previews_user_data && previews_user_data->server_lite_page_info()) { + navigation_restart_penalty_ = + navigation_handle->NavigationStart() - + previews_user_data->server_lite_page_info()->original_navigation_start; + } return CONTINUE_OBSERVING; } @@ -121,9 +130,13 @@ page_load_metrics::PageEndReason::PAGE_END_REASON_COUNT); // Only record previews types when they are active. + // |navigation_restart_penalty_| is included here because a Lite Page Redirect + // preview can be attempted and not commit. This incurs the penalty but may + // also cause no preview to be committed. if (!server_lofi_seen_ && !client_lofi_seen_ && !lite_page_seen_ && !noscript_seen_ && !resource_loading_hints_seen_ && - !origin_opt_out_occurred_ && !save_data_enabled_) { + !origin_opt_out_occurred_ && !save_data_enabled_ && + !lite_page_redirect_seen_ && !navigation_restart_penalty_.has_value()) { return; } @@ -134,6 +147,8 @@ builder.Setclient_lofi(1); if (lite_page_seen_) builder.Setlite_page(1); + if (lite_page_redirect_seen_) + builder.Setlite_page_redirect(1); if (noscript_seen_) builder.Setnoscript(1); if (resource_loading_hints_seen_) @@ -144,6 +159,10 @@ builder.Setorigin_opt_out(1); if (save_data_enabled_) builder.Setsave_data_enabled(1); + if (navigation_restart_penalty_.has_value()) { + builder.Setnavigation_restart_penalty( + navigation_restart_penalty_->InMilliseconds()); + } builder.Record(ukm::UkmRecorder::Get()); }
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.h b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.h index 1d1f1aaf..814466b 100644 --- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.h +++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.h
@@ -6,7 +6,9 @@ #define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_PREVIEWS_UKM_OBSERVER_H_ #include "base/macros.h" +#include "base/optional.h" #include "base/sequence_checker.h" +#include "base/time/time.h" #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" #include "components/previews/core/previews_experiments.h" @@ -56,11 +58,13 @@ bool server_lofi_seen_ = false; bool client_lofi_seen_ = false; bool lite_page_seen_ = false; + bool lite_page_redirect_seen_ = false; bool noscript_seen_ = false; bool resource_loading_hints_seen_ = false; bool opt_out_occurred_ = false; bool origin_opt_out_occurred_ = false; bool save_data_enabled_ = false; + base::Optional<base::TimeDelta> navigation_restart_penalty_ = base::nullopt; SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc index 2d84087..ff7d7bb 100644 --- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
@@ -36,18 +36,23 @@ class TestPreviewsUKMObserver : public PreviewsUKMObserver { public: - TestPreviewsUKMObserver(PreviewsType committed_preview, - bool lite_page_received, - bool noscript_on, - bool resource_loading_hints_on, - bool origin_opt_out_received, - bool save_data_enabled) + TestPreviewsUKMObserver( + PreviewsType committed_preview, + bool lite_page_received, + bool lite_page_redirect_received, + bool noscript_on, + bool resource_loading_hints_on, + bool origin_opt_out_received, + bool save_data_enabled, + base::Optional<base::TimeDelta> navigation_restart_penalty) : committed_preview_(committed_preview), lite_page_received_(lite_page_received), + lite_page_redirect_received_(lite_page_redirect_received), noscript_on_(noscript_on), resource_loading_hints_on_(resource_loading_hints_on), origin_opt_out_received_(origin_opt_out_received), - save_data_enabled_(save_data_enabled) {} + save_data_enabled_(save_data_enabled), + navigation_restart_penalty_(navigation_restart_penalty) {} ~TestPreviewsUKMObserver() override {} @@ -83,6 +88,21 @@ content::SERVER_LITE_PAGE_ON); } + if (lite_page_redirect_received_) { + content::PreviewsState previews_state = + user_data->committed_previews_state(); + user_data->set_committed_previews_state(previews_state |= + content::LITE_PAGE_REDIRECT_ON); + } + + if (navigation_restart_penalty_.has_value()) { + user_data->set_server_lite_page_info( + std::make_unique<previews::PreviewsUserData::ServerLitePageInfo>()); + user_data->server_lite_page_info()->original_navigation_start = + navigation_handle->NavigationStart() - + navigation_restart_penalty_.value(); + } + if (origin_opt_out_received_) { user_data->set_cache_control_no_transform_directive(); } @@ -98,10 +118,12 @@ PreviewsType committed_preview_; bool lite_page_received_; + bool lite_page_redirect_received_; bool noscript_on_; bool resource_loading_hints_on_; bool origin_opt_out_received_; const bool save_data_enabled_; + base::Optional<base::TimeDelta> navigation_restart_penalty_; DISALLOW_COPY_AND_ASSIGN(TestPreviewsUKMObserver); }; @@ -114,33 +136,40 @@ void RunTest(PreviewsType committed_preview, bool lite_page_received, + bool lite_page_redirect_received, bool noscript_on, bool resource_loading_hints_on, bool origin_opt_out, - bool save_data_enabled) { + bool save_data_enabled, + base::Optional<base::TimeDelta> navigation_restart_penalty) { committed_preview_ = committed_preview; lite_page_received_ = lite_page_received; + lite_page_redirect_received_ = lite_page_redirect_received; noscript_on_ = noscript_on; resource_loading_hints_on_ = resource_loading_hints_on; origin_opt_out_ = origin_opt_out; save_data_enabled_ = save_data_enabled; + navigation_restart_penalty_ = navigation_restart_penalty; NavigateAndCommit(GURL(kDefaultTestUrl)); } void ValidateUKM(bool server_lofi_expected, bool client_lofi_expected, bool lite_page_expected, + bool lite_page_redirect_expected, bool noscript_expected, bool resource_loading_hints_expected, int opt_out_value, bool origin_opt_out_expected, - bool save_data_enabled_expected) { + bool save_data_enabled_expected, + base::Optional<base::TimeDelta> navigation_restart_penalty) { using UkmEntry = ukm::builders::Previews; auto entries = test_ukm_recorder().GetEntriesByName(UkmEntry::kEntryName); if (!server_lofi_expected && !client_lofi_expected && !lite_page_expected && - !noscript_expected && !resource_loading_hints_expected && - opt_out_value == 0 && !origin_opt_out_expected && - !save_data_enabled_expected) { + !lite_page_redirect_expected && !noscript_expected && + !resource_loading_hints_expected && opt_out_value == 0 && + !origin_opt_out_expected && !save_data_enabled_expected && + !navigation_restart_penalty.has_value()) { EXPECT_EQ(0u, entries.size()); return; } @@ -153,6 +182,9 @@ entry, UkmEntry::kclient_lofiName)); EXPECT_EQ(lite_page_expected, test_ukm_recorder().EntryHasMetric( entry, UkmEntry::klite_pageName)); + EXPECT_EQ(lite_page_redirect_expected, + test_ukm_recorder().EntryHasMetric( + entry, UkmEntry::klite_page_redirectName)); EXPECT_EQ(noscript_expected, test_ukm_recorder().EntryHasMetric( entry, UkmEntry::knoscriptName)); EXPECT_EQ(resource_loading_hints_expected, @@ -170,6 +202,11 @@ EXPECT_EQ(save_data_enabled_expected, test_ukm_recorder().EntryHasMetric( entry, UkmEntry::ksave_data_enabledName)); + if (navigation_restart_penalty.has_value()) { + test_ukm_recorder().ExpectEntryMetric( + entry, UkmEntry::knavigation_restart_penaltyName, + navigation_restart_penalty.value().InMilliseconds()); + } } } @@ -181,70 +218,87 @@ protected: void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override { tracker->AddObserver(std::make_unique<TestPreviewsUKMObserver>( - committed_preview_, lite_page_received_, noscript_on_, - resource_loading_hints_on_, origin_opt_out_, save_data_enabled_)); + committed_preview_, lite_page_received_, lite_page_redirect_received_, + noscript_on_, resource_loading_hints_on_, origin_opt_out_, + save_data_enabled_, navigation_restart_penalty_)); // Data is only added to the first navigation after RunTest(). committed_preview_ = PreviewsType::NONE; lite_page_received_ = false; + lite_page_redirect_received_ = false; noscript_on_ = false; resource_loading_hints_on_ = false; origin_opt_out_ = false; + navigation_restart_penalty_ = base::nullopt; } private: PreviewsType committed_preview_ = PreviewsType::NONE; bool lite_page_received_ = false; + bool lite_page_redirect_received_ = false; bool noscript_on_ = false; bool resource_loading_hints_on_ = false; bool origin_opt_out_ = false; bool save_data_enabled_ = false; + base::Optional<base::TimeDelta> navigation_restart_penalty_ = base::nullopt; DISALLOW_COPY_AND_ASSIGN(PreviewsUKMObserverTest); }; TEST_F(PreviewsUKMObserverTest, NoPreviewSeen) { RunTest(PreviewsType::NONE, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); NavigateToUntrackedUrl(); ValidateUKM(false /* server_lofi_expected */, false /* client_lofi_expected */, false /* lite_page_expected */, + false /* lite_page_redirect_expected */, false /* noscript_expected */, false /* resource_loading_hints_expected */, 0 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, UntrackedPreviewTypeOptOut) { RunTest(PreviewsType::NONE, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); observer()->BroadcastEventToObservers(PreviewsUITabHelper::OptOutEventKey()); NavigateToUntrackedUrl(); // Opt out should not be added since we don't track this type. ValidateUKM(false /* server_lofi_expected */, false /* client_lofi_expected */, false /* lite_page_expected */, + false /* lite_page_redirect_expected */, false /* noscript_expected */, false /* resource_loading_hints_expected */, 0 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, LitePageSeen) { RunTest(PreviewsType::NONE, true /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); NavigateToUntrackedUrl(); ValidateUKM(false /* server_lofi_expected */, false /* client_lofi_expected */, true /* lite_page_expected */, + false /* lite_page_redirect_expected */, false /* noscript_expected */, false /* resource_loading_hints_expected */, 0 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, LitePageOptOut) { @@ -255,18 +309,22 @@ kAndroidOmniboxPreviewsBadge} /* disabled features */); RunTest(PreviewsType::LITE_PAGE, true /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); observer()->BroadcastEventToObservers(PreviewsUITabHelper::OptOutEventKey()); NavigateToUntrackedUrl(); ValidateUKM(false /* server_lofi_expected */, false /* client_lofi_expected */, true /* lite_page_expected */, + false /* lite_page_redirect_expected */, false /* noscript_expected */, false /* resource_loading_hints_expected */, 1 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, LitePageOptOutChip) { @@ -276,33 +334,110 @@ {} /*disabled features */); RunTest(PreviewsType::LITE_PAGE, true /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); observer()->BroadcastEventToObservers(PreviewsUITabHelper::OptOutEventKey()); NavigateToUntrackedUrl(); ValidateUKM(false /* server_lofi_expected */, false /* client_lofi_expected */, true /* lite_page_expected */, + false /* lite_page_redirect_expected */, false /* noscript_expected */, false /* resource_loading_hints_expected */, 2 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } -TEST_F(PreviewsUKMObserverTest, NoScriptSeen) { - RunTest(PreviewsType::NOSCRIPT, false /* lite_page_received */, - true /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); +TEST_F(PreviewsUKMObserverTest, LitePageRedirectSeen) { + RunTest(PreviewsType::NONE, false /* lite_page_received */, + true /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); NavigateToUntrackedUrl(); ValidateUKM(false /* server_lofi_expected */, false /* client_lofi_expected */, false /* lite_page_expected */, - true /* noscript_expected */, + true /* lite_page_redirect_expected */, + false /* noscript_expected */, false /* resource_loading_hints_expected */, 0 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); +} + +TEST_F(PreviewsUKMObserverTest, LitePageRedirectOptOut) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + {} /* enabled features */, + {previews::features:: + kAndroidOmniboxPreviewsBadge} /* disabled features */); + + RunTest(PreviewsType::LITE_PAGE_REDIRECT, false /* lite_page_received */, + true /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); + + observer()->BroadcastEventToObservers(PreviewsUITabHelper::OptOutEventKey()); + NavigateToUntrackedUrl(); + + ValidateUKM(false /* server_lofi_expected */, + false /* client_lofi_expected */, false /* lite_page_expected */, + true /* lite_page_redirect_expected */, + false /* noscript_expected */, + false /* resource_loading_hints_expected */, + 1 /* opt_out_value */, false /* origin_opt_out_expected */, + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); +} + +TEST_F(PreviewsUKMObserverTest, LitePageRedirectOptOutChip) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + {previews::features::kAndroidOmniboxPreviewsBadge} /* enabled features */, + {} /*disabled features */); + + RunTest(PreviewsType::LITE_PAGE_REDIRECT, false /* lite_page_received */, + true /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); + + observer()->BroadcastEventToObservers(PreviewsUITabHelper::OptOutEventKey()); + NavigateToUntrackedUrl(); + + ValidateUKM(false /* server_lofi_expected */, + false /* client_lofi_expected */, false /* lite_page_expected */, + true /* lite_page_redirect_expected */, + false /* noscript_expected */, + false /* resource_loading_hints_expected */, + 2 /* opt_out_value */, false /* origin_opt_out_expected */, + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); +} + +TEST_F(PreviewsUKMObserverTest, NoScriptSeen) { + RunTest(PreviewsType::NOSCRIPT, false /* lite_page_received */, + false /* lite_page_redirect_received */, true /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); + + NavigateToUntrackedUrl(); + + ValidateUKM( + false /* server_lofi_expected */, false /* client_lofi_expected */, + false /* lite_page_expected */, false /* lite_page_redirect_expected */, + true /* noscript_expected */, false /* resource_loading_hints_expected */, + 0 /* opt_out_value */, false /* origin_opt_out_expected */, + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, NoScriptOptOut) { @@ -313,18 +448,21 @@ kAndroidOmniboxPreviewsBadge} /* disabled features */); RunTest(PreviewsType::NOSCRIPT, false /* lite_page_received */, - true /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, true /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); observer()->BroadcastEventToObservers(PreviewsUITabHelper::OptOutEventKey()); NavigateToUntrackedUrl(); - ValidateUKM(false /* server_lofi_expected */, - false /* client_lofi_expected */, false /* lite_page_expected */, - true /* noscript_expected */, - false /* resource_loading_hints_expected */, - 1 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + ValidateUKM( + false /* server_lofi_expected */, false /* client_lofi_expected */, + false /* lite_page_expected */, false /* lite_page_redirect_expected */, + true /* noscript_expected */, false /* resource_loading_hints_expected */, + 1 /* opt_out_value */, false /* origin_opt_out_expected */, + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, NoScriptOptOutChip) { @@ -334,33 +472,39 @@ {} /*disabled features */); RunTest(PreviewsType::NOSCRIPT, false /* lite_page_received */, - true /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, true /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); observer()->BroadcastEventToObservers(PreviewsUITabHelper::OptOutEventKey()); NavigateToUntrackedUrl(); - ValidateUKM(false /* server_lofi_expected */, - false /* client_lofi_expected */, false /* lite_page_expected */, - true /* noscript_expected */, - false /* resource_loading_hints_expected */, - 2 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + ValidateUKM( + false /* server_lofi_expected */, false /* client_lofi_expected */, + false /* lite_page_expected */, false /* lite_page_redirect_expected */, + true /* noscript_expected */, false /* resource_loading_hints_expected */, + 2 /* opt_out_value */, false /* origin_opt_out_expected */, + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, ResourceLoadingHintsSeen) { RunTest(PreviewsType::RESOURCE_LOADING_HINTS, false /* lite_page_received */, - false /* noscript_on */, true /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + true /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); NavigateToUntrackedUrl(); - ValidateUKM(false /* server_lofi_expected */, - false /* client_lofi_expected */, false /* lite_page_expected */, - false /* noscript_expected */, - true /* resource_loading_hints_expected */, 0 /* opt_out_value */, - false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + ValidateUKM( + false /* server_lofi_expected */, false /* client_lofi_expected */, + false /* lite_page_expected */, false /* lite_page_redirect_expected */, + false /* noscript_expected */, true /* resource_loading_hints_expected */, + 0 /* opt_out_value */, false /* origin_opt_out_expected */, + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, ResourceLoadingHintsOptOut) { @@ -371,18 +515,21 @@ kAndroidOmniboxPreviewsBadge} /* disabled features */); RunTest(PreviewsType::RESOURCE_LOADING_HINTS, false /* lite_page_received */, - false /* noscript_on */, true /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + true /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); observer()->BroadcastEventToObservers(PreviewsUITabHelper::OptOutEventKey()); NavigateToUntrackedUrl(); - ValidateUKM(false /* server_lofi_expected */, - false /* client_lofi_expected */, false /* lite_page_expected */, - false /* noscript_expected */, - true /* resource_loading_hints_expected */, 1 /* opt_out_value */, - false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + ValidateUKM( + false /* server_lofi_expected */, false /* client_lofi_expected */, + false /* lite_page_expected */, false /* lite_page_redirect_expected */, + false /* noscript_expected */, true /* resource_loading_hints_expected */, + 1 /* opt_out_value */, false /* origin_opt_out_expected */, + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, ResourceLoadingHintsOptOutChip) { @@ -392,24 +539,29 @@ {} /*disabled features */); RunTest(PreviewsType::RESOURCE_LOADING_HINTS, false /* lite_page_received */, - false /* noscript_on */, true /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + true /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); observer()->BroadcastEventToObservers(PreviewsUITabHelper::OptOutEventKey()); NavigateToUntrackedUrl(); - ValidateUKM(false /* server_lofi_expected */, - false /* client_lofi_expected */, false /* lite_page_expected */, - false /* noscript_expected */, - true /* resource_loading_hints_expected */, 2 /* opt_out_value */, - false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + ValidateUKM( + false /* server_lofi_expected */, false /* client_lofi_expected */, + false /* lite_page_expected */, false /* lite_page_redirect_expected */, + false /* noscript_expected */, true /* resource_loading_hints_expected */, + 2 /* opt_out_value */, false /* origin_opt_out_expected */, + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, ClientLoFiSeen) { RunTest(PreviewsType::LOFI, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data = std::make_unique<data_reduction_proxy::DataReductionProxyData>(); @@ -438,10 +590,13 @@ NavigateToUntrackedUrl(); ValidateUKM(false /* server_lofi_expected */, true /* client_lofi_expected */, - false /* lite_page_expected */, false /* noscript_expected */, + false /* lite_page_expected */, + false /* lite_page_redirect_expected */, + false /* noscript_expected */, false /* resource_loading_hints_expected */, 0 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, ClientLoFiOptOut) { @@ -452,8 +607,10 @@ kAndroidOmniboxPreviewsBadge} /* disabled features */); RunTest(PreviewsType::LOFI, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data = std::make_unique<data_reduction_proxy::DataReductionProxyData>(); @@ -482,10 +639,13 @@ NavigateToUntrackedUrl(); ValidateUKM(false /* server_lofi_expected */, true /* client_lofi_expected */, - false /* lite_page_expected */, false /* noscript_expected */, + false /* lite_page_expected */, + false /* lite_page_redirect_expected */, + false /* noscript_expected */, false /* resource_loading_hints_expected */, 1 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, ClientLoFiOptOutChip) { @@ -495,8 +655,10 @@ {} /*disabled features */); RunTest(PreviewsType::LOFI, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data = std::make_unique<data_reduction_proxy::DataReductionProxyData>(); @@ -525,16 +687,21 @@ NavigateToUntrackedUrl(); ValidateUKM(false /* server_lofi_expected */, true /* client_lofi_expected */, - false /* lite_page_expected */, false /* noscript_expected */, + false /* lite_page_expected */, + false /* lite_page_redirect_expected */, + false /* noscript_expected */, false /* resource_loading_hints_expected */, 2 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, ServerLoFiSeen) { RunTest(PreviewsType::LOFI, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data = std::make_unique<data_reduction_proxy::DataReductionProxyData>(); @@ -563,10 +730,13 @@ NavigateToUntrackedUrl(); ValidateUKM(true /* server_lofi_expected */, false /* client_lofi_expected */, - false /* lite_page_expected */, false /* noscript_expected */, + false /* lite_page_expected */, + false /* lite_page_redirect_expected */, + false /* noscript_expected */, false /* resource_loading_hints_expected */, 0 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, ServerLoFiOptOut) { @@ -577,8 +747,10 @@ kAndroidOmniboxPreviewsBadge} /* disabled features */); RunTest(PreviewsType::LOFI, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data = std::make_unique<data_reduction_proxy::DataReductionProxyData>(); @@ -608,10 +780,13 @@ NavigateToUntrackedUrl(); ValidateUKM(true /* server_lofi_expected */, false /* client_lofi_expected */, - false /* lite_page_expected */, false /* noscript_expected */, + false /* lite_page_expected */, + false /* lite_page_redirect_expected */, + false /* noscript_expected */, false /* resource_loading_hints_expected */, 1 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, ServerLoFiOptOutChip) { @@ -621,8 +796,10 @@ {} /*disabled features */); RunTest(PreviewsType::LOFI, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data = std::make_unique<data_reduction_proxy::DataReductionProxyData>(); @@ -652,16 +829,21 @@ NavigateToUntrackedUrl(); ValidateUKM(true /* server_lofi_expected */, false /* client_lofi_expected */, - false /* lite_page_expected */, false /* noscript_expected */, + false /* lite_page_expected */, + false /* lite_page_redirect_expected */, + false /* noscript_expected */, false /* resource_loading_hints_expected */, 2 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, BothLoFiSeen) { RunTest(PreviewsType::LOFI, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data1 = std::make_unique<data_reduction_proxy::DataReductionProxyData>(); @@ -695,10 +877,13 @@ NavigateToUntrackedUrl(); ValidateUKM(true /* server_lofi_expected */, true /* client_lofi_expected */, - false /* lite_page_expected */, false /* noscript_expected */, + false /* lite_page_expected */, + false /* lite_page_redirect_expected */, + false /* noscript_expected */, false /* resource_loading_hints_expected */, 0 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, BothLoFiOptOut) { @@ -709,8 +894,10 @@ kAndroidOmniboxPreviewsBadge} /* disabled features */); RunTest(PreviewsType::LOFI, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data1 = std::make_unique<data_reduction_proxy::DataReductionProxyData>(); @@ -744,10 +931,13 @@ observer()->BroadcastEventToObservers(PreviewsUITabHelper::OptOutEventKey()); NavigateToUntrackedUrl(); ValidateUKM(true /* server_lofi_expected */, true /* client_lofi_expected */, - false /* lite_page_expected */, false /* noscript_expected */, + false /* lite_page_expected */, + false /* lite_page_redirect_expected */, + false /* noscript_expected */, false /* resource_loading_hints_expected */, 1 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, BothLoFiOptOutChip) { @@ -757,8 +947,10 @@ {} /*disabled features */); RunTest(PreviewsType::LOFI, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data1 = std::make_unique<data_reduction_proxy::DataReductionProxyData>(); @@ -792,70 +984,111 @@ observer()->BroadcastEventToObservers(PreviewsUITabHelper::OptOutEventKey()); NavigateToUntrackedUrl(); ValidateUKM(true /* server_lofi_expected */, true /* client_lofi_expected */, - false /* lite_page_expected */, false /* noscript_expected */, + false /* lite_page_expected */, + false /* lite_page_redirect_expected */, + false /* noscript_expected */, false /* resource_loading_hints_expected */, 2 /* opt_out_value */, false /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, OriginOptOut) { RunTest(PreviewsType::NONE, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - true /* origin_opt_out */, false /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, true /* origin_opt_out */, + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); NavigateToUntrackedUrl(); ValidateUKM(false /* server_lofi_expected */, false /* client_lofi_expected */, false /* lite_page_expected */, + false /* lite_page_redirect_expected */, false /* noscript_expected */, false /* resource_loading_hints_expected */, 0 /* opt_out_value */, true /* origin_opt_out_expected */, - false /* save_data_enabled_expected */); + false /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, DataSaverEnabled) { RunTest(PreviewsType::NONE, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, true /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + true /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); NavigateToUntrackedUrl(); ValidateUKM(false /* server_lofi_expected */, false /* client_lofi_expected */, false /* lite_page_expected */, + false /* lite_page_redirect_expected */, false /* noscript_expected */, false /* resource_loading_hints_expected */, 0 /* opt_out_value */, false /* origin_opt_out_expected */, - true /* save_data_enabled_expected */); + true /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); +} + +// Navigation restart penalty can occur independently of a preview being +// committed so we do not consider the opt out tests here. +TEST_F(PreviewsUKMObserverTest, NavigationRestartPenaltySeen) { + RunTest( + PreviewsType::NONE, false /* lite_page_received */, + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + false /* save_data_enabled */, + base::TimeDelta::FromMilliseconds(1337) /* navigation_restart_penalty */); + + NavigateToUntrackedUrl(); + + ValidateUKM( + false /* server_lofi_expected */, false /* client_lofi_expected */, + false /* lite_page_expected */, false /* lite_page_redirect_expected */, + false /* noscript_expected */, + false /* resource_loading_hints_expected */, 0 /* opt_out_value */, + false /* origin_opt_out_expected */, + false /* save_data_enabled_expected */, + base::TimeDelta::FromMilliseconds(1337) /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, CheckReportingForHidden) { RunTest(PreviewsType::NONE, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, true /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + true /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); web_contents()->WasHidden(); ValidateUKM(false /* server_lofi_expected */, false /* client_lofi_expected */, false /* lite_page_expected */, + false /* lite_page_redirect_expected */, false /* noscript_expected */, false /* resource_loading_hints_expected */, 0 /* opt_out_value */, false /* origin_opt_out_expected */, - true /* save_data_enabled_expected */); + true /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, CheckReportingForFlushMetrics) { RunTest(PreviewsType::NONE, false /* lite_page_received */, - false /* noscript_on */, false /* resource_loading_hints_on */, - false /* origin_opt_out */, true /* save_data_enabled */); + false /* lite_page_redirect_received */, false /* noscript_on */, + false /* resource_loading_hints_on */, false /* origin_opt_out */, + true /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); SimulateAppEnterBackground(); ValidateUKM(false /* server_lofi_expected */, false /* client_lofi_expected */, false /* lite_page_expected */, + false /* lite_page_redirect_expected */, false /* noscript_expected */, false /* resource_loading_hints_expected */, 0 /* opt_out_value */, false /* origin_opt_out_expected */, - true /* save_data_enabled_expected */); + true /* save_data_enabled_expected */, + base::nullopt /* navigation_restart_penalty */); } TEST_F(PreviewsUKMObserverTest, TestPageEndReasonUMA) { @@ -866,9 +1099,11 @@ continue; base::HistogramTester tester; - RunTest(type, false /* lite_page_received */, false /* noscript_on */, + RunTest(type, false /* lite_page_received */, + false /* lite_page_redirect_received */, false /* noscript_on */, false /* resource_loading_hints_on */, false /* origin_opt_out */, - false /* save_data_enabled */); + false /* save_data_enabled */, + base::nullopt /* navigation_restart_penalty */); NavigateToUntrackedUrl();
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc index f97cc99..2b061499 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -78,7 +78,6 @@ #include "third_party/blink/public/web/web_context_menu_data.h" #include "ui/base/emoji/emoji_panel_helper.h" #include "ui/base/models/menu_model.h" -#include "ui/base/ui_base_features.h" #if defined(OS_CHROMEOS) #include "ash/public/cpp/window_properties.h" @@ -522,10 +521,7 @@ } IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, - ContextMenuForEmojiPanel_Enabled) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kEnableEmojiContextMenu); - + ContextMenuForEmojiPanel_Editable) { content::ContextMenuParams params; params.is_editable = true; @@ -539,10 +535,7 @@ } IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, - ContextMenuForEmojiPanel_Enabled_NonEditable) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kEnableEmojiContextMenu); - + ContextMenuForEmojiPanel_NonEditable) { content::ContextMenuParams params; params.is_editable = false; @@ -555,23 +548,6 @@ EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_EMOJI)); } -IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, - ContextMenuForEmojiPanel_Disabled) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndDisableFeature(features::kEnableEmojiContextMenu); - - content::ContextMenuParams params; - params.is_editable = true; - - TestRenderViewContextMenu menu( - browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(), - params); - menu.Init(); - - // If the feature is disabled, the emoji context menu should never be present. - EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_EMOJI)); -} - IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, CopyLinkTextMouse) { std::unique_ptr<TestRenderViewContextMenu> menu = CreateContextMenu( GURL("http://www.google.com/"), GURL("http://www.google.com/"),
diff --git a/chrome/browser/resource_coordinator/tab_load_tracker.cc b/chrome/browser/resource_coordinator/tab_load_tracker.cc index 2d60841..ee69f1b 100644 --- a/chrome/browser/resource_coordinator/tab_load_tracker.cc +++ b/chrome/browser/resource_coordinator/tab_load_tracker.cc
@@ -327,6 +327,8 @@ // checking for specific cases where |web_contents| is not a ui tab. if (prerender::PrerenderContents::FromWebContents(web_contents) != nullptr) return false; + if (web_contents->GetOuterWebContents()) + return false; return true; }
diff --git a/chrome/browser/resources/print_preview/data/destination.js b/chrome/browser/resources/print_preview/data/destination.js index 7ba5afb5..5580239c5 100644 --- a/chrome/browser/resources/print_preview/data/destination.js +++ b/chrome/browser/resources/print_preview/data/destination.js
@@ -633,7 +633,8 @@ /** * @return {string} Human readable status for a destination that is offline - * or has a bad certificate. */ + * or has a bad certificate. + */ get connectionStatusText() { if (!this.isOfflineOrInvalid) { return ''; @@ -688,52 +689,6 @@ return 'print-preview:printer-shared'; } - /** @return {string} Relative URL of the destination's icon. */ - get iconUrl() { - if (this.id_ == Destination.GooglePromotedId.DOCS) { - return Destination.IconUrl_.DOCS; - } - if (this.id_ == Destination.GooglePromotedId.SAVE_AS_PDF) { - return Destination.IconUrl_.PDF; - } - if (this.isEnterprisePrinter) { - return Destination.IconUrl_.ENTERPRISE; - } - if (this.isLocal) { - return Destination.IconUrl_.LOCAL_1X; - } - if (this.type_ == print_preview.DestinationType.MOBILE && this.isOwned_) { - return Destination.IconUrl_.MOBILE; - } - if (this.type_ == print_preview.DestinationType.MOBILE) { - return Destination.IconUrl_.MOBILE_SHARED; - } - if (this.isOwned_) { - return Destination.IconUrl_.CLOUD_1X; - } - return Destination.IconUrl_.CLOUD_SHARED_1X; - } - - /** - * @return {string} The srcset="" attribute of a destination. Generally used - * for a 2x (e.g. HiDPI) icon. Can be empty or of the format '<url> 2x'. - */ - get srcSet() { - let srcSetIcon = ''; - const iconUrl = this.iconUrl; - if (iconUrl == Destination.IconUrl_.LOCAL_1X) { - srcSetIcon = Destination.IconUrl_.LOCAL_2X; - } else if (iconUrl == Destination.IconUrl_.CLOUD_1X) { - srcSetIcon = Destination.IconUrl_.CLOUD_2X; - } else if (iconUrl == Destination.IconUrl_.CLOUD_SHARED_1X) { - srcSetIcon = Destination.IconUrl_.CLOUD_SHARED_2X; - } - if (srcSetIcon) { - srcSetIcon += ' 2x'; - } - return srcSetIcon; - } - /** * @return {!Array<string>} Properties (besides display name) to match * search queries against. @@ -928,25 +883,6 @@ SAVE_AS_PDF: 'Save as PDF' }; - /** - * Enumeration of relative icon URLs for various types of destinations. - * @enum {string} - * @private - */ - Destination.IconUrl_ = { - CLOUD_1X: 'images/1x/printer.png', - CLOUD_2X: 'images/2x/printer.png', - CLOUD_SHARED_1X: 'images/1x/printer_shared.png', - CLOUD_SHARED_2X: 'images/2x/printer_shared.png', - LOCAL_1X: 'images/1x/printer.png', - LOCAL_2X: 'images/2x/printer.png', - MOBILE: 'images/mobile.png', - MOBILE_SHARED: 'images/mobile_shared.png', - PDF: 'images/pdf.png', - DOCS: 'images/google_doc.png', - ENTERPRISE: 'images/business.svg' - }; - // Export return { Destination: Destination,
diff --git a/chrome/browser/resources/settings/device_page/device_page.html b/chrome/browser/resources/settings/device_page/device_page.html index 1785424..727746e 100644 --- a/chrome/browser/resources/settings/device_page/device_page.html +++ b/chrome/browser/resources/settings/device_page/device_page.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> @@ -22,55 +23,51 @@ <settings-animated-pages id="pages" section="device" focus-config="[[focusConfig_]]"> <div id="main" route-path="default"> - <div id="pointersRow" class="settings-box first" - on-click="onPointersTap_" actionable> - <div class="start"> - [[getPointersTitle_(hasMouse_, hasTouchpad_)]] - </div> - <paper-icon-button-light class="subpage-arrow"> - <button - aria-label$="[[getPointersTitle_(hasMouse_, hasTouchpad_)]]"> - </button> - </paper-icon-button-light> - </div> - <div id="keyboardRow" class="settings-box" on-click="onKeyboardTap_" - actionable> - <div class="start">$i18n{keyboardTitle}</div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{keyboardTitle}"></button> - </paper-icon-button-light> - </div> + <cr-link-row + icon-class="subpage-arrow" + id="pointersRow" + label="[[getPointersTitle_(hasMouse_, hasTouchpad_)]]" + on-click="onPointersTap_"> + </cr-link-row> + <cr-link-row + class="hr" + icon-class="subpage-arrow" + id="keyboardRow" + label="$i18n{keyboardTitle}" + on-click="onKeyboardTap_"> + </cr-link-row> <template is="dom-if" if="[[hasStylus_]]"> - <div id="stylusRow" class="settings-box" on-click="onStylusTap_" - actionable> - <div class="start">$i18n{stylusTitle}</div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{stylusTitle}"></button> - </paper-icon-button-light> - </div> + <cr-link-row + class="hr" + icon-class="subpage-arrow" + id="stylusRow" + label="$i18n{stylusTitle}" + on-click="onStylusTap_"> + </cr-link-row> </template> - <div id="displayRow" class="settings-box" on-click="onDisplayTap_" - actionable> - <div class="start">$i18n{displayTitle}</div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{displayTitle}"></button> - </paper-icon-button-light> - </div> - <div id="storageRow" hidden="[[hideStorageInfo_]]" class="settings-box" - on-click="onStorageTap_" actionable> - <div class="start">$i18n{storageTitle}</div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{storageTitle}"></button> - </paper-icon-button-light> - </div> + <cr-link-row + class="hr" + icon-class="subpage-arrow" + id="displayRow" + label="$i18n{displayTitle}" + on-click="onDisplayTap_"> + </cr-link-row> + <cr-link-row + class="hr" + hidden="[[hideStorageInfo_]]" + icon-class="subpage-arrow" + id="storageRow" + label="$i18n{storageTitle}" + on-click="onStorageTap_"> + </cr-link-row> <template is="dom-if" if="[[enablePowerSettings_]]"> - <div id="powerRow" class="settings-box" on-click="onPowerTap_" - actionable> - <div class="start">$i18n{powerTitle}</div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{powerTitle}"></button> - </paper-icon-button-light> - </div> + <cr-link-row + class="hr" + icon-class="subpage-arrow" + id="powerRow" + label="$i18n{powerTitle}" + on-click="onPowerTap_"> + </cr-link-row> </template> </div> <template is="dom-if" route-path="/pointer-overlay">
diff --git a/chrome/browser/resources/settings/device_page/device_page.js b/chrome/browser/resources/settings/device_page/device_page.js index 38bb4866..b201a446 100644 --- a/chrome/browser/resources/settings/device_page/device_page.js +++ b/chrome/browser/resources/settings/device_page/device_page.js
@@ -74,32 +74,22 @@ value: function() { const map = new Map(); if (settings.routes.POINTERS) { - map.set( - settings.routes.POINTERS.path, - '#pointersRow .subpage-arrow button'); + map.set(settings.routes.POINTERS.path, '#pointersRow'); } if (settings.routes.KEYBOARD) { - map.set( - settings.routes.KEYBOARD.path, - '#keyboardRow .subpage-arrow button'); + map.set(settings.routes.KEYBOARD.path, '#keyboardRow'); } if (settings.routes.STYLUS) { - map.set( - settings.routes.STYLUS.path, '#stylusRow .subpage-arrow button'); + map.set(settings.routes.STYLUS.path, '#stylusRow'); } if (settings.routes.DISPLAY) { - map.set( - settings.routes.DISPLAY.path, - '#displayRow .subpage-arrow button'); + map.set(settings.routes.DISPLAY.path, '#displayRow'); } if (settings.routes.STORAGE) { - map.set( - settings.routes.STORAGE.path, - '#storageRow .subpage-arrow button'); + map.set(settings.routes.STORAGE.path, '#storageRow'); } if (settings.routes.POWER) { - map.set( - settings.routes.POWER.path, '#powerRow .subpage-arrow button'); + map.set(settings.routes.POWER.path, '#powerRow'); } return map; },
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 98b2856..32c95502 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -22,13 +22,6 @@ import("//ui/base/ui_features.gni") import("//ui/views/features.gni") -config("ui_warnings") { - if (is_mac) { - # TODO(thakis): Remove this once http://crbug.com/383820 is figured out - cflags = [ "-Wno-nonnull" ] - } -} - # Use a static library here because many test binaries depend on this but don't # require many files from it. This makes linking more efficient. jumbo_split_static_library("ui") { @@ -347,7 +340,6 @@ libs = [] configs += [ - ":ui_warnings", "//build/config:precompiled_headers", "//build/config/compiler:wexit_time_destructors", ] @@ -2120,6 +2112,7 @@ "//third_party/google_toolbox_for_mac", "//third_party/mozilla", "//ui/accelerated_widget_mac:accelerated_widget_mac", + "//ui/views_bridge_mac", ] include_dirs = [ "$target_gen_dir" ] libs += [
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc index 3b6f6f6..c5ce41f 100644 --- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -152,6 +152,9 @@ void ChromeBrowserMainExtraPartsAsh::ServiceManagerConnectionStarted( content::ServiceManagerConnection* connection) { if (features::IsMultiProcessMash()) { + // Mash and SingleProcessMash cannot be enabled simultaneously. + DCHECK(!features::IsSingleProcessMash()); + // ash::Shell will not be created because ash is running out-of-process. ash::Shell::SetIsBrowserProcessWithMash(); }
diff --git a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h index 04a258a..79235c50 100644 --- a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h +++ b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h
@@ -10,7 +10,10 @@ #include "base/logging.h" #include "base/mac/scoped_nsobject.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "components/app_modal/native_app_modal_dialog.h" +#include "ui/views_bridge_mac/alert.h" +#include "ui/views_bridge_mac/mojo/alert.mojom.h" class PopunderPreventer; @@ -18,19 +21,10 @@ class JavaScriptAppModalDialog; } -#if __OBJC__ -@class NSAlert; -@class JavaScriptAppModalDialogHelper; -#else -class NSAlert; -class JavaScriptAppModalDialogHelper; -#endif - class JavaScriptAppModalDialogCocoa : public app_modal::NativeAppModalDialog { public: explicit JavaScriptAppModalDialogCocoa( app_modal::JavaScriptAppModalDialog* dialog); - ~JavaScriptAppModalDialogCocoa() override; // Overridden from NativeAppModalDialog: int GetAppModalDialogButtons() const override; @@ -46,17 +40,30 @@ } private: - // Returns the NSAlert associated with the modal dialog. - NSAlert* GetAlert() const; + ~JavaScriptAppModalDialogCocoa() override; + + // Return the parameters to use for the alert. + views_bridge_mac::mojom::AlertBridgeInitParamsPtr GetAlertParams(); + + // Called when the alert completes. Deletes |this|. + void OnAlertFinished(views_bridge_mac::mojom::AlertDisposition disposition, + const base::string16& prompt_text, + bool suppress_js_messages); + + // Called if there is an error connecting to the alert process. Deletes + // |this|. + void OnConnectionError(); + + // Mojo interface to the NSAlert. + views_bridge_mac::mojom::AlertBridgePtr alert_bridge_; std::unique_ptr<app_modal::JavaScriptAppModalDialog> dialog_; std::unique_ptr<PopunderPreventer> popunder_preventer_; - // Created in the constructor and destroyed in the destructor. - base::scoped_nsobject<JavaScriptAppModalDialogHelper> helper_; + int num_buttons_ = 0; + bool is_showing_ = false; - bool is_showing_; - + base::WeakPtrFactory<JavaScriptAppModalDialogCocoa> weak_factory_; DISALLOW_COPY_AND_ASSIGN(JavaScriptAppModalDialogCocoa); };
diff --git a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm index 2a520cb6..78fd8865 100644 --- a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm +++ b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm
@@ -7,12 +7,9 @@ #import <Cocoa/Cocoa.h> #include <stddef.h> -#include "base/i18n/rtl.h" #include "base/logging.h" -#import "base/mac/foundation_util.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/strings/sys_string_conversions.h" #import "chrome/browser/chrome_browser_application_mac.h" #include "chrome/browser/ui/blocked_content/popunder_preventer.h" #include "chrome/browser/ui/javascript_dialogs/chrome_javascript_native_dialog_factory.h" @@ -22,381 +19,99 @@ #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" -#include "ui/base/l10n/l10n_util_mac.h" +#include "ui/accelerated_widget_mac/window_resize_helper_mac.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_types.h" -#include "ui/gfx/text_elider.h" #include "ui/strings/grit/ui_strings.h" +#include "ui/views/cocoa/bridge_factory_host.h" +#include "ui/views/cocoa/bridged_native_widget_host_impl.h" +#include "ui/views_bridge_mac/alert.h" -namespace { - -const int kSlotsPerLine = 50; -const int kMessageTextMaxSlots = 2000; - -} // namespace - -// Helper object that receives the notification that the dialog/sheet is -// going away. Is responsible for cleaning itself up. -@interface JavaScriptAppModalDialogHelper : NSObject<NSAlertDelegate> { - @private - base::scoped_nsobject<NSAlert> alert_; - JavaScriptAppModalDialogCocoa* nativeDialog_; // Weak. - base::scoped_nsobject<NSTextField> textField_; - BOOL alertShown_; -} - -// Creates an NSAlert if one does not already exist. Otherwise returns the -// existing NSAlert. -- (NSAlert*)alert; -- (void)addTextFieldWithPrompt:(NSString*)prompt; - -// Presents an AppKit blocking dialog. -- (void)showAlert; - -// Selects the first button of the alert, which should accept it. -- (void)acceptAlert; - -// Selects the second button of the alert, which should cancel it. -- (void)cancelAlert; - -// Closes the window, and the alert along with it. -- (void)closeWindow; - -// Designated initializer. -- (instancetype)initWithNativeDialog:(JavaScriptAppModalDialogCocoa*)dialog; - -@end - -@implementation JavaScriptAppModalDialogHelper - -- (instancetype)init { - NOTREACHED(); - return nil; -} - -- (instancetype)initWithNativeDialog:(JavaScriptAppModalDialogCocoa*)dialog { - DCHECK(dialog); - self = [super init]; - if (self) - nativeDialog_ = dialog; - return self; -} - -- (NSAlert*)alert { - if (!alert_) { - alert_.reset([[NSAlert alloc] init]); - if (!nativeDialog_->dialog()->is_before_unload_dialog()) { - // Set a blank icon for dialogs with text provided by the page. - // "onbeforeunload" dialogs don't have text provided by the page, so it's - // OK to use the app icon. - NSImage* image = - [[[NSImage alloc] initWithSize:NSMakeSize(1, 1)] autorelease]; - [alert_ setIcon:image]; - } - } - return alert_; -} - -- (void)addTextFieldWithPrompt:(NSString*)prompt { - DCHECK(!textField_); - textField_.reset( - [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 22)]); - [[textField_ cell] setLineBreakMode:NSLineBreakByTruncatingTail]; - [[self alert] setAccessoryView:textField_]; - [[alert_ window] setInitialFirstResponder:textField_]; - - [textField_ setStringValue:prompt]; -} - -// |contextInfo| is the JavaScriptAppModalDialogCocoa that owns us. -- (void)alertDidEnd:(NSAlert*)alert - returnCode:(int)returnCode - contextInfo:(void*)contextInfo { - switch (returnCode) { - case NSAlertFirstButtonReturn: { // OK - [self sendAcceptToNativeDialog]; - break; - } - case NSAlertSecondButtonReturn: { // Cancel - // If the user wants to stay on this page, stop quitting (if a quit is in - // progress). - [self sendCancelToNativeDialog]; - break; - } - case NSRunStoppedResponse: { // Window was closed underneath us - // Need to call OnClose() because there is some cleanup that needs - // to be done. It won't call back to the javascript since the - // JavaScriptAppModalDialog knows that the WebContents was destroyed. - [self sendCloseToNativeDialog]; - break; - } - default: { - NOTREACHED(); - } - } -} - -- (void)showAlert { - DCHECK(nativeDialog_); - DCHECK(!alertShown_); - alertShown_ = YES; - NSAlert* alert = [self alert]; - - [alert layout]; - [[alert window] recalculateKeyViewLoop]; - - [alert beginSheetModalForWindow:nil // nil here makes it app-modal - modalDelegate:self - didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) - contextInfo:NULL]; -} - -- (void)acceptAlert { - DCHECK(nativeDialog_); - if (!alertShown_) { - [self sendAcceptToNativeDialog]; - return; - } - NSButton* first = [[[self alert] buttons] objectAtIndex:0]; - [first performClick:nil]; -} - -- (void)cancelAlert { - DCHECK(nativeDialog_); - if (!alertShown_) { - [self sendCancelToNativeDialog]; - return; - } - DCHECK_GE([[[self alert] buttons] count], 2U); - NSButton* second = [[[self alert] buttons] objectAtIndex:1]; - [second performClick:nil]; -} - -- (void)closeWindow { - DCHECK(nativeDialog_); - if (!alertShown_) { - [self sendCloseToNativeDialog]; - return; - } - [NSApp endSheet:[[self alert] window]]; -} - -- (void)sendAcceptToNativeDialog { - DCHECK(nativeDialog_); - nativeDialog_->dialog()->OnAccept([self input], [self shouldSuppress]); - [self destroyNativeDialog]; -} - -- (void)sendCancelToNativeDialog { - DCHECK(nativeDialog_); - // If the user wants to stay on this page, stop quitting (if a quit is in - // progress). - if (nativeDialog_->dialog()->is_before_unload_dialog()) - chrome_browser_application_mac::CancelTerminate(); - nativeDialog_->dialog()->OnCancel([self shouldSuppress]); - [self destroyNativeDialog]; -} - -- (void)sendCloseToNativeDialog { - DCHECK(nativeDialog_); - nativeDialog_->dialog()->OnClose(); - [self destroyNativeDialog]; -} - -- (void)destroyNativeDialog { - DCHECK(nativeDialog_); - JavaScriptAppModalDialogCocoa* nativeDialog = nativeDialog_; - nativeDialog_ = nil; // Need to fail on DCHECK if something wrong happens. - delete nativeDialog; // Careful, this will delete us. -} - -- (base::string16)input { - if (textField_) - return base::SysNSStringToUTF16([textField_ stringValue]); - return base::string16(); -} - -- (bool)shouldSuppress { - if ([[self alert] showsSuppressionButton]) - return [[[self alert] suppressionButton] state] == NSOnState; - return false; -} - -@end +using views_bridge_mac::mojom::AlertDisposition; //////////////////////////////////////////////////////////////////////////////// -// JavaScriptAppModalDialogCocoa, public: +// JavaScriptAppModalDialogCocoa: JavaScriptAppModalDialogCocoa::JavaScriptAppModalDialogCocoa( app_modal::JavaScriptAppModalDialog* dialog) : dialog_(dialog), popunder_preventer_(new PopunderPreventer(dialog->web_contents())), - is_showing_(false) { + weak_factory_(this) {} + +JavaScriptAppModalDialogCocoa::~JavaScriptAppModalDialogCocoa() {} + +views_bridge_mac::mojom::AlertBridgeInitParamsPtr +JavaScriptAppModalDialogCocoa::GetAlertParams() { + views_bridge_mac::mojom::AlertBridgeInitParamsPtr params = + views_bridge_mac::mojom::AlertBridgeInitParams::New(); + params->title = dialog_->title(); + params->message_text = dialog_->message_text(); + + // Set a blank icon for dialogs with text provided by the page. + // "onbeforeunload" dialogs don't have text provided by the page, so it's + // OK to use the app icon. + params->hide_application_icon = !dialog_->is_before_unload_dialog(); + // Determine the names of the dialog buttons based on the flags. "Default" // is the OK button. "Other" is the cancel button. We don't use the // "Alternate" button in NSRunAlertPanel. - NSString* default_button = l10n_util::GetNSStringWithFixup(IDS_APP_OK); - NSString* other_button = l10n_util::GetNSStringWithFixup(IDS_APP_CANCEL); - bool text_field = false; - bool one_button = false; + params->primary_button_text = l10n_util::GetStringUTF16(IDS_APP_OK); switch (dialog_->javascript_dialog_type()) { case content::JAVASCRIPT_DIALOG_TYPE_ALERT: - one_button = true; + num_buttons_ = 1; break; case content::JAVASCRIPT_DIALOG_TYPE_CONFIRM: + num_buttons_ = 2; if (dialog_->is_before_unload_dialog()) { if (dialog_->is_reload()) { - default_button = l10n_util::GetNSStringWithFixup( + params->primary_button_text = l10n_util::GetStringUTF16( IDS_BEFORERELOAD_MESSAGEBOX_OK_BUTTON_LABEL); } else { - default_button = l10n_util::GetNSStringWithFixup( + params->primary_button_text = l10n_util::GetStringUTF16( IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL); } } + params->secondary_button_text.emplace( + l10n_util::GetStringUTF16(IDS_APP_CANCEL)); break; case content::JAVASCRIPT_DIALOG_TYPE_PROMPT: - text_field = true; + num_buttons_ = 2; + params->secondary_button_text.emplace( + l10n_util::GetStringUTF16(IDS_APP_CANCEL)); + params->text_field_text.emplace(dialog_->default_prompt_text()); break; default: NOTREACHED(); } + return params; +} - // Create a helper which will receive the sheet ended selector. It will - // delete itself when done. - helper_.reset( - [[JavaScriptAppModalDialogHelper alloc] initWithNativeDialog:this]); - - // Show the modal dialog. - if (text_field) { - [helper_ addTextFieldWithPrompt:base::SysUTF16ToNSString( - dialog_->default_prompt_text())]; - } - [GetAlert() setDelegate:helper_]; - NSString* informative_text = - base::SysUTF16ToNSString(dialog_->message_text()); - - // Truncate long JS alerts - crbug.com/331219 - NSCharacterSet* newline_char_set = [NSCharacterSet newlineCharacterSet]; - for (size_t index = 0, slots_count = 0; index < informative_text.length; - ++index) { - unichar current_char = [informative_text characterAtIndex:index]; - if ([newline_char_set characterIsMember:current_char]) - slots_count += kSlotsPerLine; - else - slots_count++; - if (slots_count > kMessageTextMaxSlots) { - base::string16 info_text = base::SysNSStringToUTF16(informative_text); - informative_text = base::SysUTF16ToNSString( - gfx::TruncateString(info_text, index, gfx::WORD_BREAK)); +void JavaScriptAppModalDialogCocoa::OnAlertFinished( + AlertDisposition disposition, + const base::string16& text_field_value, + bool check_box_value) { + switch (disposition) { + case AlertDisposition::PRIMARY_BUTTON: + dialog_->OnAccept(text_field_value, check_box_value); break; - } + case AlertDisposition::SECONDARY_BUTTON: + // If the user wants to stay on this page, stop quitting (if a quit is in + // progress). + if (dialog_->is_before_unload_dialog()) + chrome_browser_application_mac::CancelTerminate(); + dialog_->OnCancel(check_box_value); + break; + case AlertDisposition::CLOSE: + dialog_->OnClose(); + break; } - - [GetAlert() setInformativeText:informative_text]; - NSString* message_text = - base::SysUTF16ToNSString(dialog_->title()); - [GetAlert() setMessageText:message_text]; - [GetAlert() addButtonWithTitle:default_button]; - if (!one_button) { - NSButton* other = [GetAlert() addButtonWithTitle:other_button]; - [other setKeyEquivalent:@"\e"]; - } - if (dialog_->display_suppress_checkbox()) { - [GetAlert() setShowsSuppressionButton:YES]; - NSString* suppression_title = l10n_util::GetNSStringWithFixup( - IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION); - [[GetAlert() suppressionButton] setTitle:suppression_title]; - } - - // Fix RTL dialogs. - // - // Mac OS X will always display NSAlert strings as LTR. A workaround is to - // manually set the text as attributed strings in the implementing - // NSTextFields. This is a basic correctness issue. - // - // In addition, for readability, the overall alignment is set based on the - // directionality of the first strongly-directional character. - // - // If the dialog fields are selectable then they will scramble when clicked. - // Therefore, selectability is disabled. - // - // See http://crbug.com/70806 for more details. - - bool message_has_rtl = - base::i18n::StringContainsStrongRTLChars(dialog_->title()); - bool informative_has_rtl = - base::i18n::StringContainsStrongRTLChars(dialog_->message_text()); - - NSTextField* message_text_field = nil; - NSTextField* informative_text_field = nil; - if (message_has_rtl || informative_has_rtl) { - // Force layout of the dialog. NSAlert leaves its dialog alone once laid - // out; if this is not done then all the modifications that are to come will - // be un-done when the dialog is finally displayed. - [GetAlert() layout]; - - // Locate the NSTextFields that implement the text display. These are - // actually available as the ivars |_messageField| and |_informationField| - // of the NSAlert, but it is safer (and more forward-compatible) to search - // for them in the subviews. - for (NSView* view in [[[GetAlert() window] contentView] subviews]) { - NSTextField* text_field = base::mac::ObjCCast<NSTextField>(view); - if ([[text_field stringValue] isEqualTo:message_text]) - message_text_field = text_field; - else if ([[text_field stringValue] isEqualTo:informative_text]) - informative_text_field = text_field; - } - - // This may fail in future OS releases, but it will still work for shipped - // versions of Chromium. - DCHECK(message_text_field); - DCHECK(informative_text_field); - } - - if (message_has_rtl && message_text_field) { - base::scoped_nsobject<NSMutableParagraphStyle> alignment( - [[NSParagraphStyle defaultParagraphStyle] mutableCopy]); - [alignment setAlignment:NSRightTextAlignment]; - - NSDictionary* alignment_attributes = - @{ NSParagraphStyleAttributeName : alignment }; - base::scoped_nsobject<NSAttributedString> attr_string( - [[NSAttributedString alloc] initWithString:message_text - attributes:alignment_attributes]); - - [message_text_field setAttributedStringValue:attr_string]; - [message_text_field setSelectable:NO]; - } - - if (informative_has_rtl && informative_text_field) { - base::i18n::TextDirection direction = - base::i18n::GetFirstStrongCharacterDirection(dialog_->message_text()); - base::scoped_nsobject<NSMutableParagraphStyle> alignment( - [[NSParagraphStyle defaultParagraphStyle] mutableCopy]); - [alignment setAlignment: - (direction == base::i18n::RIGHT_TO_LEFT) ? NSRightTextAlignment - : NSLeftTextAlignment]; - - NSDictionary* alignment_attributes = - @{ NSParagraphStyleAttributeName : alignment }; - base::scoped_nsobject<NSAttributedString> attr_string( - [[NSAttributedString alloc] initWithString:informative_text - attributes:alignment_attributes]); - - [informative_text_field setAttributedStringValue:attr_string]; - [informative_text_field setSelectable:NO]; - } + delete this; } -JavaScriptAppModalDialogCocoa::~JavaScriptAppModalDialogCocoa() { - [NSObject cancelPreviousPerformRequestsWithTarget:helper_.get()]; -} - -//////////////////////////////////////////////////////////////////////////////// -// JavaScriptAppModalDialogCocoa, private: - -NSAlert* JavaScriptAppModalDialogCocoa::GetAlert() const { - return [helper_ alert]; +void JavaScriptAppModalDialogCocoa::OnConnectionError() { + dialog()->OnClose(); + delete this; } //////////////////////////////////////////////////////////////////////////////// @@ -405,8 +120,7 @@ int JavaScriptAppModalDialogCocoa::GetAppModalDialogButtons() const { // From the above, it is the case that if there is 1 button, it is always the // OK button. The second button, if it exists, is always the Cancel button. - int num_buttons = [[GetAlert() buttons] count]; - switch (num_buttons) { + switch (num_buttons_) { case 1: return ui::DIALOG_BUTTON_OK; case 2: @@ -420,28 +134,54 @@ void JavaScriptAppModalDialogCocoa::ShowAppModalDialog() { is_showing_ = true; - // Dispatch the method to show the alert back to the top of the CFRunLoop. - // This fixes an interaction bug with NSSavePanel. http://crbug.com/375785 - // When this object is destroyed, outstanding performSelector: requests - // should be cancelled. - [helper_.get() performSelector:@selector(showAlert) - withObject:nil - afterDelay:0]; + views_bridge_mac::mojom::AlertBridgeRequest bridge_request = + mojo::MakeRequest(&alert_bridge_); + alert_bridge_.set_connection_error_handler( + base::BindOnce(&JavaScriptAppModalDialogCocoa::OnConnectionError, + weak_factory_.GetWeakPtr())); + // If the alert is from a window that is out of process then use the + // views::BridgeFactoryHost for that window to create the alert. Otherwise + // create an AlertBridge in-process (but still communicate with it over + // mojo). + auto* bridged_native_widget_host = + views::BridgedNativeWidgetHostImpl::GetFromNativeView( + dialog_->web_contents()->GetNativeView()); + views::BridgeFactoryHost* bridge_factory_host = + bridged_native_widget_host + ? bridged_native_widget_host->bridge_factory_host() + : nullptr; + if (bridge_factory_host) + bridge_factory_host->GetFactory()->CreateAlert(std::move(bridge_request)); + else + ignore_result(new views_bridge_mac::AlertBridge(std::move(bridge_request))); + alert_bridge_->Show( + GetAlertParams(), + base::BindOnce(&JavaScriptAppModalDialogCocoa::OnAlertFinished, + weak_factory_.GetWeakPtr())); } void JavaScriptAppModalDialogCocoa::ActivateAppModalDialog() { } void JavaScriptAppModalDialogCocoa::CloseAppModalDialog() { - [helper_ closeWindow]; + // This function expects that dialog_->OnClose will be called before this + // function completes. + OnAlertFinished(AlertDisposition::CLOSE, base::string16(), + false /* check_box_value */); } void JavaScriptAppModalDialogCocoa::AcceptAppModalDialog() { - [helper_ acceptAlert]; + // Note that for out-of-process dialogs, we cannot find out the actual + // prompt text or suppression checkbox state in time (because the caller + // expects that OnAlertFinished be called before the function ends), so just + // use the initial values. + OnAlertFinished(AlertDisposition::PRIMARY_BUTTON, + dialog_->default_prompt_text(), false /* check_box_value */); } void JavaScriptAppModalDialogCocoa::CancelAppModalDialog() { - [helper_ cancelAlert]; + OnAlertFinished(AlertDisposition::SECONDARY_BUTTON, base::string16(), false + /* check_box_value */); } bool JavaScriptAppModalDialogCocoa::IsShowing() const {
diff --git a/chrome/browser/ui/views/frame/browser_frame.cc b/chrome/browser/ui/views/frame/browser_frame.cc index c9dc03e..d2b2a0d 100644 --- a/chrome/browser/ui/views/frame/browser_frame.cc +++ b/chrome/browser/ui/views/frame/browser_frame.cc
@@ -102,7 +102,8 @@ return native_browser_frame_->GetMinimizeButtonOffset(); } -gfx::Rect BrowserFrame::GetBoundsForTabStrip(views::View* tabstrip) const { +gfx::Rect BrowserFrame::GetBoundsForTabStrip( + const views::View* tabstrip) const { // This can be invoked before |browser_frame_view_| has been set. return browser_frame_view_ ? browser_frame_view_->GetBoundsForTabStrip(tabstrip) : gfx::Rect();
diff --git a/chrome/browser/ui/views/frame/browser_frame.h b/chrome/browser/ui/views/frame/browser_frame.h index 7281e86..15246f8 100644 --- a/chrome/browser/ui/views/frame/browser_frame.h +++ b/chrome/browser/ui/views/frame/browser_frame.h
@@ -58,7 +58,7 @@ // Retrieves the bounds, in non-client view coordinates for the specified // TabStrip view. - gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const; + gfx::Rect GetBoundsForTabStrip(const views::View* tabstrip) const; // Returns the inset of the topmost view in the client view from the top of // the non-client view. The topmost view depends on the window type. The
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h index f5a24e0..3f829c6 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -52,7 +52,7 @@ // Retrieves the bounds, in non-client view coordinates within which the // TabStrip should be laid out. - virtual gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const = 0; + virtual gfx::Rect GetBoundsForTabStrip(const views::View* tabstrip) const = 0; // Returns the inset of the topmost view in the client view from the top of // the non-client view. The topmost view depends on the window type. The
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index 9d20fa9..67c5b52 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -222,7 +222,7 @@ // BrowserNonClientFrameView: gfx::Rect BrowserNonClientFrameViewAsh::GetBoundsForTabStrip( - views::View* tabstrip) const { + const views::View* tabstrip) const { if (!tabstrip) return gfx::Rect();
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h index 29f190c..ffe2d92 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -62,7 +62,7 @@ ash::mojom::SplitViewObserverPtr CreateInterfacePtrForTesting(); // BrowserNonClientFrameView: - gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const override; + gfx::Rect GetBoundsForTabStrip(const views::View* tabstrip) const override; int GetTopInset(bool restored) const override; int GetThemeBackgroundXInset() const override; void UpdateThrobber(bool running) override;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h index f8a496c..dfd46579 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h
@@ -27,7 +27,7 @@ // BrowserNonClientFrameView: void OnFullscreenStateChanged() override; bool CaptionButtonsOnLeadingEdge() const override; - gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const override; + gfx::Rect GetBoundsForTabStrip(const views::View* tabstrip) const override; int GetTopInset(bool restored) const override; int GetThemeBackgroundXInset() const override; void UpdateFullscreenTopUI(bool needs_check_tab_fullscreen) override;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm index c192d576..e1b08a7 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
@@ -108,7 +108,7 @@ } gfx::Rect BrowserNonClientFrameViewMac::GetBoundsForTabStrip( - views::View* tabstrip) const { + const views::View* tabstrip) const { // TODO(weili): In the future, we should hide the title bar, and show the // tab strip directly under the menu bar. For now, just lay our content // under the native title bar. Use the default title bar height to avoid
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 9ffc4f2..8fed8969 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -183,6 +183,7 @@ // Accessor for the TabStrip. TabStrip* tabstrip() { return tabstrip_; } + const TabStrip* tabstrip() const { return tabstrip_; } // Accessor for the Toolbar. ToolbarView* toolbar() { return toolbar_; }
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc index 2941e4b..8e32e6c 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -151,7 +151,7 @@ } gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip( - views::View* tabstrip) const { + const views::View* tabstrip) const { const int x = CaptionButtonsOnLeadingEdge() ? (width() - frame()->GetMinimizeButtonOffset()) : 0; @@ -223,7 +223,7 @@ // Ensure that the minimum width is enough to hold a min-width tab strip. if (browser_view()->IsTabStripVisible()) { - TabStrip* tabstrip = browser_view()->tabstrip(); + const TabStrip* tabstrip = browser_view()->tabstrip(); int min_tabstrip_width = tabstrip->GetMinimumSize().width(); int min_tabstrip_area_width = width() - GetBoundsForTabStrip(tabstrip).width() + min_tabstrip_width;
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h index 2108d5c..6e96f19 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -35,7 +35,7 @@ // BrowserNonClientFrameView: bool CaptionButtonsOnLeadingEdge() const override; - gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const override; + gfx::Rect GetBoundsForTabStrip(const views::View* tabstrip) const override; int GetTopInset(bool restored) const override; int GetThemeBackgroundXInset() const override; bool HasVisibleBackgroundTabShapes(ActiveState active_state) const override;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc index 09710c0..b710df7 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -204,7 +204,7 @@ // OpaqueBrowserFrameView, BrowserNonClientFrameView implementation: gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStrip( - views::View* tabstrip) const { + const views::View* tabstrip) const { if (!tabstrip) return gfx::Rect();
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h index 5d19c64..744505c 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
@@ -58,7 +58,7 @@ void InitViews(); // BrowserNonClientFrameView: - gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const override; + gfx::Rect GetBoundsForTabStrip(const views::View* tabstrip) const override; int GetTopInset(bool restored) const override; int GetThemeBackgroundXInset() const override; void UpdateThrobber(bool running) override;
diff --git a/chrome/browser/ui/views/sync/dice_signin_button_view.cc b/chrome/browser/ui/views/sync/dice_signin_button_view.cc index 1d751ec..95d4cac 100644 --- a/chrome/browser/ui/views/sync/dice_signin_button_view.cc +++ b/chrome/browser/ui/views/sync/dice_signin_button_view.cc
@@ -36,8 +36,7 @@ // Regular MD text button when there is no account. views::MdTextButton* button = views::MdTextButton::Create( button_listener, - l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SIGNIN_BUTTON), - views::style::CONTEXT_BUTTON); + l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SIGNIN_BUTTON)); button->SetProminent(prominent); AddChildView(button); signin_button_ = button; @@ -101,8 +100,7 @@ views::GridLayout::USE_PREF, 0, 0); views::MdTextButton* button = views::MdTextButton::Create( button_listener, - l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SIGNIN_BUTTON), - views::style::CONTEXT_BUTTON); + l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SIGNIN_BUTTON)); button->SetProminent(true); grid_layout->AddView(button); signin_button_ = button;
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc index 72889559..66aeb1b 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -218,22 +218,20 @@ ResetIDs(browser->tab_strip_model(), 0); } -Browser* TabDragControllerTest::CreateAnotherWindowBrowserAndRelayout() { +Browser* TabDragControllerTest::CreateAnotherBrowserAndResize() { // Create another browser. Browser* browser2 = CreateBrowser(browser()->profile()); ResetIDs(browser2->tab_strip_model(), 100); // Resize the two windows so they're right next to each other. + const gfx::NativeWindow window = browser()->window()->GetNativeWindow(); gfx::Rect work_area = - display::Screen::GetScreen() - ->GetDisplayNearestWindow(browser()->window()->GetNativeWindow()) - .work_area(); - gfx::Size half_size = - gfx::Size(work_area.width() / 3 - 10, work_area.height() / 2 - 10); - browser()->window()->SetBounds(gfx::Rect(work_area.origin(), half_size)); - browser2->window()->SetBounds(gfx::Rect( - work_area.x() + half_size.width(), work_area.y(), - half_size.width(), half_size.height())); + display::Screen::GetScreen()->GetDisplayNearestWindow(window).work_area(); + const gfx::Size size(work_area.width() / 3, work_area.height() / 2); + gfx::Rect browser_rect(work_area.origin(), size); + browser()->window()->SetBounds(browser_rect); + browser_rect.set_x(browser_rect.right()); + browser2->window()->SetBounds(browser_rect); return browser2; } @@ -763,7 +761,7 @@ AddTabAndResetBrowser(browser()); // Create another browser. - Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); + Browser* browser2 = CreateAnotherBrowserAndResize(); TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); // Move to the first tab and drag it enough so that it detaches, but not @@ -830,17 +828,10 @@ } // namespace -#if defined(OS_CHROMEOS) || defined(OS_LINUX) -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 -#define MAYBE_CaptureLostDuringDrag DISABLED_CaptureLostDuringDrag -#else -#define MAYBE_CaptureLostDuringDrag CaptureLostDuringDrag -#endif // Calls OnMouseCaptureLost() from WindowFinder::GetLocalProcessWindowAtPoint() // and verifies we don't crash. This simulates a crash seen on windows. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - MAYBE_CaptureLostDuringDrag) { + CaptureLostDuringDrag) { TabStrip* tab_strip = GetTabStripForBrowser(browser()); // Add another tab to browser(). @@ -928,14 +919,9 @@ } // namespace -#if defined(OS_CHROMEOS) -#define MAYBE_DetachToOwnWindow DISABLED_DetachToOwnWindow -#else -#define MAYBE_DetachToOwnWindow DetachToOwnWindow -#endif // Drags from browser to separate window and releases mouse. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - MAYBE_DetachToOwnWindow) { + DetachToOwnWindow) { const gfx::Rect initial_bounds(browser()->window()->GetBounds()); // Add another tab. AddTabAndResetBrowser(browser()); @@ -948,10 +934,9 @@ ASSERT_TRUE(DragInputToNotifyWhenDone( tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), base::Bind(&DetachToOwnWindowStep2, this))); - if (input_source() == INPUT_SOURCE_MOUSE) { + if (input_source() == INPUT_SOURCE_MOUSE) ReleaseMouseAfterWindowDetached(); - QuitWhenNotDragging(); - } + QuitWhenNotDragging(); // Should no longer be dragging. ASSERT_FALSE(tab_strip->IsDragSessionActive()); @@ -999,23 +984,10 @@ EXPECT_FALSE(tab_strip2->GetWidget()->HasCapture()); } -#if defined(OS_LINUX) || defined(OS_MACOSX) -// TODO(afakhry,varkha): Disabled on Linux as it fails on the bot because -// setting the window bounds to the work area bounds in -// DesktopWindowTreeHostX11::SetBounds() always insets it by one pixel in both -// width and height. This results in considering the source browser window not -// being full size, and the test is not as expected. -// crbug.com/626761, crbug.com/331924. -// TODO(tapted,mblsha): Disabled as the Mac IsMaximized() behavior is not -// consistent with other platforms. crbug.com/603562 -#define MAYBE_DetachFromFullsizeWindow DISABLED_DetachFromFullsizeWindow -#else -#define MAYBE_DetachFromFullsizeWindow DetachFromFullsizeWindow -#endif // Tests that a tab can be dragged from a browser window that is resized to full // screen. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - MAYBE_DetachFromFullsizeWindow) { + DetachFromFullsizeWindow) { // Resize the browser window so that it is as big as the work area. gfx::Rect work_area = display::Screen::GetScreen() @@ -1033,10 +1005,9 @@ ASSERT_TRUE(DragInputToNotifyWhenDone( tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), base::Bind(&DetachToOwnWindowStep2, this))); - if (input_source() == INPUT_SOURCE_MOUSE) { + if (input_source() == INPUT_SOURCE_MOUSE) ReleaseMouseAfterWindowDetached(); - QuitWhenNotDragging(); - } + QuitWhenNotDragging(); // Should no longer be dragging. ASSERT_FALSE(tab_strip->IsDragSessionActive()); @@ -1063,29 +1034,17 @@ EXPECT_TRUE( IsWindowPositionManaged(new_browser->window()->GetNativeWindow())); - // Only second window should be maximized. - EXPECT_FALSE(browser()->window()->IsMaximized()); - MaximizedBrowserWindowWaiter(new_browser->window()).Wait(); - EXPECT_TRUE(new_browser->window()->IsMaximized()); - // The tab strip should no longer have capture because the drag was ended and // mouse/touch was released. EXPECT_FALSE(tab_strip->GetWidget()->HasCapture()); EXPECT_FALSE(tab_strip2->GetWidget()->HasCapture()); } -#if defined(OS_MACOSX) -// TODO(tapted,mblsha): Disabled as the Mac IsMaximized() behavior is not -// consistent with other platforms. crbug.com/603562 -#define MAYBE_DetachToOwnWindowFromMaximizedWindow \ - DISABLED_DetachToOwnWindowFromMaximizedWindow -#else -#define MAYBE_DetachToOwnWindowFromMaximizedWindow \ - DetachToOwnWindowFromMaximizedWindow -#endif +// This test doesn't make sense on Mac, since it has no concept of "maximized". +#if !defined(OS_MACOSX) // Drags from browser to a separate window and releases mouse. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - MAYBE_DetachToOwnWindowFromMaximizedWindow) { + DetachToOwnWindowFromMaximizedWindow) { // Maximize the initial browser window. browser()->window()->Maximize(); MaximizedBrowserWindowWaiter(browser()->window()).Wait(); @@ -1134,6 +1093,7 @@ MaximizedBrowserWindowWaiter(new_browser->window()).Wait(); EXPECT_TRUE(new_browser->window()->IsMaximized()); } +#endif #if defined(OS_CHROMEOS) @@ -1255,23 +1215,9 @@ EXPECT_TRUE(ReleaseInput()); } -#if defined(OS_CHROMEOS) -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 -#define MAYBE_DeleteTabWhileAttached DISABLED_DeleteTabWhileAttached -#else -#define MAYBE_DeleteTabWhileAttached DeleteTabWhileAttached -#endif // Deletes a tab being dragged while still attached. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - MAYBE_DeleteTabWhileAttached) { - // TODO(sky,sad): Disabled as it fails due to resize locks with a real - // compositor. crbug.com/331924 - if (input_source() == INPUT_SOURCE_MOUSE) { - VLOG(1) << "Test is DISABLED for mouse input."; - return; - } - + DeleteTabWhileAttached) { // Add another tab. AddTabAndResetBrowser(browser()); TabStrip* tab_strip = GetTabStripForBrowser(browser()); @@ -1312,17 +1258,10 @@ } // namespace -#if defined(OS_CHROMEOS) -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 -#define MAYBE_DeleteTabsWhileDetached DISABLED_DeleteTabsWhileDetached -#else -#define MAYBE_DeleteTabsWhileDetached DeleteTabsWhileDetached -#endif // Selects 2 tabs out of 4, drags them out and closes the new browser window // while dragging tabs. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - MAYBE_DeleteTabsWhileDetached) { + DeleteTabsWhileDetached) { // Add 3 tabs for a total of 4 tabs. AddTabAndResetBrowser(browser()); AddTabAndResetBrowser(browser()); @@ -1366,17 +1305,10 @@ } // namespace -#if defined(OS_CHROMEOS) || defined(OS_LINUX) -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 -#define MAYBE_PressEscapeWhileDetached DISABLED_PressEscapeWhileDetached -#else -#define MAYBE_PressEscapeWhileDetached PressEscapeWhileDetached -#endif // This is disabled until NativeViewHost::Detach really detaches. // Detaches a tab and while detached presses escape to revert the drag. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - MAYBE_PressEscapeWhileDetached) { + PressEscapeWhileDetached) { // Add another tab. AddTabAndResetBrowser(browser()); TabStrip* tab_strip = GetTabStripForBrowser(browser()); @@ -1421,15 +1353,8 @@ } // namespace -#if defined(OS_CHROMEOS) || defined(OS_LINUX) -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 -#define MAYBE_DragAll DISABLED_DragAll -#else -#define MAYBE_DragAll DragAll -#endif // Selects multiple tabs and starts dragging the window. -IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, MAYBE_DragAll) { +IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, DragAll) { // Add another tab. AddTabAndResetBrowser(browser()); TabStrip* tab_strip = GetTabStripForBrowser(browser()); @@ -1489,23 +1414,16 @@ } // namespace -#if !defined(OS_CHROMEOS) && defined(OS_LINUX) -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 -#define MAYBE_DragAllToSeparateWindow DISABLED_DragAllToSeparateWindow -#else -#define MAYBE_DragAllToSeparateWindow DragAllToSeparateWindow -#endif // Creates two browsers, selects all tabs in first and drags into second. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - MAYBE_DragAllToSeparateWindow) { + DragAllToSeparateWindow) { TabStrip* tab_strip = GetTabStripForBrowser(browser()); // Add another tab to browser(). AddTabAndResetBrowser(browser()); // Create another browser. - Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); + Browser* browser2 = CreateAnotherBrowserAndResize(); TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); browser()->tab_strip_model()->ToggleSelectionAt(0); @@ -1561,25 +1479,17 @@ } // namespace -#if !defined(OS_CHROMEOS) && defined(OS_LINUX) -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 -#define MAYBE_DragAllToSeparateWindowAndCancel \ - DISABLED_DragAllToSeparateWindowAndCancel -#else -#define MAYBE_DragAllToSeparateWindowAndCancel DragAllToSeparateWindowAndCancel -#endif // Creates two browsers, selects all tabs in first, drags into second, then hits // escape. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - MAYBE_DragAllToSeparateWindowAndCancel) { + DragAllToSeparateWindowAndCancel) { TabStrip* tab_strip = GetTabStripForBrowser(browser()); // Add another tab to browser(). AddTabAndResetBrowser(browser()); // Create another browser. - Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); + Browser* browser2 = CreateAnotherBrowserAndResize(); TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); browser()->tab_strip_model()->ToggleSelectionAt(0); @@ -1617,34 +1527,48 @@ EXPECT_FALSE(browser2->window()->IsMaximized()); } -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 -// Also fails on mac, crbug.com/837219 // Creates two browsers, drags from first into the second in such a way that // no detaching should happen. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - DISABLED_DragDirectlyToSecondWindow) { + DragDirectlyToSecondWindow) { + // TODO(pkasting): Crashes when detaching browser. https://crbug.com/918733 + if (input_source() == INPUT_SOURCE_TOUCH) { + VLOG(1) << "Test is DISABLED for touch input."; + return; + } + TabStrip* tab_strip = GetTabStripForBrowser(browser()); // Add another tab to browser(). AddTabAndResetBrowser(browser()); // Create another browser. - Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); + Browser* browser2 = CreateAnotherBrowserAndResize(); TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); - // Move the tabstrip down enough so that we can detach. - gfx::Rect bounds(browser2->window()->GetBounds()); - bounds.Offset(0, 100); - browser2->window()->SetBounds(bounds); + // Place the first browser directly below the second in such a way that + // dragging a tab upwards will drag it directly into the second browser's + // tabstrip. + const BrowserView* const browser_view2 = + BrowserView::GetBrowserViewForBrowser(browser2); + const gfx::Rect tabstrip2_bounds = + browser_view2->frame()->GetBoundsForTabStrip(browser_view2->tabstrip()); + gfx::Rect bounds = browser2->window()->GetBounds(); + bounds.Offset(0, tabstrip2_bounds.bottom()); + browser()->window()->SetBounds(bounds); - // Move to the first tab and drag it enough so that it detaches, but not - // enough that it attaches to browser2. + // Ensure the first browser is on top so clicks go to it. + ui_test_utils::BrowserActivationWaiter activation_waiter(browser()); + browser()->window()->Activate(); + activation_waiter.WaitForActivation(); + + // Move to the first tab and drag it to browser2. gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); ASSERT_TRUE(PressInput(tab_0_center)); - gfx::Point b2_location(5, 0); - views::View::ConvertPointToScreen(tab_strip2, &b2_location); + const views::View* tab = tab_strip2->tab_at(0); + gfx::Point b2_location(GetCenterInScreenCoordinates(tab)); + b2_location.Offset(-tab->width() / 4, 0); ASSERT_TRUE(DragInputTo(b2_location)); // Should now be attached to tab_strip2. @@ -1659,18 +1583,10 @@ ASSERT_FALSE(TabDragController::IsActive()); EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); EXPECT_EQ("1", IDString(browser()->tab_strip_model())); - - EXPECT_FALSE(GetIsDragged(browser())); - EXPECT_FALSE(GetIsDragged(browser2)); - - // Both windows should not be maximized - EXPECT_FALSE(browser()->window()->IsMaximized()); - EXPECT_FALSE(browser2->window()->IsMaximized()); } -#if defined(OS_CHROMEOS) || defined(OS_LINUX) -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 +#if defined(OS_CHROMEOS) +// TODO(pkasting): https://crbug.com/910791 Segfaults on CrOS. #define MAYBE_DragSingleTabToSeparateWindow \ DISABLED_DragSingleTabToSeparateWindow #else @@ -1685,7 +1601,7 @@ ResetIDs(browser()->tab_strip_model(), 0); // Create another browser. - Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); + Browser* browser2 = CreateAnotherBrowserAndResize(); TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); const gfx::Rect initial_bounds(browser2->window()->GetBounds()); @@ -1740,17 +1656,10 @@ } // namespace -#if defined(OS_CHROMEOS) || defined(OS_LINUX) -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 -#define MAYBE_CancelOnNewTabWhenDragging DISABLED_CancelOnNewTabWhenDragging -#else -#define MAYBE_CancelOnNewTabWhenDragging CancelOnNewTabWhenDragging -#endif // Adds another tab, detaches into separate window, adds another tab and // verifies the run loop ends. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - MAYBE_CancelOnNewTabWhenDragging) { + CancelOnNewTabWhenDragging) { TabStrip* tab_strip = GetTabStripForBrowser(browser()); // Add another tab to browser(). @@ -1784,8 +1693,6 @@ } #if defined(OS_CHROMEOS) -// TODO(sky,sad): A number of tests below are disabled as they fail due to -// resize locks with a real compositor. crbug.com/331924 namespace { void DragInMaximizedWindowStep2(DetachToBrowserTabDragControllerTest* test, @@ -1814,7 +1721,7 @@ // Creates a browser with two tabs, maximizes it, drags the tab out. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - DISABLED_DragInMaximizedWindow) { + DragInMaximizedWindow) { AddTabAndResetBrowser(browser()); browser()->window()->Maximize(); @@ -1861,7 +1768,7 @@ DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line); // Make screens sufficiently wide to host 2 browsers side by side. command_line->AppendSwitchASCII("ash-host-window-bounds", - "0+0-600x600,601+0-600x600"); + "0+0-600x600,600+0-600x600"); } private: @@ -2225,6 +2132,7 @@ // Drags from a restored browser to an immersive fullscreen browser on a // second display and releases input. +// TODO(pkasting) https://crbug.com/910782 Hangs. IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, DISABLED_DragTabToImmersiveBrowserOnSeparateDisplay) { // Add another tab. @@ -2317,7 +2225,7 @@ void SetUpCommandLine(base::CommandLine* command_line) override { DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line); command_line->AppendSwitchASCII("ash-host-window-bounds", - "400x400,0+400-800x800*2"); + "400x400,400+0-800x800*2"); } float GetCursorDeviceScaleFactor() const { @@ -2345,7 +2253,7 @@ {300, 200}, }; -// The expected device scale factors before the cursor is moved to the +// The expected device scale factors after the cursor is moved to the // corresponding kDragPoints in CursorDeviceScaleFactorStep. const float kDeviceScaleFactorExpectations[] = { 1.0f, @@ -2365,19 +2273,25 @@ DifferentDeviceScaleFactorDisplayTabDragControllerTest* test, TabStrip* not_attached_tab_strip, size_t index) { + SCOPED_TRACE(index); ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive()); ASSERT_TRUE(TabDragController::IsActive()); - if (index < base::size(kDragPoints)) { - EXPECT_EQ(kDeviceScaleFactorExpectations[index], + if (index > 0) { + const DragPoint p = kDragPoints[index - 1]; + EXPECT_EQ(gfx::Point(p.x, p.y), + ash::Shell::Get()->aura_env()->last_mouse_location()); + EXPECT_EQ(kDeviceScaleFactorExpectations[index - 1], test->GetCursorDeviceScaleFactor()); + } + + if (index < base::size(kDragPoints)) { const DragPoint p = kDragPoints[index]; ASSERT_TRUE(test->DragInputToNotifyWhenDone( p.x, p.y, base::Bind(&CursorDeviceScaleFactorStep, test, not_attached_tab_strip, index + 1))); } else { - // Finishes a serise of CursorDeviceScaleFactorStep calls and ends drag. - EXPECT_EQ(1.0f, test->GetCursorDeviceScaleFactor()); + // Finishes a series of CursorDeviceScaleFactorStep calls and ends drag. ASSERT_TRUE(ui_test_utils::SendMouseEventsSync( ui_controls::LEFT, ui_controls::UP)); } @@ -2387,6 +2301,12 @@ // Verifies cursor's device scale factor is updated when a tab is moved across // displays with different device scale factors (http://crbug.com/154183). +// TODO(pkasting): In interactive_ui_tests, scale factor never changes to 2. +// https://crbug.com/918731 +// TODO(pkasting): In non_single_process_mash_interactive_ui_tests, pointer is +// warped during the drag (which results in changing to scale factor 2 early), +// and scale factor doesn't change back to 1 at the end. +// https://crbug.com/918732 IN_PROC_BROWSER_TEST_P(DifferentDeviceScaleFactorDisplayTabDragControllerTest, DISABLED_CursorDeviceScaleFactor) { // Add another tab. @@ -2676,7 +2596,7 @@ AddTabAndResetBrowser(browser()); // Create another browser. - Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); + Browser* browser2 = CreateAnotherBrowserAndResize(); TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); // Move to the first tab and drag it enough so that it detaches, but not @@ -2842,7 +2762,7 @@ TabStrip* tab_strip = GetTabStripForBrowser(browser()); // Create another browser. - Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); + Browser* browser2 = CreateAnotherBrowserAndResize(); TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); EXPECT_EQ(2u, browser_list->size()); @@ -2908,7 +2828,7 @@ AddTabAndResetBrowser(browser()); // Create another browser. - Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); + Browser* browser2 = CreateAnotherBrowserAndResize(); TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); EXPECT_EQ(2u, browser_list->size()); @@ -2980,7 +2900,7 @@ AddTabAndResetBrowser(browser()); // Create another browser. - Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); + Browser* browser2 = CreateAnotherBrowserAndResize(); TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); // Move to the first tab and drag it enough so that it detaches, but not @@ -3047,7 +2967,7 @@ AddTabAndResetBrowser(browser()); // Create another browser. - Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); + Browser* browser2 = CreateAnotherBrowserAndResize(); TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); // Move to the first tab and drag it enough so that it detaches, but not @@ -3184,7 +3104,7 @@ AddTabAndResetBrowser(browser()); // Create another browser. - Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); + Browser* browser2 = CreateAnotherBrowserAndResize(); TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); EXPECT_EQ(2u, browser_list->size()); @@ -3250,7 +3170,7 @@ TabStrip* tab_strip = GetTabStripForBrowser(browser()); // Create another browser. - Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); + Browser* browser2 = CreateAnotherBrowserAndResize(); TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); EXPECT_EQ(2u, browser_list->size());
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.h b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.h index 7bb3f075..c1a1ef10 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.h +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.h
@@ -38,9 +38,9 @@ // the tabs in |browser|. void AddTabAndResetBrowser(Browser* browser); - // Creates a new Browser and resizes |browser()| and the new browser to be - // side by side. - Browser* CreateAnotherWindowBrowserAndRelayout(); + // Creates a new Browser and resizes browser() and the new browser to be side + // by side. + Browser* CreateAnotherBrowserAndResize(); void SetWindowFinderForTabStrip(TabStrip* tab_strip, std::unique_ptr<WindowFinder> window_finder);
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc index d19cd89..8cb90ea 100644 --- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc +++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
@@ -442,7 +442,6 @@ void DiceTurnSyncOnHelper::SigninAndShowSyncConfirmationUI() { // Signin. auto* primary_account_mutator = identity_manager_->GetPrimaryAccountMutator(); - DCHECK(primary_account_mutator); primary_account_mutator->SetPrimaryAccount(account_info_.account_id); signin_metrics::LogSigninAccessPointCompleted(signin_access_point_, signin_promo_action_);
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h index 678e45e..38c1786 100644 --- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h +++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h
@@ -30,8 +30,8 @@ class SyncSetupInProgressHandle; } -// Handles details of signing the user in with IdentityManager and turning on -// sync for an account that is already present in the token service. +// Handles details of setting the primary account with IdentityManager and +// turning on sync for an account for which there is already a refresh token. class DiceTurnSyncOnHelper : public SyncStartupTracker::Observer { public: // Behavior when the signin is aborted (by an error or cancelled by the user).
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc index ae77422..8fff227 100644 --- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc +++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
@@ -175,14 +175,6 @@ const base::FilePath& path, Profile::Delegate* delegate) { TestingProfile::Builder profile_builder; - - TestingProfile::TestingFactories testing_factories = - IdentityTestEnvironmentProfileAdaptor:: - GetIdentityTestEnvironmentFactories(); - for (auto& testing_factory : testing_factories) { - profile_builder.AddTestingFactory(testing_factory.first, - testing_factory.second); - } profile_builder.AddTestingFactory( ChromeSigninClientFactory::GetInstance(), base::BindRepeating(&signin::BuildTestSigninClient)); @@ -194,7 +186,8 @@ base::BindRepeating(&FakeUserPolicySigninService::Build)); profile_builder.SetDelegate(delegate); profile_builder.SetPath(path); - return profile_builder.Build(); + return IdentityTestEnvironmentProfileAdaptor:: + CreateProfileForIdentityTestEnvironment(profile_builder); } } // namespace @@ -808,7 +801,7 @@ DiceTurnSyncOnHelper* dice_sync_starter = CreateDiceTurnOnSyncHelper( DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT); - // Check that the account was set in the sign-in manager, but the sync + // Check that the primary account was set with IdentityManager, but the sync // confirmation dialog was not yet shown. EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id())); EXPECT_EQ(account_id(), identity_manager()->GetPrimaryAccountId());
diff --git a/chrome/browser/web_applications/extensions/web_app_audio_focus_browsertest.cc b/chrome/browser/web_applications/extensions/web_app_audio_focus_browsertest.cc index ce005c0..274b4c3 100644 --- a/chrome/browser/web_applications/extensions/web_app_audio_focus_browsertest.cc +++ b/chrome/browser/web_applications/extensions/web_app_audio_focus_browsertest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/macros.h" +#include "base/test/scoped_feature_list.h" #include "chrome/browser/extensions/browsertest_util.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/ui/browser.h" @@ -13,6 +14,7 @@ #include "content/public/test/browser_test_utils.h" #include "extensions/test/extension_test_message_listener.h" #include "extensions/test/test_extension_dir.h" +#include "media/base/media_switches.h" #include "services/media_session/public/cpp/switches.h" namespace web_app { @@ -34,6 +36,8 @@ void SetUpCommandLine(base::CommandLine* command_line) override { InProcessBrowserTest::SetUpCommandLine(command_line); command_line->AppendSwitch(media_session::switches::kEnableAudioFocus); + scoped_feature_list_.InitAndEnableFeature( + media::kUseGroupedBrowserAudioFocus); } bool IsPaused(content::WebContents* web_contents) { @@ -74,6 +78,8 @@ } private: + base::test::ScopedFeatureList scoped_feature_list_; + DISALLOW_COPY_AND_ASSIGN(WebAppAudioFocusBrowserTest); };
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl index fda5528..bd615f2 100644 --- a/chrome/common/extensions/api/autotest_private.idl +++ b/chrome/common/extensions/api/autotest_private.idl
@@ -284,5 +284,11 @@ // |callback|: Called when response has been received. static void sendAssistantTextQuery(DOMString query, long timeout_ms, AssistantQueryResponseCallback callback); + + // Enable/disable a Crostini app's "scaled" property. + // |appId|: The Crostini application ID. + // |scaled|: The app is "scaled" when shown, which means it uses low display density. + // |callback|: Called when the operation has completed. + static void setCrostiniAppScaled(DOMString appId, boolean scaled, VoidCallback callback); }; };
diff --git a/chrome/common/media_router/providers/cast/cast_media_source.cc b/chrome/common/media_router/providers/cast/cast_media_source.cc index edc701b..4904ee0f 100644 --- a/chrome/common/media_router/providers/cast/cast_media_source.cc +++ b/chrome/common/media_router/providers/cast/cast_media_source.cc
@@ -220,7 +220,7 @@ CastAppInfo::CastAppInfo(const CastAppInfo& other) = default; // static -std::unique_ptr<CastMediaSource> CastMediaSource::From( +std::unique_ptr<CastMediaSource> CastMediaSource::FromMediaSourceId( const MediaSource::Id& source_id) { MediaSource source(source_id); if (IsTabMirroringMediaSource(source)) @@ -246,6 +246,12 @@ return nullptr; } +// static +std::unique_ptr<CastMediaSource> CastMediaSource::FromAppId( + const std::string& app_id) { + return FromMediaSourceId(kCastPresentationUrlScheme + (":" + app_id)); +} + CastMediaSource::CastMediaSource(const MediaSource::Id& source_id, const std::vector<CastAppInfo>& app_infos) : source_id_(source_id), app_infos_(app_infos) {}
diff --git a/chrome/common/media_router/providers/cast/cast_media_source.h b/chrome/common/media_router/providers/cast/cast_media_source.h index e46b725..2bd2942 100644 --- a/chrome/common/media_router/providers/cast/cast_media_source.h +++ b/chrome/common/media_router/providers/cast/cast_media_source.h
@@ -47,7 +47,10 @@ class CastMediaSource { public: // Returns the parsed form of |source|, or nullptr if it cannot be parsed. - static std::unique_ptr<CastMediaSource> From(const MediaSource::Id& source); + static std::unique_ptr<CastMediaSource> FromMediaSourceId( + const MediaSource::Id& source); + + static std::unique_ptr<CastMediaSource> FromAppId(const std::string& app_id); CastMediaSource(const MediaSource::Id& source_id, const std::vector<CastAppInfo>& app_infos);
diff --git a/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc b/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc index 5ab5eaa..dabbeff 100644 --- a/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc +++ b/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
@@ -16,7 +16,8 @@ "&broadcastMessage=message" "&clientId=12345" "&launchTimeout=30000"); - std::unique_ptr<CastMediaSource> source = CastMediaSource::From(source_id); + std::unique_ptr<CastMediaSource> source = + CastMediaSource::FromMediaSourceId(source_id); ASSERT_TRUE(source); EXPECT_EQ(source_id, source->source_id()); ASSERT_EQ(1u, source->app_infos().size()); @@ -40,7 +41,8 @@ "/__castBroadcastMessage__=message" "/__castClientId__=12345" "/__castLaunchTimeout__=30000"); - std::unique_ptr<CastMediaSource> source = CastMediaSource::From(source_id); + std::unique_ptr<CastMediaSource> source = + CastMediaSource::FromMediaSourceId(source_id); ASSERT_TRUE(source); EXPECT_EQ(source_id, source->source_id()); ASSERT_EQ(1u, source->app_infos().size()); @@ -59,7 +61,8 @@ TEST(CastMediaSourceTest, FromPresentationURL) { MediaSource::Id source_id("https://google.com"); - std::unique_ptr<CastMediaSource> source = CastMediaSource::From(source_id); + std::unique_ptr<CastMediaSource> source = + CastMediaSource::FromMediaSourceId(source_id); ASSERT_TRUE(source); EXPECT_EQ(source_id, source->source_id()); ASSERT_EQ(2u, source->app_infos().size()); @@ -71,7 +74,8 @@ TEST(CastMediaSourceTest, FromMirroringURN) { MediaSource::Id source_id("urn:x-org.chromium.media:source:tab:5"); - std::unique_ptr<CastMediaSource> source = CastMediaSource::From(source_id); + std::unique_ptr<CastMediaSource> source = + CastMediaSource::FromMediaSourceId(source_id); ASSERT_TRUE(source); EXPECT_EQ(source_id, source->source_id()); ASSERT_EQ(2u, source->app_infos().size()); @@ -83,7 +87,8 @@ TEST(CastMediaSourceTest, FromDesktopUrn) { MediaSource::Id source_id("urn:x-org.chromium.media:source:desktop"); - std::unique_ptr<CastMediaSource> source = CastMediaSource::From(source_id); + std::unique_ptr<CastMediaSource> source = + CastMediaSource::FromMediaSourceId(source_id); ASSERT_TRUE(source); EXPECT_EQ(source_id, source->source_id()); ASSERT_EQ(1u, source->app_infos().size()); @@ -93,14 +98,14 @@ } TEST(CastMediaSourceTest, FromInvalidSource) { - EXPECT_FALSE(CastMediaSource::From("invalid:source")); - EXPECT_FALSE(CastMediaSource::From("file:///foo.mp4")); - EXPECT_FALSE(CastMediaSource::From("")); - EXPECT_FALSE(CastMediaSource::From("cast:")); + EXPECT_FALSE(CastMediaSource::FromMediaSourceId("invalid:source")); + EXPECT_FALSE(CastMediaSource::FromMediaSourceId("file:///foo.mp4")); + EXPECT_FALSE(CastMediaSource::FromMediaSourceId("")); + EXPECT_FALSE(CastMediaSource::FromMediaSourceId("cast:")); // Missing app ID. - EXPECT_FALSE(CastMediaSource::From("cast:?param=foo")); - EXPECT_FALSE(CastMediaSource::From( + EXPECT_FALSE(CastMediaSource::FromMediaSourceId("cast:?param=foo")); + EXPECT_FALSE(CastMediaSource::FromMediaSourceId( "https://google.com/cast#__castAppId__=/param=foo")); }
diff --git a/chrome/renderer/extensions/app_bindings.cc b/chrome/renderer/extensions/app_bindings.cc index 77ffa86..b35a315 100644 --- a/chrome/renderer/extensions/app_bindings.cc +++ b/chrome/renderer/extensions/app_bindings.cc
@@ -19,18 +19,18 @@ AppBindings::~AppBindings() {} void AppBindings::AddRoutes() { - RouteHandlerFunction( - "GetIsInstalled", "app.getIsInstalled", - base::Bind(&AppBindings::GetIsInstalled, base::Unretained(this))); + RouteHandlerFunction("GetIsInstalled", "app.getIsInstalled", + base::BindRepeating(&AppBindings::GetIsInstalled, + base::Unretained(this))); RouteHandlerFunction( "GetDetails", "app.getDetails", - base::Bind(&AppBindings::GetDetails, base::Unretained(this))); - RouteHandlerFunction( - "GetInstallState", "app.installState", - base::Bind(&AppBindings::GetInstallState, base::Unretained(this))); - RouteHandlerFunction( - "GetRunningState", "app.runningState", - base::Bind(&AppBindings::GetRunningState, base::Unretained(this))); + base::BindRepeating(&AppBindings::GetDetails, base::Unretained(this))); + RouteHandlerFunction("GetInstallState", "app.installState", + base::BindRepeating(&AppBindings::GetInstallState, + base::Unretained(this))); + RouteHandlerFunction("GetRunningState", "app.runningState", + base::BindRepeating(&AppBindings::GetRunningState, + base::Unretained(this))); } void AppBindings::GetIsInstalled(
diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.cc b/chrome/renderer/extensions/automation_internal_custom_bindings.cc index b7fe419..2b5c175 100644 --- a/chrome/renderer/extensions/automation_internal_custom_bindings.cc +++ b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
@@ -502,10 +502,11 @@ // It's safe to use base::Unretained(this) here because these bindings // will only be called on a valid AutomationInternalCustomBindings instance // and none of the functions have any side effects. -#define ROUTE_FUNCTION(FN) \ - RouteHandlerFunction(#FN, "automation", \ - base::Bind(&AutomationInternalCustomBindings::FN, \ - base::Unretained(this))) +#define ROUTE_FUNCTION(FN) \ + RouteHandlerFunction( \ + #FN, "automation", \ + base::BindRepeating(&AutomationInternalCustomBindings::FN, \ + base::Unretained(this))) ROUTE_FUNCTION(IsInteractPermitted); ROUTE_FUNCTION(GetSchemaAdditions); ROUTE_FUNCTION(StartCachingAccessibilityTrees); @@ -815,8 +816,9 @@ attr_value = node->GetSetSize(); if (attr_value == 0) return; - } else if (!node->data().GetIntAttribute(attribute, &attr_value)) + } else if (!node->data().GetIntAttribute(attribute, &attr_value)) { return; + } result.Set(v8::Integer::New(isolate, attr_value)); }); @@ -1571,7 +1573,7 @@ const std::string& name, TreeIDFunction callback) { scoped_refptr<TreeIDWrapper> wrapper = new TreeIDWrapper(this, callback); - RouteHandlerFunction(name, base::Bind(&TreeIDWrapper::Run, wrapper)); + RouteHandlerFunction(name, base::BindRepeating(&TreeIDWrapper::Run, wrapper)); } void AutomationInternalCustomBindings::RouteNodeIDFunction( @@ -1586,8 +1588,8 @@ NodeIDPlusAttributeFunction callback) { scoped_refptr<NodeIDPlusAttributeWrapper> wrapper = new NodeIDPlusAttributeWrapper(this, callback); - RouteHandlerFunction(name, - base::Bind(&NodeIDPlusAttributeWrapper::Run, wrapper)); + RouteHandlerFunction( + name, base::BindRepeating(&NodeIDPlusAttributeWrapper::Run, wrapper)); } void AutomationInternalCustomBindings::RouteNodeIDPlusRangeFunction( @@ -1595,7 +1597,8 @@ NodeIDPlusRangeFunction callback) { scoped_refptr<NodeIDPlusRangeWrapper> wrapper = new NodeIDPlusRangeWrapper(this, callback); - RouteHandlerFunction(name, base::Bind(&NodeIDPlusRangeWrapper::Run, wrapper)); + RouteHandlerFunction( + name, base::BindRepeating(&NodeIDPlusRangeWrapper::Run, wrapper)); } void AutomationInternalCustomBindings::RouteNodeIDPlusStringBoolFunction(
diff --git a/chrome/renderer/extensions/cast_streaming_native_handler.cc b/chrome/renderer/extensions/cast_streaming_native_handler.cc index b489179..b85e4f7 100644 --- a/chrome/renderer/extensions/cast_streaming_native_handler.cc +++ b/chrome/renderer/extensions/cast_streaming_native_handler.cc
@@ -15,6 +15,7 @@ #include <utility> #include <vector> +#include "base/bind.h" #include "base/location.h" #include "base/logging.h" #include "base/single_thread_task_runner.h" @@ -335,45 +336,51 @@ void CastStreamingNativeHandler::AddRoutes() { RouteHandlerFunction( "CreateSession", "cast.streaming.session", - base::Bind(&CastStreamingNativeHandler::CreateCastSession, - weak_factory_.GetWeakPtr())); + base::BindRepeating(&CastStreamingNativeHandler::CreateCastSession, + weak_factory_.GetWeakPtr())); RouteHandlerFunction( "DestroyCastRtpStream", "cast.streaming.rtpStream", - base::Bind(&CastStreamingNativeHandler::DestroyCastRtpStream, - weak_factory_.GetWeakPtr())); + base::BindRepeating(&CastStreamingNativeHandler::DestroyCastRtpStream, + weak_factory_.GetWeakPtr())); RouteHandlerFunction( "GetSupportedParamsCastRtpStream", "cast.streaming.rtpStream", - base::Bind(&CastStreamingNativeHandler::GetSupportedParamsCastRtpStream, - weak_factory_.GetWeakPtr())); + base::BindRepeating( + &CastStreamingNativeHandler::GetSupportedParamsCastRtpStream, + weak_factory_.GetWeakPtr())); RouteHandlerFunction( "StartCastRtpStream", "cast.streaming.rtpStream", - base::Bind(&CastStreamingNativeHandler::StartCastRtpStream, - weak_factory_.GetWeakPtr())); + base::BindRepeating(&CastStreamingNativeHandler::StartCastRtpStream, + weak_factory_.GetWeakPtr())); RouteHandlerFunction( "StopCastRtpStream", "cast.streaming.rtpStream", - base::Bind(&CastStreamingNativeHandler::StopCastRtpStream, - weak_factory_.GetWeakPtr())); + base::BindRepeating(&CastStreamingNativeHandler::StopCastRtpStream, + weak_factory_.GetWeakPtr())); RouteHandlerFunction( "DestroyCastUdpTransport", "cast.streaming.udpTransport", - base::Bind(&CastStreamingNativeHandler::DestroyCastUdpTransport, - weak_factory_.GetWeakPtr())); + base::BindRepeating(&CastStreamingNativeHandler::DestroyCastUdpTransport, + weak_factory_.GetWeakPtr())); RouteHandlerFunction( "SetDestinationCastUdpTransport", "cast.streaming.udpTransport", - base::Bind(&CastStreamingNativeHandler::SetDestinationCastUdpTransport, - weak_factory_.GetWeakPtr())); + base::BindRepeating( + &CastStreamingNativeHandler::SetDestinationCastUdpTransport, + weak_factory_.GetWeakPtr())); RouteHandlerFunction( "SetOptionsCastUdpTransport", "cast.streaming.udpTransport", - base::Bind(&CastStreamingNativeHandler::SetOptionsCastUdpTransport, - weak_factory_.GetWeakPtr())); - RouteHandlerFunction("ToggleLogging", "cast.streaming.rtpStream", - base::Bind(&CastStreamingNativeHandler::ToggleLogging, - weak_factory_.GetWeakPtr())); - RouteHandlerFunction("GetRawEvents", "cast.streaming.rtpStream", - base::Bind(&CastStreamingNativeHandler::GetRawEvents, - weak_factory_.GetWeakPtr())); - RouteHandlerFunction("GetStats", "cast.streaming.rtpStream", - base::Bind(&CastStreamingNativeHandler::GetStats, - weak_factory_.GetWeakPtr())); + base::BindRepeating( + &CastStreamingNativeHandler::SetOptionsCastUdpTransport, + weak_factory_.GetWeakPtr())); + RouteHandlerFunction( + "ToggleLogging", "cast.streaming.rtpStream", + base::BindRepeating(&CastStreamingNativeHandler::ToggleLogging, + weak_factory_.GetWeakPtr())); + RouteHandlerFunction( + "GetRawEvents", "cast.streaming.rtpStream", + base::BindRepeating(&CastStreamingNativeHandler::GetRawEvents, + weak_factory_.GetWeakPtr())); + RouteHandlerFunction( + "GetStats", "cast.streaming.rtpStream", + base::BindRepeating(&CastStreamingNativeHandler::GetStats, + weak_factory_.GetWeakPtr())); } void CastStreamingNativeHandler::Invalidate() {
diff --git a/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc b/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc index 997f24ed..851753b 100644 --- a/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc +++ b/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/bind.h" #include "base/logging.h" #include "build/build_config.h" #include "extensions/renderer/script_context.h" @@ -22,7 +23,7 @@ void FileBrowserHandlerCustomBindings::AddRoutes() { RouteHandlerFunction( "GetExternalFileEntry", "fileBrowserHandler", - base::Bind( + base::BindRepeating( &FileBrowserHandlerCustomBindings::GetExternalFileEntryCallback, base::Unretained(this))); }
diff --git a/chrome/renderer/extensions/file_manager_private_custom_bindings.cc b/chrome/renderer/extensions/file_manager_private_custom_bindings.cc index e54fd92..c57d0b1 100644 --- a/chrome/renderer/extensions/file_manager_private_custom_bindings.cc +++ b/chrome/renderer/extensions/file_manager_private_custom_bindings.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/bind.h" #include "base/logging.h" #include "chrome/renderer/extensions/file_browser_handler_custom_bindings.h" #include "extensions/renderer/script_context.h" @@ -23,16 +24,17 @@ void FileManagerPrivateCustomBindings::AddRoutes() { RouteHandlerFunction( "GetFileSystem", "fileManagerPrivate", - base::Bind(&FileManagerPrivateCustomBindings::GetFileSystem, - base::Unretained(this))); + base::BindRepeating(&FileManagerPrivateCustomBindings::GetFileSystem, + base::Unretained(this))); RouteHandlerFunction( "GetExternalFileEntry", "fileManagerPrivate", - base::Bind(&FileManagerPrivateCustomBindings::GetExternalFileEntry, - base::Unretained(this))); + base::BindRepeating( + &FileManagerPrivateCustomBindings::GetExternalFileEntry, + base::Unretained(this))); RouteHandlerFunction( "GetEntryURL", "fileManagerPrivate", - base::Bind(&FileManagerPrivateCustomBindings::GetEntryURL, - base::Unretained(this))); + base::BindRepeating(&FileManagerPrivateCustomBindings::GetEntryURL, + base::Unretained(this))); } void FileManagerPrivateCustomBindings::GetFileSystem(
diff --git a/chrome/renderer/extensions/media_galleries_custom_bindings.cc b/chrome/renderer/extensions/media_galleries_custom_bindings.cc index e514a1a..5912488 100644 --- a/chrome/renderer/extensions/media_galleries_custom_bindings.cc +++ b/chrome/renderer/extensions/media_galleries_custom_bindings.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/bind.h" #include "extensions/renderer/script_context.h" #include "storage/common/fileapi/file_system_util.h" #include "third_party/blink/public/platform/url_conversion.h" @@ -25,8 +26,9 @@ void MediaGalleriesCustomBindings::AddRoutes() { RouteHandlerFunction( "GetMediaFileSystemObject", "mediaGalleries", - base::Bind(&MediaGalleriesCustomBindings::GetMediaFileSystemObject, - base::Unretained(this))); + base::BindRepeating( + &MediaGalleriesCustomBindings::GetMediaFileSystemObject, + base::Unretained(this))); } // FileSystemObject GetMediaFileSystem(string file_system_url): construct
diff --git a/chrome/renderer/extensions/notifications_native_handler.cc b/chrome/renderer/extensions/notifications_native_handler.cc index 7ef420d..22c9fd0 100644 --- a/chrome/renderer/extensions/notifications_native_handler.cc +++ b/chrome/renderer/extensions/notifications_native_handler.cc
@@ -7,6 +7,7 @@ #include <memory> #include <string> +#include "base/bind.h" #include "base/logging.h" #include "base/values.h" #include "chrome/common/extensions/api/notifications/notification_style.h" @@ -22,8 +23,9 @@ void NotificationsNativeHandler::AddRoutes() { RouteHandlerFunction( "GetNotificationImageSizes", "notifications", - base::Bind(&NotificationsNativeHandler::GetNotificationImageSizes, - base::Unretained(this))); + base::BindRepeating( + &NotificationsNativeHandler::GetNotificationImageSizes, + base::Unretained(this))); } void NotificationsNativeHandler::GetNotificationImageSizes(
diff --git a/chrome/renderer/extensions/page_capture_custom_bindings.cc b/chrome/renderer/extensions/page_capture_custom_bindings.cc index 445ff1df..3688266 100644 --- a/chrome/renderer/extensions/page_capture_custom_bindings.cc +++ b/chrome/renderer/extensions/page_capture_custom_bindings.cc
@@ -18,12 +18,14 @@ : ObjectBackedNativeHandler(context) {} void PageCaptureCustomBindings::AddRoutes() { - RouteHandlerFunction("CreateBlob", "pageCapture", - base::Bind(&PageCaptureCustomBindings::CreateBlob, - base::Unretained(this))); - RouteHandlerFunction("SendResponseAck", "pageCapture", - base::Bind(&PageCaptureCustomBindings::SendResponseAck, - base::Unretained(this))); + RouteHandlerFunction( + "CreateBlob", "pageCapture", + base::BindRepeating(&PageCaptureCustomBindings::CreateBlob, + base::Unretained(this))); + RouteHandlerFunction( + "SendResponseAck", "pageCapture", + base::BindRepeating(&PageCaptureCustomBindings::SendResponseAck, + base::Unretained(this))); } void PageCaptureCustomBindings::CreateBlob(
diff --git a/chrome/renderer/extensions/platform_keys_natives.cc b/chrome/renderer/extensions/platform_keys_natives.cc index 3b5d275..c7d3c118 100644 --- a/chrome/renderer/extensions/platform_keys_natives.cc +++ b/chrome/renderer/extensions/platform_keys_natives.cc
@@ -8,6 +8,7 @@ #include <string> #include <utility> +#include "base/bind.h" #include "base/values.h" #include "content/public/renderer/v8_value_converter.h" #include "extensions/renderer/script_context.h" @@ -97,9 +98,10 @@ : ObjectBackedNativeHandler(context) {} void PlatformKeysNatives::AddRoutes() { - RouteHandlerFunction("NormalizeAlgorithm", - base::Bind(&PlatformKeysNatives::NormalizeAlgorithm, - base::Unretained(this))); + RouteHandlerFunction( + "NormalizeAlgorithm", + base::BindRepeating(&PlatformKeysNatives::NormalizeAlgorithm, + base::Unretained(this))); } void PlatformKeysNatives::NormalizeAlgorithm(
diff --git a/chrome/renderer/extensions/sync_file_system_custom_bindings.cc b/chrome/renderer/extensions/sync_file_system_custom_bindings.cc index 423a142..34583e97 100644 --- a/chrome/renderer/extensions/sync_file_system_custom_bindings.cc +++ b/chrome/renderer/extensions/sync_file_system_custom_bindings.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/bind.h" #include "extensions/renderer/script_context.h" #include "storage/common/fileapi/file_system_util.h" #include "third_party/blink/public/web/web_dom_file_system.h" @@ -21,8 +22,9 @@ void SyncFileSystemCustomBindings::AddRoutes() { RouteHandlerFunction( "GetSyncFileSystemObject", "syncFileSystem", - base::Bind(&SyncFileSystemCustomBindings::GetSyncFileSystemObject, - base::Unretained(this))); + base::BindRepeating( + &SyncFileSystemCustomBindings::GetSyncFileSystemObject, + base::Unretained(this))); } void SyncFileSystemCustomBindings::GetSyncFileSystemObject(
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index a054566..7621b57 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3347,6 +3347,7 @@ "../browser/media/router/providers/cast/cast_internal_message_util_unittest.cc", "../browser/media/router/providers/cast/cast_media_route_provider_metrics_unittest.cc", "../browser/media/router/providers/cast/cast_media_route_provider_unittest.cc", + "../browser/media/router/providers/cast/cast_session_tracker_unittest.cc", "../browser/media/router/providers/cast/dual_media_sink_service_unittest.cc", "../browser/media/router/providers/dial/dial_activity_manager_unittest.cc", "../browser/media/router/providers/dial/dial_internal_message_util_unittest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/document/MockStorageDelegate.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/document/MockStorageDelegate.java index 6ab547f9..4d6bc38 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/document/MockStorageDelegate.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/document/MockStorageDelegate.java
@@ -11,7 +11,7 @@ import org.junit.Assert; import org.chromium.base.StreamUtil; -import org.chromium.chrome.browser.TabState; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.document.StorageDelegate; import java.io.File;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/document/MockTabDelegate.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/document/MockTabDelegate.java index 257f6b40..3f816f9 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/document/MockTabDelegate.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/document/MockTabDelegate.java
@@ -4,8 +4,8 @@ package org.chromium.chrome.test.util.browser.tabmodel.document; -import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabState; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.document.AsyncTabCreationParams; import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
diff --git a/chrome/test/data/extensions/api_test/autotest_private/test.js b/chrome/test/data/extensions/api_test/autotest_private/test.js index 70ff9707..5fabe62 100644 --- a/chrome/test/data/extensions/api_test/autotest_private/test.js +++ b/chrome/test/data/extensions/api_test/autotest_private/test.js
@@ -190,6 +190,17 @@ chrome.autotestPrivate.runCrostiniInstaller(chrome.test.callbackFail( 'Crostini is not available for the current user')); }, + // This sets a Crostini app's "scaled" property in the app registry. + // When the property is set to true, the app will be launched in low display + // density. + function setCrostiniAppScaled() { + chrome.autotestPrivate.setCrostiniAppScaled( + 'nodabfiipdopnjihbfpiengllkohmfkl', true, + function() { + chrome.test.assertNoLastError(); + chrome.test.succeed(); + }); + }, function bootstrapMachineLearningService() { chrome.autotestPrivate.bootstrapMachineLearningService( chrome.test.callbackFail('ML Service connection error'));
diff --git a/chrome/test/data/xr/e2e_test_files/html/test_webxr_poses.html b/chrome/test/data/xr/e2e_test_files/html/test_webxr_poses.html index 8ea6296f..2da68b6 100644 --- a/chrome/test/data/xr/e2e_test_files/html/test_webxr_poses.html +++ b/chrome/test/data/xr/e2e_test_files/html/test_webxr_poses.html
@@ -65,13 +65,13 @@ // Encode an index into the clear color. frame_id++; frame_data_array[frame_id] = frame; - cached_frame_of_ref = sessionInfos[sessionTypes.IMMERSIVE].currentFrameOfRef; + cached_frame_of_ref = sessionInfos[sessionTypes.IMMERSIVE].currentRefSpace; var encoded_frame_id = {}; encoded_frame_id.r = frame_id % 256; encoded_frame_id.g = ((frame_id - frame_id % 256) / 256) % 256; encoded_frame_id.b = ((frame_id - frame_id % (256 * 256)) / (256 * 256)) % 256; - // We divide by 255 rather than 256, because our range of values is [0, 255], + // We divide by 255 rather than 256, because our range of values is [0, 255], // which should map to [0.0f, 1.0f]. gl.clearColor(encoded_frame_id.r / 255, encoded_frame_id.g / 255, encoded_frame_id.b / 255, 1.0); gl.clear(gl.COLOR_BUFFER_BIT);
diff --git a/chrome/test/data/xr/e2e_test_files/html/webxr_test_pose_data_unfocused_tab.html b/chrome/test/data/xr/e2e_test_files/html/webxr_test_pose_data_unfocused_tab.html index 19dac53d..dd35f36 100644 --- a/chrome/test/data/xr/e2e_test_files/html/webxr_test_pose_data_unfocused_tab.html +++ b/chrome/test/data/xr/e2e_test_files/html/webxr_test_pose_data_unfocused_tab.html
@@ -26,7 +26,7 @@ return; } onMagicWindowXRFrameCallback = null; - pose = frame.getViewerPose(sessionInfos[sessionTypes.MAGIC_WINDOW].currentFrameOfRef); + pose = frame.getViewerPose(sessionInfos[sessionTypes.MAGIC_WINDOW].currentRefSpace); assert_true(pose != null, "getViewerPose returned a non-null object"); assert_true(pose instanceof XRViewerPose,
diff --git a/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js b/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js index 1889f19..5081b38f 100644 --- a/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js +++ b/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js
@@ -42,7 +42,7 @@ return this.session; } - get currentFrameOfRef() { + get currentRefSpace() { return this.frameOfRef; } @@ -50,7 +50,7 @@ this.session = session; } - set currentFrameOfRef(frameOfRef) { + set currentRefSpace(frameOfRef) { this.frameOfRef = frameOfRef; } @@ -127,10 +127,11 @@ } session.baseLayer = new XRWebGLLayer(session, gl); - session.requestFrameOfReference('eye-level').then( (frameOfRef) => { - sessionInfos[getSessionType(session)].currentFrameOfRef = frameOfRef; - session.requestAnimationFrame(onXRFrame); - }); + session.requestReferenceSpace({ type: 'stationary', subtype: 'eye-level' }) + .then( (refSpace) => { + sessionInfos[getSessionType(session)].currentRefSpace = refSpace; + session.requestAnimationFrame(onXRFrame); + }); } function onSessionEnded(event) { @@ -141,9 +142,8 @@ let session = frame.session; session.requestAnimationFrame(onXRFrame); - let frameOfRef = null; - frameOfRef = sessionInfos[getSessionType(session)].currentFrameOfRef; - let pose = frame.getViewerPose(frameOfRef); + let refSpace = sessionInfos[getSessionType(session)].currentRefSpace; + let pose = frame.getViewerPose(refSpace); if (onPoseCallback) { onPoseCallback(pose); }
diff --git a/chromecast/browser/cast_web_view_default.cc b/chromecast/browser/cast_web_view_default.cc index b49b465..671b74c0 100644 --- a/chromecast/browser/cast_web_view_default.cc +++ b/chromecast/browser/cast_web_view_default.cc
@@ -14,7 +14,6 @@ #include "chromecast/browser/cast_browser_process.h" #include "chromecast/browser/cast_web_contents_manager.h" #include "chromecast/chromecast_buildflags.h" -#include "chromecast/public/cast_media_shlib.h" #include "content/public/browser/media_capture_devices.h" #include "content/public/browser/media_session.h" #include "content/public/browser/navigation_handle.h" @@ -137,10 +136,6 @@ void CastWebViewDefault::InitializeWindow(CastWindowManager* window_manager, CastWindowManager::WindowId z_order, VisibilityPriority initial_priority) { - if (media::CastMediaShlib::ClearVideoPlaneImage) { - media::CastMediaShlib::ClearVideoPlaneImage(); - } - DCHECK(window_manager); window_->CreateWindowForWebContents(web_contents_.get(), window_manager, z_order, initial_priority);
diff --git a/chromecast/browser/extensions/api/tabs/tabs_api.cc b/chromecast/browser/extensions/api/tabs/tabs_api.cc index 8ef1defd..146bd1ba 100644 --- a/chromecast/browser/extensions/api/tabs/tabs_api.cc +++ b/chromecast/browser/extensions/api/tabs/tabs_api.cc
@@ -717,10 +717,6 @@ TabsCaptureVisibleTabFunction::TabsCaptureVisibleTabFunction() {} -bool TabsCaptureVisibleTabFunction::HasPermission() { - return false; -} - ExtensionFunction::ResponseAction TabsCaptureVisibleTabFunction::Run() { return RespondNow(Error("Cannot capture tab")); } @@ -737,18 +733,6 @@ ExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() {} -bool ExecuteCodeInTabFunction::HasPermission() { - if (Init() == SUCCESS && - // TODO(devlin/lazyboy): Consider removing the following check as it isn't - // doing anything. The fallback to ExtensionFunction::HasPermission() - // below dictates what this function returns. - extension_->permissions_data()->HasAPIPermissionForTab( - execute_tab_id_, APIPermission::kTab)) { - return true; - } - return ExtensionFunction::HasPermission(); -} - ExecuteCodeFunction::InitResult ExecuteCodeInTabFunction::Init() { if (init_result_) return init_result_.value();
diff --git a/chromecast/browser/extensions/api/tabs/tabs_api.h b/chromecast/browser/extensions/api/tabs/tabs_api.h index 7e80568d..da0233c5 100644 --- a/chromecast/browser/extensions/api/tabs/tabs_api.h +++ b/chromecast/browser/extensions/api/tabs/tabs_api.h
@@ -168,7 +168,6 @@ TabsCaptureVisibleTabFunction(); // ExtensionFunction implementation. - bool HasPermission() override; ResponseAction Run() override; protected: @@ -188,9 +187,6 @@ protected: ~ExecuteCodeInTabFunction() override; - // ExtensionFunction: - bool HasPermission() override; - // Initializes |execute_tab_id_| and |details_|. InitResult Init() override; bool CanExecuteScriptOnPage(std::string* error) override;
diff --git a/chromecast/public/cast_media_shlib.h b/chromecast/public/cast_media_shlib.h index fc38d8a..6255274 100644 --- a/chromecast/public/cast_media_shlib.h +++ b/chromecast/public/cast_media_shlib.h
@@ -140,13 +140,6 @@ const std::string& config) __attribute__((__weak__)); - // Only used on Chromecast: set and clear an image on the video plane. - // Image data is 8-bit ARGB format; |data| buffer byte length must be - // |width|*|height|*4. Returns whether the image could be successfully set. - static bool SetVideoPlaneImage(int width, int height, const uint8_t* data) - __attribute__((__weak__)); - static void ClearVideoPlaneImage() __attribute__((__weak__)); - // Sets up a direct audio source for output. The media backend will pull audio // directly from |source| whenever more output data is needed; this provides // low-latency output. The source must remain valid until
diff --git a/chromecast/renderer/extensions/automation_internal_custom_bindings.cc b/chromecast/renderer/extensions/automation_internal_custom_bindings.cc index 5c590686..5ae210d5 100644 --- a/chromecast/renderer/extensions/automation_internal_custom_bindings.cc +++ b/chromecast/renderer/extensions/automation_internal_custom_bindings.cc
@@ -503,10 +503,11 @@ // It's safe to use base::Unretained(this) here because these bindings // will only be called on a valid AutomationInternalCustomBindings instance // and none of the functions have any side effects. -#define ROUTE_FUNCTION(FN) \ - RouteHandlerFunction(#FN, "automation", \ - base::Bind(&AutomationInternalCustomBindings::FN, \ - base::Unretained(this))) +#define ROUTE_FUNCTION(FN) \ + RouteHandlerFunction( \ + #FN, "automation", \ + base::BindRepeating(&AutomationInternalCustomBindings::FN, \ + base::Unretained(this))) ROUTE_FUNCTION(IsInteractPermitted); ROUTE_FUNCTION(GetSchemaAdditions); ROUTE_FUNCTION(StartCachingAccessibilityTrees); @@ -1563,7 +1564,7 @@ const std::string& name, TreeIDFunction callback) { scoped_refptr<TreeIDWrapper> wrapper = new TreeIDWrapper(this, callback); - RouteHandlerFunction(name, base::Bind(&TreeIDWrapper::Run, wrapper)); + RouteHandlerFunction(name, base::BindRepeating(&TreeIDWrapper::Run, wrapper)); } void AutomationInternalCustomBindings::RouteNodeIDFunction( @@ -1578,8 +1579,8 @@ NodeIDPlusAttributeFunction callback) { scoped_refptr<NodeIDPlusAttributeWrapper> wrapper = new NodeIDPlusAttributeWrapper(this, callback); - RouteHandlerFunction(name, - base::Bind(&NodeIDPlusAttributeWrapper::Run, wrapper)); + RouteHandlerFunction( + name, base::BindRepeating(&NodeIDPlusAttributeWrapper::Run, wrapper)); } void AutomationInternalCustomBindings::RouteNodeIDPlusRangeFunction( @@ -1587,7 +1588,8 @@ NodeIDPlusRangeFunction callback) { scoped_refptr<NodeIDPlusRangeWrapper> wrapper = new NodeIDPlusRangeWrapper(this, callback); - RouteHandlerFunction(name, base::Bind(&NodeIDPlusRangeWrapper::Run, wrapper)); + RouteHandlerFunction( + name, base::BindRepeating(&NodeIDPlusRangeWrapper::Run, wrapper)); } void AutomationInternalCustomBindings::RouteNodeIDPlusStringBoolFunction(
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index fb9a1b34..cb3b4f06 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -452,7 +452,7 @@ // Only upload server statistics and UMA metrics if at least some local data // is available to use as a baseline. std::vector<AutofillProfile*> profiles = personal_data_->GetProfiles(); - personal_data_->UpdateProfilesValidityMapsIfNeeded(profiles); + personal_data_->UpdateProfilesServerValidityMapsIfNeeded(profiles); if (observed_submission && form_structure->IsAutofillable()) { AutofillMetrics::LogNumberOfProfilesAtAutofillableFormSubmission( personal_data_->GetProfiles().size());
diff --git a/components/autofill/core/browser/autofill_profile.cc b/components/autofill/core/browser/autofill_profile.cc index d413da9..3fd9100 100644 --- a/components/autofill/core/browser/autofill_profile.cc +++ b/components/autofill/core/browser/autofill_profile.cc
@@ -447,8 +447,6 @@ bool AutofillProfile::EqualsSansOrigin(const AutofillProfile& profile) const { return guid() == profile.guid() && language_code() == profile.language_code() && - is_client_validity_states_updated() == - profile.is_client_validity_states_updated() && Compare(profile) == 0; }
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index b646acb8..006b157 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -575,6 +575,7 @@ upload->set_autofill_used(form_was_autofilled); upload->set_data_present(EncodeFieldTypes(available_field_types)); upload->set_passwords_revealed(passwords_were_revealed_); + upload->set_has_form_tag(is_form_tag_); if (!page_language_.empty() && randomized_encoder_ != nullptr) { upload->set_language(page_language_); }
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc index 6e37ca47..cdc3cd5 100644 --- a/components/autofill/core/browser/form_structure_unittest.cc +++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -2444,6 +2444,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; form_structure = std::make_unique<FormStructure>(form); form_structure->DetermineHeuristicTypes(); @@ -2537,6 +2538,7 @@ upload.set_action_signature(15724779818122431245U); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_NONE); + upload.set_has_form_tag(true); test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text", nullptr, 3U, 0); @@ -2765,6 +2767,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; form_structure = std::make_unique<FormStructure>(form); form_structure->DetermineHeuristicTypes(); @@ -2859,6 +2862,7 @@ upload.set_action_signature(15724779818122431245U); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_NONE); + upload.set_has_form_tag(true); test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text", nullptr, 3U, {0, 2}); @@ -2892,6 +2896,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; form_structure = std::make_unique<FormStructure>(form); form_structure->DetermineHeuristicTypes(); @@ -2983,6 +2988,7 @@ upload.set_password_has_numeric(true); upload.set_password_length(10u); upload.set_action_signature(15724779818122431245U); + upload.set_has_form_tag(true); test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text", nullptr, 3U); @@ -3103,6 +3109,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; form_structure = std::make_unique<FormStructure>(form); form_structure->DetermineHeuristicTypes(); @@ -3182,6 +3189,7 @@ upload.set_passwords_revealed(false); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_NONE); + upload.set_has_form_tag(true); AutofillUploadContents::Field* upload_firstname_field = upload.add_field(); test::FillUploadField(upload_firstname_field, 4224610201U, "firstname", "", @@ -3227,6 +3235,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; form_structure = std::make_unique<FormStructure>(form); form_structure->DetermineHeuristicTypes(); @@ -3281,6 +3290,7 @@ upload.set_passwords_revealed(false); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_NONE); + upload.set_has_form_tag(true); test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text", "given-name", 3U); @@ -3309,6 +3319,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; form_structure = std::make_unique<FormStructure>(form); form_structure->DetermineHeuristicTypes(); @@ -3376,6 +3387,7 @@ upload.set_passwords_revealed(false); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_NONE); + upload.set_has_form_tag(true); test::FillUploadField(upload.add_field(), 3763331450U, nullptr, nullptr, nullptr, 3U); @@ -3407,6 +3419,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; form_structure = std::make_unique<FormStructure>(form); form_structure->DetermineHeuristicTypes(); @@ -3461,6 +3474,7 @@ upload.set_passwords_revealed(false); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_NONE); + upload.set_has_form_tag(true); test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text", nullptr, 3U); @@ -3488,6 +3502,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; form_structure = std::make_unique<FormStructure>(form); form_structure->DetermineHeuristicTypes(); @@ -3535,6 +3550,7 @@ upload.set_passwords_revealed(false); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_NONE); + upload.set_has_form_tag(true); test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text", nullptr, 3U); @@ -3560,6 +3576,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; FormFieldData field; field.form_control_type = "text"; @@ -3605,6 +3622,7 @@ upload.set_passwords_revealed(false); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_NONE); + upload.set_has_form_tag(true); AutofillUploadContents::Field* firstname_field = upload.add_field(); test::FillUploadField(firstname_field, 1318412689U, nullptr, "text", nullptr, @@ -3640,6 +3658,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; // Setting the form name which we expect to see in the upload. form.name = ASCIIToUTF16("myform"); @@ -3689,6 +3708,7 @@ upload.set_passwords_revealed(false); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_FRAME_DETACHED); + upload.set_has_form_tag(true); test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text", nullptr, 3U); @@ -3715,6 +3735,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; form_structure = std::make_unique<FormStructure>(form); form_structure->DetermineHeuristicTypes(); @@ -3769,6 +3790,7 @@ upload.set_action_signature(15724779818122431245U); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_NONE); + upload.set_has_form_tag(true); test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text", nullptr, 3U); @@ -3798,6 +3820,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; form_structure = std::make_unique<FormStructure>(form); form_structure->DetermineHeuristicTypes(); @@ -3860,6 +3883,7 @@ upload.set_passwords_revealed(false); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_NONE); + upload.set_has_form_tag(true); test::FillUploadField(upload.add_field(), 3763331450U, nullptr, nullptr, nullptr, 3U); @@ -3885,6 +3909,7 @@ TEST_F(FormStructureTest, CheckDataPresence) { FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = true; FormFieldData field; field.form_control_type = "text"; @@ -3934,6 +3959,7 @@ upload.set_action_signature(15724779818122431245U); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_HTML_FORM_SUBMISSION); + upload.set_has_form_tag(true); test::FillUploadField(upload.add_field(), 1089846351U, "first", "text", nullptr, 1U); @@ -4163,6 +4189,7 @@ std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.origin = GURL("http://www.foo.com/"); + form.is_form_tag = false; FormFieldData field; field.form_control_type = "text"; @@ -4212,6 +4239,7 @@ upload.set_autofill_used(false); upload.set_data_present("1440000360000008"); upload.set_passwords_revealed(false); + upload.set_has_form_tag(false); upload.set_action_signature(15724779818122431245U); upload.set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_XHR_SUCCEEDED); @@ -4329,6 +4357,29 @@ EXPECT_EQ(true, upload.passwords_revealed()); } +TEST_F(FormStructureTest, EncodeUploadRequest_IsFormTag) { + for (bool is_form_tag : {false, true}) { + SCOPED_TRACE(testing::Message() << "is_form_tag=" << is_form_tag); + + FormData form; + form.origin = GURL("http://www.foo.com/"); + FormFieldData field; + field.name = ASCIIToUTF16("email"); + form.fields.push_back(field); + + form.is_form_tag = is_form_tag; + + FormStructure form_structure(form); + form_structure.set_passwords_were_revealed(true); + AutofillUploadContents upload; + EXPECT_TRUE(form_structure.EncodeUploadRequest( + {{}} /* available_field_types */, false /* form_was_autofilled */, + std::string() /* login_form_signature */, + true /* observed_submission */, &upload)); + EXPECT_EQ(is_form_tag, upload.has_form_tag()); + } +} + TEST_F(FormStructureTest, EncodeUploadRequest_RichMetadata) { struct FieldMetadata { const char *id, *name, *label, *placeholder, *aria_label, *aria_description, @@ -6537,8 +6588,8 @@ FormData form; form.origin = GURL("http://foo.com"); FormFieldData field; - // Check that the form with 100 fields are processed correctly. - for (size_t i = 0; i < 100; ++i) { + // Check that the form with 250 fields are processed correctly. + for (size_t i = 0; i < 250; ++i) { field.form_control_type = "text"; field.name = ASCIIToUTF16("text") + base::NumberToString16(i); form.fields.push_back(field);
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 2a5cf4c..409bb94 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -1009,11 +1009,11 @@ return result; } -void PersonalDataManager::UpdateProfilesValidityMapsIfNeeded( +void PersonalDataManager::UpdateProfilesServerValidityMapsIfNeeded( const std::vector<AutofillProfile*>& profiles) { - if (!profile_validities_need_update_) + if (!profiles_server_validities_need_update) return; - profile_validities_need_update_ = false; + profiles_server_validities_need_update = false; for (auto* profile : profiles) { profile->UpdateServerValidityMap(GetProfileValidityByGUID(profile->guid())); } @@ -1092,7 +1092,7 @@ LoadProfiles(); LoadCreditCards(); LoadPaymentsCustomerData(); - profile_validities_need_update_ = true; + profiles_server_validities_need_update = true; } std::vector<AutofillProfile*> PersonalDataManager::GetProfilesToSuggest() @@ -1172,7 +1172,7 @@ min_last_used, &sorted_profiles); } // We need the updated information on the validity states of the profiles. - UpdateProfilesValidityMapsIfNeeded(sorted_profiles); + UpdateProfilesServerValidityMapsIfNeeded(sorted_profiles); MaybeRemoveInvalidSuggestions(type, &sorted_profiles); } @@ -1452,7 +1452,7 @@ const std::string& guid) { static const ProfileValidityMap& empty_validity_map = ProfileValidityMap(); if (!synced_profile_validity_) { - profile_validities_need_update_ = true; + profiles_server_validities_need_update = true; synced_profile_validity_ = std::make_unique<UserProfileValidityMap>(); if (!synced_profile_validity_->ParseFromString( ::autofill::prefs::GetAllProfilesValidityMapsEncodedString( @@ -2570,7 +2570,7 @@ void PersonalDataManager::ResetProfileValidity() { synced_profile_validity_.reset(); - profile_validities_need_update_ = true; + profiles_server_validities_need_update = true; } } // namespace autofill
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h index 3a789b4..f8bd2d11 100644 --- a/components/autofill/core/browser/personal_data_manager.h +++ b/components/autofill/core/browser/personal_data_manager.h
@@ -262,7 +262,7 @@ virtual PaymentsCustomerData* GetPaymentsCustomerData() const; // Updates the validity states of |profiles| according to server validity map. - void UpdateProfilesValidityMapsIfNeeded( + void UpdateProfilesServerValidityMapsIfNeeded( const std::vector<AutofillProfile*>& profiles); // Updates the validity states of |profiles| according to client side @@ -618,7 +618,7 @@ base::ObserverList<PersonalDataManagerObserver>::Unchecked observers_; // |profile_valditiies_need_update| whenever the profile validities are out of - bool profile_validities_need_update_ = true; + bool profiles_server_validities_need_update = true; private: // Saves |imported_credit_card| to the WebDB if it exists. Returns the guid of
diff --git a/components/autofill/core/browser/proto/server.proto b/components/autofill/core/browser/proto/server.proto index 35326fe..079c944 100644 --- a/components/autofill/core/browser/proto/server.proto +++ b/components/autofill/core/browser/proto/server.proto
@@ -185,7 +185,7 @@ // This message contains information about the field types in a single form. // It is sent by the toolbar to contribute to the field type statistics. -// Next available id: 37 +// Next available id: 38 message AutofillUploadContents { required string client_version = 1; required fixed64 form_signature = 2; @@ -393,6 +393,9 @@ // Titles of form's buttons. // TODO(850606): Deprecate once randomized metadata is launched. repeated ButtonTitle button_title = 36; + + // Whether the fields are enclosed by a <form> tag or are unowned elements. + optional bool has_form_tag = 37; } // This proto contains information about the validity of each field in an
diff --git a/components/cast_channel/cast_message_handler.cc b/components/cast_channel/cast_message_handler.cc index 2f56a82..fa1eb9bd 100644 --- a/components/cast_channel/cast_message_handler.cc +++ b/components/cast_channel/cast_message_handler.cc
@@ -89,7 +89,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); CastSocket* socket = socket_service_->GetSocket(channel_id); if (!socket) { - DVLOG(2) << __func__ << ": socket not found: " << channel_id; + DVLOG(2) << "Socket not found: " << channel_id; return; } @@ -130,6 +130,19 @@ } } +void CastMessageHandler::RequestReceiverStatus(int channel_id) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + CastSocket* socket = socket_service_->GetSocket(channel_id); + if (!socket) { + DVLOG(2) << __func__ << ": socket not found: " << channel_id; + return; + } + + int request_id = NextRequestId(); + SendCastMessage(socket, CreateReceiverStatusRequest(sender_id_, request_id)); +} + void CastMessageHandler::SendBroadcastMessage( int channel_id, const std::vector<std::string>& app_ids,
diff --git a/components/cast_channel/cast_message_handler.h b/components/cast_channel/cast_message_handler.h index 0e13ea15..c8d66ab 100644 --- a/components/cast_channel/cast_message_handler.h +++ b/components/cast_channel/cast_message_handler.h
@@ -146,6 +146,9 @@ const std::string& app_id, GetAppAvailabilityCallback callback); + // Sends a receiver status request to the socket given by |channel_id|. + virtual void RequestReceiverStatus(int channel_id); + // Sends a broadcast message containing |app_ids| and |request| to the socket // given by |channel_id|. virtual void SendBroadcastMessage(int channel_id,
diff --git a/components/cast_channel/cast_message_util.cc b/components/cast_channel/cast_message_util.cc index 0dda18942..35844cd 100644 --- a/components/cast_channel/cast_message_util.cc +++ b/components/cast_channel/cast_message_util.cc
@@ -27,6 +27,7 @@ constexpr char kKeepAlivePingType[] = "PING"; constexpr char kKeepAlivePongType[] = "PONG"; constexpr char kGetAppAvailabilityRequestType[] = "GET_APP_AVAILABILITY"; +constexpr char kReceiverStatusRequestType[] = "GET_STATUS"; constexpr char kConnectionRequestType[] = "CONNECT"; constexpr char kCloseConnectionRequestType[] = "CLOSE"; constexpr char kBroadcastRequestType[] = "APPLICATION_BROADCAST"; @@ -115,6 +116,8 @@ return kKeepAlivePongType; case CastMessageType::kGetAppAvailability: return kGetAppAvailabilityRequestType; + case CastMessageType::kReceiverStatusRequest: + return kReceiverStatusRequestType; case CastMessageType::kConnect: return kConnectionRequestType; case CastMessageType::kCloseConnection: @@ -143,6 +146,8 @@ return CastMessageType::kPong; if (type == kGetAppAvailabilityRequestType) return CastMessageType::kGetAppAvailability; + if (type == kReceiverStatusRequestType) + return CastMessageType::kReceiverStatusRequest; if (type == kConnectionRequestType) return CastMessageType::kConnect; if (type == kCloseConnectionRequestType) @@ -289,6 +294,15 @@ kPlatformReceiverId); } +CastMessage CreateReceiverStatusRequest(const std::string& source_id, + int request_id) { + Value dict(Value::Type::DICTIONARY); + dict.SetKey(kTypeNodeId, Value(kReceiverStatusRequestType)); + dict.SetKey(kRequestIdNodeId, Value(request_id)); + return CreateCastMessage(kReceiverNamespace, dict, source_id, + kPlatformReceiverId); +} + BroadcastRequest::BroadcastRequest(const std::string& broadcast_namespace, const std::string& message) : broadcast_namespace(broadcast_namespace), message(message) {}
diff --git a/components/cast_channel/cast_message_util.h b/components/cast_channel/cast_message_util.h index e3777a4..bdbdb3b 100644 --- a/components/cast_channel/cast_message_util.h +++ b/components/cast_channel/cast_message_util.h
@@ -38,6 +38,7 @@ kPing, kPong, kGetAppAvailability, + kReceiverStatusRequest, kConnect, // Virtual connection request kCloseConnection, // Close virtual connection kBroadcast, // Application broadcast / precache @@ -115,6 +116,9 @@ int request_id, const std::string& app_id); +CastMessage CreateReceiverStatusRequest(const std::string& source_id, + int request_id); + // Represents a broadcast request. Currently it is used for precaching data // on a receiver. struct BroadcastRequest { @@ -143,10 +147,6 @@ int request_id, const std::string& session_id); -CastMessage CreateStopRequest(const std::string& source_id, - int request_id, - const std::string& session_id); - // Creates a generic CastMessage with |message| as the string payload. Used for // app messages. CastMessage CreateCastMessage(const std::string& message_namespace,
diff --git a/components/cast_channel/cast_message_util_unittest.cc b/components/cast_channel/cast_message_util_unittest.cc index 8e629cfd..26fa818 100644 --- a/components/cast_channel/cast_message_util_unittest.cc +++ b/components/cast_channel/cast_message_util_unittest.cc
@@ -99,4 +99,25 @@ EXPECT_EQ(*expected_value, *actual_value); } +TEST(CastMessageUtilTest, CreateReceiverStatusRequest) { + std::string expected_message = R"( + { + "type": "GET_STATUS", + "requestId": 123 + } + )"; + + std::unique_ptr<base::Value> expected_value = + base::JSONReader::Read(expected_message); + ASSERT_TRUE(expected_value); + + CastMessage message = CreateReceiverStatusRequest("sourceId", 123); + ASSERT_TRUE(IsCastMessageValid(message)); + + std::unique_ptr<base::Value> actual_value = + base::JSONReader::Read(message.payload_utf8()); + ASSERT_TRUE(actual_value); + EXPECT_EQ(*expected_value, *actual_value); +} + } // namespace cast_channel
diff --git a/components/cast_channel/cast_test_util.h b/components/cast_channel/cast_test_util.h index d7483885..67fcd19 100644 --- a/components/cast_channel/cast_test_util.h +++ b/components/cast_channel/cast_test_util.h
@@ -153,6 +153,7 @@ void(CastSocket* socket, const std::string& app_id, GetAppAvailabilityCallback callback)); + MOCK_METHOD1(RequestReceiverStatus, void(int channel_id)); MOCK_METHOD3(SendBroadcastMessage, void(int, const std::vector<std::string>&,
diff --git a/components/crash/content/app/BUILD.gn b/components/crash/content/app/BUILD.gn index cd4dac9..5a13a519 100644 --- a/components/crash/content/app/BUILD.gn +++ b/components/crash/content/app/BUILD.gn
@@ -61,7 +61,6 @@ if (is_mac || is_win || is_android || (is_linux && !is_chromeos)) { deps += [ "//third_party/crashpad/crashpad/client", - "//third_party/crashpad/crashpad/snapshot:snapshot_api", "//third_party/crashpad/crashpad/util", ] }
diff --git a/components/safe_browsing/db/v4_local_database_manager.cc b/components/safe_browsing/db/v4_local_database_manager.cc index 2cdff113..317a9c6 100644 --- a/components/safe_browsing/db/v4_local_database_manager.cc +++ b/components/safe_browsing/db/v4_local_database_manager.cc
@@ -16,7 +16,6 @@ #include "base/memory/ref_counted.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" -#include "base/strings/string_util.h" #include "base/task/post_task.h" #include "base/timer/elapsed_timer.h" #include "components/safe_browsing/db/v4_feature_list.h" @@ -35,10 +34,6 @@ const ThreatSeverity kLeastSeverity = std::numeric_limits<ThreatSeverity>::max(); -const char* const kV4UnusedStoreFileExists = - "SafeBrowsing.V4UnusedStoreFileExists"; -const char* const kV3Suffix = ".V3."; - // The list of the name of any store files that are no longer used and can be // safely deleted from the disk. There's no overlap allowed between the files // on this list and the list returned by GetListInfos(). @@ -159,28 +154,6 @@ return stores_to_check; } -const char* const kPVer3FileNameSuffixesToDelete[] = { - "Bloom", - "Bloom Prefix Set", - "Csd Whitelist", - "Download", - "Download Whitelist", - "Extension Blacklist", - "IP Blacklist", - "Inclusion Whitelist", - "Module Whitelist", - "Resource Blacklist", - "Side-Effect Free Whitelist", - "UwS List", - "UwS List Prefix Set"}; - -std::string GetUmaSuffixForPVer3FileNameSuffix(const std::string& suffix) { - DCHECK(!suffix.empty()); - std::string uma_suffix; - base::RemoveChars(suffix, base::kWhitespaceASCII, &uma_suffix); - return uma_suffix; -} - // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum StoreAvailabilityResult { @@ -281,7 +254,6 @@ DCHECK(!list_infos_.empty()); DeleteUnusedStoreFiles(); - DeletePVer3StoreFiles(); DVLOG(1) << "V4LocalDatabaseManager::V4LocalDatabaseManager: " << "base_path_: " << base_path_.AsUTF8Unsafe(); @@ -598,27 +570,6 @@ } } -void V4LocalDatabaseManager::DeletePVer3StoreFiles() { - // PVer3 files are directly in the profile directory, whereas PVer4 files are - // under "Safe Browsing" directory, so we need to look in the DirName() of - // base_path_. - for (auto* const pver3_store_suffix : kPVer3FileNameSuffixesToDelete) { - const base::FilePath store_path = base_path_.DirName().AppendASCII( - std::string("Safe Browsing ") + pver3_store_suffix); - bool path_exists = base::PathExists(store_path); - base::UmaHistogramBoolean( - std::string(kV4UnusedStoreFileExists) + kV3Suffix + - GetUmaSuffixForPVer3FileNameSuffix(pver3_store_suffix), - path_exists); - if (!path_exists) { - continue; - } - task_runner_->PostTask(FROM_HERE, - base::BindOnce(base::IgnoreResult(&base::DeleteFile), - store_path, false /* recursive */)); - } -} - void V4LocalDatabaseManager::DeleteUnusedStoreFiles() { for (auto* const store_filename_to_delete : kStoreFileNamesToDelete) { // Is the file marked for deletion also being used for a valid V4Store? @@ -630,9 +581,9 @@ const base::FilePath store_path = base_path_.AppendASCII(store_filename_to_delete); bool path_exists = base::PathExists(store_path); - base::UmaHistogramBoolean( - kV4UnusedStoreFileExists + GetUmaSuffixForStore(store_path), - path_exists); + base::UmaHistogramBoolean("SafeBrowsing.V4UnusedStoreFileExists" + + GetUmaSuffixForStore(store_path), + path_exists); if (!path_exists) { continue; }
diff --git a/components/safe_browsing/db/v4_local_database_manager.h b/components/safe_browsing/db/v4_local_database_manager.h index 932267e..ee80698 100644 --- a/components/safe_browsing/db/v4_local_database_manager.h +++ b/components/safe_browsing/db/v4_local_database_manager.h
@@ -210,11 +210,6 @@ // Called when the database has been updated and schedules the next update. void DatabaseUpdated(); - // Delete any PVer3 list files from disk because PVer3 has been deprecated. - // This method can be removed after the UMA metrics for the following prefix - // go down to 0 in Stable: "SafeBrowsing.V4UnusedStoreFileExists.V3." - void DeletePVer3StoreFiles(); - // Delete any *.store files from disk that are no longer used. void DeleteUnusedStoreFiles();
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 4851019..f18f8c5e 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -226,15 +226,26 @@ { base::Optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use; - if (gpu_service_->gr_shader_cache()) + if (gpu_service_->gr_shader_cache()) { cache_use.emplace(gpu_service_->gr_shader_cache(), gpu::kInProcessCommandBufferClientId); + } sk_surface_->draw(ddl.get()); gr_context()->flush(); } + + // Note that the ScopedCacheUse for GrShaderCache is scoped until the + // ReleaseFenceSync call here since releasing the fence may schedule a + // different decoder's stream which also uses the shader cache. sync_point_client_state_->ReleaseFenceSync(sync_fence_release); if (overdraw_ddl) { + base::Optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use; + if (gpu_service_->gr_shader_cache()) { + cache_use.emplace(gpu_service_->gr_shader_cache(), + gpu::kInProcessCommandBufferClientId); + } + sk_sp<SkSurface> overdraw_surface = SkSurface::MakeRenderTarget( gr_context(), overdraw_ddl->characterization(), SkBudgeted::kNo); overdraw_surface->draw(overdraw_ddl.get());
diff --git a/content/browser/appcache/appcache_navigation_handle.h b/content/browser/appcache/appcache_navigation_handle.h index 0b91060..7afa478e 100644 --- a/content/browser/appcache/appcache_navigation_handle.h +++ b/content/browser/appcache/appcache_navigation_handle.h
@@ -37,7 +37,7 @@ // host id was updated. // // 5) When the navigation is ready to commit, the NavigationRequest will -// update the RequestNavigationParams based on the id from the +// update the CommitNavigationParams based on the id from the // AppCacheNavigationHandle. // // 6) The commit leads to AppCache registrations happening from the renderer.
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc index e7f2a6d..714a1b95 100644 --- a/content/browser/devtools/protocol/network_handler.cc +++ b/content/browser/devtools/protocol/network_handler.cc
@@ -1609,10 +1609,10 @@ headers_dict->setString(net::HttpRequestHeaders::kReferer, referrer.spec()); std::unique_ptr<Network::Response> redirect_response; - const RequestNavigationParams& request_params = nav_request.request_params(); - if (!request_params.redirect_response.empty()) { - redirect_response = BuildResponse(request_params.redirects.back(), - request_params.redirect_response.back()); + const CommitNavigationParams& commit_params = nav_request.commit_params(); + if (!commit_params.redirect_response.empty()) { + redirect_response = BuildResponse(commit_params.redirects.back(), + commit_params.redirect_response.back()); } std::string url_fragment; std::string url_without_fragment =
diff --git a/content/browser/frame_host/interstitial_page_impl_browsertest.cc b/content/browser/frame_host/interstitial_page_impl_browsertest.cc index 00c1736..915f062 100644 --- a/content/browser/frame_host/interstitial_page_impl_browsertest.cc +++ b/content/browser/frame_host/interstitial_page_impl_browsertest.cc
@@ -318,12 +318,6 @@ // commits in the original page while an interstitial is showing. // See https://crbug.com/729105. IN_PROC_BROWSER_TEST_F(InterstitialPageImplTest, UnderlyingSubframeCommit) { - // This test doesn't apply in PlzNavigate, since the subframe does not - // succesfully commit in that mode. - // TODO(creis, clamy): Determine if this is a bug that should be fixed. - if (IsBrowserSideNavigationEnabled()) - return; - ASSERT_TRUE(embedded_test_server()->Start()); // Load an initial page and inject an iframe that won't commit yet.
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index 2a983133..e460d996 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -366,13 +366,13 @@ } DCHECK_EQ(request->common_params().should_replace_current_entry, entry->should_replace_entry()); - DCHECK_EQ(request->request_params().should_clear_history_list, + DCHECK_EQ(request->commit_params().should_clear_history_list, entry->should_clear_history_list()); DCHECK_EQ(request->common_params().has_user_gesture, entry->has_user_gesture()); DCHECK_EQ(request->common_params().base_url_for_data_url, entry->GetBaseURLForDataURL()); - DCHECK_EQ(request->request_params().can_load_local_resources, + DCHECK_EQ(request->commit_params().can_load_local_resources, entry->GetCanLoadLocalResources()); DCHECK_EQ(request->common_params().started_from_context_menu, entry->has_started_from_context_menu()); @@ -387,10 +387,10 @@ DCHECK_EQ(request->common_params().url, frame_entry->url()); DCHECK_EQ(request->common_params().method, frame_entry->method()); - size_t redirect_size = request->request_params().redirects.size(); + size_t redirect_size = request->commit_params().redirects.size(); if (redirect_size == frame_entry->redirect_chain().size()) { for (size_t i = 0; i < redirect_size; ++i) { - DCHECK_EQ(request->request_params().redirects[i], + DCHECK_EQ(request->commit_params().redirects[i], frame_entry->redirect_chain()[i]); } } else { @@ -2881,7 +2881,7 @@ params.started_from_context_menu, has_user_gesture, InitiatorCSPInfo(), params.href_translate, params.input_start); - RequestNavigationParams request_params( + CommitNavigationParams commit_params( override_user_agent, params.redirect_chain, common_params.url, common_params.method, params.can_load_local_resources, frame_entry->page_state(), entry.GetUniqueID(), @@ -2893,11 +2893,11 @@ is_view_source_mode, params.should_clear_history_list); #if defined(OS_ANDROID) if (ValidateDataURLAsString(params.data_url_as_string)) { - request_params.data_url_as_string = params.data_url_as_string->data(); + commit_params.data_url_as_string = params.data_url_as_string->data(); } #endif - request_params.was_activated = params.was_activated; + commit_params.was_activated = params.was_activated; // A form submission may happen here if the navigation is a renderer-initiated // form submission that took the OpenURL path. @@ -2907,7 +2907,7 @@ std::string extra_headers_crlf; base::ReplaceChars(params.extra_headers, "\n", "\r\n", &extra_headers_crlf); return NavigationRequest::CreateBrowserInitiated( - node, common_params, request_params, !params.is_renderer_initiated, + node, common_params, commit_params, !params.is_renderer_initiated, extra_headers_crlf, *frame_entry, entry, request_body, params.navigation_ui_data ? params.navigation_ui_data->Clone() : nullptr); } @@ -2990,18 +2990,16 @@ // TODO(clamy): |intended_as_new_entry| below should always be false once // Reload no longer leads to this being called for a pending NavigationEntry // of index -1. - RequestNavigationParams request_params = - entry.ConstructRequestNavigationParams( - *frame_entry, common_params.url, common_params.method, - is_history_navigation_in_new_child, - entry.GetSubframeUniqueNames(frame_tree_node), - GetPendingEntryIndex() == -1 /* intended_as_new_entry */, - GetIndexOfEntry(&entry), GetLastCommittedEntryIndex(), - GetEntryCount()); - request_params.post_content_type = post_content_type; + CommitNavigationParams commit_params = entry.ConstructCommitNavigationParams( + *frame_entry, common_params.url, common_params.method, + is_history_navigation_in_new_child, + entry.GetSubframeUniqueNames(frame_tree_node), + GetPendingEntryIndex() == -1 /* intended_as_new_entry */, + GetIndexOfEntry(&entry), GetLastCommittedEntryIndex(), GetEntryCount()); + commit_params.post_content_type = post_content_type; return NavigationRequest::CreateBrowserInitiated( - frame_tree_node, common_params, request_params, + frame_tree_node, common_params, commit_params, !entry.is_renderer_initiated(), entry.extra_headers(), *frame_entry, entry, request_body, nullptr /* navigation_ui_data */); }
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc index f65390e..8d320fa 100644 --- a/content/browser/frame_host/navigation_entry_impl.cc +++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -706,7 +706,7 @@ has_user_gesture(), InitiatorCSPInfo(), std::string(), input_start); } -RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams( +CommitNavigationParams NavigationEntryImpl::ConstructCommitNavigationParams( const FrameNavigationEntry& frame_entry, const GURL& original_url, const std::string& original_method, @@ -735,7 +735,7 @@ current_length_to_send = 0; } - RequestNavigationParams request_params( + CommitNavigationParams commit_params( GetIsOverridingUserAgent(), redirects, original_url, original_method, GetCanLoadLocalResources(), frame_entry.page_state(), GetUniqueID(), is_history_navigation_in_new_child, subframe_unique_names, @@ -743,10 +743,10 @@ current_length_to_send, IsViewSourceMode(), should_clear_history_list()); #if defined(OS_ANDROID) if (NavigationControllerImpl::ValidateDataURLAsString(GetDataURLAsString())) { - request_params.data_url_as_string = GetDataURLAsString()->data(); + commit_params.data_url_as_string = GetDataURLAsString()->data(); } #endif - return request_params; + return commit_params; } void NavigationEntryImpl::ResetForCommit(FrameNavigationEntry* frame_entry) {
diff --git a/content/browser/frame_host/navigation_entry_impl.h b/content/browser/frame_host/navigation_entry_impl.h index 89d2fb5..ada1a1c 100644 --- a/content/browser/frame_host/navigation_entry_impl.h +++ b/content/browser/frame_host/navigation_entry_impl.h
@@ -33,7 +33,7 @@ namespace content { struct CommonNavigationParams; -struct RequestNavigationParams; +struct CommitNavigationParams; class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry { public: @@ -189,7 +189,7 @@ PreviewsState previews_state, base::TimeTicks navigation_start, base::TimeTicks input_start) const; - RequestNavigationParams ConstructRequestNavigationParams( + CommitNavigationParams ConstructCommitNavigationParams( const FrameNavigationEntry& frame_entry, const GURL& original_url, const std::string& original_method,
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 115f298..df434ea 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -288,7 +288,7 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated( FrameTreeNode* frame_tree_node, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool browser_initiated, const std::string& extra_headers, const FrameNavigationEntry& frame_entry, @@ -317,7 +317,7 @@ std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest( frame_tree_node, common_params, std::move(navigation_params), - request_params, browser_initiated, false /* from_begin_navigation */, + commit_params, browser_initiated, false /* from_begin_navigation */, false /* is_for_commit */, &frame_entry, &entry, std::move(navigation_ui_data), nullptr, nullptr)); navigation_request->blob_url_loader_factory_ = @@ -350,7 +350,7 @@ // TODO(clamy): See if the navigation start time should be measured in the // renderer and sent to the browser instead of being measured here. - RequestNavigationParams request_params( + CommitNavigationParams commit_params( override_user_agent, std::vector<GURL>(), // redirects common_params.url, common_params.method, @@ -366,7 +366,7 @@ false, // is_view_source false /*should_clear_history_list*/); std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest( - frame_tree_node, common_params, std::move(begin_params), request_params, + frame_tree_node, common_params, std::move(begin_params), commit_params, false, // browser_initiated true, // from_begin_navigation false, // is_for_commit @@ -399,7 +399,7 @@ base::Optional<SourceLocation>(), false /* started_from_context_menu */, params.gesture == NavigationGestureUser, InitiatorCSPInfo(), std::string() /* href_translate */, base::TimeTicks::Now()); - RequestNavigationParams request_params( + CommitNavigationParams commit_params( params.is_overriding_user_agent, params.redirects, params.original_request_url, params.method, false /* can_load_local_resources */, params.page_state, @@ -412,7 +412,7 @@ mojom::BeginNavigationParamsPtr begin_params = mojom::BeginNavigationParams::New(); std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest( - frame_tree_node, common_params, std::move(begin_params), request_params, + frame_tree_node, common_params, std::move(begin_params), commit_params, !is_renderer_initiated, false /* from_begin_navigation */, true /* is_for_commit */, entry ? entry->GetFrameEntry(frame_tree_node) : nullptr, entry, @@ -432,7 +432,7 @@ FrameTreeNode* frame_tree_node, const CommonNavigationParams& common_params, mojom::BeginNavigationParamsPtr begin_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool browser_initiated, bool from_begin_navigation, bool is_for_commit, @@ -444,7 +444,7 @@ : frame_tree_node_(frame_tree_node), common_params_(common_params), begin_params_(std::move(begin_params)), - request_params_(request_params), + commit_params_(commit_params), browser_initiated_(browser_initiated), navigation_ui_data_(std::move(navigation_ui_data)), state_(NOT_STARTED), @@ -511,7 +511,7 @@ nav_entry_id_ = entry->GetUniqueID(); std::string user_agent_override; - if (request_params.is_overriding_user_agent || + if (commit_params.is_overriding_user_agent || (entry && entry->GetIsOverridingUserAgent())) { user_agent_override = frame_tree_node_->navigator()->GetDelegate()->GetUserAgentOverride(); @@ -538,17 +538,17 @@ frame_tree_node); if (begin_params_->is_form_submission) { - if (browser_initiated && !request_params.post_content_type.empty()) { + if (browser_initiated && !commit_params.post_content_type.empty()) { // This is a form resubmit, so make sure to set the Content-Type header. headers.SetHeaderIfMissing(net::HttpRequestHeaders::kContentType, - request_params.post_content_type); + commit_params.post_content_type); } else if (!browser_initiated) { // Save the Content-Type in case the form is resubmitted. This will get // sent back to the renderer in the CommitNavigation IPC. The renderer // will then send it back with the post body so that we can access it // along with the body in FrameNavigationEntry::page_state_. headers.GetHeader(net::HttpRequestHeaders::kContentType, - &request_params_.post_content_type); + &commit_params_.post_content_type); } } @@ -592,7 +592,7 @@ if (!GetContentClient()->browser()->ShouldOverrideUrlLoading( frame_tree_node_->frame_tree_node_id(), browser_initiated_, - request_params_.original_url, request_params_.original_method, + commit_params_.original_url, commit_params_.original_method, common_params_.has_user_gesture, false, frame_tree_node_->IsMainFrame(), common_params_.transition, &should_override_url_loading)) { @@ -714,19 +714,19 @@ // |begin_params_->client_side_redirect_url| will be set when the navigation // was triggered by a client-side redirect. redirect_chain.push_back(begin_params_->client_side_redirect_url); - } else if (!request_params_.redirects.empty()) { + } else if (!commit_params_.redirects.empty()) { // Redirects that were specified at NavigationRequest creation time should // be added to the list of redirects. In particular, if the // NavigationRequest was created at commit time, redirects that happened - // during the navigation have been added to |request_params_.redirects| and + // during the navigation have been added to |commit_params_.redirects| and // should be passed to the NavigationHandle. - for (const auto& url : request_params_.redirects) + for (const auto& url : commit_params_.redirects) redirect_chain.push_back(url); } // Finally, add the current URL to the vector of redirects. // Note: for NavigationRequests created at commit time, the current URL has - // been added to |request_params_.redirects|, so don't add it a second time. + // been added to |commit_params_.redirects|, so don't add it a second time. if (!is_for_commit) redirect_chain.push_back(common_params_.url); @@ -892,17 +892,17 @@ common_params_.post_data = nullptr; // Mark time for the Navigation Timing API. - if (request_params_.navigation_timing.redirect_start.is_null()) { - request_params_.navigation_timing.redirect_start = - request_params_.navigation_timing.fetch_start; + if (commit_params_.navigation_timing.redirect_start.is_null()) { + commit_params_.navigation_timing.redirect_start = + commit_params_.navigation_timing.fetch_start; } - request_params_.navigation_timing.redirect_end = base::TimeTicks::Now(); - request_params_.navigation_timing.fetch_start = base::TimeTicks::Now(); + commit_params_.navigation_timing.redirect_end = base::TimeTicks::Now(); + commit_params_.navigation_timing.fetch_start = base::TimeTicks::Now(); - request_params_.redirect_response.push_back(response->head); - request_params_.redirect_infos.push_back(redirect_info); + commit_params_.redirect_response.push_back(response->head); + commit_params_.redirect_infos.push_back(redirect_info); - request_params_.redirects.push_back(common_params_.url); + commit_params_.redirects.push_back(common_params_.url); common_params_.url = redirect_info.new_url; common_params_.method = redirect_info.new_method; common_params_.referrer.url = GURL(redirect_info.new_referrer); @@ -1033,13 +1033,13 @@ net_error_ = net::ERR_ABORTED; } - // Update the service worker and AppCache params of the request params. - request_params_.service_worker_provider_id = + // Update the service worker and AppCache params of the commit params. + commit_params_.service_worker_provider_id = navigation_handle_->service_worker_handle() ? navigation_handle_->service_worker_handle() ->service_worker_provider_host_id() : kInvalidServiceWorkerProviderId; - request_params_.appcache_host_id = + commit_params_.appcache_host_id = navigation_handle_->appcache_handle() ? navigation_handle_->appcache_handle()->appcache_host_id() : kAppCacheNoHostId; @@ -1050,8 +1050,8 @@ // worker ready time if it is greater than the current value to make sure // fetch start timing always comes after worker start timing (if a service // worker intercepted the navigation). - request_params_.navigation_timing.fetch_start = - std::max(request_params_.navigation_timing.fetch_start, + commit_params_.navigation_timing.fetch_start = + std::max(commit_params_.navigation_timing.fetch_start, response->head.service_worker_ready_time); // A navigation is user activated if it contains a user gesture or the frame @@ -1071,8 +1071,8 @@ // context menu. This should apply to pages that open in a new tab and we // have to follow the referrer. It means that the activation might not be // transmitted if it should have. - if (request_params_.was_activated == WasActivatedOption::kUnknown) { - request_params_.was_activated = WasActivatedOption::kNo; + if (commit_params_.was_activated == WasActivatedOption::kUnknown) { + commit_params_.was_activated = WasActivatedOption::kNo; if (navigation_handle_->IsRendererInitiated() && (frame_tree_node_->has_received_user_gesture() || @@ -1080,7 +1080,7 @@ ShouldPropagateUserActivation( frame_tree_node_->current_origin(), url::Origin::Create(navigation_handle_->GetURL()))) { - request_params_.was_activated = WasActivatedOption::kYes; + commit_params_.was_activated = WasActivatedOption::kYes; // TODO(805871): the next check is relying on // navigation_handle_->GetReferrer() but should ideally use a more // reliable source for the originating URL when the navigation is renderer @@ -1091,7 +1091,7 @@ ShouldPropagateUserActivation( url::Origin::Create(navigation_handle_->GetReferrer().url), url::Origin::Create(navigation_handle_->GetURL()))) { - request_params_.was_activated = WasActivatedOption::kYes; + commit_params_.was_activated = WasActivatedOption::kYes; } } @@ -1410,7 +1410,7 @@ bool can_create_service_worker = (frame_tree_node_->pending_frame_policy().sandbox_flags & blink::WebSandboxFlags::kOrigin) != blink::WebSandboxFlags::kOrigin; - request_params_.should_create_service_worker = can_create_service_worker; + commit_params_.should_create_service_worker = can_create_service_worker; if (can_create_service_worker) { ServiceWorkerContextWrapper* service_worker_context = static_cast<ServiceWorkerContextWrapper*>( @@ -1428,7 +1428,7 @@ } // Mark the fetch_start (Navigation Timing API). - request_params_.navigation_timing.fetch_start = base::TimeTicks::Now(); + commit_params_.navigation_timing.fetch_start = base::TimeTicks::Now(); GURL base_url; #if defined(OS_ANDROID) @@ -1711,7 +1711,7 @@ void NavigationRequest::CommitErrorPage( RenderFrameHostImpl* render_frame_host, const base::Optional<std::string>& error_page_content) { - UpdateRequestNavigationParamsHistory(); + UpdateCommitNavigationParamsHistory(); frame_tree_node_->TransferNavigationRequestOwnership(render_frame_host); if (IsPerNavigationMojoInterfaceEnabled() && request_navigation_client_ && request_navigation_client_.is_bound()) { @@ -1733,12 +1733,12 @@ navigation_handle_->ReadyToCommitNavigation(render_frame_host, true); render_frame_host->FailedNavigation( - navigation_handle_->GetNavigationId(), common_params_, request_params_, + navigation_handle_->GetNavigationId(), common_params_, commit_params_, has_stale_copy_in_cache_, net_error_, error_page_content); } void NavigationRequest::CommitNavigation() { - UpdateRequestNavigationParamsHistory(); + UpdateCommitNavigationParamsHistory(); DCHECK(response_ || !IsURLHandledByNetworkStack(common_params_.url) || navigation_handle_->IsSameDocument()); DCHECK(!common_params_.url.SchemeIs(url::kJavaScriptScheme)); @@ -1782,7 +1782,7 @@ } render_frame_host->CommitNavigation( navigation_handle_->GetNavigationId(), response_.get(), - std::move(url_loader_client_endpoints_), common_params_, request_params_, + std::move(url_loader_client_endpoints_), common_params_, commit_params_, is_view_source_, std::move(subresource_loader_params_), std::move(subresource_overrides_), devtools_navigation_token_); @@ -1895,7 +1895,7 @@ parent->ShouldModifyRequestUrlForCsp(true /* is subresource */)) { upgrade_if_insecure_ = true; parent->ModifyRequestUrlForCsp(&common_params_.url); - request_params_.original_url = common_params_.url; + commit_params_.original_url = common_params_.url; } } @@ -1973,12 +1973,12 @@ return LegacyProtocolInSubresourceCheckResult::BLOCK_REQUEST; } -void NavigationRequest::UpdateRequestNavigationParamsHistory() { +void NavigationRequest::UpdateCommitNavigationParamsHistory() { NavigationController* navigation_controller = frame_tree_node_->navigator()->GetController(); - request_params_.current_history_list_offset = + commit_params_.current_history_list_offset = navigation_controller->GetCurrentEntryIndex(); - request_params_.current_history_list_length = + commit_params_.current_history_list_length = navigation_controller->GetEntryCount(); }
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index 8431404..ee33d80 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -86,7 +86,7 @@ static std::unique_ptr<NavigationRequest> CreateBrowserInitiated( FrameTreeNode* frame_tree_node, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool browser_initiated, const std::string& extra_headers, const FrameNavigationEntry& frame_entry, @@ -135,9 +135,7 @@ return begin_params_.get(); } - const RequestNavigationParams& request_params() const { - return request_params_; - } + const CommitNavigationParams& commit_params() const { return commit_params_; } // Updates the navigation start time. void set_navigation_start_time(const base::TimeTicks& time) { @@ -175,7 +173,7 @@ associated_site_instance_type_ = type; } - void set_was_discarded() { request_params_.was_discarded = true; } + void set_was_discarded() { commit_params_.was_discarded = true; } NavigationHandleImpl* navigation_handle() const { return navigation_handle_.get(); @@ -232,7 +230,7 @@ NavigationRequest(FrameTreeNode* frame_tree_node, const CommonNavigationParams& common_params, mojom::BeginNavigationParamsPtr begin_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool browser_initiated, bool from_begin_navigation, bool is_for_commit, @@ -350,9 +348,9 @@ const; // Called before a commit. Updates the history index and length held in - // RequestNavigationParams. This is used to update this shared state with the + // CommitNavigationParams. This is used to update this shared state with the // renderer process. - void UpdateRequestNavigationParamsHistory(); + void UpdateCommitNavigationParamsHistory(); // Called when an ongoing renderer-initiated navigation is aborted. // Only used with PerNavigationMojoInterface enabled. @@ -374,11 +372,11 @@ // redirects. // Note: |common_params_| and |begin_params_| are not const as they can be // modified during redirects. - // Note: |request_params_| is not const because service_worker_provider_id + // Note: |commit_params_| is not const because service_worker_provider_id // and should_create_service_worker will be set in OnResponseStarted. CommonNavigationParams common_params_; mojom::BeginNavigationParamsPtr begin_params_; - RequestNavigationParams request_params_; + CommitNavigationParams commit_params_; const bool browser_initiated_; // Stores the NavigationUIData for this navigation until the NavigationHandle
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index f4c38a2..dbb4903 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc
@@ -336,7 +336,7 @@ bool should_dispatch_beforeunload = !FrameMsg_Navigate_Type::IsSameDocument( request->common_params().navigation_type) && - !request->request_params().is_history_navigation_in_new_child && + !request->commit_params().is_history_navigation_in_new_child && frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload( false /* check_subframes_only */); @@ -594,7 +594,7 @@ // Client redirects during the initial history navigation of a child frame // should take precedence over the history navigation (despite being renderer- // initiated). See https://crbug.com/348447 and https://crbug.com/691168. - if (ongoing_navigation_request && ongoing_navigation_request->request_params() + if (ongoing_navigation_request && ongoing_navigation_request->commit_params() .is_history_navigation_in_new_child) { // Preemptively clear this local pointer before deleting the request. ongoing_navigation_request = nullptr;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index e9a5273..cad68ea 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -4151,7 +4151,7 @@ base::Optional<SourceLocation>(), false /* started_from_context_menu */, false /* has_user_gesture */, InitiatorCSPInfo(), std::string()); CommitNavigation(0, nullptr, network::mojom::URLLoaderClientEndpointsPtr(), - common_params, RequestNavigationParams(), false, + common_params, CommitNavigationParams(), false, base::nullopt, base::nullopt /* subresource_overrides */, base::UnguessableToken::Create() /* not traced */); } @@ -4482,7 +4482,7 @@ network::ResourceResponse* response, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool is_view_source, base::Optional<SubresourceLoaderParams> subresource_loader_params, base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> @@ -4501,7 +4501,7 @@ const bool is_first_navigation = !has_committed_any_navigation_; has_committed_any_navigation_ = true; - UpdatePermissionsForNavigation(common_params, request_params); + UpdatePermissionsForNavigation(common_params, commit_params); // Get back to a clean state, in case we start a new navigation without // completing an unload handler. @@ -4660,7 +4660,7 @@ if (is_same_document) { DCHECK(same_document_navigation_request_); GetNavigationControl()->CommitSameDocumentNavigation( - common_params, request_params, + common_params, commit_params, base::BindOnce(&RenderFrameHostImpl::OnSameDocumentCommitProcessed, base::Unretained(this), same_document_navigation_request_->navigation_handle() @@ -4731,7 +4731,7 @@ if (IsPerNavigationMojoInterfaceEnabled() && navigation_request_ && navigation_request_->GetCommitNavigationClient()) { navigation_request_->GetCommitNavigationClient()->CommitNavigation( - head, common_params, request_params, + head, common_params, commit_params, std::move(url_loader_client_endpoints), std::move(subresource_loader_factories), std::move(subresource_overrides), std::move(controller), @@ -4740,7 +4740,7 @@ base::Unretained(this), navigation_id)); } else { GetNavigationControl()->CommitNavigation( - head, common_params, request_params, + head, common_params, commit_params, std::move(url_loader_client_endpoints), std::move(subresource_loader_factories), std::move(subresource_overrides), std::move(controller), @@ -4775,7 +4775,7 @@ void RenderFrameHostImpl::FailedNavigation( int64_t navigation_id, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool has_stale_copy_in_cache, int error_code, const base::Optional<std::string>& error_page_content) { @@ -4785,7 +4785,7 @@ // Update renderer permissions even for failed commits, so that for example // the URL bar correctly displays privileged URLs instead of filtering them. - UpdatePermissionsForNavigation(common_params, request_params); + UpdatePermissionsForNavigation(common_params, commit_params); // Get back to a clean state, in case a new navigation started without // completing an unload handler. @@ -4818,13 +4818,13 @@ if (IsPerNavigationMojoInterfaceEnabled() && request && request->GetCommitNavigationClient()) { request->GetCommitNavigationClient()->CommitFailedNavigation( - common_params, request_params, has_stale_copy_in_cache, error_code, + common_params, commit_params, has_stale_copy_in_cache, error_code, error_page_content, std::move(subresource_loader_factories), base::BindOnce(&RenderFrameHostImpl::OnCrossDocumentCommitProcessed, base::Unretained(this), navigation_id)); } else { GetNavigationControl()->CommitFailedNavigation( - common_params, request_params, has_stale_copy_in_cache, error_code, + common_params, commit_params, has_stale_copy_in_cache, error_code, error_page_content, std::move(subresource_loader_factories), base::BindOnce(&RenderFrameHostImpl::OnCrossDocumentCommitProcessed, base::Unretained(this), navigation_id)); @@ -5265,7 +5265,7 @@ void RenderFrameHostImpl::UpdatePermissionsForNavigation( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params) { + const CommitNavigationParams& commit_params) { // Browser plugin guests are not allowed to navigate outside web-safe schemes, // so do not grant them the ability to commit additional URLs. if (!GetProcess()->IsForGuestsOnly()) { @@ -5287,8 +5287,8 @@ // access again. Abuse is prevented, because the files listed in the page // state are validated earlier, when they are received from the renderer (in // RenderFrameHostImpl::CanAccessFilesOfPageState). - if (request_params.page_state.IsValid()) - GrantFileAccessFromPageState(request_params.page_state); + if (commit_params.page_state.IsValid()) + GrantFileAccessFromPageState(commit_params.page_state); // We may be here after transferring navigation to a different renderer // process. In this case, we need to ensure that the new renderer retains @@ -6072,7 +6072,7 @@ } if (navigation_request_) - was_discarded_ = navigation_request_->request_params().was_discarded; + was_discarded_ = navigation_request_->commit_params().was_discarded; // Find the appropriate NavigationRequest for this navigation. std::unique_ptr<NavigationRequest> navigation_request;
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 788fea70..b2ac802 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -154,7 +154,7 @@ struct ContextMenuParams; struct FrameOwnerProperties; struct PendingNavigation; -struct RequestNavigationParams; +struct CommitNavigationParams; struct ResourceTimingInfo; struct SubresourceLoaderParams; @@ -631,7 +631,7 @@ network::ResourceResponse* response, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool is_view_source, base::Optional<SubresourceLoaderParams> subresource_loader_params, base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> @@ -642,7 +642,7 @@ // an error page. void FailedNavigation(int64_t navigation_id, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool has_stale_copy_in_cache, int error_code, const base::Optional<std::string>& error_page_content); @@ -1099,7 +1099,7 @@ void UpdatePermissionsForNavigation( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params); + const CommitNavigationParams& commit_params); // Creates a Network Service-backed factory from appropriate |NetworkContext| // and sets a connection error handler to trigger @@ -1490,7 +1490,7 @@ bool has_shown_beforeunload_dialog_ = false; // Returns whether the tab was previously discarded. - // This is passed to RequestNavigationParams in NavigationRequest. + // This is passed to CommitNavigationParams in NavigationRequest. bool was_discarded_; // Indicates whether this RenderFrameHost is in the process of loading a
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc index 099d478..679bae80 100644 --- a/content/browser/frame_host/render_frame_host_manager_unittest.cc +++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -461,8 +461,8 @@ *frame_entry, request_body, frame_entry->url(), frame_entry->referrer(), navigate_type, PREVIEWS_UNSPECIFIED, base::TimeTicks::Now(), base::TimeTicks::Now()); - RequestNavigationParams request_params = - entry.ConstructRequestNavigationParams( + CommitNavigationParams commit_params = + entry.ConstructCommitNavigationParams( *frame_entry, common_params.url, common_params.method, false, entry.GetSubframeUniqueNames(frame_tree_node), controller->GetPendingEntryIndex() == @@ -470,11 +470,11 @@ controller->GetIndexOfEntry(&entry), controller->GetLastCommittedEntryIndex(), controller->GetEntryCount()); - request_params.post_content_type = post_content_type; + commit_params.post_content_type = post_content_type; std::unique_ptr<NavigationRequest> navigation_request = NavigationRequest::CreateBrowserInitiated( - frame_tree_node, common_params, request_params, + frame_tree_node, common_params, commit_params, !entry.is_renderer_initiated(), entry.extra_headers(), *frame_entry, entry, request_body, nullptr /* navigation_ui_data */); @@ -2858,19 +2858,17 @@ *frame_entry, nullptr, frame_entry->url(), frame_entry->referrer(), FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED, base::TimeTicks::Now(), base::TimeTicks::Now()); - RequestNavigationParams request_params = - entry.ConstructRequestNavigationParams( - *frame_entry, common_params.url, common_params.method, false, - entry.GetSubframeUniqueNames(frame_tree_node), - controller().GetPendingEntryIndex() == -1 /* intended_as_new_entry */, - static_cast<NavigationControllerImpl&>(controller()) - .GetIndexOfEntry(&entry), - controller().GetLastCommittedEntryIndex(), - controller().GetEntryCount()); + CommitNavigationParams commit_params = entry.ConstructCommitNavigationParams( + *frame_entry, common_params.url, common_params.method, false, + entry.GetSubframeUniqueNames(frame_tree_node), + controller().GetPendingEntryIndex() == -1 /* intended_as_new_entry */, + static_cast<NavigationControllerImpl&>(controller()) + .GetIndexOfEntry(&entry), + controller().GetLastCommittedEntryIndex(), controller().GetEntryCount()); std::unique_ptr<NavigationRequest> navigation_request = NavigationRequest::CreateBrowserInitiated( - frame_tree_node, common_params, request_params, + frame_tree_node, common_params, commit_params, !entry.is_renderer_initiated(), entry.extra_headers(), *frame_entry, entry, nullptr /* request_body */, nullptr /* navigation_ui_data */); manager->DidCreateNavigationRequest(navigation_request.get()); @@ -2934,19 +2932,17 @@ *frame_entry, nullptr, frame_entry->url(), frame_entry->referrer(), FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED, base::TimeTicks::Now(), base::TimeTicks::Now()); - RequestNavigationParams request_params = - entry.ConstructRequestNavigationParams( - *frame_entry, common_params.url, common_params.method, false, - entry.GetSubframeUniqueNames(frame_tree_node), - controller().GetPendingEntryIndex() == -1 /* intended_as_new_entry */, - static_cast<NavigationControllerImpl&>(controller()) - .GetIndexOfEntry(&entry), - controller().GetLastCommittedEntryIndex(), - controller().GetEntryCount()); + CommitNavigationParams commit_params = entry.ConstructCommitNavigationParams( + *frame_entry, common_params.url, common_params.method, false, + entry.GetSubframeUniqueNames(frame_tree_node), + controller().GetPendingEntryIndex() == -1 /* intended_as_new_entry */, + static_cast<NavigationControllerImpl&>(controller()) + .GetIndexOfEntry(&entry), + controller().GetLastCommittedEntryIndex(), controller().GetEntryCount()); std::unique_ptr<NavigationRequest> navigation_request = NavigationRequest::CreateBrowserInitiated( - frame_tree_node, common_params, request_params, + frame_tree_node, common_params, commit_params, !entry.is_renderer_initiated(), entry.extra_headers(), *frame_entry, entry, nullptr /* request_body */, nullptr /* navigation_ui_data */); manager->DidCreateNavigationRequest(navigation_request.get()); @@ -3007,19 +3003,17 @@ *frame_entry, nullptr, frame_entry->url(), frame_entry->referrer(), FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED, base::TimeTicks::Now(), base::TimeTicks::Now()); - RequestNavigationParams request_params = - entry.ConstructRequestNavigationParams( - *frame_entry, common_params.url, common_params.method, false, - entry.GetSubframeUniqueNames(frame_tree_node), - controller().GetPendingEntryIndex() == -1 /* intended_as_new_entry */, - static_cast<NavigationControllerImpl&>(controller()) - .GetIndexOfEntry(&entry), - controller().GetLastCommittedEntryIndex(), - controller().GetEntryCount()); + CommitNavigationParams commit_params = entry.ConstructCommitNavigationParams( + *frame_entry, common_params.url, common_params.method, false, + entry.GetSubframeUniqueNames(frame_tree_node), + controller().GetPendingEntryIndex() == -1 /* intended_as_new_entry */, + static_cast<NavigationControllerImpl&>(controller()) + .GetIndexOfEntry(&entry), + controller().GetLastCommittedEntryIndex(), controller().GetEntryCount()); std::unique_ptr<NavigationRequest> navigation_request = NavigationRequest::CreateBrowserInitiated( - frame_tree_node, common_params, request_params, + frame_tree_node, common_params, commit_params, !entry.is_renderer_initiated(), entry.extra_headers(), *frame_entry, entry, nullptr /* request_body */, nullptr /* navigation_ui_data */); manager->DidCreateNavigationRequest(navigation_request.get());
diff --git a/content/browser/media/session/audio_focus_delegate_default.cc b/content/browser/media/session/audio_focus_delegate_default.cc index 9962a55..dbe761a7 100644 --- a/content/browser/media/session/audio_focus_delegate_default.cc +++ b/content/browser/media/session/audio_focus_delegate_default.cc
@@ -6,9 +6,11 @@ #include "base/no_destructor.h" #include "base/unguessable_token.h" +#include "build/build_config.h" #include "content/browser/media/session/media_session_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/service_manager_connection.h" +#include "media/base/media_switches.h" #include "services/media_session/public/cpp/switches.h" #include "services/media_session/public/mojom/audio_focus.mojom.h" #include "services/media_session/public/mojom/constants.mojom.h" @@ -22,10 +24,20 @@ const char kAudioFocusSourceName[] = "web"; -static const base::UnguessableToken& GetBrowserGroupId() { - static const base::NoDestructor<base::UnguessableToken> token( - base::UnguessableToken::Create()); - return *token; +base::UnguessableToken GetAudioFocusGroupId(MediaSessionImpl* session) { + // Allow the media session to override the group id. + if (session->audio_focus_group_id() != base::UnguessableToken::Null()) + return session->audio_focus_group_id(); + + // If it is enabled then use a shared audio focus group id for the whole + // browser. This will mean that tabs will share audio focus. + if (base::FeatureList::IsEnabled(media::kUseGroupedBrowserAudioFocus)) { + static const base::NoDestructor<base::UnguessableToken> token( + base::UnguessableToken::Create()); + return *token; + } + + return base::UnguessableToken::Create(); } // AudioFocusDelegateDefault is the default implementation of @@ -102,9 +114,7 @@ audio_focus_ptr_->RequestGroupedAudioFocus( mojo::MakeRequest(&request_client_ptr_), std::move(media_session), session_info_.Clone(), audio_focus_type, - media_session_->audio_focus_group_id() == base::UnguessableToken::Null() - ? GetBrowserGroupId() - : media_session_->audio_focus_group_id(), + GetAudioFocusGroupId(media_session_), base::BindOnce(&AudioFocusDelegateDefault::FinishAudioFocusRequest, base::Unretained(this), audio_focus_type)); }
diff --git a/content/browser/media/session/audio_focus_delegate_default_browsertest.cc b/content/browser/media/session/audio_focus_delegate_default_browsertest.cc index 45cdfc24..67b9aec 100644 --- a/content/browser/media/session/audio_focus_delegate_default_browsertest.cc +++ b/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
@@ -4,12 +4,14 @@ #include "base/command_line.h" #include "base/unguessable_token.h" +#include "build/build_config.h" #include "content/browser/media/session/media_session_impl.h" #include "content/browser/media/session/mock_media_session_player_observer.h" #include "content/public/common/service_manager_connection.h" #include "content/public/test/content_browser_test.h" #include "content/shell/browser/shell.h" #include "media/base/media_content_type.h" +#include "media/base/media_switches.h" #include "services/media_session/public/cpp/switches.h" #include "services/media_session/public/cpp/test/audio_focus_test_util.h" #include "services/media_session/public/cpp/test/mock_media_session.h" @@ -106,7 +108,8 @@ media_session::test::MockMediaSessionMojoObserver observer( *media_session); observer.WaitForState( - use_separate_group_id + use_separate_group_id || !base::FeatureList::IsEnabled( + media::kUseGroupedBrowserAudioFocus) ? media_session::mojom::MediaSessionInfo::SessionState::kSuspended : media_session::mojom::MediaSessionInfo::SessionState::kActive); }
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc index 3e6cbc8..3c720de3 100644 --- a/content/browser/media/session/media_session_impl.cc +++ b/content/browser/media/session/media_session_impl.cc
@@ -224,6 +224,13 @@ const std::set<media_session::mojom::MediaSessionAction>& actions) { for (auto& observer : observers_) observer.MediaSessionActionsChanged(actions); + + std::vector<media_session::mojom::MediaSessionAction> actions_vec( + actions.begin(), actions.end()); + mojo_observers_.ForAllPtrs( + [&actions_vec](media_session::mojom::MediaSessionObserver* observer) { + observer->MediaSessionActionsChanged(actions_vec); + }); } bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer, @@ -754,6 +761,15 @@ observer->MediaSessionMetadataChanged( routed_service_ ? routed_service_->metadata() : base::nullopt); + if (routed_service_) { + std::vector<media_session::mojom::MediaSessionAction> actions( + routed_service_->actions().begin(), routed_service_->actions().end()); + observer->MediaSessionActionsChanged(actions); + } else { + observer->MediaSessionActionsChanged( + std::vector<media_session::mojom::MediaSessionAction>()); + } + mojo_observers_.AddPtr(std::move(observer)); }
diff --git a/content/browser/media/session/media_session_impl_service_routing_unittest.cc b/content/browser/media/session/media_session_impl_service_routing_unittest.cc index d033481..546ce54 100644 --- a/content/browser/media/session/media_session_impl_service_routing_unittest.cc +++ b/content/browser/media/session/media_session_impl_service_routing_unittest.cc
@@ -605,4 +605,27 @@ } } +TEST_F(MediaSessionImplServiceRoutingTest, + NotifyMojoObserverWhenActionsChange) { + CreateServiceForFrame(main_frame_); + StartPlayerForFrame(main_frame_); + + services_[main_frame_]->EnableAction( + media_session::mojom::MediaSessionAction::kPlay); + + media_session::test::MockMediaSessionMojoObserver observer( + *GetMediaSession()); + observer.WaitForActions(); + + EXPECT_EQ(1u, observer.actions().size()); + EXPECT_EQ(media_session::mojom::MediaSessionAction::kPlay, + observer.actions()[0]); + + services_[main_frame_]->DisableAction( + media_session::mojom::MediaSessionAction::kPlay); + observer.WaitForActions(); + + EXPECT_TRUE(observer.actions().empty()); +} + } // namespace content
diff --git a/content/browser/service_worker/service_worker_navigation_handle.h b/content/browser/service_worker/service_worker_navigation_handle.h index fffae16..45ab104 100644 --- a/content/browser/service_worker/service_worker_navigation_handle.h +++ b/content/browser/service_worker/service_worker_navigation_handle.h
@@ -36,7 +36,7 @@ // provider id was updated. // // 5) When the navigation is ready to commit, the NavigationRequest will -// update the RequestNavigationParams based on the id from the +// update the CommitNavigationParams based on the id from the // ServiceWorkerNavigationHandle. // // 6) If the commit leads to the creation of a ServiceWorkerNetworkProvider
diff --git a/content/common/frame.mojom b/content/common/frame.mojom index b1bfe9ad5..7e999e4 100644 --- a/content/common/frame.mojom +++ b/content/common/frame.mojom
@@ -64,7 +64,7 @@ // See src/content/common/navigation_params.h [Native] -struct RequestNavigationParams; +struct CommitNavigationParams; // Implemented by the frame provider and currently must be associated with the // legacy IPC channel. @@ -104,7 +104,7 @@ CommitNavigation( network.mojom.URLResponseHead head, CommonNavigationParams common_params, - RequestNavigationParams request_params, + CommitNavigationParams request_params, network.mojom.URLLoaderClientEndpoints? url_loader_client_endpoints, blink.mojom.URLLoaderFactoryBundle? subresource_loader_factories, array<TransferrableURLLoader>? subresource_overrides, @@ -124,7 +124,7 @@ // subresources where applicable. CommitFailedNavigation( CommonNavigationParams common_params, - RequestNavigationParams request_params, + CommitNavigationParams request_params, bool has_stale_copy_in_cache, int32 error_code, string? error_page_content, @@ -138,7 +138,7 @@ // if the renderer committed another navigation in the meantime. CommitSameDocumentNavigation( CommonNavigationParams common_params, - RequestNavigationParams request_params) + CommitNavigationParams request_params) => (blink.mojom.CommitResult commit_result); // Asks the renderer to handle a renderer-debug URL.
diff --git a/content/common/frame.typemap b/content/common/frame.typemap index 792faa10..7ae0bf1 100644 --- a/content/common/frame.typemap +++ b/content/common/frame.typemap
@@ -10,5 +10,5 @@ ] type_mappings = [ "content.mojom.CommonNavigationParams=content::CommonNavigationParams", - "content.mojom.RequestNavigationParams=content::RequestNavigationParams", + "content.mojom.CommitNavigationParams=content::CommitNavigationParams", ]
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index bdf5fc3..5738a30 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -493,7 +493,7 @@ IPC_STRUCT_TRAITS_MEMBER(fetch_start) IPC_STRUCT_TRAITS_END() -IPC_STRUCT_TRAITS_BEGIN(content::RequestNavigationParams) +IPC_STRUCT_TRAITS_BEGIN(content::CommitNavigationParams) IPC_STRUCT_TRAITS_MEMBER(is_overriding_user_agent) IPC_STRUCT_TRAITS_MEMBER(redirects) IPC_STRUCT_TRAITS_MEMBER(redirect_response)
diff --git a/content/common/navigation_client.mojom b/content/common/navigation_client.mojom index 68fcecb..64e54037 100644 --- a/content/common/navigation_client.mojom +++ b/content/common/navigation_client.mojom
@@ -19,7 +19,7 @@ // See src/content/common/navigation_params.h [Native] -struct RequestNavigationParams; +struct CommitNavigationParams; interface NavigationClient { // Tells the renderer that a navigation is ready to commit. @@ -55,7 +55,7 @@ CommitNavigation( network.mojom.URLResponseHead head, CommonNavigationParams common_params, - RequestNavigationParams request_params, + CommitNavigationParams request_params, network.mojom.URLLoaderClientEndpoints? url_loader_client_endpoints, blink.mojom.URLLoaderFactoryBundle? subresource_loader_factories, array<TransferrableURLLoader>? subresource_overrides, @@ -75,7 +75,7 @@ // subresources where applicable. CommitFailedNavigation( CommonNavigationParams common_params, - RequestNavigationParams request_params, + CommitNavigationParams request_params, bool has_stale_copy_in_cache, int32 error_code, string? error_page_content,
diff --git a/content/common/navigation_params.cc b/content/common/navigation_params.cc index f27cfbd1..8d8ffee 100644 --- a/content/common/navigation_params.cc +++ b/content/common/navigation_params.cc
@@ -103,9 +103,9 @@ CommonNavigationParams::~CommonNavigationParams() = default; -RequestNavigationParams::RequestNavigationParams() = default; +CommitNavigationParams::CommitNavigationParams() = default; -RequestNavigationParams::RequestNavigationParams( +CommitNavigationParams::CommitNavigationParams( bool is_overriding_user_agent, const std::vector<GURL>& redirects, const GURL& original_url, @@ -137,9 +137,9 @@ is_view_source(is_view_source), should_clear_history_list(should_clear_history_list) {} -RequestNavigationParams::RequestNavigationParams( - const RequestNavigationParams& other) = default; +CommitNavigationParams::CommitNavigationParams( + const CommitNavigationParams& other) = default; -RequestNavigationParams::~RequestNavigationParams() = default; +CommitNavigationParams::~CommitNavigationParams() = default; } // namespace content
diff --git a/content/common/navigation_params.h b/content/common/navigation_params.h index 42885d5..6d3d932 100644 --- a/content/common/navigation_params.h +++ b/content/common/navigation_params.h
@@ -237,7 +237,7 @@ // PlzNavigate // Timings collected in the browser during navigation for the -// Navigation Timing API. Sent to Blink in RequestNavigationParams when +// Navigation Timing API. Sent to Blink in CommitNavigationParams when // the navigation is ready to be committed. struct CONTENT_EXPORT NavigationTiming { base::TimeTicks redirect_start; @@ -245,29 +245,27 @@ base::TimeTicks fetch_start; }; -// Used by FrameMsg_Navigate. Holds the parameters needed by the renderer to -// start a browser-initiated navigation besides those in CommonNavigationParams. -// PlzNavigate: sent to the renderer to make it issue a stream request for a -// navigation that is ready to commit. -struct CONTENT_EXPORT RequestNavigationParams { - RequestNavigationParams(); - RequestNavigationParams(bool is_overriding_user_agent, - const std::vector<GURL>& redirects, - const GURL& original_url, - const std::string& original_method, - bool can_load_local_resources, - const PageState& page_state, - int nav_entry_id, - bool is_history_navigation_in_new_child, - std::map<std::string, bool> subframe_unique_names, - bool intended_as_new_entry, - int pending_history_list_offset, - int current_history_list_offset, - int current_history_list_length, - bool is_view_source, - bool should_clear_history_list); - RequestNavigationParams(const RequestNavigationParams& other); - ~RequestNavigationParams(); +// Used by commit IPC messages. Holds the parameters needed by the renderer to +// commit a navigation besides those in CommonNavigationParams. +struct CONTENT_EXPORT CommitNavigationParams { + CommitNavigationParams(); + CommitNavigationParams(bool is_overriding_user_agent, + const std::vector<GURL>& redirects, + const GURL& original_url, + const std::string& original_method, + bool can_load_local_resources, + const PageState& page_state, + int nav_entry_id, + bool is_history_navigation_in_new_child, + std::map<std::string, bool> subframe_unique_names, + bool intended_as_new_entry, + int pending_history_list_offset, + int current_history_list_offset, + int current_history_list_length, + bool is_view_source, + bool should_clear_history_list); + CommitNavigationParams(const CommitNavigationParams& other); + ~CommitNavigationParams(); // Whether or not the user agent override string should be used. bool is_overriding_user_agent = false;
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc index 9e74214..ef1334c 100644 --- a/content/public/test/render_view_test.cc +++ b/content/public/test/render_view_test.cc
@@ -576,7 +576,7 @@ RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); TestRenderFrame* frame = static_cast<TestRenderFrame*>(impl->GetMainRenderFrame()); - frame->Navigate(common_params, RequestNavigationParams()); + frame->Navigate(common_params, CommitNavigationParams()); FrameLoadWaiter(frame).Wait(); view_->GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases( blink::WebWidget::LifecycleUpdateReason::kTest); @@ -717,16 +717,16 @@ PREVIEWS_UNSPECIFIED, base::TimeTicks::Now(), "GET", nullptr, base::Optional<SourceLocation>(), false /* started_from_context_menu */, false /* has_user_gesture */, InitiatorCSPInfo(), std::string()); - RequestNavigationParams request_params; - request_params.page_state = state; - request_params.nav_entry_id = pending_offset + 1; - request_params.pending_history_list_offset = pending_offset; - request_params.current_history_list_offset = impl->history_list_offset_; - request_params.current_history_list_length = history_list_length; + CommitNavigationParams commit_params; + commit_params.page_state = state; + commit_params.nav_entry_id = pending_offset + 1; + commit_params.pending_history_list_offset = pending_offset; + commit_params.current_history_list_offset = impl->history_list_offset_; + commit_params.current_history_list_length = history_list_length; TestRenderFrame* frame = static_cast<TestRenderFrame*>(impl->GetMainRenderFrame()); - frame->Navigate(common_params, request_params); + frame->Navigate(common_params, commit_params); // The load actually happens asynchronously, so we pump messages to process // the pending continuation.
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc index 98a4da4..2462fad6 100644 --- a/content/renderer/loader/web_url_loader_impl.cc +++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -45,7 +45,6 @@ #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" #include "net/http/http_response_headers.h" -#include "net/http/http_util.h" #include "net/ssl/ssl_cipher_suite_names.h" #include "net/ssl/ssl_connection_status_flags.h" #include "net/ssl/ssl_info.h" @@ -841,20 +840,6 @@ WebURLResponse response; PopulateURLResponse(url_, info, &response, report_raw_headers_, request_id_); - if (info.headers.get() && info.mime_type == "multipart/x-mixed-replace") { - std::string content_type; - info.headers->EnumerateHeader(nullptr, "content-type", &content_type); - - std::string mime_type; - std::string charset; - bool had_charset = false; - std::string boundary; - net::HttpUtil::ParseContentType(content_type, &mime_type, &charset, - &had_charset, &boundary); - base::TrimString(boundary, " \"", &boundary); - response.SetMultipartBoundary(boundary.data(), boundary.size()); - } - if (use_stream_on_response_) { auto read_handle = std::make_unique<SharedMemoryDataConsumerHandle>( base::BindOnce(&Context::CancelBodyStreaming, this),
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc index 15514e08..954659d 100644 --- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc +++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
@@ -136,10 +136,9 @@ } void GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs( - std::vector<media::mojom::SupportedVideoDecoderConfigPtr> - supported_configs) { + const std::vector<media::SupportedVideoDecoderConfig>& supported_configs) { base::AutoLock lock(supported_decoder_configs_lock_); - supported_decoder_configs_ = std::move(supported_configs); + supported_decoder_configs_ = supported_configs; video_decoder_.reset(); } @@ -200,18 +199,9 @@ if (!supported_decoder_configs_) return true; - for (const media::mojom::SupportedVideoDecoderConfigPtr& supported : - *supported_decoder_configs_) { - if (config.profile() >= supported->profile_min && - config.profile() <= supported->profile_max && - config.coded_size().width() >= supported->coded_size_min.width() && - config.coded_size().width() <= supported->coded_size_max.width() && - config.coded_size().height() >= supported->coded_size_min.height() && - config.coded_size().height() <= supported->coded_size_max.height() && - (config.is_encrypted() ? supported->allow_encrypted - : !supported->require_encrypted)) { + for (const auto& supported : *supported_decoder_configs_) { + if (supported.Matches(config)) return true; - } } return false; }
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h index 4239d7f..af23b7f 100644 --- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h +++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h
@@ -158,8 +158,7 @@ void SetContextProviderLostOnMainThread(); void OnSupportedDecoderConfigs( - std::vector<media::mojom::SupportedVideoDecoderConfigPtr> - supported_configs); + const std::vector<media::SupportedVideoDecoderConfig>& supported_configs); const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; @@ -193,7 +192,10 @@ // SupportedDecoderConfigs state. mojo::InterfacePtr<media::mojom::VideoDecoder> video_decoder_; base::Lock supported_decoder_configs_lock_; - base::Optional<std::vector<media::mojom::SupportedVideoDecoderConfigPtr>> + // If the Optional is empty, then we have not yet gotten the configs. If the + // Optional contains an empty vector, then we have gotten the result and there + // are no supported configs. + base::Optional<std::vector<media::SupportedVideoDecoderConfig>> supported_decoder_configs_ GUARDED_BY(supported_decoder_configs_lock_); // For sending requests to allocate shared memory in the Browser process.
diff --git a/content/renderer/navigation_client.cc b/content/renderer/navigation_client.cc index 649ad2a..febe3c7 100644 --- a/content/renderer/navigation_client.cc +++ b/content/renderer/navigation_client.cc
@@ -16,7 +16,7 @@ void NavigationClient::CommitNavigation( const network::ResourceResponseHead& head, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders, base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>> @@ -31,7 +31,7 @@ // unexpectedly abort the ongoing navigation. Remove when the races are fixed. ResetDisconnectionHandler(); render_frame_->CommitNavigation( - head, common_params, request_params, + head, common_params, commit_params, std::move(url_loader_client_endpoints), std::move(subresource_loaders), std::move(subresource_overrides), std::move(controller_service_worker_info), @@ -41,7 +41,7 @@ void NavigationClient::CommitFailedNavigation( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool has_stale_copy_in_cache, int error_code, const base::Optional<std::string>& error_page_content, @@ -49,7 +49,7 @@ CommitFailedNavigationCallback callback) { ResetDisconnectionHandler(); render_frame_->CommitFailedNavigation( - common_params, request_params, has_stale_copy_in_cache, error_code, + common_params, commit_params, has_stale_copy_in_cache, error_code, error_page_content, std::move(subresource_loaders), std::move(callback)); }
diff --git a/content/renderer/navigation_client.h b/content/renderer/navigation_client.h index 1499207..753b655e 100644 --- a/content/renderer/navigation_client.h +++ b/content/renderer/navigation_client.h
@@ -21,7 +21,7 @@ void CommitNavigation( const network::ResourceResponseHead& head, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders, base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>> @@ -33,7 +33,7 @@ CommitNavigationCallback callback) override; void CommitFailedNavigation( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool has_stale_copy_in_cache, int error_code, const base::Optional<std::string>& error_page_content,
diff --git a/content/renderer/navigation_state.cc b/content/renderer/navigation_state.cc index 54b4cc2b..97b6a39 100644 --- a/content/renderer/navigation_state.cc +++ b/content/renderer/navigation_state.cc
@@ -15,10 +15,10 @@ // static std::unique_ptr<NavigationState> NavigationState::CreateBrowserInitiated( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, base::TimeTicks time_commit_requested, mojom::FrameNavigationControl::CommitNavigationCallback callback) { - return base::WrapUnique(new NavigationState(common_params, request_params, + return base::WrapUnique(new NavigationState(common_params, commit_params, time_commit_requested, false, std::move(callback))); } @@ -26,7 +26,7 @@ // static std::unique_ptr<NavigationState> NavigationState::CreateContentInitiated() { return base::WrapUnique(new NavigationState( - CommonNavigationParams(), RequestNavigationParams(), base::TimeTicks(), + CommonNavigationParams(), CommitNavigationParams(), base::TimeTicks(), true, content::mojom::FrameNavigationControl::CommitNavigationCallback())); } @@ -54,7 +54,7 @@ NavigationState::NavigationState( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, base::TimeTicks time_commit_requested, bool is_content_initiated, mojom::FrameNavigationControl::CommitNavigationCallback callback) @@ -62,7 +62,7 @@ was_within_same_document_(false), is_content_initiated_(is_content_initiated), common_params_(common_params), - request_params_(request_params), + commit_params_(commit_params), time_commit_requested_(time_commit_requested), navigation_client_(nullptr), commit_callback_(std::move(callback)) {}
diff --git a/content/renderer/navigation_state.h b/content/renderer/navigation_state.h index ea329af..95db5e1d 100644 --- a/content/renderer/navigation_state.h +++ b/content/renderer/navigation_state.h
@@ -25,7 +25,7 @@ static std::unique_ptr<NavigationState> CreateBrowserInitiated( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, base::TimeTicks time_commit_requested, mojom::FrameNavigationControl::CommitNavigationCallback callback); @@ -41,9 +41,7 @@ bool IsContentInitiated(); const CommonNavigationParams& common_params() const { return common_params_; } - const RequestNavigationParams& request_params() const { - return request_params_; - } + const CommitNavigationParams& commit_params() const { return commit_params_; } bool request_committed() const { return request_committed_; } void set_request_committed(bool value) { request_committed_ = value; } void set_was_within_same_document(bool value) { @@ -73,7 +71,7 @@ private: NavigationState( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, base::TimeTicks time_commit_requested, bool is_content_initiated, content::mojom::FrameNavigationControl::CommitNavigationCallback @@ -98,7 +96,7 @@ // swaps because FrameLoader::loadWithNavigationAction treats loads before a // FrameLoader has committedFirstRealDocumentLoad as a replacement. (Added for // http://crbug.com/178380). - const RequestNavigationParams request_params_; + const CommitNavigationParams commit_params_; // Time when RenderFrameImpl::CommitNavigation() is called. base::TimeTicks time_commit_requested_;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 39e2f20..33b0e82 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -426,17 +426,17 @@ WebURLRequest CreateURLRequestForNavigation( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, std::unique_ptr<NavigationResponseOverrideParameters> response_override, bool is_view_source_mode_enabled) { // Use the original navigation url to construct the WebURLRequest. The // WebURLloaderImpl will replay the redirects afterwards and will eventually // commit the final url. - const GURL navigation_url = !request_params.original_url.is_empty() - ? request_params.original_url + const GURL navigation_url = !commit_params.original_url.is_empty() + ? commit_params.original_url : common_params.url; - const std::string navigation_method = !request_params.original_method.empty() - ? request_params.original_method + const std::string navigation_method = !commit_params.original_method.empty() + ? commit_params.original_method : common_params.method; WebURLRequest request(navigation_url); request.SetHTTPMethod(WebString::FromUTF8(navigation_method)); @@ -458,10 +458,10 @@ if (common_params.post_data) { request.SetHTTPBody(GetWebHTTPBodyForRequestBody(*common_params.post_data)); - if (!request_params.post_content_type.empty()) { + if (!commit_params.post_content_type.empty()) { request.AddHTTPHeaderField( WebString::FromASCII(net::HttpRequestHeaders::kContentType), - WebString::FromASCII(request_params.post_content_type)); + WebString::FromASCII(commit_params.post_content_type)); } } @@ -485,10 +485,10 @@ auto extra_data = std::make_unique<RequestExtraData>(); extra_data->set_navigation_response_override(std::move(response_override)); - extra_data->set_navigation_initiated_by_renderer( - request_params.nav_entry_id == 0); + extra_data->set_navigation_initiated_by_renderer(commit_params.nav_entry_id == + 0); request.SetExtraData(std::move(extra_data)); - request.SetWasDiscarded(request_params.was_discarded); + request.SetWasDiscarded(commit_params.was_discarded); return request; } @@ -848,7 +848,7 @@ // navigation parameters available in the RenderFrameImpl. std::unique_ptr<DocumentState> BuildDocumentStateFromParams( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, base::TimeTicks time_commit_requested, mojom::FrameNavigationControl::CommitNavigationCallback commit_callback, const network::ResourceResponseHead* head) { @@ -875,12 +875,12 @@ } internal_data->set_is_overriding_user_agent( - request_params.is_overriding_user_agent); + commit_params.is_overriding_user_agent); internal_data->set_must_reset_scroll_and_scale_state( common_params.navigation_type == FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL); document_state->set_can_load_local_resources( - request_params.can_load_local_resources); + commit_params.can_load_local_resources); if (head) { if (head->headers) @@ -907,7 +907,7 @@ InternalDocumentStateData::FromDocumentState(document_state.get()) ->set_navigation_state(NavigationState::CreateBrowserInitiated( - common_params, request_params, time_commit_requested, + common_params, commit_params, time_commit_requested, std::move(commit_callback))); return document_state; } @@ -982,10 +982,10 @@ // Fills navigation data sent by the browser to a blink understandable // format, blink::WebNavigationParams. void FillNavigationParams(const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, blink::WebNavigationParams* navigation_params) { navigation_params->navigation_timings = BuildNavigationTimings( - common_params.navigation_start, request_params.navigation_timing, + common_params.navigation_start, commit_params.navigation_timing, common_params.input_start); if (common_params.source_location.has_value()) { @@ -999,7 +999,7 @@ } navigation_params->is_user_activated = - request_params.was_activated == WasActivatedOption::kYes; + commit_params.was_activated == WasActivatedOption::kYes; } } // namespace @@ -2830,11 +2830,11 @@ NavigationState* navigation_state = NavigationState::FromDocumentLoader(document_loader); document_state = BuildDocumentStateFromParams( - navigation_state->common_params(), navigation_state->request_params(), + navigation_state->common_params(), navigation_state->commit_params(), base::TimeTicks(), // Not used for failed navigation. CommitNavigationCallback(), nullptr); FillNavigationParams(navigation_state->common_params(), - navigation_state->request_params(), + navigation_state->commit_params(), navigation_params.get()); } else { document_state = BuildDocumentState(); @@ -3197,7 +3197,7 @@ void RenderFrameImpl::CommitNavigation( const network::ResourceResponseHead& head, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loader_factories, @@ -3214,8 +3214,8 @@ // frame, but it was aborted, then ignore it. if (!browser_side_navigation_pending_ && !browser_side_navigation_pending_url_.is_empty() && - browser_side_navigation_pending_url_ == request_params.original_url && - request_params.nav_entry_id == 0) { + browser_side_navigation_pending_url_ == commit_params.original_url && + commit_params.nav_entry_id == 0) { browser_side_navigation_pending_url_ = GURL(); std::move(callback).Run(blink::mojom::CommitResult::Aborted); return; @@ -3233,10 +3233,10 @@ // If the navigation is for "view source", the WebLocalFrame needs to be put // in a special mode. - if (request_params.is_view_source) + if (commit_params.is_view_source) frame_->EnableViewSourceMode(true); - PrepareFrameForCommit(common_params.url, request_params); + PrepareFrameForCommit(common_params.url, commit_params); // We only save metrics of the main frame's main resource to the // document state. In view source mode, we effectively let the user @@ -3246,12 +3246,12 @@ if (!frame_->Parent() && !frame_->IsViewSourceModeEnabled()) response_head = &head; std::unique_ptr<DocumentState> document_state(BuildDocumentStateFromParams( - common_params, request_params, base::TimeTicks::Now(), - std::move(callback), response_head)); + common_params, commit_params, base::TimeTicks::Now(), std::move(callback), + response_head)); blink::WebFrameLoadType load_type = NavigationTypeToLoadType( common_params.navigation_type, common_params.should_replace_current_entry, - request_params.page_state.IsValid()); + commit_params.page_state.IsValid()); WebHistoryItem item_for_history_navigation; blink::mojom::CommitResult commit_status = blink::mojom::CommitResult::Ok; @@ -3260,11 +3260,11 @@ // We must know the nav entry ID of the page we are navigating back to, // which should be the case because history navigations are routed via the // browser. - DCHECK_NE(0, request_params.nav_entry_id); + DCHECK_NE(0, commit_params.nav_entry_id); // Check that the history navigation can commit. commit_status = PrepareForHistoryNavigationCommit( - common_params.navigation_type, request_params, + common_params.navigation_type, commit_params, &item_for_history_navigation, &load_type); } @@ -3288,19 +3288,19 @@ navigation_params->is_client_redirect = is_client_redirect; navigation_params->service_worker_network_provider = BuildServiceWorkerNetworkProviderForNavigation( - &request_params, std::move(controller_service_worker_info)); - FillNavigationParams(common_params, request_params, navigation_params.get()); + &commit_params, std::move(controller_service_worker_info)); + FillNavigationParams(common_params, commit_params, navigation_params.get()); // Perform a navigation to a data url if needed (for main frames). // Note: the base URL might be invalid, so also check the data URL string. bool should_load_data_url = !common_params.base_url_for_data_url.is_empty(); #if defined(OS_ANDROID) - should_load_data_url |= !request_params.data_url_as_string.empty(); + should_load_data_url |= !commit_params.data_url_as_string.empty(); #endif if (is_main_frame_ && should_load_data_url) { std::string mime_type, charset, data; GURL base_url; - DecodeDataURL(common_params, request_params, &mime_type, &charset, &data, + DecodeDataURL(common_params, commit_params, &mime_type, &charset, &data, &base_url); navigation_params->request = WebURLRequest(base_url); navigation_params->data = WebData(data.c_str(), data.length()); @@ -3315,7 +3315,7 @@ // navigation in the renderer process should be simplified and avoid going // through the ResourceFetcher for the main resource. navigation_params->request = - CreateURLRequestForCommit(common_params, request_params, + CreateURLRequestForCommit(common_params, commit_params, std::move(url_loader_client_endpoints), head); } @@ -3335,7 +3335,7 @@ void RenderFrameImpl::CommitFailedNavigation( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool has_stale_copy_in_cache, int error_code, const base::Optional<std::string>& error_page_content, @@ -3347,7 +3347,7 @@ DCHECK( !FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type)); RenderFrameImpl::PrepareRenderViewForNavigation(common_params.url, - request_params); + commit_params); sync_navigation_callback_.Cancel(); // Log a console message for subframe loads that failed due to a legacy @@ -3373,7 +3373,7 @@ : WebURLError::HasCopyInCache::kFalse, WebURLError::IsWebSecurityViolation::kFalse, common_params.url); WebURLRequest failed_request = CreateURLRequestForNavigation( - common_params, request_params, + common_params, commit_params, /*response_override=*/nullptr, frame_->IsViewSourceModeEnabled()); if (!ShouldDisplayErrorPageForFailedLoad(error_code, common_params.url)) { @@ -3419,10 +3419,10 @@ bool replace = is_reload_or_history || common_params.url == GetLoadingUrl() || common_params.should_replace_current_entry; std::unique_ptr<HistoryEntry> history_entry; - if (request_params.page_state.IsValid()) - history_entry = PageStateToHistoryEntry(request_params.page_state); + if (commit_params.page_state.IsValid()) + history_entry = PageStateToHistoryEntry(commit_params.page_state); - if (request_params.nav_entry_id == 0) { + if (commit_params.nav_entry_id == 0) { // For renderer initiated navigations, we send out a // DidFailProvisionalLoad() notification. NotifyObserversOfFailedProvisionalLoad(error); @@ -3466,8 +3466,8 @@ navigation_params->frame_load_type = WebFrameLoadType::kReplaceCurrentItem; } navigation_params->service_worker_network_provider = - BuildServiceWorkerNetworkProviderForNavigation(&request_params, nullptr); - FillNavigationParams(common_params, request_params, navigation_params.get()); + BuildServiceWorkerNetworkProviderForNavigation(&commit_params, nullptr); + FillNavigationParams(common_params, commit_params, navigation_params.get()); failed_request.SetURL(GURL(kUnreachableWebDataURL)); failed_request.SetCacheMode(blink::mojom::FetchCacheMode::kNoStore); @@ -3479,7 +3479,7 @@ navigation_params->unreachable_url = error.url(); std::unique_ptr<DocumentState> document_state = BuildDocumentStateFromParams( - common_params, request_params, base::TimeTicks(), std::move(callback), + common_params, commit_params, base::TimeTicks(), std::move(callback), nullptr); // The load of the error page can result in this frame being removed. @@ -3498,32 +3498,32 @@ void RenderFrameImpl::CommitSameDocumentNavigation( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, CommitSameDocumentNavigationCallback callback) { DCHECK(!IsRendererDebugURL(common_params.url)); DCHECK(!FrameMsg_Navigate_Type::IsReload(common_params.navigation_type)); - DCHECK(!request_params.is_view_source); + DCHECK(!commit_params.is_view_source); DCHECK(FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type)); - PrepareFrameForCommit(common_params.url, request_params); + PrepareFrameForCommit(common_params.url, commit_params); blink::WebFrameLoadType load_type = NavigationTypeToLoadType( common_params.navigation_type, common_params.should_replace_current_entry, - request_params.page_state.IsValid()); + commit_params.page_state.IsValid()); blink::mojom::CommitResult commit_status = blink::mojom::CommitResult::Ok; WebHistoryItem item_for_history_navigation; if (common_params.navigation_type == FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT) { - DCHECK(request_params.page_state.IsValid()); + DCHECK(commit_params.page_state.IsValid()); // We must know the nav entry ID of the page we are navigating back to, // which should be the case because history navigations are routed via the // browser. - DCHECK_NE(0, request_params.nav_entry_id); - DCHECK(!request_params.is_history_navigation_in_new_child); + DCHECK_NE(0, commit_params.nav_entry_id); + DCHECK(!commit_params.is_history_navigation_in_new_child); commit_status = PrepareForHistoryNavigationCommit( - common_params.navigation_type, request_params, + common_params.navigation_type, commit_params, &item_for_history_navigation, &load_type); } @@ -3540,7 +3540,7 @@ internal_data->CopyFrom( InternalDocumentStateData::FromDocumentState(original_document_state)); internal_data->set_navigation_state(NavigationState::CreateBrowserInitiated( - common_params, request_params, + common_params, commit_params, base::TimeTicks(), // Not used for same-document navigation. CommitNavigationCallback())); @@ -3707,7 +3707,7 @@ return std::make_unique<RendererWebApplicationCacheHostImpl>( RenderViewImpl::FromWebView(frame_->View()), client, RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy(), - navigation_state->request_params().appcache_host_id, routing_id_); + navigation_state->commit_params().appcache_host_id, routing_id_); } std::unique_ptr<blink::WebContentSettingsClient> @@ -4228,7 +4228,7 @@ document_loader->SetExtraData(BuildDocumentState()); document_loader->SetServiceWorkerNetworkProvider( BuildServiceWorkerNetworkProviderForNavigation( - nullptr /* request_params */, nullptr /* controller_info */)); + nullptr /* commit_params */, nullptr /* controller_info */)); } } @@ -5504,11 +5504,11 @@ params->url_is_unreachable = document_loader->HasUnreachableURL(); params->method = "GET"; params->intended_as_new_entry = - navigation_state->request_params().intended_as_new_entry; + navigation_state->commit_params().intended_as_new_entry; params->should_replace_current_entry = document_loader->ReplacesCurrentHistoryItem(); params->post_id = -1; - params->nav_entry_id = navigation_state->request_params().nav_entry_id; + params->nav_entry_id = navigation_state->commit_params().nav_entry_id; // "Standard" commits from Blink create new NavigationEntries. We also treat // main frame "inert" commits as creating new NavigationEntries if they @@ -5601,7 +5601,7 @@ params->original_request_url = GetOriginalRequestURL(document_loader); params->history_list_was_cleared = - navigation_state->request_params().should_clear_history_list; + navigation_state->commit_params().should_clear_history_list; } else { // Subframe navigation: the type depends on whether this navigation // generated a new session history entry. When they do generate a session @@ -5612,7 +5612,7 @@ else params->transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME; - DCHECK(!navigation_state->request_params().should_clear_history_list); + DCHECK(!navigation_state->commit_params().should_clear_history_list); params->history_list_was_cleared = false; } @@ -5678,8 +5678,8 @@ blink::WebHistoryCommitType commit_type) { NavigationState* navigation_state = NavigationState::FromDocumentLoader(frame_->GetDocumentLoader()); - const RequestNavigationParams& request_params = - navigation_state->request_params(); + const CommitNavigationParams& commit_params = + navigation_state->commit_params(); // Update the current history item for this frame. current_history_item_ = item; @@ -5688,7 +5688,7 @@ current_history_item_.SetTarget( blink::WebString::FromUTF8(unique_name_helper_.value())); bool is_new_navigation = commit_type == blink::kWebStandardCommit; - if (request_params.should_clear_history_list) { + if (commit_params.should_clear_history_list) { render_view_->history_list_offset_ = 0; render_view_->history_list_length_ = 1; } else if (is_new_navigation) { @@ -5703,10 +5703,10 @@ render_view_->history_list_length_ = render_view_->history_list_offset_ + 1; } - } else if (request_params.nav_entry_id != 0 && - !request_params.intended_as_new_entry) { + } else if (commit_params.nav_entry_id != 0 && + !commit_params.intended_as_new_entry) { render_view_->history_list_offset_ = - navigation_state->request_params().pending_history_list_offset; + navigation_state->commit_params().pending_history_list_offset; } if (commit_type == blink::WebHistoryCommitType::kWebBackForwardCommit) @@ -5805,7 +5805,7 @@ void RenderFrameImpl::PrepareFrameForCommit( const GURL& url, - const RequestNavigationParams& request_params) { + const CommitNavigationParams& commit_params) { browser_side_navigation_pending_ = false; browser_side_navigation_pending_url_ = GURL(); sync_navigation_callback_.Cancel(); @@ -5813,12 +5813,12 @@ GetContentClient()->SetActiveURL( url, frame_->Top()->GetSecurityOrigin().ToString().Utf8()); - RenderFrameImpl::PrepareRenderViewForNavigation(url, request_params); + RenderFrameImpl::PrepareRenderViewForNavigation(url, commit_params); } blink::mojom::CommitResult RenderFrameImpl::PrepareForHistoryNavigationCommit( FrameMsg_Navigate_Type::Value navigation_type, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, WebHistoryItem* item_for_history_navigation, blink::WebFrameLoadType* load_type) { DCHECK(navigation_type == FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT || @@ -5827,7 +5827,7 @@ navigation_type == FrameMsg_Navigate_Type::RESTORE || navigation_type == FrameMsg_Navigate_Type::RESTORE_WITH_POST); std::unique_ptr<HistoryEntry> entry = - PageStateToHistoryEntry(request_params.page_state); + PageStateToHistoryEntry(commit_params.page_state); if (!entry) return blink::mojom::CommitResult::Aborted; @@ -5840,7 +5840,7 @@ // Keep track of which subframes the browser process has history items // for during a history navigation. - history_subframe_unique_names_ = request_params.subframe_unique_names; + history_subframe_unique_names_ = commit_params.subframe_unique_names; if (navigation_type == FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT) { // If this is marked as a same document load but we haven't committed @@ -5868,7 +5868,7 @@ bool interrupted_by_client_redirect = frame_->IsNavigationScheduledWithin(0) || frame_->GetProvisionalDocumentLoader() || !current_history_item_.IsNull(); - if (request_params.is_history_navigation_in_new_child && + if (commit_params.is_history_navigation_in_new_child && interrupted_by_client_redirect) { return blink::mojom::CommitResult::Aborted; } @@ -6186,7 +6186,7 @@ // though the provider should not be used for any actual networking. navigation_params->service_worker_network_provider = BuildServiceWorkerNetworkProviderForNavigation( - nullptr /* request_params */, + nullptr /* commit_params */, nullptr /* controller_service_worker_info */); frame_->CommitNavigation(std::move(navigation_params), BuildDocumentState()); } @@ -6475,7 +6475,7 @@ WebURLRequest RenderFrameImpl::CreateURLRequestForCommit( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, const network::ResourceResponseHead& head) { // This will override the url requested by the WebURLLoader, as well as @@ -6485,11 +6485,11 @@ response_override->url_loader_client_endpoints = std::move(url_loader_client_endpoints); response_override->response = head; - response_override->redirect_responses = request_params.redirect_response; - response_override->redirect_infos = request_params.redirect_infos; + response_override->redirect_responses = commit_params.redirect_response; + response_override->redirect_infos = commit_params.redirect_infos; WebURLRequest request = CreateURLRequestForNavigation( - common_params, request_params, std::move(response_override), + common_params, commit_params, std::move(response_override), frame_->IsViewSourceModeEnabled()); request.SetFrameType(IsTopLevelNavigation(frame_) ? network::mojom::RequestContextFrameType::kTopLevel @@ -6674,7 +6674,7 @@ void RenderFrameImpl::PrepareRenderViewForNavigation( const GURL& url, - const RequestNavigationParams& request_params) { + const CommitNavigationParams& commit_params) { DCHECK(render_view_->webview()); if (is_main_frame_) { @@ -6683,9 +6683,9 @@ } render_view_->history_list_offset_ = - request_params.current_history_list_offset; + commit_params.current_history_list_offset; render_view_->history_list_length_ = - request_params.current_history_list_length; + commit_params.current_history_list_length; } namespace { @@ -6838,17 +6838,16 @@ } } -void RenderFrameImpl::DecodeDataURL( - const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, - std::string* mime_type, - std::string* charset, - std::string* data, - GURL* base_url) { +void RenderFrameImpl::DecodeDataURL(const CommonNavigationParams& common_params, + const CommitNavigationParams& commit_params, + std::string* mime_type, + std::string* charset, + std::string* data, + GURL* base_url) { // A loadData request with a specified base URL. GURL data_url = common_params.url; #if defined(OS_ANDROID) - if (!request_params.data_url_as_string.empty()) { + if (!commit_params.data_url_as_string.empty()) { #if DCHECK_IS_ON() { std::string mime_type_tmp, charset_tmp, data_tmp; @@ -6857,7 +6856,7 @@ DCHECK(data_tmp.empty()); } #endif - data_url = GURL(request_params.data_url_as_string); + data_url = GURL(commit_params.data_url_as_string); if (!data_url.is_valid() || !data_url.SchemeIs(url::kDataScheme)) { data_url = common_params.url; } @@ -7291,14 +7290,14 @@ std::unique_ptr<blink::WebServiceWorkerNetworkProvider> RenderFrameImpl::BuildServiceWorkerNetworkProviderForNavigation( - const RequestNavigationParams* request_params, + const CommitNavigationParams* commit_params, blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info) { scoped_refptr<network::SharedURLLoaderFactory> fallback_factory = network::SharedURLLoaderFactory::Create( GetLoaderFactoryBundle()->CloneWithoutAppCacheFactory()); return ServiceWorkerNetworkProvider::CreateForNavigation( - routing_id_, request_params, frame_, + routing_id_, commit_params, frame_, std::move(controller_service_worker_info), std::move(fallback_factory)); }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index c41c69e..68fb96be 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -178,7 +178,7 @@ struct CustomContextMenuContext; struct FrameOwnerProperties; struct FrameReplicationState; -struct RequestNavigationParams; +struct CommitNavigationParams; struct ScreenInfo; class CONTENT_EXPORT RenderFrameImpl @@ -540,7 +540,7 @@ void CommitNavigation( const network::ResourceResponseHead& head, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders, base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> @@ -552,7 +552,7 @@ CommitNavigationCallback callback) override; void CommitFailedNavigation( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool has_stale_copy_in_cache, int error_code, const base::Optional<std::string>& error_page_content, @@ -560,7 +560,7 @@ CommitFailedNavigationCallback callback) override; void CommitSameDocumentNavigation( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, CommitSameDocumentNavigationCallback callback) override; void HandleRendererDebugURL(const GURL& url) override; void UpdateSubresourceLoaderFactories( @@ -1098,7 +1098,7 @@ // Creates a WebURLRequest to use fo the commit of a navigation. blink::WebURLRequest CreateURLRequestForCommit( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, const network::ResourceResponseHead& head); @@ -1158,7 +1158,7 @@ // Does preparation for the navigation to |url|. void PrepareRenderViewForNavigation( const GURL& url, - const RequestNavigationParams& request_params); + const CommitNavigationParams& commit_params); // Creates a placeholder document loader, while navigation is taking place, // either in the browser or in the renderer. @@ -1173,7 +1173,7 @@ // Decodes a data url for navigation commit. void DecodeDataURL(const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, std::string* mime_type, std::string* charset, std::string* data, @@ -1269,7 +1269,7 @@ // Updates the state of this frame when asked to commit a navigation. void PrepareFrameForCommit(const GURL& url, - const RequestNavigationParams& request_params); + const CommitNavigationParams& commit_params); // Updates the state when asked to commit a history navigation. Sets // |item_for_history_navigation| and |load_type| to the appropriate values for @@ -1297,7 +1297,7 @@ // so that it can be performed in cross-document fashion. blink::mojom::CommitResult PrepareForHistoryNavigationCommit( FrameMsg_Navigate_Type::Value navigation_type, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, blink::WebHistoryItem* item_for_history_navigation, blink::WebFrameLoadType* load_type); @@ -1308,7 +1308,7 @@ // to be supplied to the loader. std::unique_ptr<blink::WebServiceWorkerNetworkProvider> BuildServiceWorkerNetworkProviderForNavigation( - const RequestNavigationParams* request_params, + const CommitNavigationParams* commit_params, blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info);
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc index 9eb54432..2484a670 100644 --- a/content/renderer/render_frame_impl_browsertest.cc +++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -464,7 +464,7 @@ common_params.url = GURL("data:text/html,min_zoomlimit_test"); common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT; GetMainRenderFrame()->SetHostZoomLevel(common_params.url, kMinZoomLevel); - GetMainRenderFrame()->Navigate(common_params, RequestNavigationParams()); + GetMainRenderFrame()->Navigate(common_params, CommitNavigationParams()); base::RunLoop().RunUntilIdle(); EXPECT_DOUBLE_EQ(kMinZoomLevel, view_->GetWebView()->ZoomLevel()); @@ -473,7 +473,7 @@ ZoomFactorToZoomLevel(1.0)); common_params.url = GURL("data:text/html,max_zoomlimit_test"); GetMainRenderFrame()->SetHostZoomLevel(common_params.url, kMaxZoomLevel); - GetMainRenderFrame()->Navigate(common_params, RequestNavigationParams()); + GetMainRenderFrame()->Navigate(common_params, CommitNavigationParams()); base::RunLoop().RunUntilIdle(); EXPECT_DOUBLE_EQ(kMaxZoomLevel, view_->GetWebView()->ZoomLevel()); }
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 0d63fca..404f3ac2 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -271,16 +271,16 @@ void GoToOffsetWithParams(int offset, const PageState& state, const CommonNavigationParams common_params, - RequestNavigationParams request_params) { + CommitNavigationParams commit_params) { EXPECT_TRUE(common_params.transition & ui::PAGE_TRANSITION_FORWARD_BACK); int pending_offset = offset + view()->history_list_offset_; - request_params.page_state = state; - request_params.nav_entry_id = pending_offset + 1; - request_params.pending_history_list_offset = pending_offset; - request_params.current_history_list_offset = view()->history_list_offset_; - request_params.current_history_list_length = view()->history_list_length_; - frame()->Navigate(common_params, request_params); + commit_params.page_state = state; + commit_params.nav_entry_id = pending_offset + 1; + commit_params.pending_history_list_offset = pending_offset; + commit_params.current_history_list_offset = view()->history_list_offset_; + commit_params.current_history_list_length = view()->history_list_length_; + frame()->Navigate(common_params, commit_params); // The load actually happens asynchronously, so we pump messages to process // the pending continuation. @@ -586,7 +586,7 @@ TEST_F(RenderViewImplTest, OnNavigationHttpPost) { // An http url will trigger a resource load so cannot be used here. CommonNavigationParams common_params; - RequestNavigationParams request_params; + CommitNavigationParams commit_params; common_params.url = GURL("data:text/html,<div>Page</div>"); common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT; common_params.transition = ui::PAGE_TRANSITION_TYPED; @@ -600,7 +600,7 @@ post_data->AppendBytes(raw_data, length); common_params.post_data = post_data; - frame()->Navigate(common_params, request_params); + frame()->Navigate(common_params, commit_params); base::RunLoop().RunUntilIdle(); auto last_commit_params = frame()->TakeLastCommitParams(); @@ -637,12 +637,12 @@ common_params.transition = ui::PAGE_TRANSITION_TYPED; common_params.base_url_for_data_url = GURL("about:blank"); common_params.history_url_for_data_url = GURL("about:blank"); - RequestNavigationParams request_params; - request_params.data_url_as_string = + CommitNavigationParams commit_params; + commit_params.data_url_as_string = "data:text/html,<html><head><title>Data page</title></head></html>"; render_thread_->sink().ClearMessages(); - frame()->Navigate(common_params, request_params); + frame()->Navigate(common_params, commit_params); const IPC::Message* frame_title_msg = nullptr; do { base::RunLoop().RunUntilIdle(); @@ -1002,12 +1002,12 @@ // Navigate to other page, which triggers the swap in. CommonNavigationParams common_params; - RequestNavigationParams request_params; + CommitNavigationParams commit_params; common_params.url = GURL("data:text/html,<div>Page</div>"); common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT; common_params.transition = ui::PAGE_TRANSITION_TYPED; - provisional_frame->Navigate(common_params, request_params); + provisional_frame->Navigate(common_params, commit_params); base::RunLoop().RunUntilIdle(); EXPECT_EQ(device_scale, view()->GetDeviceScaleFactor()); @@ -1147,16 +1147,16 @@ // Go back to C and commit, preparing for our real test. CommonNavigationParams common_params_C; - RequestNavigationParams request_params_C; + CommitNavigationParams commit_params_C; common_params_C.navigation_type = FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT; common_params_C.transition = ui::PAGE_TRANSITION_FORWARD_BACK; - request_params_C.current_history_list_length = 4; - request_params_C.current_history_list_offset = 3; - request_params_C.pending_history_list_offset = 2; - request_params_C.nav_entry_id = 3; - request_params_C.page_state = state_C; - frame()->Navigate(common_params_C, request_params_C); + commit_params_C.current_history_list_length = 4; + commit_params_C.current_history_list_offset = 3; + commit_params_C.pending_history_list_offset = 2; + commit_params_C.nav_entry_id = 3; + commit_params_C.page_state = state_C; + frame()->Navigate(common_params_C, commit_params_C); base::RunLoop().RunUntilIdle(); render_thread_->sink().ClearMessages(); @@ -1166,29 +1166,29 @@ // Back to page B without committing. CommonNavigationParams common_params_B; - RequestNavigationParams request_params_B; + CommitNavigationParams commit_params_B; common_params_B.navigation_type = FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT; common_params_B.transition = ui::PAGE_TRANSITION_FORWARD_BACK; - request_params_B.current_history_list_length = 4; - request_params_B.current_history_list_offset = 2; - request_params_B.pending_history_list_offset = 1; - request_params_B.nav_entry_id = 2; - request_params_B.page_state = state_B; - frame()->Navigate(common_params_B, request_params_B); + commit_params_B.current_history_list_length = 4; + commit_params_B.current_history_list_offset = 2; + commit_params_B.pending_history_list_offset = 1; + commit_params_B.nav_entry_id = 2; + commit_params_B.page_state = state_B; + frame()->Navigate(common_params_B, commit_params_B); // Back to page A and commit. CommonNavigationParams common_params; - RequestNavigationParams request_params; + CommitNavigationParams commit_params; common_params.navigation_type = FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT; common_params.transition = ui::PAGE_TRANSITION_FORWARD_BACK; - request_params.current_history_list_length = 4; - request_params.current_history_list_offset = 2; - request_params.pending_history_list_offset = 0; - request_params.nav_entry_id = 1; - request_params.page_state = state_A; - frame()->Navigate(common_params, request_params); + commit_params.current_history_list_length = 4; + commit_params.current_history_list_offset = 2; + commit_params.pending_history_list_offset = 0; + commit_params.nav_entry_id = 1; + commit_params.page_state = state_A; + frame()->Navigate(common_params, commit_params); base::RunLoop().RunUntilIdle(); // Now ensure that the UpdateState message we receive is consistent @@ -1515,7 +1515,7 @@ CommonNavigationParams common_params; common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT; common_params.url = GURL("data:text/html,test data"); - frame()->Navigate(common_params, RequestNavigationParams()); + frame()->Navigate(common_params, CommitNavigationParams()); // An error occurred. view()->GetMainRenderFrame()->DidFailProvisionalLoad( @@ -1534,7 +1534,7 @@ CommonNavigationParams common_params; common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT; common_params.url = GURL("data:text/html,test data"); - frame()->Navigate(common_params, RequestNavigationParams()); + frame()->Navigate(common_params, CommitNavigationParams()); // A cancellation occurred. view()->GetMainRenderFrame()->DidFailProvisionalLoad( @@ -1913,19 +1913,19 @@ // Navigate the frame only. CommonNavigationParams common_params; - RequestNavigationParams request_params; + CommitNavigationParams commit_params; common_params.url = GURL("data:text/html,world"); common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT; common_params.transition = ui::PAGE_TRANSITION_TYPED; common_params.navigation_start = base::TimeTicks::FromInternalValue(1); - request_params.current_history_list_length = 1; - request_params.current_history_list_offset = 0; - request_params.pending_history_list_offset = 1; + commit_params.current_history_list_length = 1; + commit_params.current_history_list_offset = 0; + commit_params.pending_history_list_offset = 1; TestRenderFrame* subframe = static_cast<TestRenderFrame*>(RenderFrameImpl::FromWebFrame( frame()->GetWebFrame()->FindFrameByName("frame"))); - subframe->Navigate(common_params, request_params); + subframe->Navigate(common_params, commit_params); FrameLoadWaiter(subframe).Wait(); // Copy the document content to std::wstring and compare with the @@ -2034,7 +2034,7 @@ common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT; common_params.url = GURL("data:text/html,test data"); TestRenderFrame* main_frame = static_cast<TestRenderFrame*>(frame()); - main_frame->Navigate(common_params, RequestNavigationParams()); + main_frame->Navigate(common_params, CommitNavigationParams()); // An error occurred. main_frame->DidFailProvisionalLoad(error, blink::kWebStandardCommit); @@ -2061,7 +2061,7 @@ common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT; common_params.url = GURL("data:text/html,test data"); TestRenderFrame* main_frame = static_cast<TestRenderFrame*>(frame()); - main_frame->Navigate(common_params, RequestNavigationParams()); + main_frame->Navigate(common_params, CommitNavigationParams()); // An error occurred. main_frame->DidFailProvisionalLoad(error, blink::kWebStandardCommit); @@ -2097,7 +2097,7 @@ net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size())); TestRenderFrame* main_frame = static_cast<TestRenderFrame*>(frame()); - main_frame->Navigate(head, common_params, RequestNavigationParams()); + main_frame->Navigate(head, common_params, CommitNavigationParams()); main_frame->DidFinishDocumentLoad(); main_frame->RunScriptsAtDocumentReady(true); @@ -2239,7 +2239,7 @@ TEST_F(RenderViewImplTest, BrowserNavigationStart) { auto common_params = MakeCommonNavigationParams(-TimeDelta::FromSeconds(1)); - frame()->Navigate(common_params, RequestNavigationParams()); + frame()->Navigate(common_params, CommitNavigationParams()); NavigationState* navigation_state = NavigationState::FromDocumentLoader( frame()->GetWebFrame()->GetProvisionalDocumentLoader()); EXPECT_EQ(common_params.navigation_start, @@ -2256,7 +2256,7 @@ auto late_common_params = MakeCommonNavigationParams(TimeDelta::FromDays(42)); late_common_params.method = "POST"; - frame()->Navigate(late_common_params, RequestNavigationParams()); + frame()->Navigate(late_common_params, CommitNavigationParams()); base::RunLoop().RunUntilIdle(); base::Time after_navigation = base::Time::Now() + base::TimeDelta::FromDays(1); @@ -2275,7 +2275,7 @@ ExecuteJavaScriptForTests("document.title = 'Hi!';"); auto common_params = MakeCommonNavigationParams(-TimeDelta::FromSeconds(1)); - frame()->Navigate(common_params, RequestNavigationParams()); + frame()->Navigate(common_params, CommitNavigationParams()); NavigationState* navigation_state = NavigationState::FromDocumentLoader( frame()->GetWebFrame()->GetProvisionalDocumentLoader()); @@ -2298,7 +2298,7 @@ // The browser navigation_start should not be used because beforeunload will // be fired during Navigate. - frame()->Navigate(common_params, RequestNavigationParams()); + frame()->Navigate(common_params, CommitNavigationParams()); // The browser navigation_start is always used. NavigationState* navigation_state = NavigationState::FromDocumentLoader( @@ -2324,7 +2324,7 @@ common_params_back.navigation_type = FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT; GoToOffsetWithParams(-1, back_state, common_params_back, - RequestNavigationParams()); + CommitNavigationParams()); NavigationState* navigation_state = NavigationState::FromDocumentLoader( frame()->GetWebFrame()->GetDocumentLoader()); @@ -2340,7 +2340,7 @@ common_params_forward.navigation_type = FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT; GoToOffsetWithParams(1, forward_state, common_params_forward, - RequestNavigationParams()); + CommitNavigationParams()); navigation_state = NavigationState::FromDocumentLoader( frame()->GetWebFrame()->GetDocumentLoader()); EXPECT_EQ(common_params_forward.navigation_start, @@ -2353,14 +2353,14 @@ common_params.navigation_type = FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT; - RequestNavigationParams request_params; - request_params.page_state = + CommitNavigationParams commit_params; + commit_params.page_state = PageState::CreateForTesting(common_params.url, false, nullptr, nullptr); - request_params.nav_entry_id = 42; - request_params.pending_history_list_offset = 1; - request_params.current_history_list_offset = 0; - request_params.current_history_list_length = 1; - frame()->Navigate(common_params, request_params); + commit_params.nav_entry_id = 42; + commit_params.pending_history_list_offset = 1; + commit_params.current_history_list_offset = 0; + commit_params.current_history_list_length = 1; + frame()->Navigate(common_params, commit_params); NavigationState* navigation_state = NavigationState::FromDocumentLoader( frame()->GetWebFrame()->GetProvisionalDocumentLoader()); @@ -2418,10 +2418,10 @@ view()->HistoryForwardListCount() + 1); // Receive a CommitNavigation message with history parameters. - RequestNavigationParams request_params; - request_params.current_history_list_offset = 1; - request_params.current_history_list_length = 2; - frame()->Navigate(CommonNavigationParams(), request_params); + CommitNavigationParams commit_params; + commit_params.current_history_list_offset = 1; + commit_params.current_history_list_length = 2; + frame()->Navigate(CommonNavigationParams(), commit_params); // The current history list in RenderView is updated. EXPECT_EQ(1, view()->HistoryBackListCount()); @@ -2437,12 +2437,12 @@ view()->HistoryForwardListCount() + 1); // Receive a CommitNavigation message with history parameters. - RequestNavigationParams request_params; - request_params.current_history_list_offset = 1; - request_params.current_history_list_length = 25; - request_params.pending_history_list_offset = 12; - request_params.nav_entry_id = 777; - frame()->Navigate(CommonNavigationParams(), request_params); + CommitNavigationParams commit_params; + commit_params.current_history_list_offset = 1; + commit_params.current_history_list_length = 25; + commit_params.pending_history_list_offset = 12; + commit_params.nav_entry_id = 777; + frame()->Navigate(CommonNavigationParams(), commit_params); // The current history list in RenderView is updated. EXPECT_EQ(12, view()->HistoryBackListCount()); @@ -2458,11 +2458,11 @@ view()->HistoryForwardListCount() + 1); // Receive a CommitNavigation message with history parameters. - RequestNavigationParams request_params; - request_params.current_history_list_offset = 12; - request_params.current_history_list_length = 25; - request_params.should_clear_history_list = true; - frame()->Navigate(CommonNavigationParams(), request_params); + CommitNavigationParams commit_params; + commit_params.current_history_list_offset = 12; + commit_params.current_history_list_length = 25; + commit_params.should_clear_history_list = true; + frame()->Navigate(CommonNavigationParams(), commit_params); // The current history list in RenderView is updated. EXPECT_EQ(0, view()->HistoryBackListCount());
diff --git a/content/renderer/service_worker/service_worker_network_provider.cc b/content/renderer/service_worker/service_worker_network_provider.cc index 02e7e85..09562be 100644 --- a/content/renderer/service_worker/service_worker_network_provider.cc +++ b/content/renderer/service_worker/service_worker_network_provider.cc
@@ -158,7 +158,7 @@ std::unique_ptr<blink::WebServiceWorkerNetworkProvider> ServiceWorkerNetworkProvider::CreateForNavigation( int route_id, - const RequestNavigationParams* request_params, + const CommitNavigationParams* commit_params, blink::WebLocalFrame* frame, blink::mojom::ControllerServiceWorkerInfoPtr controller_info, scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory) { @@ -168,9 +168,9 @@ // however it will have an invalid id. bool should_create_provider = false; int provider_id = kInvalidServiceWorkerProviderId; - if (request_params) { - should_create_provider = request_params->should_create_service_worker; - provider_id = request_params->service_worker_provider_id; + if (commit_params) { + should_create_provider = commit_params->should_create_service_worker; + provider_id = commit_params->service_worker_provider_id; } else { should_create_provider = ((frame->EffectiveSandboxFlags() & blink::WebSandboxFlags::kOrigin) !=
diff --git a/content/renderer/service_worker/service_worker_network_provider.h b/content/renderer/service_worker/service_worker_network_provider.h index bb174c01..9fc21e4 100644 --- a/content/renderer/service_worker/service_worker_network_provider.h +++ b/content/renderer/service_worker/service_worker_network_provider.h
@@ -35,7 +35,7 @@ class URLLoaderFactory; } -struct RequestNavigationParams; +struct CommitNavigationParams; class ServiceWorkerProviderContext; // ServiceWorkerNetworkProvider enables the browser process to recognize @@ -59,12 +59,12 @@ // Creates a ServiceWorkerNetworkProvider for navigation and wraps it // with WebServiceWorkerNetworkProvider to be owned by Blink. // - // |request_params| are navigation parameters that were transmitted to the + // |commit_params| are navigation parameters that were transmitted to the // renderer by the browser on a navigation commit. It is null if we have not // yet heard from the browser (currently only during the time it takes from // having the renderer initiate a navigation until the browser commits it). // Note: in particular, provisional load failure do not provide - // |request_params|. + // |commit_params|. // TODO(ahemery): Update this comment when do not create placeholder document // loaders for renderer-initiated navigations. In this case, this should never // be null. @@ -79,7 +79,7 @@ static std::unique_ptr<blink::WebServiceWorkerNetworkProvider> CreateForNavigation( int route_id, - const RequestNavigationParams* request_params, + const CommitNavigationParams* commit_params, blink::WebLocalFrame* frame, blink::mojom::ControllerServiceWorkerInfoPtr controller_info, scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory);
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc index f13145a..4d889d1 100644 --- a/content/shell/browser/shell.cc +++ b/content/shell/browser/shell.cc
@@ -122,6 +122,12 @@ } } + // Always destroy WebContents before calling PlatformExit(). WebContents + // destruction sequence may depend on the resources destroyed in + // PlatformExit() (e.g. the display::Screen singleton). + web_contents_->SetDelegate(nullptr); + web_contents_.reset(); + if (windows_.empty()) { if (headless_) PlatformExit(); @@ -132,8 +138,6 @@ if (*g_quit_main_message_loop) std::move(*g_quit_main_message_loop).Run(); } - - web_contents_->SetDelegate(nullptr); } Shell* Shell::CreateShell(std::unique_ptr<WebContents> web_contents,
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc index 9f4f1f1..d216b50 100644 --- a/content/shell/browser/shell_content_browser_client.cc +++ b/content/shell/browser/shell_content_browser_client.cc
@@ -19,6 +19,7 @@ #include "build/build_config.h" #include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/login_delegate.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/page_navigator.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/resource_dispatcher_host.h" @@ -41,11 +42,14 @@ #include "content/shell/browser/shell_web_contents_view_delegate_creator.h" #include "content/shell/common/shell_messages.h" #include "content/shell/common/shell_switches.h" +#include "content/shell/common/web_test/web_test_switches.h" #include "content/shell/grit/shell_resources.h" #include "media/mojo/buildflags.h" #include "net/ssl/client_cert_identity.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context_getter.h" +#include "services/network/public/cpp/features.h" +#include "services/network/public/mojom/network_service.mojom.h" #include "services/test/echo/public/mojom/echo.mojom.h" #include "storage/browser/quota/quota_settings.h" #include "ui/base/resource/resource_bundle.h" @@ -451,6 +455,41 @@ } #endif // OS_WIN +network::mojom::NetworkContextPtr +ShellContentBrowserClient::CreateNetworkContext( + BrowserContext* context, + bool in_memory, + const base::FilePath& relative_partition_path) { + DCHECK(context); + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return nullptr; + + network::mojom::NetworkContextPtr network_context; + network::mojom::NetworkContextParamsPtr context_params = + network::mojom::NetworkContextParams::New(); + context_params->user_agent = GetUserAgent(); + context_params->accept_language = "en-us,en"; + context_params->enable_data_url_support = true; + +#if BUILDFLAG(ENABLE_REPORTING) + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kRunWebTests)) { + // Configure the Reporting service in a manner expected by certain Web + // Platform Tests (network-error-logging and reporting-api). + // + // (1) Always send reports (irrespective of BACKGROUND_SYNC permission) + // (2) Lower the timeout for sending reports. + context_params->reporting_delivery_interval = + kReportingDeliveryIntervalTimeForWebTests; + context_params->skip_reporting_send_permission_check = true; + } +#endif + + GetNetworkService()->CreateNetworkContext(MakeRequest(&network_context), + std::move(context_params)); + return network_context; +} + ShellBrowserContext* ShellContentBrowserClient::browser_context() { return shell_browser_main_parts_->browser_context(); }
diff --git a/content/shell/browser/shell_content_browser_client.h b/content/shell/browser/shell_content_browser_client.h index 52a837f..2a1f674 100644 --- a/content/shell/browser/shell_content_browser_client.h +++ b/content/shell/browser/shell_content_browser_client.h
@@ -100,6 +100,11 @@ bool PreSpawnRenderer(sandbox::TargetPolicy* policy) override; #endif + network::mojom::NetworkContextPtr CreateNetworkContext( + BrowserContext* context, + bool in_memory, + const base::FilePath& relative_partition_path) override; + ShellBrowserContext* browser_context(); ShellBrowserContext* off_the_record_browser_context(); ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate() { @@ -149,6 +154,10 @@ ShellBrowserMainParts* shell_browser_main_parts_; }; +// The delay for sending reports when running with --run-web-tests +constexpr base::TimeDelta kReportingDeliveryIntervalTimeForWebTests = + base::TimeDelta::FromMilliseconds(100); + } // namespace content #endif // CONTENT_SHELL_BROWSER_SHELL_CONTENT_BROWSER_CLIENT_H_
diff --git a/content/shell/browser/shell_url_request_context_getter.cc b/content/shell/browser/shell_url_request_context_getter.cc index 01ae2c4..a471a2d4 100644 --- a/content/shell/browser/shell_url_request_context_getter.cc +++ b/content/shell/browser/shell_url_request_context_getter.cc
@@ -231,7 +231,7 @@ net::ReportingPolicy::Create(); if (command_line.HasSwitch(switches::kRunWebTests)) reporting_policy->delivery_interval = - base::TimeDelta::FromMilliseconds(100); + kReportingDeliveryIntervalTimeForWebTests; builder.set_reporting_policy(std::move(reporting_policy)); }
diff --git a/content/test/mock_navigation_client_impl.cc b/content/test/mock_navigation_client_impl.cc index 1043925..452d53e9 100644 --- a/content/test/mock_navigation_client_impl.cc +++ b/content/test/mock_navigation_client_impl.cc
@@ -18,7 +18,7 @@ void MockNavigationClientImpl::CommitNavigation( const network::ResourceResponseHead& head, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders, base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>> @@ -30,7 +30,7 @@ void MockNavigationClientImpl::CommitFailedNavigation( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool has_stale_copy_in_cache, int error_code, const base::Optional<std::string>& error_page_content,
diff --git a/content/test/mock_navigation_client_impl.h b/content/test/mock_navigation_client_impl.h index 638b9b7..c16d07c 100644 --- a/content/test/mock_navigation_client_impl.h +++ b/content/test/mock_navigation_client_impl.h
@@ -20,7 +20,7 @@ void CommitNavigation( const network::ResourceResponseHead& head, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders, base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>> @@ -32,7 +32,7 @@ CommitNavigationCallback callback) override; void CommitFailedNavigation( const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, + const CommitNavigationParams& commit_params, bool has_stale_copy_in_cache, int error_code, const base::Optional<std::string>& error_page_content,
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc index 4e30a73..b87f192 100644 --- a/content/test/test_render_frame.cc +++ b/content/test/test_render_frame.cc
@@ -162,9 +162,9 @@ void TestRenderFrame::Navigate(const network::ResourceResponseHead& head, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params) { + const CommitNavigationParams& commit_params) { CommitNavigation( - head, common_params, request_params, + head, common_params, commit_params, network::mojom::URLLoaderClientEndpointsPtr(), std::make_unique<blink::URLLoaderFactoryBundleInfo>(), base::nullopt, blink::mojom::ControllerServiceWorkerInfoPtr(), @@ -173,8 +173,8 @@ } void TestRenderFrame::Navigate(const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params) { - Navigate(network::ResourceResponseHead(), common_params, request_params); + const CommitNavigationParams& commit_params) { + Navigate(network::ResourceResponseHead(), common_params, commit_params); } void TestRenderFrame::SwapOut(
diff --git a/content/test/test_render_frame.h b/content/test/test_render_frame.h index f123aed..b0ad152a 100644 --- a/content/test/test_render_frame.h +++ b/content/test/test_render_frame.h
@@ -21,7 +21,7 @@ struct CommonNavigationParams; class MockFrameHost; -struct RequestNavigationParams; +struct CommitNavigationParams; // A test class to use in RenderViewTests. class TestRenderFrame : public RenderFrameImpl { @@ -42,9 +42,9 @@ void WillSendRequest(blink::WebURLRequest& request) override; void Navigate(const network::ResourceResponseHead& head, const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params); + const CommitNavigationParams& commit_params); void Navigate(const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params); + const CommitNavigationParams& commit_params); void SwapOut(int proxy_routing_id, bool is_loading, const FrameReplicationState& replicated_frame_state);
diff --git a/docs/security/sheriff.md b/docs/security/sheriff.md index 47896ec..48e61b9 100644 --- a/docs/security/sheriff.md +++ b/docs/security/sheriff.md
@@ -70,6 +70,7 @@ and [chrome-security@google.com](https://groups.google.com/a/google.com/forum/#!forum/chrome-security) lists get a reply (by someone; not necessarily the sheriffs themselves). +See [go/chrome-security-emails](https://goto.google.com/chrome-security-emails) for a dashboard. * Note: external emails will always come in on security@chromium.org as chrome-security@google.com is a google-only list, but both need to be triaged. * Ensure [accurate label management](security-labels.md) on bugs, for example
diff --git a/extensions/browser/extension_function.cc b/extensions/browser/extension_function.cc index c2de84f..51271ba 100644 --- a/extensions/browser/extension_function.cc +++ b/extensions/browser/extension_function.cc
@@ -311,7 +311,7 @@ return NULL; } -bool ExtensionFunction::HasPermission() { +bool ExtensionFunction::HasPermission() const { Feature::Availability availability = ExtensionAPI::GetSharedInstance()->IsAvailable( name_, extension_.get(), source_context_type_, source_url(),
diff --git a/extensions/browser/extension_function.h b/extensions/browser/extension_function.h index 2201b0a..5be0273 100644 --- a/extensions/browser/extension_function.h +++ b/extensions/browser/extension_function.h
@@ -130,12 +130,10 @@ // Returns true if the function has permission to run. // - // The default implementation is to check the Extension's permissions against - // what this function requires to run, but some APIs may require finer - // grained control, such as tabs.executeScript being allowed for active tabs. - // - // This will be run after the function has been set up but before Run(). - virtual bool HasPermission(); + // This checks the Extension's permissions against the features declared in + // the *_features.json files. Note that some functions may perform additional + // checks in Run(), such as for specific host permissions or user gestures. + bool HasPermission() const; // The result of a function call. // @@ -272,10 +270,10 @@ int request_id() { return request_id_; } void set_source_url(const GURL& source_url) { source_url_ = source_url; } - const GURL& source_url() { return source_url_; } + const GURL& source_url() const { return source_url_; } void set_has_callback(bool has_callback) { has_callback_ = has_callback; } - bool has_callback() { return has_callback_; } + bool has_callback() const { return has_callback_; } void set_include_incognito_information(bool include) { include_incognito_information_ = include;
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index b33ceb3c..738dacf 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1366,6 +1366,7 @@ AUTOTESTPRIVATE_CLOSEAPP = 1303, ACCESSIBILITY_PRIVATE_SETSWITCHACCESSMENUSTATE = 1304, AUTOTESTPRIVATE_SENDASSISTANTTEXTQUERY = 1305, + AUTOTESTPRIVATE_SETCROSTINIAPPSCALED = 1306, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/common/common_manifest_handlers.cc b/extensions/common/common_manifest_handlers.cc index 74660a6..2ef361b 100644 --- a/extensions/common/common_manifest_handlers.cc +++ b/extensions/common/common_manifest_handlers.cc
@@ -52,8 +52,7 @@ registry->RegisterHandler(std::make_unique<BluetoothManifestHandler>()); registry->RegisterHandler(std::make_unique<ContentCapabilitiesHandler>()); registry->RegisterHandler(std::make_unique<ContentScriptsHandler>()); - registry->RegisterHandler(std::make_unique<CSPHandler>(false)); - registry->RegisterHandler(std::make_unique<CSPHandler>(true)); + registry->RegisterHandler(std::make_unique<CSPHandler>()); registry->RegisterHandler( std::make_unique<declarative_net_request::DNRManifestHandler>()); registry->RegisterHandler(std::make_unique<DeclarativeManifestHandler>());
diff --git a/extensions/common/manifest.h b/extensions/common/manifest.h index 0596978..609643b 100644 --- a/extensions/common/manifest.h +++ b/extensions/common/manifest.h
@@ -181,6 +181,9 @@ // These access the wrapped manifest value, returning false when the property // does not exist or if the manifest type can't access it. + // TODO(karandeepb): These methods should be changed to use base::StringPiece. + // Better, we should pass a list of path components instead of a unified + // |path| to do away with our usage of deprecated base::Value methods. bool HasKey(const std::string& key) const; bool HasPath(const std::string& path) const; bool Get(const std::string& path, const base::Value** out_value) const;
diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc index fed39270..17e168c 100644 --- a/extensions/common/manifest_constants.cc +++ b/extensions/common/manifest_constants.cc
@@ -598,8 +598,6 @@ "Invalid value for 'sandbox.pages'."; const char kInvalidSandboxedPage[] = "Invalid value for 'sandbox.pages[*]'."; -const char kInvalidSandboxedPagesCSP[] = - "Invalid value for 'sandbox.content_security_policy'."; const char kInvalidSearchEngineMissingKeys[] = "Missing mandatory parameters for " "'chrome_settings_overrides.search_provider'.";
diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h index de7db078..961423e 100644 --- a/extensions/common/manifest_constants.h +++ b/extensions/common/manifest_constants.h
@@ -425,7 +425,6 @@ extern const char kInvalidRunAt[]; extern const char kInvalidSandboxedPagesList[]; extern const char kInvalidSandboxedPage[]; -extern const char kInvalidSandboxedPagesCSP[]; extern const char kInvalidSearchEngineMissingKeys[]; extern const char kInvalidSearchEngineURL[]; extern const char kInvalidShortName[];
diff --git a/extensions/common/manifest_handlers/csp_info.cc b/extensions/common/manifest_handlers/csp_info.cc index 7e5148b..36c519c 100644 --- a/extensions/common/manifest_handlers/csp_info.cc +++ b/extensions/common/manifest_handlers/csp_info.cc
@@ -31,6 +31,10 @@ "script-src 'self' blob: filesystem: chrome-extension-resource:; " "object-src 'self' blob: filesystem:;"; +const char kDefaultSandboxedPageContentSecurityPolicy[] = + "sandbox allow-scripts allow-forms allow-popups allow-modals; " + "script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self';"; + const char kExtensionPagesKey[] = "extension_pages"; const char kExtensionPagesPath[] = "content_security_policy.extension_pages"; @@ -84,6 +88,14 @@ return ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidManifestKey, key); } +// Returns null if the manifest type can't access the path. Else returns the +// corresponding Value. +const base::Value* GetManifestPath(const Extension* extension, + const char* path) { + const base::Value* value = nullptr; + return extension->manifest()->Get(path, &value) ? value : nullptr; +} + } // namespace CSPInfo::CSPInfo(const std::string& security_policy) @@ -102,41 +114,50 @@ } // static +const std::string& CSPInfo::GetSandboxContentSecurityPolicy( + const Extension* extension) { + CSPInfo* csp_info = static_cast<CSPInfo*>( + extension->GetManifestData(keys::kContentSecurityPolicy)); + return csp_info ? csp_info->sandbox_content_security_policy + : base::EmptyString(); +} + +// static const std::string& CSPInfo::GetResourceContentSecurityPolicy( const Extension* extension, const std::string& relative_path) { - return SandboxedPageInfo::IsSandboxedPage(extension, relative_path) ? - SandboxedPageInfo::GetContentSecurityPolicy(extension) : - GetContentSecurityPolicy(extension); + return SandboxedPageInfo::IsSandboxedPage(extension, relative_path) + ? GetSandboxContentSecurityPolicy(extension) + : GetContentSecurityPolicy(extension); } -CSPHandler::CSPHandler(bool is_platform_app) - : is_platform_app_(is_platform_app) { -} +CSPHandler::CSPHandler() = default; -CSPHandler::~CSPHandler() { -} +CSPHandler::~CSPHandler() = default; bool CSPHandler::Parse(Extension* extension, base::string16* error) { - const std::string key = Keys()[0]; + const char* key = extension->GetType() == Manifest::TYPE_PLATFORM_APP + ? keys::kPlatformAppContentSecurityPolicy + : keys::kContentSecurityPolicy; + // The "content_security_policy" manifest key can either be a string or a // dictionary of the format // "content_security_policy" : { // "extension_pages" : "" // } - const base::Value* csp = nullptr; - bool result = extension->manifest()->Get(key, &csp); - DCHECK_EQ(result, !!csp); + const base::Value* csp = GetManifestPath(extension, key); // TODO(crbug.com/914224): Remove the channel check once the support for the // dictionary key is launched to other channels. bool csp_dictionary_supported = - !is_platform_app_ && + extension->GetType() == Manifest::TYPE_EXTENSION && GetCurrentChannel() == version_info::Channel::UNKNOWN; if (csp_dictionary_supported && csp && csp->is_dict()) return ParseCSPDictionary(extension, error, *csp); - return ParseExtensionPagesCSP(extension, error, key, csp); + return ParseExtensionPagesCSP(extension, error, key, csp) && + ParseSandboxCSP(extension, error, keys::kSandboxedPagesCSP, + GetManifestPath(extension, keys::kSandboxedPagesCSP)); } bool CSPHandler::ParseCSPDictionary(Extension* extension, @@ -150,7 +171,7 @@ bool CSPHandler::ParseExtensionPagesCSP( Extension* extension, base::string16* error, - const std::string& manifest_key, + base::StringPiece manifest_key, const base::Value* content_security_policy) { if (!content_security_policy) return SetDefaultExtensionPagesCSP(extension); @@ -181,12 +202,43 @@ return true; } +bool CSPHandler::ParseSandboxCSP(Extension* extension, + base::string16* error, + base::StringPiece manifest_key, + const base::Value* sandbox_csp) { + if (!sandbox_csp) { + SetSandboxCSP(extension, kDefaultSandboxedPageContentSecurityPolicy); + return true; + } + + if (!sandbox_csp->is_string()) { + *error = GetInvalidManifestKeyError(manifest_key); + return false; + } + + const std::string& sandbox_csp_str = sandbox_csp->GetString(); + if (!csp_validator::ContentSecurityPolicyIsLegal(sandbox_csp_str) || + !csp_validator::ContentSecurityPolicyIsSandboxed(sandbox_csp_str, + extension->GetType())) { + *error = GetInvalidManifestKeyError(manifest_key); + return false; + } + + std::vector<InstallWarning> warnings; + std::string effective_sandbox_csp = + csp_validator::GetEffectiveSandoxedPageCSP(sandbox_csp_str, &warnings); + SetSandboxCSP(extension, std::move(effective_sandbox_csp)); + extension->AddInstallWarnings(std::move(warnings)); + return true; +} + bool CSPHandler::SetDefaultExtensionPagesCSP(Extension* extension) { // TODO(abarth): Should we continue to let extensions override the // default Content-Security-Policy? const char* content_security_policy = - is_platform_app_ ? kDefaultPlatformAppContentSecurityPolicy - : kDefaultContentSecurityPolicy; + extension->GetType() == Manifest::TYPE_PLATFORM_APP + ? kDefaultPlatformAppContentSecurityPolicy + : kDefaultContentSecurityPolicy; DCHECK_EQ( content_security_policy, @@ -198,21 +250,27 @@ return true; } +void CSPHandler::SetSandboxCSP(Extension* extension, std::string sandbox_csp) { + CHECK(csp_validator::ContentSecurityPolicyIsSandboxed(sandbox_csp, + extension->GetType())); + + // By now we must have parsed the extension page CSP. + CSPInfo* csp_info = static_cast<CSPInfo*>( + extension->GetManifestData(keys::kContentSecurityPolicy)); + DCHECK(csp_info); + csp_info->sandbox_content_security_policy = std::move(sandbox_csp); +} + bool CSPHandler::AlwaysParseForType(Manifest::Type type) const { - if (is_platform_app_) - return type == Manifest::TYPE_PLATFORM_APP; - else - return type == Manifest::TYPE_EXTENSION || - type == Manifest::TYPE_LEGACY_PACKAGED_APP; + return type == Manifest::TYPE_PLATFORM_APP || + type == Manifest::TYPE_EXTENSION || + type == Manifest::TYPE_LEGACY_PACKAGED_APP; } base::span<const char* const> CSPHandler::Keys() const { - if (is_platform_app_) { - static constexpr const char* kKeys[] = { - keys::kPlatformAppContentSecurityPolicy}; - return kKeys; - } - static constexpr const char* kKeys[] = {keys::kContentSecurityPolicy}; + static constexpr const char* kKeys[] = { + keys::kContentSecurityPolicy, keys::kPlatformAppContentSecurityPolicy, + keys::kSandboxedPagesCSP}; return kKeys; }
diff --git a/extensions/common/manifest_handlers/csp_info.h b/extensions/common/manifest_handlers/csp_info.h index 5f5d0b0..c2ad9262 100644 --- a/extensions/common/manifest_handlers/csp_info.h +++ b/extensions/common/manifest_handlers/csp_info.h
@@ -8,6 +8,7 @@ #include <string> #include "base/macros.h" +#include "base/strings/string_piece_forward.h" #include "extensions/common/extension.h" #include "extensions/common/manifest_handler.h" @@ -23,9 +24,18 @@ // vulnerabilities. std::string content_security_policy; + // Content Security Policy that should be used to enforce the sandbox used + // by sandboxed pages (guaranteed to have the "sandbox" directive without the + // "allow-same-origin" token). + std::string sandbox_content_security_policy; + static const std::string& GetContentSecurityPolicy( const Extension* extension); + // Returns the extension's Content Security Policy for the sandboxed pages. + static const std::string& GetSandboxContentSecurityPolicy( + const Extension* extension); + // Returns the Content Security Policy that the specified resource should be // served with. static const std::string& GetResourceContentSecurityPolicy( @@ -33,10 +43,11 @@ const std::string& relative_path); }; -// Parses "content_security_policy" and "app.content_security_policy" keys. +// Parses "content_security_policy", "app.content_security_policy" and +// "sandbox.content_security_policy" manifest keys. class CSPHandler : public ManifestHandler { public: - explicit CSPHandler(bool is_platform_app); + CSPHandler(); ~CSPHandler() override; bool Parse(Extension* extension, base::string16* error) override; @@ -52,15 +63,23 @@ // pages. bool ParseExtensionPagesCSP(Extension* extension, base::string16* error, - const std::string& manifest_key, + base::StringPiece manifest_key, const base::Value* content_security_policy); + // Parses the content security policy specified in the manifest for sandboxed + // pages. This should be called after ParseExtensionPagesCSP. + bool ParseSandboxCSP(Extension* extension, + base::string16* error, + base::StringPiece manifest_key, + const base::Value* sandbox_csp); + // Sets the default CSP value for the extension. bool SetDefaultExtensionPagesCSP(Extension* extension); - base::span<const char* const> Keys() const override; + // Helper to set the sandbox content security policy manifest data. + void SetSandboxCSP(Extension* extension, std::string sandbox_csp); - bool is_platform_app_; + base::span<const char* const> Keys() const override; DISALLOW_COPY_AND_ASSIGN(CSPHandler); };
diff --git a/extensions/common/manifest_handlers/csp_info_unittest.cc b/extensions/common/manifest_handlers/csp_info_unittest.cc index adfa397..da050fe3 100644 --- a/extensions/common/manifest_handlers/csp_info_unittest.cc +++ b/extensions/common/manifest_handlers/csp_info_unittest.cc
@@ -47,6 +47,14 @@ scoped_refptr<Extension> extension5( LoadAndExpectSuccess("sandboxed_pages_valid_5.json")); + // Sandboxed pages specified for a platform app with a custom CSP. + scoped_refptr<Extension> extension6( + LoadAndExpectSuccess("sandboxed_pages_valid_6.json")); + + // Sandboxed pages specified for a platform app with no custom CSP. + scoped_refptr<Extension> extension7( + LoadAndExpectSuccess("sandboxed_pages_valid_7.json")); + const char kSandboxedCSP[] = "sandbox allow-scripts allow-forms allow-popups allow-modals; " "script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self';"; @@ -72,17 +80,21 @@ extension5.get(), "/path/test.ext")); EXPECT_EQ(kDefaultCSP, CSPInfo::GetResourceContentSecurityPolicy( extension5.get(), "/test")); + EXPECT_EQ(kCustomSandboxedCSP, CSPInfo::GetResourceContentSecurityPolicy( + extension6.get(), "/test")); + EXPECT_EQ(kSandboxedCSP, CSPInfo::GetResourceContentSecurityPolicy( + extension7.get(), "/test")); Testcase testcases[] = { Testcase("sandboxed_pages_invalid_1.json", errors::kInvalidSandboxedPagesList), Testcase("sandboxed_pages_invalid_2.json", errors::kInvalidSandboxedPage), Testcase("sandboxed_pages_invalid_3.json", - errors::kInvalidSandboxedPagesCSP), + GetInvalidManifestKeyError(keys::kSandboxedPagesCSP)), Testcase("sandboxed_pages_invalid_4.json", - errors::kInvalidSandboxedPagesCSP), + GetInvalidManifestKeyError(keys::kSandboxedPagesCSP)), Testcase("sandboxed_pages_invalid_5.json", - errors::kInvalidSandboxedPagesCSP)}; + GetInvalidManifestKeyError(keys::kSandboxedPagesCSP))}; RunTestcases(testcases, base::size(testcases), EXPECT_TYPE_ERROR); }
diff --git a/extensions/common/manifest_handlers/sandboxed_page_info.cc b/extensions/common/manifest_handlers/sandboxed_page_info.cc index f29b3197b..4bb0315 100644 --- a/extensions/common/manifest_handlers/sandboxed_page_info.cc +++ b/extensions/common/manifest_handlers/sandboxed_page_info.cc
@@ -12,7 +12,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" -#include "extensions/common/csp_validator.h" #include "extensions/common/error_utils.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/url_pattern.h" @@ -24,10 +23,6 @@ namespace { -const char kDefaultSandboxedPageContentSecurityPolicy[] = - "sandbox allow-scripts allow-forms allow-popups allow-modals; " - "script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self';"; - static base::LazyInstance<SandboxedPageInfo>::DestructorAtExit g_empty_sandboxed_info = LAZY_INSTANCE_INITIALIZER; @@ -45,11 +40,6 @@ SandboxedPageInfo::~SandboxedPageInfo() { } -const std::string& SandboxedPageInfo::GetContentSecurityPolicy( - const Extension* extension) { - return GetSandboxedPageInfo(extension).content_security_policy; -} - const URLPatternSet& SandboxedPageInfo::GetPages(const Extension* extension) { return GetSandboxedPageInfo(extension).pages; } @@ -94,33 +84,6 @@ sandboxed_info->pages.AddPattern(pattern); } - if (extension->manifest()->HasPath(keys::kSandboxedPagesCSP)) { - std::string content_security_policy; - if (!extension->manifest()->GetString(keys::kSandboxedPagesCSP, - &content_security_policy)) { - *error = base::ASCIIToUTF16(errors::kInvalidSandboxedPagesCSP); - return false; - } - - if (!csp_validator::ContentSecurityPolicyIsLegal(content_security_policy) || - !csp_validator::ContentSecurityPolicyIsSandboxed( - content_security_policy, extension->GetType())) { - *error = base::ASCIIToUTF16(errors::kInvalidSandboxedPagesCSP); - return false; - } - - std::vector<InstallWarning> warnings; - sandboxed_info->content_security_policy = - csp_validator::GetEffectiveSandoxedPageCSP(content_security_policy, - &warnings); - extension->AddInstallWarnings(std::move(warnings)); - } else { - sandboxed_info->content_security_policy = - kDefaultSandboxedPageContentSecurityPolicy; - } - CHECK(csp_validator::ContentSecurityPolicyIsSandboxed( - sandboxed_info->content_security_policy, extension->GetType())); - extension->SetManifestData(keys::kSandboxedPages, std::move(sandboxed_info)); return true; }
diff --git a/extensions/common/manifest_handlers/sandboxed_page_info.h b/extensions/common/manifest_handlers/sandboxed_page_info.h index b897162..4eea981 100644 --- a/extensions/common/manifest_handlers/sandboxed_page_info.h +++ b/extensions/common/manifest_handlers/sandboxed_page_info.h
@@ -18,10 +18,6 @@ SandboxedPageInfo(); ~SandboxedPageInfo() override; - // Returns the extension's Content Security Policy for the sandboxed pages. - static const std::string& GetContentSecurityPolicy( - const Extension* extension); - // Returns the extension's sandboxed pages. static const URLPatternSet& GetPages(const Extension* extension); @@ -32,13 +28,10 @@ // Optional list of extension pages that are sandboxed (served from a unique // origin with a different Content Security Policy). URLPatternSet pages; - - // Content Security Policy that should be used to enforce the sandbox used - // by sandboxed pages (guaranteed to have the "sandbox" directive without the - // "allow-same-origin" token). - std::string content_security_policy; }; +// Responsible for parsing the "sandbox.pages" manifest key. +// "sandbox.content_security_policy" is parsed by CSPHandler. class SandboxedPageHandler : public ManifestHandler { public: SandboxedPageHandler();
diff --git a/extensions/renderer/api_activity_logger.cc b/extensions/renderer/api_activity_logger.cc index 0df01cc..e4c7fc1 100644 --- a/extensions/renderer/api_activity_logger.cc +++ b/extensions/renderer/api_activity_logger.cc
@@ -29,11 +29,12 @@ APIActivityLogger::~APIActivityLogger() {} void APIActivityLogger::AddRoutes() { - RouteHandlerFunction("LogEvent", base::Bind(&APIActivityLogger::LogForJS, - base::Unretained(this), EVENT)); + RouteHandlerFunction("LogEvent", + base::BindRepeating(&APIActivityLogger::LogForJS, + base::Unretained(this), EVENT)); RouteHandlerFunction("LogAPICall", - base::Bind(&APIActivityLogger::LogForJS, - base::Unretained(this), APICALL)); + base::BindRepeating(&APIActivityLogger::LogForJS, + base::Unretained(this), APICALL)); } // static
diff --git a/extensions/renderer/api_definitions_natives.cc b/extensions/renderer/api_definitions_natives.cc index 6adb0e4..8ce5032 100644 --- a/extensions/renderer/api_definitions_natives.cc +++ b/extensions/renderer/api_definitions_natives.cc
@@ -4,6 +4,7 @@ #include "extensions/renderer/api_definitions_natives.h" +#include "base/bind.h" #include "extensions/common/features/feature.h" #include "extensions/common/features/feature_provider.h" #include "extensions/renderer/dispatcher.h" @@ -18,8 +19,9 @@ void ApiDefinitionsNatives::AddRoutes() { RouteHandlerFunction( "GetExtensionAPIDefinitionsForTest", "test", - base::Bind(&ApiDefinitionsNatives::GetExtensionAPIDefinitionsForTest, - base::Unretained(this))); + base::BindRepeating( + &ApiDefinitionsNatives::GetExtensionAPIDefinitionsForTest, + base::Unretained(this))); } void ApiDefinitionsNatives::GetExtensionAPIDefinitionsForTest(
diff --git a/extensions/renderer/app_window_custom_bindings.cc b/extensions/renderer/app_window_custom_bindings.cc index 1ce274a9..c61523b4 100644 --- a/extensions/renderer/app_window_custom_bindings.cc +++ b/extensions/renderer/app_window_custom_bindings.cc
@@ -4,6 +4,7 @@ #include "extensions/renderer/app_window_custom_bindings.h" +#include "base/bind.h" #include "base/command_line.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_thread.h"
diff --git a/extensions/renderer/blob_native_handler.cc b/extensions/renderer/blob_native_handler.cc index 32fc9a6..69fd96e 100644 --- a/extensions/renderer/blob_native_handler.cc +++ b/extensions/renderer/blob_native_handler.cc
@@ -29,10 +29,11 @@ : ObjectBackedNativeHandler(context) {} void BlobNativeHandler::AddRoutes() { - RouteHandlerFunction("GetBlobUuid", base::Bind(&GetBlobUuid)); - RouteHandlerFunction("TakeBrowserProcessBlob", - base::Bind(&BlobNativeHandler::TakeBrowserProcessBlob, - base::Unretained(this))); + RouteHandlerFunction("GetBlobUuid", base::BindRepeating(&GetBlobUuid)); + RouteHandlerFunction( + "TakeBrowserProcessBlob", + base::BindRepeating(&BlobNativeHandler::TakeBrowserProcessBlob, + base::Unretained(this))); } // Take ownership of a Blob created on the browser process. Expects the Blob's
diff --git a/extensions/renderer/context_menus_custom_bindings.cc b/extensions/renderer/context_menus_custom_bindings.cc index 7469546a..72fec49 100644 --- a/extensions/renderer/context_menus_custom_bindings.cc +++ b/extensions/renderer/context_menus_custom_bindings.cc
@@ -29,7 +29,7 @@ void ContextMenusCustomBindings::AddRoutes() { RouteHandlerFunction("GetNextContextMenuId", - base::Bind(&GetNextContextMenuId)); + base::BindRepeating(&GetNextContextMenuId)); } } // extensions
diff --git a/extensions/renderer/css_native_handler.cc b/extensions/renderer/css_native_handler.cc index 41768f6a..ee79b5ae 100644 --- a/extensions/renderer/css_native_handler.cc +++ b/extensions/renderer/css_native_handler.cc
@@ -19,8 +19,8 @@ void CssNativeHandler::AddRoutes() { RouteHandlerFunction( "CanonicalizeCompoundSelector", "declarativeContent", - base::Bind(&CssNativeHandler::CanonicalizeCompoundSelector, - base::Unretained(this))); + base::BindRepeating(&CssNativeHandler::CanonicalizeCompoundSelector, + base::Unretained(this))); } void CssNativeHandler::CanonicalizeCompoundSelector(
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index 9df4190..ad6d2733 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc
@@ -166,9 +166,9 @@ // ObjectBackedNativeHandler: void AddRoutes() override { - RouteHandlerFunction( - "GetChrome", - base::Bind(&ChromeNativeHandler::GetChrome, base::Unretained(this))); + RouteHandlerFunction("GetChrome", + base::BindRepeating(&ChromeNativeHandler::GetChrome, + base::Unretained(this))); } void GetChrome(const v8::FunctionCallbackInfo<v8::Value>& args) {
diff --git a/extensions/renderer/display_source_custom_bindings.cc b/extensions/renderer/display_source_custom_bindings.cc index 9347495..5d583991 100644 --- a/extensions/renderer/display_source_custom_bindings.cc +++ b/extensions/renderer/display_source_custom_bindings.cc
@@ -35,13 +35,14 @@ DisplaySourceCustomBindings::~DisplaySourceCustomBindings() {} void DisplaySourceCustomBindings::AddRoutes() { - RouteHandlerFunction("StartSession", "displaySource", - base::Bind(&DisplaySourceCustomBindings::StartSession, - weak_factory_.GetWeakPtr())); + RouteHandlerFunction( + "StartSession", "displaySource", + base::BindRepeating(&DisplaySourceCustomBindings::StartSession, + weak_factory_.GetWeakPtr())); RouteHandlerFunction( "TerminateSession", "displaySource", - base::Bind(&DisplaySourceCustomBindings::TerminateSession, - weak_factory_.GetWeakPtr())); + base::BindRepeating(&DisplaySourceCustomBindings::TerminateSession, + weak_factory_.GetWeakPtr())); } void DisplaySourceCustomBindings::Invalidate() {
diff --git a/extensions/renderer/event_bindings.cc b/extensions/renderer/event_bindings.cc index 229bb9b..05315d9 100644 --- a/extensions/renderer/event_bindings.cc +++ b/extensions/renderer/event_bindings.cc
@@ -90,24 +90,25 @@ EventBindings::~EventBindings() {} void EventBindings::AddRoutes() { + RouteHandlerFunction("AttachEvent", + base::BindRepeating(&EventBindings::AttachEventHandler, + base::Unretained(this))); + RouteHandlerFunction("DetachEvent", + base::BindRepeating(&EventBindings::DetachEventHandler, + base::Unretained(this))); + RouteHandlerFunction("AttachFilteredEvent", + base::BindRepeating(&EventBindings::AttachFilteredEvent, + base::Unretained(this))); RouteHandlerFunction( - "AttachEvent", - base::Bind(&EventBindings::AttachEventHandler, base::Unretained(this))); - RouteHandlerFunction( - "DetachEvent", - base::Bind(&EventBindings::DetachEventHandler, base::Unretained(this))); - RouteHandlerFunction( - "AttachFilteredEvent", - base::Bind(&EventBindings::AttachFilteredEvent, base::Unretained(this))); - RouteHandlerFunction("DetachFilteredEvent", - base::Bind(&EventBindings::DetachFilteredEventHandler, - base::Unretained(this))); - RouteHandlerFunction( - "AttachUnmanagedEvent", - base::Bind(&EventBindings::AttachUnmanagedEvent, base::Unretained(this))); - RouteHandlerFunction( - "DetachUnmanagedEvent", - base::Bind(&EventBindings::DetachUnmanagedEvent, base::Unretained(this))); + "DetachFilteredEvent", + base::BindRepeating(&EventBindings::DetachFilteredEventHandler, + base::Unretained(this))); + RouteHandlerFunction("AttachUnmanagedEvent", + base::BindRepeating(&EventBindings::AttachUnmanagedEvent, + base::Unretained(this))); + RouteHandlerFunction("DetachUnmanagedEvent", + base::BindRepeating(&EventBindings::DetachUnmanagedEvent, + base::Unretained(this))); } // static
diff --git a/extensions/renderer/file_system_natives.cc b/extensions/renderer/file_system_natives.cc index 1d906b6..2567f43 100644 --- a/extensions/renderer/file_system_natives.cc +++ b/extensions/renderer/file_system_natives.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/bind.h" #include "extensions/common/constants.h" #include "extensions/renderer/script_context.h" #include "storage/common/fileapi/file_system_types.h" @@ -21,16 +22,17 @@ : ObjectBackedNativeHandler(context) {} void FileSystemNatives::AddRoutes() { + RouteHandlerFunction("GetFileEntry", + base::BindRepeating(&FileSystemNatives::GetFileEntry, + base::Unretained(this))); RouteHandlerFunction( - "GetFileEntry", - base::Bind(&FileSystemNatives::GetFileEntry, base::Unretained(this))); - RouteHandlerFunction("GetIsolatedFileSystem", - base::Bind(&FileSystemNatives::GetIsolatedFileSystem, - base::Unretained(this))); + "GetIsolatedFileSystem", + base::BindRepeating(&FileSystemNatives::GetIsolatedFileSystem, + base::Unretained(this))); RouteHandlerFunction( "CrackIsolatedFileSystemName", - base::Bind(&FileSystemNatives::CrackIsolatedFileSystemName, - base::Unretained(this))); + base::BindRepeating(&FileSystemNatives::CrackIsolatedFileSystemName, + base::Unretained(this))); } void FileSystemNatives::GetIsolatedFileSystem(
diff --git a/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc b/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc index 53a3b249..2220670 100644 --- a/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc +++ b/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc
@@ -82,44 +82,48 @@ GuestViewInternalCustomBindings::~GuestViewInternalCustomBindings() {} void GuestViewInternalCustomBindings::AddRoutes() { - RouteHandlerFunction("AttachGuest", - base::Bind(&GuestViewInternalCustomBindings::AttachGuest, - base::Unretained(this))); - RouteHandlerFunction("DetachGuest", - base::Bind(&GuestViewInternalCustomBindings::DetachGuest, - base::Unretained(this))); + RouteHandlerFunction( + "AttachGuest", + base::BindRepeating(&GuestViewInternalCustomBindings::AttachGuest, + base::Unretained(this))); + RouteHandlerFunction( + "DetachGuest", + base::BindRepeating(&GuestViewInternalCustomBindings::DetachGuest, + base::Unretained(this))); RouteHandlerFunction( "AttachIframeGuest", - base::Bind(&GuestViewInternalCustomBindings::AttachIframeGuest, - base::Unretained(this))); + base::BindRepeating(&GuestViewInternalCustomBindings::AttachIframeGuest, + base::Unretained(this))); RouteHandlerFunction( "DestroyContainer", - base::Bind(&GuestViewInternalCustomBindings::DestroyContainer, - base::Unretained(this))); + base::BindRepeating(&GuestViewInternalCustomBindings::DestroyContainer, + base::Unretained(this))); RouteHandlerFunction( "GetContentWindow", - base::Bind(&GuestViewInternalCustomBindings::GetContentWindow, - base::Unretained(this))); + base::BindRepeating(&GuestViewInternalCustomBindings::GetContentWindow, + base::Unretained(this))); RouteHandlerFunction( "GetViewFromID", - base::Bind(&GuestViewInternalCustomBindings::GetViewFromID, - base::Unretained(this))); + base::BindRepeating(&GuestViewInternalCustomBindings::GetViewFromID, + base::Unretained(this))); RouteHandlerFunction( "RegisterDestructionCallback", - base::Bind(&GuestViewInternalCustomBindings::RegisterDestructionCallback, - base::Unretained(this))); + base::BindRepeating( + &GuestViewInternalCustomBindings::RegisterDestructionCallback, + base::Unretained(this))); RouteHandlerFunction( "RegisterElementResizeCallback", - base::Bind( + base::BindRepeating( &GuestViewInternalCustomBindings::RegisterElementResizeCallback, base::Unretained(this))); RouteHandlerFunction( - "RegisterView", base::Bind(&GuestViewInternalCustomBindings::RegisterView, - base::Unretained(this))); + "RegisterView", + base::BindRepeating(&GuestViewInternalCustomBindings::RegisterView, + base::Unretained(this))); RouteHandlerFunction( "RunWithGesture", - base::Bind(&GuestViewInternalCustomBindings::RunWithGesture, - base::Unretained(this))); + base::BindRepeating(&GuestViewInternalCustomBindings::RunWithGesture, + base::Unretained(this))); RouteHandlerFunction( "AllowGuestViewElementDefinition", base::BindRepeating(
diff --git a/extensions/renderer/i18n_custom_bindings.cc b/extensions/renderer/i18n_custom_bindings.cc index f43e993f..12419758 100644 --- a/extensions/renderer/i18n_custom_bindings.cc +++ b/extensions/renderer/i18n_custom_bindings.cc
@@ -20,15 +20,17 @@ : ObjectBackedNativeHandler(context) {} void I18NCustomBindings::AddRoutes() { + RouteHandlerFunction("GetL10nMessage", "i18n", + base::BindRepeating(&I18NCustomBindings::GetL10nMessage, + base::Unretained(this))); RouteHandlerFunction( - "GetL10nMessage", "i18n", - base::Bind(&I18NCustomBindings::GetL10nMessage, base::Unretained(this))); - RouteHandlerFunction("GetL10nUILanguage", "i18n", - base::Bind(&I18NCustomBindings::GetL10nUILanguage, - base::Unretained(this))); - RouteHandlerFunction("DetectTextLanguage", "i18n", - base::Bind(&I18NCustomBindings::DetectTextLanguage, - base::Unretained(this))); + "GetL10nUILanguage", "i18n", + base::BindRepeating(&I18NCustomBindings::GetL10nUILanguage, + base::Unretained(this))); + RouteHandlerFunction( + "DetectTextLanguage", "i18n", + base::BindRepeating(&I18NCustomBindings::DetectTextLanguage, + base::Unretained(this))); } void I18NCustomBindings::GetL10nMessage(
diff --git a/extensions/renderer/id_generator_custom_bindings.cc b/extensions/renderer/id_generator_custom_bindings.cc index faa2e83..af8070f 100644 --- a/extensions/renderer/id_generator_custom_bindings.cc +++ b/extensions/renderer/id_generator_custom_bindings.cc
@@ -15,9 +15,9 @@ : ObjectBackedNativeHandler(context) {} void IdGeneratorCustomBindings::AddRoutes() { - RouteHandlerFunction("GetNextId", - base::Bind(&IdGeneratorCustomBindings::GetNextId, - base::Unretained(this))); + RouteHandlerFunction( + "GetNextId", base::BindRepeating(&IdGeneratorCustomBindings::GetNextId, + base::Unretained(this))); } void IdGeneratorCustomBindings::GetNextId(
diff --git a/extensions/renderer/lazy_background_page_native_handler.cc b/extensions/renderer/lazy_background_page_native_handler.cc index bd09bfa..5a43d4e 100644 --- a/extensions/renderer/lazy_background_page_native_handler.cc +++ b/extensions/renderer/lazy_background_page_native_handler.cc
@@ -19,12 +19,14 @@ void LazyBackgroundPageNativeHandler::AddRoutes() { RouteHandlerFunction( "IncrementKeepaliveCount", "tts", - base::Bind(&LazyBackgroundPageNativeHandler::IncrementKeepaliveCount, - base::Unretained(this))); + base::BindRepeating( + &LazyBackgroundPageNativeHandler::IncrementKeepaliveCount, + base::Unretained(this))); RouteHandlerFunction( "DecrementKeepaliveCount", "tts", - base::Bind(&LazyBackgroundPageNativeHandler::DecrementKeepaliveCount, - base::Unretained(this))); + base::BindRepeating( + &LazyBackgroundPageNativeHandler::DecrementKeepaliveCount, + base::Unretained(this))); } void LazyBackgroundPageNativeHandler::IncrementKeepaliveCount(
diff --git a/extensions/renderer/logging_native_handler.cc b/extensions/renderer/logging_native_handler.cc index 9bd2b61..b8b1739 100644 --- a/extensions/renderer/logging_native_handler.cc +++ b/extensions/renderer/logging_native_handler.cc
@@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "extensions/renderer/logging_native_handler.h" + +#include "base/bind.h" #include "base/logging.h" #include "base/strings/stringprintf.h" -#include "extensions/renderer/logging_native_handler.h" #include "extensions/renderer/script_context.h" namespace extensions { @@ -15,17 +17,25 @@ LoggingNativeHandler::~LoggingNativeHandler() {} void LoggingNativeHandler::AddRoutes() { - RouteHandlerFunction("DCHECK", base::Bind(&LoggingNativeHandler::Dcheck, - base::Unretained(this))); - RouteHandlerFunction("CHECK", base::Bind(&LoggingNativeHandler::Check, + RouteHandlerFunction("DCHECK", + base::BindRepeating(&LoggingNativeHandler::Dcheck, base::Unretained(this))); - RouteHandlerFunction( - "DCHECK_IS_ON", - base::Bind(&LoggingNativeHandler::DcheckIsOn, base::Unretained(this))); - RouteHandlerFunction( - "LOG", base::Bind(&LoggingNativeHandler::Log, base::Unretained(this))); - RouteHandlerFunction("WARNING", base::Bind(&LoggingNativeHandler::Warning, - base::Unretained(this))); + RouteHandlerFunction("CHECK", + base::BindRepeating(&LoggingNativeHandler::Check, + base::Unretained(this))); + // A blatant ugly hack to get around our "dcheck is on" validity presubmit + // checks (which assert that it's always written as `#if DCHECK_IS_ON()`). + constexpr char kDCheckIsOnFunctionKey[] = + "DCHECK_IS_" + "ON"; + RouteHandlerFunction(kDCheckIsOnFunctionKey, + base::BindRepeating(&LoggingNativeHandler::DcheckIsOn, + base::Unretained(this))); + RouteHandlerFunction("LOG", base::BindRepeating(&LoggingNativeHandler::Log, + base::Unretained(this))); + RouteHandlerFunction("WARNING", + base::BindRepeating(&LoggingNativeHandler::Warning, + base::Unretained(this))); } void LoggingNativeHandler::Check(
diff --git a/extensions/renderer/messaging_bindings.cc b/extensions/renderer/messaging_bindings.cc index bf5ff720..cfb66cb 100644 --- a/extensions/renderer/messaging_bindings.cc +++ b/extensions/renderer/messaging_bindings.cc
@@ -66,24 +66,27 @@ } void MessagingBindings::AddRoutes() { - RouteHandlerFunction( - "CloseChannel", - base::Bind(&MessagingBindings::CloseChannel, base::Unretained(this))); - RouteHandlerFunction( - "PostMessage", - base::Bind(&MessagingBindings::PostMessage, base::Unretained(this))); + RouteHandlerFunction("CloseChannel", + base::BindRepeating(&MessagingBindings::CloseChannel, + base::Unretained(this))); + RouteHandlerFunction("PostMessage", + base::BindRepeating(&MessagingBindings::PostMessage, + base::Unretained(this))); // TODO(fsamuel, kalman): Move BindToGC out of messaging natives. - RouteHandlerFunction("BindToGC", base::Bind(&MessagingBindings::BindToGC, - base::Unretained(this))); - RouteHandlerFunction("OpenChannelToExtension", "runtime.connect", - base::Bind(&MessagingBindings::OpenChannelToExtension, - base::Unretained(this))); - RouteHandlerFunction("OpenChannelToNativeApp", "runtime.connectNative", - base::Bind(&MessagingBindings::OpenChannelToNativeApp, - base::Unretained(this))); + RouteHandlerFunction("BindToGC", + base::BindRepeating(&MessagingBindings::BindToGC, + base::Unretained(this))); RouteHandlerFunction( - "OpenChannelToTab", - base::Bind(&MessagingBindings::OpenChannelToTab, base::Unretained(this))); + "OpenChannelToExtension", "runtime.connect", + base::BindRepeating(&MessagingBindings::OpenChannelToExtension, + base::Unretained(this))); + RouteHandlerFunction( + "OpenChannelToNativeApp", "runtime.connectNative", + base::BindRepeating(&MessagingBindings::OpenChannelToNativeApp, + base::Unretained(this))); + RouteHandlerFunction("OpenChannelToTab", + base::BindRepeating(&MessagingBindings::OpenChannelToTab, + base::Unretained(this))); } // static
diff --git a/extensions/renderer/module_system.cc b/extensions/renderer/module_system.cc index 1d8a819630..d096b6fe 100644 --- a/extensions/renderer/module_system.cc +++ b/extensions/renderer/module_system.cc
@@ -189,14 +189,17 @@ } void ModuleSystem::AddRoutes() { - RouteHandlerFunction("require", base::Bind(&ModuleSystem::RequireForJs, - base::Unretained(this))); - RouteHandlerFunction("requireNative", base::Bind(&ModuleSystem::RequireNative, - base::Unretained(this))); - RouteHandlerFunction("loadScript", base::Bind(&ModuleSystem::LoadScript, - base::Unretained(this))); RouteHandlerFunction( - "privates", base::Bind(&ModuleSystem::Private, base::Unretained(this))); + "require", + base::BindRepeating(&ModuleSystem::RequireForJs, base::Unretained(this))); + RouteHandlerFunction("requireNative", + base::BindRepeating(&ModuleSystem::RequireNative, + base::Unretained(this))); + RouteHandlerFunction( + "loadScript", + base::BindRepeating(&ModuleSystem::LoadScript, base::Unretained(this))); + RouteHandlerFunction("privates", base::BindRepeating(&ModuleSystem::Private, + base::Unretained(this))); } void ModuleSystem::Invalidate() {
diff --git a/extensions/renderer/module_system_test.cc b/extensions/renderer/module_system_test.cc index 311b786..95551cf 100644 --- a/extensions/renderer/module_system_test.cc +++ b/extensions/renderer/module_system_test.cc
@@ -11,6 +11,7 @@ #include <string> #include <utility> +#include "base/bind.h" #include "base/callback.h" #include "base/command_line.h" #include "base/feature_list.h" @@ -86,8 +87,8 @@ args.GetReturnValue().Set(api); }; - RouteHandlerFunction("get", - base::Bind(get_api, context(), bindings_system_)); + RouteHandlerFunction( + "get", base::BindRepeating(get_api, context(), bindings_system_)); } private: @@ -109,10 +110,12 @@ // ObjectBackedNativeHandler: void AddRoutes() override { - RouteHandlerFunction("AssertTrue", base::Bind(&AssertNatives::AssertTrue, - base::Unretained(this))); - RouteHandlerFunction("AssertFalse", base::Bind(&AssertNatives::AssertFalse, - base::Unretained(this))); + RouteHandlerFunction("AssertTrue", + base::BindRepeating(&AssertNatives::AssertTrue, + base::Unretained(this))); + RouteHandlerFunction("AssertFalse", + base::BindRepeating(&AssertNatives::AssertFalse, + base::Unretained(this))); } bool assertion_made() { return assertion_made_; }
diff --git a/extensions/renderer/module_system_unittest.cc b/extensions/renderer/module_system_unittest.cc index c7a2542..6d2ffab8 100644 --- a/extensions/renderer/module_system_unittest.cc +++ b/extensions/renderer/module_system_unittest.cc
@@ -9,6 +9,7 @@ #include <memory> #include <utility> +#include "base/bind.h" #include "extensions/renderer/module_system_test.h" namespace extensions { @@ -20,10 +21,11 @@ // ObjectBackedNativeHandler: void AddRoutes() override { - RouteHandlerFunction( - "Get", base::Bind(&CounterNatives::Get, base::Unretained(this))); - RouteHandlerFunction("Increment", base::Bind(&CounterNatives::Increment, - base::Unretained(this))); + RouteHandlerFunction("Get", base::BindRepeating(&CounterNatives::Get, + base::Unretained(this))); + RouteHandlerFunction("Increment", + base::BindRepeating(&CounterNatives::Increment, + base::Unretained(this))); } void Get(const v8::FunctionCallbackInfo<v8::Value>& args) {
diff --git a/extensions/renderer/object_backed_native_handler.cc b/extensions/renderer/object_backed_native_handler.cc index 8784a77..504e7eb 100644 --- a/extensions/renderer/object_backed_native_handler.cc +++ b/extensions/renderer/object_backed_native_handler.cc
@@ -5,6 +5,7 @@ #include "extensions/renderer/object_backed_native_handler.h" #include <stddef.h> +#include <utility> #include "base/logging.h" #include "content/public/renderer/worker_thread.h" @@ -118,14 +119,14 @@ void ObjectBackedNativeHandler::RouteHandlerFunction( const std::string& name, - const HandlerFunction& handler_function) { - RouteHandlerFunction(name, "", handler_function); + HandlerFunction handler_function) { + RouteHandlerFunction(name, "", std::move(handler_function)); } void ObjectBackedNativeHandler::RouteHandlerFunction( const std::string& name, const std::string& feature_name, - const HandlerFunction& handler_function) { + HandlerFunction handler_function) { DCHECK_EQ(init_state_, kInitializingRoutes) << "RouteHandlerFunction() can only be called from AddRoutes()!"; @@ -135,7 +136,8 @@ v8::Local<v8::Object> data = v8::Object::New(isolate); SetPrivate(data, kHandlerFunction, - v8::External::New(isolate, new HandlerFunction(handler_function))); + v8::External::New( + isolate, new HandlerFunction(std::move(handler_function)))); DCHECK(feature_name.empty() || ExtensionAPI::GetSharedInstance()->GetFeatureDependency(feature_name)) << feature_name;
diff --git a/extensions/renderer/object_backed_native_handler.h b/extensions/renderer/object_backed_native_handler.h index 71314d1..1532920 100644 --- a/extensions/renderer/object_backed_native_handler.h +++ b/extensions/renderer/object_backed_native_handler.h
@@ -36,8 +36,8 @@ v8::Isolate* GetIsolate() const; protected: - typedef base::Callback<void(const v8::FunctionCallbackInfo<v8::Value>&)> - HandlerFunction; + using HandlerFunction = + base::RepeatingCallback<void(const v8::FunctionCallbackInfo<v8::Value>&)>; virtual void AddRoutes() = 0; @@ -54,10 +54,10 @@ // the |handler_function| is not invoked. // TODO(devlin): Deprecate the version that doesn't take a |feature_name|. void RouteHandlerFunction(const std::string& name, - const HandlerFunction& handler_function); + HandlerFunction handler_function); void RouteHandlerFunction(const std::string& name, const std::string& feature_name, - const HandlerFunction& handler_function); + HandlerFunction handler_function); ScriptContext* context() const { return context_; }
diff --git a/extensions/renderer/process_info_native_handler.cc b/extensions/renderer/process_info_native_handler.cc index 224c9d48..df9ea13f 100644 --- a/extensions/renderer/process_info_native_handler.cc +++ b/extensions/renderer/process_info_native_handler.cc
@@ -31,32 +31,36 @@ send_request_disabled_(send_request_disabled) {} void ProcessInfoNativeHandler::AddRoutes() { - RouteHandlerFunction("GetExtensionId", - base::Bind(&ProcessInfoNativeHandler::GetExtensionId, - base::Unretained(this))); - RouteHandlerFunction("GetContextType", - base::Bind(&ProcessInfoNativeHandler::GetContextType, - base::Unretained(this))); - RouteHandlerFunction("InIncognitoContext", - base::Bind(&ProcessInfoNativeHandler::InIncognitoContext, - base::Unretained(this))); + RouteHandlerFunction( + "GetExtensionId", + base::BindRepeating(&ProcessInfoNativeHandler::GetExtensionId, + base::Unretained(this))); + RouteHandlerFunction( + "GetContextType", + base::BindRepeating(&ProcessInfoNativeHandler::GetContextType, + base::Unretained(this))); + RouteHandlerFunction( + "InIncognitoContext", + base::BindRepeating(&ProcessInfoNativeHandler::InIncognitoContext, + base::Unretained(this))); RouteHandlerFunction( "IsComponentExtension", - base::Bind(&ProcessInfoNativeHandler::IsComponentExtension, - base::Unretained(this))); - RouteHandlerFunction("GetManifestVersion", - base::Bind(&ProcessInfoNativeHandler::GetManifestVersion, - base::Unretained(this))); + base::BindRepeating(&ProcessInfoNativeHandler::IsComponentExtension, + base::Unretained(this))); + RouteHandlerFunction( + "GetManifestVersion", + base::BindRepeating(&ProcessInfoNativeHandler::GetManifestVersion, + base::Unretained(this))); RouteHandlerFunction( "IsSendRequestDisabled", - base::Bind(&ProcessInfoNativeHandler::IsSendRequestDisabled, - base::Unretained(this))); + base::BindRepeating(&ProcessInfoNativeHandler::IsSendRequestDisabled, + base::Unretained(this))); + RouteHandlerFunction("HasSwitch", + base::BindRepeating(&ProcessInfoNativeHandler::HasSwitch, + base::Unretained(this))); RouteHandlerFunction( - "HasSwitch", - base::Bind(&ProcessInfoNativeHandler::HasSwitch, base::Unretained(this))); - RouteHandlerFunction("GetPlatform", - base::Bind(&ProcessInfoNativeHandler::GetPlatform, - base::Unretained(this))); + "GetPlatform", base::BindRepeating(&ProcessInfoNativeHandler::GetPlatform, + base::Unretained(this))); } void ProcessInfoNativeHandler::GetExtensionId(
diff --git a/extensions/renderer/render_frame_observer_natives.cc b/extensions/renderer/render_frame_observer_natives.cc index 918c2833..aef1a53 100644 --- a/extensions/renderer/render_frame_observer_natives.cc +++ b/extensions/renderer/render_frame_observer_natives.cc
@@ -60,8 +60,8 @@ void RenderFrameObserverNatives::AddRoutes() { RouteHandlerFunction( "OnDocumentElementCreated", "app.window", - base::Bind(&RenderFrameObserverNatives::OnDocumentElementCreated, - base::Unretained(this))); + base::BindRepeating(&RenderFrameObserverNatives::OnDocumentElementCreated, + base::Unretained(this))); } void RenderFrameObserverNatives::Invalidate() {
diff --git a/extensions/renderer/runtime_custom_bindings.cc b/extensions/renderer/runtime_custom_bindings.cc index 816e23e..3c48477 100644 --- a/extensions/renderer/runtime_custom_bindings.cc +++ b/extensions/renderer/runtime_custom_bindings.cc
@@ -26,12 +26,13 @@ RuntimeCustomBindings::~RuntimeCustomBindings() {} void RuntimeCustomBindings::AddRoutes() { + RouteHandlerFunction("GetManifest", + base::BindRepeating(&RuntimeCustomBindings::GetManifest, + base::Unretained(this))); RouteHandlerFunction( - "GetManifest", - base::Bind(&RuntimeCustomBindings::GetManifest, base::Unretained(this))); - RouteHandlerFunction("GetExtensionViews", - base::Bind(&RuntimeCustomBindings::GetExtensionViews, - base::Unretained(this))); + "GetExtensionViews", + base::BindRepeating(&RuntimeCustomBindings::GetExtensionViews, + base::Unretained(this))); } void RuntimeCustomBindings::GetManifest(
diff --git a/extensions/renderer/send_request_natives.cc b/extensions/renderer/send_request_natives.cc index 3e2c4d3..008811f2 100644 --- a/extensions/renderer/send_request_natives.cc +++ b/extensions/renderer/send_request_natives.cc
@@ -6,6 +6,7 @@ #include <stdint.h> +#include "base/bind.h" #include "base/json/json_reader.h" #include "base/metrics/histogram_macros.h" #include "base/timer/elapsed_timer.h" @@ -20,11 +21,12 @@ : ObjectBackedNativeHandler(context), request_sender_(request_sender) {} void SendRequestNatives::AddRoutes() { - RouteHandlerFunction( - "StartRequest", - base::Bind(&SendRequestNatives::StartRequest, base::Unretained(this))); - RouteHandlerFunction("GetGlobal", base::Bind(&SendRequestNatives::GetGlobal, - base::Unretained(this))); + RouteHandlerFunction("StartRequest", + base::BindRepeating(&SendRequestNatives::StartRequest, + base::Unretained(this))); + RouteHandlerFunction("GetGlobal", + base::BindRepeating(&SendRequestNatives::GetGlobal, + base::Unretained(this))); } // Starts an API request to the browser, with an optional callback. The
diff --git a/extensions/renderer/set_icon_natives.cc b/extensions/renderer/set_icon_natives.cc index d5cb75c3..4dba7aa 100644 --- a/extensions/renderer/set_icon_natives.cc +++ b/extensions/renderer/set_icon_natives.cc
@@ -10,6 +10,7 @@ #include <limits> #include <memory> +#include "base/bind.h" #include "base/macros.h" #include "base/strings/string_number_conversions.h" #include "content/public/common/common_param_traits.h" @@ -67,9 +68,9 @@ : ObjectBackedNativeHandler(context) {} void SetIconNatives::AddRoutes() { - RouteHandlerFunction( - "SetIconCommon", - base::Bind(&SetIconNatives::SetIconCommon, base::Unretained(this))); + RouteHandlerFunction("SetIconCommon", + base::BindRepeating(&SetIconNatives::SetIconCommon, + base::Unretained(this))); } bool SetIconNatives::ConvertImageDataToBitmapValue(
diff --git a/extensions/renderer/test_features_native_handler.cc b/extensions/renderer/test_features_native_handler.cc index c2006c4..6857f0b 100644 --- a/extensions/renderer/test_features_native_handler.cc +++ b/extensions/renderer/test_features_native_handler.cc
@@ -16,9 +16,10 @@ : ObjectBackedNativeHandler(context) {} void TestFeaturesNativeHandler::AddRoutes() { - RouteHandlerFunction("GetAPIFeatures", "test", - base::Bind(&TestFeaturesNativeHandler::GetAPIFeatures, - base::Unretained(this))); + RouteHandlerFunction( + "GetAPIFeatures", "test", + base::BindRepeating(&TestFeaturesNativeHandler::GetAPIFeatures, + base::Unretained(this))); } void TestFeaturesNativeHandler::GetAPIFeatures(
diff --git a/extensions/renderer/test_native_handler.cc b/extensions/renderer/test_native_handler.cc index 14a64385..0df3eab 100644 --- a/extensions/renderer/test_native_handler.cc +++ b/extensions/renderer/test_native_handler.cc
@@ -4,6 +4,7 @@ #include "extensions/renderer/test_native_handler.h" +#include "base/bind.h" #include "extensions/renderer/wake_event_page.h" namespace extensions { @@ -12,9 +13,9 @@ : ObjectBackedNativeHandler(context) {} void TestNativeHandler::AddRoutes() { - RouteHandlerFunction( - "GetWakeEventPage", "test", - base::Bind(&TestNativeHandler::GetWakeEventPage, base::Unretained(this))); + RouteHandlerFunction("GetWakeEventPage", "test", + base::BindRepeating(&TestNativeHandler::GetWakeEventPage, + base::Unretained(this))); } void TestNativeHandler::GetWakeEventPage(
diff --git a/extensions/renderer/user_gestures_native_handler.cc b/extensions/renderer/user_gestures_native_handler.cc index 79e111b7..bfc42efe 100644 --- a/extensions/renderer/user_gestures_native_handler.cc +++ b/extensions/renderer/user_gestures_native_handler.cc
@@ -17,12 +17,12 @@ void UserGesturesNativeHandler::AddRoutes() { RouteHandlerFunction( "IsProcessingUserGesture", "test", - base::Bind(&UserGesturesNativeHandler::IsProcessingUserGesture, - base::Unretained(this))); + base::BindRepeating(&UserGesturesNativeHandler::IsProcessingUserGesture, + base::Unretained(this))); RouteHandlerFunction( "RunWithUserGesture", "test", - base::Bind(&UserGesturesNativeHandler::RunWithUserGesture, - base::Unretained(this))); + base::BindRepeating(&UserGesturesNativeHandler::RunWithUserGesture, + base::Unretained(this))); } void UserGesturesNativeHandler::IsProcessingUserGesture(
diff --git a/extensions/renderer/utils_native_handler.cc b/extensions/renderer/utils_native_handler.cc index b0fe4d79..03a3cff 100644 --- a/extensions/renderer/utils_native_handler.cc +++ b/extensions/renderer/utils_native_handler.cc
@@ -4,6 +4,7 @@ #include "extensions/renderer/utils_native_handler.h" +#include "base/bind.h" #include "base/macros.h" #include "extensions/renderer/script_context.h" #include "third_party/blink/public/web/web_serialized_script_value.h" @@ -16,8 +17,9 @@ UtilsNativeHandler::~UtilsNativeHandler() {} void UtilsNativeHandler::AddRoutes() { - RouteHandlerFunction("deepCopy", base::Bind(&UtilsNativeHandler::DeepCopy, - base::Unretained(this))); + RouteHandlerFunction("deepCopy", + base::BindRepeating(&UtilsNativeHandler::DeepCopy, + base::Unretained(this))); } void UtilsNativeHandler::DeepCopy(
diff --git a/extensions/renderer/v8_context_native_handler.cc b/extensions/renderer/v8_context_native_handler.cc index 02aa1f71..ac3b850 100644 --- a/extensions/renderer/v8_context_native_handler.cc +++ b/extensions/renderer/v8_context_native_handler.cc
@@ -16,12 +16,14 @@ : ObjectBackedNativeHandler(context), context_(context) {} void V8ContextNativeHandler::AddRoutes() { - RouteHandlerFunction("GetAvailability", - base::Bind(&V8ContextNativeHandler::GetAvailability, - base::Unretained(this))); - RouteHandlerFunction("GetModuleSystem", - base::Bind(&V8ContextNativeHandler::GetModuleSystem, - base::Unretained(this))); + RouteHandlerFunction( + "GetAvailability", + base::BindRepeating(&V8ContextNativeHandler::GetAvailability, + base::Unretained(this))); + RouteHandlerFunction( + "GetModuleSystem", + base::BindRepeating(&V8ContextNativeHandler::GetModuleSystem, + base::Unretained(this))); } void V8ContextNativeHandler::GetAvailability(
diff --git a/extensions/renderer/v8_schema_registry.cc b/extensions/renderer/v8_schema_registry.cc index 7533a276..418fbc3 100644 --- a/extensions/renderer/v8_schema_registry.cc +++ b/extensions/renderer/v8_schema_registry.cc
@@ -8,6 +8,7 @@ #include <utility> +#include "base/bind.h" #include "base/logging.h" #include "base/values.h" #include "content/public/renderer/v8_value_converter.h" @@ -52,12 +53,14 @@ // ObjectBackedNativeHandler: void AddRoutes() override { - RouteHandlerFunction("GetSchema", - base::Bind(&SchemaRegistryNativeHandler::GetSchema, - base::Unretained(this))); - RouteHandlerFunction("GetObjectType", - base::Bind(&SchemaRegistryNativeHandler::GetObjectType, - base::Unretained(this))); + RouteHandlerFunction( + "GetSchema", + base::BindRepeating(&SchemaRegistryNativeHandler::GetSchema, + base::Unretained(this))); + RouteHandlerFunction( + "GetObjectType", + base::BindRepeating(&SchemaRegistryNativeHandler::GetObjectType, + base::Unretained(this))); } ~SchemaRegistryNativeHandler() override { context_->Invalidate(); }
diff --git a/extensions/renderer/wake_event_page.cc b/extensions/renderer/wake_event_page.cc index 5175e18a..688d3082 100644 --- a/extensions/renderer/wake_event_page.cc +++ b/extensions/renderer/wake_event_page.cc
@@ -57,8 +57,8 @@ // after destruction. RouteHandlerFunction( kWakeEventPageFunctionName, - base::Bind(&WakeEventPageNativeHandler::DoWakeEventPage, - base::Unretained(this))); + base::BindRepeating(&WakeEventPageNativeHandler::DoWakeEventPage, + base::Unretained(this))); }; ~WakeEventPageNativeHandler() override {}
diff --git a/extensions/test/data/manifest_tests/sandboxed_pages_valid_6.json b/extensions/test/data/manifest_tests/sandboxed_pages_valid_6.json new file mode 100644 index 0000000..bcd5e79 --- /dev/null +++ b/extensions/test/data/manifest_tests/sandboxed_pages_valid_6.json
@@ -0,0 +1,14 @@ +{ + "name": "test", + "version": "0.1", + "manifest_version": 2, + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "sandbox": { + "pages": ["test"], + "content_security_policy": "sandbox; script-src https://www.google.com" + } +}
diff --git a/extensions/test/data/manifest_tests/sandboxed_pages_valid_7.json b/extensions/test/data/manifest_tests/sandboxed_pages_valid_7.json new file mode 100644 index 0000000..19ce291 --- /dev/null +++ b/extensions/test/data/manifest_tests/sandboxed_pages_valid_7.json
@@ -0,0 +1,13 @@ +{ + "name": "test", + "version": "0.1", + "manifest_version": 2, + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "sandbox": { + "pages": ["test"] + } +}
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn index 9bc19c2..5663ed0 100644 --- a/gpu/BUILD.gn +++ b/gpu/BUILD.gn
@@ -244,6 +244,7 @@ "command_buffer/tests/gl_unittests_android.cc", "command_buffer/tests/gl_virtual_contexts_ext_window_rectangles_unittest.cc", "command_buffer/tests/gl_virtual_contexts_unittest.cc", + "command_buffer/tests/gl_webgl_multi_draw_test.cc", "command_buffer/tests/occlusion_query_unittest.cc", "command_buffer/tests/texture_image_factory.cc", "command_buffer/tests/texture_image_factory.h",
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index c5f78d1..2cc75e3 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -2854,7 +2854,25 @@ 'trace_level': 2, 'es31': True }, - 'MultiDrawArraysWEBGL': { + 'MultiDrawBeginCHROMIUM': { + 'decoder_func': 'DoMultiDrawBeginCHROMIUM', + 'extension': 'WEBGL_multi_draw', + 'extension_flag': 'webgl_multi_draw', + 'internal': True, + 'trace_level': 1, + 'impl_func': False, + 'unit_test': False, + }, + 'MultiDrawEndCHROMIUM': { + 'decoder_func': 'DoMultiDrawEndCHROMIUM', + 'extension': 'WEBGL_multi_draw', + 'extension_flag': 'webgl_multi_draw', + 'internal': True, + 'trace_level': 1, + 'impl_func': False, + 'unit_test': False, + }, + 'MultiDrawArraysCHROMIUM': { 'type': 'Custom', 'cmd_args': 'GLenumDrawMode mode, ' 'uint32_t firsts_shm_id, uint32_t firsts_shm_offset, ' @@ -2869,9 +2887,10 @@ 'defer_draws': True, 'impl_func': False, 'client_test': False, + 'internal': True, 'trace_level': 2, }, - 'MultiDrawArraysInstancedWEBGL': { + 'MultiDrawArraysInstancedCHROMIUM': { 'type': 'Custom', 'cmd_args': 'GLenumDrawMode mode, ' 'uint32_t firsts_shm_id, uint32_t firsts_shm_offset, ' @@ -2888,9 +2907,10 @@ 'defer_draws': True, 'impl_func': False, 'client_test': False, + 'internal': True, 'trace_level': 2, }, - 'MultiDrawElementsWEBGL': { + 'MultiDrawElementsCHROMIUM': { 'type': 'Custom', 'cmd_args': 'GLenumDrawMode mode, ' 'uint32_t counts_shm_id, uint32_t counts_shm_offset, ' @@ -2906,9 +2926,10 @@ 'defer_draws': True, 'impl_func': False, 'client_test': False, + 'internal': True, 'trace_level': 2, }, - 'MultiDrawElementsInstancedWEBGL': { + 'MultiDrawElementsInstancedCHROMIUM': { 'type': 'Custom', 'cmd_args': 'GLenumDrawMode mode, ' 'uint32_t counts_shm_id, uint32_t counts_shm_offset, ' @@ -2926,8 +2947,29 @@ 'defer_draws': True, 'impl_func': False, 'client_test': False, + 'internal': True, 'trace_level': 2, }, + 'MultiDrawArraysWEBGL': { + 'type': 'NoCommand', + 'extension': 'WEBGL_multi_draw', + 'extension_flag': 'webgl_multi_draw', + }, + 'MultiDrawArraysInstancedWEBGL': { + 'type': 'NoCommand', + 'extension': 'WEBGL_multi_draw_instanced', + 'extension_flag': 'webgl_multi_draw_instanced', + }, + 'MultiDrawElementsWEBGL': { + 'type': 'NoCommand', + 'extension': 'WEBGL_multi_draw', + 'extension_flag': 'webgl_multi_draw', + }, + 'MultiDrawElementsInstancedWEBGL': { + 'type': 'NoCommand', + 'extension': 'WEBGL_multi_draw_instanced', + 'extension_flag': 'webgl_multi_draw_instanced', + }, 'OverlayPromotionHintCHROMIUM': { 'decoder_func': 'DoOverlayPromotionHintCHROMIUM', 'extension': "CHROMIUM_uniform_stream_texture_matrix",
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 828846a..4b936cbc 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -1506,30 +1506,46 @@ } } -void MultiDrawArraysWEBGL(GLenum mode, - uint32_t firsts_shm_id, - uint32_t firsts_shm_offset, - uint32_t counts_shm_id, - uint32_t counts_shm_offset, - GLsizei drawcount) { - gles2::cmds::MultiDrawArraysWEBGL* c = - GetCmdSpace<gles2::cmds::MultiDrawArraysWEBGL>(); +void MultiDrawBeginCHROMIUM(GLsizei drawcount) { + gles2::cmds::MultiDrawBeginCHROMIUM* c = + GetCmdSpace<gles2::cmds::MultiDrawBeginCHROMIUM>(); + if (c) { + c->Init(drawcount); + } +} + +void MultiDrawEndCHROMIUM() { + gles2::cmds::MultiDrawEndCHROMIUM* c = + GetCmdSpace<gles2::cmds::MultiDrawEndCHROMIUM>(); + if (c) { + c->Init(); + } +} + +void MultiDrawArraysCHROMIUM(GLenum mode, + uint32_t firsts_shm_id, + uint32_t firsts_shm_offset, + uint32_t counts_shm_id, + uint32_t counts_shm_offset, + GLsizei drawcount) { + gles2::cmds::MultiDrawArraysCHROMIUM* c = + GetCmdSpace<gles2::cmds::MultiDrawArraysCHROMIUM>(); if (c) { c->Init(mode, firsts_shm_id, firsts_shm_offset, counts_shm_id, counts_shm_offset, drawcount); } } -void MultiDrawArraysInstancedWEBGL(GLenum mode, - uint32_t firsts_shm_id, - uint32_t firsts_shm_offset, - uint32_t counts_shm_id, - uint32_t counts_shm_offset, - uint32_t instance_counts_shm_id, - uint32_t instance_counts_shm_offset, - GLsizei drawcount) { - gles2::cmds::MultiDrawArraysInstancedWEBGL* c = - GetCmdSpace<gles2::cmds::MultiDrawArraysInstancedWEBGL>(); +void MultiDrawArraysInstancedCHROMIUM(GLenum mode, + uint32_t firsts_shm_id, + uint32_t firsts_shm_offset, + uint32_t counts_shm_id, + uint32_t counts_shm_offset, + uint32_t instance_counts_shm_id, + uint32_t instance_counts_shm_offset, + GLsizei drawcount) { + gles2::cmds::MultiDrawArraysInstancedCHROMIUM* c = + GetCmdSpace<gles2::cmds::MultiDrawArraysInstancedCHROMIUM>(); if (c) { c->Init(mode, firsts_shm_id, firsts_shm_offset, counts_shm_id, counts_shm_offset, instance_counts_shm_id, @@ -1537,32 +1553,32 @@ } } -void MultiDrawElementsWEBGL(GLenum mode, - uint32_t counts_shm_id, - uint32_t counts_shm_offset, - GLenum type, - uint32_t offsets_shm_id, - uint32_t offsets_shm_offset, - GLsizei drawcount) { - gles2::cmds::MultiDrawElementsWEBGL* c = - GetCmdSpace<gles2::cmds::MultiDrawElementsWEBGL>(); +void MultiDrawElementsCHROMIUM(GLenum mode, + uint32_t counts_shm_id, + uint32_t counts_shm_offset, + GLenum type, + uint32_t offsets_shm_id, + uint32_t offsets_shm_offset, + GLsizei drawcount) { + gles2::cmds::MultiDrawElementsCHROMIUM* c = + GetCmdSpace<gles2::cmds::MultiDrawElementsCHROMIUM>(); if (c) { c->Init(mode, counts_shm_id, counts_shm_offset, type, offsets_shm_id, offsets_shm_offset, drawcount); } } -void MultiDrawElementsInstancedWEBGL(GLenum mode, - uint32_t counts_shm_id, - uint32_t counts_shm_offset, - GLenum type, - uint32_t offsets_shm_id, - uint32_t offsets_shm_offset, - uint32_t instance_counts_shm_id, - uint32_t instance_counts_shm_offset, - GLsizei drawcount) { - gles2::cmds::MultiDrawElementsInstancedWEBGL* c = - GetCmdSpace<gles2::cmds::MultiDrawElementsInstancedWEBGL>(); +void MultiDrawElementsInstancedCHROMIUM(GLenum mode, + uint32_t counts_shm_id, + uint32_t counts_shm_offset, + GLenum type, + uint32_t offsets_shm_id, + uint32_t offsets_shm_offset, + uint32_t instance_counts_shm_id, + uint32_t instance_counts_shm_offset, + GLsizei drawcount) { + gles2::cmds::MultiDrawElementsInstancedCHROMIUM* c = + GetCmdSpace<gles2::cmds::MultiDrawElementsInstancedCHROMIUM>(); if (c) { c->Init(mode, counts_shm_id, counts_shm_offset, type, offsets_shm_id, offsets_shm_offset, instance_counts_shm_id,
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index dd1ef9d..e857907 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -2174,18 +2174,19 @@ uint32_t buffer_size = ComputeCombinedCopySize(drawcount, firsts, counts); ScopedTransferBufferPtr buffer(buffer_size, helper_, transfer_buffer_); - // TODO(crbug.com/890539): Increment a base gl_DrawID for multiple calls to - // this helper + + helper_->MultiDrawBeginCHROMIUM(drawcount); auto DoMultiDraw = [&](const std::array<uint32_t, 2>& offsets, uint32_t, uint32_t copy_count) { - helper_->MultiDrawArraysWEBGL(mode, buffer.shm_id(), - buffer.offset() + offsets[0], buffer.shm_id(), - buffer.offset() + offsets[1], copy_count); + helper_->MultiDrawArraysCHROMIUM( + mode, buffer.shm_id(), buffer.offset() + offsets[0], buffer.shm_id(), + buffer.offset() + offsets[1], copy_count); }; if (!TransferArraysAndExecute(drawcount, &buffer, DoMultiDraw, firsts, counts)) { SetGLError(GL_OUT_OF_MEMORY, "glMultiDrawArraysWEBGL", "out of memory"); } + helper_->MultiDrawEndCHROMIUM(); } void GLES2Implementation::MultiDrawArraysInstancedWEBGLHelper( @@ -2199,11 +2200,11 @@ uint32_t buffer_size = ComputeCombinedCopySize(drawcount, firsts, counts, instance_counts); ScopedTransferBufferPtr buffer(buffer_size, helper_, transfer_buffer_); - // TODO(crbug.com/890539): Increment a base gl_DrawID for multiple calls to - // this helper + + helper_->MultiDrawBeginCHROMIUM(drawcount); auto DoMultiDraw = [&](const std::array<uint32_t, 3>& offsets, uint32_t, uint32_t copy_count) { - helper_->MultiDrawArraysInstancedWEBGL( + helper_->MultiDrawArraysInstancedCHROMIUM( mode, buffer.shm_id(), buffer.offset() + offsets[0], buffer.shm_id(), buffer.offset() + offsets[1], buffer.shm_id(), buffer.offset() + offsets[2], copy_count); @@ -2213,6 +2214,7 @@ SetGLError(GL_OUT_OF_MEMORY, "glMultiDrawArraysInstancedWEBGL", "out of memory"); } + helper_->MultiDrawEndCHROMIUM(); } void GLES2Implementation::MultiDrawElementsWEBGLHelper(GLenum mode, @@ -2224,11 +2226,11 @@ uint32_t buffer_size = ComputeCombinedCopySize(drawcount, counts, offsets); ScopedTransferBufferPtr buffer(buffer_size, helper_, transfer_buffer_); - // TODO(crbug.com/890539): Increment a base gl_DrawID for multiple calls to - // this helper + + helper_->MultiDrawBeginCHROMIUM(drawcount); auto DoMultiDraw = [&](const std::array<uint32_t, 2>& offsets, uint32_t, uint32_t copy_count) { - helper_->MultiDrawElementsWEBGL( + helper_->MultiDrawElementsCHROMIUM( mode, buffer.shm_id(), buffer.offset() + offsets[0], type, buffer.shm_id(), buffer.offset() + offsets[1], copy_count); }; @@ -2236,6 +2238,7 @@ offsets)) { SetGLError(GL_OUT_OF_MEMORY, "glMultiDrawElementsWEBGL", "out of memory"); } + helper_->MultiDrawEndCHROMIUM(); } void GLES2Implementation::MultiDrawElementsInstancedWEBGLHelper( @@ -2250,11 +2253,11 @@ uint32_t buffer_size = ComputeCombinedCopySize(drawcount, counts, offsets, instance_counts); ScopedTransferBufferPtr buffer(buffer_size, helper_, transfer_buffer_); - // TODO(crbug.com/890539): Increment a base gl_DrawID for multiple calls to - // this helper + + helper_->MultiDrawBeginCHROMIUM(drawcount); auto DoMultiDraw = [&](const std::array<uint32_t, 3>& offsets, uint32_t, uint32_t copy_count) { - helper_->MultiDrawElementsInstancedWEBGL( + helper_->MultiDrawElementsInstancedCHROMIUM( mode, buffer.shm_id(), buffer.offset() + offsets[0], type, buffer.shm_id(), buffer.offset() + offsets[1], buffer.shm_id(), buffer.offset() + offsets[2], copy_count); @@ -2264,6 +2267,7 @@ SetGLError(GL_OUT_OF_MEMORY, "glMultiDrawElementsInstancedWEBGL", "out of memory"); } + helper_->MultiDrawEndCHROMIUM(); } void GLES2Implementation::MultiDrawArraysWEBGL(GLenum mode,
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index c4e1a10..44f1e44 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -3084,6 +3084,39 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, MultiDrawArraysWEBGLLargerThanTransferBuffer) { + struct Cmds { + cmds::MultiDrawBeginCHROMIUM begin; + cmds::MultiDrawArraysCHROMIUM draw1; + cmd::SetToken set_token1; + cmds::MultiDrawArraysCHROMIUM draw2; + cmd::SetToken set_token2; + cmds::MultiDrawEndCHROMIUM end; + }; + const unsigned kUsableSize = + kTransferBufferSize - GLES2Implementation::kStartingOffset; + const unsigned kDrawCount = kUsableSize / sizeof(int); + const unsigned kChunkDrawCount = kDrawCount / 2; + const unsigned kCountsOffset = kChunkDrawCount * sizeof(int); + GLint firsts[kDrawCount] = {0}; + GLsizei counts[kDrawCount] = {0}; + + ExpectedMemoryInfo mem1 = GetExpectedMemory(kUsableSize); + ExpectedMemoryInfo mem2 = GetExpectedMemory(kUsableSize); + + Cmds expected; + expected.begin.Init(kDrawCount); + expected.draw1.Init(GL_TRIANGLES, mem1.id, mem1.offset, mem1.id, + mem1.offset + kCountsOffset, kChunkDrawCount); + expected.set_token1.Init(GetNextToken()); + expected.draw2.Init(GL_TRIANGLES, mem2.id, mem2.offset, mem2.id, + mem2.offset + kCountsOffset, kChunkDrawCount); + expected.set_token2.Init(GetNextToken()); + expected.end.Init(); + gl_->MultiDrawArraysWEBGL(GL_TRIANGLES, firsts, counts, kDrawCount); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, CapabilitiesAreCached) { static const GLenum kStates[] = { GL_DITHER,
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index 58f64e8d..d45e669 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -7493,9 +7493,69 @@ static_assert(offsetof(ShaderSourceBucket, str_bucket_id) == 8, "offset of ShaderSourceBucket str_bucket_id should be 8"); -struct MultiDrawArraysWEBGL { - typedef MultiDrawArraysWEBGL ValueType; - static const CommandId kCmdId = kMultiDrawArraysWEBGL; +struct MultiDrawBeginCHROMIUM { + typedef MultiDrawBeginCHROMIUM ValueType; + static const CommandId kCmdId = kMultiDrawBeginCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLsizei _drawcount) { + SetHeader(); + drawcount = _drawcount; + } + + void* Set(void* cmd, GLsizei _drawcount) { + static_cast<ValueType*>(cmd)->Init(_drawcount); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + int32_t drawcount; +}; + +static_assert(sizeof(MultiDrawBeginCHROMIUM) == 8, + "size of MultiDrawBeginCHROMIUM should be 8"); +static_assert(offsetof(MultiDrawBeginCHROMIUM, header) == 0, + "offset of MultiDrawBeginCHROMIUM header should be 0"); +static_assert(offsetof(MultiDrawBeginCHROMIUM, drawcount) == 4, + "offset of MultiDrawBeginCHROMIUM drawcount should be 4"); + +struct MultiDrawEndCHROMIUM { + typedef MultiDrawEndCHROMIUM ValueType; + static const CommandId kCmdId = kMultiDrawEndCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1); + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init() { SetHeader(); } + + void* Set(void* cmd) { + static_cast<ValueType*>(cmd)->Init(); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; +}; + +static_assert(sizeof(MultiDrawEndCHROMIUM) == 4, + "size of MultiDrawEndCHROMIUM should be 4"); +static_assert(offsetof(MultiDrawEndCHROMIUM, header) == 0, + "offset of MultiDrawEndCHROMIUM header should be 0"); + +struct MultiDrawArraysCHROMIUM { + typedef MultiDrawArraysCHROMIUM ValueType; + static const CommandId kCmdId = kMultiDrawArraysCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); @@ -7542,26 +7602,28 @@ int32_t drawcount; }; -static_assert(sizeof(MultiDrawArraysWEBGL) == 28, - "size of MultiDrawArraysWEBGL should be 28"); -static_assert(offsetof(MultiDrawArraysWEBGL, header) == 0, - "offset of MultiDrawArraysWEBGL header should be 0"); -static_assert(offsetof(MultiDrawArraysWEBGL, mode) == 4, - "offset of MultiDrawArraysWEBGL mode should be 4"); -static_assert(offsetof(MultiDrawArraysWEBGL, firsts_shm_id) == 8, - "offset of MultiDrawArraysWEBGL firsts_shm_id should be 8"); -static_assert(offsetof(MultiDrawArraysWEBGL, firsts_shm_offset) == 12, - "offset of MultiDrawArraysWEBGL firsts_shm_offset should be 12"); -static_assert(offsetof(MultiDrawArraysWEBGL, counts_shm_id) == 16, - "offset of MultiDrawArraysWEBGL counts_shm_id should be 16"); -static_assert(offsetof(MultiDrawArraysWEBGL, counts_shm_offset) == 20, - "offset of MultiDrawArraysWEBGL counts_shm_offset should be 20"); -static_assert(offsetof(MultiDrawArraysWEBGL, drawcount) == 24, - "offset of MultiDrawArraysWEBGL drawcount should be 24"); +static_assert(sizeof(MultiDrawArraysCHROMIUM) == 28, + "size of MultiDrawArraysCHROMIUM should be 28"); +static_assert(offsetof(MultiDrawArraysCHROMIUM, header) == 0, + "offset of MultiDrawArraysCHROMIUM header should be 0"); +static_assert(offsetof(MultiDrawArraysCHROMIUM, mode) == 4, + "offset of MultiDrawArraysCHROMIUM mode should be 4"); +static_assert(offsetof(MultiDrawArraysCHROMIUM, firsts_shm_id) == 8, + "offset of MultiDrawArraysCHROMIUM firsts_shm_id should be 8"); +static_assert( + offsetof(MultiDrawArraysCHROMIUM, firsts_shm_offset) == 12, + "offset of MultiDrawArraysCHROMIUM firsts_shm_offset should be 12"); +static_assert(offsetof(MultiDrawArraysCHROMIUM, counts_shm_id) == 16, + "offset of MultiDrawArraysCHROMIUM counts_shm_id should be 16"); +static_assert( + offsetof(MultiDrawArraysCHROMIUM, counts_shm_offset) == 20, + "offset of MultiDrawArraysCHROMIUM counts_shm_offset should be 20"); +static_assert(offsetof(MultiDrawArraysCHROMIUM, drawcount) == 24, + "offset of MultiDrawArraysCHROMIUM drawcount should be 24"); -struct MultiDrawArraysInstancedWEBGL { - typedef MultiDrawArraysInstancedWEBGL ValueType; - static const CommandId kCmdId = kMultiDrawArraysInstancedWEBGL; +struct MultiDrawArraysInstancedCHROMIUM { + typedef MultiDrawArraysInstancedCHROMIUM ValueType; + static const CommandId kCmdId = kMultiDrawArraysInstancedCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); @@ -7617,38 +7679,41 @@ int32_t drawcount; }; -static_assert(sizeof(MultiDrawArraysInstancedWEBGL) == 36, - "size of MultiDrawArraysInstancedWEBGL should be 36"); -static_assert(offsetof(MultiDrawArraysInstancedWEBGL, header) == 0, - "offset of MultiDrawArraysInstancedWEBGL header should be 0"); -static_assert(offsetof(MultiDrawArraysInstancedWEBGL, mode) == 4, - "offset of MultiDrawArraysInstancedWEBGL mode should be 4"); +static_assert(sizeof(MultiDrawArraysInstancedCHROMIUM) == 36, + "size of MultiDrawArraysInstancedCHROMIUM should be 36"); +static_assert(offsetof(MultiDrawArraysInstancedCHROMIUM, header) == 0, + "offset of MultiDrawArraysInstancedCHROMIUM header should be 0"); +static_assert(offsetof(MultiDrawArraysInstancedCHROMIUM, mode) == 4, + "offset of MultiDrawArraysInstancedCHROMIUM mode should be 4"); static_assert( - offsetof(MultiDrawArraysInstancedWEBGL, firsts_shm_id) == 8, - "offset of MultiDrawArraysInstancedWEBGL firsts_shm_id should be 8"); + offsetof(MultiDrawArraysInstancedCHROMIUM, firsts_shm_id) == 8, + "offset of MultiDrawArraysInstancedCHROMIUM firsts_shm_id should be 8"); +static_assert(offsetof(MultiDrawArraysInstancedCHROMIUM, firsts_shm_offset) == + 12, + "offset of MultiDrawArraysInstancedCHROMIUM firsts_shm_offset " + "should be 12"); static_assert( - offsetof(MultiDrawArraysInstancedWEBGL, firsts_shm_offset) == 12, - "offset of MultiDrawArraysInstancedWEBGL firsts_shm_offset should be 12"); -static_assert( - offsetof(MultiDrawArraysInstancedWEBGL, counts_shm_id) == 16, - "offset of MultiDrawArraysInstancedWEBGL counts_shm_id should be 16"); -static_assert( - offsetof(MultiDrawArraysInstancedWEBGL, counts_shm_offset) == 20, - "offset of MultiDrawArraysInstancedWEBGL counts_shm_offset should be 20"); -static_assert(offsetof(MultiDrawArraysInstancedWEBGL, instance_counts_shm_id) == - 24, - "offset of MultiDrawArraysInstancedWEBGL instance_counts_shm_id " - "should be 24"); -static_assert(offsetof(MultiDrawArraysInstancedWEBGL, + offsetof(MultiDrawArraysInstancedCHROMIUM, counts_shm_id) == 16, + "offset of MultiDrawArraysInstancedCHROMIUM counts_shm_id should be 16"); +static_assert(offsetof(MultiDrawArraysInstancedCHROMIUM, counts_shm_offset) == + 20, + "offset of MultiDrawArraysInstancedCHROMIUM counts_shm_offset " + "should be 20"); +static_assert(offsetof(MultiDrawArraysInstancedCHROMIUM, + instance_counts_shm_id) == 24, + "offset of MultiDrawArraysInstancedCHROMIUM " + "instance_counts_shm_id should be 24"); +static_assert(offsetof(MultiDrawArraysInstancedCHROMIUM, instance_counts_shm_offset) == 28, - "offset of MultiDrawArraysInstancedWEBGL " + "offset of MultiDrawArraysInstancedCHROMIUM " "instance_counts_shm_offset should be 28"); -static_assert(offsetof(MultiDrawArraysInstancedWEBGL, drawcount) == 32, - "offset of MultiDrawArraysInstancedWEBGL drawcount should be 32"); +static_assert( + offsetof(MultiDrawArraysInstancedCHROMIUM, drawcount) == 32, + "offset of MultiDrawArraysInstancedCHROMIUM drawcount should be 32"); -struct MultiDrawElementsWEBGL { - typedef MultiDrawElementsWEBGL ValueType; - static const CommandId kCmdId = kMultiDrawElementsWEBGL; +struct MultiDrawElementsCHROMIUM { + typedef MultiDrawElementsCHROMIUM ValueType; + static const CommandId kCmdId = kMultiDrawElementsCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); @@ -7699,30 +7764,31 @@ int32_t drawcount; }; -static_assert(sizeof(MultiDrawElementsWEBGL) == 32, - "size of MultiDrawElementsWEBGL should be 32"); -static_assert(offsetof(MultiDrawElementsWEBGL, header) == 0, - "offset of MultiDrawElementsWEBGL header should be 0"); -static_assert(offsetof(MultiDrawElementsWEBGL, mode) == 4, - "offset of MultiDrawElementsWEBGL mode should be 4"); -static_assert(offsetof(MultiDrawElementsWEBGL, counts_shm_id) == 8, - "offset of MultiDrawElementsWEBGL counts_shm_id should be 8"); +static_assert(sizeof(MultiDrawElementsCHROMIUM) == 32, + "size of MultiDrawElementsCHROMIUM should be 32"); +static_assert(offsetof(MultiDrawElementsCHROMIUM, header) == 0, + "offset of MultiDrawElementsCHROMIUM header should be 0"); +static_assert(offsetof(MultiDrawElementsCHROMIUM, mode) == 4, + "offset of MultiDrawElementsCHROMIUM mode should be 4"); +static_assert(offsetof(MultiDrawElementsCHROMIUM, counts_shm_id) == 8, + "offset of MultiDrawElementsCHROMIUM counts_shm_id should be 8"); static_assert( - offsetof(MultiDrawElementsWEBGL, counts_shm_offset) == 12, - "offset of MultiDrawElementsWEBGL counts_shm_offset should be 12"); -static_assert(offsetof(MultiDrawElementsWEBGL, type) == 16, - "offset of MultiDrawElementsWEBGL type should be 16"); -static_assert(offsetof(MultiDrawElementsWEBGL, offsets_shm_id) == 20, - "offset of MultiDrawElementsWEBGL offsets_shm_id should be 20"); + offsetof(MultiDrawElementsCHROMIUM, counts_shm_offset) == 12, + "offset of MultiDrawElementsCHROMIUM counts_shm_offset should be 12"); +static_assert(offsetof(MultiDrawElementsCHROMIUM, type) == 16, + "offset of MultiDrawElementsCHROMIUM type should be 16"); static_assert( - offsetof(MultiDrawElementsWEBGL, offsets_shm_offset) == 24, - "offset of MultiDrawElementsWEBGL offsets_shm_offset should be 24"); -static_assert(offsetof(MultiDrawElementsWEBGL, drawcount) == 28, - "offset of MultiDrawElementsWEBGL drawcount should be 28"); + offsetof(MultiDrawElementsCHROMIUM, offsets_shm_id) == 20, + "offset of MultiDrawElementsCHROMIUM offsets_shm_id should be 20"); +static_assert( + offsetof(MultiDrawElementsCHROMIUM, offsets_shm_offset) == 24, + "offset of MultiDrawElementsCHROMIUM offsets_shm_offset should be 24"); +static_assert(offsetof(MultiDrawElementsCHROMIUM, drawcount) == 28, + "offset of MultiDrawElementsCHROMIUM drawcount should be 28"); -struct MultiDrawElementsInstancedWEBGL { - typedef MultiDrawElementsInstancedWEBGL ValueType; - static const CommandId kCmdId = kMultiDrawElementsInstancedWEBGL; +struct MultiDrawElementsInstancedCHROMIUM { + typedef MultiDrawElementsInstancedCHROMIUM ValueType; + static const CommandId kCmdId = kMultiDrawElementsInstancedCHROMIUM; static const cmd::ArgFlags kArgFlags = cmd::kFixed; static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); @@ -7782,38 +7848,40 @@ int32_t drawcount; }; -static_assert(sizeof(MultiDrawElementsInstancedWEBGL) == 40, - "size of MultiDrawElementsInstancedWEBGL should be 40"); -static_assert(offsetof(MultiDrawElementsInstancedWEBGL, header) == 0, - "offset of MultiDrawElementsInstancedWEBGL header should be 0"); -static_assert(offsetof(MultiDrawElementsInstancedWEBGL, mode) == 4, - "offset of MultiDrawElementsInstancedWEBGL mode should be 4"); +static_assert(sizeof(MultiDrawElementsInstancedCHROMIUM) == 40, + "size of MultiDrawElementsInstancedCHROMIUM should be 40"); static_assert( - offsetof(MultiDrawElementsInstancedWEBGL, counts_shm_id) == 8, - "offset of MultiDrawElementsInstancedWEBGL counts_shm_id should be 8"); + offsetof(MultiDrawElementsInstancedCHROMIUM, header) == 0, + "offset of MultiDrawElementsInstancedCHROMIUM header should be 0"); +static_assert(offsetof(MultiDrawElementsInstancedCHROMIUM, mode) == 4, + "offset of MultiDrawElementsInstancedCHROMIUM mode should be 4"); static_assert( - offsetof(MultiDrawElementsInstancedWEBGL, counts_shm_offset) == 12, - "offset of MultiDrawElementsInstancedWEBGL counts_shm_offset should be 12"); -static_assert(offsetof(MultiDrawElementsInstancedWEBGL, type) == 16, - "offset of MultiDrawElementsInstancedWEBGL type should be 16"); + offsetof(MultiDrawElementsInstancedCHROMIUM, counts_shm_id) == 8, + "offset of MultiDrawElementsInstancedCHROMIUM counts_shm_id should be 8"); +static_assert(offsetof(MultiDrawElementsInstancedCHROMIUM, counts_shm_offset) == + 12, + "offset of MultiDrawElementsInstancedCHROMIUM counts_shm_offset " + "should be 12"); +static_assert(offsetof(MultiDrawElementsInstancedCHROMIUM, type) == 16, + "offset of MultiDrawElementsInstancedCHROMIUM type should be 16"); static_assert( - offsetof(MultiDrawElementsInstancedWEBGL, offsets_shm_id) == 20, - "offset of MultiDrawElementsInstancedWEBGL offsets_shm_id should be 20"); -static_assert(offsetof(MultiDrawElementsInstancedWEBGL, offsets_shm_offset) == - 24, - "offset of MultiDrawElementsInstancedWEBGL offsets_shm_offset " + offsetof(MultiDrawElementsInstancedCHROMIUM, offsets_shm_id) == 20, + "offset of MultiDrawElementsInstancedCHROMIUM offsets_shm_id should be 20"); +static_assert(offsetof(MultiDrawElementsInstancedCHROMIUM, + offsets_shm_offset) == 24, + "offset of MultiDrawElementsInstancedCHROMIUM offsets_shm_offset " "should be 24"); -static_assert(offsetof(MultiDrawElementsInstancedWEBGL, +static_assert(offsetof(MultiDrawElementsInstancedCHROMIUM, instance_counts_shm_id) == 28, - "offset of MultiDrawElementsInstancedWEBGL " + "offset of MultiDrawElementsInstancedCHROMIUM " "instance_counts_shm_id should be 28"); -static_assert(offsetof(MultiDrawElementsInstancedWEBGL, +static_assert(offsetof(MultiDrawElementsInstancedCHROMIUM, instance_counts_shm_offset) == 32, - "offset of MultiDrawElementsInstancedWEBGL " + "offset of MultiDrawElementsInstancedCHROMIUM " "instance_counts_shm_offset should be 32"); static_assert( - offsetof(MultiDrawElementsInstancedWEBGL, drawcount) == 36, - "offset of MultiDrawElementsInstancedWEBGL drawcount should be 36"); + offsetof(MultiDrawElementsInstancedCHROMIUM, drawcount) == 36, + "offset of MultiDrawElementsInstancedCHROMIUM drawcount should be 36"); struct StencilFunc { typedef StencilFunc ValueType;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 84d7ce4..62958cd 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -2298,13 +2298,34 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } -TEST_F(GLES2FormatTest, MultiDrawArraysWEBGL) { - cmds::MultiDrawArraysWEBGL& cmd = *GetBufferAs<cmds::MultiDrawArraysWEBGL>(); +TEST_F(GLES2FormatTest, MultiDrawBeginCHROMIUM) { + cmds::MultiDrawBeginCHROMIUM& cmd = + *GetBufferAs<cmds::MultiDrawBeginCHROMIUM>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLsizei>(11)); + EXPECT_EQ(static_cast<uint32_t>(cmds::MultiDrawBeginCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLsizei>(11), cmd.drawcount); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, MultiDrawEndCHROMIUM) { + cmds::MultiDrawEndCHROMIUM& cmd = *GetBufferAs<cmds::MultiDrawEndCHROMIUM>(); + void* next_cmd = cmd.Set(&cmd); + EXPECT_EQ(static_cast<uint32_t>(cmds::MultiDrawEndCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, MultiDrawArraysCHROMIUM) { + cmds::MultiDrawArraysCHROMIUM& cmd = + *GetBufferAs<cmds::MultiDrawArraysCHROMIUM>(); void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<uint32_t>(12), static_cast<uint32_t>(13), static_cast<uint32_t>(14), static_cast<uint32_t>(15), static_cast<GLsizei>(16)); - EXPECT_EQ(static_cast<uint32_t>(cmds::MultiDrawArraysWEBGL::kCmdId), + EXPECT_EQ(static_cast<uint32_t>(cmds::MultiDrawArraysCHROMIUM::kCmdId), cmd.header.command); EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); EXPECT_EQ(static_cast<GLenum>(11), cmd.mode); @@ -2316,16 +2337,17 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } -TEST_F(GLES2FormatTest, MultiDrawArraysInstancedWEBGL) { - cmds::MultiDrawArraysInstancedWEBGL& cmd = - *GetBufferAs<cmds::MultiDrawArraysInstancedWEBGL>(); +TEST_F(GLES2FormatTest, MultiDrawArraysInstancedCHROMIUM) { + cmds::MultiDrawArraysInstancedCHROMIUM& cmd = + *GetBufferAs<cmds::MultiDrawArraysInstancedCHROMIUM>(); void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<uint32_t>(12), static_cast<uint32_t>(13), static_cast<uint32_t>(14), static_cast<uint32_t>(15), static_cast<uint32_t>(16), static_cast<uint32_t>(17), static_cast<GLsizei>(18)); - EXPECT_EQ(static_cast<uint32_t>(cmds::MultiDrawArraysInstancedWEBGL::kCmdId), - cmd.header.command); + EXPECT_EQ( + static_cast<uint32_t>(cmds::MultiDrawArraysInstancedCHROMIUM::kCmdId), + cmd.header.command); EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); EXPECT_EQ(static_cast<GLenum>(11), cmd.mode); EXPECT_EQ(static_cast<uint32_t>(12), cmd.firsts_shm_id); @@ -2338,14 +2360,14 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } -TEST_F(GLES2FormatTest, MultiDrawElementsWEBGL) { - cmds::MultiDrawElementsWEBGL& cmd = - *GetBufferAs<cmds::MultiDrawElementsWEBGL>(); +TEST_F(GLES2FormatTest, MultiDrawElementsCHROMIUM) { + cmds::MultiDrawElementsCHROMIUM& cmd = + *GetBufferAs<cmds::MultiDrawElementsCHROMIUM>(); void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<uint32_t>(12), static_cast<uint32_t>(13), static_cast<GLenum>(14), static_cast<uint32_t>(15), static_cast<uint32_t>(16), static_cast<GLsizei>(17)); - EXPECT_EQ(static_cast<uint32_t>(cmds::MultiDrawElementsWEBGL::kCmdId), + EXPECT_EQ(static_cast<uint32_t>(cmds::MultiDrawElementsCHROMIUM::kCmdId), cmd.header.command); EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); EXPECT_EQ(static_cast<GLenum>(11), cmd.mode); @@ -2358,16 +2380,16 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } -TEST_F(GLES2FormatTest, MultiDrawElementsInstancedWEBGL) { - cmds::MultiDrawElementsInstancedWEBGL& cmd = - *GetBufferAs<cmds::MultiDrawElementsInstancedWEBGL>(); +TEST_F(GLES2FormatTest, MultiDrawElementsInstancedCHROMIUM) { + cmds::MultiDrawElementsInstancedCHROMIUM& cmd = + *GetBufferAs<cmds::MultiDrawElementsInstancedCHROMIUM>(); void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<uint32_t>(12), static_cast<uint32_t>(13), static_cast<GLenum>(14), static_cast<uint32_t>(15), static_cast<uint32_t>(16), static_cast<uint32_t>(17), static_cast<uint32_t>(18), static_cast<GLsizei>(19)); EXPECT_EQ( - static_cast<uint32_t>(cmds::MultiDrawElementsInstancedWEBGL::kCmdId), + static_cast<uint32_t>(cmds::MultiDrawElementsInstancedCHROMIUM::kCmdId), cmd.header.command); EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); EXPECT_EQ(static_cast<GLenum>(11), cmd.mode);
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 61b3de1..c3321ba 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -165,195 +165,197 @@ OP(Scissor) /* 406 */ \ OP(ShaderBinary) /* 407 */ \ OP(ShaderSourceBucket) /* 408 */ \ - OP(MultiDrawArraysWEBGL) /* 409 */ \ - OP(MultiDrawArraysInstancedWEBGL) /* 410 */ \ - OP(MultiDrawElementsWEBGL) /* 411 */ \ - OP(MultiDrawElementsInstancedWEBGL) /* 412 */ \ - OP(StencilFunc) /* 413 */ \ - OP(StencilFuncSeparate) /* 414 */ \ - OP(StencilMask) /* 415 */ \ - OP(StencilMaskSeparate) /* 416 */ \ - OP(StencilOp) /* 417 */ \ - OP(StencilOpSeparate) /* 418 */ \ - OP(TexImage2D) /* 419 */ \ - OP(TexImage3D) /* 420 */ \ - OP(TexParameterf) /* 421 */ \ - OP(TexParameterfvImmediate) /* 422 */ \ - OP(TexParameteri) /* 423 */ \ - OP(TexParameterivImmediate) /* 424 */ \ - OP(TexStorage3D) /* 425 */ \ - OP(TexSubImage2D) /* 426 */ \ - OP(TexSubImage3D) /* 427 */ \ - OP(TransformFeedbackVaryingsBucket) /* 428 */ \ - OP(Uniform1f) /* 429 */ \ - OP(Uniform1fvImmediate) /* 430 */ \ - OP(Uniform1i) /* 431 */ \ - OP(Uniform1ivImmediate) /* 432 */ \ - OP(Uniform1ui) /* 433 */ \ - OP(Uniform1uivImmediate) /* 434 */ \ - OP(Uniform2f) /* 435 */ \ - OP(Uniform2fvImmediate) /* 436 */ \ - OP(Uniform2i) /* 437 */ \ - OP(Uniform2ivImmediate) /* 438 */ \ - OP(Uniform2ui) /* 439 */ \ - OP(Uniform2uivImmediate) /* 440 */ \ - OP(Uniform3f) /* 441 */ \ - OP(Uniform3fvImmediate) /* 442 */ \ - OP(Uniform3i) /* 443 */ \ - OP(Uniform3ivImmediate) /* 444 */ \ - OP(Uniform3ui) /* 445 */ \ - OP(Uniform3uivImmediate) /* 446 */ \ - OP(Uniform4f) /* 447 */ \ - OP(Uniform4fvImmediate) /* 448 */ \ - OP(Uniform4i) /* 449 */ \ - OP(Uniform4ivImmediate) /* 450 */ \ - OP(Uniform4ui) /* 451 */ \ - OP(Uniform4uivImmediate) /* 452 */ \ - OP(UniformBlockBinding) /* 453 */ \ - OP(UniformMatrix2fvImmediate) /* 454 */ \ - OP(UniformMatrix2x3fvImmediate) /* 455 */ \ - OP(UniformMatrix2x4fvImmediate) /* 456 */ \ - OP(UniformMatrix3fvImmediate) /* 457 */ \ - OP(UniformMatrix3x2fvImmediate) /* 458 */ \ - OP(UniformMatrix3x4fvImmediate) /* 459 */ \ - OP(UniformMatrix4fvImmediate) /* 460 */ \ - OP(UniformMatrix4x2fvImmediate) /* 461 */ \ - OP(UniformMatrix4x3fvImmediate) /* 462 */ \ - OP(UseProgram) /* 463 */ \ - OP(ValidateProgram) /* 464 */ \ - OP(VertexAttrib1f) /* 465 */ \ - OP(VertexAttrib1fvImmediate) /* 466 */ \ - OP(VertexAttrib2f) /* 467 */ \ - OP(VertexAttrib2fvImmediate) /* 468 */ \ - OP(VertexAttrib3f) /* 469 */ \ - OP(VertexAttrib3fvImmediate) /* 470 */ \ - OP(VertexAttrib4f) /* 471 */ \ - OP(VertexAttrib4fvImmediate) /* 472 */ \ - OP(VertexAttribI4i) /* 473 */ \ - OP(VertexAttribI4ivImmediate) /* 474 */ \ - OP(VertexAttribI4ui) /* 475 */ \ - OP(VertexAttribI4uivImmediate) /* 476 */ \ - OP(VertexAttribIPointer) /* 477 */ \ - OP(VertexAttribPointer) /* 478 */ \ - OP(Viewport) /* 479 */ \ - OP(WaitSync) /* 480 */ \ - OP(BlitFramebufferCHROMIUM) /* 481 */ \ - OP(RenderbufferStorageMultisampleCHROMIUM) /* 482 */ \ - OP(RenderbufferStorageMultisampleEXT) /* 483 */ \ - OP(FramebufferTexture2DMultisampleEXT) /* 484 */ \ - OP(TexStorage2DEXT) /* 485 */ \ - OP(GenQueriesEXTImmediate) /* 486 */ \ - OP(DeleteQueriesEXTImmediate) /* 487 */ \ - OP(QueryCounterEXT) /* 488 */ \ - OP(BeginQueryEXT) /* 489 */ \ - OP(BeginTransformFeedback) /* 490 */ \ - OP(EndQueryEXT) /* 491 */ \ - OP(EndTransformFeedback) /* 492 */ \ - OP(SetDisjointValueSyncCHROMIUM) /* 493 */ \ - OP(InsertEventMarkerEXT) /* 494 */ \ - OP(PushGroupMarkerEXT) /* 495 */ \ - OP(PopGroupMarkerEXT) /* 496 */ \ - OP(GenVertexArraysOESImmediate) /* 497 */ \ - OP(DeleteVertexArraysOESImmediate) /* 498 */ \ - OP(IsVertexArrayOES) /* 499 */ \ - OP(BindVertexArrayOES) /* 500 */ \ - OP(FramebufferParameteri) /* 501 */ \ - OP(BindImageTexture) /* 502 */ \ - OP(DispatchCompute) /* 503 */ \ - OP(MemoryBarrierEXT) /* 504 */ \ - OP(MemoryBarrierByRegion) /* 505 */ \ - OP(SwapBuffers) /* 506 */ \ - OP(GetMaxValueInBufferCHROMIUM) /* 507 */ \ - OP(EnableFeatureCHROMIUM) /* 508 */ \ - OP(MapBufferRange) /* 509 */ \ - OP(UnmapBuffer) /* 510 */ \ - OP(FlushMappedBufferRange) /* 511 */ \ - OP(ResizeCHROMIUM) /* 512 */ \ - OP(GetRequestableExtensionsCHROMIUM) /* 513 */ \ - OP(RequestExtensionCHROMIUM) /* 514 */ \ - OP(GetProgramInfoCHROMIUM) /* 515 */ \ - OP(GetUniformBlocksCHROMIUM) /* 516 */ \ - OP(GetTransformFeedbackVaryingsCHROMIUM) /* 517 */ \ - OP(GetUniformsES3CHROMIUM) /* 518 */ \ - OP(DescheduleUntilFinishedCHROMIUM) /* 519 */ \ - OP(GetTranslatedShaderSourceANGLE) /* 520 */ \ - OP(PostSubBufferCHROMIUM) /* 521 */ \ - OP(CopyTextureCHROMIUM) /* 522 */ \ - OP(CopySubTextureCHROMIUM) /* 523 */ \ - OP(DrawArraysInstancedANGLE) /* 524 */ \ - OP(DrawElementsInstancedANGLE) /* 525 */ \ - OP(VertexAttribDivisorANGLE) /* 526 */ \ - OP(ProduceTextureDirectCHROMIUMImmediate) /* 527 */ \ - OP(CreateAndConsumeTextureINTERNALImmediate) /* 528 */ \ - OP(BindUniformLocationCHROMIUMBucket) /* 529 */ \ - OP(BindTexImage2DCHROMIUM) /* 530 */ \ - OP(BindTexImage2DWithInternalformatCHROMIUM) /* 531 */ \ - OP(ReleaseTexImage2DCHROMIUM) /* 532 */ \ - OP(TraceBeginCHROMIUM) /* 533 */ \ - OP(TraceEndCHROMIUM) /* 534 */ \ - OP(DiscardFramebufferEXTImmediate) /* 535 */ \ - OP(LoseContextCHROMIUM) /* 536 */ \ - OP(InsertFenceSyncCHROMIUM) /* 537 */ \ - OP(UnpremultiplyAndDitherCopyCHROMIUM) /* 538 */ \ - OP(DrawBuffersEXTImmediate) /* 539 */ \ - OP(DiscardBackbufferCHROMIUM) /* 540 */ \ - OP(ScheduleOverlayPlaneCHROMIUM) /* 541 */ \ - OP(ScheduleCALayerSharedStateCHROMIUM) /* 542 */ \ - OP(ScheduleCALayerCHROMIUM) /* 543 */ \ - OP(ScheduleCALayerInUseQueryCHROMIUMImmediate) /* 544 */ \ - OP(CommitOverlayPlanesCHROMIUM) /* 545 */ \ - OP(FlushDriverCachesCHROMIUM) /* 546 */ \ - OP(ScheduleDCLayerCHROMIUM) /* 547 */ \ - OP(SetActiveURLCHROMIUM) /* 548 */ \ - OP(MatrixLoadfCHROMIUMImmediate) /* 549 */ \ - OP(MatrixLoadIdentityCHROMIUM) /* 550 */ \ - OP(GenPathsCHROMIUM) /* 551 */ \ - OP(DeletePathsCHROMIUM) /* 552 */ \ - OP(IsPathCHROMIUM) /* 553 */ \ - OP(PathCommandsCHROMIUM) /* 554 */ \ - OP(PathParameterfCHROMIUM) /* 555 */ \ - OP(PathParameteriCHROMIUM) /* 556 */ \ - OP(PathStencilFuncCHROMIUM) /* 557 */ \ - OP(StencilFillPathCHROMIUM) /* 558 */ \ - OP(StencilStrokePathCHROMIUM) /* 559 */ \ - OP(CoverFillPathCHROMIUM) /* 560 */ \ - OP(CoverStrokePathCHROMIUM) /* 561 */ \ - OP(StencilThenCoverFillPathCHROMIUM) /* 562 */ \ - OP(StencilThenCoverStrokePathCHROMIUM) /* 563 */ \ - OP(StencilFillPathInstancedCHROMIUM) /* 564 */ \ - OP(StencilStrokePathInstancedCHROMIUM) /* 565 */ \ - OP(CoverFillPathInstancedCHROMIUM) /* 566 */ \ - OP(CoverStrokePathInstancedCHROMIUM) /* 567 */ \ - OP(StencilThenCoverFillPathInstancedCHROMIUM) /* 568 */ \ - OP(StencilThenCoverStrokePathInstancedCHROMIUM) /* 569 */ \ - OP(BindFragmentInputLocationCHROMIUMBucket) /* 570 */ \ - OP(ProgramPathFragmentInputGenCHROMIUM) /* 571 */ \ - OP(CoverageModulationCHROMIUM) /* 572 */ \ - OP(BlendBarrierKHR) /* 573 */ \ - OP(ApplyScreenSpaceAntialiasingCHROMIUM) /* 574 */ \ - OP(BindFragDataLocationIndexedEXTBucket) /* 575 */ \ - OP(BindFragDataLocationEXTBucket) /* 576 */ \ - OP(GetFragDataIndexEXT) /* 577 */ \ - OP(UniformMatrix4fvStreamTextureMatrixCHROMIUMImmediate) /* 578 */ \ - OP(OverlayPromotionHintCHROMIUM) /* 579 */ \ - OP(SwapBuffersWithBoundsCHROMIUMImmediate) /* 580 */ \ - OP(SetDrawRectangleCHROMIUM) /* 581 */ \ - OP(SetEnableDCLayersCHROMIUM) /* 582 */ \ - OP(InitializeDiscardableTextureCHROMIUM) /* 583 */ \ - OP(UnlockDiscardableTextureCHROMIUM) /* 584 */ \ - OP(LockDiscardableTextureCHROMIUM) /* 585 */ \ - OP(TexStorage2DImageCHROMIUM) /* 586 */ \ - OP(SetColorSpaceMetadataCHROMIUM) /* 587 */ \ - OP(WindowRectanglesEXTImmediate) /* 588 */ \ - OP(CreateGpuFenceINTERNAL) /* 589 */ \ - OP(WaitGpuFenceCHROMIUM) /* 590 */ \ - OP(DestroyGpuFenceCHROMIUM) /* 591 */ \ - OP(SetReadbackBufferShadowAllocationINTERNAL) /* 592 */ \ - OP(FramebufferTextureMultiviewLayeredANGLE) /* 593 */ \ - OP(MaxShaderCompilerThreadsKHR) /* 594 */ \ - OP(CreateAndTexStorage2DSharedImageINTERNALImmediate) /* 595 */ \ - OP(BeginSharedImageAccessDirectCHROMIUM) /* 596 */ \ - OP(EndSharedImageAccessDirectCHROMIUM) /* 597 */ + OP(MultiDrawBeginCHROMIUM) /* 409 */ \ + OP(MultiDrawEndCHROMIUM) /* 410 */ \ + OP(MultiDrawArraysCHROMIUM) /* 411 */ \ + OP(MultiDrawArraysInstancedCHROMIUM) /* 412 */ \ + OP(MultiDrawElementsCHROMIUM) /* 413 */ \ + OP(MultiDrawElementsInstancedCHROMIUM) /* 414 */ \ + OP(StencilFunc) /* 415 */ \ + OP(StencilFuncSeparate) /* 416 */ \ + OP(StencilMask) /* 417 */ \ + OP(StencilMaskSeparate) /* 418 */ \ + OP(StencilOp) /* 419 */ \ + OP(StencilOpSeparate) /* 420 */ \ + OP(TexImage2D) /* 421 */ \ + OP(TexImage3D) /* 422 */ \ + OP(TexParameterf) /* 423 */ \ + OP(TexParameterfvImmediate) /* 424 */ \ + OP(TexParameteri) /* 425 */ \ + OP(TexParameterivImmediate) /* 426 */ \ + OP(TexStorage3D) /* 427 */ \ + OP(TexSubImage2D) /* 428 */ \ + OP(TexSubImage3D) /* 429 */ \ + OP(TransformFeedbackVaryingsBucket) /* 430 */ \ + OP(Uniform1f) /* 431 */ \ + OP(Uniform1fvImmediate) /* 432 */ \ + OP(Uniform1i) /* 433 */ \ + OP(Uniform1ivImmediate) /* 434 */ \ + OP(Uniform1ui) /* 435 */ \ + OP(Uniform1uivImmediate) /* 436 */ \ + OP(Uniform2f) /* 437 */ \ + OP(Uniform2fvImmediate) /* 438 */ \ + OP(Uniform2i) /* 439 */ \ + OP(Uniform2ivImmediate) /* 440 */ \ + OP(Uniform2ui) /* 441 */ \ + OP(Uniform2uivImmediate) /* 442 */ \ + OP(Uniform3f) /* 443 */ \ + OP(Uniform3fvImmediate) /* 444 */ \ + OP(Uniform3i) /* 445 */ \ + OP(Uniform3ivImmediate) /* 446 */ \ + OP(Uniform3ui) /* 447 */ \ + OP(Uniform3uivImmediate) /* 448 */ \ + OP(Uniform4f) /* 449 */ \ + OP(Uniform4fvImmediate) /* 450 */ \ + OP(Uniform4i) /* 451 */ \ + OP(Uniform4ivImmediate) /* 452 */ \ + OP(Uniform4ui) /* 453 */ \ + OP(Uniform4uivImmediate) /* 454 */ \ + OP(UniformBlockBinding) /* 455 */ \ + OP(UniformMatrix2fvImmediate) /* 456 */ \ + OP(UniformMatrix2x3fvImmediate) /* 457 */ \ + OP(UniformMatrix2x4fvImmediate) /* 458 */ \ + OP(UniformMatrix3fvImmediate) /* 459 */ \ + OP(UniformMatrix3x2fvImmediate) /* 460 */ \ + OP(UniformMatrix3x4fvImmediate) /* 461 */ \ + OP(UniformMatrix4fvImmediate) /* 462 */ \ + OP(UniformMatrix4x2fvImmediate) /* 463 */ \ + OP(UniformMatrix4x3fvImmediate) /* 464 */ \ + OP(UseProgram) /* 465 */ \ + OP(ValidateProgram) /* 466 */ \ + OP(VertexAttrib1f) /* 467 */ \ + OP(VertexAttrib1fvImmediate) /* 468 */ \ + OP(VertexAttrib2f) /* 469 */ \ + OP(VertexAttrib2fvImmediate) /* 470 */ \ + OP(VertexAttrib3f) /* 471 */ \ + OP(VertexAttrib3fvImmediate) /* 472 */ \ + OP(VertexAttrib4f) /* 473 */ \ + OP(VertexAttrib4fvImmediate) /* 474 */ \ + OP(VertexAttribI4i) /* 475 */ \ + OP(VertexAttribI4ivImmediate) /* 476 */ \ + OP(VertexAttribI4ui) /* 477 */ \ + OP(VertexAttribI4uivImmediate) /* 478 */ \ + OP(VertexAttribIPointer) /* 479 */ \ + OP(VertexAttribPointer) /* 480 */ \ + OP(Viewport) /* 481 */ \ + OP(WaitSync) /* 482 */ \ + OP(BlitFramebufferCHROMIUM) /* 483 */ \ + OP(RenderbufferStorageMultisampleCHROMIUM) /* 484 */ \ + OP(RenderbufferStorageMultisampleEXT) /* 485 */ \ + OP(FramebufferTexture2DMultisampleEXT) /* 486 */ \ + OP(TexStorage2DEXT) /* 487 */ \ + OP(GenQueriesEXTImmediate) /* 488 */ \ + OP(DeleteQueriesEXTImmediate) /* 489 */ \ + OP(QueryCounterEXT) /* 490 */ \ + OP(BeginQueryEXT) /* 491 */ \ + OP(BeginTransformFeedback) /* 492 */ \ + OP(EndQueryEXT) /* 493 */ \ + OP(EndTransformFeedback) /* 494 */ \ + OP(SetDisjointValueSyncCHROMIUM) /* 495 */ \ + OP(InsertEventMarkerEXT) /* 496 */ \ + OP(PushGroupMarkerEXT) /* 497 */ \ + OP(PopGroupMarkerEXT) /* 498 */ \ + OP(GenVertexArraysOESImmediate) /* 499 */ \ + OP(DeleteVertexArraysOESImmediate) /* 500 */ \ + OP(IsVertexArrayOES) /* 501 */ \ + OP(BindVertexArrayOES) /* 502 */ \ + OP(FramebufferParameteri) /* 503 */ \ + OP(BindImageTexture) /* 504 */ \ + OP(DispatchCompute) /* 505 */ \ + OP(MemoryBarrierEXT) /* 506 */ \ + OP(MemoryBarrierByRegion) /* 507 */ \ + OP(SwapBuffers) /* 508 */ \ + OP(GetMaxValueInBufferCHROMIUM) /* 509 */ \ + OP(EnableFeatureCHROMIUM) /* 510 */ \ + OP(MapBufferRange) /* 511 */ \ + OP(UnmapBuffer) /* 512 */ \ + OP(FlushMappedBufferRange) /* 513 */ \ + OP(ResizeCHROMIUM) /* 514 */ \ + OP(GetRequestableExtensionsCHROMIUM) /* 515 */ \ + OP(RequestExtensionCHROMIUM) /* 516 */ \ + OP(GetProgramInfoCHROMIUM) /* 517 */ \ + OP(GetUniformBlocksCHROMIUM) /* 518 */ \ + OP(GetTransformFeedbackVaryingsCHROMIUM) /* 519 */ \ + OP(GetUniformsES3CHROMIUM) /* 520 */ \ + OP(DescheduleUntilFinishedCHROMIUM) /* 521 */ \ + OP(GetTranslatedShaderSourceANGLE) /* 522 */ \ + OP(PostSubBufferCHROMIUM) /* 523 */ \ + OP(CopyTextureCHROMIUM) /* 524 */ \ + OP(CopySubTextureCHROMIUM) /* 525 */ \ + OP(DrawArraysInstancedANGLE) /* 526 */ \ + OP(DrawElementsInstancedANGLE) /* 527 */ \ + OP(VertexAttribDivisorANGLE) /* 528 */ \ + OP(ProduceTextureDirectCHROMIUMImmediate) /* 529 */ \ + OP(CreateAndConsumeTextureINTERNALImmediate) /* 530 */ \ + OP(BindUniformLocationCHROMIUMBucket) /* 531 */ \ + OP(BindTexImage2DCHROMIUM) /* 532 */ \ + OP(BindTexImage2DWithInternalformatCHROMIUM) /* 533 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 534 */ \ + OP(TraceBeginCHROMIUM) /* 535 */ \ + OP(TraceEndCHROMIUM) /* 536 */ \ + OP(DiscardFramebufferEXTImmediate) /* 537 */ \ + OP(LoseContextCHROMIUM) /* 538 */ \ + OP(InsertFenceSyncCHROMIUM) /* 539 */ \ + OP(UnpremultiplyAndDitherCopyCHROMIUM) /* 540 */ \ + OP(DrawBuffersEXTImmediate) /* 541 */ \ + OP(DiscardBackbufferCHROMIUM) /* 542 */ \ + OP(ScheduleOverlayPlaneCHROMIUM) /* 543 */ \ + OP(ScheduleCALayerSharedStateCHROMIUM) /* 544 */ \ + OP(ScheduleCALayerCHROMIUM) /* 545 */ \ + OP(ScheduleCALayerInUseQueryCHROMIUMImmediate) /* 546 */ \ + OP(CommitOverlayPlanesCHROMIUM) /* 547 */ \ + OP(FlushDriverCachesCHROMIUM) /* 548 */ \ + OP(ScheduleDCLayerCHROMIUM) /* 549 */ \ + OP(SetActiveURLCHROMIUM) /* 550 */ \ + OP(MatrixLoadfCHROMIUMImmediate) /* 551 */ \ + OP(MatrixLoadIdentityCHROMIUM) /* 552 */ \ + OP(GenPathsCHROMIUM) /* 553 */ \ + OP(DeletePathsCHROMIUM) /* 554 */ \ + OP(IsPathCHROMIUM) /* 555 */ \ + OP(PathCommandsCHROMIUM) /* 556 */ \ + OP(PathParameterfCHROMIUM) /* 557 */ \ + OP(PathParameteriCHROMIUM) /* 558 */ \ + OP(PathStencilFuncCHROMIUM) /* 559 */ \ + OP(StencilFillPathCHROMIUM) /* 560 */ \ + OP(StencilStrokePathCHROMIUM) /* 561 */ \ + OP(CoverFillPathCHROMIUM) /* 562 */ \ + OP(CoverStrokePathCHROMIUM) /* 563 */ \ + OP(StencilThenCoverFillPathCHROMIUM) /* 564 */ \ + OP(StencilThenCoverStrokePathCHROMIUM) /* 565 */ \ + OP(StencilFillPathInstancedCHROMIUM) /* 566 */ \ + OP(StencilStrokePathInstancedCHROMIUM) /* 567 */ \ + OP(CoverFillPathInstancedCHROMIUM) /* 568 */ \ + OP(CoverStrokePathInstancedCHROMIUM) /* 569 */ \ + OP(StencilThenCoverFillPathInstancedCHROMIUM) /* 570 */ \ + OP(StencilThenCoverStrokePathInstancedCHROMIUM) /* 571 */ \ + OP(BindFragmentInputLocationCHROMIUMBucket) /* 572 */ \ + OP(ProgramPathFragmentInputGenCHROMIUM) /* 573 */ \ + OP(CoverageModulationCHROMIUM) /* 574 */ \ + OP(BlendBarrierKHR) /* 575 */ \ + OP(ApplyScreenSpaceAntialiasingCHROMIUM) /* 576 */ \ + OP(BindFragDataLocationIndexedEXTBucket) /* 577 */ \ + OP(BindFragDataLocationEXTBucket) /* 578 */ \ + OP(GetFragDataIndexEXT) /* 579 */ \ + OP(UniformMatrix4fvStreamTextureMatrixCHROMIUMImmediate) /* 580 */ \ + OP(OverlayPromotionHintCHROMIUM) /* 581 */ \ + OP(SwapBuffersWithBoundsCHROMIUMImmediate) /* 582 */ \ + OP(SetDrawRectangleCHROMIUM) /* 583 */ \ + OP(SetEnableDCLayersCHROMIUM) /* 584 */ \ + OP(InitializeDiscardableTextureCHROMIUM) /* 585 */ \ + OP(UnlockDiscardableTextureCHROMIUM) /* 586 */ \ + OP(LockDiscardableTextureCHROMIUM) /* 587 */ \ + OP(TexStorage2DImageCHROMIUM) /* 588 */ \ + OP(SetColorSpaceMetadataCHROMIUM) /* 589 */ \ + OP(WindowRectanglesEXTImmediate) /* 590 */ \ + OP(CreateGpuFenceINTERNAL) /* 591 */ \ + OP(WaitGpuFenceCHROMIUM) /* 592 */ \ + OP(DestroyGpuFenceCHROMIUM) /* 593 */ \ + OP(SetReadbackBufferShadowAllocationINTERNAL) /* 594 */ \ + OP(FramebufferTextureMultiviewLayeredANGLE) /* 595 */ \ + OP(MaxShaderCompilerThreadsKHR) /* 596 */ \ + OP(CreateAndTexStorage2DSharedImageINTERNALImmediate) /* 597 */ \ + OP(BeginSharedImageAccessDirectCHROMIUM) /* 598 */ \ + OP(EndSharedImageAccessDirectCHROMIUM) /* 599 */ enum CommandId { kOneBeforeStartPoint =
diff --git a/gpu/command_buffer/gles2_cmd_buffer_functions.txt b/gpu/command_buffer/gles2_cmd_buffer_functions.txt index e375c467..740a8dc 100644 --- a/gpu/command_buffer/gles2_cmd_buffer_functions.txt +++ b/gpu/command_buffer/gles2_cmd_buffer_functions.txt
@@ -158,10 +158,20 @@ GL_APICALL void GL_APIENTRY glShallowFinishCHROMIUM (void); GL_APICALL void GL_APIENTRY glShallowFlushCHROMIUM (void); GL_APICALL void GL_APIENTRY glOrderingBarrierCHROMIUM (void); + +// Extensions WEBGL_multi_draw and WEBGL_multi_draw_instanced +// WEBGL entrypoints are public, CHROMIUM entrypoints are internal to the command buffer +GL_APICALL void GL_APIENTRY glMultiDrawBeginCHROMIUM (GLsizei drawcount); +GL_APICALL void GL_APIENTRY glMultiDrawEndCHROMIUM (void); +GL_APICALL void GL_APIENTRY glMultiDrawArraysCHROMIUM (GLenumDrawMode mode, const GLint* firsts, const GLsizei* counts, GLsizei drawcount); +GL_APICALL void GL_APIENTRY glMultiDrawArraysInstancedCHROMIUM (GLenumDrawMode mode, const GLint* firsts, const GLsizei* counts, const GLsizei* instance_counts, GLsizei drawcount); +GL_APICALL void GL_APIENTRY glMultiDrawElementsCHROMIUM (GLenumDrawMode mode, const GLsizei* counts, GLenumIndexType type, const GLsizei* offsets, GLsizei drawcount); +GL_APICALL void GL_APIENTRY glMultiDrawElementsInstancedCHROMIUM (GLenumDrawMode mode, const GLsizei* counts, GLenumIndexType type, const GLsizei* offsets, const GLsizei* instance_counts, GLsizei drawcount); GL_APICALL void GL_APIENTRY glMultiDrawArraysWEBGL (GLenumDrawMode mode, const GLint* firsts, const GLsizei* counts, GLsizei drawcount); GL_APICALL void GL_APIENTRY glMultiDrawArraysInstancedWEBGL (GLenumDrawMode mode, const GLint* firsts, const GLsizei* counts, const GLsizei* instance_counts, GLsizei drawcount); GL_APICALL void GL_APIENTRY glMultiDrawElementsWEBGL (GLenumDrawMode mode, const GLsizei* counts, GLenumIndexType type, const GLsizei* offsets, GLsizei drawcount); GL_APICALL void GL_APIENTRY glMultiDrawElementsInstancedWEBGL (GLenumDrawMode mode, const GLsizei* counts, GLenumIndexType type, const GLsizei* offsets, const GLsizei* instance_counts, GLsizei drawcount); + GL_APICALL void GL_APIENTRY glStencilFunc (GLenumCmpFunction func, GLint ref, GLuint mask); GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenumFaceType face, GLenumCmpFunction func, GLint ref, GLuint mask); GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn index 697d74c..bd70014 100644 --- a/gpu/command_buffer/service/BUILD.gn +++ b/gpu/command_buffer/service/BUILD.gn
@@ -183,6 +183,8 @@ "mailbox_manager_sync.h", "memory_program_cache.cc", "memory_program_cache.h", + "multi_draw_manager.cc", + "multi_draw_manager.h", "passthrough_abstract_texture_impl.cc", "passthrough_abstract_texture_impl.h", "passthrough_discardable_manager.cc",
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index e04ab57..5457525 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -67,6 +67,7 @@ #include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" +#include "gpu/command_buffer/service/multi_draw_manager.h" #include "gpu/command_buffer/service/path_manager.h" #include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/renderbuffer_manager.h" @@ -1890,33 +1891,8 @@ // Wrapper for glLinkProgram void DoLinkProgram(GLuint program); - // Wrapper for glMultiDrawArraysWEBGL - void DoMultiDrawArraysWEBGL(GLenum mode, - const GLint* firsts, - const GLsizei* counts, - GLsizei drawcount); - - // Wrapper for glMultiDrawArraysInstancedWEBGL - void DoMultiDrawArraysInstancedWEBGL(GLenum mode, - const GLint* firsts, - const GLsizei* counts, - const GLsizei* instance_counts, - GLsizei drawcount); - - // Wrapper for glMultiDrawElementsWEBGL - void DoMultiDrawElementsWEBGL(GLenum mode, - const GLsizei* counts, - GLenum type, - const GLsizei* offsets, - GLsizei drawcount); - - // Wrapper for glMultiDrawElementsInstancedWEBGL - void DoMultiDrawElementsInstancedWEBGL(GLenum mode, - const GLsizei* counts, - GLenum type, - const GLsizei* offsets, - const GLsizei* instance_counts, - GLsizei drawcount); + void DoMultiDrawBeginCHROMIUM(GLsizei drawcount); + void DoMultiDrawEndCHROMIUM(); // Wrapper for glOverlayPromotionHintCHROMIUIM void DoOverlayPromotionHintCHROMIUM(GLuint client_id, @@ -2623,6 +2599,8 @@ std::unique_ptr<GpuFenceManager> gpu_fence_manager_; + std::unique_ptr<MultiDrawManager> multi_draw_manager_; + std::unique_ptr<VertexArrayManager> vertex_array_manager_; base::flat_set<scoped_refptr<Buffer>> writes_submitted_but_not_completed_; @@ -3662,6 +3640,9 @@ gpu_fence_manager_.reset(new GpuFenceManager()); + multi_draw_manager_.reset( + new MultiDrawManager(MultiDrawManager::IndexStorageType::Offset)); + util_.set_num_compressed_texture_formats( validators_->compressed_texture_format.GetValues().size()); @@ -5355,6 +5336,8 @@ framebuffer_manager_.reset(); } + multi_draw_manager_.reset(); + if (query_manager_.get()) { query_manager_->Destroy(have_context); query_manager_.reset(); @@ -9410,44 +9393,6 @@ ExitCommandProcessingEarly(); } -void GLES2DecoderImpl::DoMultiDrawArraysWEBGL(GLenum mode, - const GLint* firsts, - const GLsizei* counts, - GLsizei drawcount) { - DoMultiDrawArrays("glMultiDrawArraysWEBGL", false, mode, firsts, counts, - nullptr, drawcount); -} - -void GLES2DecoderImpl::DoMultiDrawArraysInstancedWEBGL( - GLenum mode, - const GLint* firsts, - const GLsizei* counts, - const GLsizei* instance_counts, - GLsizei drawcount) { - DoMultiDrawArrays("glMultiDrawArraysInstancedWEBGL", true, mode, firsts, - counts, instance_counts, drawcount); -} - -void GLES2DecoderImpl::DoMultiDrawElementsWEBGL(GLenum mode, - const GLsizei* counts, - GLenum type, - const GLsizei* offsets, - GLsizei drawcount) { - DoMultiDrawElements("glMultiDrawElementsWEBGL", false, mode, counts, type, - offsets, nullptr, drawcount); -} - -void GLES2DecoderImpl::DoMultiDrawElementsInstancedWEBGL( - GLenum mode, - const GLsizei* counts, - GLenum type, - const GLsizei* offsets, - const GLsizei* instance_counts, - GLsizei drawcount) { - DoMultiDrawElements("glMultiDrawElementsInstancedWEBGL", true, mode, counts, - type, offsets, instance_counts, drawcount); -} - void GLES2DecoderImpl::DoOverlayPromotionHintCHROMIUM(GLuint client_id, GLboolean promotion_hint, GLint display_x, @@ -11363,11 +11308,55 @@ static_cast<GLenum>(c.type), &offset, &primcount, 1); } -error::Error GLES2DecoderImpl::HandleMultiDrawArraysWEBGL( +void GLES2DecoderImpl::DoMultiDrawBeginCHROMIUM(GLsizei drawcount) { + if (!multi_draw_manager_->Begin(drawcount)) { + MarkContextLost(error::kGuilty); + group_->LoseContexts(error::kInnocent); + } +} + +void GLES2DecoderImpl::DoMultiDrawEndCHROMIUM() { + bool success; + MultiDrawManager::ResultData result = multi_draw_manager_->End(&success); + if (!success) { + MarkContextLost(error::kGuilty); + group_->LoseContexts(error::kInnocent); + } + switch (result.draw_function) { + case MultiDrawManager::DrawFunction::DrawArrays: + DoMultiDrawArrays("glMultiDrawArraysWEBGL", false, result.mode, + result.firsts.data(), result.counts.data(), nullptr, + result.drawcount); + break; + case MultiDrawManager::DrawFunction::DrawArraysInstanced: + DoMultiDrawArrays("glMultiDrawArraysInstancedWEBGL", true, result.mode, + result.firsts.data(), result.counts.data(), + result.instance_counts.data(), result.drawcount); + break; + case MultiDrawManager::DrawFunction::DrawElements: + DoMultiDrawElements("glMultiDrawElementsWEBGL", false, result.mode, + result.counts.data(), result.type, + result.offsets.data(), nullptr, result.drawcount); + break; + case MultiDrawManager::DrawFunction::DrawElementsInstanced: + DoMultiDrawElements("glMultiDrawElementsInstancedWEBGL", true, + result.mode, result.counts.data(), result.type, + result.offsets.data(), result.instance_counts.data(), + result.drawcount); + break; + default: + NOTREACHED(); + MarkContextLost(error::kGuilty); + group_->LoseContexts(error::kInnocent); + } +} + +error::Error GLES2DecoderImpl::HandleMultiDrawArraysCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { - const volatile gles2::cmds::MultiDrawArraysWEBGL& c = - *static_cast<const volatile gles2::cmds::MultiDrawArraysWEBGL*>(cmd_data); + const volatile gles2::cmds::MultiDrawArraysCHROMIUM& c = + *static_cast<const volatile gles2::cmds::MultiDrawArraysCHROMIUM*>( + cmd_data); if (!features().webgl_multi_draw) { return error::kUnknownCommand; } @@ -11393,21 +11382,18 @@ if (counts == nullptr) { return error::kOutOfBounds; } - // Copy these arrays out of shared memory because it is possible - // for the shared memory to be modified after validation but - // before drawing. - std::vector<GLint> firsts_copy(firsts, firsts + drawcount); - std::vector<GLsizei> counts_copy(counts, counts + drawcount); - DoMultiDrawArraysWEBGL(mode, firsts_copy.data(), counts_copy.data(), - drawcount); + if (!multi_draw_manager_->MultiDrawArrays(mode, firsts, counts, drawcount)) { + return error::kInvalidArguments; + } return error::kNoError; } -error::Error GLES2DecoderImpl::HandleMultiDrawArraysInstancedWEBGL( +error::Error GLES2DecoderImpl::HandleMultiDrawArraysInstancedCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { - const volatile gles2::cmds::MultiDrawArraysInstancedWEBGL& c = - *static_cast<const volatile gles2::cmds::MultiDrawArraysInstancedWEBGL*>( + const volatile gles2::cmds::MultiDrawArraysInstancedCHROMIUM& c = + *static_cast< + const volatile gles2::cmds::MultiDrawArraysInstancedCHROMIUM*>( cmd_data); if (!features().webgl_multi_draw_instanced) { return error::kUnknownCommand; @@ -11443,23 +11429,18 @@ if (instance_counts == nullptr) { return error::kOutOfBounds; } - // Copy these arrays out of shared memory because it is possible - // for the shared memory to be modified after validation but - // before drawing. - std::vector<GLint> firsts_copy(firsts, firsts + drawcount); - std::vector<GLsizei> counts_copy(counts, counts + drawcount); - std::vector<GLsizei> instance_counts_copy(instance_counts, - instance_counts + drawcount); - DoMultiDrawArraysInstancedWEBGL(mode, firsts_copy.data(), counts_copy.data(), - instance_counts_copy.data(), drawcount); + if (!multi_draw_manager_->MultiDrawArraysInstanced( + mode, firsts, counts, instance_counts, drawcount)) { + return error::kInvalidArguments; + } return error::kNoError; } -error::Error GLES2DecoderImpl::HandleMultiDrawElementsWEBGL( +error::Error GLES2DecoderImpl::HandleMultiDrawElementsCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { - const volatile gles2::cmds::MultiDrawElementsWEBGL& c = - *static_cast<const volatile gles2::cmds::MultiDrawElementsWEBGL*>( + const volatile gles2::cmds::MultiDrawElementsCHROMIUM& c = + *static_cast<const volatile gles2::cmds::MultiDrawElementsCHROMIUM*>( cmd_data); if (!features().webgl_multi_draw) { return error::kUnknownCommand; @@ -11487,21 +11468,20 @@ if (offsets == nullptr) { return error::kOutOfBounds; } - // Copy these arrays out of shared memory because it is possible - // for the shared memory to be modified after validation but - // before drawing. - std::vector<GLsizei> counts_copy(counts, counts + drawcount); - std::vector<GLsizei> offsets_copy(offsets, offsets + drawcount); - DoMultiDrawElementsWEBGL(mode, counts_copy.data(), type, offsets_copy.data(), - drawcount); + if (!multi_draw_manager_->MultiDrawElements(mode, counts, type, offsets, + drawcount)) { + return error::kInvalidArguments; + } return error::kNoError; } -error::Error GLES2DecoderImpl::HandleMultiDrawElementsInstancedWEBGL( +error::Error GLES2DecoderImpl::HandleMultiDrawElementsInstancedCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { - const volatile gles2::cmds::MultiDrawElementsInstancedWEBGL& c = *static_cast< - const volatile gles2::cmds::MultiDrawElementsInstancedWEBGL*>(cmd_data); + const volatile gles2::cmds::MultiDrawElementsInstancedCHROMIUM& c = + *static_cast< + const volatile gles2::cmds::MultiDrawElementsInstancedCHROMIUM*>( + cmd_data); if (!features().webgl_multi_draw_instanced) { return error::kUnknownCommand; } @@ -11537,16 +11517,10 @@ if (instance_counts == nullptr) { return error::kOutOfBounds; } - // Copy these arrays out of shared memory because it is possible - // for the shared memory to be modified after validation but - // before drawing. - std::vector<GLsizei> counts_copy(counts, counts + drawcount); - std::vector<GLsizei> offsets_copy(offsets, offsets + drawcount); - std::vector<GLsizei> instance_counts_copy(instance_counts, - instance_counts + drawcount); - DoMultiDrawElementsInstancedWEBGL(mode, counts_copy.data(), type, - offsets_copy.data(), - instance_counts_copy.data(), drawcount); + if (!multi_draw_manager_->MultiDrawElementsInstanced( + mode, counts, type, offsets, instance_counts, drawcount)) { + return error::kInvalidArguments; + } return error::kNoError; }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index c9f8548..ff95e670 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -2736,6 +2736,37 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleMultiDrawBeginCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::MultiDrawBeginCHROMIUM& c = + *static_cast<const volatile gles2::cmds::MultiDrawBeginCHROMIUM*>( + cmd_data); + if (!features().webgl_multi_draw) { + return error::kUnknownCommand; + } + + GLsizei drawcount = static_cast<GLsizei>(c.drawcount); + if (drawcount < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glMultiDrawBeginCHROMIUM", + "drawcount < 0"); + return error::kNoError; + } + DoMultiDrawBeginCHROMIUM(drawcount); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleMultiDrawEndCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + if (!features().webgl_multi_draw) { + return error::kUnknownCommand; + } + + DoMultiDrawEndCHROMIUM(); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleStencilFunc( uint32_t immediate_data_size, const volatile void* cmd_data) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index e1e95fe..0a27c82 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -16,6 +16,7 @@ #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/gpu_fence_manager.h" #include "gpu/command_buffer/service/gpu_tracer.h" +#include "gpu/command_buffer/service/multi_draw_manager.h" #include "gpu/command_buffer/service/passthrough_discardable_manager.h" #include "gpu/command_buffer/service/program_cache.h" #include "gpu/command_buffer/service/shared_image_representation.h" @@ -685,6 +686,9 @@ gpu_fence_manager_.reset(new GpuFenceManager()); + multi_draw_manager_.reset( + new MultiDrawManager(MultiDrawManager::IndexStorageType::Pointer)); + auto result = group_->Initialize(this, attrib_helper.context_type, disallowed_features); if (result != gpu::ContextResult::kSuccess) { @@ -1053,6 +1057,10 @@ gpu_tracer_.reset(); } + if (multi_draw_manager_.get()) { + multi_draw_manager_.reset(); + } + if (!have_context) { for (auto& fence : deschedule_until_finished_fences_) { fence->Invalidate();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h index 6ea1632..c2d06e1 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -46,6 +46,7 @@ class ContextGroup; class GPUTracer; +class MultiDrawManager; class PassthroughAbstractTextureImpl; struct MappedBuffer { @@ -575,6 +576,8 @@ std::unique_ptr<GpuFenceManager> gpu_fence_manager_; + std::unique_ptr<MultiDrawManager> multi_draw_manager_; + // State tracking of currently bound 2D textures (client IDs) size_t active_texture_unit_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h index 1d892c8..046f791 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
@@ -430,26 +430,8 @@ error::Error DoLinkProgram(GLuint program); error::Error DoMemoryBarrierEXT(GLbitfield barriers); error::Error DoMemoryBarrierByRegion(GLbitfield barriers); -error::Error DoMultiDrawArraysWEBGL(GLenum mode, - const GLint* firsts, - const GLsizei* counts, - GLsizei drawcount); -error::Error DoMultiDrawArraysInstancedWEBGL(GLenum mode, - const GLint* firsts, - const GLsizei* counts, - const GLsizei* instanceCounts, - GLsizei drawcount); -error::Error DoMultiDrawElementsWEBGL(GLenum mode, - const GLsizei* counts, - GLenum type, - const GLvoid* const* indices, - GLsizei drawcount); -error::Error DoMultiDrawElementsInstancedWEBGL(GLenum mode, - const GLsizei* counts, - GLenum type, - const GLvoid* const* indices, - const GLsizei* instanceCounts, - GLsizei drawcount); +error::Error DoMultiDrawBeginCHROMIUM(GLsizei drawcount); +error::Error DoMultiDrawEndCHROMIUM(); error::Error DoPauseTransformFeedback(); error::Error DoPixelStorei(GLenum pname, GLint param); error::Error DoPolygonOffset(GLfloat factor, GLfloat units);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index 79191cf8..bd803bb 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -10,6 +10,7 @@ #include "gpu/command_buffer/service/decoder_client.h" #include "gpu/command_buffer/service/gpu_fence_manager.h" #include "gpu/command_buffer/service/gpu_tracer.h" +#include "gpu/command_buffer/service/multi_draw_manager.h" #include "gpu/command_buffer/service/passthrough_discardable_manager.h" #include "gpu/command_buffer/service/shared_image_factory.h" #include "gpu/command_buffer/service/shared_image_representation.h" @@ -2165,46 +2166,44 @@ return error::kNoError; } -error::Error GLES2DecoderPassthroughImpl::DoMultiDrawArraysWEBGL( - GLenum mode, - const GLint* firsts, - const GLsizei* counts, +error::Error GLES2DecoderPassthroughImpl::DoMultiDrawBeginCHROMIUM( GLsizei drawcount) { - api()->glMultiDrawArraysANGLEFn(mode, firsts, counts, drawcount); + if (!multi_draw_manager_->Begin(drawcount)) { + return error::kInvalidArguments; + } return error::kNoError; } -error::Error GLES2DecoderPassthroughImpl::DoMultiDrawArraysInstancedWEBGL( - GLenum mode, - const GLint* firsts, - const GLsizei* counts, - const GLsizei* instanceCounts, - GLsizei drawcount) { - api()->glMultiDrawArraysInstancedANGLEFn(mode, firsts, counts, instanceCounts, - drawcount); - return error::kNoError; -} - -error::Error GLES2DecoderPassthroughImpl::DoMultiDrawElementsWEBGL( - GLenum mode, - const GLsizei* counts, - GLenum type, - const GLvoid* const* indices, - GLsizei drawcount) { - api()->glMultiDrawElementsANGLEFn(mode, counts, type, indices, drawcount); - return error::kNoError; -} - -error::Error GLES2DecoderPassthroughImpl::DoMultiDrawElementsInstancedWEBGL( - GLenum mode, - const GLsizei* counts, - GLenum type, - const GLvoid* const* indices, - const GLsizei* instanceCounts, - GLsizei drawcount) { - api()->glMultiDrawElementsInstancedANGLEFn(mode, counts, type, indices, - instanceCounts, drawcount); - return error::kNoError; +error::Error GLES2DecoderPassthroughImpl::DoMultiDrawEndCHROMIUM() { + bool success; + MultiDrawManager::ResultData result = multi_draw_manager_->End(&success); + if (!success) { + return error::kInvalidArguments; + } + switch (result.draw_function) { + case MultiDrawManager::DrawFunction::DrawArrays: + api()->glMultiDrawArraysANGLEFn(result.mode, result.firsts.data(), + result.counts.data(), result.drawcount); + return error::kNoError; + case MultiDrawManager::DrawFunction::DrawArraysInstanced: + api()->glMultiDrawArraysInstancedANGLEFn( + result.mode, result.firsts.data(), result.counts.data(), + result.instance_counts.data(), result.drawcount); + return error::kNoError; + case MultiDrawManager::DrawFunction::DrawElements: + api()->glMultiDrawElementsANGLEFn(result.mode, result.counts.data(), + result.type, result.indices.data(), + result.drawcount); + return error::kNoError; + case MultiDrawManager::DrawFunction::DrawElementsInstanced: + api()->glMultiDrawElementsInstancedANGLEFn( + result.mode, result.counts.data(), result.type, result.indices.data(), + result.instance_counts.data(), result.drawcount); + return error::kNoError; + default: + NOTREACHED(); + return error::kLostContext; + } } error::Error GLES2DecoderPassthroughImpl::DoPauseTransformFeedback() {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc index eb3165d7..3925efb 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
@@ -5,6 +5,7 @@ #include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h" #include "gpu/command_buffer/common/discardable_handle.h" +#include "gpu/command_buffer/service/multi_draw_manager.h" #include "ui/gfx/ipc/color/gfx_param_traits.h" namespace gpu { @@ -1615,11 +1616,12 @@ return DoDrawElementsInstancedANGLE(mode, count, type, indices, primcount); } -error::Error GLES2DecoderPassthroughImpl::HandleMultiDrawArraysWEBGL( +error::Error GLES2DecoderPassthroughImpl::HandleMultiDrawArraysCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { - const volatile gles2::cmds::MultiDrawArraysWEBGL& c = - *static_cast<const volatile gles2::cmds::MultiDrawArraysWEBGL*>(cmd_data); + const volatile gles2::cmds::MultiDrawArraysCHROMIUM& c = + *static_cast<const volatile gles2::cmds::MultiDrawArraysCHROMIUM*>( + cmd_data); if (!features().webgl_multi_draw) { return error::kUnknownCommand; } @@ -1645,20 +1647,19 @@ if (counts == nullptr) { return error::kOutOfBounds; } - // Copy these arrays out of shared memory because it is possible - // for the shared memory to be modified after validation but - // before drawing. - std::vector<GLint> firsts_copy(firsts, firsts + drawcount); - std::vector<GLsizei> counts_copy(counts, counts + drawcount); - return DoMultiDrawArraysWEBGL(mode, firsts_copy.data(), counts_copy.data(), - drawcount); + if (!multi_draw_manager_->MultiDrawArrays(mode, firsts, counts, drawcount)) { + return error::kInvalidArguments; + } + return error::kNoError; } -error::Error GLES2DecoderPassthroughImpl::HandleMultiDrawArraysInstancedWEBGL( +error::Error +GLES2DecoderPassthroughImpl::HandleMultiDrawArraysInstancedCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { - const volatile gles2::cmds::MultiDrawArraysInstancedWEBGL& c = - *static_cast<const volatile gles2::cmds::MultiDrawArraysInstancedWEBGL*>( + const volatile gles2::cmds::MultiDrawArraysInstancedCHROMIUM& c = + *static_cast< + const volatile gles2::cmds::MultiDrawArraysInstancedCHROMIUM*>( cmd_data); if (!features().webgl_multi_draw_instanced) { return error::kUnknownCommand; @@ -1694,23 +1695,18 @@ if (instance_counts == nullptr) { return error::kOutOfBounds; } - // Copy these arrays out of shared memory because it is possible - // for the shared memory to be modified after validation but - // before drawing. - std::vector<GLint> firsts_copy(firsts, firsts + drawcount); - std::vector<GLsizei> counts_copy(counts, counts + drawcount); - std::vector<GLsizei> instance_counts_copy(instance_counts, - instance_counts + drawcount); - return DoMultiDrawArraysInstancedWEBGL( - mode, firsts_copy.data(), counts_copy.data(), instance_counts_copy.data(), - drawcount); + if (!multi_draw_manager_->MultiDrawArraysInstanced( + mode, firsts, counts, instance_counts, drawcount)) { + return error::kInvalidArguments; + } + return error::kNoError; } -error::Error GLES2DecoderPassthroughImpl::HandleMultiDrawElementsWEBGL( +error::Error GLES2DecoderPassthroughImpl::HandleMultiDrawElementsCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { - const volatile gles2::cmds::MultiDrawElementsWEBGL& c = - *static_cast<const volatile gles2::cmds::MultiDrawElementsWEBGL*>( + const volatile gles2::cmds::MultiDrawElementsCHROMIUM& c = + *static_cast<const volatile gles2::cmds::MultiDrawElementsCHROMIUM*>( cmd_data); if (!features().webgl_multi_draw) { return error::kUnknownCommand; @@ -1738,26 +1734,21 @@ if (offsets == nullptr) { return error::kOutOfBounds; } - // The do-er for this function calls the ANGLE implementation which - // requires an array of pointers, not 32-bit integers - std::vector<const GLvoid*> indices(drawcount); - for (GLsizei draw_id = 0; draw_id < drawcount; ++draw_id) { - indices[draw_id] = - reinterpret_cast<GLvoid*>(static_cast<GLintptr>(offsets[draw_id])); + if (!multi_draw_manager_->MultiDrawElements(mode, counts, type, offsets, + drawcount)) { + return error::kInvalidArguments; } - // Copy these arrays out of shared memory because it is possible - // for the shared memory to be modified after validation but - // before drawing. - std::vector<GLsizei> counts_copy(counts, counts + drawcount); - return DoMultiDrawElementsWEBGL(mode, counts_copy.data(), type, - indices.data(), drawcount); + return error::kNoError; } -error::Error GLES2DecoderPassthroughImpl::HandleMultiDrawElementsInstancedWEBGL( +error::Error +GLES2DecoderPassthroughImpl::HandleMultiDrawElementsInstancedCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { - const volatile gles2::cmds::MultiDrawElementsInstancedWEBGL& c = *static_cast< - const volatile gles2::cmds::MultiDrawElementsInstancedWEBGL*>(cmd_data); + const volatile gles2::cmds::MultiDrawElementsInstancedCHROMIUM& c = + *static_cast< + const volatile gles2::cmds::MultiDrawElementsInstancedCHROMIUM*>( + cmd_data); if (!features().webgl_multi_draw_instanced) { return error::kUnknownCommand; } @@ -1793,22 +1784,11 @@ if (instance_counts == nullptr) { return error::kOutOfBounds; } - // The do-er for this function calls the ANGLE implementation which - // requires an array of pointers, not 32-bit integers - std::vector<const GLvoid*> indices(drawcount); - for (GLsizei draw_id = 0; draw_id < drawcount; ++draw_id) { - indices[draw_id] = - reinterpret_cast<GLvoid*>(static_cast<GLintptr>(offsets[draw_id])); + if (!multi_draw_manager_->MultiDrawElementsInstanced( + mode, counts, type, offsets, instance_counts, drawcount)) { + return error::kInvalidArguments; } - // Copy these arrays out of shared memory because it is possible - // for the shared memory to be modified after validation but - // before drawing. - std::vector<GLsizei> counts_copy(counts, counts + drawcount); - std::vector<GLsizei> instance_counts_copy(instance_counts, - instance_counts + drawcount); - return DoMultiDrawElementsInstancedWEBGL( - mode, counts_copy.data(), type, indices.data(), - instance_counts_copy.data(), drawcount); + return error::kNoError; } error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribDivisorANGLE(
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc index d147a5c..022e81f 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
@@ -2299,6 +2299,38 @@ return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::HandleMultiDrawBeginCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::MultiDrawBeginCHROMIUM& c = + *static_cast<const volatile gles2::cmds::MultiDrawBeginCHROMIUM*>( + cmd_data); + if (!features().webgl_multi_draw) { + return error::kUnknownCommand; + } + + GLsizei drawcount = static_cast<GLsizei>(c.drawcount); + error::Error error = DoMultiDrawBeginCHROMIUM(drawcount); + if (error != error::kNoError) { + return error; + } + return error::kNoError; +} + +error::Error GLES2DecoderPassthroughImpl::HandleMultiDrawEndCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + if (!features().webgl_multi_draw) { + return error::kUnknownCommand; + } + + error::Error error = DoMultiDrawEndCHROMIUM(); + if (error != error::kNoError) { + return error; + } + return error::kNoError; +} + error::Error GLES2DecoderPassthroughImpl::HandleStencilFunc( uint32_t immediate_data_size, const volatile void* cmd_data) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc index 61fa6fa..e1e262e 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
@@ -824,12 +824,6 @@ }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform4ivImmediate, 0>( - bool /* valid */) { - SetupShaderForUniform(GL_INT_VEC4); -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::UniformMatrix2fvImmediate, 0>( bool /* valid */) { SetupShaderForUniform(GL_FLOAT_MAT2);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h index 9816bd4..cbc26cc 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
@@ -1328,16 +1328,4 @@ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } - -TEST_P(GLES2DecoderTest2, Uniform4ivImmediateValidArgs) { - cmds::Uniform4ivImmediate& cmd = *GetImmediateAs<cmds::Uniform4ivImmediate>(); - SpecializedSetup<cmds::Uniform4ivImmediate, 0>(true); - GLint temp[4 * 2] = { - 0, - }; - EXPECT_CALL(*gl_, Uniform4iv(1, 2, PointsToArray(temp, 4))); - cmd.Init(1, 2, &temp[0]); - EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3.cc index b44e0074..6bace90 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3.cc
@@ -53,6 +53,12 @@ INSTANTIATE_TEST_CASE_P(Service, GLES3DecoderTest3, ::testing::Bool()); template <> +void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform4ivImmediate, 0>( + bool /* valid */) { + SetupShaderForUniform(GL_INT_VEC4); +}; + +template <> void GLES2DecoderTestBase::SpecializedSetup<UniformMatrix3fvImmediate, 0>( bool /* valid */) { SetupShaderForUniform(GL_FLOAT_MAT3);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h index f03276c3..5f729cd7 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
@@ -12,6 +12,18 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ +TEST_P(GLES2DecoderTest3, Uniform4ivImmediateValidArgs) { + cmds::Uniform4ivImmediate& cmd = *GetImmediateAs<cmds::Uniform4ivImmediate>(); + SpecializedSetup<cmds::Uniform4ivImmediate, 0>(true); + GLint temp[4 * 2] = { + 0, + }; + EXPECT_CALL(*gl_, Uniform4iv(1, 2, PointsToArray(temp, 4))); + cmd.Init(1, 2, &temp[0]); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_P(GLES3DecoderTest3, UniformMatrix2x3fvImmediateValidArgs) { cmds::UniformMatrix2x3fvImmediate& cmd = *GetImmediateAs<cmds::UniformMatrix2x3fvImmediate>();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index 47979044..0ba7ee7 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -531,9 +531,7 @@ void DoLockDiscardableTextureCHROMIUM(GLuint texture_id); bool IsDiscardableTextureUnlocked(GLuint texture_id); - GLvoid* BufferOffset(unsigned i) { - return static_cast<int8_t*>(nullptr) + (i); - } + GLvoid* BufferOffset(unsigned i) { return reinterpret_cast<GLvoid*>(i); } template <typename Command, typename Result> bool IsObjectHelper(GLuint client_id) {
diff --git a/gpu/command_buffer/service/gr_shader_cache.cc b/gpu/command_buffer/service/gr_shader_cache.cc index 1a9bdc5..6fd8f0e 100644 --- a/gpu/command_buffer/service/gr_shader_cache.cc +++ b/gpu/command_buffer/service/gr_shader_cache.cc
@@ -149,6 +149,9 @@ GrShaderCache::ScopedCacheUse::ScopedCacheUse(GrShaderCache* cache, int32_t client_id) : cache_(cache) { + DCHECK_EQ(cache_->current_client_id_, kInvalidClientId); + DCHECK_NE(client_id, kInvalidClientId); + cache_->current_client_id_ = client_id; }
diff --git a/gpu/command_buffer/service/multi_draw_manager.cc b/gpu/command_buffer/service/multi_draw_manager.cc new file mode 100644 index 0000000..d7d2cba --- /dev/null +++ b/gpu/command_buffer/service/multi_draw_manager.cc
@@ -0,0 +1,224 @@ +// 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 "gpu/command_buffer/service/multi_draw_manager.h" + +#include <algorithm> + +#include "base/logging.h" +#include "base/numerics/checked_math.h" + +namespace gpu { +namespace gles2 { + +MultiDrawManager::ResultData::ResultData() + : draw_function(DrawFunction::None) {} + +MultiDrawManager::ResultData::ResultData(ResultData&& rhs) + : draw_function(rhs.draw_function), + drawcount(rhs.drawcount), + mode(rhs.mode), + type(rhs.type), + firsts(std::move(rhs.firsts)), + counts(std::move(rhs.counts)), + offsets(std::move(rhs.offsets)), + indices(std::move(rhs.indices)), + instance_counts(std::move(rhs.instance_counts)) { + rhs.draw_function = DrawFunction::None; +} + +MultiDrawManager::ResultData& MultiDrawManager::ResultData::operator=( + ResultData&& rhs) { + if (&rhs == this) { + return *this; + } + draw_function = rhs.draw_function; + drawcount = rhs.drawcount; + mode = rhs.mode; + type = rhs.type; + std::swap(firsts, rhs.firsts); + std::swap(counts, rhs.counts); + std::swap(offsets, rhs.offsets); + std::swap(indices, rhs.indices); + std::swap(instance_counts, rhs.instance_counts); + + rhs.draw_function = DrawFunction::None; + return *this; +} + +MultiDrawManager::ResultData::~ResultData() {} + +MultiDrawManager::MultiDrawManager(IndexStorageType index_type) + : current_draw_offset_(0), index_type_(index_type), result_() {} + +bool MultiDrawManager::Begin(GLsizei drawcount) { + result_.drawcount = drawcount; + current_draw_offset_ = 0; + if (result_.draw_function != DrawFunction::None) { + NOTREACHED(); + return false; + } + return true; +} + +MultiDrawManager::ResultData MultiDrawManager::End(bool* success) { + *success = current_draw_offset_ == result_.drawcount; + DCHECK(*success); + return std::move(result_); +} + +bool MultiDrawManager::MultiDrawArrays(GLenum mode, + const GLint* firsts, + const GLsizei* counts, + GLsizei drawcount) { + if (!EnsureDrawArraysFunction(DrawFunction::DrawArrays, mode) || + base::CheckAdd(current_draw_offset_, drawcount).ValueOrDie() > + result_.drawcount) { + NOTREACHED(); + return false; + } + std::copy(firsts, firsts + drawcount, &result_.firsts[current_draw_offset_]); + std::copy(counts, counts + drawcount, &result_.counts[current_draw_offset_]); + current_draw_offset_ += drawcount; + return true; +} + +bool MultiDrawManager::MultiDrawArraysInstanced(GLenum mode, + const GLint* firsts, + const GLsizei* counts, + const GLsizei* instance_counts, + GLsizei drawcount) { + if (!EnsureDrawArraysFunction(DrawFunction::DrawArraysInstanced, mode) || + base::CheckAdd(current_draw_offset_, drawcount).ValueOrDie() > + result_.drawcount) { + NOTREACHED(); + return false; + } + std::copy(firsts, firsts + drawcount, &result_.firsts[current_draw_offset_]); + std::copy(counts, counts + drawcount, &result_.counts[current_draw_offset_]); + std::copy(instance_counts, instance_counts + drawcount, + &result_.instance_counts[current_draw_offset_]); + current_draw_offset_ += drawcount; + return true; +} + +bool MultiDrawManager::MultiDrawElements(GLenum mode, + const GLsizei* counts, + GLenum type, + const GLsizei* offsets, + GLsizei drawcount) { + if (!EnsureDrawElementsFunction(DrawFunction::DrawElements, mode, type) || + base::CheckAdd(current_draw_offset_, drawcount).ValueOrDie() > + result_.drawcount) { + NOTREACHED(); + return false; + } + std::copy(counts, counts + drawcount, &result_.counts[current_draw_offset_]); + switch (index_type_) { + case IndexStorageType::Offset: + std::copy(offsets, offsets + drawcount, + &result_.offsets[current_draw_offset_]); + break; + case IndexStorageType::Pointer: + std::transform( + offsets, offsets + drawcount, &result_.indices[current_draw_offset_], + [](uint32_t offset) { + return reinterpret_cast<void*>(static_cast<intptr_t>(offset)); + }); + break; + } + current_draw_offset_ += drawcount; + return true; +} + +bool MultiDrawManager::MultiDrawElementsInstanced( + GLenum mode, + const GLsizei* counts, + GLenum type, + const GLsizei* offsets, + const GLsizei* instance_counts, + GLsizei drawcount) { + if (!EnsureDrawElementsFunction(DrawFunction::DrawElementsInstanced, mode, + type) || + base::CheckAdd(current_draw_offset_, drawcount).ValueOrDie() > + result_.drawcount) { + NOTREACHED(); + return false; + } + std::copy(counts, counts + drawcount, &result_.counts[current_draw_offset_]); + std::copy(instance_counts, instance_counts + drawcount, + &result_.instance_counts[current_draw_offset_]); + switch (index_type_) { + case IndexStorageType::Offset: + std::copy(offsets, offsets + drawcount, + &result_.offsets[current_draw_offset_]); + break; + case IndexStorageType::Pointer: + std::transform( + offsets, offsets + drawcount, &result_.indices[current_draw_offset_], + [](uint32_t offset) { + return reinterpret_cast<void*>(static_cast<intptr_t>(offset)); + }); + break; + } + current_draw_offset_ += drawcount; + return true; +} + +void MultiDrawManager::ResizeArrays() { + switch (result_.draw_function) { + case DrawFunction::DrawArraysInstanced: + result_.instance_counts.resize(result_.drawcount); + FALLTHROUGH; + case DrawFunction::DrawArrays: + result_.firsts.resize(result_.drawcount); + result_.counts.resize(result_.drawcount); + break; + case DrawFunction::DrawElementsInstanced: + result_.instance_counts.resize(result_.drawcount); + FALLTHROUGH; + case DrawFunction::DrawElements: + result_.counts.resize(result_.drawcount); + switch (index_type_) { + case IndexStorageType::Offset: + result_.offsets.resize(result_.drawcount); + break; + case IndexStorageType::Pointer: + result_.indices.resize(result_.drawcount); + break; + } + break; + default: + NOTREACHED(); + } +} + +bool MultiDrawManager::EnsureDrawArraysFunction(DrawFunction draw_function, + GLenum mode) { + bool first_call = result_.draw_function == DrawFunction::None; + bool enums_match = result_.mode == mode; + if (first_call) { + result_.draw_function = draw_function; + result_.mode = mode; + ResizeArrays(); + } + return first_call || enums_match; +} + +bool MultiDrawManager::EnsureDrawElementsFunction(DrawFunction draw_function, + GLenum mode, + GLenum type) { + bool first_call = result_.draw_function == DrawFunction::None; + bool enums_match = result_.mode == mode && result_.type == type; + if (first_call) { + result_.draw_function = draw_function; + result_.mode = mode; + result_.type = type; + ResizeArrays(); + } + return first_call || enums_match; +} + +} // namespace gles2 +} // namespace gpu
diff --git a/gpu/command_buffer/service/multi_draw_manager.h b/gpu/command_buffer/service/multi_draw_manager.h new file mode 100644 index 0000000..4a4dd56 --- /dev/null +++ b/gpu/command_buffer/service/multi_draw_manager.h
@@ -0,0 +1,92 @@ +// 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 GPU_COMMAND_BUFFER_SERVICE_MULTI_DRAW_MANAGER_H_ +#define GPU_COMMAND_BUFFER_SERVICE_MULTI_DRAW_MANAGER_H_ + +#include <vector> + +#include "gpu/gpu_gles2_export.h" + +// Forwardly declare a few GL types to avoid including GL header files. +typedef unsigned GLenum; +typedef int GLsizei; +typedef int GLint; + +namespace gpu { +namespace gles2 { + +class GPU_GLES2_EXPORT MultiDrawManager { + public: + enum class DrawFunction { + None, + DrawArrays, + DrawArraysInstanced, + DrawElements, + DrawElementsInstanced, + }; + + struct ResultData { + DrawFunction draw_function; + GLsizei drawcount; + GLenum mode; + GLenum type; + std::vector<GLint> firsts; + std::vector<GLsizei> counts; + std::vector<GLsizei> offsets; + std::vector<const void*> indices; + std::vector<GLsizei> instance_counts; + + ResultData(); + ResultData(ResultData&& rhs); + ResultData& operator=(ResultData&& rhs); + ~ResultData(); + }; + + enum class IndexStorageType { + Offset, + Pointer, + }; + + MultiDrawManager(IndexStorageType index_type); + + bool Begin(GLsizei drawcount); + ResultData End(bool* success); + bool MultiDrawArrays(GLenum mode, + const GLint* firsts, + const GLsizei* counts, + GLsizei drawcount); + bool MultiDrawArraysInstanced(GLenum mode, + const GLint* firsts, + const GLsizei* counts, + const GLsizei* instance_counts, + GLsizei drawcount); + bool MultiDrawElements(GLenum mode, + const GLsizei* counts, + GLenum type, + const GLsizei* offsets, + GLsizei drawcount); + bool MultiDrawElementsInstanced(GLenum mode, + const GLsizei* counts, + GLenum type, + const GLsizei* offsets, + const GLsizei* instance_counts, + GLsizei drawcount); + + private: + void ResizeArrays(); + bool EnsureDrawArraysFunction(DrawFunction draw_function, GLenum mode); + bool EnsureDrawElementsFunction(DrawFunction draw_function, + GLenum mode, + GLenum type); + + GLsizei current_draw_offset_; + IndexStorageType index_type_; + ResultData result_; +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_MULTI_DRAW_MANAGER_H_
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_base.h b/gpu/command_buffer/service/raster_decoder_unittest_base.h index ad43b76..bbcbfad1 100644 --- a/gpu/command_buffer/service/raster_decoder_unittest_base.h +++ b/gpu/command_buffer/service/raster_decoder_unittest_base.h
@@ -212,9 +212,7 @@ GLsizei height, GLuint bound_pixel_unpack_buffer); - GLvoid* BufferOffset(unsigned i) { - return static_cast<int8_t*>(nullptr) + (i); - } + GLvoid* BufferOffset(unsigned i) { return reinterpret_cast<GLvoid*>(i); } protected: static const GLint kMaxTextureSize = 2048;
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index 66f4e4f..bbe571b 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -22,7 +22,6 @@ #include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/command_buffer/client/gles2_lib.h" -#include "gpu/command_buffer/client/shared_memory_limits.h" #include "gpu/command_buffer/client/transfer_buffer.h" #include "gpu/command_buffer/common/constants.h" #include "gpu/command_buffer/common/context_creation_attribs.h" @@ -284,7 +283,7 @@ void GLManager::InitializeWithWorkaroundsImpl( const GLManager::Options& options, const GpuDriverBugWorkarounds& workarounds) { - const SharedMemoryLimits limits; + const SharedMemoryLimits limits = options.shared_memory_limits; const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); DCHECK(!command_line.HasSwitch(switches::kDisableGLExtensions));
diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h index a0d61b8..de0df9e 100644 --- a/gpu/command_buffer/tests/gl_manager.h +++ b/gpu/command_buffer/tests/gl_manager.h
@@ -12,6 +12,7 @@ #include "base/memory/ref_counted.h" #include "gpu/command_buffer/client/gpu_control.h" +#include "gpu/command_buffer/client/shared_memory_limits.h" #include "gpu/command_buffer/common/context_creation_attribs.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gpu_tracer.h" @@ -77,6 +78,8 @@ gpu::ImageFactory* image_factory = nullptr; // Whether to preserve the backbuffer after a call to SwapBuffers(). bool preserve_backbuffer = false; + // Shared memory limits + SharedMemoryLimits shared_memory_limits = {}; }; GLManager(); ~GLManager() override;
diff --git a/gpu/command_buffer/tests/gl_webgl_multi_draw_test.cc b/gpu/command_buffer/tests/gl_webgl_multi_draw_test.cc new file mode 100644 index 0000000..f80201f --- /dev/null +++ b/gpu/command_buffer/tests/gl_webgl_multi_draw_test.cc
@@ -0,0 +1,180 @@ +// 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 <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#include <GLES2/gl2extchromium.h> +#include <math.h> +#include <stdint.h> +#include <vector> + +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/shared_memory_limits.h" +#include "gpu/command_buffer/tests/gl_manager.h" +#include "gpu/command_buffer/tests/gl_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace gpu { + +class GLWebGLMultiDrawTest : public ::testing::Test { + protected: + GLWebGLMultiDrawTest() : max_transfer_buffer_size_(16 * 1024) { + size_t vertex_bytes_per_pixel = sizeof(GLint) + sizeof(GLsizei); + uint32_t pixel_count = max_transfer_buffer_size_ / vertex_bytes_per_pixel; + canvas_size_ = 2 * static_cast<uint32_t>(std::sqrt(pixel_count)); + } + + void SetUp() override { + GLManager::Options options; + options.shared_memory_limits.min_transfer_buffer_size = + max_transfer_buffer_size_ / 2; + options.shared_memory_limits.max_transfer_buffer_size = + max_transfer_buffer_size_; + options.shared_memory_limits.start_transfer_buffer_size = + max_transfer_buffer_size_ / 2; + options.context_type = CONTEXT_TYPE_WEBGL1; + options.size = gfx::Size(canvas_size_, canvas_size_); + gl_.Initialize(options); + } + + void TearDown() override { gl_.Destroy(); } + + uint32_t canvas_size() const { return canvas_size_; } + + uint32_t max_transfer_buffer_size() const { + return max_transfer_buffer_size_; + } + + gles2::GLES2Implementation* gles2_implementation() const { + return gl_.gles2_implementation(); + } + + private: + GLManager gl_; + uint32_t canvas_size_; + uint32_t max_transfer_buffer_size_; +}; + +// This test issues a MultiDrawArrays that requires more command space than +// the maximum size of the transfer buffer. To check that every draw is issued, +// each gl_DrawID is transformed to a unique pixel and colored a unique value. +// The pixels are read back and checked that every pixel is correct. +TEST_F(GLWebGLMultiDrawTest, MultiDrawLargerThanTransferBuffer) { + std::string requestable_extensions_string = + reinterpret_cast<const char*>(glGetRequestableExtensionsCHROMIUM()); + + // This test is only valid if the multi draw extension is supported + if (!GLTestHelper::HasExtension("GL_ANGLE_multi_draw")) { + if (requestable_extensions_string.find("GL_ANGLE_multi_draw ") == + std::string::npos) { + return; + } + glRequestExtensionCHROMIUM("GL_ANGLE_multi_draw"); + } + + if (!GLTestHelper::HasExtension("GL_WEBGL_multi_draw")) { + if (requestable_extensions_string.find("GL_WEBGL_multi_draw ") == + std::string::npos) { + return; + } + glRequestExtensionCHROMIUM("GL_WEBGL_multi_draw"); + } + + std::string vertex_source = + "#define SIZE " + std::to_string(canvas_size()) + "\n"; + vertex_source += "#extension GL_ANGLE_multi_draw : require\n"; + vertex_source += R"( + attribute vec2 a_position; + varying vec4 v_color; + + int mod(int x, int y) { + int q = x / y; + return x - q * y; + } + + int rshift8(int x) { + int result = x; + for (int i = 0; i < 8; ++i) { + result = result / 2; + } + return result; + } + + int rshift16(int x) { + int result = x; + for (int i = 0; i < 16; ++i) { + result = result / 2; + } + return result; + } + + int rshift24(int x) { + int result = x; + for (int i = 0; i < 24; ++i) { + result = result / 2; + } + return result; + } + + void main() { + int x_int = mod(gl_DrawID, SIZE); + int y_int = gl_DrawID / SIZE; + + float s = 1.0 / float(SIZE); + float x = float(x_int) / float(SIZE); + float y = float(y_int) / float(SIZE); + float z = 0.0; + mat4 m = mat4(s, 0, 0, 0, 0, s, 0, 0, 0, 0, s, 0, x, y, z, 1); + vec2 position01 = a_position * 0.5 + 0.5; + gl_Position = (m * vec4(position01, 0.0, 1.0)) * 2.0 - 1.0; + int r = mod(rshift24(gl_DrawID), 256); + int g = mod(rshift16(gl_DrawID), 256); + int b = mod(rshift8(gl_DrawID), 256); + int a = mod(gl_DrawID, 256); + float denom = 1.0 / 255.0; + v_color = vec4(r, g, b, a) * denom; + })"; + + GLuint program = GLTestHelper::LoadProgram(vertex_source.c_str(), R"( + precision mediump float; + varying vec4 v_color; + void main() { gl_FragColor = v_color; } + )"); + ASSERT_NE(program, 0u); + GLint position_loc = glGetAttribLocation(program, "a_position"); + ASSERT_NE(position_loc, -1); + glUseProgram(program); + + GLuint vbo = GLTestHelper::SetupUnitQuad(position_loc); + ASSERT_NE(vbo, 0u); + + std::vector<GLint> firsts(canvas_size() * canvas_size(), 0); + std::vector<GLsizei> counts(canvas_size() * canvas_size(), 6); + + ASSERT_GT(firsts.size() * sizeof(GLint) + counts.size() * sizeof(GLsizei), + max_transfer_buffer_size()); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gles2_implementation()->MultiDrawArraysWEBGL(GL_TRIANGLES, firsts.data(), + counts.data(), + canvas_size() * canvas_size()); + glFlush(); + + std::vector<std::array<uint8_t, 4>> pixels(canvas_size() * canvas_size()); + glReadPixels(0, 0, canvas_size(), canvas_size(), GL_RGBA, GL_UNSIGNED_BYTE, + pixels.data()); + unsigned int expected = 0; + for (const auto& pixel : pixels) { + unsigned int id = + ((pixel[0] << 24) + (pixel[1] << 16) + (pixel[2] << 8) + pixel[3]); + EXPECT_EQ(id, expected); + expected++; + } + + GLTestHelper::CheckGLError( + "GLWebGLMultiDrawTest.MultiDrawLargerThanTransferBuffer", __LINE__); +} + +} // namespace gpu
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc index 105509da..c0d4db7 100644 --- a/headless/lib/browser/headless_web_contents_impl.cc +++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -153,6 +153,7 @@ } content::NavigationController::LoadURLParams load_url_params(params.url); + load_url_params.initiator_origin = params.initiator_origin; load_url_params.source_site_instance = params.source_site_instance; load_url_params.transition_type = params.transition; load_url_params.frame_tree_node_id = params.frame_tree_node_id;
diff --git a/ios/BUILD.gn b/ios/BUILD.gn index f09a7eb2..da00ac7 100644 --- a/ios/BUILD.gn +++ b/ios/BUILD.gn
@@ -52,6 +52,7 @@ # List all the test targets that need to be built on iOS by default. "//ios/chrome/test:all_tests", "//ios/chrome/test/earl_grey:all_tests", + "//ios/chrome/test/earl_grey2:all_tests", "//ios/components:all_tests", "//ios/net:all_tests", "//ios/showcase:all_tests",
diff --git a/ios/chrome/browser/tabs/tab_model.mm b/ios/chrome/browser/tabs/tab_model.mm index b2e7e5e6..d11d934 100644 --- a/ios/chrome/browser/tabs/tab_model.mm +++ b/ios/chrome/browser/tabs/tab_model.mm
@@ -562,7 +562,6 @@ - (void)closeAllTabs { _webStateList->CloseAllWebStates(WebStateList::CLOSE_USER_ACTION); - [_observers tabModelClosedAllTabs:self]; } - (void)haltAllTabs {
diff --git a/ios/chrome/browser/tabs/tab_model_observer.h b/ios/chrome/browser/tabs/tab_model_observer.h index 243f0be2..4e82e82 100644 --- a/ios/chrome/browser/tabs/tab_model_observer.h +++ b/ios/chrome/browser/tabs/tab_model_observer.h
@@ -24,9 +24,6 @@ // The given tab will be removed. - (void)tabModel:(TabModel*)model willRemoveTab:(Tab*)tab; -// All tabs in the model will close. -- (void)tabModelClosedAllTabs:(TabModel*)model; - // A tab was removed at the given index. - (void)tabModel:(TabModel*)model didRemoveTab:(Tab*)tab
diff --git a/ios/chrome/browser/web/page_placeholder_tab_helper.mm b/ios/chrome/browser/web/page_placeholder_tab_helper.mm index ab3b976..1543879 100644 --- a/ios/chrome/browser/web/page_placeholder_tab_helper.mm +++ b/ios/chrome/browser/web/page_placeholder_tab_helper.mm
@@ -73,6 +73,7 @@ // Lazily create the placeholder view. if (!placeholder_view_) { placeholder_view_ = [[UIImageView alloc] init]; + placeholder_view_.backgroundColor = [UIColor whiteColor]; placeholder_view_.contentMode = UIViewContentModeScaleAspectFit; placeholder_view_.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
diff --git a/ios/chrome/test/earl_grey2/BUILD.gn b/ios/chrome/test/earl_grey2/BUILD.gn new file mode 100644 index 0000000..11827da0 --- /dev/null +++ b/ios/chrome/test/earl_grey2/BUILD.gn
@@ -0,0 +1,78 @@ +# 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. + +import("//build/config/ios/ios_sdk.gni") +import("//build/config/ios/rules.gni") +import("//ios/chrome/test/earl_grey2/chrome_ios_eg2_test.gni") + +group("all_tests") { + testonly = true + deps = [ + ":ios_chrome_eg2_test_app_host", + ":ios_chrome_smoke_eg2tests", + ] +} + +chrome_ios_eg2_test_app_host("ios_chrome_eg2_test_app_host") { + deps = [ + ":earl_grey2_host_distant_object_sources", + ] +} + +chrome_ios_eg2_test("ios_chrome_smoke_eg2tests") { + xcode_test_application_name = "ios_chrome_eg2_test_app_host" + + deps = [ + "//ios/chrome/test/earl_grey2:eg2_tests", + ] +} + +source_set("earl_grey2_host_distant_object_headers") { + testonly = true + sources = [ + "//ios/chrome/test/earl_grey2/chrome_earl_grey_edo.h", + ] +} + +source_set("earl_grey2_host_distant_object_sources") { + configs += [ "//build/config/compiler:enable_arc" ] + testonly = true + sources = [ + "//ios/chrome/test/earl_grey2/chrome_earl_grey_edo.mm", + ] + + include_dirs = [ + "//ios/third_party/earl_grey2/src", + "//ios/third_party/edo/src", + ] + + deps = [ + ":earl_grey2_host_distant_object_headers", + "//base", + "//base/test:test_support", + "//ios/chrome/test/app:test_support", + "//ios/third_party/earl_grey2:app_framework+link", + ] +} + +source_set("eg2_tests") { + configs += [ + "//build/config/compiler:enable_arc", + "//build/config/ios:xctest_config", + ] + testonly = true + + sources = [ + "smoke_egtest.mm", + ] + + include_dirs = [ "//ios/third_party/edo/src" ] + + deps = [ + "//ios/chrome/test/earl_grey2:earl_grey2_host_distant_object_headers", + "//ios/third_party/earl_grey2:test_lib", + ] + + libs = [ "UIKit.framework" ] +}
diff --git a/ios/chrome/test/earl_grey2/chrome_earl_grey_edo.h b/ios/chrome/test/earl_grey2/chrome_earl_grey_edo.h new file mode 100644 index 0000000..8c637aca --- /dev/null +++ b/ios/chrome/test/earl_grey2/chrome_earl_grey_edo.h
@@ -0,0 +1,17 @@ +// 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 IOS_CHROME_TEST_EARL_GREY2_CHROME_EARL_GREY_EDO_H_ +#define IOS_CHROME_TEST_EARL_GREY2_CHROME_EARL_GREY_EDO_H_ + +#import <CommonLib/DistantObject/GREYHostApplicationDistantObject.h> + +@interface GREYHostApplicationDistantObject (RemoteTest) + +// Returns the number of main tabs. +- (NSUInteger)GetMainTabCount; + +@end + +#endif // IOS_CHROME_TEST_EARL_GREY2_CHROME_EARL_GREY_EDO_H_
diff --git a/ios/chrome/test/earl_grey2/chrome_earl_grey_edo.mm b/ios/chrome/test/earl_grey2/chrome_earl_grey_edo.mm new file mode 100644 index 0000000..848b674 --- /dev/null +++ b/ios/chrome/test/earl_grey2/chrome_earl_grey_edo.mm
@@ -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. + +#import "ios/chrome/test/earl_grey2/chrome_earl_grey_edo.h" + +#import "ios/chrome/test/app/tab_test_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation GREYHostApplicationDistantObject (RemoteTest) + +- (NSUInteger)GetMainTabCount { + return chrome_test_util::GetMainTabCount(); +} +@end
diff --git a/ios/chrome/test/earl_grey2/chrome_ios_eg2_test.gni b/ios/chrome/test/earl_grey2/chrome_ios_eg2_test.gni new file mode 100644 index 0000000..fc6832c --- /dev/null +++ b/ios/chrome/test/earl_grey2/chrome_ios_eg2_test.gni
@@ -0,0 +1,153 @@ +# 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. + +import("//build/config/ios/rules.gni") +import("//build/mac/tweak_info_plist.gni") +import("//ios/build/chrome_build.gni") +import("//ios/public/provider/chrome/browser/build_config.gni") +import("//ios/third_party/earl_grey2/ios_eg2_test.gni") + +template("chrome_ios_eg2_test_app_host") { + if (!defined(entitlements_path) && !defined(entitlements_target)) { + _target_name = target_name + _tweak_entitlements = target_name + "_tweak_entitlements" + compile_entitlements(_tweak_entitlements) { + substitutions = [ "IOS_BUNDLE_ID_PREFIX=$ios_app_bundle_id_prefix" ] + output_name = "$target_gen_dir/$_target_name.entitlements" + entitlements_templates = + [ "//ios/chrome/test/earl_grey/resources/Chrome.entitlements" ] + if (ios_egtests_entitlements_additions != []) { + entitlements_templates += ios_egtests_entitlements_additions + } + } + } + + if (!defined(info_plist) && !defined(info_plist_target)) { + _tweak_info_plist = target_name + "_tweak_info_plist" + tweak_info_plist(_tweak_info_plist) { + info_plists = [ + "//ios/chrome/app/resources/Info.plist", + "//ios/chrome/app/resources/EarlGreyAddition+Info.plist", + ] + if (ios_chrome_info_plist_additions != []) { + info_plists += ios_chrome_info_plist_additions + } + if (defined(invoker.extra_info_plists)) { + info_plists += invoker.extra_info_plists + } + args = [ + "--breakpad=$breakpad_enabled_as_int", + "--branding=$chromium_short_name", + "--version-overrides=MINOR=9999", + ] + } + } + + _deps_group_name = target_name + "_deps_group" + group(_deps_group_name) { + testonly = true + + public_deps = [] + if (defined(invoker.deps)) { + public_deps += invoker.deps + } + + if (defined(invoker.public_deps)) { + public_deps += invoker.public_deps + } + } + + ios_eg2_test_app_host(target_name) { + forward_variables_from(invoker, + [ + "entitlements_path", + "entitlements_target", + "eg_main_application_delegate", + "info_plist", + "info_plist_target", + ], + [ + "deps", + "public_deps", + ]) + testonly = true + + if (!defined(entitlements_path) && !defined(entitlements_target)) { + entitlements_target = ":$_tweak_entitlements" + } + + if (!defined(info_plist) && !defined(info_plist_target)) { + info_plist_target = ":$_tweak_info_plist" + } + + _eg_main_application_delegate = "MainApplicationDelegate" + if (defined(eg_main_application_delegate)) { + _eg_main_application_delegate = eg_main_application_delegate + } + + deps = [ + ":$_deps_group_name", + "//ios/chrome/app:main", + "//ios/chrome/test/earl_grey:hooks", + "//ios/testing:http_server_bundle_data", + "//ios/third_party/earl_grey2:app_framework+link", + ] + + if (!defined(bundle_deps)) { + bundle_deps = [] + } + bundle_deps += [ + "//ios/chrome/app/resources", + "//ios/third_party/earl_grey2:app_framework+bundle", + ios_application_icons_target, + ] + + if (!defined(extra_substitutions)) { + extra_substitutions = [] + } + extra_substitutions += [ + "CHROMIUM_HANDOFF_ID=$chromium_handoff_id", + "CHROMIUM_SHORT_NAME=$target_name", + "CHROMIUM_URL_SCHEME_1=$url_unsecure_scheme", + "CHROMIUM_URL_SCHEME_2=$url_secure_scheme", + "CHROMIUM_URL_SCHEME_3=$url_x_callback_scheme", + "CHROMIUM_URL_CHANNEL_SCHEME=$url_channel_scheme", + "EG_MAIN_APPLICATION_DELEGATE=$_eg_main_application_delegate", + "SSOAUTH_URL_SCHEME=$url_ssoauth_scheme", + "CONTENT_WIDGET_EXTENSION_BUNDLE_ID=$chromium_bundle_id.ContentTodayExtension", + ] + if (ios_automatically_manage_certs) { + # Use the same bundle identifier for EarlGrey tests as for unit tests + # when managing certificates as the number of free certs is limited. + extra_substitutions += + [ "CHROMIUM_BUNDLE_ID=gtest.${ios_generic_test_bundle_id_suffix}" ] + } else { + extra_substitutions += [ "CHROMIUM_BUNDLE_ID=gtest.$target_name" ] + } + } +} + +set_defaults("chrome_ios_eg_v2_test_app_host") { + configs = default_executable_configs +} + +template("chrome_ios_eg2_test") { + assert(defined(invoker.xcode_test_application_name), + "xcode_test_application_name must be defined for $target_name") + assert( + defined(invoker.deps), + "deps must be defined for $target_name to include at least one earl grey test file.") + + ios_eg2_test(target_name) { + forward_variables_from(invoker, + [ + "xcode_test_application_name", + "deps", + ]) + } +} + +set_defaults("chrome_ios_eg2_test") { + configs = default_shared_library_configs +}
diff --git a/ios/chrome/test/earl_grey2/smoke_egtest.mm b/ios/chrome/test/earl_grey2/smoke_egtest.mm new file mode 100644 index 0000000..37696705 --- /dev/null +++ b/ios/chrome/test/earl_grey2/smoke_egtest.mm
@@ -0,0 +1,64 @@ +// 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. + +#import <TestLib/EarlGreyImpl/EarlGrey.h> +#import <UIKit/UIKit.h> +#import <XCTest/XCTest.h> + +#import "ios/chrome/test/earl_grey2/chrome_earl_grey_edo.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// Test case to verify that EarlGrey tests can be launched and perform basic +// UI interactions. +@interface Eg2TestCase : XCTestCase +@end + +@implementation Eg2TestCase + +- (void)setUp { + [super setUp]; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + XCUIApplication* application = [[XCUIApplication alloc] init]; + [application launch]; + }); +} + +// Tests that the tools menu is tappable. +- (void)testTapToolsMenu { + id<GREYMatcher> toolsMenuButtonID = + grey_allOf(grey_accessibilityID(@"kToolbarToolsMenuButtonIdentifier"), + grey_sufficientlyVisible(), nil); + [[EarlGrey selectElementWithMatcher:toolsMenuButtonID] + performAction:grey_tap()]; +} + +// Tests that a tab can be opened. +- (void)testOpenTab { + // Open tools menu. + // TODO(crbug.com/917114): Calling the string directly is temporary while we + // roll out a solution to access constants across the code base for EG2. + id<GREYMatcher> toolsMenuButtonID = + grey_allOf(grey_accessibilityID(@"kToolbarToolsMenuButtonIdentifier"), + grey_sufficientlyVisible(), nil); + [[EarlGrey selectElementWithMatcher:toolsMenuButtonID] + performAction:grey_tap()]; + + // Open new tab. + // TODO(crbug.com/917114): Calling the string directly is temporary while we + // roll out a solution to access constants across the code base for EG2. + id<GREYMatcher> newTabButtonMatcher = + grey_accessibilityID(@"kToolsMenuNewTabId"); + [[EarlGrey selectElementWithMatcher:newTabButtonMatcher] + performAction:grey_tap()]; + + // Get tab count. + NSUInteger tabCount = + [[GREYHostApplicationDistantObject sharedInstance] GetMainTabCount]; + GREYAssertEqual(2, tabCount, @"Expected 2 tabs."); +} +@end
diff --git a/ios/third_party/earl_grey2/BUILD.gn b/ios/third_party/earl_grey2/BUILD.gn index 8f04f07..8633180 100644 --- a/ios/third_party/earl_grey2/BUILD.gn +++ b/ios/third_party/earl_grey2/BUILD.gn
@@ -367,12 +367,9 @@ ] } -ios_framework_bundle("test_lib") { +source_set("test_lib") { testonly = true - output_name = "EarlGreyTestLib" - info_plist = "Info.plist" - sources = [ "src/AppFramework/Error/GREYFailureScreenshotterStub.m", "src/AppFramework/Matcher/GREYMatchersShorthand.m", @@ -433,8 +430,6 @@ "UIKit.framework", ] - public_headers = [ "src/TestLib/EarlGreyImpl/EarlGrey.h" ] - public_configs = [ ":config" ] configs -= [
diff --git a/ios/third_party/earl_grey2/Info.plist b/ios/third_party/earl_grey2/Info.plist index 63cd4ba..0c5092a5 100644 --- a/ios/third_party/earl_grey2/Info.plist +++ b/ios/third_party/earl_grey2/Info.plist
@@ -17,4 +17,4 @@ <key>CFBundleDevelopmentRegion</key> <string>English</string> </dict> -</plist> \ No newline at end of file +</plist>
diff --git a/ios/third_party/earl_grey2/ios_eg2_test.gni b/ios/third_party/earl_grey2/ios_eg2_test.gni new file mode 100644 index 0000000..b1b5a74 --- /dev/null +++ b/ios/third_party/earl_grey2/ios_eg2_test.gni
@@ -0,0 +1,85 @@ +# 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. + +import("//build/config/ios/rules.gni") +import("//ios/third_party/firebase/firebase.gni") + +template("ios_eg2_test_app_host") { + ios_app_bundle(target_name) { + testonly = true + forward_variables_from(invoker, "*") + + configs += [ "//build/config/ios:xctest_config" ] + + if (!defined(bundle_deps)) { + bundle_deps = [] + } + bundle_deps += [ "//ios/third_party/earl_grey2:app_framework+bundle" ] + if (ios_enable_firebase_sdk) { + assert(ios_firebase_resources_target != "", + "ios_firebase_resources_target must be defined if Firebase SDK " + + "is enabled.") + bundle_deps += [ ios_firebase_resources_target ] + } + + if (!defined(deps)) { + deps = [] + } + deps += [ "//ios/third_party/earl_grey2:app_framework+link" ] + if (ios_enable_firebase_sdk) { + deps += [ "//ios/third_party/firebase" ] + } + + # Xcode needs those two framework installed in the application (and signed) + # for the XCTest to run, so install them using extra_system_frameworks. + _ios_platform_library = "$ios_sdk_platform_path/Developer/Library" + extra_system_frameworks = + [ "$_ios_platform_library/Frameworks/XCTest.framework" ] + + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += [ + "-Xlinker", + "-rpath", + "-Xlinker", + "@executable_path/Frameworks", + "-Xlinker", + "-rpath", + "-Xlinker", + "@loader_path/Frameworks", + ] + } +} + +set_defaults("ios_eg2_test_app_host") { + configs = default_executable_configs +} + +# EarlGrey2 tests are just XCUITests that also depends on EarlGrey2. +template("ios_eg2_test") { + assert(defined(invoker.xcode_test_application_name), + "xcode_test_application_name must be defined for $target_name") + assert( + defined(invoker.deps), + "deps must be defined for $target_name to include at least one earl grey test file.") + + ios_xcuitest_test(target_name) { + forward_variables_from(invoker, + [ + "xcode_test_application_name", + "bundle_deps", + "deps", + ]) + + if (!defined(deps)) { + deps = [] + } + deps += [ "//ios/third_party/earl_grey2:test_lib" ] + } +} + +set_defaults("ios_eg2_test") { + configs = default_shared_library_configs +}
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 5c25cc3..b532a7b 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -500,4 +500,15 @@ return false; } +// Enable grouped browser audio focus. This means that all browser media +// sessions will share audio focus. This should only be enabled on Chrome OS. +const base::Feature kUseGroupedBrowserAudioFocus { + "UseGroupedBrowserAudioFocus", +#if defined(OS_CHROMEOS) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif +}; + } // namespace media
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 8f6ca8c..bfcd21b 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -132,6 +132,7 @@ MEDIA_EXPORT extern const base::Feature kUnifiedAutoplay; MEDIA_EXPORT extern const base::Feature kUseAndroidOverlay; MEDIA_EXPORT extern const base::Feature kUseAndroidOverlayAggressively; +MEDIA_EXPORT extern const base::Feature kUseGroupedBrowserAudioFocus; MEDIA_EXPORT extern const base::Feature kUseModernMediaControls; MEDIA_EXPORT extern const base::Feature kUseNewMediaCache; MEDIA_EXPORT extern const base::Feature kUseR16Texture;
diff --git a/media/capture/video/win/video_capture_device_factory_win.cc b/media/capture/video/win/video_capture_device_factory_win.cc index 2aa5d9d..9e121baf 100644 --- a/media/capture/video/win/video_capture_device_factory_win.cc +++ b/media/capture/video/win/video_capture_device_factory_win.cc
@@ -82,7 +82,9 @@ // Devices using Empia 2860 or 2820 chips, see https://crbug.com/849636. "eb1a:2860", "eb1a:2820", "1ce6:2820", // Elgato HD60 Pro - "12ab:0380"}; + "12ab:0380", + // Sensoray 2253 + "1943:2253"}; const std::pair<VideoCaptureApi, std::vector<std::pair<GUID, GUID>>> kMfAttributes[] = {{VideoCaptureApi::WIN_MEDIA_FOUNDATION,
diff --git a/media/mojo/interfaces/supported_video_decoder_config_struct_traits.cc b/media/mojo/interfaces/supported_video_decoder_config_struct_traits.cc new file mode 100644 index 0000000..812d86a6 --- /dev/null +++ b/media/mojo/interfaces/supported_video_decoder_config_struct_traits.cc
@@ -0,0 +1,32 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/mojo/interfaces/supported_video_decoder_config_struct_traits.h" + +namespace mojo { + +// static +bool StructTraits<media::mojom::SupportedVideoDecoderConfigDataView, + media::SupportedVideoDecoderConfig>:: + Read(media::mojom::SupportedVideoDecoderConfigDataView input, + media::SupportedVideoDecoderConfig* output) { + if (!input.ReadProfileMin(&output->profile_min)) + return false; + + if (!input.ReadProfileMax(&output->profile_max)) + return false; + + if (!input.ReadCodedSizeMin(&output->coded_size_min)) + return false; + + if (!input.ReadCodedSizeMax(&output->coded_size_max)) + return false; + + output->allow_encrypted = input.allow_encrypted(); + output->require_encrypted = input.require_encrypted(); + + return true; +} + +} // namespace mojo
diff --git a/media/mojo/interfaces/supported_video_decoder_config_struct_traits.h b/media/mojo/interfaces/supported_video_decoder_config_struct_traits.h new file mode 100644 index 0000000..87561575 --- /dev/null +++ b/media/mojo/interfaces/supported_video_decoder_config_struct_traits.h
@@ -0,0 +1,54 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_MOJO_INTERFACES_SUPPORTED_VIDEO_DECODER_CONFIG_STRUCT_TRAITS_H_ +#define MEDIA_MOJO_INTERFACES_SUPPORTED_VIDEO_DECODER_CONFIG_STRUCT_TRAITS_H_ + +#include "media/base/ipc/media_param_traits.h" +#include "media/mojo/interfaces/media_types.mojom.h" +#include "media/mojo/interfaces/video_decoder.mojom.h" +#include "media/video/supported_video_decoder_config.h" +#include "ui/gfx/geometry/mojo/geometry_struct_traits.h" + +namespace mojo { + +template <> +struct StructTraits<media::mojom::SupportedVideoDecoderConfigDataView, + media::SupportedVideoDecoderConfig> { + static media::VideoCodecProfile profile_min( + const media::SupportedVideoDecoderConfig& input) { + return input.profile_min; + } + + static media::VideoCodecProfile profile_max( + const media::SupportedVideoDecoderConfig& input) { + return input.profile_max; + } + + static const gfx::Size& coded_size_min( + const media::SupportedVideoDecoderConfig& input) { + return input.coded_size_min; + } + + static const gfx::Size& coded_size_max( + const media::SupportedVideoDecoderConfig& input) { + return input.coded_size_max; + } + + static bool allow_encrypted(const media::SupportedVideoDecoderConfig& input) { + return input.allow_encrypted; + } + + static bool require_encrypted( + const media::SupportedVideoDecoderConfig& input) { + return input.require_encrypted; + } + + static bool Read(media::mojom::SupportedVideoDecoderConfigDataView input, + media::SupportedVideoDecoderConfig* output); +}; + +} // namespace mojo + +#endif // MEDIA_MOJO_INTERFACES_SUPPORTED_VIDEO_DECODER_CONFIG_STRUCT_TRAITS_H_
diff --git a/media/mojo/interfaces/video_decoder.typemap b/media/mojo/interfaces/video_decoder.typemap index 8b58cde..bcc9160 100644 --- a/media/mojo/interfaces/video_decoder.typemap +++ b/media/mojo/interfaces/video_decoder.typemap
@@ -4,12 +4,26 @@ mojom = "//media/mojo/interfaces/video_decoder.mojom" -public_headers = [ "//media/base/overlay_info.h" ] +public_headers = [ + "//media/base/overlay_info.h", + "//media/video/supported_video_decoder_config.h", +] -traits_headers = [ "//media/base/ipc/media_param_traits_macros.h" ] +traits_headers = [ + "//media/base/ipc/media_param_traits_macros.h", + "//media/mojo/interfaces/supported_video_decoder_config_struct_traits.h", +] + +sources = [ + "supported_video_decoder_config_struct_traits.cc", + "supported_video_decoder_config_struct_traits.h", +] deps = [ "//media/gpu/ipc/common", ] -type_mappings = [ "media.mojom.OverlayInfo=media::OverlayInfo" ] +type_mappings = [ + "media.mojom.OverlayInfo=media::OverlayInfo", + "media.mojom.SupportedVideoDecoderConfig=media::SupportedVideoDecoderConfig", +]
diff --git a/media/mojo/services/gpu_mojo_media_client.cc b/media/mojo/services/gpu_mojo_media_client.cc index f056e1b..b47fea5 100644 --- a/media/mojo/services/gpu_mojo_media_client.cc +++ b/media/mojo/services/gpu_mojo_media_client.cc
@@ -102,7 +102,7 @@ #endif // defined(OS_ANDROID) } -std::vector<mojom::SupportedVideoDecoderConfigPtr> +std::vector<SupportedVideoDecoderConfig> GpuMojoMediaClient::GetSupportedVideoDecoderConfigs() { // TODO(liberato): Implement for D3D11VideoDecoder and MediaCodecVideoDecoder. VideoDecodeAccelerator::Capabilities capabilities = @@ -113,9 +113,9 @@ capabilities.flags & VideoDecodeAccelerator::Capabilities::SUPPORTS_ENCRYPTED_STREAMS; - std::vector<mojom::SupportedVideoDecoderConfigPtr> supported_configs; + std::vector<SupportedVideoDecoderConfig> supported_configs; for (const auto& supported_profile : capabilities.supported_profiles) { - supported_configs.push_back(mojom::SupportedVideoDecoderConfig::New( + supported_configs.push_back(SupportedVideoDecoderConfig( supported_profile.profile, // profile_min supported_profile.profile, // profile_max supported_profile.min_resolution, // coded_size_min
diff --git a/media/mojo/services/gpu_mojo_media_client.h b/media/mojo/services/gpu_mojo_media_client.h index 9981dc1..0c55b10 100644 --- a/media/mojo/services/gpu_mojo_media_client.h +++ b/media/mojo/services/gpu_mojo_media_client.h
@@ -39,8 +39,8 @@ ~GpuMojoMediaClient() final; // MojoMediaClient implementation. - std::vector<mojom::SupportedVideoDecoderConfigPtr> - GetSupportedVideoDecoderConfigs() final; + std::vector<SupportedVideoDecoderConfig> GetSupportedVideoDecoderConfigs() + final; void Initialize(service_manager::Connector* connector) final; std::unique_ptr<AudioDecoder> CreateAudioDecoder( scoped_refptr<base::SingleThreadTaskRunner> task_runner) final;
diff --git a/media/mojo/services/mojo_media_client.cc b/media/mojo/services/mojo_media_client.cc index ef4a342e..1abaa147 100644 --- a/media/mojo/services/mojo_media_client.cc +++ b/media/mojo/services/mojo_media_client.cc
@@ -28,9 +28,9 @@ return nullptr; } -std::vector<mojom::SupportedVideoDecoderConfigPtr> +std::vector<SupportedVideoDecoderConfig> MojoMediaClient::GetSupportedVideoDecoderConfigs() { - return std::vector<mojom::SupportedVideoDecoderConfigPtr>(); + return {}; } std::unique_ptr<VideoDecoder> MojoMediaClient::CreateVideoDecoder(
diff --git a/media/mojo/services/mojo_media_client.h b/media/mojo/services/mojo_media_client.h index a3adfb19..acf246b 100644 --- a/media/mojo/services/mojo_media_client.h +++ b/media/mojo/services/mojo_media_client.h
@@ -15,6 +15,7 @@ #include "media/media_buildflags.h" #include "media/mojo/interfaces/video_decoder.mojom.h" #include "media/mojo/services/media_mojo_export.h" +#include "media/video/supported_video_decoder_config.h" namespace base { class SingleThreadTaskRunner; @@ -55,7 +56,7 @@ virtual std::unique_ptr<AudioDecoder> CreateAudioDecoder( scoped_refptr<base::SingleThreadTaskRunner> task_runner); - virtual std::vector<mojom::SupportedVideoDecoderConfigPtr> + virtual std::vector<SupportedVideoDecoderConfig> GetSupportedVideoDecoderConfigs(); virtual std::unique_ptr<VideoDecoder> CreateVideoDecoder(
diff --git a/media/video/BUILD.gn b/media/video/BUILD.gn index 77e6410..f453174a 100644 --- a/media/video/BUILD.gn +++ b/media/video/BUILD.gn
@@ -35,6 +35,8 @@ "jpeg_encode_accelerator.h", "picture.cc", "picture.h", + "supported_video_decoder_config.cc", + "supported_video_decoder_config.h", "trace_util.cc", "trace_util.h", "video_decode_accelerator.cc", @@ -106,6 +108,7 @@ "h264_parser_unittest.cc", "h264_poc_unittest.cc", "half_float_maker_unittest.cc", + "supported_video_decoder_config_unittest.cc", ] if (enable_hevc_demuxing) { sources += [ "h265_parser_unittest.cc" ]
diff --git a/media/video/supported_video_decoder_config.cc b/media/video/supported_video_decoder_config.cc new file mode 100644 index 0000000..7da92f9 --- /dev/null +++ b/media/video/supported_video_decoder_config.cc
@@ -0,0 +1,53 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/video/supported_video_decoder_config.h" + +namespace media { + +SupportedVideoDecoderConfig::SupportedVideoDecoderConfig() = default; + +SupportedVideoDecoderConfig::SupportedVideoDecoderConfig( + VideoCodecProfile profile_min, + VideoCodecProfile profile_max, + const gfx::Size& coded_size_min, + const gfx::Size& coded_size_max, + bool allow_encrypted, + bool require_encrypted) + : profile_min(profile_min), + profile_max(profile_max), + coded_size_min(coded_size_min), + coded_size_max(coded_size_max), + allow_encrypted(allow_encrypted), + require_encrypted(require_encrypted) {} + +SupportedVideoDecoderConfig::~SupportedVideoDecoderConfig() = default; + +bool SupportedVideoDecoderConfig::Matches( + const VideoDecoderConfig& config) const { + if (config.profile() < profile_min || config.profile() > profile_max) + return false; + + if (config.is_encrypted()) { + if (!allow_encrypted) + return false; + } else { + if (require_encrypted) + return false; + } + + if (config.coded_size().width() < coded_size_min.width()) + return false; + if (config.coded_size().height() < coded_size_min.height()) + return false; + + if (config.coded_size().width() > coded_size_max.width()) + return false; + if (config.coded_size().height() > coded_size_max.height()) + return false; + + return true; +} + +} // namespace media
diff --git a/media/video/supported_video_decoder_config.h b/media/video/supported_video_decoder_config.h new file mode 100644 index 0000000..c0791af --- /dev/null +++ b/media/video/supported_video_decoder_config.h
@@ -0,0 +1,54 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_VIDEO_SUPPORTED_VIDEO_DECODER_CONFIG_H_ +#define MEDIA_VIDEO_SUPPORTED_VIDEO_DECODER_CONFIG_H_ + +#include "base/macros.h" +#include "media/base/media_export.h" +#include "media/base/video_codecs.h" +#include "media/base/video_decoder_config.h" +#include "ui/gfx/geometry/size.h" + +namespace media { + +// Specification of a range of configurations that are supported by a video +// decoder. Also provides the ability to check if a VideoDecoderConfig matches +// the supported range. +struct MEDIA_EXPORT SupportedVideoDecoderConfig { + SupportedVideoDecoderConfig(); + SupportedVideoDecoderConfig(VideoCodecProfile profile_min, + VideoCodecProfile profile_max, + const gfx::Size& coded_size_min, + const gfx::Size& coded_size_max, + bool allow_encrypted, + bool require_encrypted); + ~SupportedVideoDecoderConfig(); + + // Returns true if and only if |config| is a supported config. + bool Matches(const VideoDecoderConfig& config) const; + + // Range of VideoCodecProfiles to match, inclusive. + VideoCodecProfile profile_min = VIDEO_CODEC_PROFILE_UNKNOWN; + VideoCodecProfile profile_max = VIDEO_CODEC_PROFILE_UNKNOWN; + + // Coded size range, inclusive. + gfx::Size coded_size_min; + gfx::Size coded_size_max; + + // TODO(liberato): consider switching these to "allow_clear" and + // "allow_encrypted", so that they're orthogonal. + + // If true, then this will match encrypted configs. + bool allow_encrypted = true; + + // If true, then unencrypted configs will not match. + bool require_encrypted = false; + + // Allow copy and assignment. +}; + +} // namespace media + +#endif // MEDIA_VIDEO_SUPPORTED_VIDEO_DECODER_CONFIG_H_
diff --git a/media/video/supported_video_decoder_config_unittest.cc b/media/video/supported_video_decoder_config_unittest.cc new file mode 100644 index 0000000..c2e3593 --- /dev/null +++ b/media/video/supported_video_decoder_config_unittest.cc
@@ -0,0 +1,104 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/video/supported_video_decoder_config.h" +#include "media/base/test_helpers.h" +#include "media/base/video_codecs.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +class SupportedVideoDecoderConfigTest : public ::testing::Test { + public: + SupportedVideoDecoderConfigTest() + : decoder_config_( + TestVideoConfig::NormalCodecProfile(kCodecH264, + H264PROFILE_EXTENDED)) { + supported_config_.profile_min = H264PROFILE_MIN; + supported_config_.profile_max = H264PROFILE_MAX; + supported_config_.coded_size_min = gfx::Size(10, 20); + supported_config_.coded_size_max = gfx::Size(10000, 20000); + supported_config_.allow_encrypted = true; + supported_config_.require_encrypted = false; + } + + SupportedVideoDecoderConfig supported_config_; + + // Decoder config that matches |supported_config_|. + VideoDecoderConfig decoder_config_; +}; + +TEST_F(SupportedVideoDecoderConfigTest, ConstructionWithArgs) { + SupportedVideoDecoderConfig config2( + supported_config_.profile_min, supported_config_.profile_max, + supported_config_.coded_size_min, supported_config_.coded_size_max, + supported_config_.allow_encrypted, supported_config_.require_encrypted); + EXPECT_EQ(supported_config_.profile_min, config2.profile_min); + EXPECT_EQ(supported_config_.profile_max, config2.profile_max); + EXPECT_EQ(supported_config_.coded_size_min, config2.coded_size_min); + EXPECT_EQ(supported_config_.coded_size_max, config2.coded_size_max); + EXPECT_EQ(supported_config_.allow_encrypted, config2.allow_encrypted); + EXPECT_EQ(supported_config_.require_encrypted, config2.require_encrypted); +} + +TEST_F(SupportedVideoDecoderConfigTest, MatchingConfigMatches) { + EXPECT_TRUE(supported_config_.Matches(decoder_config_)); + + // Since |supported_config_| allows encrypted, this should also succeed. + decoder_config_.SetIsEncrypted(true); + EXPECT_TRUE(supported_config_.Matches(decoder_config_)); +} + +TEST_F(SupportedVideoDecoderConfigTest, LowerProfileMismatches) { + // Raise |profile_min| above |decoder_config_|. + supported_config_.profile_min = H264PROFILE_HIGH; + EXPECT_FALSE(supported_config_.Matches(decoder_config_)); +} + +TEST_F(SupportedVideoDecoderConfigTest, HigherProfileMismatches) { + // Lower |profile_max| below |decoder_config_|. + supported_config_.profile_max = H264PROFILE_MAIN; + EXPECT_FALSE(supported_config_.Matches(decoder_config_)); +} + +TEST_F(SupportedVideoDecoderConfigTest, SmallerMinWidthMismatches) { + supported_config_.coded_size_min = + gfx::Size(decoder_config_.coded_size().width() + 1, 0); + EXPECT_FALSE(supported_config_.Matches(decoder_config_)); +} + +TEST_F(SupportedVideoDecoderConfigTest, SmallerMinHeightMismatches) { + supported_config_.coded_size_min = + gfx::Size(0, decoder_config_.coded_size().height() + 1); + EXPECT_FALSE(supported_config_.Matches(decoder_config_)); +} + +TEST_F(SupportedVideoDecoderConfigTest, LargerMaxWidthMismatches) { + supported_config_.coded_size_max = + gfx::Size(decoder_config_.coded_size().width() - 1, 10000); + EXPECT_FALSE(supported_config_.Matches(decoder_config_)); +} + +TEST_F(SupportedVideoDecoderConfigTest, LargerMaxHeightMismatches) { + supported_config_.coded_size_max = + gfx::Size(10000, decoder_config_.coded_size().height() - 1); + EXPECT_FALSE(supported_config_.Matches(decoder_config_)); +} + +TEST_F(SupportedVideoDecoderConfigTest, RequiredEncryptionMismatches) { + supported_config_.require_encrypted = true; + EXPECT_FALSE(supported_config_.Matches(decoder_config_)); + + // The encrypted version should succeed. + decoder_config_.SetIsEncrypted(true); + EXPECT_TRUE(supported_config_.Matches(decoder_config_)); +} + +TEST_F(SupportedVideoDecoderConfigTest, AllowedEncryptionMismatches) { + supported_config_.allow_encrypted = false; + decoder_config_.SetIsEncrypted(true); + EXPECT_FALSE(supported_config_.Matches(decoder_config_)); +} + +} // namespace media
diff --git a/net/BUILD.gn b/net/BUILD.gn index 0dbd8f4b..3a9176b 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1315,6 +1315,10 @@ "third_party/quic/core/qpack/qpack_constants.h", "third_party/quic/core/qpack/qpack_decoder.cc", "third_party/quic/core/qpack/qpack_decoder.h", + "third_party/quic/core/qpack/qpack_decoder_stream_receiver.cc", + "third_party/quic/core/qpack/qpack_decoder_stream_receiver.h", + "third_party/quic/core/qpack/qpack_decoder_stream_sender.cc", + "third_party/quic/core/qpack/qpack_decoder_stream_sender.h", "third_party/quic/core/qpack/qpack_encoder.cc", "third_party/quic/core/qpack/qpack_encoder.h", "third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc", @@ -5089,6 +5093,8 @@ "third_party/quic/core/http/spdy_utils_test.cc", "third_party/quic/core/legacy_quic_stream_id_manager_test.cc", "third_party/quic/core/packet_number_indexed_queue_test.cc", + "third_party/quic/core/qpack/qpack_decoder_stream_receiver_test.cc", + "third_party/quic/core/qpack/qpack_decoder_stream_sender_test.cc", "third_party/quic/core/qpack/qpack_decoder_test.cc", "third_party/quic/core/qpack/qpack_encoder_stream_receiver_test.cc", "third_party/quic/core/qpack/qpack_encoder_stream_sender_test.cc",
diff --git a/net/docs/supported-projects.md b/net/docs/supported-projects.md index 1403dc3..e34abca8 100644 --- a/net/docs/supported-projects.md +++ b/net/docs/supported-projects.md
@@ -73,10 +73,12 @@ * **Automatic Updates**: Varies. Updates are made available on the Android App Store, but users must explicitly choose to update. As such, the rate of update varies much more than for the Chromium browser. - * **Command-line Flags**: No - * **Field Trials (Finch)**: No - * **Enterprise Policy**: No - * **User Metrics (UMA)**: No + * **Command-line Flags**: No for production devices, [yes for userdebug + devices](https://chromium.googlesource.com/chromium/src/+/HEAD/android_webview/docs/commandline-flags.md) + * **Field Trials (Finch)**: Yes, [with + caveats](https://g3doc.corp.google.com/analysis/uma/g3doc/finch/platforms.md?cl=head) + * **Enterprise Policy**: Yes, with caveats (TODO(rsleevi): document caveats) + * **User Metrics (UMA)**: Yes, [with caveats](http://go/clank-webview/uma) * **Component Updater**: No ## `//content` Embedders
diff --git a/net/third_party/quic/core/qpack/qpack_constants.cc b/net/third_party/quic/core/qpack/qpack_constants.cc index 7f628f1e..579f49b6 100644 --- a/net/third_party/quic/core/qpack/qpack_constants.cc +++ b/net/third_party/quic/core/qpack/qpack_constants.cc
@@ -56,6 +56,37 @@ return language; } +const QpackInstruction* TableStateSynchronizeInstruction() { + static const QpackInstructionOpcode* const opcode = + new QpackInstructionOpcode{0b00000000, 0b11000000}; + static const QpackInstruction* const instruction = + new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 6}}}; + return instruction; +} + +const QpackInstruction* HeaderAcknowledgementInstruction() { + static const QpackInstructionOpcode* const opcode = + new QpackInstructionOpcode{0b10000000, 0b10000000}; + static const QpackInstruction* const instruction = + new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 7}}}; + return instruction; +} + +const QpackInstruction* StreamCancellationInstruction() { + static const QpackInstructionOpcode* const opcode = + new QpackInstructionOpcode{0b01000000, 0b11000000}; + static const QpackInstruction* const instruction = + new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 6}}}; + return instruction; +} + +const QpackLanguage* QpackDecoderStreamLanguage() { + static const QpackLanguage* const language = new QpackLanguage{ + TableStateSynchronizeInstruction(), HeaderAcknowledgementInstruction(), + StreamCancellationInstruction()}; + return language; +} + const QpackInstruction* QpackPrefixInstruction() { // This opcode matches every input. static const QpackInstructionOpcode* const opcode =
diff --git a/net/third_party/quic/core/qpack/qpack_constants.h b/net/third_party/quic/core/qpack/qpack_constants.h index 5e01ed4..163d376 100644 --- a/net/third_party/quic/core/qpack/qpack_constants.h +++ b/net/third_party/quic/core/qpack/qpack_constants.h
@@ -102,6 +102,20 @@ // Encoder stream language. const QpackLanguage* QpackEncoderStreamLanguage(); +// 5.3 Decoder stream instructions + +// 5.3.1 Table State Synchronize +const QpackInstruction* TableStateSynchronizeInstruction(); + +// 5.3.2 Header Acknowledgement +const QpackInstruction* HeaderAcknowledgementInstruction(); + +// 5.3.3 Stream Cancellation +const QpackInstruction* StreamCancellationInstruction(); + +// Decoder stream language. +const QpackLanguage* QpackDecoderStreamLanguage(); + // 5.4.1. Header data prefix instructions const QpackInstruction* QpackPrefixInstruction();
diff --git a/net/third_party/quic/core/qpack/qpack_decoder_stream_receiver.cc b/net/third_party/quic/core/qpack/qpack_decoder_stream_receiver.cc new file mode 100644 index 0000000..7efd5ec --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_decoder_stream_receiver.cc
@@ -0,0 +1,52 @@ +// 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. + +#include "net/third_party/quic/core/qpack/qpack_decoder_stream_receiver.h" + +#include "net/third_party/quic/core/qpack/qpack_constants.h" +#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h" +#include "net/third_party/quiche/src/http2/decoder/decode_status.h" + +namespace quic { + +QpackDecoderStreamReceiver::QpackDecoderStreamReceiver(Delegate* delegate) + : instruction_decoder_(QpackDecoderStreamLanguage(), this), + delegate_(delegate), + error_detected_(false) { + DCHECK(delegate_); +} + +void QpackDecoderStreamReceiver::Decode(QuicStringPiece data) { + if (data.empty() || error_detected_) { + return; + } + + instruction_decoder_.Decode(data); +} + +bool QpackDecoderStreamReceiver::OnInstructionDecoded( + const QpackInstruction* instruction) { + if (instruction == TableStateSynchronizeInstruction()) { + delegate_->OnTableStateSynchronize(instruction_decoder_.varint()); + return true; + } + + if (instruction == HeaderAcknowledgementInstruction()) { + delegate_->OnHeaderAcknowledgement(instruction_decoder_.varint()); + return true; + } + + DCHECK_EQ(instruction, StreamCancellationInstruction()); + delegate_->OnStreamCancellation(instruction_decoder_.varint()); + return true; +} + +void QpackDecoderStreamReceiver::OnError(QuicStringPiece error_message) { + DCHECK(!error_detected_); + + error_detected_ = true; + delegate_->OnErrorDetected(error_message); +} + +} // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_decoder_stream_receiver.h b/net/third_party/quic/core/qpack/qpack_decoder_stream_receiver.h new file mode 100644 index 0000000..54511083 --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_decoder_stream_receiver.h
@@ -0,0 +1,61 @@ +// 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 NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_DECODER_STREAM_RECEIVER_H_ +#define NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_DECODER_STREAM_RECEIVER_H_ + +#include <cstdint> + +#include "net/third_party/quic/core/qpack/qpack_instruction_decoder.h" +#include "net/third_party/quic/platform/api/quic_export.h" +#include "net/third_party/quic/platform/api/quic_string_piece.h" + +namespace quic { + +// This class decodes data received on the decoder stream. +class QUIC_EXPORT_PRIVATE QpackDecoderStreamReceiver + : public QpackInstructionDecoder::Delegate { + public: + // An interface for handling instructions decoded from the decoder stream, see + // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.3 + class Delegate { + public: + virtual ~Delegate() = default; + + // 5.3.1 Table State Synchronize + virtual void OnTableStateSynchronize(uint64_t insert_count) = 0; + // 5.3.2 Header Acknowledgement + virtual void OnHeaderAcknowledgement(uint64_t stream_id) = 0; + // 5.3.3 Stream Cancellation + virtual void OnStreamCancellation(uint64_t stream_id) = 0; + // Decoding error + virtual void OnErrorDetected(QuicStringPiece error_message) = 0; + }; + + explicit QpackDecoderStreamReceiver(Delegate* delegate); + QpackDecoderStreamReceiver() = delete; + QpackDecoderStreamReceiver(const QpackDecoderStreamReceiver&) = delete; + QpackDecoderStreamReceiver& operator=(const QpackDecoderStreamReceiver&) = + delete; + + // Decode data and call appropriate Delegate method after each decoded + // instruction. Once an error occurs, Delegate::OnErrorDetected() is called, + // and all further data is ignored. + void Decode(QuicStringPiece data); + + // QpackInstructionDecoder::Delegate implementation. + bool OnInstructionDecoded(const QpackInstruction* instruction) override; + void OnError(QuicStringPiece error_message) override; + + private: + QpackInstructionDecoder instruction_decoder_; + Delegate* const delegate_; + + // True if a decoding error has been detected. + bool error_detected_; +}; + +} // namespace quic + +#endif // NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_DECODER_STREAM_RECEIVER_H_
diff --git a/net/third_party/quic/core/qpack/qpack_decoder_stream_receiver_test.cc b/net/third_party/quic/core/qpack/qpack_decoder_stream_receiver_test.cc new file mode 100644 index 0000000..9c166f4d --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_decoder_stream_receiver_test.cc
@@ -0,0 +1,90 @@ +// 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. + +#include "net/third_party/quic/core/qpack/qpack_decoder_stream_receiver.h" + +#include "net/third_party/quic/platform/api/quic_test.h" +#include "net/third_party/quic/platform/api/quic_text_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::Eq; +using testing::StrictMock; + +namespace quic { +namespace test { +namespace { + +class MockDelegate : public QpackDecoderStreamReceiver::Delegate { + public: + ~MockDelegate() override = default; + + MOCK_METHOD1(OnTableStateSynchronize, void(uint64_t insert_count)); + MOCK_METHOD1(OnHeaderAcknowledgement, void(uint64_t stream_id)); + MOCK_METHOD1(OnStreamCancellation, void(uint64_t stream_id)); + MOCK_METHOD1(OnErrorDetected, void(QuicStringPiece error_message)); +}; + +class QpackDecoderStreamReceiverTest : public QuicTest { + protected: + QpackDecoderStreamReceiverTest() : stream_(&delegate_) {} + + QpackDecoderStreamReceiver stream_; + StrictMock<MockDelegate> delegate_; +}; + +TEST_F(QpackDecoderStreamReceiverTest, TableStateSynchronize) { + EXPECT_CALL(delegate_, OnTableStateSynchronize(0)); + stream_.Decode(QuicTextUtils::HexDecode("00")); + + EXPECT_CALL(delegate_, OnTableStateSynchronize(10)); + stream_.Decode(QuicTextUtils::HexDecode("0a")); + + EXPECT_CALL(delegate_, OnTableStateSynchronize(63)); + stream_.Decode(QuicTextUtils::HexDecode("3f00")); + + EXPECT_CALL(delegate_, OnTableStateSynchronize(200)); + stream_.Decode(QuicTextUtils::HexDecode("3f8901")); + + EXPECT_CALL(delegate_, OnErrorDetected(Eq("Encoded integer too large."))); + stream_.Decode(QuicTextUtils::HexDecode("3fffffffffffffffffffff")); +} + +TEST_F(QpackDecoderStreamReceiverTest, HeaderAcknowledgement) { + EXPECT_CALL(delegate_, OnHeaderAcknowledgement(0)); + stream_.Decode(QuicTextUtils::HexDecode("80")); + + EXPECT_CALL(delegate_, OnHeaderAcknowledgement(37)); + stream_.Decode(QuicTextUtils::HexDecode("a5")); + + EXPECT_CALL(delegate_, OnHeaderAcknowledgement(127)); + stream_.Decode(QuicTextUtils::HexDecode("ff00")); + + EXPECT_CALL(delegate_, OnHeaderAcknowledgement(503)); + stream_.Decode(QuicTextUtils::HexDecode("fff802")); + + EXPECT_CALL(delegate_, OnErrorDetected(Eq("Encoded integer too large."))); + stream_.Decode(QuicTextUtils::HexDecode("ffffffffffffffffffffff")); +} + +TEST_F(QpackDecoderStreamReceiverTest, StreamCancellation) { + EXPECT_CALL(delegate_, OnStreamCancellation(0)); + stream_.Decode(QuicTextUtils::HexDecode("40")); + + EXPECT_CALL(delegate_, OnStreamCancellation(19)); + stream_.Decode(QuicTextUtils::HexDecode("53")); + + EXPECT_CALL(delegate_, OnStreamCancellation(63)); + stream_.Decode(QuicTextUtils::HexDecode("7f00")); + + EXPECT_CALL(delegate_, OnStreamCancellation(110)); + stream_.Decode(QuicTextUtils::HexDecode("7f2f")); + + EXPECT_CALL(delegate_, OnErrorDetected(Eq("Encoded integer too large."))); + stream_.Decode(QuicTextUtils::HexDecode("7fffffffffffffffffffff")); +} + +} // namespace +} // namespace test +} // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_decoder_stream_sender.cc b/net/third_party/quic/core/qpack/qpack_decoder_stream_sender.cc new file mode 100644 index 0000000..4c05fa56e2 --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_decoder_stream_sender.cc
@@ -0,0 +1,60 @@ +// 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. + +#include "net/third_party/quic/core/qpack/qpack_decoder_stream_sender.h" + +#include <limits> + +#include "net/third_party/quic/core/qpack/qpack_constants.h" +#include "net/third_party/quic/platform/api/quic_logging.h" +#include "net/third_party/quic/platform/api/quic_string.h" + +namespace quic { + +QpackDecoderStreamSender::QpackDecoderStreamSender(Delegate* delegate) + : delegate_(delegate) { + DCHECK(delegate_); +} + +void QpackDecoderStreamSender::SendTableStateSynchronize( + uint64_t insert_count) { + instruction_encoder_.set_varint(insert_count); + + instruction_encoder_.Encode(TableStateSynchronizeInstruction()); + + QuicString output; + + instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output); + DCHECK(!instruction_encoder_.HasNext()); + + delegate_->Write(output); +} + +void QpackDecoderStreamSender::SendHeaderAcknowledgement(uint64_t stream_id) { + instruction_encoder_.set_varint(stream_id); + + instruction_encoder_.Encode(HeaderAcknowledgementInstruction()); + + QuicString output; + + instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output); + DCHECK(!instruction_encoder_.HasNext()); + + delegate_->Write(output); +} + +void QpackDecoderStreamSender::SendStreamCancellation(uint64_t stream_id) { + instruction_encoder_.set_varint(stream_id); + + instruction_encoder_.Encode(StreamCancellationInstruction()); + + QuicString output; + + instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output); + DCHECK(!instruction_encoder_.HasNext()); + + delegate_->Write(output); +} + +} // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_decoder_stream_sender.h b/net/third_party/quic/core/qpack/qpack_decoder_stream_sender.h new file mode 100644 index 0000000..283d656 --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_decoder_stream_sender.h
@@ -0,0 +1,53 @@ +// 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 NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_DECODER_STREAM_SENDER_H_ +#define NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_DECODER_STREAM_SENDER_H_ + +#include <cstdint> + +#include "net/third_party/quic/core/qpack/qpack_instruction_encoder.h" +#include "net/third_party/quic/platform/api/quic_export.h" +#include "net/third_party/quic/platform/api/quic_string_piece.h" + +namespace quic { + +// This class serializes (encodes) instructions for transmission on the decoder +// stream. +class QUIC_EXPORT_PRIVATE QpackDecoderStreamSender { + public: + // An interface for handling encoded data. + class Delegate { + public: + virtual ~Delegate() = default; + + // Encoded |data| is ready to be written on the decoder stream. + // Write() is called exactly once for each instruction, |data| contains the + // entire encoded instruction and it is guaranteed to be not empty. + virtual void Write(QuicStringPiece data) = 0; + }; + + explicit QpackDecoderStreamSender(Delegate* delegate); + QpackDecoderStreamSender() = delete; + QpackDecoderStreamSender(const QpackDecoderStreamSender&) = delete; + QpackDecoderStreamSender& operator=(const QpackDecoderStreamSender&) = delete; + + // Methods for sending instructions, see + // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.3 + + // 5.3.1 Table State Synchronize + void SendTableStateSynchronize(uint64_t insert_count); + // 5.3.2 Header Acknowledgement + void SendHeaderAcknowledgement(uint64_t stream_id); + // 5.3.3 Stream Cancellation + void SendStreamCancellation(uint64_t stream_id); + + private: + Delegate* const delegate_; + QpackInstructionEncoder instruction_encoder_; +}; + +} // namespace quic + +#endif // NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_DECODER_STREAM_SENDER_H_
diff --git a/net/third_party/quic/core/qpack/qpack_decoder_stream_sender_test.cc b/net/third_party/quic/core/qpack/qpack_decoder_stream_sender_test.cc new file mode 100644 index 0000000..35c9284c --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_decoder_stream_sender_test.cc
@@ -0,0 +1,78 @@ +// 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. + +#include "net/third_party/quic/core/qpack/qpack_decoder_stream_sender.h" + +#include "net/third_party/quic/platform/api/quic_test.h" +#include "net/third_party/quic/platform/api/quic_text_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::Eq; +using ::testing::StrictMock; + +namespace quic { +namespace test { +namespace { + +class MockSenderDelegate : public QpackDecoderStreamSender::Delegate { + public: + ~MockSenderDelegate() override = default; + + MOCK_METHOD1(Write, void(QuicStringPiece data)); +}; + +class QpackDecoderStreamSenderTest : public QuicTest { + protected: + QpackDecoderStreamSenderTest() : stream_(&delegate_) {} + + StrictMock<MockSenderDelegate> delegate_; + QpackDecoderStreamSender stream_; +}; + +TEST_F(QpackDecoderStreamSenderTest, TableStateSynchronize) { + EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("00")))); + stream_.SendTableStateSynchronize(0); + + EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("0a")))); + stream_.SendTableStateSynchronize(10); + + EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("3f00")))); + stream_.SendTableStateSynchronize(63); + + EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("3f8901")))); + stream_.SendTableStateSynchronize(200); +} + +TEST_F(QpackDecoderStreamSenderTest, HeaderAcknowledgement) { + EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("80")))); + stream_.SendHeaderAcknowledgement(0); + + EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("a5")))); + stream_.SendHeaderAcknowledgement(37); + + EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("ff00")))); + stream_.SendHeaderAcknowledgement(127); + + EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("fff802")))); + stream_.SendHeaderAcknowledgement(503); +} + +TEST_F(QpackDecoderStreamSenderTest, StreamCancellation) { + EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("40")))); + stream_.SendStreamCancellation(0); + + EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("53")))); + stream_.SendStreamCancellation(19); + + EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("7f00")))); + stream_.SendStreamCancellation(63); + + EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("7f2f")))); + stream_.SendStreamCancellation(110); +} + +} // namespace +} // namespace test +} // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_stream_sender_test.cc b/net/third_party/quic/core/qpack/qpack_encoder_stream_sender_test.cc index ffef8f6..6a1e4c6 100644 --- a/net/third_party/quic/core/qpack/qpack_encoder_stream_sender_test.cc +++ b/net/third_party/quic/core/qpack/qpack_encoder_stream_sender_test.cc
@@ -20,7 +20,7 @@ public: ~MockSenderDelegate() override = default; - MOCK_METHOD1(Write, void(QuicStringPiece)); + MOCK_METHOD1(Write, void(QuicStringPiece data)); }; class QpackEncoderStreamSenderTest : public QuicTest {
diff --git a/net/third_party/quic/core/quic_session.cc b/net/third_party/quic/core/quic_session.cc index 0f9706c..0b92dcb 100644 --- a/net/third_party/quic/core/quic_session.cc +++ b/net/third_party/quic/core/quic_session.cc
@@ -694,15 +694,18 @@ void QuicSession::ClosePendingStream(QuicStreamId stream_id) { QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << stream_id; - auto it = pending_stream_map_.find(stream_id); - if (it == pending_stream_map_.end()) { + if (pending_stream_map_.find(stream_id) == pending_stream_map_.end()) { QUIC_BUG << ENDPOINT << "Stream is already closed: " << stream_id; return; } SendRstStream(stream_id, QUIC_RST_ACKNOWLEDGEMENT, 0); - pending_stream_map_.erase(it); + // The pending stream may have been deleted and removed during SendRstStream. + // Remove the stream from pending stream map iff it is still in the map. + if (pending_stream_map_.find(stream_id) != pending_stream_map_.end()) { + pending_stream_map_.erase(stream_id); + } --num_dynamic_incoming_streams_;
diff --git a/ppapi/examples/media_stream_video/media_stream_video.cc b/ppapi/examples/media_stream_video/media_stream_video.cc index e49aa13..9decc9a4 100644 --- a/ppapi/examples/media_stream_video/media_stream_video.cc +++ b/ppapi/examples/media_stream_video/media_stream_video.cc
@@ -244,8 +244,10 @@ glEnableVertexAttribArray(pos_location); glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(tc_location); - glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, - static_cast<float*>(0) + 16); // Skip position coordinates. + glVertexAttribPointer( + tc_location, 2, GL_FLOAT, GL_FALSE, 0, + reinterpret_cast<void*>(16 * + sizeof(GLfloat))); // Skip position coordinates. AssertNoGLError(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); @@ -263,8 +265,10 @@ glEnableVertexAttribArray(pos_location); glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(tc_location); - glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, - static_cast<float*>(0) + 16); // Skip position coordinates. + glVertexAttribPointer( + tc_location, 2, GL_FLOAT, GL_FALSE, 0, + reinterpret_cast<void*>(16 * + sizeof(GLfloat))); // Skip position coordinates. AssertNoGLError(); glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
diff --git a/ppapi/examples/video_capture/video_capture.cc b/ppapi/examples/video_capture/video_capture.cc index 9a0a32d..44387f97 100644 --- a/ppapi/examples/video_capture/video_capture.cc +++ b/ppapi/examples/video_capture/video_capture.cc
@@ -401,7 +401,8 @@ gles2_if_->EnableVertexAttribArray(context, tc_location); gles2_if_->VertexAttribPointer( context, tc_location, 2, GL_FLOAT, GL_FALSE, 0, - static_cast<float*>(0) + 8); // Skip position coordinates. + reinterpret_cast<void*>(8 * + sizeof(GLfloat))); // Skip position coordinates. AssertNoGLError(); }
diff --git a/ppapi/examples/video_decode/video_decode.cc b/ppapi/examples/video_decode/video_decode.cc index 2e6e9a3..fdbc186 100644 --- a/ppapi/examples/video_decode/video_decode.cc +++ b/ppapi/examples/video_decode/video_decode.cc
@@ -694,13 +694,9 @@ context_->pp_resource(), pos_location, 2, GL_FLOAT, GL_FALSE, 0, 0); gles2_if_->EnableVertexAttribArray(context_->pp_resource(), tc_location); gles2_if_->VertexAttribPointer( - context_->pp_resource(), - tc_location, - 2, - GL_FLOAT, - GL_FALSE, - 0, - static_cast<float*>(0) + 8); // Skip position coordinates. + context_->pp_resource(), tc_location, 2, GL_FLOAT, GL_FALSE, 0, + reinterpret_cast<void*>(8 * + sizeof(GLfloat))); // Skip position coordinates. gles2_if_->UseProgram(context_->pp_resource(), 0); assertNoGLError();
diff --git a/ppapi/examples/video_decode/video_decode_dev.cc b/ppapi/examples/video_decode/video_decode_dev.cc index 2c87192..ae955a6b 100644 --- a/ppapi/examples/video_decode/video_decode_dev.cc +++ b/ppapi/examples/video_decode/video_decode_dev.cc
@@ -666,7 +666,8 @@ gles2_if_->EnableVertexAttribArray(context_->pp_resource(), tc_location); gles2_if_->VertexAttribPointer( context_->pp_resource(), tc_location, 2, GL_FLOAT, GL_FALSE, 0, - static_cast<float*>(0) + 8); // Skip position coordinates. + reinterpret_cast<void*>(8 * + sizeof(GLfloat))); // Skip position coordinates. gles2_if_->UseProgram(context_->pp_resource(), 0); assertNoGLError();
diff --git a/remoting/client/display/gl_canvas.cc b/remoting/client/display/gl_canvas.cc index 58ec1af..1eee53b2 100644 --- a/remoting/client/display/gl_canvas.cc +++ b/remoting/client/display/gl_canvas.cc
@@ -140,8 +140,9 @@ glVertexAttribPointer(position_location_, kVertexSize, GL_FLOAT, GL_FALSE, 0, 0); - glVertexAttribPointer(tex_cord_location_, kVertexSize, GL_FLOAT, GL_FALSE, 0, - static_cast<float*>(0) + kVertexSize * kVertexCount); + glVertexAttribPointer( + tex_cord_location_, kVertexSize, GL_FLOAT, GL_FALSE, 0, + reinterpret_cast<void*>(kVertexSize * kVertexCount * sizeof(GLfloat))); glDrawArrays(GL_TRIANGLE_STRIP, 0, kVertexCount); glBindBuffer(GL_ARRAY_BUFFER, 0);
diff --git a/remoting/client/plugin/pepper_video_renderer_3d.cc b/remoting/client/plugin/pepper_video_renderer_3d.cc index 214ab4a..d9b8429 100644 --- a/remoting/client/plugin/pepper_video_renderer_3d.cc +++ b/remoting/client/plugin/pepper_video_renderer_3d.cc
@@ -566,7 +566,8 @@ gles2_if_->EnableVertexAttribArray(graphics_3d, tc_location); gles2_if_->VertexAttribPointer( graphics_3d, tc_location, 2, GL_FLOAT, GL_FALSE, 0, - static_cast<float*>(0) + 8); // Skip position coordinates. + reinterpret_cast<void*>(8 * + sizeof(GLfloat))); // Skip position coordinates. gles2_if_->UseProgram(graphics_3d, 0);
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 960f11d..47f8216 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -746,6 +746,10 @@ return sum; } +bool NetworkContext::SkipReportingPermissionCheck() const { + return params_ && params_->skip_reporting_send_permission_check; +} + void NetworkContext::ClearNetworkingHistorySince( base::Time time, base::OnceClosure completion_callback) { @@ -1809,10 +1813,16 @@ #endif #if BUILDFLAG(ENABLE_REPORTING) - if (base::FeatureList::IsEnabled(features::kReporting)) - builder->set_reporting_policy(net::ReportingPolicy::Create()); - else + if (base::FeatureList::IsEnabled(features::kReporting)) { + auto reporting_policy = net::ReportingPolicy::Create(); + if (params_->reporting_delivery_interval) { + reporting_policy->delivery_interval = + *params_->reporting_delivery_interval; + } + builder->set_reporting_policy(std::move(reporting_policy)); + } else { builder->set_reporting_policy(nullptr); + } builder->set_network_error_logging_enabled( base::FeatureList::IsEnabled(features::kNetworkErrorLogging));
diff --git a/services/network/network_context.h b/services/network/network_context.h index 2fb7f8e..c784de05 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h
@@ -375,6 +375,10 @@ return &cors_preflight_controller_; } + // Returns true if reports should unconditionally be sent without first + // consulting NetworkContextClient.OnCanSendReportingReports() + bool SkipReportingPermissionCheck() const; + private: class ContextNetworkDelegate;
diff --git a/services/network/network_service_network_delegate.cc b/services/network/network_service_network_delegate.cc index d2fad63..adfa706 100644 --- a/services/network/network_service_network_delegate.cc +++ b/services/network/network_service_network_delegate.cc
@@ -129,6 +129,11 @@ return; } + if (network_context_->SkipReportingPermissionCheck()) { + std::move(result_callback).Run(std::move(origins)); + return; + } + std::vector<url::Origin> origin_vector; std::copy(origins.begin(), origins.end(), std::back_inserter(origin_vector)); client->OnCanSendReportingReports(
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom index ed02555..bb94cec 100644 --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom
@@ -290,6 +290,15 @@ // Whether to discard Domain Reliability uploads. bool discard_domain_reliablity_uploads = false; + // When reporting is enabled, this sets the delay between sending reports. + // When omitted a default value is used. + mojo_base.mojom.TimeDelta? reporting_delivery_interval; + + // Whether to bypass the ordinary permission checks for sending reports, + // rather than calling NetworkContextClient.OnCanSendReportingReports() to + // decide. This should only be used by tests. + bool skip_reporting_send_permission_check = false; + // Sets whether the NetworkContext should be used for globally scoped tasks // that need to make network requests. Currently this includes DNS over HTTPS // requests and certain cert validation requests (OCSP, AIA, etc) on some
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 95da4b76..9ccca6c 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -8,6 +8,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -42,6 +43,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -58,6 +60,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -355,6 +358,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -389,6 +393,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -405,6 +410,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -539,6 +545,7 @@ ], "isolate_name": "command_buffer_perftests", "name": "passthrough_command_buffer_perftests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -559,6 +566,7 @@ ], "isolate_name": "command_buffer_perftests", "name": "validating_command_buffer_perftests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -760,6 +768,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -796,6 +805,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -857,6 +867,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -893,6 +904,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -954,6 +966,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -990,6 +1003,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1055,6 +1069,7 @@ "--recover-devices" ], "name": "angle_deqp_gles2_vulkan_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1099,6 +1114,7 @@ "--recover-devices" ], "name": "angle_deqp_gles2_vulkan_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1143,6 +1159,7 @@ "--recover-devices" ], "name": "angle_deqp_gles2_vulkan_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1183,6 +1200,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1219,6 +1237,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1280,6 +1299,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1316,6 +1336,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1377,6 +1398,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1413,6 +1435,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1478,6 +1501,7 @@ "--recover-devices" ], "name": "angle_deqp_gles2_vulkan_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1522,6 +1546,7 @@ "--recover-devices" ], "name": "angle_deqp_gles2_vulkan_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1566,6 +1591,7 @@ "--recover-devices" ], "name": "angle_deqp_gles2_vulkan_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1606,6 +1632,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -1642,6 +1669,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -2087,6 +2115,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -2512,6 +2541,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -2901,6 +2931,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -3326,6 +3357,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -3362,6 +3394,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -3807,6 +3840,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -4255,6 +4289,7 @@ "--recover-devices" ], "name": "angle_deqp_egl_gles_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -4294,6 +4329,7 @@ "--recover-devices" ], "name": "angle_deqp_gles2_gles_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -4326,12 +4362,14 @@ }, { "args": [ + "--deqp-egl-display-type=angle-gles", "--enable-xml-result-parsing", "--shard-timeout=500", "--gs-results-bucket=chromium-result-details", "--recover-devices" ], "name": "angle_deqp_gles3_gles_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ @@ -4539,6 +4577,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -4558,6 +4597,7 @@ "--test-launcher-retry-limit=0", "--no-xvfb" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -4574,6 +4614,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -4971,6 +5012,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -4990,6 +5032,7 @@ "--test-launcher-retry-limit=0", "--no-xvfb" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -5006,6 +5049,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -5042,24 +5086,6 @@ { "args": [ "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:1cb3-410.78", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "shards": 4 - }, - "test": "dawn_end2end_tests" - }, - { - "args": [ - "--use-gpu-in-tests", "--use-cmd-decoder=validating" ], "swarming": { @@ -5496,6 +5522,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -5515,6 +5542,7 @@ "--test-launcher-retry-limit=0", "--no-xvfb" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -5531,6 +5559,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -5653,6 +5682,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -5672,6 +5702,7 @@ "--test-launcher-retry-limit=0", "--no-xvfb" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -5694,6 +5725,7 @@ "--test-launcher-retry-limit=0", "--no-xvfb" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -5711,6 +5743,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -6138,6 +6171,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -6157,6 +6191,7 @@ "--test-launcher-retry-limit=0", "--no-xvfb" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -6173,6 +6208,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -6645,6 +6681,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -6664,6 +6701,7 @@ "--test-launcher-retry-limit=0", "--no-xvfb" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -6680,6 +6718,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -7171,6 +7210,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_gles2_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -7194,6 +7234,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_egl_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -7213,6 +7254,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_gles2_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -7232,6 +7274,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_gles31_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -7251,6 +7294,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_gles3_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -7273,6 +7317,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -7292,6 +7337,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -7760,6 +7806,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -7779,6 +7826,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -8247,6 +8295,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -8266,6 +8315,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -8734,6 +8784,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -8751,6 +8802,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -9134,6 +9186,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -9153,6 +9206,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -9607,6 +9661,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -9627,6 +9682,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -10100,6 +10156,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -10120,6 +10177,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -10593,6 +10651,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -10616,6 +10675,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -11134,6 +11194,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -11151,6 +11212,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -11579,6 +11641,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -11598,6 +11661,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -12017,6 +12081,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -12036,6 +12101,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -12455,6 +12521,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -12474,6 +12541,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -12942,6 +13010,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -12961,6 +13030,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -13430,6 +13500,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_egl_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -13450,6 +13521,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_gles2_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -13470,6 +13542,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_gles3_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -13494,6 +13567,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_egl_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -13512,6 +13586,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_gles2_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -13530,6 +13605,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_gles3_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -13551,6 +13627,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -13570,6 +13647,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -14007,6 +14085,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -14024,6 +14103,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -14174,6 +14254,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -14191,6 +14272,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -14359,6 +14441,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -14507,6 +14590,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -14671,6 +14755,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -14807,6 +14892,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -14840,6 +14926,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -15191,6 +15278,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -15242,6 +15330,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -15595,6 +15684,7 @@ ], "isolate_name": "command_buffer_perftests", "name": "passthrough_command_buffer_perftests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -15624,6 +15714,7 @@ ], "isolate_name": "command_buffer_perftests", "name": "validating_command_buffer_perftests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -15859,6 +15950,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -15893,6 +15985,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -15909,6 +16002,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -16544,6 +16638,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -16580,6 +16675,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -16597,6 +16693,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -17346,6 +17443,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -17382,6 +17480,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -17399,6 +17498,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -17856,6 +17956,7 @@ ], "isolate_name": "command_buffer_perftests", "name": "passthrough_command_buffer_perftests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -17968,6 +18069,7 @@ ], "isolate_name": "command_buffer_perftests", "name": "validating_command_buffer_perftests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -18229,6 +18331,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -18263,6 +18366,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -18279,6 +18383,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -18996,6 +19101,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -19048,6 +19154,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -19073,6 +19180,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -19706,6 +19814,7 @@ ], "isolate_name": "command_buffer_perftests", "name": "passthrough_command_buffer_perftests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -19850,6 +19959,7 @@ ], "isolate_name": "command_buffer_perftests", "name": "validating_command_buffer_perftests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20192,6 +20302,7 @@ "--deqp-egl-display-type=angle-d3d11" ], "name": "angle_deqp_gles2_d3d11_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20215,6 +20326,7 @@ "--deqp-egl-display-type=angle-d3d11" ], "name": "angle_deqp_egl_d3d11_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20234,6 +20346,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_egl_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20253,6 +20366,7 @@ "--deqp-egl-display-type=angle-vulkan" ], "name": "angle_deqp_egl_vulkan_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20272,6 +20386,7 @@ "--deqp-egl-display-type=angle-d3d11" ], "name": "angle_deqp_gles2_d3d11_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20291,6 +20406,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_gles2_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20310,6 +20426,7 @@ "--test-launcher-batch-limit=400" ], "name": "angle_deqp_gles2_vulkan_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20329,6 +20446,7 @@ "--deqp-egl-display-type=angle-d3d11" ], "name": "angle_deqp_gles31_d3d11_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20348,6 +20466,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_gles31_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20367,6 +20486,7 @@ "--deqp-egl-display-type=angle-d3d11" ], "name": "angle_deqp_gles3_d3d11_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20386,6 +20506,7 @@ "--deqp-egl-display-type=angle-gl" ], "name": "angle_deqp_gles3_gl_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20408,6 +20529,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20426,6 +20548,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20528,6 +20651,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20564,6 +20688,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -20581,6 +20706,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -21159,6 +21285,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -21195,6 +21322,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -21212,6 +21340,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -21865,6 +21994,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -21919,6 +22049,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -21945,6 +22076,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -22886,6 +23018,7 @@ "--deqp-egl-display-type=angle-d3d11" ], "name": "angle_deqp_gles2_d3d11_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -22906,6 +23039,7 @@ "--test-launcher-batch-limit=400" ], "name": "angle_deqp_gles2_vulkan_tests", + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -22929,6 +23063,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -22965,6 +23100,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -22982,6 +23118,7 @@ "args": [ "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [
diff --git a/testing/buildbot/chromium.gpu.json b/testing/buildbot/chromium.gpu.json index 05a5a71..fe7d4f2a3 100644 --- a/testing/buildbot/chromium.gpu.json +++ b/testing/buildbot/chromium.gpu.json
@@ -288,6 +288,7 @@ "--test-launcher-retry-limit=0", "--no-xvfb" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -614,6 +615,7 @@ "--test-launcher-retry-limit=0", "--no-xvfb" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -960,6 +962,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -1271,6 +1274,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -1711,6 +1715,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -2048,6 +2053,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -2418,6 +2424,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -2793,6 +2800,7 @@ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], + "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index b5572b16..288dd67 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -491,6 +491,7 @@ 'dawn_end2end_tests': { 'remove_from': [ # chromium.gpu.fyi + 'Linux FYI Experimental Release (NVIDIA)', # https://crbug.com/918942 'Linux FYI Release (AMD R7 240)', # https://crbug.com/915430 ], },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index bdef3ee..89cf426 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -2812,6 +2812,7 @@ '--test-launcher-batch-limit=400', '--deqp-egl-display-type=angle-d3d11', ], + 'should_retry_with_patch': False, 'swarming': { 'shards': 4, }, @@ -2825,6 +2826,7 @@ '--test-launcher-batch-limit=400', '--deqp-egl-display-type=angle-gl', ], + 'should_retry_with_patch': False, 'swarming': { 'shards': 4, }, @@ -2834,6 +2836,10 @@ 'gpu_angle_deqp_egl_gles_tests': { 'angle_deqp_egl_gles_tests': { + 'android_args': [ + '--enable-xml-result-parsing', + '--shard-timeout=500', + ], # Only pass the display type to desktop. The Android runner doesn't support # passing args to the executable but only one display type is supported on # Android anyways. Regardless, this test is only run on Android right now. @@ -2841,10 +2847,7 @@ '--test-launcher-batch-limit=400', '--deqp-egl-display-type=angle-gles', ], - 'android_args': [ - '--enable-xml-result-parsing', - '--shard-timeout=500', - ], + 'should_retry_with_patch': False, 'swarming': { 'shards': 4, }, @@ -2858,6 +2861,7 @@ '--test-launcher-batch-limit=400', '--deqp-egl-display-type=angle-vulkan', ], + 'should_retry_with_patch': False, 'swarming': { 'shards': 4, }, @@ -2867,72 +2871,77 @@ 'gpu_angle_deqp_gles2_d3d11_tests': { 'angle_deqp_gles2_d3d11_tests': { - 'swarming': { - 'shards': 4, - }, - 'test': 'angle_deqp_gles2_tests', 'args': [ '--test-launcher-batch-limit=400', '--deqp-egl-display-type=angle-d3d11', ], + 'should_retry_with_patch': False, + 'swarming': { + 'shards': 4, + }, + 'test': 'angle_deqp_gles2_tests', }, }, 'gpu_angle_deqp_gles2_gl_tests': { 'angle_deqp_gles2_gl_tests': { - 'swarming': { - 'shards': 4, - }, - 'test': 'angle_deqp_gles2_tests', 'args': [ '--test-launcher-batch-limit=400', '--deqp-egl-display-type=angle-gl', ], + 'should_retry_with_patch': False, + 'swarming': { + 'shards': 4, + }, + 'test': 'angle_deqp_gles2_tests', }, }, 'gpu_angle_deqp_gles2_vulkan_tests': { 'angle_deqp_gles2_vulkan_tests': { - 'swarming': { - 'shards': 4, - }, - 'test': 'angle_deqp_gles2_tests', + 'android_args': [ + '--enable-xml-result-parsing', + '--shard-timeout=500' + ], 'args': [ '--deqp-egl-display-type=angle-vulkan', ], 'desktop_args': [ '--test-launcher-batch-limit=400', ], - 'android_args': [ - '--enable-xml-result-parsing', - '--shard-timeout=500' - ], + 'should_retry_with_patch': False, + 'swarming': { + 'shards': 4, + }, + 'test': 'angle_deqp_gles2_tests', }, }, 'gpu_angle_deqp_gles31_d3d11_tests': { 'angle_deqp_gles31_d3d11_tests': { - 'swarming': { - 'shards': 6, - }, - 'test': 'angle_deqp_gles31_tests', 'args': [ '--test-launcher-batch-limit=400', '--deqp-egl-display-type=angle-d3d11' ], + 'should_retry_with_patch': False, + 'swarming': { + 'shards': 6, + }, + 'test': 'angle_deqp_gles31_tests', }, }, 'gpu_angle_deqp_gles31_gl_tests': { 'angle_deqp_gles31_gl_tests': { - 'swarming': { - 'shards': 6, - }, - 'test': 'angle_deqp_gles31_tests', 'args': [ '--test-launcher-batch-limit=400', '--deqp-egl-display-type=angle-gl' ], + 'should_retry_with_patch': False, + 'swarming': { + 'shards': 6, + }, + 'test': 'angle_deqp_gles31_tests', }, }, @@ -2941,52 +2950,58 @@ # Temporarily disabled on AMD Win 7 to prevent a recipe engine crash. # TODO(jmadill): Re-enable there when http://crbug.com/713196 is fixed. 'angle_deqp_gles3_d3d11_tests': { - 'swarming': { - 'shards': 12, - }, - 'test': 'angle_deqp_gles3_tests', 'args': [ '--test-launcher-batch-limit=400', '--deqp-egl-display-type=angle-d3d11', ], + 'should_retry_with_patch': False, + 'swarming': { + 'shards': 12, + }, + 'test': 'angle_deqp_gles3_tests', }, }, 'gpu_angle_deqp_gles3_gl_tests': { 'angle_deqp_gles3_gl_tests': { - 'swarming': { - 'shards': 12, - }, - 'test': 'angle_deqp_gles3_tests', 'args': [ '--test-launcher-batch-limit=400', '--deqp-egl-display-type=angle-gl', ], + 'should_retry_with_patch': False, + 'swarming': { + 'shards': 12, + }, + 'test': 'angle_deqp_gles3_tests', }, }, 'gpu_angle_deqp_gles_gtests': { 'angle_deqp_gles2_gles_tests': { - 'swarming': { - 'shards': 4, - }, - 'test': 'angle_deqp_gles2_tests', + 'android_args': [ + '--enable-xml-result-parsing', + '--shard-timeout=500' + ], 'args': [ '--deqp-egl-display-type=angle-gles' ], 'desktop_args': [ '--test-launcher-batch-limit=400', ], + 'should_retry_with_patch': False, + 'swarming': { + 'shards': 4, + }, + 'test': 'angle_deqp_gles2_tests', + }, + 'angle_deqp_gles3_gles_tests': { 'android_args': [ '--enable-xml-result-parsing', '--shard-timeout=500' ], - }, - 'angle_deqp_gles3_gles_tests': { - 'swarming': { - 'shards': 12, - }, - 'test': 'angle_deqp_gles3_tests', + 'args': [ + '--deqp-egl-display-type=angle-gles' + ], # Only pass the display type to desktop. The Android runner doesn't support # passing args to the executable but only one display type is supported on # Android anyways. @@ -2994,10 +3009,11 @@ '--test-launcher-batch-limit=400', '--deqp-egl-display-type=angle-gles' ], - 'android_args': [ - '--enable-xml-result-parsing', - '--shard-timeout=500' - ], + 'should_retry_with_patch': False, + 'swarming': { + 'shards': 12, + }, + 'test': 'angle_deqp_gles3_tests', }, }, @@ -3009,6 +3025,7 @@ # http://crbug.com/669196 '--test-launcher-retry-limit=0' ], + 'should_retry_with_patch': False, 'swarming': { 'shards': 4, }, @@ -3018,23 +3035,25 @@ 'gpu_angle_fyi_and_optional_win_specific_isolated_scripts': { # TODO(jmadill): Run on Linux bots when possible. 'passthrough_command_buffer_perftests': { - 'isolate_name': 'command_buffer_perftests', 'args': [ '-v', '--use-cmd-decoder=passthrough', '--use-angle=gl-null', '--fast-run', ], + 'isolate_name': 'command_buffer_perftests', + 'should_retry_with_patch': False, }, # TODO(jmadill): Run on Linux bots when possible. 'validating_command_buffer_perftests': { - 'isolate_name': 'command_buffer_perftests', 'args': [ '-v', '--use-cmd-decoder=validating', '--use-stub', '--fast-run', ], + 'isolate_name': 'command_buffer_perftests', + 'should_retry_with_patch': False, }, }, @@ -3047,6 +3066,7 @@ '--test-launcher-retry-limit=0' ], 'linux_args': ['--no-xvfb'], + 'should_retry_with_patch': False, }, }, @@ -3060,6 +3080,7 @@ # http://crbug.com/669196 '--test-launcher-retry-limit=0' ], + 'should_retry_with_patch': False, }, },
diff --git a/testing/libfuzzer/fuzzer_test.gni b/testing/libfuzzer/fuzzer_test.gni index ec4858ad..28fc2efb 100644 --- a/testing/libfuzzer/fuzzer_test.gni +++ b/testing/libfuzzer/fuzzer_test.gni
@@ -4,7 +4,6 @@ # Defines fuzzer_test. # -import("//build/config/coverage/coverage.gni") import("//build/config/features.gni") import("//build/config/sanitizers/sanitizers.gni") import("//testing/test.gni") @@ -36,10 +35,6 @@ # config (.options file) file would be generated or modified in root output # dir (next to test). template("fuzzer_test") { - assert(!(is_mac && use_clang_coverage && use_fuzzing_engine), - "Code Coverage for fuzz targets does not work on Mac until " + - "crbug.com/790747 is resolved.") - if (!disable_libfuzzer && (use_fuzzing_engine || use_drfuzz || is_linux)) { assert(defined(invoker.sources), "Need sources in $target_name.")
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 683cd19f..53c48ef 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1769,23 +1769,6 @@ ] } ], - "EnableEmojiContextMenu": [ - { - "platforms": [ - "chromeos", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "EnableEmojiContextMenu" - ] - } - ] - } - ], "EnableMediaRouter": [ { "platforms": [ @@ -3645,6 +3628,21 @@ ] } ], + "PredictivePrefetchingAllowedOnAllConnectionTypes": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "PredictivePrefetchingAllowedOnAllConnectionTypes", + "enable_features": [ + "PredictivePrefetchingAllowedOnAllConnectionTypes" + ] + } + ] + } + ], "PreviewsClientLoFi": [ { "platforms": [
diff --git a/third_party/blink/public/platform/web_url_response.h b/third_party/blink/public/platform/web_url_response.h index f7b605a..07a284a 100644 --- a/third_party/blink/public/platform/web_url_response.h +++ b/third_party/blink/public/platform/web_url_response.h
@@ -254,10 +254,6 @@ // Returns true if the URL list is not empty. BLINK_PLATFORM_EXPORT bool HasUrlListViaServiceWorker() const; - // The boundary of the response. Set only when this is a multipart response. - BLINK_PLATFORM_EXPORT void SetMultipartBoundary(const char* bytes, - size_t /* size */); - // The cache name of the CacheStorage from where the response is served via // the ServiceWorker. Null if the response isn't from the CacheStorage. BLINK_PLATFORM_EXPORT void SetCacheStorageCacheName(const WebString&);
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 112026b..1dd75cc 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -2021,6 +2021,7 @@ "layout/layout_table_row_test.cc", "layout/layout_table_section_test.cc", "layout/layout_table_test.cc", + "layout/layout_text_control_single_line_test.cc", "layout/layout_text_control_test.cc", "layout/layout_text_fragment_test.cc", "layout/layout_text_test.cc",
diff --git a/third_party/blink/renderer/core/core_idl_files.gni b/third_party/blink/renderer/core/core_idl_files.gni index 994710a5..eeb7e174 100644 --- a/third_party/blink/renderer/core/core_idl_files.gni +++ b/third_party/blink/renderer/core/core_idl_files.gni
@@ -288,6 +288,7 @@ "html/media/html_audio_element.idl", "html/media/media_error.idl", "html/portal/html_portal_element.idl", + "html/portal/portal_host.idl", "html/track/audio_track_list.idl", "html/track/html_track_element.idl", "html/track/text_track.idl", @@ -545,6 +546,7 @@ "fullscreen/document_fullscreen.idl", "fullscreen/element_fullscreen.idl", "html/html_hyperlink_element_utils.idl", + "html/portal/window_portal_host.idl", "layout/custom/css_layout_worklet.idl", "svg/svg_document.idl", "svg/svg_filter_primitive_standard_attributes.idl",
diff --git a/third_party/blink/renderer/core/html/BUILD.gn b/third_party/blink/renderer/core/html/BUILD.gn index ac776d1..bb0fd6fad 100644 --- a/third_party/blink/renderer/core/html/BUILD.gn +++ b/third_party/blink/renderer/core/html/BUILD.gn
@@ -511,8 +511,11 @@ "plugin_document.h", "portal/document_portals.cc", "portal/document_portals.h", + "portal/dom_window_portal_host.cc", + "portal/dom_window_portal_host.h", "portal/html_portal_element.cc", "portal/html_portal_element.h", + "portal/portal_host.h", "rel_list.cc", "rel_list.h", "shadow/details_marker_control.cc",
diff --git a/third_party/blink/renderer/core/html/portal/dom_window_portal_host.cc b/third_party/blink/renderer/core/html/portal/dom_window_portal_host.cc new file mode 100644 index 0000000..85e3cc5 --- /dev/null +++ b/third_party/blink/renderer/core/html/portal/dom_window_portal_host.cc
@@ -0,0 +1,14 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/html/portal/dom_window_portal_host.h" + +namespace blink { + +// static +PortalHost* DOMWindowPortalHost::portalHost(LocalDOMWindow& window) { + return nullptr; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/html/portal/dom_window_portal_host.h b/third_party/blink/renderer/core/html/portal/dom_window_portal_host.h new file mode 100644 index 0000000..96e0154 --- /dev/null +++ b/third_party/blink/renderer/core/html/portal/dom_window_portal_host.h
@@ -0,0 +1,22 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_DOM_WINDOW_PORTAL_HOST_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_DOM_WINDOW_PORTAL_HOST_H_ + +#include "third_party/blink/renderer/core/core_export.h" + +namespace blink { + +class LocalDOMWindow; +class PortalHost; + +class CORE_EXPORT DOMWindowPortalHost { + public: + static PortalHost* portalHost(LocalDOMWindow& window); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_DOM_WINDOW_PORTAL_HOST_H_
diff --git a/third_party/blink/renderer/core/html/portal/portal_host.h b/third_party/blink/renderer/core/html/portal/portal_host.h new file mode 100644 index 0000000..f4066072 --- /dev/null +++ b/third_party/blink/renderer/core/html/portal/portal_host.h
@@ -0,0 +1,19 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_PORTAL_HOST_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_PORTAL_HOST_H_ + +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/dom/events/event_target.h" + +namespace blink { + +class CORE_EXPORT PortalHost : public EventTargetWithInlineData { + DEFINE_WRAPPERTYPEINFO(); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_PORTAL_HOST_H_
diff --git a/third_party/blink/renderer/core/html/portal/portal_host.idl b/third_party/blink/renderer/core/html/portal/portal_host.idl new file mode 100644 index 0000000..7d972d0 --- /dev/null +++ b/third_party/blink/renderer/core/html/portal/portal_host.idl
@@ -0,0 +1,8 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://wicg.github.io/portals/#the-portalhost-interface + +[RuntimeEnabled=Portals] +interface PortalHost : EventTarget {};
diff --git a/third_party/blink/renderer/core/html/portal/window_portal_host.idl b/third_party/blink/renderer/core/html/portal/window_portal_host.idl new file mode 100644 index 0000000..becf8ac7 --- /dev/null +++ b/third_party/blink/renderer/core/html/portal/window_portal_host.idl
@@ -0,0 +1,11 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://wicg.github.io/portals/#miscellaneous-extensions + +[ + ImplementedAs=DOMWindowPortalHost +] partial interface Window { + [RuntimeEnabled=Portals] readonly attribute PortalHost? portalHost; +};
diff --git a/third_party/blink/renderer/core/layout/layout_table.cc b/third_party/blink/renderer/core/layout/layout_table.cc index 25deec9..3300d6a 100644 --- a/third_party/blink/renderer/core/layout/layout_table.cc +++ b/third_party/blink/renderer/core/layout/layout_table.cc
@@ -925,6 +925,7 @@ void LayoutTable::ComputeVisualOverflow(bool) { LayoutRect previous_visual_overflow_rect = VisualOverflowRect(); + ClearVisualOverflow(); AddVisualOverflowFromChildren(); AddVisualEffectOverflow();
diff --git a/third_party/blink/renderer/core/layout/layout_table_test.cc b/third_party/blink/renderer/core/layout/layout_table_test.cc index d43c46e..2e6b9d1 100644 --- a/third_party/blink/renderer/core/layout/layout_table_test.cc +++ b/third_party/blink/renderer/core/layout/layout_table_test.cc
@@ -319,6 +319,24 @@ table->BottomNonEmptySection()); } +TEST_F(LayoutTableTest, VisualOverflowCleared) { + SetBodyInnerHTML(R"HTML( + <style> + #table { + width: 50px; height: 50px; box-shadow: 5px 5px 5px black; + } + </style> + <table id='table' style='width: 50px; height: 50px'></table> + )HTML"); + auto* table = GetTableByElementId("table"); + EXPECT_EQ(LayoutRect(-3, -3, 66, 66), table->SelfVisualOverflowRect()); + ToElement(table->GetNode()) + ->setAttribute(html_names::kStyleAttr, "box-shadow: initial"); + GetDocument().View()->UpdateAllLifecyclePhases( + DocumentLifecycle::LifecycleUpdateReason::kTest); + EXPECT_EQ(LayoutRect(0, 0, 50, 50), table->SelfVisualOverflowRect()); +} + } // anonymous namespace } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc b/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc index 375d0a3..173ea71a 100644 --- a/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc +++ b/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc
@@ -321,6 +321,7 @@ void LayoutTextControlSingleLine::ComputeVisualOverflow( bool recompute_floats) { LayoutRect previous_visual_overflow_rect = VisualOverflowRect(); + ClearVisualOverflow(); AddVisualOverflowFromChildren(); AddVisualEffectOverflow();
diff --git a/third_party/blink/renderer/core/layout/layout_text_control_single_line_test.cc b/third_party/blink/renderer/core/layout/layout_text_control_single_line_test.cc new file mode 100644 index 0000000..5624741 --- /dev/null +++ b/third_party/blink/renderer/core/layout/layout_text_control_single_line_test.cc
@@ -0,0 +1,45 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/layout/layout_text_control_single_line.h" + +#include "build/build_config.h" +#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" + +namespace blink { + +namespace { + +class LayoutTextControlSingleLineTest : public RenderingTest {}; + +TEST_F(LayoutTextControlSingleLineTest, VisualOverflowCleared) { + SetBodyInnerHTML(R"HTML( + <style> + #input { + width: 50px; height: 50px; box-shadow: 5px 5px 5px black; + } + </style> + <input id=input type="text"></input. + )HTML"); + auto* input = + ToLayoutTextControlSingleLine(GetLayoutObjectByElementId("input")); +#if defined(OS_MACOSX) + EXPECT_EQ(LayoutRect(-3, -3, 72, 72), input->SelfVisualOverflowRect()); +#else + EXPECT_EQ(LayoutRect(-3, -3, 70, 72), input->SelfVisualOverflowRect()); +#endif + ToElement(input->GetNode()) + ->setAttribute(html_names::kStyleAttr, "box-shadow: initial"); + GetDocument().View()->UpdateAllLifecyclePhases( + DocumentLifecycle::LifecycleUpdateReason::kTest); +#if defined(OS_MACOSX) + EXPECT_EQ(LayoutRect(0, 0, 56, 56), input->SelfVisualOverflowRect()); +#else + EXPECT_EQ(LayoutRect(0, 0, 54, 56), input->SelfVisualOverflowRect()); +#endif +} + +} // anonymous namespace + +} // namespace blink
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource.cc b/third_party/blink/renderer/core/loader/resource/image_resource.cc index 9599ff2..651e85b 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource.cc +++ b/third_party/blink/renderer/core/loader/resource/image_resource.cc
@@ -44,6 +44,7 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h" #include "third_party/blink/renderer/platform/network/http_parsers.h" +#include "third_party/blink/renderer/platform/network/network_utils.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/shared_buffer.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" @@ -482,10 +483,14 @@ std::unique_ptr<WebDataConsumerHandle> handle) { DCHECK(!handle); DCHECK(!multipart_parser_); - // If there's no boundary, just handle the request normally. - if (response.IsMultipart() && !response.MultipartBoundary().IsEmpty()) { - multipart_parser_ = MakeGarbageCollected<MultipartImageResourceParser>( - response, response.MultipartBoundary(), this); + if (response.MimeType() == "multipart/x-mixed-replace") { + Vector<char> boundary = network_utils::ParseMultipartBoundary( + response.HttpHeaderField(http_names::kContentType)); + // If there's no boundary, just handle the request normally. + if (!boundary.IsEmpty()) { + multipart_parser_ = MakeGarbageCollected<MultipartImageResourceParser>( + response, boundary, this); + } } // Notify the base class that a response has been received. Note that after
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_test.cc b/third_party/blink/renderer/core/loader/resource/image_resource_test.cc index f2433f1..5bfd163 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource_test.cc +++ b/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
@@ -377,7 +377,8 @@ // flagged as multipart. ResourceResponse multipart_response(NullURL()); multipart_response.SetMimeType("multipart/x-mixed-replace"); - multipart_response.SetMultipartBoundary("boundary", strlen("boundary")); + multipart_response.SetHTTPHeaderField( + http_names::kContentType, "multipart/x-mixed-replace; boundary=boundary"); image_resource->Loader()->DidReceiveResponse( WrappedResourceResponse(multipart_response), nullptr); EXPECT_FALSE(image_resource->ResourceBuffer()); @@ -457,7 +458,8 @@ ResourceResponse multipart_response(NullURL()); multipart_response.SetMimeType("multipart/x-mixed-replace"); - multipart_response.SetMultipartBoundary("boundary", strlen("boundary")); + multipart_response.SetHTTPHeaderField( + http_names::kContentType, "multipart/x-mixed-replace; boundary=boundary"); image_resource->Loader()->DidReceiveResponse( WrappedResourceResponse(multipart_response), nullptr); EXPECT_FALSE(image_resource->GetContent()->HasImage());
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 152ba0a4..4ed152e 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
@@ -198,22 +198,12 @@ is_main_frame_layout_view_layer_ = true; CreatePrimaryGraphicsLayer(); - - // ImagePainter has a micro-optimization to embed object-fit and clip into - // the drawing so the property nodes were omitted if not composited. - if (GetLayoutObject().IsLayoutImage()) - GetLayoutObject().SetNeedsPaintPropertyUpdate(); } CompositedLayerMapping::~CompositedLayerMapping() { // Hits in compositing/squashing/squash-onto-nephew.html. DisableCompositingQueryAsserts disabler; - // ImagePainter has a micro-optimization to embed object-fit and clip into - // the drawing so the property nodes should be omitted if not composited. - if (GetLayoutObject().IsLayoutImage()) - GetLayoutObject().SetNeedsPaintPropertyUpdate(); - // Do not leave the destroyed pointer dangling on any Layers that painted to // this mapping's squashing layer. for (wtf_size_t i = 0; i < squashed_layers_.size(); ++i) {
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc index 53dcd18..242ae6f 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
@@ -76,14 +76,16 @@ geometry_map_.PushMappingsToAncestor(layer, layer->Parent()); - PaintLayer* enclosing_composited_layer = info.enclosing_composited_layer; + PaintLayer* enclosing_stacking_composited_layer = + info.enclosing_stacking_composited_layer; PaintLayer* enclosing_squashing_composited_layer = info.enclosing_squashing_composited_layer; switch (layer->GetCompositingState()) { case kNotComposited: break; case kPaintsIntoOwnBacking: - enclosing_composited_layer = layer; + if (layer->GetLayoutObject().StyleRef().IsStackingContext()) + enclosing_stacking_composited_layer = layer; break; case kPaintsIntoGroupedBacking: enclosing_squashing_composited_layer = @@ -92,8 +94,8 @@ } if (layer->NeedsCompositingInputsUpdate()) { - if (enclosing_composited_layer) { - enclosing_composited_layer->GetCompositedLayerMapping() + if (enclosing_stacking_composited_layer) { + enclosing_stacking_composited_layer->GetCompositedLayerMapping() ->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree); } if (enclosing_squashing_composited_layer) { @@ -117,7 +119,8 @@ if (update_type == kForceUpdate) UpdateAncestorDependentCompositingInputs(layer, info); - info.enclosing_composited_layer = enclosing_composited_layer; + info.enclosing_stacking_composited_layer = + enclosing_stacking_composited_layer; info.enclosing_squashing_composited_layer = enclosing_squashing_composited_layer;
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h index 8510932..04fbc010 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h +++ b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h
@@ -32,7 +32,8 @@ }; struct AncestorInfo { - PaintLayer* enclosing_composited_layer = nullptr; + // The ancestor composited PaintLayer which is also a stacking context. + PaintLayer* enclosing_stacking_composited_layer = nullptr; // A "squashing composited layer" is a PaintLayer that owns a squashing // layer. This variable stores the squashing composited layer for the // nearest PaintLayer ancestor which is squashed.
diff --git a/third_party/blink/renderer/core/paint/embedded_object_painter.cc b/third_party/blink/renderer/core/paint/embedded_object_painter.cc index 8af38df..e506970c 100644 --- a/third_party/blink/renderer/core/paint/embedded_object_painter.cc +++ b/third_party/blink/renderer/core/paint/embedded_object_painter.cc
@@ -12,7 +12,6 @@ #include "third_party/blink/renderer/platform/fonts/font.h" #include "third_party/blink/renderer/platform/fonts/font_selector.h" #include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h" -#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h" #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h" #include "third_party/blink/renderer/platform/graphics/path.h" #include "third_party/blink/renderer/platform/text/text_run.h" @@ -55,8 +54,6 @@ LayoutRect content_rect(layout_embedded_object_.PhysicalContentBoxRect()); content_rect.MoveBy(paint_offset); DrawingRecorder recorder(context, layout_embedded_object_, paint_info.phase); - GraphicsContextStateSaver state_saver(context); - context.Clip(PixelSnappedIntRect(content_rect)); Font font = ReplacementTextFont(); const SimpleFontData* font_data = font.PrimaryFont();
diff --git a/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc b/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc index a40b3a9..53f6c8f 100644 --- a/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc +++ b/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
@@ -1075,9 +1075,7 @@ NonCompositedInvalidationChangeOpacity) { // This test runs in a non-composited mode, so invalidations should // be issued via InvalidateChromeClient. - SetBodyInnerHTML(R"HTML( - <div id=target style="opacity: 0.99"></div> - )HTML"); + SetBodyInnerHTML("<div id=target style='opacity: 0.99'></div>"); auto* target = GetDocument().getElementById("target"); ASSERT_TRUE(target); @@ -1090,4 +1088,26 @@ EXPECT_TRUE(InvalidationRecorded()); } +TEST_F(PaintInvalidatorCustomClientTest, + NoInvalidationRepeatedUpdateLifecyleExceptPaint) { + SetBodyInnerHTML("<div id=target style='opacity: 0.99'></div>"); + + auto* target = GetDocument().getElementById("target"); + ASSERT_TRUE(target); + ResetInvalidationRecorded(); + + target->setAttribute(html_names::kStyleAttr, "opacity: 0.98"); + GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); + EXPECT_TRUE(GetDocument().View()->GetLayoutView()->Layer()->NeedsRepaint()); + EXPECT_TRUE(InvalidationRecorded()); + + ResetInvalidationRecorded(); + // Let PrePaintTreeWalk do something instead of no-op. + GetDocument().View()->SetNeedsPaintPropertyUpdate(); + GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); + // The layer NeedsRepaint flag is only cleared after paint. + EXPECT_TRUE(GetDocument().View()->GetLayoutView()->Layer()->NeedsRepaint()); + EXPECT_FALSE(InvalidationRecorded()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.cc b/third_party/blink/renderer/core/paint/paint_invalidator.cc index 4439a51..f554d4e0 100644 --- a/third_party/blink/renderer/core/paint/paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -16,7 +16,6 @@ #include "third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset_rect.h" #include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h" -#include "third_party/blink/renderer/core/page/chrome_client.h" #include "third_party/blink/renderer/core/paint/clip_path_clipper.h" #include "third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h" #include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h" @@ -249,13 +248,14 @@ context.paint_invalidation_container_for_stacked_contents = ToLayoutBoxModelObject(&object); } else if (object.IsLayoutView()) { - // paintInvalidationContainerForStackedContents is only for stacked + // paint_invalidation_container_for_stacked_contents is only for stacked // descendants in its own frame, because it doesn't establish stacking // context for stacked contents in sub-frames. // Contents stacked in the root stacking context in this frame should use - // this frame's paintInvalidationContainer. + // this frame's PaintInvalidationContainer. context.paint_invalidation_container_for_stacked_contents = - context.paint_invalidation_container; + context.paint_invalidation_container = + &object.ContainerForPaintInvalidation(); } else if (object.IsColumnSpanAll() || object.IsFloatingWithNonContainingBlockParent()) { // In these cases, the object may belong to an ancestor of the current @@ -368,44 +368,6 @@ } } -void PaintInvalidator::InvalidatePaint( - LocalFrameView& frame_view, - const PaintPropertyTreeBuilderContext* tree_builder_context, - - PaintInvalidatorContext& context) { - LayoutView* layout_view = frame_view.GetLayoutView(); - CHECK(layout_view); - - context.paint_invalidation_container = - context.paint_invalidation_container_for_stacked_contents = - &layout_view->ContainerForPaintInvalidation(); - context.painting_layer = layout_view->Layer(); - context.fragment_data = &layout_view->FirstFragment(); - if (tree_builder_context) { - context.tree_builder_context_ = &tree_builder_context->fragments[0]; -#if DCHECK_IS_ON() - context.tree_builder_context_actually_needed_ = - tree_builder_context->is_actually_needed; -#endif - } -} - -static void InvalidateChromeClient( - const LayoutBoxModelObject& paint_invalidation_container) { - if (paint_invalidation_container.GetDocument().Printing() && - !RuntimeEnabledFeatures::PrintBrowserEnabled()) - return; - - DCHECK(paint_invalidation_container.IsLayoutView()); - DCHECK(!paint_invalidation_container.IsPaintInvalidationContainer()); - - auto* frame_view = paint_invalidation_container.GetFrameView(); - DCHECK(!frame_view->GetFrame().OwnerLayoutObject()); - if (auto* client = frame_view->GetChromeClient()) { - client->InvalidateRect(IntRect(IntPoint(), frame_view->Size())); - } -} - void PaintInvalidator::UpdateEmptyVisualRectFlag( const LayoutObject& object, PaintInvalidatorContext& context) { @@ -428,7 +390,7 @@ } } -void PaintInvalidator::InvalidatePaint( +bool PaintInvalidator::InvalidatePaint( const LayoutObject& object, const PaintPropertyTreeBuilderContext* tree_builder_context, PaintInvalidatorContext& context) { @@ -436,11 +398,11 @@ "PaintInvalidator::InvalidatePaint()", "object", object.DebugName().Ascii()); - if (object.IsSVGHiddenContainer()) { + if (object.IsSVGHiddenContainer()) context.subtree_flags |= PaintInvalidatorContext::kSubtreeNoInvalidation; - } + if (context.subtree_flags & PaintInvalidatorContext::kSubtreeNoInvalidation) - return; + return false; object.GetMutableForPainting().EnsureIsReadyForPaintInvalidation(); @@ -460,7 +422,7 @@ UpdateEmptyVisualRectFlag(object, context); if (!object.ShouldCheckForPaintInvalidation() && !context.NeedsSubtreeWalk()) - return; + return false; unsigned tree_builder_index = 0; @@ -532,14 +494,7 @@ PaintInvalidatorContext::kSubtreeInvalidationChecking; } - // The object is under a frame for WebViewPlugin, SVG images etc. Need to - // inform the chrome client of the invalidation so that the client will - // initiate painting of the contents. - // TODO(wangxianzhu): Do we need this for CAP? - if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && - !context.paint_invalidation_container->IsPaintInvalidationContainer() && - reason != PaintInvalidationReason::kNone) - InvalidateChromeClient(*context.paint_invalidation_container); + return reason != PaintInvalidationReason::kNone; } void PaintInvalidator::ProcessPendingDelayedPaintInvalidations() {
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.h b/third_party/blink/renderer/core/paint/paint_invalidator.h index cabfa006..870bc8a 100644 --- a/third_party/blink/renderer/core/paint/paint_invalidator.h +++ b/third_party/blink/renderer/core/paint/paint_invalidator.h
@@ -138,10 +138,8 @@ class PaintInvalidator { public: - void InvalidatePaint(LocalFrameView&, - const PaintPropertyTreeBuilderContext*, - PaintInvalidatorContext&); - void InvalidatePaint(const LayoutObject&, + // Returns true if the object is invalidated. + bool InvalidatePaint(const LayoutObject&, const PaintPropertyTreeBuilderContext*, PaintInvalidatorContext&);
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 82e84a7d..342a288 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -1255,6 +1255,9 @@ return !ToLocalFrame(parent_frame)->GetDocument()->Printing(); } +// TODO(wangxianzhu): Combine the logic by overriding LayoutBox:: +// ComputeShouldClipOverflow() in LayoutReplaced and subclasses and remove +// this function. static bool NeedsOverflowClipForReplacedContents( const LayoutReplaced& replaced) { // <svg> may optionally allow overflow. If an overflow clip is required, @@ -1262,18 +1265,17 @@ if (replaced.IsSVGRoot()) return ToLayoutSVGRoot(replaced).ShouldApplyViewportClip(); + // A replaced element with border-radius always clips the content. if (replaced.StyleRef().HasBorderRadius()) return true; - // Non-composited images have a micro-optimization to embed clip rects into - // the drawings instead of using a clip node. - bool is_spv1_composited = - replaced.HasLayer() && replaced.Layer()->GetCompositedLayerMapping(); - if (replaced.IsImage() && !is_spv1_composited) + // ImagePainter (but not painters for LayoutMedia whose IsImage is also true) + // won't paint outside of the content box. + if (replaced.IsImage() && !replaced.IsMedia()) return false; - // Embedded objects are always sized to fit the content rect. - if (replaced.IsLayoutEmbeddedContent()) + // Non-plugin embedded contents are always sized to fit the content box. + if (replaced.IsLayoutEmbeddedContent() && !replaced.IsEmbeddedObject()) return false; return true; @@ -1416,12 +1418,6 @@ return false; const auto& block = ToLayoutBlock(object); - // This is a heuristic to avoid costly paint property subtree rebuild on - // CanOmitOverflowClip() changes, e.g. on selection. This also avoids omitting - // overflow clip when there is any self-painting descendant which is not - // covered by ContentsVisualOverflowRect(). - if (block.HasLayer() && block.Layer()->FirstChild()) - return false; // Selection may overflow. if (block.IsSelected()) return false; @@ -1430,15 +1426,6 @@ if (block.HasControlClip() || block.ShouldPaintCarets()) return false; - if (object.IsLayoutReplaced()) { - const LayoutReplaced& replaced = ToLayoutReplaced(object); - if (replaced.StyleRef().HasBorderRadius()) - return false; - LayoutRect replaced_content_rect = replaced.ReplacedContentRect(); - return replaced_content_rect.IsEmpty() || - replaced.PhysicalContentBoxRect().Contains(replaced_content_rect); - } - // We need OverflowClip for hit-testing if the clip rect excluding overlay // scrollbars is different from the normal clip rect. auto clip_rect = block.OverflowClipRect(LayoutPoint()); @@ -1446,7 +1433,19 @@ LayoutPoint(), kExcludeOverlayScrollbarSizeForHitTesting); if (clip_rect != clip_rect_excluding_overlay_scrollbars) return false; - return clip_rect.Contains(block.ContentsVisualOverflowRect()); + + // Visual overflow extending beyond the clip rect must be clipped. + // ContentsVisualOverflowRect() does not include self-painting descendants + // (see comment above |BoxOverflowModel|) so, as a simplification, do not + // omit the clip if there are any PaintLayer descendants. + if (block.HasLayer() && block.Layer()->FirstChild()) + return false; + if (!clip_rect.Contains(block.ContentsVisualOverflowRect())) + return false; + + // Content can scroll, and needs to be clipped, if the layout overflow extends + // beyond the clip rect. + return clip_rect.Contains(block.LayoutOverflowRect()); } void FragmentPaintPropertyTreeBuilder::UpdateOverflowClip() {
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc index 33fed0f1..cc4412ab 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -1537,6 +1537,26 @@ EXPECT_EQ(nullptr, properties2); } +TEST_P(PaintPropertyTreeBuilderTest, OverflowClipWithEmptyVisualOverflow) { + SetBodyInnerHTML(R"HTML( + <style> + body { margin: 0 } + ::-webkit-scrollbar { + width: 10px; + height: 10px; + } + </style> + <div id='container' style='width: 100px; height: 100px; + will-change: transform; overflow: scroll; background: lightblue;'> + <div id='forcescroll' style='width: 0; height: 400px;'></div> + </div> + )HTML"); + + const auto* clip = PaintPropertiesForElement("container")->OverflowClip(); + EXPECT_NE(nullptr, clip); + EXPECT_EQ(FloatRect(0, 0, 90, 90), clip->ClipRect().Rect()); +} + TEST_P(PaintPropertyTreeBuilderTest, PaintOffsetTranslationSVGHTMLBoundaryMulticol) { SetBodyInnerHTML(R"HTML( @@ -6093,52 +6113,6 @@ EXPECT_EQ(LayoutPoint(100, 85), paint_offset("float-right-rtl-vlr")); } -TEST_P(PaintPropertyTreeBuilderTest, ClipInvalidationForReplacedElement) { - // Non-composited LayoutImage has a micro-optimization to embed object-fit - // and clip to the drawing, thus not creating nodes. - // CAP makes everything non-composited essentially. - if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) - return; - // This test verifies clip nodes are correctly updated in response to - // content box mutation. - SetBodyInnerHTML(R"HTML( - <style> - img { - box-sizing: border-box; - width: 8px; - height: 8px; - object-fit: none; - will-change: transform; - } - </style> - <!-- An image of 10x10 white pixels. --> - <img id="target" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAA - AAKCAIAAAACUFjqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gcVABQvx8CBmA - AAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFUlEQVQY02P - 8//8/A27AxIAXjFRpAKXjAxH/0Dm5AAAAAElFTkSuQmCC"/> - )HTML"); - - { - const auto* properties = PaintPropertiesForElement("target"); - ASSERT_TRUE(properties); - ASSERT_TRUE(properties->OverflowClip()); - EXPECT_EQ(FloatRect(0, 0, 8, 8), - properties->OverflowClip()->ClipRect().Rect()); - } - - GetDocument().getElementById("target")->setAttribute( - html_names::kStyleAttr, "padding: 1px 2px 3px 4px;"); - UpdateAllLifecyclePhasesForTest(); - - { - const auto* properties = PaintPropertiesForElement("target"); - ASSERT_TRUE(properties); - ASSERT_TRUE(properties->OverflowClip()); - EXPECT_EQ(FloatRect(4, 1, 2, 4), - properties->OverflowClip()->ClipRect().Rect()); - } -} - TEST_P(PaintPropertyTreeBuilderTest, SubpixelPositionedScrollNode) { SetBodyInnerHTML(R"HTML( <!DOCTYPE html>
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc index d236377a..39c20eb 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
@@ -1409,6 +1409,128 @@ svg2_properties->PaintOffsetTranslation())); } +TEST_P(PaintPropertyTreeUpdateTest, OverflowClipUpdateForImage) { + // This test verifies clip nodes are correctly updated in response to + // content box mutation. + SetBodyInnerHTML(R"HTML( + <style> + img { + box-sizing: border-box; + width: 8px; + height: 8px; + } + </style> + <!-- An image of 10x10 white pixels. --> + <img id="target" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAA + AAKCAIAAAACUFjqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gcVABQvx8CBmA + AAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFUlEQVQY02P + 8//8/A27AxIAXjFRpAKXjAxH/0Dm5AAAAAElFTkSuQmCC"> + )HTML"); + + auto* target = GetDocument().getElementById("target"); + const auto* properties = PaintPropertiesForElement("target"); + // We don't need paint properties for object-fit: fill because the content + // never overflows. + EXPECT_EQ(nullptr, properties); + + target->setAttribute(html_names::kStyleAttr, "object-fit: cover"); + UpdateAllLifecyclePhasesForTest(); + properties = PaintPropertiesForElement("target"); + // We don't need paint properties because image painter always clip to the + // content box. + EXPECT_EQ(nullptr, properties); + + target->setAttribute(html_names::kStyleAttr, "object-fit: none"); + UpdateAllLifecyclePhasesForTest(); + properties = PaintPropertiesForElement("target"); + // Ditto. + EXPECT_EQ(nullptr, properties); + + // We need overflow clip when there is border radius. + target->setAttribute(html_names::kStyleAttr, + "object-fit: none; border-radius: 2px"); + UpdateAllLifecyclePhasesForTest(); + properties = PaintPropertiesForElement("target"); + ASSERT_TRUE(properties); + ASSERT_TRUE(properties->OverflowClip()); + FloatSize corner(2, 2); + FloatRoundedRect::Radii radii(corner, corner, corner, corner); + EXPECT_EQ(FloatRoundedRect(FloatRect(8, 8, 8, 8), radii), + properties->OverflowClip()->ClipRect()); + + // We should update clip rect on border radius change. + target->setAttribute(html_names::kStyleAttr, + "object-fit: none; border-radius: 3px"); + UpdateAllLifecyclePhasesForTest(); + ASSERT_EQ(properties, PaintPropertiesForElement("target")); + ASSERT_TRUE(properties->OverflowClip()); + radii.Expand(1); + EXPECT_EQ(FloatRoundedRect(FloatRect(8, 8, 8, 8), radii), + properties->OverflowClip()->ClipRect()); + + // We should update clip rect on padding change. + target->setAttribute( + html_names::kStyleAttr, + "object-fit: none; border-radius: 3px; padding: 1px 2px 3px 4px"); + UpdateAllLifecyclePhasesForTest(); + ASSERT_EQ(properties, PaintPropertiesForElement("target")); + ASSERT_TRUE(properties->OverflowClip()); + // The rounded clip rect is the intersection of the rounded inner border + // rect and the content box rect. + EXPECT_EQ( + FloatRoundedRect(FloatRect(12, 9, 2, 4), + FloatRoundedRect::Radii(FloatSize(0, 2), FloatSize(1, 2), + FloatSize(), FloatSize(1, 0))), + properties->OverflowClip()->ClipRect()); +} + +TEST_P(PaintPropertyTreeUpdateTest, OverflowClipUpdateForVideo) { + // This test verifies clip nodes are correctly updated in response to + // content box mutation. + SetBodyInnerHTML(R"HTML( + <style> + video { + box-sizing: border-box; + width: 8px; + height: 8px; + } + </style> + <video id="target"></video> + )HTML"); + + auto* target = GetDocument().getElementById("target"); + const auto* properties = PaintPropertiesForElement("target"); + // We always create overflow clip for video regardless of object-fit. + ASSERT_TRUE(properties); + ASSERT_TRUE(properties->OverflowClip()); + EXPECT_EQ(FloatRoundedRect(8, 8, 8, 8), + properties->OverflowClip()->ClipRect()); + + target->setAttribute(html_names::kStyleAttr, "object-fit: cover"); + UpdateAllLifecyclePhasesForTest(); + ASSERT_EQ(properties, PaintPropertiesForElement("target")); + ASSERT_TRUE(properties->OverflowClip()); + EXPECT_EQ(FloatRoundedRect(8, 8, 8, 8), + properties->OverflowClip()->ClipRect()); + + // We need OverflowClip for object-fit: cover, too. + target->setAttribute(html_names::kStyleAttr, "object-fit: none"); + UpdateAllLifecyclePhasesForTest(); + ASSERT_EQ(properties, PaintPropertiesForElement("target")); + ASSERT_TRUE(properties->OverflowClip()); + EXPECT_EQ(FloatRoundedRect(8, 8, 8, 8), + properties->OverflowClip()->ClipRect()); + + // We should update clip rect on padding change. + target->setAttribute(html_names::kStyleAttr, + "object-fit: none; padding: 1px 2px 3px 4px"); + UpdateAllLifecyclePhasesForTest(); + ASSERT_EQ(properties, PaintPropertiesForElement("target")); + ASSERT_TRUE(properties->OverflowClip()); + EXPECT_EQ(FloatRoundedRect(12, 9, 2, 4), + properties->OverflowClip()->ClipRect()); +} + TEST_P(PaintPropertyTreeUpdateTest, ChangingClipPath) { GetDocument().GetSettings()->SetPreferCompositingToLCDTextEnabled(false); SetBodyInnerHTML(R"HTML(
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc index b8e0e9f..f19485f 100644 --- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc +++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -16,6 +16,7 @@ #include "third_party/blink/renderer/core/layout/layout_embedded_content.h" #include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h" #include "third_party/blink/renderer/core/layout/layout_view.h" +#include "third_party/blink/renderer/core/page/chrome_client.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h" #include "third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.h" @@ -68,6 +69,13 @@ if (VLOG_IS_ON(1)) showAllPropertyTrees(root_frame_view); #endif + + // If the frame is invalidated, we need to inform the frame's chrome client + // so that the client will initiate repaint of the contents. + if (needs_invalidate_chrome_client_) { + if (auto* client = root_frame_view.GetChromeClient()) + client->InvalidateRect(IntRect(IntPoint(), root_frame_view.Size())); + } } void PrePaintTreeWalk::Walk(LocalFrameView& frame_view) { @@ -107,11 +115,6 @@ if (context().tree_builder_context) { PaintPropertyTreeBuilder::SetupContextForFrame( frame_view, *context().tree_builder_context); - } - paint_invalidator_.InvalidatePaint( - frame_view, base::OptionalOrNullptr(context().tree_builder_context), - context().paint_invalidator_context); - if (context().tree_builder_context) { context().tree_builder_context->supports_composited_raster_invalidation = frame_view.GetFrame().GetSettings()->GetAcceleratedCompositingEnabled(); } @@ -339,9 +342,10 @@ // depends on the effective whitelisted touch action. UpdateEffectiveWhitelistedTouchAction(object, context); - paint_invalidator_.InvalidatePaint( - object, base::OptionalOrNullptr(context.tree_builder_context), - paint_invalidator_context); + if (paint_invalidator_.InvalidatePaint( + object, base::OptionalOrNullptr(context.tree_builder_context), + paint_invalidator_context)) + needs_invalidate_chrome_client_ = true; InvalidatePaintForHitTesting(object, context);
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h index 3a0f2a5..5dbf2e9 100644 --- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h +++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h
@@ -115,6 +115,8 @@ PaintInvalidator paint_invalidator_; Vector<PrePaintTreeWalkContext> context_storage_; + bool needs_invalidate_chrome_client_ = false; + FRIEND_TEST_ALL_PREFIXES(PrePaintTreeWalkTest, ClipRects); };
diff --git a/third_party/blink/renderer/core/paint/replaced_painter.cc b/third_party/blink/renderer/core/paint/replaced_painter.cc index c94a14b..36390783 100644 --- a/third_party/blink/renderer/core/paint/replaced_painter.cc +++ b/third_party/blink/renderer/core/paint/replaced_painter.cc
@@ -56,11 +56,8 @@ property_changed = true; } - bool painter_implements_content_box_clip = replaced.IsLayoutImage(); - if (paint_properties->OverflowClip() && - (!painter_implements_content_box_clip || - replaced.StyleRef().HasBorderRadius())) { - new_properties.SetClip(paint_properties->OverflowClip()); + if (const auto* clip = paint_properties->OverflowClip()) { + new_properties.SetClip(clip); property_changed = true; } @@ -157,9 +154,10 @@ !layout_replaced_.IsSelected()) return; - bool skip_clip = layout_replaced_.IsSVGRoot() && - !ToLayoutSVGRoot(layout_replaced_).ShouldApplyViewportClip(); - if (skip_clip || !layout_replaced_.PhysicalContentBoxRect().IsEmpty()) { + bool has_clip = + layout_replaced_.FirstFragment().PaintProperties() && + layout_replaced_.FirstFragment().PaintProperties()->OverflowClip(); + if (!has_clip || !layout_replaced_.PhysicalContentBoxRect().IsEmpty()) { ScopedReplacedContentPaintState content_paint_state(paint_state, layout_replaced_); layout_replaced_.PaintReplaced(content_paint_state.GetPaintInfo(),
diff --git a/third_party/blink/renderer/core/paint/video_painter.cc b/third_party/blink/renderer/core/paint/video_painter.cc index 6ddf7ec..5d8bbb1 100644 --- a/third_party/blink/renderer/core/paint/video_painter.cc +++ b/third_party/blink/renderer/core/paint/video_painter.cc
@@ -60,8 +60,6 @@ } } - // TODO(trchen): Video rect could overflow the content rect due to object-fit. - // Should apply a clip here like EmbeddedObjectPainter does. DrawingRecorder recorder(context, layout_video_, paint_info.phase); if (displaying_poster || !force_software_video_paint) {
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth.cc index 9cc9b0a..2a8fd95 100644 --- a/third_party/blink/renderer/modules/bluetooth/bluetooth.cc +++ b/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
@@ -246,6 +246,7 @@ const BluetoothLEScanOptions* options, ExceptionState& exception_state) { ExecutionContext* context = ExecutionContext::From(script_state); + DCHECK(context); // Remind developers when they are using Web Bluetooth on unsupported // platforms. @@ -303,9 +304,11 @@ } void Bluetooth::ScanEvent(mojom::blink::WebBluetoothScanResultPtr result) { - ExecutionContext* content = ContextLifecycleObserver::GetExecutionContext(); + ExecutionContext* context = ContextLifecycleObserver::GetExecutionContext(); + DCHECK(context); + BluetoothDevice* bluetooth_device = - GetBluetoothDeviceRepresentingDevice(std::move(result->device), content); + GetBluetoothDeviceRepresentingDevice(std::move(result->device), context); HeapVector<blink::StringOrUnsignedLong> uuids; for (const String& uuid : result->uuids) {
diff --git a/third_party/blink/renderer/modules/event_target_modules_names.json5 b/third_party/blink/renderer/modules/event_target_modules_names.json5 index e2ef962..77778755 100644 --- a/third_party/blink/renderer/modules/event_target_modules_names.json5 +++ b/third_party/blink/renderer/modules/event_target_modules_names.json5
@@ -65,8 +65,8 @@ "MIDIInput", "MIDIPort", "XR", - "XRCoordinateSystem", "XRSession", + "XRSpace", { name: "WebSocket", ImplementedAs: "DOMWebSocket",
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index e88b2985..9d1d425 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -451,11 +451,10 @@ "webusb/usb_isochronous_out_transfer_result.idl", "webusb/usb_out_transfer_result.idl", "xr/xr.idl", - "xr/xr_coordinate_system.idl", + "xr/xr_bounded_reference_space.idl", "xr/xr_device.idl", "xr/xr_viewer_pose.idl", "xr/xr_frame.idl", - "xr/xr_frame_of_reference.idl", "xr/xr_hit_result.idl", "xr/xr_input_pose.idl", "xr/xr_input_source.idl", @@ -463,9 +462,13 @@ "xr/xr_layer.idl", "xr/xr_presentation_context.idl", "xr/xr_ray.idl", + "xr/xr_reference_space.idl", "xr/xr_session.idl", "xr/xr_session_event.idl", + "xr/xr_space.idl", "xr/xr_stage_bounds.idl", + "xr/xr_stationary_reference_space.idl", + "xr/xr_unbounded_reference_space.idl", "xr/xr_view.idl", "xr/xr_viewport.idl", "xr/xr_webgl_layer.idl", @@ -726,8 +729,8 @@ "webusb/usb_control_transfer_parameters.idl", "webusb/usb_device_filter.idl", "webusb/usb_device_request_options.idl", - "xr/xr_frame_of_reference_options.idl", "xr/xr_input_source_event_init.idl", + "xr/xr_reference_space_options.idl", "xr/xr_session_creation_options.idl", "xr/xr_session_event_init.idl", "xr/xr_webgl_layer_init.idl",
diff --git a/third_party/blink/renderer/modules/payments/can_make_payment_test.cc b/third_party/blink/renderer/modules/payments/can_make_payment_test.cc index 19e383286..ac712f7 100644 --- a/third_party/blink/renderer/modules/payments/can_make_payment_test.cc +++ b/third_party/blink/renderer/modules/payments/can_make_payment_test.cc
@@ -20,7 +20,7 @@ // HasEnrolledInstrumentTest is parameterized on this enum to test that // canMakePayment when PaymentRequestHasEnrolledInstrumentEnabled is false // behaves identically to hasEnrolledInstrument. -enum class HasEnrolledInstrumentEnabled { YES, NO }; +enum class HasEnrolledInstrumentEnabled { kYes, kNo }; class HasEnrolledInstrumentTest : public testing::Test, @@ -28,7 +28,7 @@ void SetUp() override { testing::Test::SetUp(); RuntimeEnabledFeatures::SetPaymentRequestHasEnrolledInstrumentEnabled( - GetParam() == HasEnrolledInstrumentEnabled::YES); + GetParam() == HasEnrolledInstrumentEnabled::kYes); } }; @@ -40,7 +40,7 @@ scope.GetExecutionContext(), BuildPaymentMethodDataForTest(), BuildPaymentDetailsInitForTest(), scope.GetExceptionState()); - if (GetParam() == HasEnrolledInstrumentEnabled::YES) { + if (GetParam() == HasEnrolledInstrumentEnabled::kYes) { request->hasEnrolledInstrument(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectCall()); } else { @@ -60,7 +60,7 @@ scope.GetExecutionContext(), BuildPaymentMethodDataForTest(), BuildPaymentDetailsInitForTest(), scope.GetExceptionState()); - if (GetParam() == HasEnrolledInstrumentEnabled::YES) { + if (GetParam() == HasEnrolledInstrumentEnabled::kYes) { request->hasEnrolledInstrument(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectCall()); } else { @@ -79,7 +79,7 @@ PaymentRequest* request = PaymentRequest::Create( scope.GetExecutionContext(), BuildPaymentMethodDataForTest(), BuildPaymentDetailsInitForTest(), scope.GetExceptionState()); - if (GetParam() == HasEnrolledInstrumentEnabled::YES) { + if (GetParam() == HasEnrolledInstrumentEnabled::kYes) { request->hasEnrolledInstrument(scope.GetScriptState()); request->hasEnrolledInstrument(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectCall()); @@ -99,7 +99,7 @@ scope.GetExecutionContext(), BuildPaymentMethodDataForTest(), BuildPaymentDetailsInitForTest(), scope.GetExceptionState()); - if (GetParam() == HasEnrolledInstrumentEnabled::YES) { + if (GetParam() == HasEnrolledInstrumentEnabled::kYes) { request->hasEnrolledInstrument(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectCall()); } else { @@ -119,7 +119,7 @@ scope.GetExecutionContext(), BuildPaymentMethodDataForTest(), BuildPaymentDetailsInitForTest(), scope.GetExceptionState()); String captor; - if (GetParam() == HasEnrolledInstrumentEnabled::YES) { + if (GetParam() == HasEnrolledInstrumentEnabled::kYes) { request->hasEnrolledInstrument(scope.GetScriptState()) .Then(funcs.ExpectCall(&captor), funcs.ExpectNoCall()); } else { @@ -142,7 +142,7 @@ scope.GetExecutionContext(), BuildPaymentMethodDataForTest(), BuildPaymentDetailsInitForTest(), scope.GetExceptionState()); String captor; - if (GetParam() == HasEnrolledInstrumentEnabled::YES) { + if (GetParam() == HasEnrolledInstrumentEnabled::kYes) { request->hasEnrolledInstrument(scope.GetScriptState()) .Then(funcs.ExpectCall(&captor), funcs.ExpectNoCall()); } else { @@ -159,8 +159,8 @@ INSTANTIATE_TEST_CASE_P(ProgrammaticHasEnrolledInstrumentTest, HasEnrolledInstrumentTest, - ::testing::Values(HasEnrolledInstrumentEnabled::YES, - HasEnrolledInstrumentEnabled::NO)); + ::testing::Values(HasEnrolledInstrumentEnabled::kYes, + HasEnrolledInstrumentEnabled::kNo)); // Test fixture for canMakePayment when // PaymentRequestHasEnrolledInstrumentEnabled is true.
diff --git a/third_party/blink/renderer/modules/xr/BUILD.gn b/third_party/blink/renderer/modules/xr/BUILD.gn index 0d737cd..8da73d2 100644 --- a/third_party/blink/renderer/modules/xr/BUILD.gn +++ b/third_party/blink/renderer/modules/xr/BUILD.gn
@@ -8,16 +8,14 @@ sources = [ "xr.cc", "xr.h", + "xr_bounded_reference_space.cc", + "xr_bounded_reference_space.h", "xr_canvas_input_provider.cc", "xr_canvas_input_provider.h", - "xr_coordinate_system.cc", - "xr_coordinate_system.h", "xr_device.cc", "xr_device.h", "xr_frame.cc", "xr_frame.h", - "xr_frame_of_reference.cc", - "xr_frame_of_reference.h", "xr_frame_provider.cc", "xr_frame_provider.h", "xr_frame_request_callback_collection.cc", @@ -36,12 +34,20 @@ "xr_presentation_context.h", "xr_ray.cc", "xr_ray.h", + "xr_reference_space.cc", + "xr_reference_space.h", "xr_session.cc", "xr_session.h", "xr_session_event.cc", "xr_session_event.h", + "xr_space.cc", + "xr_space.h", "xr_stage_bounds.cc", "xr_stage_bounds.h", + "xr_stationary_reference_space.cc", + "xr_stationary_reference_space.h", + "xr_unbounded_reference_space.cc", + "xr_unbounded_reference_space.h", "xr_utils.cc", "xr_utils.h", "xr_view.cc",
diff --git a/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc new file mode 100644 index 0000000..443f117 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.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 "third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h" + +#include "device/vr/public/mojom/vr_service.mojom-blink.h" +#include "third_party/blink/renderer/modules/xr/xr_session.h" +#include "third_party/blink/renderer/modules/xr/xr_stage_bounds.h" + +namespace blink { + +XRBoundedReferenceSpace::XRBoundedReferenceSpace(XRSession* session) + : XRReferenceSpace(session) {} + +XRBoundedReferenceSpace::~XRBoundedReferenceSpace() = default; + +void XRBoundedReferenceSpace::UpdateBoundsGeometry( + XRStageBounds* bounds_geometry) { + // TODO(https://crbug.com/917411): Support bounds geometry and fire a 'reset' + // event when the bounds change. +} + +void XRBoundedReferenceSpace::UpdateFloorLevelTransform() { + const device::mojom::blink::VRDisplayInfoPtr& display_info = + session()->GetVRDisplayInfo(); + + if (display_info && display_info->stageParameters) { + // Use the transform given by xrDisplayInfo's stageParameters if available. + const WTF::Vector<float>& m = + display_info->stageParameters->standingTransform; + floor_level_transform_ = TransformationMatrix::Create( + m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], + m[11], m[12], m[13], m[14], m[15]); + } else { + // If stage parameters aren't available set the transform to null, which + // will subsequently cause this reference space to return null poses. + floor_level_transform_.reset(); + } + + display_info_id_ = session()->DisplayInfoPtrId(); +} + +// Transforms a given pose from a "base" reference space used by the XR +// service to the bounded (floor level) reference space. Ideally in the future +// this reference space can be used without additional transforms, with +// the various XR backends returning poses already in the right space. +std::unique_ptr<TransformationMatrix> +XRBoundedReferenceSpace::TransformBasePose( + const TransformationMatrix& base_pose) { + // Check first to see if the xrDisplayInfo has updated since the last + // call. If so, update the pose transform. + if (display_info_id_ != session()->DisplayInfoPtrId()) + UpdateFloorLevelTransform(); + + // If the reference space has a transform apply it to the base pose and return + // that, otherwise return null. + if (floor_level_transform_) { + std::unique_ptr<TransformationMatrix> pose( + TransformationMatrix::Create(*floor_level_transform_)); + pose->Multiply(base_pose); + return pose; + } + + return nullptr; +} + +// Serves the same purpose as TransformBasePose, but for input poses. Needs to +// know the head pose so that cases like the head-model frame of reference can +// properly adjust the input's relative position. +std::unique_ptr<TransformationMatrix> +XRBoundedReferenceSpace::TransformBaseInputPose( + const TransformationMatrix& base_input_pose, + const TransformationMatrix& base_pose) { + return TransformBasePose(base_input_pose); +} + +void XRBoundedReferenceSpace::Trace(blink::Visitor* visitor) { + visitor->Trace(bounds_geometry_); + XRSpace::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h new file mode 100644 index 0000000..804996c --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.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 THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_BOUNDED_REFERENCE_SPACE_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_BOUNDED_REFERENCE_SPACE_H_ + +#include "third_party/blink/renderer/core/geometry/dom_point_read_only.h" +#include "third_party/blink/renderer/modules/xr/xr_reference_space.h" +#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h" + +namespace blink { + +class XRStageBounds; + +class XRBoundedReferenceSpace final : public XRReferenceSpace { + DEFINE_WRAPPERTYPEINFO(); + + public: + XRBoundedReferenceSpace(XRSession*); + ~XRBoundedReferenceSpace() override; + + void UpdateBoundsGeometry(XRStageBounds*); + + std::unique_ptr<TransformationMatrix> TransformBasePose( + const TransformationMatrix& base_pose) override; + std::unique_ptr<TransformationMatrix> TransformBaseInputPose( + const TransformationMatrix& base_input_pose, + const TransformationMatrix& base_pose) override; + + HeapVector<Member<DOMPointReadOnly>> boundsGeometry() const { + return bounds_geometry_; + } + + void Trace(blink::Visitor*) override; + + private: + void UpdateFloorLevelTransform(); + + HeapVector<Member<DOMPointReadOnly>> bounds_geometry_; + std::unique_ptr<TransformationMatrix> floor_level_transform_; + unsigned int display_info_id_ = 0; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_BOUNDED_REFERENCE_SPACE_H_
diff --git a/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.idl b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.idl new file mode 100644 index 0000000..ea8d30b --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.idl
@@ -0,0 +1,13 @@ +// 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. + +// https://immersive-web.github.io/webxr/#xrboundedreferencespace-interface + +[ + SecureContext, + Exposed=Window, + OriginTrialEnabled=WebXR +] interface XRBoundedReferenceSpace : XRReferenceSpace { + readonly attribute FrozenArray<DOMPointReadOnly> boundsGeometry; +};
diff --git a/third_party/blink/renderer/modules/xr/xr_coordinate_system.h b/third_party/blink/renderer/modules/xr/xr_coordinate_system.h deleted file mode 100644 index 9ba5d6e..0000000 --- a/third_party/blink/renderer/modules/xr/xr_coordinate_system.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_COORDINATE_SYSTEM_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_COORDINATE_SYSTEM_H_ - -#include "third_party/blink/renderer/core/dom/events/event_target.h" -#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" -#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/wtf/forward.h" - -namespace blink { - -class TransformationMatrix; -class XRSession; - -class XRCoordinateSystem : public EventTargetWithInlineData { - DEFINE_WRAPPERTYPEINFO(); - - public: - explicit XRCoordinateSystem(XRSession*); - ~XRCoordinateSystem() override; - - DOMFloat32Array* getTransformTo(XRCoordinateSystem*) const; - - XRSession* session() const { return session_; } - - // EventTarget overrides. - ExecutionContext* GetExecutionContext() const override; - const AtomicString& InterfaceName() const override; - - virtual std::unique_ptr<TransformationMatrix> TransformBasePose( - const TransformationMatrix& base_pose) = 0; - virtual std::unique_ptr<TransformationMatrix> TransformBaseInputPose( - const TransformationMatrix& base_input_pose, - const TransformationMatrix& base_pose) = 0; - - void Trace(blink::Visitor*) override; - - private: - const Member<XRSession> session_; -}; - -} // namespace blink - -#endif // XRWebGLLayer_h
diff --git a/third_party/blink/renderer/modules/xr/xr_coordinate_system.idl b/third_party/blink/renderer/modules/xr/xr_coordinate_system.idl deleted file mode 100644 index 668360f2..0000000 --- a/third_party/blink/renderer/modules/xr/xr_coordinate_system.idl +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// https://immersive-web.github.io/webxr/#xrcoordinatesystem-interface -[ - SecureContext, - Exposed=Window, - OriginTrialEnabled=WebXR -] interface XRCoordinateSystem : EventTarget { - Float32Array? getTransformTo(XRCoordinateSystem other); -};
diff --git a/third_party/blink/renderer/modules/xr/xr_frame.cc b/third_party/blink/renderer/modules/xr/xr_frame.cc index 73fe39d1..a8121c8 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame.cc +++ b/third_party/blink/renderer/modules/xr/xr_frame.cc
@@ -4,9 +4,9 @@ #include "third_party/blink/renderer/modules/xr/xr_frame.h" -#include "third_party/blink/renderer/modules/xr/xr_coordinate_system.h" #include "third_party/blink/renderer/modules/xr/xr_input_pose.h" #include "third_party/blink/renderer/modules/xr/xr_input_source.h" +#include "third_party/blink/renderer/modules/xr/xr_reference_space.h" #include "third_party/blink/renderer/modules/xr/xr_session.h" #include "third_party/blink/renderer/modules/xr/xr_view.h" #include "third_party/blink/renderer/modules/xr/xr_viewer_pose.h" @@ -19,23 +19,22 @@ return session_->views(); } -XRViewerPose* XRFrame::getViewerPose( - XRCoordinateSystem* coordinate_system) const { +XRViewerPose* XRFrame::getViewerPose(XRReferenceSpace* reference_space) const { session_->LogGetPose(); // If we don't have a valid base pose return null. Most common when tracking // is lost. - if (!base_pose_matrix_ || !coordinate_system) { + if (!base_pose_matrix_ || !reference_space) { return nullptr; } // Must use a coordinate system created from the same session. - if (coordinate_system->session() != session_) { + if (reference_space->session() != session_) { return nullptr; } std::unique_ptr<TransformationMatrix> pose = - coordinate_system->TransformBasePose(*base_pose_matrix_); + reference_space->TransformBasePose(*base_pose_matrix_); if (!pose) { return nullptr; @@ -44,16 +43,15 @@ return MakeGarbageCollected<XRViewerPose>(session(), std::move(pose)); } -XRInputPose* XRFrame::getInputPose( - XRInputSource* input_source, - XRCoordinateSystem* coordinate_system) const { - if (!input_source || !coordinate_system) { +XRInputPose* XRFrame::getInputPose(XRInputSource* input_source, + XRReferenceSpace* reference_space) const { + if (!input_source || !reference_space) { return nullptr; } // Must use an input source and coordinate system from the same session. if (input_source->session() != session_ || - coordinate_system->session() != session_) { + reference_space->session() != session_) { return nullptr; } @@ -68,7 +66,7 @@ // Multiply the head pose and pointer transform to get the final pointer. std::unique_ptr<TransformationMatrix> pointer_pose = - coordinate_system->TransformBasePose(*base_pose_matrix_); + reference_space->TransformBasePose(*base_pose_matrix_); pointer_pose->Multiply(*(input_source->pointer_transform_matrix_)); return MakeGarbageCollected<XRInputPose>(std::move(pointer_pose), @@ -84,7 +82,7 @@ // Just return the head pose as the pointer pose. std::unique_ptr<TransformationMatrix> pointer_pose = - coordinate_system->TransformBasePose(*base_pose_matrix_); + reference_space->TransformBasePose(*base_pose_matrix_); return MakeGarbageCollected<XRInputPose>( std::move(pointer_pose), nullptr, input_source->emulatedPosition()); @@ -96,7 +94,7 @@ } std::unique_ptr<TransformationMatrix> grip_pose = - coordinate_system->TransformBaseInputPose( + reference_space->TransformBaseInputPose( *(input_source->base_pose_matrix_), *base_pose_matrix_); if (!grip_pose) {
diff --git a/third_party/blink/renderer/modules/xr/xr_frame.h b/third_party/blink/renderer/modules/xr/xr_frame.h index 7491838..9c4b942 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame.h +++ b/third_party/blink/renderer/modules/xr/xr_frame.h
@@ -14,10 +14,10 @@ namespace blink { -class XRCoordinateSystem; class XRViewerPose; class XRInputPose; class XRInputSource; +class XRReferenceSpace; class XRSession; class XRView; @@ -30,8 +30,8 @@ XRSession* session() const { return session_; } const HeapVector<Member<XRView>>& views() const; - XRViewerPose* getViewerPose(XRCoordinateSystem*) const; - XRInputPose* getInputPose(XRInputSource*, XRCoordinateSystem*) const; + XRViewerPose* getViewerPose(XRReferenceSpace*) const; + XRInputPose* getInputPose(XRInputSource*, XRReferenceSpace*) const; void SetBasePoseMatrix(const TransformationMatrix&);
diff --git a/third_party/blink/renderer/modules/xr/xr_frame.idl b/third_party/blink/renderer/modules/xr/xr_frame.idl index 09f4bfb..a693437 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame.idl +++ b/third_party/blink/renderer/modules/xr/xr_frame.idl
@@ -11,8 +11,7 @@ readonly attribute XRSession session; readonly attribute FrozenArray<XRView> views; - // TODO(https://crbug.com/915050): Update definition to match spec. - XRViewerPose? getViewerPose(XRCoordinateSystem coordinateSystem); + XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace); XRInputPose? getInputPose(XRInputSource inputSource, - XRCoordinateSystem coordinateSystem); + XRReferenceSpace referenceSpace); };
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_of_reference.cc b/third_party/blink/renderer/modules/xr/xr_frame_of_reference.cc deleted file mode 100644 index 5c29f5d..0000000 --- a/third_party/blink/renderer/modules/xr/xr_frame_of_reference.cc +++ /dev/null
@@ -1,158 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/modules/xr/xr_frame_of_reference.h" - -#include "device/vr/public/mojom/vr_service.mojom-blink.h" -#include "third_party/blink/renderer/modules/xr/xr_device.h" -#include "third_party/blink/renderer/modules/xr/xr_session.h" -#include "third_party/blink/renderer/modules/xr/xr_stage_bounds.h" - -namespace blink { - -// Rough estimate of avg human eye height in meters. -const double kDefaultEmulationHeight = 1.6; - -XRFrameOfReference::XRFrameOfReference(XRSession* session, Type type) - : XRCoordinateSystem(session), type_(type) {} - -XRFrameOfReference::~XRFrameOfReference() = default; - -void XRFrameOfReference::UpdatePoseTransform( - std::unique_ptr<TransformationMatrix> transform) { - pose_transform_ = std::move(transform); -} - -void XRFrameOfReference::UpdateStageBounds(XRStageBounds* bounds) { - bounds_ = bounds; - // TODO(bajones): Fire a boundschange event -} - -void XRFrameOfReference::UpdateStageTransform() { - const device::mojom::blink::VRDisplayInfoPtr& display_info = - session()->GetVRDisplayInfo(); - - if (display_info && display_info->stageParameters) { - // Use the transform given by xrDisplayInfo's stageParamters if available. - const WTF::Vector<float>& m = - display_info->stageParameters->standingTransform; - pose_transform_ = TransformationMatrix::Create( - m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], - m[11], m[12], m[13], m[14], m[15]); - } else if (emulated_height_ != 0.0) { - // Otherwise, if this frame of reference has specified that an emulated - // height may be used, create a transform based on that. - pose_transform_ = TransformationMatrix::Create(); - pose_transform_->Translate3d(0, emulated_height_, 0); - } else { - // If stage parameters aren't available and emulation is disabled, set the - // transform to null, which will subsequently cause this frame of reference - // to return null poses. - pose_transform_.reset(); - } - - display_info_id_ = session()->DisplayInfoPtrId(); -} - -// Enables emulated height when using a stage frame of reference, which should -// only be used if the sytem does not have a native concept of how far above the -// floor the XRDevice is at any given moment. This applies a static vertical -// offset to the coordinate system so that the user feels approximately like -// they are standing on a floor plane located at Y = 0. An explicit offset in -// meters can be given if the page has specific needs. -void XRFrameOfReference::UseEmulatedHeight(double value) { - if (value == 0.0) - value = kDefaultEmulationHeight; - - emulated_height_ = value; - UpdateStageTransform(); -} - -// Transforms a given pose from a "base" coordinate system used by the XR -// service to the frame of reference's coordinate system. This model is a bit -// over-simplified and will need to be made more robust when we start dealing -// with world-scale 6DoF tracking. -std::unique_ptr<TransformationMatrix> XRFrameOfReference::TransformBasePose( - const TransformationMatrix& base_pose) { - switch (type_) { - case kTypeHeadModel: { - // TODO(bajones): Detect if base pose is already neck modeled and return - // it unchanged if so for better performance. - - // Strip out translation component. - std::unique_ptr<TransformationMatrix> pose( - TransformationMatrix::Create(base_pose)); - pose->SetM41(0.0); - pose->SetM42(0.0); - pose->SetM43(0.0); - // TODO(bajones): Apply our own neck model - return pose; - } break; - case kTypeEyeLevel: - // For now we assume that all base poses are delivered as eye-level poses. - // Thus in this case we just return the pose without transformation. - return TransformationMatrix::Create(base_pose); - break; - case kTypeStage: - // Check first to see if the xrDisplayInfo has updated since the last - // call. If so, update the pose transform. - if (display_info_id_ != session()->DisplayInfoPtrId()) - UpdateStageTransform(); - - // If the stage has a transform apply it to the base pose and return that, - // otherwise return null. - if (pose_transform_) { - std::unique_ptr<TransformationMatrix> pose( - TransformationMatrix::Create(*pose_transform_)); - pose->Multiply(base_pose); - return pose; - } - break; - } - - return nullptr; -} - -// Serves the same purpose as TransformBasePose, but for input poses. Needs to -// know the head pose so that cases like the head-model frame of reference can -// properly adjust the input's relative position. -std::unique_ptr<TransformationMatrix> -XRFrameOfReference::TransformBaseInputPose( - const TransformationMatrix& base_input_pose, - const TransformationMatrix& base_pose) { - switch (type_) { - case kTypeHeadModel: { - std::unique_ptr<TransformationMatrix> head_model_pose( - TransformBasePose(base_pose)); - - // Get the positional delta between the base pose and the head model pose. - float dx = head_model_pose->M41() - base_pose.M41(); - float dy = head_model_pose->M42() - base_pose.M42(); - float dz = head_model_pose->M43() - base_pose.M43(); - - // Translate the controller by the same delta so that it shows up in the - // right relative position. - std::unique_ptr<TransformationMatrix> pose( - TransformationMatrix::Create(base_input_pose)); - pose->SetM41(pose->M41() + dx); - pose->SetM42(pose->M42() + dy); - pose->SetM43(pose->M43() + dz); - - return pose; - } break; - case kTypeEyeLevel: - case kTypeStage: - return TransformBasePose(base_input_pose); - break; - } - - return nullptr; -} - -void XRFrameOfReference::Trace(blink::Visitor* visitor) { - visitor->Trace(bounds_); - XRCoordinateSystem::Trace(visitor); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_of_reference.h b/third_party/blink/renderer/modules/xr/xr_frame_of_reference.h deleted file mode 100644 index eca778a..0000000 --- a/third_party/blink/renderer/modules/xr/xr_frame_of_reference.h +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_FRAME_OF_REFERENCE_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_FRAME_OF_REFERENCE_H_ - -#include "third_party/blink/renderer/modules/xr/xr_coordinate_system.h" -#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h" - -namespace blink { - -class XRStageBounds; - -class XRFrameOfReference final : public XRCoordinateSystem { - DEFINE_WRAPPERTYPEINFO(); - - public: - enum Type { kTypeHeadModel, kTypeEyeLevel, kTypeStage }; - - XRFrameOfReference(XRSession*, Type); - ~XRFrameOfReference() override; - - void UpdatePoseTransform(std::unique_ptr<TransformationMatrix>); - void UpdateStageBounds(XRStageBounds*); - void UseEmulatedHeight(double value); - - std::unique_ptr<TransformationMatrix> TransformBasePose( - const TransformationMatrix& base_pose) override; - std::unique_ptr<TransformationMatrix> TransformBaseInputPose( - const TransformationMatrix& base_input_pose, - const TransformationMatrix& base_pose) override; - - XRStageBounds* bounds() const { return bounds_; } - double emulatedHeight() const { return emulated_height_; } - - Type type() const { return type_; } - - void Trace(blink::Visitor*) override; - - private: - void UpdateStageTransform(); - - Member<XRStageBounds> bounds_; - double emulated_height_ = 0.0; - Type type_; - std::unique_ptr<TransformationMatrix> pose_transform_; - unsigned int display_info_id_ = 0; -}; - -} // namespace blink - -#endif // XRWebGLLayer_h
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_of_reference.idl b/third_party/blink/renderer/modules/xr/xr_frame_of_reference.idl deleted file mode 100644 index b1b3856..0000000 --- a/third_party/blink/renderer/modules/xr/xr_frame_of_reference.idl +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// https://immersive-web.github.io/webxr/#xrframeofreference-interface - -enum XRFrameOfReferenceType { - "head-model", - "eye-level", - "stage", -}; - -[ - SecureContext, - Exposed=Window, - OriginTrialEnabled=WebXR -] interface XRFrameOfReference : XRCoordinateSystem { - readonly attribute XRStageBounds? bounds; - readonly attribute double emulatedHeight; -};
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_of_reference_options.idl b/third_party/blink/renderer/modules/xr/xr_frame_of_reference_options.idl deleted file mode 100644 index cdc2f098..0000000 --- a/third_party/blink/renderer/modules/xr/xr_frame_of_reference_options.idl +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// https://immersive-web.github.io/webxr/#xrframeofreference-interface -dictionary XRFrameOfReferenceOptions { - boolean disableStageEmulation = false; - double stageEmulationHeight = 0.0; -};
diff --git a/third_party/blink/renderer/modules/xr/xr_reference_space.cc b/third_party/blink/renderer/modules/xr/xr_reference_space.cc new file mode 100644 index 0000000..4b41ac9 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_reference_space.cc
@@ -0,0 +1,21 @@ +// 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 "third_party/blink/renderer/modules/xr/xr_reference_space.h" + +#include "device/vr/public/mojom/vr_service.mojom-blink.h" +#include "third_party/blink/renderer/modules/xr/xr_session.h" +#include "third_party/blink/renderer/modules/xr/xr_stage_bounds.h" + +namespace blink { + +XRReferenceSpace::XRReferenceSpace(XRSession* session) : XRSpace(session) {} + +XRReferenceSpace::~XRReferenceSpace() = default; + +void XRReferenceSpace::Trace(blink::Visitor* visitor) { + XRSpace::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_reference_space.h b/third_party/blink/renderer/modules/xr/xr_reference_space.h new file mode 100644 index 0000000..0b64888 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_reference_space.h
@@ -0,0 +1,31 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_REFERENCE_SPACE_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_REFERENCE_SPACE_H_ + +#include "third_party/blink/renderer/modules/xr/xr_space.h" +#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h" + +namespace blink { + +class XRReferenceSpace : public XRSpace { + DEFINE_WRAPPERTYPEINFO(); + + public: + XRReferenceSpace(XRSession*); + ~XRReferenceSpace() override; + + virtual std::unique_ptr<TransformationMatrix> TransformBasePose( + const TransformationMatrix& base_pose) = 0; + virtual std::unique_ptr<TransformationMatrix> TransformBaseInputPose( + const TransformationMatrix& base_input_pose, + const TransformationMatrix& base_pose) = 0; + + void Trace(blink::Visitor*) override; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_REFERENCE_SPACE_H_
diff --git a/third_party/blink/renderer/modules/xr/xr_reference_space.idl b/third_party/blink/renderer/modules/xr/xr_reference_space.idl new file mode 100644 index 0000000..6fc94da9 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_reference_space.idl
@@ -0,0 +1,19 @@ +// 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. + +// https://immersive-web.github.io/webxr/#xrreferencespace-interface + +enum XRReferenceSpaceType { + "stationary", + "bounded", + "unbounded" +}; + +[ + SecureContext, + Exposed=Window, + OriginTrialEnabled=WebXR +] interface XRReferenceSpace : XRSpace { + attribute EventHandler onreset; +};
diff --git a/third_party/blink/renderer/modules/xr/xr_reference_space_options.idl b/third_party/blink/renderer/modules/xr/xr_reference_space_options.idl new file mode 100644 index 0000000..76b5c285 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_reference_space_options.idl
@@ -0,0 +1,10 @@ +// 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. + +// https://immersive-web.github.io/webxr/#xrreferencespace-interface + +dictionary XRReferenceSpaceOptions { + required XRReferenceSpaceType type; + XRStationaryReferenceSpaceSubtype subtype; +};
diff --git a/third_party/blink/renderer/modules/xr/xr_session.cc b/third_party/blink/renderer/modules/xr/xr_session.cc index 05286005c..fe0ebf7 100644 --- a/third_party/blink/renderer/modules/xr/xr_session.cc +++ b/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -17,17 +17,20 @@ #include "third_party/blink/renderer/modules/event_target_modules.h" #include "third_party/blink/renderer/modules/screen_orientation/screen_orientation.h" #include "third_party/blink/renderer/modules/xr/xr.h" +#include "third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h" #include "third_party/blink/renderer/modules/xr/xr_canvas_input_provider.h" #include "third_party/blink/renderer/modules/xr/xr_device.h" #include "third_party/blink/renderer/modules/xr/xr_frame.h" -#include "third_party/blink/renderer/modules/xr/xr_frame_of_reference.h" -#include "third_party/blink/renderer/modules/xr/xr_frame_of_reference_options.h" #include "third_party/blink/renderer/modules/xr/xr_frame_provider.h" #include "third_party/blink/renderer/modules/xr/xr_hit_result.h" #include "third_party/blink/renderer/modules/xr/xr_input_source_event.h" #include "third_party/blink/renderer/modules/xr/xr_layer.h" #include "third_party/blink/renderer/modules/xr/xr_presentation_context.h" +#include "third_party/blink/renderer/modules/xr/xr_reference_space.h" +#include "third_party/blink/renderer/modules/xr/xr_reference_space_options.h" #include "third_party/blink/renderer/modules/xr/xr_session_event.h" +#include "third_party/blink/renderer/modules/xr/xr_stationary_reference_space.h" +#include "third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.h" #include "third_party/blink/renderer/modules/xr/xr_view.h" #include "third_party/blink/renderer/modules/xr/xr_webgl_layer.h" #include "third_party/blink/renderer/platform/transforms/transformation_matrix.h" @@ -38,10 +41,13 @@ const char kSessionEnded[] = "XRSession has already ended."; -const char kUnknownFrameOfReference[] = "Unknown frame of reference type."; +const char kUnknownReferenceSpace[] = "Unknown reference space type."; -const char kNonEmulatedStageNotSupported[] = - "This device does not support a non-emulated 'stage' frame of reference."; +const char kSubtypeRequired[] = + "Subtype must be specified when requesting a stationary reference space."; + +const char kReferenceSpaceNotSupported[] = + "This device does not support the requested reference space type."; const double kDegToRad = M_PI / 180.0; @@ -183,48 +189,68 @@ return event_target_names::kXRSession; } -ScriptPromise XRSession::requestFrameOfReference( +ScriptPromise XRSession::requestReferenceSpace( ScriptState* script_state, - const String& type, - const XRFrameOfReferenceOptions* options) { + const XRReferenceSpaceOptions* options) { if (ended_) { return ScriptPromise::RejectWithDOMException( script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError, kSessionEnded)); } - XRFrameOfReference* frameOfRef = nullptr; - if (type == "head-model") { - frameOfRef = MakeGarbageCollected<XRFrameOfReference>( - this, XRFrameOfReference::kTypeHeadModel); - } else if (type == "eye-level") { - frameOfRef = MakeGarbageCollected<XRFrameOfReference>( - this, XRFrameOfReference::kTypeEyeLevel); - } else if (type == "stage") { - if (!options->disableStageEmulation()) { - frameOfRef = MakeGarbageCollected<XRFrameOfReference>( - this, XRFrameOfReference::kTypeStage); - frameOfRef->UseEmulatedHeight(options->stageEmulationHeight()); - } else if (display_info_ && display_info_->stageParameters) { - frameOfRef = MakeGarbageCollected<XRFrameOfReference>( - this, XRFrameOfReference::kTypeStage); + XRReferenceSpace* reference_space = nullptr; + if (options->type() == "stationary") { + if (!options->hasSubtype()) { + return ScriptPromise::RejectWithDOMException( + script_state, + DOMException::Create(DOMExceptionCode::kNotSupportedError, + kSubtypeRequired)); + } + + XRStationaryReferenceSpace::Subtype subtype; + + if (options->subtype() == "eye-level") { + subtype = XRStationaryReferenceSpace::kSubtypeEyeLevel; + } else if (options->subtype() == "floor-level") { + subtype = XRStationaryReferenceSpace::kSubtypeFloorLevel; + } else if (options->subtype() == "position-disabled") { + subtype = XRStationaryReferenceSpace::kSubtypePositionDisabled; } else { return ScriptPromise::RejectWithDOMException( script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError, - kNonEmulatedStageNotSupported)); + kSubtypeRequired)); + } + + reference_space = + MakeGarbageCollected<XRStationaryReferenceSpace>(this, subtype); + } else if (options->type() == "bounded") { + // TODO(https://crbug.com/917411): Bounded reference spaces cannot be + // returned unless they have bounds geometry. Until we implement that they + // will be considered unsupported. + return ScriptPromise::RejectWithDOMException( + script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError, + kReferenceSpaceNotSupported)); + } else if (options->type() == "unbounded") { + if (immersive_ && environment_integration_) { + reference_space = MakeGarbageCollected<XRUnboundedReferenceSpace>(this); + } else { + return ScriptPromise::RejectWithDOMException( + script_state, + DOMException::Create(DOMExceptionCode::kNotSupportedError, + kReferenceSpaceNotSupported)); } } - if (!frameOfRef) { + if (!reference_space) { return ScriptPromise::RejectWithDOMException( script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError, - kUnknownFrameOfReference)); + kUnknownReferenceSpace)); } ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise(); - resolver->Resolve(frameOfRef); + resolver->Resolve(reference_space); return promise; } @@ -280,27 +306,26 @@ ScriptPromise XRSession::requestHitTest(ScriptState* script_state, NotShared<DOMFloat32Array> origin, NotShared<DOMFloat32Array> direction, - XRCoordinateSystem* coordinate_system) { + XRSpace* space) { if (ended_) { return ScriptPromise::RejectWithDOMException( script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError, kSessionEnded)); } - if (!coordinate_system) { + if (!space) { return ScriptPromise::Reject( script_state, V8ThrowException::CreateTypeError( - script_state->GetIsolate(), - "The coordinateSystem parameter is empty.")); + script_state->GetIsolate(), "No XRSpace specified.")); } if (origin.View()->length() != 3 || direction.View()->length() != 3) { return ScriptPromise::RejectWithDOMException( script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError, - "Invalid ray!")); + "Invalid ray")); } - // TODO(https://crbug.com/846411): use coordinate_system. + // TODO(https://crbug.com/846411): use space. // Reject the promise if device doesn't support the hit-test API. // TODO(https://crbug.com/878936): Get the environment provider without going
diff --git a/third_party/blink/renderer/modules/xr/xr_session.h b/third_party/blink/renderer/modules/xr/xr_session.h index c951e68..80e406c8 100644 --- a/third_party/blink/renderer/modules/xr/xr_session.h +++ b/third_party/blink/renderer/modules/xr/xr_session.h
@@ -28,12 +28,12 @@ class ScriptPromiseResolver; class V8XRFrameRequestCallback; class XRCanvasInputProvider; -class XRCoordinateSystem; +class XRSpace; class XRDevice; -class XRFrameOfReferenceOptions; class XRInputSourceEvent; class XRLayer; class XRPresentationContext; +class XRReferenceSpaceOptions; class XRView; class XRSession final : public EventTargetWithInlineData, @@ -83,9 +83,8 @@ DEFINE_ATTRIBUTE_EVENT_LISTENER(selectend, kSelectend); DEFINE_ATTRIBUTE_EVENT_LISTENER(select, kSelect); - ScriptPromise requestFrameOfReference(ScriptState*, - const String& type, - const XRFrameOfReferenceOptions*); + ScriptPromise requestReferenceSpace(ScriptState*, + const XRReferenceSpaceOptions*); int requestAnimationFrame(V8XRFrameRequestCallback*); void cancelAnimationFrame(int id); @@ -98,7 +97,7 @@ ScriptPromise requestHitTest(ScriptState* script_state, NotShared<DOMFloat32Array> origin, NotShared<DOMFloat32Array> direction, - XRCoordinateSystem* coordinate_system); + XRSpace* space); // Called by JavaScript to manually end the session. ScriptPromise end(ScriptState*);
diff --git a/third_party/blink/renderer/modules/xr/xr_session.idl b/third_party/blink/renderer/modules/xr/xr_session.idl index 01b791d5..aafcecaf8 100644 --- a/third_party/blink/renderer/modules/xr/xr_session.idl +++ b/third_party/blink/renderer/modules/xr/xr_session.idl
@@ -30,14 +30,14 @@ attribute EventHandler onresetpose; attribute EventHandler onend; - [CallWith=ScriptState] Promise<XRFrameOfReference> requestFrameOfReference(XRFrameOfReferenceType type, [PermissiveDictionaryConversion] optional XRFrameOfReferenceOptions options); + [CallWith=ScriptState] Promise<XRReferenceSpace> requestReferenceSpace([PermissiveDictionaryConversion] XRReferenceSpaceOptions options); long requestAnimationFrame(XRFrameRequestCallback callback); void cancelAnimationFrame(long handle); [MeasureAs=XRSessionGetInputSources] FrozenArray<XRInputSource> getInputSources(); - [RuntimeEnabled=WebXRHitTest, CallWith=ScriptState] Promise<FrozenArray<XRHitResult>> requestHitTest(Float32Array origin, Float32Array direction, XRCoordinateSystem coordinateSystem); + [RuntimeEnabled=WebXRHitTest, CallWith=ScriptState] Promise<FrozenArray<XRHitResult>> requestHitTest(Float32Array origin, Float32Array direction, XRSpace space); [CallWith=ScriptState] Promise<void> end(); };
diff --git a/third_party/blink/renderer/modules/xr/xr_coordinate_system.cc b/third_party/blink/renderer/modules/xr/xr_space.cc similarity index 60% rename from third_party/blink/renderer/modules/xr/xr_coordinate_system.cc rename to third_party/blink/renderer/modules/xr/xr_space.cc index 11c9f28c..066ab9e 100644 --- a/third_party/blink/renderer/modules/xr/xr_coordinate_system.cc +++ b/third_party/blink/renderer/modules/xr/xr_space.cc
@@ -1,23 +1,21 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. +// 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 "third_party/blink/renderer/modules/xr/xr_coordinate_system.h" +#include "third_party/blink/renderer/modules/xr/xr_space.h" #include "third_party/blink/renderer/modules/event_target_modules.h" #include "third_party/blink/renderer/modules/xr/xr_session.h" namespace blink { -XRCoordinateSystem::XRCoordinateSystem(XRSession* session) - : session_(session) {} +XRSpace::XRSpace(XRSession* session) : session_(session) {} -XRCoordinateSystem::~XRCoordinateSystem() = default; +XRSpace::~XRSpace() = default; // If possible, get the matrix required to transform between two coordinate // systems. -DOMFloat32Array* XRCoordinateSystem::getTransformTo( - XRCoordinateSystem* other) const { +DOMFloat32Array* XRSpace::getTransformTo(XRSpace* other) const { if (session_ != other->session()) { // Cannot get relationships between coordinate systems that belong to // different sessions. @@ -30,15 +28,15 @@ return nullptr; } -ExecutionContext* XRCoordinateSystem::GetExecutionContext() const { +ExecutionContext* XRSpace::GetExecutionContext() const { return session()->GetExecutionContext(); } -const AtomicString& XRCoordinateSystem::InterfaceName() const { - return event_target_names::kXRCoordinateSystem; +const AtomicString& XRSpace::InterfaceName() const { + return event_target_names::kXRSpace; } -void XRCoordinateSystem::Trace(blink::Visitor* visitor) { +void XRSpace::Trace(blink::Visitor* visitor) { visitor->Trace(session_); ScriptWrappable::Trace(visitor); EventTargetWithInlineData::Trace(visitor);
diff --git a/third_party/blink/renderer/modules/xr/xr_space.h b/third_party/blink/renderer/modules/xr/xr_space.h new file mode 100644 index 0000000..ca7460c9 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_space.h
@@ -0,0 +1,43 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_SPACE_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_SPACE_H_ + +#include "third_party/blink/renderer/core/dom/events/event_target.h" +#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" +#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/wtf/forward.h" + +namespace blink { + +class XRSession; + +class XRSpace : public EventTargetWithInlineData { + DEFINE_WRAPPERTYPEINFO(); + + public: + explicit XRSpace(XRSession*); + ~XRSpace() override; + + DOMFloat32Array* getTransformTo(XRSpace*) const; + + XRSession* session() const { return session_; } + + DEFINE_ATTRIBUTE_EVENT_LISTENER(reset, kReset); + + // EventTarget overrides. + ExecutionContext* GetExecutionContext() const override; + const AtomicString& InterfaceName() const override; + + void Trace(blink::Visitor*) override; + + private: + const Member<XRSession> session_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_SPACE_H_
diff --git a/third_party/blink/renderer/modules/xr/xr_space.idl b/third_party/blink/renderer/modules/xr/xr_space.idl new file mode 100644 index 0000000..0115c41 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_space.idl
@@ -0,0 +1,12 @@ +// 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. + +// https://immersive-web.github.io/webxr/#xrspace-interface +[ + SecureContext, + Exposed=Window, + OriginTrialEnabled=WebXR +] interface XRSpace : EventTarget { + Float32Array? getTransformTo(XRSpace other); +};
diff --git a/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.cc b/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.cc new file mode 100644 index 0000000..55c227e --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.cc
@@ -0,0 +1,141 @@ +// 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 "third_party/blink/renderer/modules/xr/xr_stationary_reference_space.h" + +#include "device/vr/public/mojom/vr_service.mojom-blink.h" +#include "third_party/blink/renderer/modules/xr/xr_session.h" +#include "third_party/blink/renderer/modules/xr/xr_stage_bounds.h" + +namespace blink { + +// Rough estimate of avg human eye height in meters. +const double kDefaultEmulationHeight = 1.6; + +XRStationaryReferenceSpace::XRStationaryReferenceSpace(XRSession* session, + Subtype subtype) + : XRReferenceSpace(session), subtype_(subtype) { + switch (subtype_) { + case kSubtypeEyeLevel: + subtype_string_ = "eye-level"; + break; + case kSubtypeFloorLevel: + subtype_string_ = "floor-level"; + UpdateFloorLevelTransform(); + break; + case kSubtypePositionDisabled: + subtype_string_ = "position-disabled"; + break; + default: + NOTREACHED() << "Unknown stationary reference space subtype: " << subtype; + } +} + +XRStationaryReferenceSpace::~XRStationaryReferenceSpace() = default; + +void XRStationaryReferenceSpace::UpdateFloorLevelTransform() { + const device::mojom::blink::VRDisplayInfoPtr& display_info = + session()->GetVRDisplayInfo(); + + if (display_info && display_info->stageParameters) { + // Use the transform given by xrDisplayInfo's stageParameters if available. + const WTF::Vector<float>& m = + display_info->stageParameters->standingTransform; + floor_level_transform_ = TransformationMatrix::Create( + m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], + m[11], m[12], m[13], m[14], m[15]); + } else { + // Otherwise, create a transform based on the default emulated height. + floor_level_transform_ = TransformationMatrix::Create(); + floor_level_transform_->Translate3d(0, kDefaultEmulationHeight, 0); + } + + display_info_id_ = session()->DisplayInfoPtrId(); +} + +// Transforms a pose into the correct space. +std::unique_ptr<TransformationMatrix> +XRStationaryReferenceSpace::TransformBasePose( + const TransformationMatrix& base_pose) { + switch (subtype_) { + case kSubtypeEyeLevel: + // Currently all base poses are 'eye-level' poses, so return directly. + return TransformationMatrix::Create(base_pose); + break; + case kSubtypeFloorLevel: + // Currently all base poses are 'eye-level' space, so use of 'floor-level' + // reference spaces requires adjustment. Ideally the service will + // eventually provide poses in the requested space directly, avoiding the + // need to do additional transformation here. + + // Check first to see if the xrDisplayInfo has updated since the last + // call. If so, update the floor-level transform. + if (display_info_id_ != session()->DisplayInfoPtrId()) + UpdateFloorLevelTransform(); + + // Apply the floor-level transform to the base pose. + if (floor_level_transform_) { + std::unique_ptr<TransformationMatrix> pose( + TransformationMatrix::Create(*floor_level_transform_)); + pose->Multiply(base_pose); + return pose; + } + break; + case kSubtypePositionDisabled: { + // 'position-disabled' poses must not contain any translation components, + // and as a result the space the base pose is originally in doesn't matter + // much. Strip out translation component and return. + std::unique_ptr<TransformationMatrix> pose( + TransformationMatrix::Create(base_pose)); + pose->SetM41(0.0); + pose->SetM42(0.0); + pose->SetM43(0.0); + return pose; + } break; + } + + return nullptr; +} + +// Serves the same purpose as TransformBasePose, but for input poses. Needs to +// know the head pose so that cases like the head-model frame of reference can +// properly adjust the input's relative position. +std::unique_ptr<TransformationMatrix> +XRStationaryReferenceSpace::TransformBaseInputPose( + const TransformationMatrix& base_input_pose, + const TransformationMatrix& base_pose) { + switch (subtype_) { + case kSubtypePositionDisabled: { + std::unique_ptr<TransformationMatrix> head_model_pose( + TransformBasePose(base_pose)); + + // Get the positional delta between the base pose and the head model pose. + float dx = head_model_pose->M41() - base_pose.M41(); + float dy = head_model_pose->M42() - base_pose.M42(); + float dz = head_model_pose->M43() - base_pose.M43(); + + // Translate the controller by the same delta so that it shows up in the + // right relative position. + std::unique_ptr<TransformationMatrix> pose( + TransformationMatrix::Create(base_input_pose)); + pose->SetM41(pose->M41() + dx); + pose->SetM42(pose->M42() + dy); + pose->SetM43(pose->M43() + dz); + + return pose; + } break; + case kSubtypeEyeLevel: + case kSubtypeFloorLevel: + return TransformBasePose(base_input_pose); + break; + } + + return nullptr; +} + +void XRStationaryReferenceSpace::Trace(blink::Visitor* visitor) { + XRReferenceSpace::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.h b/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.h new file mode 100644 index 0000000..d1065509b --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.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 THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_STATIONARY_REFERENCE_SPACE_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_STATIONARY_REFERENCE_SPACE_H_ + +#include "third_party/blink/renderer/modules/xr/xr_reference_space.h" +#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h" + +namespace blink { + +class XRStationaryReferenceSpace final : public XRReferenceSpace { + DEFINE_WRAPPERTYPEINFO(); + + public: + enum Subtype { + kSubtypeEyeLevel, + kSubtypeFloorLevel, + kSubtypePositionDisabled + }; + + XRStationaryReferenceSpace(XRSession*, Subtype); + ~XRStationaryReferenceSpace() override; + + std::unique_ptr<TransformationMatrix> TransformBasePose( + const TransformationMatrix& base_pose) override; + std::unique_ptr<TransformationMatrix> TransformBaseInputPose( + const TransformationMatrix& base_input_pose, + const TransformationMatrix& base_pose) override; + + const String& subtype() const { return subtype_string_; } + + void Trace(blink::Visitor*) override; + + private: + void UpdateFloorLevelTransform(); + + unsigned int display_info_id_ = 0; + Subtype subtype_; + String subtype_string_; + std::unique_ptr<TransformationMatrix> floor_level_transform_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_STATIONARY_REFERENCE_SPACE_H_
diff --git a/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.idl b/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.idl new file mode 100644 index 0000000..ac30cc8e --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.idl
@@ -0,0 +1,19 @@ +// 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. + +// https://immersive-web.github.io/webxr/#xrstationaryreferencespace-interface + +enum XRStationaryReferenceSpaceSubtype { + "eye-level", + "floor-level", + "position-disabled" +}; + +[ + SecureContext, + Exposed=Window, + OriginTrialEnabled=WebXR +] interface XRStationaryReferenceSpace : XRReferenceSpace { + readonly attribute XRStationaryReferenceSpaceSubtype subtype; +};
diff --git a/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.cc b/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.cc new file mode 100644 index 0000000..4998f78 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.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 "third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.h" + +#include "device/vr/public/mojom/vr_service.mojom-blink.h" +#include "third_party/blink/renderer/modules/xr/xr_session.h" + +namespace blink { + +XRUnboundedReferenceSpace::XRUnboundedReferenceSpace(XRSession* session) + : XRReferenceSpace(session) {} + +XRUnboundedReferenceSpace::~XRUnboundedReferenceSpace() = default; + +std::unique_ptr<TransformationMatrix> +XRUnboundedReferenceSpace::TransformBasePose( + const TransformationMatrix& base_pose) { + // For now we assume that poses returned by systems that support unbounded + // reference spaces are already in the correct space. + return TransformationMatrix::Create(base_pose); +} + +// Serves the same purpose as TransformBasePose, but for input poses. Needs to +// know the head pose so that cases like the head-model frame of reference can +// properly adjust the input's relative position. +std::unique_ptr<TransformationMatrix> +XRUnboundedReferenceSpace::TransformBaseInputPose( + const TransformationMatrix& base_input_pose, + const TransformationMatrix& base_pose) { + return TransformBasePose(base_input_pose); +} + +void XRUnboundedReferenceSpace::Trace(blink::Visitor* visitor) { + XRReferenceSpace::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.h b/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.h new file mode 100644 index 0000000..750e90d4 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.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 THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_UNBOUNDED_REFERENCE_SPACE_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_UNBOUNDED_REFERENCE_SPACE_H_ + +#include "third_party/blink/renderer/modules/xr/xr_reference_space.h" +#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h" + +namespace blink { + +class XRUnboundedReferenceSpace final : public XRReferenceSpace { + DEFINE_WRAPPERTYPEINFO(); + + public: + XRUnboundedReferenceSpace(XRSession*); + ~XRUnboundedReferenceSpace() override; + + std::unique_ptr<TransformationMatrix> TransformBasePose( + const TransformationMatrix& base_pose) override; + std::unique_ptr<TransformationMatrix> TransformBaseInputPose( + const TransformationMatrix& base_input_pose, + const TransformationMatrix& base_pose) override; + + void Trace(blink::Visitor*) override; + + private: + std::unique_ptr<TransformationMatrix> pose_transform_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_UNBOUNDED_REFERENCE_SPACE_H_
diff --git a/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.idl b/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.idl new file mode 100644 index 0000000..4826c55 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.idl
@@ -0,0 +1,12 @@ +// 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. + +// https://immersive-web.github.io/webxr/#xrunboundedreferencespace-interface + +[ + SecureContext, + Exposed=Window, + OriginTrialEnabled=WebXR +] interface XRUnboundedReferenceSpace : XRReferenceSpace { +};
diff --git a/third_party/blink/renderer/platform/exported/web_url_response.cc b/third_party/blink/renderer/platform/exported/web_url_response.cc index 1cbdb450..c592a50 100644 --- a/third_party/blink/renderer/platform/exported/web_url_response.cc +++ b/third_party/blink/renderer/platform/exported/web_url_response.cc
@@ -344,10 +344,6 @@ return resource_response_->UrlListViaServiceWorker().size() > 0; } -void WebURLResponse::SetMultipartBoundary(const char* bytes, size_t size) { - resource_response_->SetMultipartBoundary(bytes, size); -} - void WebURLResponse::SetCacheStorageCacheName( const WebString& cache_storage_cache_name) { resource_response_->SetCacheStorageCacheName(cache_storage_cache_name);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response.h b/third_party/blink/renderer/platform/loader/fetch/resource_response.h index d35e413..78178dbd3 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_response.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_response.h
@@ -200,8 +200,6 @@ void ClearHTTPHeaderField(const AtomicString& name); const HTTPHeaderMap& HttpHeaderFields() const; - bool IsMultipart() const { return MimeType() == "multipart/x-mixed-replace"; } - bool IsAttachment() const; AtomicString HttpContentType() const; @@ -330,12 +328,6 @@ url_list_via_service_worker_ = url_list; } - const Vector<char>& MultipartBoundary() const { return multipart_boundary_; } - void SetMultipartBoundary(const char* bytes, uint32_t size) { - multipart_boundary_.clear(); - multipart_boundary_.Append(bytes, size); - } - const String& CacheStorageCacheName() const { return cache_storage_cache_name_; } @@ -530,9 +522,6 @@ // Note: only valid for main resource responses. KURL app_cache_manifest_url_; - // The multipart boundary of this response. - Vector<char> multipart_boundary_; - // The URL list of the response which was fetched by the ServiceWorker. // This is empty if the response was created inside the ServiceWorker. Vector<KURL> url_list_via_service_worker_;
diff --git a/third_party/blink/renderer/platform/network/network_utils.cc b/third_party/blink/renderer/platform/network/network_utils.cc index a50c5d9..da84fc6 100644 --- a/third_party/blink/renderer/platform/network/network_utils.cc +++ b/third_party/blink/renderer/platform/network/network_utils.cc
@@ -133,6 +133,21 @@ net::HttpUtil::GenerateAcceptLanguageHeader(string)); } +Vector<char> ParseMultipartBoundary(const AtomicString& content_type_header) { + CString cstring(content_type_header.Utf8()); + std::string string(cstring.data(), cstring.length()); + std::string mime_type; + std::string charset; + bool had_charset = false; + std::string boundary; + net::HttpUtil::ParseContentType(string, &mime_type, &charset, &had_charset, + &boundary); + base::TrimString(boundary, " \"", &boundary); + Vector<char> result; + result.Append(boundary.data(), boundary.size()); + return result; +} + } // namespace network_utils } // namespace blink
diff --git a/third_party/blink/renderer/platform/network/network_utils.h b/third_party/blink/renderer/platform/network/network_utils.h index ac3cb6f..e974120 100644 --- a/third_party/blink/renderer/platform/network/network_utils.h +++ b/third_party/blink/renderer/platform/network/network_utils.h
@@ -46,6 +46,9 @@ PLATFORM_EXPORT String GenerateAcceptLanguageHeader(const String&); +PLATFORM_EXPORT Vector<char> ParseMultipartBoundary( + const AtomicString& content_type_header); + } // namespace network_utils } // namespace blink
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint index 65194d1..f98c60ca 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -7,7 +7,6 @@ Bug(none) external/wpt [ Skip ] Bug(none) http/tests/devtools/layers/ [ Skip ] Bug(none) http/tests/devtools/tracing/ [ Skip ] -Bug(none) plugins/ [ Skip ] Bug(none) printing/ [ Skip ] Bug(none) scrollbars/ [ Skip ] Bug(none) scrollingcoordinator/ [ Skip ] @@ -200,7 +199,6 @@ Bug(none) ietestcenter/css3/bordersbackgrounds/background-attachment-local-scrolling.htm [ Failure ] Bug(none) inspector-protocol/layers/paint-profiler.js [ Failure ] Bug(none) inspector-protocol/layers/get-layers.js [ Timeout ] -crbug.com/912357 media/video-object-fit.html [ Failure ] Bug(none) paint/pagination/pagination-change-clip-crash.html [ Failure ] Bug(none) virtual/sampling-heap-profiler/inspector-protocol/memory/sampling-native-profile-blink-gc.js [ Failure ]
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-features=NetworkService b/third_party/blink/web_tests/FlagExpectations/enable-features=NetworkService index f2cd391..425ee60 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-features=NetworkService +++ b/third_party/blink/web_tests/FlagExpectations/enable-features=NetworkService
@@ -19,17 +19,6 @@ # enabled this fails in both content_shell and chrome. Bug(none) http/tests/misc/redirect-to-about-blank.html [ Timeout ] -# Reports aren't allowed under content_shell NS -crbug.com/910212 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-404.https.html [ Failure ] -crbug.com/910212 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-cache-validation.https.html [ Failure ] -crbug.com/910212 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-redirect.https.html [ Failure ] -crbug.com/910212 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-subdomain-dns-failure.https.html [ Failure ] -crbug.com/910212 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-success-with-subdomain-policy.https.html [ Failure ] -crbug.com/910212 virtual/network-error-logging/external/wpt/network-error-logging/sends-report-on-success.https.html [ Failure ] -crbug.com/910212 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-report-only-sends-reports-on-violation.https.sub.html [ Failure ] -crbug.com/910212 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub.html [ Failure ] -crbug.com/910212 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-works-on-frame-src.https.sub.html [ Failure ] - # Skip virtual/outofblink-cors when NetworkService is on, since it's only # intended to be run with NetworkService off. Bug(none) virtual/outofblink-cors [ Skip ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 1e174b9..e4a88ba 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -6034,7 +6034,7 @@ crbug.com/917284 virtual/outofblink-cors/external/wpt/service-workers/service-worker/claim-fetch-with-appcache.https.html [ Failure ] # Sheriff 2018-12-27 -crbug.com/917970 [ Mac10.13 ] virtual/mouseevent_fractional/fast/events/popup-blocking-timers5.html [ Pass Failure ] +crbug.com/917970 [ Mac10.13 Retina ] virtual/mouseevent_fractional/fast/events/popup-blocking-timers5.html [ Pass Failure ] # Sheriff 2019-01-03 -crbug.com/918905 [ Mac10.13 ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/block-size-with-min-or-max-content-table-1b.html [ Pass Failure ] +crbug.com/918905 [ Mac Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/block-size-with-min-or-max-content-table-1b.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/compositing/lots-of-img-layers-expected.png b/third_party/blink/web_tests/compositing/lots-of-img-layers-expected.png new file mode 100644 index 0000000..08a3393 --- /dev/null +++ b/third_party/blink/web_tests/compositing/lots-of-img-layers-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json index fed2886..4d94a9d2 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -50407,6 +50407,18 @@ {} ] ], + "css/css-lists/li-with-height-001.html": [ + [ + "/css/css-lists/li-with-height-001.html", + [ + [ + "/css/css-lists/li-with-height-001-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-logical/cascading-001.html": [ [ "/css/css-logical/cascading-001.html", @@ -137584,6 +137596,11 @@ {} ] ], + "css/css-lists/li-with-height-001-ref.html": [ + [ + {} + ] + ], "css/css-logical/META.yml": [ [ {} @@ -169489,6 +169506,11 @@ {} ] ], + "html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/empty-iframe.html": [ + [ + {} + ] + ], "html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/Function.js": [ [ {} @@ -169529,6 +169551,11 @@ {} ] ], + "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document-expected.txt": [ + [ + {} + ] + ], "html/semantics/scripting-1/the-script-element/module/error-type-1.js": [ [ {} @@ -242038,6 +242065,12 @@ {} ] ], + "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document.html": [ + [ + "/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document.html", + {} + ] + ], "html/semantics/scripting-1/the-script-element/module/error-and-slow-dependency.html": [ [ "/html/semantics/scripting-1/the-script-element/module/error-and-slow-dependency.html", @@ -285334,9 +285367,9 @@ {} ] ], - "webxr/xrSession_requestFrameOfReference.https.html": [ + "webxr/xrSession_requestReferenceSpace.https.html": [ [ - "/webxr/xrSession_requestFrameOfReference.https.html", + "/webxr/xrSession_requestReferenceSpace.https.html", {} ] ], @@ -345565,6 +345598,14 @@ "ff1bcdcfb4690df571dc2d5c93df71b55ffad5e6", "testharness" ], + "css/css-lists/li-with-height-001-ref.html": [ + "486009d5604ab7a2cb66df735efff3c11c00b685", + "support" + ], + "css/css-lists/li-with-height-001.html": [ + "ad2ac65e179714dd5fb85de6b67a6f097823a507", + "reftest" + ], "css/css-lists/list-style-type-armenian-002.xht": [ "02e06b707f709870b30e810e4b1a4ec330ada296", "visual" @@ -358062,11 +358103,11 @@ "support" ], "css/css-transforms/animation/list-interpolation-expected.txt": [ - "c68eda71307495412f8a58fbc6513c6e6a3b4a77", + "7d67a780f508d185f7b9b8b310c15d126a57813a", "support" ], "css/css-transforms/animation/list-interpolation.html": [ - "90cdebbb6cdb643e4c55cb7c0dcd5340fad9a9bd", + "af221e5feaee92734f89185a413e3cd2dc57bc29", "testharness" ], "css/css-transforms/animation/matrix-interpolation-expected.txt": [ @@ -409137,6 +409178,10 @@ "f3322773a42b11868bd472cb004ea5ca41f224f1", "testharness" ], + "html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/empty-iframe.html": [ + "ad5ab30eda15c3f755c8c00b3b81029432e242d9", + "support" + ], "html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/Function.js": [ "bc88bf7bd637a06e5f1fc23743470144b1dfb55f", "support" @@ -409213,6 +409258,14 @@ "e0e3ec8a94df8b0a27ae513fc6412da1fb87062c", "testharness" ], + "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document-expected.txt": [ + "4b0d1b50ee45337bd9b2bfa7d479ee5b6cdd508c", + "support" + ], + "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document.html": [ + "a9c0528216166a458e48902c2c722a548432f4dd", + "testharness" + ], "html/semantics/scripting-1/the-script-element/module/error-and-slow-dependency.html": [ "f336276f3fcdbe1777b0c3bcf3140999655011b4", "testharness" @@ -446482,7 +446535,7 @@ "testharness" ], "web-animations/animation-model/animation-types/interpolation-per-property-expected.txt": [ - "ed7a98cf89673b19eaee5d36e55f1f4c9559f807", + "0f680fe164f073b84288be0a442b65c5467c12fe", "support" ], "web-animations/animation-model/animation-types/interpolation-per-property.html": [ @@ -454329,7 +454382,7 @@ "c6d5c1024fbadfa95af7a70216b2338fc43aef1b", "testharness" ], - "webxr/xrSession_requestFrameOfReference.https.html": [ + "webxr/xrSession_requestReferenceSpace.https.html": [ "ea758761e59de144a742019cc386b083639db6c9", "testharness" ],
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/stacking-context/opacity-change-parent-stacking-context.html b/third_party/blink/web_tests/external/wpt/css/CSS2/stacking-context/opacity-change-parent-stacking-context.html index 36033e92..94587c5 100644 --- a/third_party/blink/web_tests/external/wpt/css/CSS2/stacking-context/opacity-change-parent-stacking-context.html +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/stacking-context/opacity-change-parent-stacking-context.html
@@ -1,18 +1,21 @@ <!doctype HTML> -<title>CSS Test: Test for re-paint after stacking context removal due to opacity</title> -<link rel="author" title="Chris Harrelson" href="mailto:chrishtr@chromium.org" /> -<link rel="help" href="https://www.w3.org/TR/CSS2/zindex.html"> -<link rel="match" href="opacity-change-parent-stacking-context-ref.html"> -<div style="width: 100px; height: 100px; background: lightblue; will-change: transform; position: absolute"> - <div id=target style="opacity: 0; backface-visibility: hidden"> - <div style="width: 50px; height: 50px; background: lightgray; top: 75px; position: relative"> +<html class="reftest-wait"> + <title>CSS Test: Test for re-paint after stacking context removal due to opacity</title> + <link rel="author" title="Chris Harrelson" href="mailto:chrishtr@chromium.org" /> + <link rel="help" href="https://www.w3.org/TR/CSS2/zindex.html"> + <link rel="match" href="opacity-change-parent-stacking-context-ref.html"> + <script src="/common/reftest-wait.js"></script> + <div style="width: 100px; height: 100px; background: lightblue; will-change: transform; position: absolute"> + <div id=target style="opacity: 0; backface-visibility: hidden"> + <div style="width: 50px; height: 50px; background: lightgray; top: 75px; position: relative"> + </div> </div> -</div> - -<script> - onload = function() { - requestAnimationFrame(() => requestAnimationFrame(() => { - target.style.opacity = 1; - })); - } -</script> + <script> + onload = function() { + requestAnimationFrame(() => requestAnimationFrame(() => { + target.style.opacity = 1; + takeScreenshot(); + })); + } + </script> +</html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/size-change-under-backface-visibility-hidden-ref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/size-change-under-backface-visibility-hidden-ref.html new file mode 100644 index 0000000..e9362c3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/size-change-under-backface-visibility-hidden-ref.html
@@ -0,0 +1,9 @@ +<!doctype HTML> +<title>CSS Test</title> +<link rel="author" title="Chris Harrelson" href="mailto:chrishtr@chromium.org" /> +Passes if it shows a green 200x200 square. +<div style="will-change: transform; width: 300px; height: 0px"> + <div style="width: 1px; height: 1px; backface-visibility: hidden;"> + <div id=target style="width: 200px; height: 200px; position: relative; background: green; left: 10px;"></div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/size-change-under-backface-visibility-hidden.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/size-change-under-backface-visibility-hidden.html new file mode 100644 index 0000000..1543eeb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/size-change-under-backface-visibility-hidden.html
@@ -0,0 +1,22 @@ +<!doctype HTML> +<html class="reftest-wait"> + <title>CSS Test: Test for re-paint after resizing an element underneath a backface-visibility hidden element</title> + <link rel="author" title="Chris Harrelson" href="mailto:chrishtr@chromium.org" /> + <link rel="help" href="https://drafts.csswg.org/css-transforms-2/#propdef-backface-visibility"> + <link rel="match" href="size-change-under-backface-visibility-hidden-ref.html"> + <script src="/common/reftest-wait.js"></script> + Passes if it shows a green 200x200 square. + <div style="will-change: transform; width: 300px; height: 0px"> + <div style="width: 1px; height: 1px; backface-visibility: hidden;"> + <div id=target style="width: 200px; height: 0px; position: relative; background: green; left: 10px;"></div> + </div> + </div> + <script> + onload = function() { + requestAnimationFrame(() => requestAnimationFrame(() => { + target.style.height = '200px'; + takeScreenshot(); + })); + }; + </script> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/empty-iframe.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/empty-iframe.html new file mode 100644 index 0000000..ad5ab30ed --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/empty-iframe.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + </head> + <body> + <div id="dummy"></div> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document-expected.txt new file mode 100644 index 0000000..4b0d1b5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document-expected.txt
@@ -0,0 +1,8 @@ +This is a testharness.js-based test. +PASS eval should successfully import +FAIL setTimeout should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/dynamic-import/imports-a.js?label=setTimeout" +PASS the Function constructor should successfully import +FAIL reflected inline event handlers should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/dynamic-import/imports-a.js?label=reflected%20inline%20event%20handlers" +FAIL inline event handlers triggered by JS should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/dynamic-import/imports-a.js?label=inline%20event%20handlers%20triggered%20by%20JS" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document.html new file mode 100644 index 0000000..a9c05282 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document.html
@@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<title>Check import() works when active script is in another document</title> +<link rel="author" title="Jon Coppeard" href="mailto:jcoppeard@mozilla.com"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> + +<iframe id="frame" src="resources/empty-iframe.html"></iframe> + +<script> + +function startTest() { + const otherWindow = document.getElementById("frame").contentWindow; + const otherDiv = otherWindow.document.getElementById("dummy"); + + function createTestPromise() { + return new Promise((resolve, reject) => { + otherWindow.continueTest = resolve; + otherWindow.errorTest = reject; + }); + } + + const evaluators = { + eval: otherWindow.eval, + setTimeout: otherWindow.setTimeout, + "the Function constructor"(x) { + otherWindow.Function(x)(); + }, + "reflected inline event handlers"(x) { + otherDiv.setAttribute("onclick", x); + otherDiv.onclick(); + }, + "inline event handlers triggered by JS"(x) { + otherDiv.setAttribute("onclick", x); + otherDiv.click(); // different from .**on**click() + } + }; + + for (const [label, evaluator] of Object.entries(evaluators)) { + promise_test(t => { + t.add_cleanup(() => { + otherDiv.removeAttribute("onclick"); + delete otherWindow.evaluated_imports_a; + }); + + const promise = createTestPromise(); + + evaluator(`import('../imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`); + + return promise.then(module => { + assert_true(otherWindow.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); + }, label + " should successfully import"); + }; +} +</script> +<body onLoad="startTest()"></body>
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-host-null.html b/third_party/blink/web_tests/external/wpt/portals/portals-host-null.html new file mode 100644 index 0000000..e0f1d63 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/portals/portals-host-null.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script> + test(t => { + assert_equals(window.portalHost, null, "window.portalHost should be null"); + }); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt index 27484b4..4eb2240 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
@@ -31,7 +31,7 @@ PASS XRSession interface: attribute depthNear PASS XRSession interface: attribute depthFar PASS XRSession interface: attribute baseLayer -FAIL XRSession interface: operation requestReferenceSpace(XRReferenceSpaceType, XRReferenceSpaceOptions) assert_own_property: interface prototype object missing non-static operation expected property "requestReferenceSpace" missing +PASS XRSession interface: operation requestReferenceSpace(XRReferenceSpaceType, XRReferenceSpaceOptions) PASS XRSession interface: operation getInputSources() PASS XRSession interface: operation requestAnimationFrame(XRFrameRequestCallback) PASS XRSession interface: operation cancelAnimationFrame(long) @@ -52,40 +52,40 @@ PASS XRFrame interface: attribute session FAIL XRFrame interface: operation getViewerPose(XRReferenceSpace) assert_equals: property has wrong .length expected 0 but got 1 FAIL XRFrame interface: operation getInputPose(XRInputSource, XRReferenceSpace) assert_equals: property has wrong .length expected 1 but got 2 -FAIL XRSpace interface: existence and properties of interface object assert_own_property: self does not have own property "XRSpace" expected property "XRSpace" missing -FAIL XRSpace interface object length assert_own_property: self does not have own property "XRSpace" expected property "XRSpace" missing -FAIL XRSpace interface object name assert_own_property: self does not have own property "XRSpace" expected property "XRSpace" missing -FAIL XRSpace interface: existence and properties of interface prototype object assert_own_property: self does not have own property "XRSpace" expected property "XRSpace" missing -FAIL XRSpace interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "XRSpace" expected property "XRSpace" missing -FAIL XRSpace interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "XRSpace" expected property "XRSpace" missing -FAIL XRSpace interface: operation getTransformTo(XRSpace) assert_own_property: self does not have own property "XRSpace" expected property "XRSpace" missing -FAIL XRReferenceSpace interface: existence and properties of interface object assert_own_property: self does not have own property "XRReferenceSpace" expected property "XRReferenceSpace" missing -FAIL XRReferenceSpace interface object length assert_own_property: self does not have own property "XRReferenceSpace" expected property "XRReferenceSpace" missing -FAIL XRReferenceSpace interface object name assert_own_property: self does not have own property "XRReferenceSpace" expected property "XRReferenceSpace" missing -FAIL XRReferenceSpace interface: existence and properties of interface prototype object assert_own_property: self does not have own property "XRReferenceSpace" expected property "XRReferenceSpace" missing -FAIL XRReferenceSpace interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "XRReferenceSpace" expected property "XRReferenceSpace" missing -FAIL XRReferenceSpace interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "XRReferenceSpace" expected property "XRReferenceSpace" missing -FAIL XRReferenceSpace interface: attribute onreset assert_own_property: self does not have own property "XRReferenceSpace" expected property "XRReferenceSpace" missing -FAIL XRStationaryReferenceSpace interface: existence and properties of interface object assert_own_property: self does not have own property "XRStationaryReferenceSpace" expected property "XRStationaryReferenceSpace" missing -FAIL XRStationaryReferenceSpace interface object length assert_own_property: self does not have own property "XRStationaryReferenceSpace" expected property "XRStationaryReferenceSpace" missing -FAIL XRStationaryReferenceSpace interface object name assert_own_property: self does not have own property "XRStationaryReferenceSpace" expected property "XRStationaryReferenceSpace" missing -FAIL XRStationaryReferenceSpace interface: existence and properties of interface prototype object assert_own_property: self does not have own property "XRStationaryReferenceSpace" expected property "XRStationaryReferenceSpace" missing -FAIL XRStationaryReferenceSpace interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "XRStationaryReferenceSpace" expected property "XRStationaryReferenceSpace" missing -FAIL XRStationaryReferenceSpace interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "XRStationaryReferenceSpace" expected property "XRStationaryReferenceSpace" missing -FAIL XRStationaryReferenceSpace interface: attribute subtype assert_own_property: self does not have own property "XRStationaryReferenceSpace" expected property "XRStationaryReferenceSpace" missing -FAIL XRBoundedReferenceSpace interface: existence and properties of interface object assert_own_property: self does not have own property "XRBoundedReferenceSpace" expected property "XRBoundedReferenceSpace" missing -FAIL XRBoundedReferenceSpace interface object length assert_own_property: self does not have own property "XRBoundedReferenceSpace" expected property "XRBoundedReferenceSpace" missing -FAIL XRBoundedReferenceSpace interface object name assert_own_property: self does not have own property "XRBoundedReferenceSpace" expected property "XRBoundedReferenceSpace" missing -FAIL XRBoundedReferenceSpace interface: existence and properties of interface prototype object assert_own_property: self does not have own property "XRBoundedReferenceSpace" expected property "XRBoundedReferenceSpace" missing -FAIL XRBoundedReferenceSpace interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "XRBoundedReferenceSpace" expected property "XRBoundedReferenceSpace" missing -FAIL XRBoundedReferenceSpace interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "XRBoundedReferenceSpace" expected property "XRBoundedReferenceSpace" missing -FAIL XRBoundedReferenceSpace interface: attribute boundsGeometry assert_own_property: self does not have own property "XRBoundedReferenceSpace" expected property "XRBoundedReferenceSpace" missing -FAIL XRUnboundedReferenceSpace interface: existence and properties of interface object assert_own_property: self does not have own property "XRUnboundedReferenceSpace" expected property "XRUnboundedReferenceSpace" missing -FAIL XRUnboundedReferenceSpace interface object length assert_own_property: self does not have own property "XRUnboundedReferenceSpace" expected property "XRUnboundedReferenceSpace" missing -FAIL XRUnboundedReferenceSpace interface object name assert_own_property: self does not have own property "XRUnboundedReferenceSpace" expected property "XRUnboundedReferenceSpace" missing -FAIL XRUnboundedReferenceSpace interface: existence and properties of interface prototype object assert_own_property: self does not have own property "XRUnboundedReferenceSpace" expected property "XRUnboundedReferenceSpace" missing -FAIL XRUnboundedReferenceSpace interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "XRUnboundedReferenceSpace" expected property "XRUnboundedReferenceSpace" missing -FAIL XRUnboundedReferenceSpace interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "XRUnboundedReferenceSpace" expected property "XRUnboundedReferenceSpace" missing +PASS XRSpace interface: existence and properties of interface object +PASS XRSpace interface object length +PASS XRSpace interface object name +PASS XRSpace interface: existence and properties of interface prototype object +PASS XRSpace interface: existence and properties of interface prototype object's "constructor" property +PASS XRSpace interface: existence and properties of interface prototype object's @@unscopables property +PASS XRSpace interface: operation getTransformTo(XRSpace) +PASS XRReferenceSpace interface: existence and properties of interface object +PASS XRReferenceSpace interface object length +PASS XRReferenceSpace interface object name +PASS XRReferenceSpace interface: existence and properties of interface prototype object +PASS XRReferenceSpace interface: existence and properties of interface prototype object's "constructor" property +PASS XRReferenceSpace interface: existence and properties of interface prototype object's @@unscopables property +PASS XRReferenceSpace interface: attribute onreset +PASS XRStationaryReferenceSpace interface: existence and properties of interface object +PASS XRStationaryReferenceSpace interface object length +PASS XRStationaryReferenceSpace interface object name +PASS XRStationaryReferenceSpace interface: existence and properties of interface prototype object +PASS XRStationaryReferenceSpace interface: existence and properties of interface prototype object's "constructor" property +PASS XRStationaryReferenceSpace interface: existence and properties of interface prototype object's @@unscopables property +PASS XRStationaryReferenceSpace interface: attribute subtype +PASS XRBoundedReferenceSpace interface: existence and properties of interface object +PASS XRBoundedReferenceSpace interface object length +PASS XRBoundedReferenceSpace interface object name +PASS XRBoundedReferenceSpace interface: existence and properties of interface prototype object +PASS XRBoundedReferenceSpace interface: existence and properties of interface prototype object's "constructor" property +PASS XRBoundedReferenceSpace interface: existence and properties of interface prototype object's @@unscopables property +PASS XRBoundedReferenceSpace interface: attribute boundsGeometry +PASS XRUnboundedReferenceSpace interface: existence and properties of interface object +PASS XRUnboundedReferenceSpace interface object length +PASS XRUnboundedReferenceSpace interface object name +PASS XRUnboundedReferenceSpace interface: existence and properties of interface prototype object +PASS XRUnboundedReferenceSpace interface: existence and properties of interface prototype object's "constructor" property +PASS XRUnboundedReferenceSpace interface: existence and properties of interface prototype object's @@unscopables property PASS XRView interface: existence and properties of interface object PASS XRView interface object length PASS XRView interface object name
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html index 4093d7af..5f825fa 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html
@@ -34,8 +34,8 @@ let testFunction = function(session, testDeviceController) { testSession = session; - return session.requestFrameOfReference('eye-level') - .then((frameOfRef) => new Promise((resolve) => { + return session.requestReferenceSpace({ type: 'stationary', subtype: 'eye-level' }) + .then((referenceSpace) => new Promise((resolve) => { function onFrame(time, xrFrame) { assert_true(xrFrame instanceof XRFrame); @@ -43,7 +43,7 @@ assert_not_equals(xrFrame.views, null); assert_equals(xrFrame.views.length, 2); - let viewerPose = xrFrame.getViewerPose(frameOfRef); + let viewerPose = xrFrame.getViewerPose(referenceSpace); assert_not_equals(viewerPose, null); for(let i = 0; i < identityMatrix.length; i++) {
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html index c6d5c102..17b5307 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html
@@ -23,15 +23,15 @@ const validViewMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 3, 2, 1]; let testFunction = function(session, fakeDeviceController, t) { - return session.requestFrameOfReference("eye-level") - .then((frameOfRef) => new Promise((resolve, reject) => { + return session.requestReferenceSpace({ type: 'stationary', subtype: 'eye-level' }) + .then((referenceSpace) => new Promise((resolve, reject) => { let counter = 0; function onFrame(time, vrFrame) { session.requestAnimationFrame(onFrame); if (counter == 0) { t.step( () => { // Expecting to not get a pose since none has been supplied - assert_equals(vrFrame.getViewerPose(frameOfRef), null); + assert_equals(vrFrame.getViewerPose(referenceSpace), null); fakeDeviceController.setXRPresentationFrameData( validPoseMatrix, [{ @@ -45,11 +45,11 @@ }]); // Check that pose does not update pose within the same frame. - assert_equals(vrFrame.getViewerPose(frameOfRef), null); + assert_equals(vrFrame.getViewerPose(referenceSpace), null); }); } else { t.step( () => { - let pose = vrFrame.getViewerPose(frameOfRef); + let pose = vrFrame.getViewerPose(referenceSpace); assert_not_equals(pose, null); let poseMatrix = pose.poseModelMatrix;
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestFrameOfReference.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestFrameOfReference.https.html deleted file mode 100644 index ea75876..0000000 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestFrameOfReference.https.html +++ /dev/null
@@ -1,49 +0,0 @@ -<!DOCTYPE html> -<body> - <script src=/resources/testharness.js></script> - <script src=/resources/testharnessreport.js></script> - <script src="resources/webxr_util.js"></script> - <canvas></canvas> - <script> - - let immersiveTestName = - "Immersive XRSession requestFrameOfReference returns expected objects"; - let nonImmersiveTestName = - "Non-immersive XRSession requestFrameOfReference returns expected objects"; - - let fakeDeviceInitParams = { supportsImmersive: true }; - - let immersiveSessionOptions = { immersive: true }; - let nonImmersiveSessionOptions = { outputContext: getOutputContext() }; - - let testFunction = function(session, fakeDeviceController, t) { - return promise_rejects(t, new TypeError(), session.requestFrameOfReference("foo")) - .then(() => Promise.all([ - session.requestFrameOfReference("head-model").then( (frameOfRef) => { - assert_true(frameOfRef instanceof XRCoordinateSystem, - "head-model frameOfRef is not correct type."); - assert_true(frameOfRef instanceof XRFrameOfReference, - "head-model frameOfRef is not correct type."); - }), - session.requestFrameOfReference("eye-level").then( (frameOfRef) => { - assert_true(frameOfRef instanceof XRCoordinateSystem, - "eye-level frameOfRef is not correct type."); - assert_true(frameOfRef instanceof XRFrameOfReference, - "eye-level frameOfRef is not correct type."); - }), - session.requestFrameOfReference("stage").then( (frameOfRef) => { - assert_true(frameOfRef instanceof XRCoordinateSystem, - "stage frameOfRef is not correct type."); - assert_true(frameOfRef instanceof XRFrameOfReference, - "stage frameOfRef is not correct type."); - }) - ])); - }; - - xr_session_promise_test( - immersiveTestName, testFunction, fakeDeviceInitParams, immersiveSessionOptions); - xr_session_promise_test( - nonImmersiveTestName, testFunction, fakeDeviceInitParams, nonImmersiveSessionOptions); - - </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html new file mode 100644 index 0000000..d97852c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html
@@ -0,0 +1,75 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas></canvas> + <script> + + let immersiveTestName = + "Immersive XRSession requestReferenceSpace returns expected objects"; + let nonImmersiveTestName = + "Non-immersive XRSession requestReferenceSpace returns expected objects"; + + let fakeDeviceInitParams = { supportsImmersive: true }; + + let immersiveSessionOptions = { immersive: true }; + let nonImmersiveSessionOptions = { outputContext: getOutputContext() }; + + let testFunction = function(session, fakeDeviceController, t) { + return promise_rejects(t, new TypeError(), session.requestReferenceSpace({ type: "foo" })) + .then(() => promise_rejects(t, "NotSupportedError", session.requestReferenceSpace({ type: "stationary" }))) + .then(() => promise_rejects(t, new TypeError(), session.requestReferenceSpace({ type: "stationary", subtype: "bar" }))) + .then(() => Promise.all([ + session.requestReferenceSpace({ type: "stationary", subtype: "position-disabled" }).then( (referenceSpace) => { + t.step(() => { + assert_true(referenceSpace instanceof XRSpace, + "position-disabled stationary reference space is not correct type."); + assert_true(referenceSpace instanceof XRReferenceSpace, + "position-disabled stationary reference space is not correct type."); + assert_true(referenceSpace instanceof XRStationaryReferenceSpace, + "position-disabled stationary reference space is not correct type."); + }); + }), + session.requestReferenceSpace({ type: "stationary", subtype: "eye-level" }).then( (referenceSpace) => { + t.step(() => { + assert_true(referenceSpace instanceof XRSpace, + "eye-level stationary reference space is not correct type."); + assert_true(referenceSpace instanceof XRReferenceSpace, + "eye-level stationary reference space is not correct type."); + assert_true(referenceSpace instanceof XRStationaryReferenceSpace, + "eye-level stationary reference space is not correct type."); + }); + }), + session.requestReferenceSpace({ type: "stationary", subtype: "floor-level" }).then( (referenceSpace) => { + t.step(() => { + assert_true(referenceSpace instanceof XRSpace, + "floor-level stationary reference space is not correct type."); + assert_true(referenceSpace instanceof XRReferenceSpace, + "floor-level stationary reference space is not correct type."); + assert_true(referenceSpace instanceof XRStationaryReferenceSpace, + "floor-level stationary reference space is not correct type."); + }); + }) + ])) + .then(() => { + if (!session.immersive) { + // Bounded reference spaces are not allowed in inline sessions. + return promise_rejects(t, "NotSupportedError", session.requestReferenceSpace({ type: "bounded" })) + } + }) + .then(() => { + if (!session.immersive) { + // Unbounded reference spaces are not allowed in inline sessions. + return promise_rejects(t, "NotSupportedError", session.requestReferenceSpace({ type: "unbounded" })) + } + }) + }; + + xr_session_promise_test( + immersiveTestName, testFunction, fakeDeviceInitParams, immersiveSessionOptions); + xr_session_promise_test( + nonImmersiveTestName, testFunction, fakeDeviceInitParams, nonImmersiveSessionOptions); + + </script> +</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt index c9b062b..352726f 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -211,6 +211,7 @@ PASS oldChildWindow.performance.timing.unloadEventEnd is newChildWindow.performance.timing.unloadEventEnd PASS oldChildWindow.performance.timing.unloadEventStart is newChildWindow.performance.timing.unloadEventStart PASS oldChildWindow.personalbar.visible is newChildWindow.personalbar.visible +PASS oldChildWindow.portalHost is newChildWindow.portalHost PASS oldChildWindow.screen.availHeight is newChildWindow.screen.availHeight PASS oldChildWindow.screen.availLeft is newChildWindow.screen.availLeft PASS oldChildWindow.screen.availTop is newChildWindow.screen.availTop
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt index bd8e4ec0..4ac84a4 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
@@ -151,6 +151,7 @@ PASS childWindow.pageYOffset is 0 PASS childWindow.performance.onresourcetimingbufferfull is null PASS childWindow.personalbar.visible is false +PASS childWindow.portalHost is null PASS childWindow.screen.availHeight is 0 PASS childWindow.screen.availLeft is 0 PASS childWindow.screen.availTop is 0
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt index 217db59..6d55bba 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
@@ -151,6 +151,7 @@ PASS childWindow.pageYOffset is 0 PASS childWindow.performance.onresourcetimingbufferfull is null PASS childWindow.personalbar.visible is false +PASS childWindow.portalHost is null PASS childWindow.screen.availHeight is 0 PASS childWindow.screen.availLeft is 0 PASS childWindow.screen.availTop is 0
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/media/video-zoom-controls-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/media/video-zoom-controls-expected.png index 0bdfbb3..a8089edb 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/media/video-zoom-controls-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/media/video-zoom-controls-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/text-selection-rect-in-overflow-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/text-selection-rect-in-overflow-expected.txt index c7f2d84..b86ac26 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/text-selection-rect-in-overflow-expected.txt +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/text-selection-rect-in-overflow-expected.txt
@@ -21,11 +21,6 @@ "object": "NGPhysicalTextFragment 'Should have green background'", "rect": [8, 8, 197, 20], "reason": "selection" - }, - { - "object": "LayoutNGBlockFlow DIV id='t'", - "rect": [8, 27, 197, 1], - "reason": "incremental" } ] }
diff --git a/third_party/blink/web_tests/platform/linux/compositing/direct-image-compositing-expected.png b/third_party/blink/web_tests/platform/linux/compositing/direct-image-compositing-expected.png index b9ff78c..bb3c623 100644 --- a/third_party/blink/web_tests/platform/linux/compositing/direct-image-compositing-expected.png +++ b/third_party/blink/web_tests/platform/linux/compositing/direct-image-compositing-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/direct-image-compositing-expected.png b/third_party/blink/web_tests/platform/mac/compositing/direct-image-compositing-expected.png index 38758c7..f0fe9800 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/direct-image-compositing-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/direct-image-compositing-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/lots-of-img-layers-expected.png b/third_party/blink/web_tests/platform/mac/compositing/lots-of-img-layers-expected.png deleted file mode 100644 index d572056d..0000000 --- a/third_party/blink/web_tests/platform/mac/compositing/lots-of-img-layers-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/direct-image-compositing-expected.png b/third_party/blink/web_tests/platform/win/compositing/direct-image-compositing-expected.png index 6d558fb..c6e23ba 100644 --- a/third_party/blink/web_tests/platform/win/compositing/direct-image-compositing-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/direct-image-compositing-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/lots-of-img-layers-expected.png b/third_party/blink/web_tests/platform/win/compositing/lots-of-img-layers-expected.png deleted file mode 100644 index 34f07c89..0000000 --- a/third_party/blink/web_tests/platform/win/compositing/lots-of-img-layers-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/overflow-delete-line-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/overflow-delete-line-expected.txt index ac4b0aa..98fdcfe 100644 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/overflow-delete-line-expected.txt +++ b/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/overflow-delete-line-expected.txt
@@ -18,14 +18,9 @@ "backgroundColor": "#FFFFFF", "paintInvalidations": [ { - "object": "InlineTextBox '\n '", + "object": "LayoutBlockFlow DIV id='dv'", "rect": [8, 74, 80, 19], - "reason": "disappeared" - }, - { - "object": "InlineTextBox 'Lorem ipsum'", - "rect": [8, 74, 80, 19], - "reason": "disappeared" + "reason": "chunk disappeared" }, { "object": "InlineTextBox 'Lorem ipsu'",
diff --git a/third_party/blink/web_tests/virtual/user-activation-v2/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/virtual/user-activation-v2/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt deleted file mode 100644 index bd8e4ec0..0000000 --- a/third_party/blink/web_tests/virtual/user-activation-v2/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt +++ /dev/null
@@ -1,190 +0,0 @@ -CONSOLE WARNING: line 121: 'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead. -Tests property access on a cached DOMWindow after the associated frame is removed from a web page and garbage collected. Test should not crash and properties should be set to sane defaults. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -PASS childWindow.closed is true -PASS childWindow.defaultStatus is '' -PASS childWindow.defaultstatus is '' -PASS childWindow.devicePixelRatio is 0 -PASS childWindow.innerHeight is 0 -PASS childWindow.innerWidth is 0 -PASS childWindow.isSecureContext is false -PASS childWindow.length is 0 -PASS childWindow.locationbar.visible is false -PASS childWindow.menubar.visible is false -PASS childWindow.name is '' -PASS childWindow.navigator.appCodeName is window.navigator.appCodeName -PASS childWindow.navigator.appName is window.navigator.appName -PASS childWindow.navigator.appVersion is '' -PASS childWindow.navigator.cookieEnabled is false -PASS childWindow.navigator.doNotTrack is null -PASS childWindow.navigator.hardwareConcurrency is window.navigator.hardwareConcurrency -PASS childWindow.navigator.language is window.navigator.language -PASS childWindow.navigator.maxTouchPoints is 0 -PASS childWindow.navigator.mediaDevices.ondevicechange is null -PASS childWindow.navigator.mediaSession.metadata is null -PASS childWindow.navigator.mediaSession.playbackState is 'none' -PASS childWindow.navigator.onLine is window.navigator.onLine -PASS childWindow.navigator.platform is window.navigator.platform -PASS childWindow.navigator.product is window.navigator.product -PASS childWindow.navigator.productSub is window.navigator.productSub -PASS childWindow.navigator.userActivation.hasBeenActive is false -PASS childWindow.navigator.userActivation.isActive is false -PASS childWindow.navigator.userAgent is '' -PASS childWindow.navigator.vendor is window.navigator.vendor -PASS childWindow.navigator.vendorSub is '' -PASS childWindow.onabort is null -PASS childWindow.onactivateinvisible is null -PASS childWindow.onafterprint is null -PASS childWindow.onanimationend is null -PASS childWindow.onanimationiteration is null -PASS childWindow.onanimationstart is null -PASS childWindow.onappinstalled is null -PASS childWindow.onauxclick is null -PASS childWindow.onbeforeinstallprompt is null -PASS childWindow.onbeforeprint is null -PASS childWindow.onbeforeunload is null -PASS childWindow.onblur is null -PASS childWindow.oncancel is null -PASS childWindow.oncanplay is null -PASS childWindow.oncanplaythrough is null -PASS childWindow.onchange is null -PASS childWindow.onclick is null -PASS childWindow.onclose is null -PASS childWindow.oncontextmenu is null -PASS childWindow.oncuechange is null -PASS childWindow.ondblclick is null -PASS childWindow.ondevicemotion is null -PASS childWindow.ondeviceorientation is null -PASS childWindow.ondeviceorientationabsolute is null -PASS childWindow.ondrag is null -PASS childWindow.ondragend is null -PASS childWindow.ondragenter is null -PASS childWindow.ondragleave is null -PASS childWindow.ondragover is null -PASS childWindow.ondragstart is null -PASS childWindow.ondrop is null -PASS childWindow.ondurationchange is null -PASS childWindow.onemptied is null -PASS childWindow.onended is null -PASS childWindow.onerror is null -PASS childWindow.onfocus is null -PASS childWindow.onformdata is null -PASS childWindow.ongotpointercapture is null -PASS childWindow.onhashchange is null -PASS childWindow.oninput is null -PASS childWindow.oninvalid is null -PASS childWindow.onkeydown is null -PASS childWindow.onkeypress is null -PASS childWindow.onkeyup is null -PASS childWindow.onlanguagechange is null -PASS childWindow.onload is null -PASS childWindow.onloadeddata is null -PASS childWindow.onloadedmetadata is null -PASS childWindow.onloadstart is null -PASS childWindow.onlostpointercapture is null -PASS childWindow.onmessage is null -PASS childWindow.onmessageerror is null -PASS childWindow.onmousedown is null -PASS childWindow.onmouseenter is null -PASS childWindow.onmouseleave is null -PASS childWindow.onmousemove is null -PASS childWindow.onmouseout is null -PASS childWindow.onmouseover is null -PASS childWindow.onmouseup is null -PASS childWindow.onmousewheel is null -PASS childWindow.onoffline is null -PASS childWindow.ononline is null -PASS childWindow.onpagehide is null -PASS childWindow.onpageshow is null -PASS childWindow.onpause is null -PASS childWindow.onplay is null -PASS childWindow.onplaying is null -PASS childWindow.onpointercancel is null -PASS childWindow.onpointerdown is null -PASS childWindow.onpointerenter is null -PASS childWindow.onpointerleave is null -PASS childWindow.onpointermove is null -PASS childWindow.onpointerout is null -PASS childWindow.onpointerover is null -PASS childWindow.onpointerrawmove is null -PASS childWindow.onpointerup is null -PASS childWindow.onpopstate is null -PASS childWindow.onprogress is null -PASS childWindow.onratechange is null -PASS childWindow.onrejectionhandled is null -PASS childWindow.onreset is null -PASS childWindow.onresize is null -PASS childWindow.onscroll is null -PASS childWindow.onsearch is null -PASS childWindow.onseeked is null -PASS childWindow.onseeking is null -PASS childWindow.onselect is null -PASS childWindow.onselectionchange is null -PASS childWindow.onselectstart is null -PASS childWindow.onstalled is null -PASS childWindow.onstorage is null -PASS childWindow.onsubmit is null -PASS childWindow.onsuspend is null -PASS childWindow.ontimeupdate is null -PASS childWindow.ontoggle is null -PASS childWindow.ontouchcancel is null -PASS childWindow.ontouchend is null -PASS childWindow.ontouchmove is null -PASS childWindow.ontouchstart is null -PASS childWindow.ontransitionend is null -PASS childWindow.onunhandledrejection is null -PASS childWindow.onunload is null -PASS childWindow.onvolumechange is null -PASS childWindow.onwaiting is null -PASS childWindow.onwebkitanimationend is null -PASS childWindow.onwebkitanimationiteration is null -PASS childWindow.onwebkitanimationstart is null -PASS childWindow.onwebkittransitionend is null -PASS childWindow.onwheel is null -PASS childWindow.opener is null -PASS childWindow.origin is 'file://' -PASS childWindow.outerHeight is 0 -PASS childWindow.outerWidth is 0 -PASS childWindow.pageXOffset is 0 -PASS childWindow.pageYOffset is 0 -PASS childWindow.performance.onresourcetimingbufferfull is null -PASS childWindow.personalbar.visible is false -PASS childWindow.screen.availHeight is 0 -PASS childWindow.screen.availLeft is 0 -PASS childWindow.screen.availTop is 0 -PASS childWindow.screen.availWidth is 0 -PASS childWindow.screen.colorDepth is 0 -PASS childWindow.screen.height is 0 -PASS childWindow.screen.keepAwake is false -PASS childWindow.screen.pixelDepth is 0 -PASS childWindow.screen.width is 0 -PASS childWindow.screenLeft is 0 -PASS childWindow.screenTop is 0 -PASS childWindow.screenX is 0 -PASS childWindow.screenY is 0 -PASS childWindow.scrollX is 0 -PASS childWindow.scrollY is 0 -PASS childWindow.scrollbars.visible is false -PASS childWindow.speechSynthesis.onvoiceschanged is null -PASS childWindow.speechSynthesis.paused is false -PASS childWindow.speechSynthesis.pending is false -PASS childWindow.speechSynthesis.speaking is false -PASS childWindow.status is '' -PASS childWindow.statusbar.visible is false -PASS childWindow.styleMedia.type is '' -PASS childWindow.toolbar.visible is false -PASS childWindow.visualViewport.height is 0 -PASS childWindow.visualViewport.offsetLeft is 0 -PASS childWindow.visualViewport.offsetTop is 0 -PASS childWindow.visualViewport.onresize is null -PASS childWindow.visualViewport.onscroll is null -PASS childWindow.visualViewport.pageLeft is 0 -PASS childWindow.visualViewport.pageTop is 0 -PASS childWindow.visualViewport.scale is 0 -PASS childWindow.visualViewport.width is 0 -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/virtual/user-activation-v2/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt b/third_party/blink/web_tests/virtual/user-activation-v2/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt deleted file mode 100644 index 217db59..0000000 --- a/third_party/blink/web_tests/virtual/user-activation-v2/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt +++ /dev/null
@@ -1,190 +0,0 @@ -CONSOLE WARNING: line 121: 'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead. -Tests property access on a cached DOMWindow after the associated frame is no longer in a web page. Test should not crash and properties should be set to sane defaults. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -PASS childWindow.closed is true -PASS childWindow.defaultStatus is '' -PASS childWindow.defaultstatus is '' -PASS childWindow.devicePixelRatio is 0 -PASS childWindow.innerHeight is 0 -PASS childWindow.innerWidth is 0 -PASS childWindow.isSecureContext is false -PASS childWindow.length is 0 -PASS childWindow.locationbar.visible is false -PASS childWindow.menubar.visible is false -PASS childWindow.name is '' -PASS childWindow.navigator.appCodeName is window.navigator.appCodeName -PASS childWindow.navigator.appName is window.navigator.appName -PASS childWindow.navigator.appVersion is '' -PASS childWindow.navigator.cookieEnabled is false -PASS childWindow.navigator.doNotTrack is null -PASS childWindow.navigator.hardwareConcurrency is window.navigator.hardwareConcurrency -PASS childWindow.navigator.language is window.navigator.language -PASS childWindow.navigator.maxTouchPoints is 0 -PASS childWindow.navigator.mediaDevices.ondevicechange is null -PASS childWindow.navigator.mediaSession.metadata is null -PASS childWindow.navigator.mediaSession.playbackState is 'none' -PASS childWindow.navigator.onLine is window.navigator.onLine -PASS childWindow.navigator.platform is window.navigator.platform -PASS childWindow.navigator.product is window.navigator.product -PASS childWindow.navigator.productSub is window.navigator.productSub -PASS childWindow.navigator.userActivation.hasBeenActive is false -PASS childWindow.navigator.userActivation.isActive is false -PASS childWindow.navigator.userAgent is '' -PASS childWindow.navigator.vendor is window.navigator.vendor -PASS childWindow.navigator.vendorSub is '' -PASS childWindow.onabort is null -PASS childWindow.onactivateinvisible is null -PASS childWindow.onafterprint is null -PASS childWindow.onanimationend is null -PASS childWindow.onanimationiteration is null -PASS childWindow.onanimationstart is null -PASS childWindow.onappinstalled is null -PASS childWindow.onauxclick is null -PASS childWindow.onbeforeinstallprompt is null -PASS childWindow.onbeforeprint is null -PASS childWindow.onbeforeunload is null -PASS childWindow.onblur is null -PASS childWindow.oncancel is null -PASS childWindow.oncanplay is null -PASS childWindow.oncanplaythrough is null -PASS childWindow.onchange is null -PASS childWindow.onclick is null -PASS childWindow.onclose is null -PASS childWindow.oncontextmenu is null -PASS childWindow.oncuechange is null -PASS childWindow.ondblclick is null -PASS childWindow.ondevicemotion is null -PASS childWindow.ondeviceorientation is null -PASS childWindow.ondeviceorientationabsolute is null -PASS childWindow.ondrag is null -PASS childWindow.ondragend is null -PASS childWindow.ondragenter is null -PASS childWindow.ondragleave is null -PASS childWindow.ondragover is null -PASS childWindow.ondragstart is null -PASS childWindow.ondrop is null -PASS childWindow.ondurationchange is null -PASS childWindow.onemptied is null -PASS childWindow.onended is null -PASS childWindow.onerror is null -PASS childWindow.onfocus is null -PASS childWindow.onformdata is null -PASS childWindow.ongotpointercapture is null -PASS childWindow.onhashchange is null -PASS childWindow.oninput is null -PASS childWindow.oninvalid is null -PASS childWindow.onkeydown is null -PASS childWindow.onkeypress is null -PASS childWindow.onkeyup is null -PASS childWindow.onlanguagechange is null -PASS childWindow.onload is null -PASS childWindow.onloadeddata is null -PASS childWindow.onloadedmetadata is null -PASS childWindow.onloadstart is null -PASS childWindow.onlostpointercapture is null -PASS childWindow.onmessage is null -PASS childWindow.onmessageerror is null -PASS childWindow.onmousedown is null -PASS childWindow.onmouseenter is null -PASS childWindow.onmouseleave is null -PASS childWindow.onmousemove is null -PASS childWindow.onmouseout is null -PASS childWindow.onmouseover is null -PASS childWindow.onmouseup is null -PASS childWindow.onmousewheel is null -PASS childWindow.onoffline is null -PASS childWindow.ononline is null -PASS childWindow.onpagehide is null -PASS childWindow.onpageshow is null -PASS childWindow.onpause is null -PASS childWindow.onplay is null -PASS childWindow.onplaying is null -PASS childWindow.onpointercancel is null -PASS childWindow.onpointerdown is null -PASS childWindow.onpointerenter is null -PASS childWindow.onpointerleave is null -PASS childWindow.onpointermove is null -PASS childWindow.onpointerout is null -PASS childWindow.onpointerover is null -PASS childWindow.onpointerrawmove is null -PASS childWindow.onpointerup is null -PASS childWindow.onpopstate is null -PASS childWindow.onprogress is null -PASS childWindow.onratechange is null -PASS childWindow.onrejectionhandled is null -PASS childWindow.onreset is null -PASS childWindow.onresize is null -PASS childWindow.onscroll is null -PASS childWindow.onsearch is null -PASS childWindow.onseeked is null -PASS childWindow.onseeking is null -PASS childWindow.onselect is null -PASS childWindow.onselectionchange is null -PASS childWindow.onselectstart is null -PASS childWindow.onstalled is null -PASS childWindow.onstorage is null -PASS childWindow.onsubmit is null -PASS childWindow.onsuspend is null -PASS childWindow.ontimeupdate is null -PASS childWindow.ontoggle is null -PASS childWindow.ontouchcancel is null -PASS childWindow.ontouchend is null -PASS childWindow.ontouchmove is null -PASS childWindow.ontouchstart is null -PASS childWindow.ontransitionend is null -PASS childWindow.onunhandledrejection is null -PASS childWindow.onunload is null -PASS childWindow.onvolumechange is null -PASS childWindow.onwaiting is null -PASS childWindow.onwebkitanimationend is null -PASS childWindow.onwebkitanimationiteration is null -PASS childWindow.onwebkitanimationstart is null -PASS childWindow.onwebkittransitionend is null -PASS childWindow.onwheel is null -PASS childWindow.opener is null -PASS childWindow.origin is 'file://' -PASS childWindow.outerHeight is 0 -PASS childWindow.outerWidth is 0 -PASS childWindow.pageXOffset is 0 -PASS childWindow.pageYOffset is 0 -PASS childWindow.performance.onresourcetimingbufferfull is null -PASS childWindow.personalbar.visible is false -PASS childWindow.screen.availHeight is 0 -PASS childWindow.screen.availLeft is 0 -PASS childWindow.screen.availTop is 0 -PASS childWindow.screen.availWidth is 0 -PASS childWindow.screen.colorDepth is 0 -PASS childWindow.screen.height is 0 -PASS childWindow.screen.keepAwake is false -PASS childWindow.screen.pixelDepth is 0 -PASS childWindow.screen.width is 0 -PASS childWindow.screenLeft is 0 -PASS childWindow.screenTop is 0 -PASS childWindow.screenX is 0 -PASS childWindow.screenY is 0 -PASS childWindow.scrollX is 0 -PASS childWindow.scrollY is 0 -PASS childWindow.scrollbars.visible is false -PASS childWindow.speechSynthesis.onvoiceschanged is null -PASS childWindow.speechSynthesis.paused is false -PASS childWindow.speechSynthesis.pending is false -PASS childWindow.speechSynthesis.speaking is false -PASS childWindow.status is '' -PASS childWindow.statusbar.visible is false -PASS childWindow.styleMedia.type is '' -PASS childWindow.toolbar.visible is false -PASS childWindow.visualViewport.height is 0 -PASS childWindow.visualViewport.offsetLeft is 0 -PASS childWindow.visualViewport.offsetTop is 0 -PASS childWindow.visualViewport.onresize is null -PASS childWindow.visualViewport.onscroll is null -PASS childWindow.visualViewport.pageLeft is 0 -PASS childWindow.visualViewport.pageTop is 0 -PASS childWindow.visualViewport.scale is 0 -PASS childWindow.visualViewport.width is 0 -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 5c38b3d..65e6db0 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -5420,6 +5420,9 @@ attribute @@toStringTag getter state method constructor +interface PortalHost : EventTarget + attribute @@toStringTag + method constructor interface Presentation attribute @@toStringTag getter defaultRequest @@ -10322,10 +10325,10 @@ method constructor method requestDevice setter ondevicechange -interface XRCoordinateSystem : EventTarget +interface XRBoundedReferenceSpace : XRReferenceSpace attribute @@toStringTag + getter boundsGeometry method constructor - method getTransformTo interface XRDevice attribute @@toStringTag method constructor @@ -10338,11 +10341,6 @@ method constructor method getInputPose method getViewerPose -interface XRFrameOfReference : XRCoordinateSystem - attribute @@toStringTag - getter bounds - getter emulatedHeight - method constructor interface XRHitResult attribute @@toStringTag getter hitMatrix @@ -10376,6 +10374,11 @@ getter origin getter transformMatrix method constructor +interface XRReferenceSpace : XRSpace + attribute @@toStringTag + getter onreset + method constructor + setter onreset interface XRSession : EventTarget attribute @@toStringTag getter baseLayer @@ -10394,8 +10397,8 @@ method end method getInputSources method requestAnimationFrame - method requestFrameOfReference method requestHitTest + method requestReferenceSpace setter baseLayer setter depthFar setter depthNear @@ -10407,10 +10410,21 @@ attribute @@toStringTag getter session method constructor +interface XRSpace : EventTarget + attribute @@toStringTag + method constructor + method getTransformTo interface XRStageBounds attribute @@toStringTag getter geometry method constructor +interface XRStationaryReferenceSpace : XRReferenceSpace + attribute @@toStringTag + getter subtype + method constructor +interface XRUnboundedReferenceSpace : XRReferenceSpace + attribute @@toStringTag + method constructor interface XRView attribute @@toStringTag getter eye @@ -10787,6 +10801,7 @@ getter pageYOffset getter performance getter personalbar + getter portalHost getter screen getter screenLeft getter screenTop
diff --git a/third_party/blink/web_tests/xr/ar_hittest.html b/third_party/blink/web_tests/xr/ar_hittest.html index 86dead4..165a2f5a 100644 --- a/third_party/blink/web_tests/xr/ar_hittest.html +++ b/third_party/blink/web_tests/xr/ar_hittest.html
@@ -29,7 +29,7 @@ let testFunction = function(session, t, fakeDeviceController) { assert_false(session.immersive); - return session.requestFrameOfReference("eye-level").then((frameOfReference) => { + return session.requestReferenceSpace({ type: "stationary", subtype: "eye-level" }).then((referenceSpace) => { let direction = new Float32Array([1.0, 0.0, 0.0]); let origin = new Float32Array([0.0, 0.0, 0.0]); @@ -38,7 +38,7 @@ fakeDeviceController.setHitTestResults({ results: [hit] }); - return session.requestHitTest(origin, direction, frameOfReference).then( + return session.requestHitTest(origin, direction, referenceSpace).then( (hitResults) => { // Test that hit results are what we expected. assert_equals(hitResults.length, 1);
diff --git a/third_party/blink/web_tests/xr/getInputPose_hand.html b/third_party/blink/web_tests/xr/getInputPose_hand.html index a44188a..171012e 100644 --- a/third_party/blink/web_tests/xr/getInputPose_hand.html +++ b/third_party/blink/web_tests/xr/getInputPose_hand.html
@@ -42,14 +42,14 @@ fakeDeviceController.addInputSource(input_source); - // Must have a frameOfReference to get input poses. eye-level doesn't apply + // Must have a reference space to get input poses. eye-level doesn't apply // any transforms to the given matrix. - session.requestFrameOfReference("eye-level").then( (frameOfRef) => { + session.requestReferenceSpace({ type: "stationary", subtype: "eye-level" }).then( (referenceSpace) => { function CheckInvalidGrip(time, xrFrame) { let source = session.getInputSources()[0]; - let input_pose = xrFrame.getInputPose(source, frameOfRef); + let input_pose = xrFrame.getInputPose(source, referenceSpace); t.step( () => { // The input pose should be null when no grip matrix is provided. @@ -65,7 +65,7 @@ function CheckValidGrip(time, xrFrame) { let source = session.getInputSources()[0]; - let input_pose = xrFrame.getInputPose(source, frameOfRef); + let input_pose = xrFrame.getInputPose(source, referenceSpace); t.step( () => { // When a grip matrix is present but no pointer offset is specified, @@ -85,7 +85,7 @@ function CheckValidGripAndPointer(time, xrFrame) { let source = session.getInputSources()[0]; - let input_pose = xrFrame.getInputPose(source, frameOfRef); + let input_pose = xrFrame.getInputPose(source, referenceSpace); t.step( () => { // When a grip matrix and pointer offset are specified,
diff --git a/third_party/blink/web_tests/xr/getInputPose_ray.html b/third_party/blink/web_tests/xr/getInputPose_ray.html index 42988fb..208c6bb 100644 --- a/third_party/blink/web_tests/xr/getInputPose_ray.html +++ b/third_party/blink/web_tests/xr/getInputPose_ray.html
@@ -40,14 +40,14 @@ fakeDeviceController.addInputSource(input_source); - // Must have a frameOfReference to get input poses. eye-level doesn't apply + // Must have a reference space to get input poses. eye-level doesn't apply // any transforms to the given matrix. - session.requestFrameOfReference("eye-level").then( (frameOfRef) => { + session.requestReferenceSpace({ type: "stationary", subtype: "eye-level" }).then( (referenceSpace) => { function CheckTargetRayNoOffset(time, xrFrame) { let source = session.getInputSources()[0]; - let input_pose = xrFrame.getInputPose(source, frameOfRef); + let input_pose = xrFrame.getInputPose(source, referenceSpace); t.step( () => { assert_matrices_approx_equal(input_pose.targetRay.transformMatrix, @@ -73,7 +73,7 @@ function CheckTargetRayOffset(time, xrFrame) { let source = session.getInputSources()[0]; - let input_pose = xrFrame.getInputPose(source, frameOfRef); + let input_pose = xrFrame.getInputPose(source, referenceSpace); t.step( () => { assert_matrices_approx_equal(input_pose.targetRay.transformMatrix,
diff --git a/third_party/blink/web_tests/xr/xrSession_requestAnimationFrame_timestamp.html b/third_party/blink/web_tests/xr/xrSession_requestAnimationFrame_timestamp.html index 1a1a7ea7..186cc02 100644 --- a/third_party/blink/web_tests/xr/xrSession_requestAnimationFrame_timestamp.html +++ b/third_party/blink/web_tests/xr/xrSession_requestAnimationFrame_timestamp.html
@@ -37,8 +37,8 @@ viewMatrix: VALID_VIEW_MATRIX }]); - return session.requestFrameOfReference("eye-level") - .then((frameOfRef) => new Promise((resolve, reject) => { + return session.requestReferenceSpace({ type: "stationary", subtype: "eye-level" }) + .then((referenceSpace) => new Promise((resolve, reject) => { let counter = 0; let windowFrameTime = 0; let frameTime = 0;
diff --git a/third_party/blink/web_tests/xr/xrFrameOfReference_stage_updates.html b/third_party/blink/web_tests/xr/xrStationaryReferenceSpace_floorlevel_updates.html similarity index 87% rename from third_party/blink/web_tests/xr/xrFrameOfReference_stage_updates.html rename to third_party/blink/web_tests/xr/xrStationaryReferenceSpace_floorlevel_updates.html index 8e8223e9..77dc405 100644 --- a/third_party/blink/web_tests/xr/xrFrameOfReference_stage_updates.html +++ b/third_party/blink/web_tests/xr/xrStationaryReferenceSpace_floorlevel_updates.html
@@ -11,7 +11,7 @@ <script> let testName = - "'stage' XRFrameOfReference updates properly when the transform changes"; + "'floor-level' XRStationaryReferenceSpace updates properly when the transform changes"; let fakeDeviceInitParams = { supportsImmersive:true }; @@ -35,14 +35,14 @@ viewMatrix: VALID_VIEW_MATRIX }]); - return session.requestFrameOfReference("stage") - .then((frameOfRef) => new Promise((resolve, reject) => { + return session.requestReferenceSpace({ type: "stationary", subtype: "floor-level" }) + .then((referenceSpace) => new Promise((resolve, reject) => { function onFirstFrame(time, xrFrame) { // On the first frame where the pose has been initialized, the stage // should be using an emulated frame of reference because it has no // stageParameters yet. So the pose should be ~1.5 meters off the floor. t.step( () => { - let pose = xrFrame.getViewerPose(frameOfRef); + let pose = xrFrame.getViewerPose(referenceSpace); let poseMatrix = pose.poseModelMatrix; assert_approx_equals(poseMatrix[12], 0.0, FLOAT_EPSILON); @@ -59,7 +59,7 @@ function onFrame(time, xrFrame) { t.step( () => { // Check that stage transform was updated. - let pose = xrFrame.getViewerPose(frameOfRef); + let pose = xrFrame.getViewerPose(referenceSpace); assert_not_equals(pose, null); let poseMatrix = pose.poseModelMatrix;
diff --git a/third_party/blink/web_tests/xr/xrView_match.html b/third_party/blink/web_tests/xr/xrView_match.html index 4b61d777..132ed03 100644 --- a/third_party/blink/web_tests/xr/xrView_match.html +++ b/third_party/blink/web_tests/xr/xrView_match.html
@@ -32,7 +32,7 @@ viewMatrix: VALID_VIEW_MATRIX }]); - return session.requestFrameOfReference("eye-level").then((frameOfRef) => new Promise((resolve) =>{ + return session.requestReferenceSpace({ type: "stationary", subtype: "eye-level" }).then((referenceSpace) => new Promise((resolve) =>{ function onFrame(time, xrFrame) { // Ensure that two views are provided. assert_not_equals(xrFrame.views, null);
diff --git a/third_party/blink/web_tests/xr/xrView_oneframeupdate.html b/third_party/blink/web_tests/xr/xrView_oneframeupdate.html index 6b1985e..1094813 100644 --- a/third_party/blink/web_tests/xr/xrView_oneframeupdate.html +++ b/third_party/blink/web_tests/xr/xrView_oneframeupdate.html
@@ -31,8 +31,8 @@ viewMatrix: VALID_VIEW_MATRIX }]); - return session.requestFrameOfReference("eye-level") - .then((frameOfRef) => new Promise((resolve) =>{ + return session.requestReferenceSpace({ type: "stationary", subtype: "eye-level" }) + .then((referenceSpace) => new Promise((resolve) =>{ let counter = 0; function onFrame(time, xrFrame) {
diff --git a/third_party/blink/web_tests/xr/xrViewport_valid.html b/third_party/blink/web_tests/xr/xrViewport_valid.html index b649250..c383d2d7 100644 --- a/third_party/blink/web_tests/xr/xrViewport_valid.html +++ b/third_party/blink/web_tests/xr/xrViewport_valid.html
@@ -20,8 +20,8 @@ let webglLayer = new XRWebGLLayer(session, gl); session.baseLayer = webglLayer; - return session.requestFrameOfReference("eye-level") - .then((frameOfRef) => new Promise((resolve) =>{ + return session.requestReferenceSpace({ type: "stationary", subtype: "eye-level" }) + .then((referenceSpace) => new Promise((resolve) =>{ function onFrame(time, xrFrame) { let leftView = xrFrame.views[0]; let rightView = xrFrame.views[1];
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index d543e03..62489c4 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@ Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: abfad376ab08dfa42a984353004d72a38cadb198 +Revision: c8a016b99d97e2e5642fd7892b48a5ed0eb6d0d1 License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_mac.mm b/third_party/crashpad/crashpad/client/crash_report_database_mac.mm index 3106dc2c..0980fe3f 100644 --- a/third_party/crashpad/crashpad/client/crash_report_database_mac.mm +++ b/third_party/crashpad/crashpad/client/crash_report_database_mac.mm
@@ -35,6 +35,7 @@ #include "client/settings.h" #include "util/file/file_io.h" #include "util/mac/xattr.h" +#include "util/misc/arraysize.h" #include "util/misc/initialization_state_dcheck.h" #include "util/misc/metrics.h" @@ -279,7 +280,7 @@ } // Create the three processing directories for the database. - for (size_t i = 0; i < arraysize(kReportDirectories); ++i) { + for (size_t i = 0; i < ArraySize(kReportDirectories); ++i) { if (!CreateOrEnsureDirectoryExists(base_dir_.Append(kReportDirectories[i]))) return false; }
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_win_test.cc b/third_party/crashpad/crashpad/client/crashpad_client_win_test.cc index 99778ba..b950699 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client_win_test.cc +++ b/third_party/crashpad/crashpad/client/crashpad_client_win_test.cc
@@ -17,7 +17,6 @@ #include <vector> #include "base/files/file_path.h" -#include "base/macros.h" #include "base/logging.h" #include "gtest/gtest.h" #include "test/test_paths.h"
diff --git a/third_party/crashpad/crashpad/client/simulate_crash_mac.cc b/third_party/crashpad/crashpad/client/simulate_crash_mac.cc index 1e2d8e4..1f7eca9 100644 --- a/third_party/crashpad/crashpad/client/simulate_crash_mac.cc +++ b/third_party/crashpad/crashpad/client/simulate_crash_mac.cc
@@ -20,13 +20,13 @@ #include "base/logging.h" #include "base/mac/mach_logging.h" #include "base/mac/scoped_mach_port.h" -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "util/mach/exc_client_variants.h" #include "util/mach/exception_behaviors.h" #include "util/mach/exception_ports.h" #include "util/mach/mach_extensions.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" namespace crashpad { @@ -191,7 +191,7 @@ base::mac::ScopedMachSendRight thread(mach_thread_self()); exception_type_t exception = kMachExceptionSimulated; mach_exception_data_type_t codes[] = {0, 0}; - mach_msg_type_number_t code_count = arraysize(codes); + mach_msg_type_number_t code_count = ArraySize(codes); // Look up the handler for EXC_CRASH exceptions in the same way that the // kernel would: try a thread handler, then a task handler, and finally a host @@ -213,7 +213,7 @@ bool success = false; for (size_t target_type_index = 0; - !success && target_type_index < arraysize(kTargetTypes); + !success && target_type_index < ArraySize(kTargetTypes); ++target_type_index) { ExceptionPorts::ExceptionHandlerVector handlers; ExceptionPorts exception_ports(kTargetTypes[target_type_index],
diff --git a/third_party/crashpad/crashpad/client/simulate_crash_mac_test.cc b/third_party/crashpad/crashpad/client/simulate_crash_mac_test.cc index 1d63ff6..910971a 100644 --- a/third_party/crashpad/crashpad/client/simulate_crash_mac_test.cc +++ b/third_party/crashpad/crashpad/client/simulate_crash_mac_test.cc
@@ -31,6 +31,7 @@ #include "util/mach/mach_message.h" #include "util/mach/mach_message_server.h" #include "util/mach/symbolic_constants_mach.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" namespace crashpad { @@ -342,15 +343,13 @@ #endif }; - for (size_t target_index = 0; - target_index < arraysize(kTargets); + for (size_t target_index = 0; target_index < ArraySize(kTargets); ++target_index) { TestSimulateCrashMac::ExceptionPortsTarget target = kTargets[target_index]; SCOPED_TRACE(base::StringPrintf( "target_index %zu, target %d", target_index, target)); - for (size_t behavior_index = 0; - behavior_index < arraysize(kBehaviors); + for (size_t behavior_index = 0; behavior_index < ArraySize(kBehaviors); ++behavior_index) { exception_behavior_t behavior = kBehaviors[behavior_index]; SCOPED_TRACE(base::StringPrintf( @@ -364,8 +363,7 @@ target, behavior, THREAD_STATE_NONE); test_simulate_crash_mac.Run(); } else { - for (size_t flavor_index = 0; - flavor_index < arraysize(kFlavors); + for (size_t flavor_index = 0; flavor_index < ArraySize(kFlavors); ++flavor_index) { thread_state_flavor_t flavor = kFlavors[flavor_index]; SCOPED_TRACE(base::StringPrintf(
diff --git a/third_party/crashpad/crashpad/handler/mac/file_limit_annotation.cc b/third_party/crashpad/crashpad/handler/mac/file_limit_annotation.cc index cf56eb8..5646bde 100644 --- a/third_party/crashpad/crashpad/handler/mac/file_limit_annotation.cc +++ b/third_party/crashpad/crashpad/handler/mac/file_limit_annotation.cc
@@ -24,10 +24,10 @@ #include <string> #include "base/format_macros.h" -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "client/crashpad_info.h" #include "client/simple_string_dictionary.h" +#include "util/misc/arraysize.h" #include "util/posix/scoped_dir.h" namespace crashpad { @@ -108,7 +108,7 @@ int mib[] = {CTL_KERN, KERN_MAXFILES}; size = sizeof(value); std::string max_files = FormatFromSysctl( - sysctl(mib, arraysize(mib), &value, &size, nullptr, 0), &value, &size); + sysctl(mib, ArraySize(mib), &value, &size, nullptr, 0), &value, &size); std::string open_files = CountOpenFileDescriptors();
diff --git a/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc b/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc index a4f4797..d6b4dead 100644 --- a/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc +++ b/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc
@@ -26,10 +26,10 @@ #include "base/files/file_path.h" #include "base/logging.h" -#include "base/macros.h" #include "build/build_config.h" #include "client/crashpad_client.h" #include "client/crashpad_info.h" +#include "util/misc/arraysize.h" #include "util/win/critical_section_with_debug_info.h" #include "util/win/get_function.h" @@ -83,11 +83,11 @@ // All of these allocations are leaked, we want to view them in windbg via // !vprot. void* reserve = VirtualAlloc( - nullptr, arraysize(kPageTypes) * kPageSize, MEM_RESERVE, PAGE_READWRITE); + nullptr, ArraySize(kPageTypes) * kPageSize, MEM_RESERVE, PAGE_READWRITE); PCHECK(reserve) << "VirtualAlloc MEM_RESERVE"; uintptr_t reserve_as_int = reinterpret_cast<uintptr_t>(reserve); - for (size_t i = 0; i < arraysize(kPageTypes); ++i) { + for (size_t i = 0; i < ArraySize(kPageTypes); ++i) { void* result = VirtualAlloc(reinterpret_cast<void*>(reserve_as_int + (kPageSize * i)), kPageSize,
diff --git a/third_party/crashpad/crashpad/handler/win/hanging_program.cc b/third_party/crashpad/crashpad/handler/win/hanging_program.cc index 840c5125..49d5cea 100644 --- a/third_party/crashpad/crashpad/handler/win/hanging_program.cc +++ b/third_party/crashpad/crashpad/handler/win/hanging_program.cc
@@ -17,11 +17,11 @@ #include "base/debug/alias.h" #include "base/logging.h" -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "client/crashpad_client.h" #include "client/crashpad_info.h" +#include "util/misc/arraysize.h" namespace { @@ -123,8 +123,8 @@ fflush(stdout); // This is not expected to return. - DWORD count = - WaitForMultipleObjects(arraysize(threads), threads, true, INFINITE); + DWORD count = WaitForMultipleObjects( + static_cast<DWORD>(ArraySize(threads)), threads, true, INFINITE); if (count == WAIT_FAILED) { PLOG(ERROR) << "WaitForMultipleObjects"; } else {
diff --git a/third_party/crashpad/crashpad/minidump/minidump_annotation_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_annotation_writer_test.cc index 1641d1d6..f86ff467 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_annotation_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_annotation_writer_test.cc
@@ -16,13 +16,13 @@ #include <memory> -#include "base/macros.h" #include "gtest/gtest.h" #include "minidump/minidump_extensions.h" #include "minidump/test/minidump_byte_array_writer_test_util.h" #include "minidump/test/minidump_string_writer_test_util.h" #include "minidump/test/minidump_writable_test_util.h" #include "util/file/string_file.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -107,7 +107,7 @@ MinidumpAnnotationListWriter list_writer; - for (size_t i = 0; i < arraysize(kNames); ++i) { + for (size_t i = 0; i < ArraySize(kNames); ++i) { auto annotation = std::make_unique<MinidumpAnnotationWriter>(); annotation->InitializeWithData(kNames[i], kTypes[i], kValues[i]); list_writer.AddObject(std::move(annotation));
diff --git a/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer_test.cc index f20ad35a..94fad5c 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer_test.cc
@@ -21,6 +21,7 @@ #include "gtest/gtest.h" #include "minidump/test/minidump_writable_test_util.h" #include "util/file/string_file.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -34,7 +35,7 @@ {}, }; - for (size_t i = 0; i < arraysize(kTests); ++i) { + for (size_t i = 0; i < ArraySize(kTests); ++i) { SCOPED_TRACE(base::StringPrintf("index %" PRIuS, i)); StringFile string_file; @@ -66,7 +67,7 @@ {}, }; - for (size_t i = 0; i < arraysize(kTests); ++i) { + for (size_t i = 0; i < ArraySize(kTests); ++i) { SCOPED_TRACE(base::StringPrintf("index %" PRIuS, i)); crashpad::MinidumpByteArrayWriter writer;
diff --git a/third_party/crashpad/crashpad/minidump/minidump_exception_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_exception_writer.cc index d870de3..b0e1e62 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_exception_writer.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_exception_writer.cc
@@ -21,7 +21,7 @@ #include "minidump/minidump_context_writer.h" #include "snapshot/exception_snapshot.h" #include "util/file/file_writer.h" -#include "util/misc/arraysize_unsafe.h" +#include "util/misc/arraysize.h" namespace crashpad { @@ -65,7 +65,7 @@ const size_t parameters = exception_information.size(); constexpr size_t kMaxParameters = - ARRAYSIZE_UNSAFE(exception_.ExceptionRecord.ExceptionInformation); + ArraySize(exception_.ExceptionRecord.ExceptionInformation); CHECK_LE(parameters, kMaxParameters); exception_.ExceptionRecord.NumberParameters =
diff --git a/third_party/crashpad/crashpad/minidump/minidump_exception_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_exception_writer_test.cc index e4dc5fa..b3a4e809 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_exception_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_exception_writer_test.cc
@@ -29,6 +29,7 @@ #include "snapshot/test/test_exception_snapshot.h" #include "test/gtest_death.h" #include "util/file/string_file.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -80,7 +81,7 @@ expected->ExceptionRecord.NumberParameters); EXPECT_EQ(observed->ExceptionRecord.__unusedAlignment, 0u); for (size_t index = 0; - index < arraysize(observed->ExceptionRecord.ExceptionInformation); + index < ArraySize(observed->ExceptionRecord.ExceptionInformation); ++index) { EXPECT_EQ(observed->ExceptionRecord.ExceptionInformation[index], expected->ExceptionRecord.ExceptionInformation[index]);
diff --git a/third_party/crashpad/crashpad/minidump/minidump_file_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_file_writer_test.cc index 067ef96b..ef4813e 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_file_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_file_writer_test.cc
@@ -36,6 +36,7 @@ #include "snapshot/test/test_thread_snapshot.h" #include "test/gtest_death.h" #include "util/file/string_file.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -134,7 +135,7 @@ minidump_file.SetTimestamp(kTimestamp); static constexpr uint8_t kStreamData[] = "Hello World!"; - constexpr size_t kStreamSize = arraysize(kStreamData); + constexpr size_t kStreamSize = ArraySize(kStreamData); constexpr MinidumpStreamType kStreamType = static_cast<MinidumpStreamType>(0x4d);
diff --git a/third_party/crashpad/crashpad/minidump/minidump_memory_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_memory_writer_test.cc index 60b7fa8..fa71caf 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_memory_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_memory_writer_test.cc
@@ -26,6 +26,7 @@ #include "minidump/test/minidump_writable_test_util.h" #include "snapshot/test/test_memory_snapshot.h" #include "util/file/string_file.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -340,7 +341,7 @@ TEST(MinidumpMemoryWriter, AddFromSnapshot) { MINIDUMP_MEMORY_DESCRIPTOR expect_memory_descriptors[3] = {}; - uint8_t values[arraysize(expect_memory_descriptors)] = {}; + uint8_t values[ArraySize(expect_memory_descriptors)] = {}; expect_memory_descriptors[0].StartOfMemoryRange = 0; expect_memory_descriptors[0].Memory.DataSize = 0x1000; @@ -356,8 +357,7 @@ std::vector<std::unique_ptr<TestMemorySnapshot>> memory_snapshots_owner; std::vector<const MemorySnapshot*> memory_snapshots; - for (size_t index = 0; - index < arraysize(expect_memory_descriptors); + for (size_t index = 0; index < ArraySize(expect_memory_descriptors); ++index) { memory_snapshots_owner.push_back(std::make_unique<TestMemorySnapshot>()); TestMemorySnapshot* memory_snapshot = memory_snapshots_owner.back().get(); @@ -396,7 +396,7 @@ TEST(MinidumpMemoryWriter, CoalesceExplicitMultiple) { MINIDUMP_MEMORY_DESCRIPTOR expect_memory_descriptors[4] = {}; - uint8_t values[arraysize(expect_memory_descriptors)] = {}; + uint8_t values[ArraySize(expect_memory_descriptors)] = {}; expect_memory_descriptors[0].StartOfMemoryRange = 0; expect_memory_descriptors[0].Memory.DataSize = 1000;
diff --git a/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc index d83ed23..2d70d00 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc
@@ -26,7 +26,7 @@ #include "snapshot/process_snapshot.h" #include "snapshot/system_snapshot.h" #include "util/file/file_writer.h" -#include "util/misc/arraysize_unsafe.h" +#include "util/misc/arraysize.h" #include "util/numeric/in_range_cast.h" #include "util/numeric/safe_assignment.h" @@ -302,7 +302,7 @@ internal::MinidumpWriterUtil::AssignUTF8ToUTF16( misc_info_.TimeZone.StandardName, - ARRAYSIZE_UNSAFE(misc_info_.TimeZone.StandardName), + ArraySize(misc_info_.TimeZone.StandardName), standard_name); misc_info_.TimeZone.StandardDate = standard_date; @@ -310,7 +310,7 @@ internal::MinidumpWriterUtil::AssignUTF8ToUTF16( misc_info_.TimeZone.DaylightName, - ARRAYSIZE_UNSAFE(misc_info_.TimeZone.DaylightName), + ArraySize(misc_info_.TimeZone.DaylightName), daylight_name); misc_info_.TimeZone.DaylightDate = daylight_date; @@ -327,12 +327,10 @@ misc_info_.Flags1 |= MINIDUMP_MISC4_BUILDSTRING; internal::MinidumpWriterUtil::AssignUTF8ToUTF16( - misc_info_.BuildString, - ARRAYSIZE_UNSAFE(misc_info_.BuildString), - build_string); + misc_info_.BuildString, ArraySize(misc_info_.BuildString), build_string); internal::MinidumpWriterUtil::AssignUTF8ToUTF16( misc_info_.DbgBldStr, - ARRAYSIZE_UNSAFE(misc_info_.DbgBldStr), + ArraySize(misc_info_.DbgBldStr), debug_build_string); }
diff --git a/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer_test.cc index 3c60ebc..e134ccd 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer_test.cc
@@ -31,7 +31,7 @@ #include "snapshot/test/test_process_snapshot.h" #include "snapshot/test/test_system_snapshot.h" #include "util/file/string_file.h" -#include "util/misc/arraysize_unsafe.h" +#include "util/misc/arraysize.h" #include "util/stdlib/strlcpy.h" namespace crashpad { @@ -127,7 +127,7 @@ SCOPED_TRACE("Standard"); ExpectNULPaddedString16Equal(expected->TimeZone.StandardName, observed->TimeZone.StandardName, - arraysize(expected->TimeZone.StandardName)); + ArraySize(expected->TimeZone.StandardName)); ExpectSystemTimeEqual(&expected->TimeZone.StandardDate, &observed->TimeZone.StandardDate); EXPECT_EQ(observed->TimeZone.StandardBias, expected->TimeZone.StandardBias); @@ -136,7 +136,7 @@ SCOPED_TRACE("Daylight"); ExpectNULPaddedString16Equal(expected->TimeZone.DaylightName, observed->TimeZone.DaylightName, - arraysize(expected->TimeZone.DaylightName)); + ArraySize(expected->TimeZone.DaylightName)); ExpectSystemTimeEqual(&expected->TimeZone.DaylightDate, &observed->TimeZone.DaylightDate); EXPECT_EQ(observed->TimeZone.DaylightBias, expected->TimeZone.DaylightBias); @@ -154,13 +154,13 @@ SCOPED_TRACE("BuildString"); ExpectNULPaddedString16Equal(expected->BuildString, observed->BuildString, - arraysize(expected->BuildString)); + ArraySize(expected->BuildString)); } { SCOPED_TRACE("DbgBldStr"); ExpectNULPaddedString16Equal(expected->DbgBldStr, observed->DbgBldStr, - arraysize(expected->DbgBldStr)); + ArraySize(expected->DbgBldStr)); } } @@ -176,7 +176,7 @@ EXPECT_EQ(observed->XStateData.EnabledFeatures, expected->XStateData.EnabledFeatures); for (size_t feature_index = 0; - feature_index < arraysize(observed->XStateData.Features); + feature_index < ArraySize(observed->XStateData.Features); ++feature_index) { SCOPED_TRACE(base::StringPrintf("feature_index %" PRIuS, feature_index)); EXPECT_EQ(observed->XStateData.Features[feature_index].Offset, @@ -396,7 +396,7 @@ base::string16 standard_name_utf16 = base::UTF8ToUTF16(kStandardName); c16lcpy(expected.TimeZone.StandardName, standard_name_utf16.c_str(), - ARRAYSIZE_UNSAFE(expected.TimeZone.StandardName)); + ArraySize(expected.TimeZone.StandardName)); memcpy(&expected.TimeZone.StandardDate, &kStandardDate, sizeof(expected.TimeZone.StandardDate)); @@ -404,7 +404,7 @@ base::string16 daylight_name_utf16 = base::UTF8ToUTF16(kDaylightName); c16lcpy(expected.TimeZone.DaylightName, daylight_name_utf16.c_str(), - ARRAYSIZE_UNSAFE(expected.TimeZone.DaylightName)); + ArraySize(expected.TimeZone.DaylightName)); memcpy(&expected.TimeZone.DaylightDate, &kDaylightDate, sizeof(expected.TimeZone.DaylightDate)); @@ -424,10 +424,9 @@ constexpr int32_t kBias = 300; MINIDUMP_MISC_INFO_N tmp; ALLOW_UNUSED_LOCAL(tmp); - std::string standard_name(ARRAYSIZE_UNSAFE(tmp.TimeZone.StandardName) + 1, - 's'); + std::string standard_name(ArraySize(tmp.TimeZone.StandardName) + 1, 's'); constexpr int32_t kStandardBias = 0; - std::string daylight_name(ARRAYSIZE_UNSAFE(tmp.TimeZone.DaylightName), 'd'); + std::string daylight_name(ArraySize(tmp.TimeZone.DaylightName), 'd'); constexpr int32_t kDaylightBias = -60; // Test using kSystemTimeZero, because not all platforms will be able to @@ -458,7 +457,7 @@ base::string16 standard_name_utf16 = base::UTF8ToUTF16(standard_name); c16lcpy(expected.TimeZone.StandardName, standard_name_utf16.c_str(), - ARRAYSIZE_UNSAFE(expected.TimeZone.StandardName)); + ArraySize(expected.TimeZone.StandardName)); memcpy(&expected.TimeZone.StandardDate, &kSystemTimeZero, sizeof(expected.TimeZone.StandardDate)); @@ -466,7 +465,7 @@ base::string16 daylight_name_utf16 = base::UTF8ToUTF16(daylight_name); c16lcpy(expected.TimeZone.DaylightName, daylight_name_utf16.c_str(), - ARRAYSIZE_UNSAFE(expected.TimeZone.DaylightName)); + ArraySize(expected.TimeZone.DaylightName)); memcpy(&expected.TimeZone.DaylightDate, &kSystemTimeZero, sizeof(expected.TimeZone.DaylightDate)); @@ -497,12 +496,12 @@ base::string16 build_string_utf16 = base::UTF8ToUTF16(kBuildString); c16lcpy(expected.BuildString, build_string_utf16.c_str(), - ARRAYSIZE_UNSAFE(expected.BuildString)); + ArraySize(expected.BuildString)); base::string16 debug_build_string_utf16 = base::UTF8ToUTF16(kDebugBuildString); c16lcpy(expected.DbgBldStr, debug_build_string_utf16.c_str(), - ARRAYSIZE_UNSAFE(expected.DbgBldStr)); + ArraySize(expected.DbgBldStr)); ExpectMiscInfoEqual(&expected, observed); } @@ -516,8 +515,8 @@ MINIDUMP_MISC_INFO_N tmp; ALLOW_UNUSED_LOCAL(tmp); - std::string build_string(ARRAYSIZE_UNSAFE(tmp.BuildString) + 1, 'B'); - std::string debug_build_string(ARRAYSIZE_UNSAFE(tmp.DbgBldStr), 'D'); + std::string build_string(ArraySize(tmp.BuildString) + 1, 'B'); + std::string debug_build_string(ArraySize(tmp.DbgBldStr), 'D'); misc_info_writer->SetBuildString(build_string, debug_build_string); @@ -534,12 +533,12 @@ base::string16 build_string_utf16 = base::UTF8ToUTF16(build_string); c16lcpy(expected.BuildString, build_string_utf16.c_str(), - ARRAYSIZE_UNSAFE(expected.BuildString)); + ArraySize(expected.BuildString)); base::string16 debug_build_string_utf16 = base::UTF8ToUTF16(debug_build_string); c16lcpy(expected.DbgBldStr, debug_build_string_utf16.c_str(), - ARRAYSIZE_UNSAFE(expected.DbgBldStr)); + ArraySize(expected.DbgBldStr)); ExpectMiscInfoEqual(&expected, observed); } @@ -679,7 +678,7 @@ base::string16 standard_name_utf16 = base::UTF8ToUTF16(kStandardName); c16lcpy(expected.TimeZone.StandardName, standard_name_utf16.c_str(), - ARRAYSIZE_UNSAFE(expected.TimeZone.StandardName)); + ArraySize(expected.TimeZone.StandardName)); memcpy(&expected.TimeZone.StandardDate, &kSystemTimeZero, sizeof(expected.TimeZone.StandardDate)); @@ -687,7 +686,7 @@ base::string16 daylight_name_utf16 = base::UTF8ToUTF16(kDaylightName); c16lcpy(expected.TimeZone.DaylightName, daylight_name_utf16.c_str(), - ARRAYSIZE_UNSAFE(expected.TimeZone.DaylightName)); + ArraySize(expected.TimeZone.DaylightName)); memcpy(&expected.TimeZone.DaylightDate, &kSystemTimeZero, sizeof(expected.TimeZone.DaylightDate)); @@ -695,12 +694,12 @@ base::string16 build_string_utf16 = base::UTF8ToUTF16(kBuildString); c16lcpy(expected.BuildString, build_string_utf16.c_str(), - ARRAYSIZE_UNSAFE(expected.BuildString)); + ArraySize(expected.BuildString)); base::string16 debug_build_string_utf16 = base::UTF8ToUTF16(kDebugBuildString); c16lcpy(expected.DbgBldStr, debug_build_string_utf16.c_str(), - ARRAYSIZE_UNSAFE(expected.DbgBldStr)); + ArraySize(expected.DbgBldStr)); ExpectMiscInfoEqual(&expected, observed); } @@ -744,18 +743,18 @@ expect_misc_info.TimeZone.Bias = 300; c16lcpy(expect_misc_info.TimeZone.StandardName, standard_time_name_utf16.c_str(), - ARRAYSIZE_UNSAFE(expect_misc_info.TimeZone.StandardName)); + ArraySize(expect_misc_info.TimeZone.StandardName)); expect_misc_info.TimeZone.StandardBias = 0; c16lcpy(expect_misc_info.TimeZone.DaylightName, daylight_time_name_utf16.c_str(), - ARRAYSIZE_UNSAFE(expect_misc_info.TimeZone.DaylightName)); + ArraySize(expect_misc_info.TimeZone.DaylightName)); expect_misc_info.TimeZone.DaylightBias = -60; c16lcpy(expect_misc_info.BuildString, build_string_utf16.c_str(), - ARRAYSIZE_UNSAFE(expect_misc_info.BuildString)); + ArraySize(expect_misc_info.BuildString)); c16lcpy(expect_misc_info.DbgBldStr, debug_build_string_utf16.c_str(), - ARRAYSIZE_UNSAFE(expect_misc_info.DbgBldStr)); + ArraySize(expect_misc_info.DbgBldStr)); const timeval kStartTime = { static_cast<time_t>(expect_misc_info.ProcessCreateTime), 0 };
diff --git a/third_party/crashpad/crashpad/minidump/minidump_module_crashpad_info_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_module_crashpad_info_writer_test.cc index 63a9338..83401eca 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_module_crashpad_info_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_module_crashpad_info_writer_test.cc
@@ -28,6 +28,7 @@ #include "minidump/test/minidump_writable_test_util.h" #include "snapshot/test/test_module_snapshot.h" #include "util/file/string_file.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -154,9 +155,9 @@ sizeof(MinidumpSimpleStringDictionaryEntry) + sizeof(MinidumpAnnotationList) + 2 + // padding sizeof(MinidumpAnnotation) + sizeof(MinidumpUTF8String) + - arraysize(kEntry) + 2 + // padding - sizeof(MinidumpUTF8String) + arraysize(kKey) + - sizeof(MinidumpUTF8String) + arraysize(kValue) + + ArraySize(kEntry) + 2 + // padding + sizeof(MinidumpUTF8String) + ArraySize(kKey) + + sizeof(MinidumpUTF8String) + ArraySize(kValue) + sizeof(MinidumpUTF8String) + annotation.name.size() + 1 + sizeof(MinidumpByteArray) + annotation.value.size());
diff --git a/third_party/crashpad/crashpad/minidump/minidump_module_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_module_writer_test.cc index 0fddfe8..bef6a8c 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_module_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_module_writer_test.cc
@@ -30,6 +30,7 @@ #include "snapshot/test/test_module_snapshot.h" #include "test/gtest_death.h" #include "util/file/string_file.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" #include "util/misc/uuid.h" @@ -650,10 +651,10 @@ TEST(MinidumpModuleWriter, InitializeFromSnapshot) { MINIDUMP_MODULE expect_modules[3] = {}; - const char* module_paths[arraysize(expect_modules)] = {}; - const char* module_pdbs[arraysize(expect_modules)] = {}; - UUID uuids[arraysize(expect_modules)] = {}; - uint32_t ages[arraysize(expect_modules)] = {}; + const char* module_paths[ArraySize(expect_modules)] = {}; + const char* module_pdbs[ArraySize(expect_modules)] = {}; + UUID uuids[ArraySize(expect_modules)] = {}; + uint32_t ages[ArraySize(expect_modules)] = {}; expect_modules[0].BaseOfImage = 0x100101000; expect_modules[0].SizeOfImage = 0xf000; @@ -705,7 +706,7 @@ std::vector<std::unique_ptr<TestModuleSnapshot>> module_snapshots_owner; std::vector<const ModuleSnapshot*> module_snapshots; - for (size_t index = 0; index < arraysize(expect_modules); ++index) { + for (size_t index = 0; index < ArraySize(expect_modules); ++index) { module_snapshots_owner.push_back(std::make_unique<TestModuleSnapshot>()); TestModuleSnapshot* module_snapshot = module_snapshots_owner.back().get(); InitializeTestModuleSnapshotFromMinidumpModule(module_snapshot,
diff --git a/third_party/crashpad/crashpad/minidump/minidump_rva_list_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_rva_list_writer_test.cc index 3043287..bd376a9f 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_rva_list_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_rva_list_writer_test.cc
@@ -22,6 +22,7 @@ #include "minidump/test/minidump_rva_list_test_util.h" #include "minidump/test/minidump_writable_test_util.h" #include "util/file/string_file.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -86,10 +87,10 @@ ASSERT_TRUE(list_writer.WriteEverything(&string_file)); const MinidumpRVAList* list = - MinidumpRVAListAtStart(string_file.string(), arraysize(kValues)); + MinidumpRVAListAtStart(string_file.string(), ArraySize(kValues)); ASSERT_TRUE(list); - for (size_t index = 0; index < arraysize(kValues); ++index) { + for (size_t index = 0; index < ArraySize(kValues); ++index) { SCOPED_TRACE(base::StringPrintf("index %" PRIuS, index)); const uint32_t* child = MinidumpWritableAtRVA<uint32_t>(
diff --git a/third_party/crashpad/crashpad/minidump/minidump_string_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_string_writer_test.cc index 1d65485..aa73503 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_string_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_string_writer_test.cc
@@ -25,6 +25,7 @@ #include "minidump/test/minidump_string_writer_test_util.h" #include "minidump/test/minidump_writable_test_util.h" #include "util/file/string_file.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -66,14 +67,14 @@ {4, "\360\220\204\202", 2, {0xd800, 0xdd02}}, // 𐄂 (non-BMP) }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { SCOPED_TRACE(base::StringPrintf( "index %" PRIuS ", input %s", index, kTestData[index].input_string)); // Make sure that the expected output string with its NUL terminator fits in // the space provided. ASSERT_EQ(kTestData[index] - .output_string[arraysize(kTestData[index].output_string) - 1], + .output_string[ArraySize(kTestData[index].output_string) - 1], 0); string_file.Reset(); @@ -118,7 +119,7 @@ "\303\0\251", // NUL in middle of valid sequence }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { SCOPED_TRACE(base::StringPrintf( "index %" PRIuS ", input %s", index, kTestData[index])); string_file.Reset(); @@ -181,7 +182,7 @@ {4, "\360\220\204\202"}, // 𐄂 (non-BMP) }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { SCOPED_TRACE(base::StringPrintf( "index %" PRIuS ", input %s", index, kTestData[index].string));
diff --git a/third_party/crashpad/crashpad/minidump/minidump_system_info_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_system_info_writer.cc index cc87d24..df0e348b 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_system_info_writer.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_system_info_writer.cc
@@ -20,7 +20,7 @@ #include "minidump/minidump_string_writer.h" #include "snapshot/system_snapshot.h" #include "util/file/file_writer.h" -#include "util/misc/arraysize_unsafe.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" namespace crashpad { @@ -212,7 +212,7 @@ system_info_.ProcessorArchitecture == kMinidumpCPUArchitectureX86Win64); - static_assert(ARRAYSIZE_UNSAFE(system_info_.Cpu.X86CpuInfo.VendorId) == 3, + static_assert(ArraySize(system_info_.Cpu.X86CpuInfo.VendorId) == 3, "VendorId must have 3 elements"); system_info_.Cpu.X86CpuInfo.VendorId[0] = ebx; @@ -230,7 +230,7 @@ sizeof(registers) == sizeof(system_info_.Cpu.X86CpuInfo.VendorId), "VendorId sizes must be equal"); - for (size_t index = 0; index < arraysize(registers); ++index) { + for (size_t index = 0; index < ArraySize(registers); ++index) { memcpy(®isters[index], &vendor[index * sizeof(*registers)], sizeof(*registers)); @@ -270,9 +270,8 @@ system_info_.ProcessorArchitecture != kMinidumpCPUArchitectureX86Win64); - static_assert( - ARRAYSIZE_UNSAFE(system_info_.Cpu.OtherCpuInfo.ProcessorFeatures) == 2, - "ProcessorFeatures must have 2 elements"); + static_assert(ArraySize(system_info_.Cpu.OtherCpuInfo.ProcessorFeatures) == 2, + "ProcessorFeatures must have 2 elements"); system_info_.Cpu.OtherCpuInfo.ProcessorFeatures[0] = features_0; system_info_.Cpu.OtherCpuInfo.ProcessorFeatures[1] = features_1;
diff --git a/third_party/crashpad/crashpad/minidump/minidump_thread_id_map_test.cc b/third_party/crashpad/crashpad/minidump/minidump_thread_id_map_test.cc index 7c6795a..d64d8106 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_thread_id_map_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_thread_id_map_test.cc
@@ -21,6 +21,7 @@ #include "base/macros.h" #include "gtest/gtest.h" #include "snapshot/test/test_thread_snapshot.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -38,7 +39,7 @@ // testing::Test: void SetUp() override { - for (size_t index = 0; index < arraysize(test_thread_snapshots_); ++index) { + for (size_t index = 0; index < ArraySize(test_thread_snapshots_); ++index) { thread_snapshots_.push_back(&test_thread_snapshots_[index]); } } @@ -59,7 +60,7 @@ } void SetThreadID(size_t index, uint64_t thread_id) { - ASSERT_LT(index, arraysize(test_thread_snapshots_)); + ASSERT_LT(index, ArraySize(test_thread_snapshots_)); test_thread_snapshots_[index].SetThreadID(thread_id); }
diff --git a/third_party/crashpad/crashpad/minidump/minidump_thread_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_thread_writer_test.cc index e95c904..63269ce 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_thread_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_thread_writer_test.cc
@@ -33,6 +33,7 @@ #include "snapshot/test/test_thread_snapshot.h" #include "test/gtest_death.h" #include "util/file/string_file.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -522,10 +523,10 @@ void RunInitializeFromSnapshotTest(bool thread_id_collision) { using MinidumpContextType = typename Traits::MinidumpContextType; MINIDUMP_THREAD expect_threads[3] = {}; - uint64_t thread_ids[arraysize(expect_threads)] = {}; - uint8_t memory_values[arraysize(expect_threads)] = {}; - uint32_t context_seeds[arraysize(expect_threads)] = {}; - MINIDUMP_MEMORY_DESCRIPTOR tebs[arraysize(expect_threads)] = {}; + uint64_t thread_ids[ArraySize(expect_threads)] = {}; + uint8_t memory_values[ArraySize(expect_threads)] = {}; + uint32_t context_seeds[ArraySize(expect_threads)] = {}; + MINIDUMP_MEMORY_DESCRIPTOR tebs[ArraySize(expect_threads)] = {}; constexpr size_t kTebSize = 1024; @@ -581,7 +582,7 @@ std::vector<std::unique_ptr<TestThreadSnapshot>> thread_snapshots_owner; std::vector<const ThreadSnapshot*> thread_snapshots; - for (size_t index = 0; index < arraysize(expect_threads); ++index) { + for (size_t index = 0; index < ArraySize(expect_threads); ++index) { thread_snapshots_owner.push_back(std::make_unique<TestThreadSnapshot>()); TestThreadSnapshot* thread_snapshot = thread_snapshots_owner.back().get();
diff --git a/third_party/crashpad/crashpad/minidump/minidump_writable.cc b/third_party/crashpad/crashpad/minidump/minidump_writable.cc index d2b58f5..c8075c61 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_writable.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_writable.cc
@@ -18,6 +18,7 @@ #include "base/logging.h" #include "util/file/file_writer.h" +#include "util/misc/arraysize.h" #include "util/numeric/safe_assignment.h" namespace { @@ -244,7 +245,7 @@ // The number of elements in kZeroes must be at least one less than the // maximum Alignment() ever encountered. static constexpr uint8_t kZeroes[kMaximumAlignment - 1] = {}; - DCHECK_LE(leading_pad_bytes_, arraysize(kZeroes)); + DCHECK_LE(leading_pad_bytes_, ArraySize(kZeroes)); if (leading_pad_bytes_) { if (!file_writer->Write(&kZeroes, leading_pad_bytes_)) {
diff --git a/third_party/crashpad/crashpad/minidump/test/minidump_context_test_util.cc b/third_party/crashpad/crashpad/minidump/test/minidump_context_test_util.cc index 318b3fc..ae80d003 100644 --- a/third_party/crashpad/crashpad/minidump/test/minidump_context_test_util.cc +++ b/third_party/crashpad/crashpad/minidump/test/minidump_context_test_util.cc
@@ -18,12 +18,12 @@ #include <sys/types.h> #include "base/format_macros.h" -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "gtest/gtest.h" #include "snapshot/cpu_context.h" #include "snapshot/test/test_cpu_context.h" #include "test/hex_string.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -128,7 +128,7 @@ context->ds = static_cast<uint16_t>(value++); context->es = static_cast<uint16_t>(value++); context->ss = static_cast<uint16_t>(value++); - for (size_t index = 0; index < arraysize(context->vector_register); ++index) { + for (size_t index = 0; index < ArraySize(context->vector_register); ++index) { context->vector_register[index].lo = value++; context->vector_register[index].hi = value++; } @@ -151,7 +151,7 @@ uint32_t value = seed; - for (size_t index = 0; index < arraysize(context->regs); ++index) { + for (size_t index = 0; index < ArraySize(context->regs); ++index) { context->regs[index] = value++; } context->fp = value++; @@ -162,7 +162,7 @@ context->pc = value++; context->cpsr = value++; - for (size_t index = 0; index < arraysize(context->vfp); ++index) { + for (size_t index = 0; index < ArraySize(context->vfp); ++index) { context->vfp[index] = value++; } context->fpscr = value++; @@ -180,7 +180,7 @@ uint32_t value = seed; - for (size_t index = 0; index < arraysize(context->regs); ++index) { + for (size_t index = 0; index < ArraySize(context->regs); ++index) { context->regs[index] = value++; } context->fp = value++; @@ -189,7 +189,7 @@ context->pc = value++; context->cpsr = value++; - for (size_t index = 0; index < arraysize(context->fpsimd); ++index) { + for (size_t index = 0; index < ArraySize(context->fpsimd); ++index) { context->fpsimd[index].lo = value++; context->fpsimd[index].hi = value++; } @@ -209,7 +209,7 @@ uint32_t value = seed; - for (size_t index = 0; index < arraysize(context->regs); ++index) { + for (size_t index = 0; index < ArraySize(context->regs); ++index) { context->regs[index] = value++; } @@ -220,7 +220,7 @@ context->status = value++; context->cause = value++; - for (size_t index = 0; index < arraysize(context->fpregs.fregs); ++index) { + for (size_t index = 0; index < ArraySize(context->fpregs.fregs); ++index) { context->fpregs.fregs[index]._fp_fregs = static_cast<float>(value++); } @@ -247,7 +247,7 @@ uint64_t value = seed; - for (size_t index = 0; index < arraysize(context->regs); ++index) { + for (size_t index = 0; index < ArraySize(context->regs); ++index) { context->regs[index] = value++; } @@ -258,7 +258,7 @@ context->status = value++; context->cause = value++; - for (size_t index = 0; index < arraysize(context->fpregs.dregs); ++index) { + for (size_t index = 0; index < ArraySize(context->fpregs.dregs); ++index) { context->fpregs.dregs[index] = static_cast<double>(value++); } context->fpcsr = value++; @@ -293,35 +293,33 @@ EXPECT_EQ(observed->reserved_3, expected->reserved_3); EXPECT_EQ(observed->mxcsr, expected->mxcsr); EXPECT_EQ(observed->mxcsr_mask, expected->mxcsr_mask); - for (size_t st_mm_index = 0; - st_mm_index < arraysize(expected->st_mm); + for (size_t st_mm_index = 0; st_mm_index < ArraySize(expected->st_mm); ++st_mm_index) { SCOPED_TRACE(base::StringPrintf("st_mm_index %" PRIuS, st_mm_index)); EXPECT_EQ(BytesToHexString(observed->st_mm[st_mm_index].st, - arraysize(observed->st_mm[st_mm_index].st)), + ArraySize(observed->st_mm[st_mm_index].st)), BytesToHexString(expected->st_mm[st_mm_index].st, - arraysize(expected->st_mm[st_mm_index].st))); + ArraySize(expected->st_mm[st_mm_index].st))); EXPECT_EQ( BytesToHexString(observed->st_mm[st_mm_index].st_reserved, - arraysize(observed->st_mm[st_mm_index].st_reserved)), + ArraySize(observed->st_mm[st_mm_index].st_reserved)), BytesToHexString(expected->st_mm[st_mm_index].st_reserved, - arraysize(expected->st_mm[st_mm_index].st_reserved))); + ArraySize(expected->st_mm[st_mm_index].st_reserved))); } - for (size_t xmm_index = 0; - xmm_index < arraysize(expected->xmm); + for (size_t xmm_index = 0; xmm_index < ArraySize(expected->xmm); ++xmm_index) { EXPECT_EQ(BytesToHexString(observed->xmm[xmm_index], - arraysize(observed->xmm[xmm_index])), + ArraySize(observed->xmm[xmm_index])), BytesToHexString(expected->xmm[xmm_index], - arraysize(expected->xmm[xmm_index]))) + ArraySize(expected->xmm[xmm_index]))) << "xmm_index " << xmm_index; } EXPECT_EQ( - BytesToHexString(observed->reserved_4, arraysize(observed->reserved_4)), - BytesToHexString(expected->reserved_4, arraysize(expected->reserved_4))); + BytesToHexString(observed->reserved_4, ArraySize(observed->reserved_4)), + BytesToHexString(expected->reserved_4, ArraySize(expected->reserved_4))); EXPECT_EQ( - BytesToHexString(observed->available, arraysize(observed->available)), - BytesToHexString(expected->available, arraysize(expected->available))); + BytesToHexString(observed->available, ArraySize(observed->available)), + BytesToHexString(expected->available, ArraySize(expected->available))); } } // namespace @@ -346,11 +344,11 @@ EXPECT_EQ(observed->fsave.fpu_cs, expected.fsave.fpu_cs); EXPECT_EQ(observed->fsave.fpu_dp, expected.fsave.fpu_dp); EXPECT_EQ(observed->fsave.fpu_ds, expected.fsave.fpu_ds); - for (size_t index = 0; index < arraysize(expected.fsave.st); ++index) { + for (size_t index = 0; index < ArraySize(expected.fsave.st); ++index) { EXPECT_EQ(BytesToHexString(observed->fsave.st[index], - arraysize(observed->fsave.st[index])), + ArraySize(observed->fsave.st[index])), BytesToHexString(expected.fsave.st[index], - arraysize(expected.fsave.st[index]))) + ArraySize(expected.fsave.st[index]))) << "index " << index; } if (snapshot) { @@ -449,7 +447,7 @@ ExpectMinidumpContextFxsave(&expected.fxsave, &observed->fxsave); - for (size_t index = 0; index < arraysize(expected.vector_register); ++index) { + for (size_t index = 0; index < ArraySize(expected.vector_register); ++index) { if (snapshot) { EXPECT_EQ(observed->vector_register[index].lo, 0u) << "index " << index; EXPECT_EQ(observed->vector_register[index].hi, 0u) << "index " << index; @@ -489,7 +487,7 @@ EXPECT_EQ(observed->context_flags, expected.context_flags); - for (size_t index = 0; index < arraysize(expected.regs); ++index) { + for (size_t index = 0; index < ArraySize(expected.regs); ++index) { EXPECT_EQ(observed->regs[index], expected.regs[index]); } EXPECT_EQ(observed->fp, expected.fp); @@ -500,10 +498,10 @@ EXPECT_EQ(observed->cpsr, expected.cpsr); EXPECT_EQ(observed->fpscr, expected.fpscr); - for (size_t index = 0; index < arraysize(expected.vfp); ++index) { + for (size_t index = 0; index < ArraySize(expected.vfp); ++index) { EXPECT_EQ(observed->vfp[index], expected.vfp[index]); } - for (size_t index = 0; index < arraysize(expected.extra); ++index) { + for (size_t index = 0; index < ArraySize(expected.extra); ++index) { EXPECT_EQ(observed->extra[index], snapshot ? 0 : expected.extra[index]); } } @@ -516,14 +514,14 @@ EXPECT_EQ(observed->context_flags, expected.context_flags); - for (size_t index = 0; index < arraysize(expected.regs); ++index) { + for (size_t index = 0; index < ArraySize(expected.regs); ++index) { EXPECT_EQ(observed->regs[index], expected.regs[index]); } EXPECT_EQ(observed->cpsr, expected.cpsr); EXPECT_EQ(observed->fpsr, expected.fpsr); EXPECT_EQ(observed->fpcr, expected.fpcr); - for (size_t index = 0; index < arraysize(expected.fpsimd); ++index) { + for (size_t index = 0; index < ArraySize(expected.fpsimd); ++index) { EXPECT_EQ(observed->fpsimd[index].lo, expected.fpsimd[index].lo); EXPECT_EQ(observed->fpsimd[index].hi, expected.fpsimd[index].hi); } @@ -537,7 +535,7 @@ EXPECT_EQ(observed->context_flags, expected.context_flags); - for (size_t index = 0; index < arraysize(expected.regs); ++index) { + for (size_t index = 0; index < ArraySize(expected.regs); ++index) { EXPECT_EQ(observed->regs[index], expected.regs[index]); } @@ -548,7 +546,7 @@ EXPECT_EQ(observed->status, expected.status); EXPECT_EQ(observed->cause, expected.cause); - for (size_t index = 0; index < arraysize(expected.fpregs.fregs); ++index) { + for (size_t index = 0; index < ArraySize(expected.fpregs.fregs); ++index) { EXPECT_EQ(observed->fpregs.fregs[index]._fp_fregs, expected.fpregs.fregs[index]._fp_fregs); } @@ -570,7 +568,7 @@ EXPECT_EQ(observed->context_flags, expected.context_flags); - for (size_t index = 0; index < arraysize(expected.regs); ++index) { + for (size_t index = 0; index < ArraySize(expected.regs); ++index) { EXPECT_EQ(observed->regs[index], expected.regs[index]); } @@ -581,7 +579,7 @@ EXPECT_EQ(observed->status, expected.status); EXPECT_EQ(observed->cause, expected.cause); - for (size_t index = 0; index < arraysize(expected.fpregs.dregs); ++index) { + for (size_t index = 0; index < ArraySize(expected.fpregs.dregs); ++index) { EXPECT_EQ(observed->fpregs.dregs[index], expected.fpregs.dregs[index]); } EXPECT_EQ(observed->fpcsr, expected.fpcsr);
diff --git a/third_party/crashpad/crashpad/snapshot/BUILD.gn b/third_party/crashpad/crashpad/snapshot/BUILD.gn index 9fe8582..8d331fc 100644 --- a/third_party/crashpad/crashpad/snapshot/BUILD.gn +++ b/third_party/crashpad/crashpad/snapshot/BUILD.gn
@@ -235,29 +235,6 @@ } } -if (crashpad_is_win) { - static_library("snapshot_api") { - sources = [ - "api/module_annotations_win.cc", - "api/module_annotations_win.h", - ] - - public_configs = [ "..:crashpad_config" ] - - cflags = [ "/wd4201" ] - - deps = [ - ":snapshot", - "../compat", - "../third_party/mini_chromium:base", - "../util", - ] - } -} else { - group("snapshot_api") { - } -} - fuzzer_test("elf_image_reader_fuzzer") { sources = [ "elf/elf_image_reader_fuzzer.cc", @@ -367,11 +344,10 @@ if (crashpad_is_win) { sources += [ - "api/module_annotations_win_test.cc", "win/cpu_context_win_test.cc", "win/exception_snapshot_win_test.cc", "win/extra_memory_ranges_test.cc", - "win/pe_image_annotations_reader_test.cc", + "win/module_snapshot_win_test.cc", "win/pe_image_reader_test.cc", "win/process_reader_win_test.cc", "win/process_snapshot_win_test.cc", @@ -399,7 +375,6 @@ public_configs = [ ":snapshot_test_link" ] deps = [ - ":snapshot_api", ":test_support", "../client", "../compat",
diff --git a/third_party/crashpad/crashpad/snapshot/api/module_annotations_win.cc b/third_party/crashpad/crashpad/snapshot/api/module_annotations_win.cc deleted file mode 100644 index fd46870..0000000 --- a/third_party/crashpad/crashpad/snapshot/api/module_annotations_win.cc +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2016 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "snapshot/api/module_annotations_win.h" - -#include "snapshot/win/pe_image_annotations_reader.h" -#include "snapshot/win/pe_image_reader.h" -#include "snapshot/win/process_reader_win.h" -#include "util/misc/from_pointer_cast.h" -#include "util/win/get_module_information.h" - -namespace crashpad { - -bool ReadModuleAnnotations(HANDLE process, - HMODULE module, - std::map<std::string, std::string>* annotations) { - ProcessReaderWin process_reader; - if (!process_reader.Initialize(process, ProcessSuspensionState::kRunning)) - return false; - - MODULEINFO module_info; - if (!CrashpadGetModuleInformation( - process, module, &module_info, sizeof(module_info))) { - PLOG(ERROR) << "CrashpadGetModuleInformation"; - return false; - } - - PEImageReader image_reader; - if (!image_reader.Initialize( - &process_reader, - FromPointerCast<WinVMAddress>(module_info.lpBaseOfDll), - module_info.SizeOfImage, - "")) - return false; - - PEImageAnnotationsReader annotations_reader( - &process_reader, &image_reader, L""); - - *annotations = annotations_reader.SimpleMap(); - return true; -} - -} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/api/module_annotations_win.h b/third_party/crashpad/crashpad/snapshot/api/module_annotations_win.h deleted file mode 100644 index e024031..0000000 --- a/third_party/crashpad/crashpad/snapshot/api/module_annotations_win.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2016 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CRASHPAD_SNAPSHOT_API_MODULE_ANNOTATIONS_WIN_H_ -#define CRASHPAD_SNAPSHOT_API_MODULE_ANNOTATIONS_WIN_H_ - -#include <windows.h> - -#include <map> -#include <string> - -namespace crashpad { - -//! \brief Reads the module annotations from another process. -//! -//! \param[in] process The handle to the process that hosts the \a module. -//! Requires PROCESS_QUERY_INFORMATION and PROCESS_VM_READ accesses. -//! \param[in] module The handle to the module from which the \a annotations -//! will be read. This module should be loaded in the target process. -//! \param[out] annotations The map that will be filled with the annotations. -//! Remains unchanged if the function returns 'false'. -//! -//! \return `true` if the annotations could be read succesfully, even if the -//! module doesn't contain any annotations. -bool ReadModuleAnnotations(HANDLE process, - HMODULE module, - std::map<std::string, std::string>* annotations); - -} // namespace crashpad - -#endif // CRASHPAD_SNAPSHOT_API_MODULE_ANNOTATIONS_WIN_H_
diff --git a/third_party/crashpad/crashpad/snapshot/api/module_annotations_win_test.cc b/third_party/crashpad/crashpad/snapshot/api/module_annotations_win_test.cc deleted file mode 100644 index ecfa4659..0000000 --- a/third_party/crashpad/crashpad/snapshot/api/module_annotations_win_test.cc +++ /dev/null
@@ -1,83 +0,0 @@ -// Copyright 2016 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "snapshot/api/module_annotations_win.h" - -#include "client/crashpad_info.h" -#include "gtest/gtest.h" -#include "test/win/win_multiprocess.h" -#include "util/file/file_io.h" - -namespace crashpad { -namespace test { -namespace { - -class ModuleAnnotationsMultiprocessTest final : public WinMultiprocess { - private: - void WinMultiprocessParent() override { - // Read the child executable module. - HMODULE module = nullptr; - CheckedReadFileExactly(ReadPipeHandle(), &module, sizeof(module)); - - // Reopen the child process with necessary access. - HANDLE process_handle = - OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, - FALSE, - GetProcessId(ChildProcess())); - EXPECT_TRUE(process_handle); - - // Read the module annotations in the child process and verify them. - std::map<std::string, std::string> annotations; - ASSERT_TRUE(ReadModuleAnnotations(process_handle, module, &annotations)); - - EXPECT_GE(annotations.size(), 3u); - EXPECT_EQ(annotations["#APITEST# key"], "value"); - EXPECT_EQ(annotations["#APITEST# x"], "y"); - EXPECT_EQ(annotations["#APITEST# empty_value"], ""); - - // Signal the child process to terminate. - char c = ' '; - CheckedWriteFile(WritePipeHandle(), &c, sizeof(c)); - } - - void WinMultiprocessChild() override { - // Set some test annotations. - crashpad::CrashpadInfo* crashpad_info = - crashpad::CrashpadInfo::GetCrashpadInfo(); - - crashpad::SimpleStringDictionary* simple_annotations = - new crashpad::SimpleStringDictionary(); - simple_annotations->SetKeyValue("#APITEST# key", "value"); - simple_annotations->SetKeyValue("#APITEST# x", "y"); - simple_annotations->SetKeyValue("#APITEST# empty_value", ""); - - crashpad_info->set_simple_annotations(simple_annotations); - - // Send the executable module. - HMODULE module = GetModuleHandle(nullptr); - CheckedWriteFile(WritePipeHandle(), &module, sizeof(module)); - - // Wait until a signal from the parent process to terminate. - char c; - CheckedReadFileExactly(ReadPipeHandle(), &c, sizeof(c)); - } -}; - -TEST(ModuleAnnotationsWin, ReadAnnotations) { - WinMultiprocess::Run<ModuleAnnotationsMultiprocessTest>(); -} - -} // namespace -} // namespace test -} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/capture_memory.cc b/third_party/crashpad/crashpad/snapshot/capture_memory.cc index 98f400e..3ffbcd2 100644 --- a/third_party/crashpad/crashpad/snapshot/capture_memory.cc +++ b/third_party/crashpad/crashpad/snapshot/capture_memory.cc
@@ -20,6 +20,7 @@ #include <memory> #include "snapshot/memory_snapshot.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace internal { @@ -97,17 +98,17 @@ #elif defined(ARCH_CPU_ARM_FAMILY) if (context.architecture == kCPUArchitectureARM64) { MaybeCaptureMemoryAround(delegate, context.arm64->pc); - for (size_t i = 0; i < arraysize(context.arm64->regs); ++i) { + for (size_t i = 0; i < ArraySize(context.arm64->regs); ++i) { MaybeCaptureMemoryAround(delegate, context.arm64->regs[i]); } } else { MaybeCaptureMemoryAround(delegate, context.arm->pc); - for (size_t i = 0; i < arraysize(context.arm->regs); ++i) { + for (size_t i = 0; i < ArraySize(context.arm->regs); ++i) { MaybeCaptureMemoryAround(delegate, context.arm->regs[i]); } } #elif defined(ARCH_CPU_MIPS_FAMILY) - for (size_t i = 0; i < arraysize(context.mipsel->regs); ++i) { + for (size_t i = 0; i < ArraySize(context.mipsel->regs); ++i) { MaybeCaptureMemoryAround(delegate, context.mipsel->regs[i]); } #else
diff --git a/third_party/crashpad/crashpad/snapshot/cpu_context.cc b/third_party/crashpad/crashpad/snapshot/cpu_context.cc index 4d7c1e5..0ed1691 100644 --- a/third_party/crashpad/crashpad/snapshot/cpu_context.cc +++ b/third_party/crashpad/crashpad/snapshot/cpu_context.cc
@@ -18,7 +18,7 @@ #include <string.h> #include "base/logging.h" -#include "base/macros.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" namespace crashpad { @@ -55,9 +55,9 @@ fsave->fpu_dp = fxsave.fpu_dp; fsave->fpu_ds = fxsave.fpu_ds; fsave->reserved_4 = 0; - static_assert(arraysize(fsave->st) == arraysize(fxsave.st_mm), + static_assert(ArraySize(fsave->st) == ArraySize(fxsave.st_mm), "FPU stack registers must be equivalent"); - for (size_t index = 0; index < arraysize(fsave->st); ++index) { + for (size_t index = 0; index < ArraySize(fsave->st); ++index) { memcpy(fsave->st[index], fxsave.st_mm[index].st, sizeof(fsave->st[index])); } } @@ -77,9 +77,9 @@ fxsave->reserved_3 = 0; fxsave->mxcsr = 0; fxsave->mxcsr_mask = 0; - static_assert(arraysize(fxsave->st_mm) == arraysize(fsave.st), + static_assert(ArraySize(fxsave->st_mm) == ArraySize(fsave.st), "FPU stack registers must be equivalent"); - for (size_t index = 0; index < arraysize(fsave.st); ++index) { + for (size_t index = 0; index < ArraySize(fsave.st); ++index) { memcpy(fxsave->st_mm[index].st, fsave.st[index], sizeof(fsave.st[index])); memset(fxsave->st_mm[index].st_reserved, 0,
diff --git a/third_party/crashpad/crashpad/snapshot/cpu_context_test.cc b/third_party/crashpad/crashpad/snapshot/cpu_context_test.cc index 706f2fe..794d9b9f 100644 --- a/third_party/crashpad/crashpad/snapshot/cpu_context_test.cc +++ b/third_party/crashpad/crashpad/snapshot/cpu_context_test.cc
@@ -18,9 +18,9 @@ #include <string.h> #include <sys/types.h> -#include "base/macros.h" #include "gtest/gtest.h" #include "test/hex_string.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -124,7 +124,7 @@ &fxsave.st_mm[6].st, kExponentAllZero, false, kFractionAllZero); SetX87Register( &fxsave.st_mm[7].st, kExponentNormal, true, kFractionNormal); // valid - for (size_t index = 0; index < arraysize(fxsave.st_mm); ++index) { + for (size_t index = 0; index < ArraySize(fxsave.st_mm); ++index) { memset(&fxsave.st_mm[index].st_reserved, 0x5a, sizeof(fxsave.st_mm[index].st_reserved)); @@ -148,10 +148,10 @@ EXPECT_EQ(fsave.fpu_dp, fxsave.fpu_dp); EXPECT_EQ(fsave.fpu_ds, fxsave.fpu_ds); EXPECT_EQ(fsave.reserved_4, 0); - for (size_t index = 0; index < arraysize(fsave.st); ++index) { - EXPECT_EQ(BytesToHexString(fsave.st[index], arraysize(fsave.st[index])), + for (size_t index = 0; index < ArraySize(fsave.st); ++index) { + EXPECT_EQ(BytesToHexString(fsave.st[index], ArraySize(fsave.st[index])), BytesToHexString(fxsave.st_mm[index].st, - arraysize(fxsave.st_mm[index].st))) + ArraySize(fxsave.st_mm[index].st))) << "index " << index; } } @@ -204,14 +204,14 @@ EXPECT_EQ(fxsave.reserved_3, 0); EXPECT_EQ(fxsave.mxcsr, 0u); EXPECT_EQ(fxsave.mxcsr_mask, 0u); - for (size_t index = 0; index < arraysize(fxsave.st_mm); ++index) { + for (size_t index = 0; index < ArraySize(fxsave.st_mm); ++index) { EXPECT_EQ(BytesToHexString(fxsave.st_mm[index].st, - arraysize(fxsave.st_mm[index].st)), - BytesToHexString(fsave.st[index], arraysize(fsave.st[index]))) + ArraySize(fxsave.st_mm[index].st)), + BytesToHexString(fsave.st[index], ArraySize(fsave.st[index]))) << "index " << index; EXPECT_EQ(BytesToHexString(fxsave.st_mm[index].st_reserved, - arraysize(fxsave.st_mm[index].st_reserved)), - std::string(arraysize(fxsave.st_mm[index].st_reserved) * 2, '0')) + ArraySize(fxsave.st_mm[index].st_reserved)), + std::string(ArraySize(fxsave.st_mm[index].st_reserved) * 2, '0')) << "index " << index; } size_t unused_len = sizeof(fxsave) - offsetof(decltype(fxsave), xmm); @@ -318,7 +318,7 @@ // In this set, everything is valid. fsw = 0 << 11; // top = 0: logical 0-7 maps to physical 0-7 fxsave_tag = 0xff; // nothing empty - for (size_t index = 0; index < arraysize(st_mm); ++index) { + for (size_t index = 0; index < ArraySize(st_mm); ++index) { SetX87OrMMXRegister(&st_mm[index], kExponentNormal, true, kFractionAllZero); } EXPECT_EQ(CPUContextX86::FxsaveToFsaveTagWord(fsw, fxsave_tag, st_mm), 0);
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/memory_map_region_snapshot_fuchsia.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/memory_map_region_snapshot_fuchsia.cc index cf2ee61..45d39d2 100644 --- a/third_party/crashpad/crashpad/snapshot/fuchsia/memory_map_region_snapshot_fuchsia.cc +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/memory_map_region_snapshot_fuchsia.cc
@@ -15,6 +15,7 @@ #include "snapshot/fuchsia/memory_map_region_snapshot_fuchsia.h" #include "base/logging.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace internal { @@ -49,7 +50,7 @@ const uint32_t index = flags & (ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_PERM_EXECUTE); - DCHECK_LT(index, arraysize(mapping)); + DCHECK_LT(index, ArraySize(mapping)); const uint32_t protect_flags = mapping[index]; DCHECK_NE(protect_flags, 0u);
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia_test.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia_test.cc index df20bd3..5832a221 100644 --- a/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia_test.cc +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia_test.cc
@@ -24,6 +24,7 @@ #include "test/multiprocess_exec.h" #include "test/test_paths.h" #include "util/fuchsia/scoped_task_suspend.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -34,7 +35,7 @@ ASSERT_TRUE(process_reader.Initialize(*zx::process::self())); static constexpr char kTestMemory[] = "Some test memory"; - char buffer[arraysize(kTestMemory)]; + char buffer[ArraySize(kTestMemory)]; ASSERT_TRUE(process_reader.Memory()->Read( reinterpret_cast<zx_vaddr_t>(kTestMemory), sizeof(kTestMemory), &buffer)); EXPECT_STREQ(kTestMemory, buffer);
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia_test.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia_test.cc index 0f3e3bdc..ebb612be 100644 --- a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia_test.cc +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia_test.cc
@@ -24,6 +24,7 @@ #include "snapshot/fuchsia/process_snapshot_fuchsia.h" #include "test/multiprocess_exec.h" #include "util/fuchsia/scoped_task_suspend.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -103,8 +104,8 @@ private: void MultiprocessParent() override { - uintptr_t test_addresses[arraysize(kTestMappingPermAndSizes)]; - for (size_t i = 0; i < arraysize(test_addresses); ++i) { + uintptr_t test_addresses[ArraySize(kTestMappingPermAndSizes)]; + for (size_t i = 0; i < ArraySize(test_addresses); ++i) { ASSERT_TRUE(ReadFileExactly( ReadPipeHandle(), &test_addresses[i], sizeof(test_addresses[i]))); } @@ -114,7 +115,7 @@ ProcessSnapshotFuchsia process_snapshot; ASSERT_TRUE(process_snapshot.Initialize(*ChildProcess())); - for (size_t i = 0; i < arraysize(test_addresses); ++i) { + for (size_t i = 0; i < ArraySize(test_addresses); ++i) { const auto& t = kTestMappingPermAndSizes[i]; EXPECT_TRUE(HasSingleMatchingMapping(process_snapshot.MemoryMap(), test_addresses[i],
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc index 72d36d8a..e632bc1 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc
@@ -32,6 +32,7 @@ #include "test/errors.h" #include "test/linux/fake_ptrace_connection.h" #include "util/linux/address_types.h" +#include "util/misc/arraysize.h" #include "util/misc/clock.h" #include "util/misc/from_pointer_cast.h" #include "util/posix/signals.h" @@ -170,7 +171,7 @@ test_context->vfp.head.magic = VFP_MAGIC; test_context->vfp.head.size = sizeof(test_context->vfp); memset(&test_context->vfp.context, 'v', sizeof(test_context->vfp.context)); - for (size_t reg = 0; reg < arraysize(test_context->vfp.context.vfp.fpregs); + for (size_t reg = 0; reg < ArraySize(test_context->vfp.context.vfp.fpregs); ++reg) { test_context->vfp.context.vfp.fpregs[reg] = reg; } @@ -218,7 +219,7 @@ void InitializeContext(NativeCPUContext* context) { memset(context, 'x', sizeof(*context)); - for (size_t index = 0; index < arraysize(context->uc_mcontext.regs); + for (size_t index = 0; index < ArraySize(context->uc_mcontext.regs); ++index) { context->uc_mcontext.regs[index] = index; } @@ -237,7 +238,7 @@ test_context->fpsimd.head.size = sizeof(test_context->fpsimd); test_context->fpsimd.fpsr = 1; test_context->fpsimd.fpcr = 2; - for (size_t reg = 0; reg < arraysize(test_context->fpsimd.vregs); ++reg) { + for (size_t reg = 0; reg < ArraySize(test_context->fpsimd.vregs); ++reg) { test_context->fpsimd.vregs[reg] = reg; } @@ -270,7 +271,7 @@ using NativeCPUContext = ucontext_t; void InitializeContext(NativeCPUContext* context) { - for (size_t reg = 0; reg < arraysize(context->uc_mcontext.gregs); ++reg) { + for (size_t reg = 0; reg < ArraySize(context->uc_mcontext.gregs); ++reg) { context->uc_mcontext.gregs[reg] = reg; } memset(&context->uc_mcontext.fpregs, 44, sizeof(context->uc_mcontext.fpregs)); @@ -285,7 +286,7 @@ #define CPU_ARCH_NAME mips64 #endif - for (size_t reg = 0; reg < arraysize(expected.uc_mcontext.gregs); ++reg) { + for (size_t reg = 0; reg < ArraySize(expected.uc_mcontext.gregs); ++reg) { EXPECT_EQ(actual.CPU_ARCH_NAME->regs[reg], expected.uc_mcontext.gregs[reg]); }
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc index 1edc5ab..61b84f3 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc
@@ -47,6 +47,7 @@ #include "util/file/filesystem.h" #include "util/linux/direct_ptrace_connection.h" #include "util/misc/address_sanitizer.h" +#include "util/misc/arraysize.h" #include "util/misc/from_pointer_cast.h" #include "util/synchronization/semaphore.h" @@ -79,7 +80,7 @@ EXPECT_EQ(process_reader.ParentProcessID(), getppid()); static constexpr char kTestMemory[] = "Some test memory"; - char buffer[arraysize(kTestMemory)]; + char buffer[ArraySize(kTestMemory)]; ASSERT_TRUE(process_reader.Memory()->Read( reinterpret_cast<LinuxVMAddress>(kTestMemory), sizeof(kTestMemory),
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc index 6baee770..650b0c7 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc
@@ -28,6 +28,7 @@ #include "snapshot/mac/mach_o_image_symbol_table_reader.h" #include "snapshot/mac/process_reader_mac.h" #include "util/mac/checked_mach_address_range.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" namespace { @@ -182,7 +183,7 @@ // This vector is parallel to the kLoadCommandReaders array, and tracks // whether a singleton load command matching the |command| field has been // found yet. - std::vector<uint32_t> singleton_indices(arraysize(kLoadCommandReaders), + std::vector<uint32_t> singleton_indices(ArraySize(kLoadCommandReaders), kInvalidSegmentIndex); size_t offset = mach_header.Size(); @@ -235,8 +236,7 @@ return false; } - for (size_t reader_index = 0; - reader_index < arraysize(kLoadCommandReaders); + for (size_t reader_index = 0; reader_index < ArraySize(kLoadCommandReaders); ++reader_index) { if (load_command.cmd != kLoadCommandReaders[reader_index].command) { continue;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader_test.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader_test.cc index 2da97e8..cfbddc1 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader_test.cc
@@ -16,9 +16,9 @@ #include <mach-o/loader.h> -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -63,7 +63,7 @@ SEG_IMPORT, }; - for (size_t index = 0; index < arraysize(kSegmentTestData); ++index) { + for (size_t index = 0; index < ArraySize(kSegmentTestData); ++index) { EXPECT_EQ( MachOImageSegmentReader::SegmentNameString(kSegmentTestData[index]), kSegmentTestData[index]) @@ -106,7 +106,7 @@ SECT_ICON_TIFF, }; - for (size_t index = 0; index < arraysize(kSectionTestData); ++index) { + for (size_t index = 0; index < ArraySize(kSectionTestData); ++index) { EXPECT_EQ( MachOImageSegmentReader::SectionNameString(kSectionTestData[index]), kSectionTestData[index]) @@ -169,7 +169,7 @@ {SEG_IMPORT, "", "__IMPORT,"}, }; - for (size_t index = 0; index < arraysize(kSegmentAndSectionTestData); + for (size_t index = 0; index < ArraySize(kSegmentAndSectionTestData); ++index) { const auto& test = kSegmentAndSectionTestData[index]; EXPECT_EQ(MachOImageSegmentReader::SegmentAndSectionNameString(
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc index cf3604cf..e3f4df1 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc
@@ -41,6 +41,7 @@ #include "util/file/file_io.h" #include "util/mac/mac_util.h" #include "util/mach/mach_extensions.h" +#include "util/misc/arraysize.h" #include "util/misc/from_pointer_cast.h" #include "util/synchronization/semaphore.h" @@ -64,7 +65,7 @@ EXPECT_EQ(process_reader.ParentProcessID(), getppid()); static constexpr char kTestMemory[] = "Some test memory"; - char buffer[arraysize(kTestMemory)]; + char buffer[ArraySize(kTestMemory)]; ASSERT_TRUE(process_reader.Memory()->Read( FromPointerCast<mach_vm_address_t>(kTestMemory), sizeof(kTestMemory), @@ -612,11 +613,11 @@ const size_t source_lengths[] = { strlen(sources[0]), }; - static_assert(arraysize(sources) == arraysize(source_lengths), + static_assert(ArraySize(sources) == ArraySize(source_lengths), "arrays must be parallel"); program_ = clCreateProgramWithSource( - context_, arraysize(sources), sources, source_lengths, &rv); + context_, ArraySize(sources), sources, source_lengths, &rv); ASSERT_EQ(rv, CL_SUCCESS) << "clCreateProgramWithSource"; rv = clBuildProgram(
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types.cc index cbb114d7e..9ae8f7c 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types.cc
@@ -20,8 +20,8 @@ #include <memory> -#include "base/macros.h" #include "snapshot/mac/process_types/internal.h" +#include "util/misc/arraysize.h" #include "util/process/process_memory_mac.h" namespace crashpad { @@ -74,7 +74,7 @@ template <> inline void Assign<UInt64Array4, UInt32Array4>(UInt64Array4* destination, const UInt32Array4& source) { - for (size_t index = 0; index < arraysize(source); ++index) { + for (size_t index = 0; index < ArraySize(source); ++index) { (*destination)[index] = source[index]; } }
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc index 9020965..3d5976c 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc
@@ -25,6 +25,7 @@ #include "base/numerics/safe_math.h" #include "base/strings/stringprintf.h" #include "snapshot/mac/process_types/internal.h" +#include "util/misc/arraysize.h" #include "util/process/process_memory_mac.h" #if !DOXYGEN @@ -144,8 +145,8 @@ sizeof(dyld_all_image_infos<Traits>), // 16 }; - if (version >= arraysize(kSizeForVersion)) { - return kSizeForVersion[arraysize(kSizeForVersion) - 1]; + if (version >= ArraySize(kSizeForVersion)) { + return kSizeForVersion[ArraySize(kSizeForVersion) - 1]; } static_assert(std::is_unsigned<decltype(version)>::value,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc index f116c4d..9a9dc9d4 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc
@@ -20,13 +20,13 @@ #include <vector> -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "gtest/gtest.h" #include "snapshot/mac/process_types/internal.h" #include "test/mac/dyld.h" #include "util/mac/mac_util.h" +#include "util/misc/arraysize.h" #include "util/misc/from_pointer_cast.h" #include "util/misc/implicit_cast.h" @@ -147,7 +147,7 @@ {15, 164, 304}, {16, 176, 320}, }; - for (size_t index = 0; index < arraysize(kVersionsAndSizes); ++index) { + for (size_t index = 0; index < ArraySize(kVersionsAndSizes); ++index) { uint32_t version = kVersionsAndSizes[index].version; SCOPED_TRACE(base::StringPrintf("index %zu, version %u", index, version)); @@ -268,8 +268,7 @@ self_image_infos->sharedCacheBaseAddress); EXPECT_EQ(proctype_image_infos.dyldPath, reinterpret_cast<uint64_t>(self_image_infos->dyldPath)); - for (size_t index = 0; - index < arraysize(self_image_infos->notifyPorts); + for (size_t index = 0; index < ArraySize(self_image_infos->notifyPorts); ++index) { EXPECT_EQ(proctype_image_infos.notifyPorts[index], self_image_infos->notifyPorts[index]) @@ -289,8 +288,7 @@ // process_types version. It’s difficult to compare the reserved fields in // these older SDKs, so only do it where the declarations match. if (proctype_image_infos.version >= 14) { - for (size_t index = 0; - index < arraysize(proctype_image_infos.reserved); + for (size_t index = 0; index < ArraySize(proctype_image_infos.reserved); ++index) { EXPECT_EQ(proctype_image_infos.reserved[index], implicit_cast<uint64_t>(self_image_infos->reserved[index]))
diff --git a/third_party/crashpad/crashpad/snapshot/minidump/process_snapshot_minidump_test.cc b/third_party/crashpad/crashpad/snapshot/minidump/process_snapshot_minidump_test.cc index 52b0992..47876036 100644 --- a/third_party/crashpad/crashpad/snapshot/minidump/process_snapshot_minidump_test.cc +++ b/third_party/crashpad/crashpad/snapshot/minidump/process_snapshot_minidump_test.cc
@@ -28,6 +28,7 @@ #include "snapshot/minidump/minidump_annotation_reader.h" #include "snapshot/module_snapshot.h" #include "util/file/string_file.h" +#include "util/misc/arraysize.h" #include "util/misc/pdb_structures.h" namespace crashpad { @@ -858,27 +859,27 @@ minidump_context.fxsave.fpu_ip_64 = 42; minidump_context.fxsave.fpu_dp_64 = 43; - for (size_t i = 0; i < arraysize(minidump_context.vector_register); i++) { + for (size_t i = 0; i < ArraySize(minidump_context.vector_register); i++) { minidump_context.vector_register[i].lo = i * 2 + 44; minidump_context.vector_register[i].hi = i * 2 + 45; } - for (uint8_t i = 0; i < arraysize(minidump_context.fxsave.reserved_4); i++) { + for (uint8_t i = 0; i < ArraySize(minidump_context.fxsave.reserved_4); i++) { minidump_context.fxsave.reserved_4[i] = i * 2 + 115; minidump_context.fxsave.available[i] = i * 2 + 116; } - for (size_t i = 0; i < arraysize(minidump_context.fxsave.st_mm); i++) { + for (size_t i = 0; i < ArraySize(minidump_context.fxsave.st_mm); i++) { for (uint8_t j = 0; - j < arraysize(minidump_context.fxsave.st_mm[0].mm_value); + j < ArraySize(minidump_context.fxsave.st_mm[0].mm_value); j++) { minidump_context.fxsave.st_mm[i].mm_value[j] = j + 1; minidump_context.fxsave.st_mm[i].mm_reserved[j] = j + 1; } } - for (size_t i = 0; i < arraysize(minidump_context.fxsave.xmm); i++) { - for (uint8_t j = 0; j < arraysize(minidump_context.fxsave.xmm[0]); j++) { + for (size_t i = 0; i < ArraySize(minidump_context.fxsave.xmm); i++) { + for (uint8_t j = 0; j < ArraySize(minidump_context.fxsave.xmm[0]); j++) { minidump_context.fxsave.xmm[i][j] = j + 1; } } @@ -961,22 +962,20 @@ EXPECT_EQ(ctx->fxsave.fpu_ip_64, 42U); EXPECT_EQ(ctx->fxsave.fpu_dp_64, 43U); - for (uint8_t i = 0; i < arraysize(ctx->fxsave.reserved_4); i++) { + for (uint8_t i = 0; i < ArraySize(ctx->fxsave.reserved_4); i++) { EXPECT_EQ(ctx->fxsave.reserved_4[i], i * 2 + 115); EXPECT_EQ(ctx->fxsave.available[i], i * 2 + 116); } - for (size_t i = 0; i < arraysize(ctx->fxsave.st_mm); i++) { - for (uint8_t j = 0; - j < arraysize(ctx->fxsave.st_mm[0].mm_value); - j++) { + for (size_t i = 0; i < ArraySize(ctx->fxsave.st_mm); i++) { + for (uint8_t j = 0; j < ArraySize(ctx->fxsave.st_mm[0].mm_value); j++) { EXPECT_EQ(ctx->fxsave.st_mm[i].mm_value[j], j + 1); EXPECT_EQ(ctx->fxsave.st_mm[i].mm_reserved[j], j + 1); } } - for (size_t i = 0; i < arraysize(ctx->fxsave.xmm); i++) { - for (uint8_t j = 0; j < arraysize(ctx->fxsave.xmm[0]); j++) { + for (size_t i = 0; i < ArraySize(ctx->fxsave.xmm); i++) { + for (uint8_t j = 0; j < ArraySize(ctx->fxsave.xmm[0]); j++) { EXPECT_EQ(ctx->fxsave.xmm[i][j], j + 1); } }
diff --git a/third_party/crashpad/crashpad/snapshot/minidump/thread_snapshot_minidump.cc b/third_party/crashpad/crashpad/snapshot/minidump/thread_snapshot_minidump.cc index 00e0e9b..46ae97a 100644 --- a/third_party/crashpad/crashpad/snapshot/minidump/thread_snapshot_minidump.cc +++ b/third_party/crashpad/crashpad/snapshot/minidump/thread_snapshot_minidump.cc
@@ -18,6 +18,7 @@ #include <string.h> #include "minidump/minidump_context.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace internal { @@ -192,7 +193,7 @@ return false; } - for (size_t i = 0; i < arraysize(src->regs); i++) { + for (size_t i = 0; i < ArraySize(src->regs); i++) { context_.arm->regs[i] = src->regs[i]; } @@ -204,7 +205,7 @@ context_.arm->cpsr = src->cpsr; context_.arm->vfp_regs.fpscr = src->fpscr; - for (size_t i = 0; i < arraysize(src->vfp); i++) { + for (size_t i = 0; i < ArraySize(src->vfp); i++) { context_.arm->vfp_regs.vfp[i] = src->vfp[i]; } @@ -224,14 +225,14 @@ return false; } - for (size_t i = 0; i < arraysize(src->regs); i++) { + for (size_t i = 0; i < ArraySize(src->regs); i++) { context_.arm64->regs[i] = src->regs[i]; } context_.arm64->regs[29] = src->fp; context_.arm64->regs[30] = src->lr; - for (size_t i = 0; i < arraysize(src->fpsimd); i++) { + for (size_t i = 0; i < ArraySize(src->fpsimd); i++) { context_.arm64->fpsimd[i] = src->fpsimd[i]; } @@ -254,7 +255,7 @@ return false; } - for (size_t i = 0; i < arraysize(src->regs); i++) { + for (size_t i = 0; i < ArraySize(src->regs); i++) { context_.mipsel->regs[i] = src->regs[i]; } @@ -262,7 +263,7 @@ context_.mipsel->mdlo = static_cast<uint32_t>(src->mdlo); context_.mipsel->dsp_control = src->dsp_control; - for (size_t i = 0; i < arraysize(src->hi); i++) { + for (size_t i = 0; i < ArraySize(src->hi); i++) { context_.mipsel->hi[i] = src->hi[i]; context_.mipsel->lo[i] = src->lo[i]; } @@ -291,7 +292,7 @@ return false; } - for (size_t i = 0; i < arraysize(src->regs); i++) { + for (size_t i = 0; i < ArraySize(src->regs); i++) { context_.mips64->regs[i] = src->regs[i]; } @@ -299,7 +300,7 @@ context_.mips64->mdlo = src->mdlo; context_.mips64->dsp_control = src->dsp_control; - for (size_t i = 0; i < arraysize(src->hi); i++) { + for (size_t i = 0; i < ArraySize(src->hi); i++) { context_.mips64->hi[i] = src->hi[i]; context_.mips64->lo[i] = src->lo[i]; }
diff --git a/third_party/crashpad/crashpad/snapshot/posix/timezone.cc b/third_party/crashpad/crashpad/snapshot/posix/timezone.cc index 47c6ecfa..8b2b8221 100644 --- a/third_party/crashpad/crashpad/snapshot/posix/timezone.cc +++ b/third_party/crashpad/crashpad/snapshot/posix/timezone.cc
@@ -19,6 +19,7 @@ #include "base/logging.h" #include "build/build_config.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace internal { @@ -59,8 +60,7 @@ static constexpr int kMonthDeltas[] = {0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10, -10, 11, -11, 12, -12}; - for (size_t index = 0; - index < arraysize(kMonthDeltas) && !found_transition; + for (size_t index = 0; index < ArraySize(kMonthDeltas) && !found_transition; ++index) { // Look at a day of each month at local noon. Set tm_isdst to -1 to avoid // giving mktime() any hints about whether to consider daylight saving
diff --git a/third_party/crashpad/crashpad/snapshot/posix/timezone_test.cc b/third_party/crashpad/crashpad/snapshot/posix/timezone_test.cc index 814506fa..1bb19c4e 100644 --- a/third_party/crashpad/crashpad/snapshot/posix/timezone_test.cc +++ b/third_party/crashpad/crashpad/snapshot/posix/timezone_test.cc
@@ -25,6 +25,7 @@ #include "base/strings/stringprintf.h" #include "gtest/gtest.h" #include "test/errors.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -154,7 +155,7 @@ {"UTC", false, 0, 0, "UTC", "UTC"}, }; - for (size_t index = 0; index < arraysize(kTestTimeZones); ++index) { + for (size_t index = 0; index < ArraySize(kTestTimeZones); ++index) { const auto& test_time_zone = kTestTimeZones[index]; const char* tz = test_time_zone.tz; SCOPED_TRACE(base::StringPrintf("index %zu, tz %s", index, tz));
diff --git a/third_party/crashpad/crashpad/snapshot/sanitized/sanitization_information_test.cc b/third_party/crashpad/crashpad/snapshot/sanitized/sanitization_information_test.cc index a7bf8265..c7d836a5 100644 --- a/third_party/crashpad/crashpad/snapshot/sanitized/sanitization_information_test.cc +++ b/third_party/crashpad/crashpad/snapshot/sanitized/sanitization_information_test.cc
@@ -16,6 +16,7 @@ #include "build/build_config.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" #include "util/misc/from_pointer_cast.h" #include "util/process/process_memory_linux.h" @@ -59,8 +60,8 @@ TEST_F(WhitelistTest, NonEmptyWhitelist) { ASSERT_TRUE(ReadWhitelist(kNonEmptyWhitelist)); - ASSERT_EQ(whitelist_.size(), arraysize(kNonEmptyWhitelist) - 1); - for (size_t index = 0; index < arraysize(kNonEmptyWhitelist) - 1; ++index) { + ASSERT_EQ(whitelist_.size(), ArraySize(kNonEmptyWhitelist) - 1); + for (size_t index = 0; index < ArraySize(kNonEmptyWhitelist) - 1; ++index) { EXPECT_EQ(whitelist_[index], kNonEmptyWhitelist[index]); } }
diff --git a/third_party/crashpad/crashpad/snapshot/snapshot.gyp b/third_party/crashpad/crashpad/snapshot/snapshot.gyp index ac7de29..8c563f52 100644 --- a/third_party/crashpad/crashpad/snapshot/snapshot.gyp +++ b/third_party/crashpad/crashpad/snapshot/snapshot.gyp
@@ -210,32 +210,5 @@ }], ], }, - { - 'variables': { - 'conditions': [ - ['OS == "win"', { - 'snapshot_api_target_type%': 'static_library', - }, { - # There are no source files except on Windows. - 'snapshot_api_target_type%': 'none', - }], - ], - }, - 'target_name': 'crashpad_snapshot_api', - 'type': '<(snapshot_api_target_type)', - 'dependencies': [ - 'crashpad_snapshot', - '../compat/compat.gyp:crashpad_compat', - '../third_party/mini_chromium/mini_chromium.gyp:base', - '../util/util.gyp:crashpad_util', - ], - 'include_dirs': [ - '..', - ], - 'sources': [ - 'api/module_annotations_win.cc', - 'api/module_annotations_win.h', - ], - }, ], }
diff --git a/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp b/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp index b795d92..cf7b8aec 100644 --- a/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp +++ b/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp
@@ -57,7 +57,6 @@ 'crashpad_snapshot_test_module_large', 'crashpad_snapshot_test_module_small', 'snapshot.gyp:crashpad_snapshot', - 'snapshot.gyp:crashpad_snapshot_api', '../client/client.gyp:crashpad_client', '../compat/compat.gyp:crashpad_compat', '../test/test.gyp:crashpad_gtest_main', @@ -70,7 +69,6 @@ '..', ], 'sources': [ - 'api/module_annotations_win_test.cc', 'cpu_context_test.cc', 'memory_snapshot_test.cc', 'crashpad_info_client_options_test.cc', @@ -96,7 +94,7 @@ 'win/cpu_context_win_test.cc', 'win/exception_snapshot_win_test.cc', 'win/extra_memory_ranges_test.cc', - 'win/pe_image_annotations_reader_test.cc', + 'win/module_snapshot_win_test.cc', 'win/pe_image_reader_test.cc', 'win/process_reader_win_test.cc', 'win/process_snapshot_win_test.cc',
diff --git a/third_party/crashpad/crashpad/snapshot/test/test_cpu_context.cc b/third_party/crashpad/crashpad/snapshot/test/test_cpu_context.cc index 8e712b7a..7694d7e 100644 --- a/third_party/crashpad/crashpad/snapshot/test/test_cpu_context.cc +++ b/third_party/crashpad/crashpad/snapshot/test/test_cpu_context.cc
@@ -17,7 +17,7 @@ #include <string.h> #include <sys/types.h> -#include "base/macros.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -44,28 +44,28 @@ fxsave->reserved_3 = static_cast<uint16_t>(value++); fxsave->mxcsr = value++; fxsave->mxcsr_mask = value++; - for (size_t st_mm_index = 0; st_mm_index < arraysize(fxsave->st_mm); + for (size_t st_mm_index = 0; st_mm_index < ArraySize(fxsave->st_mm); ++st_mm_index) { - for (size_t byte = 0; byte < arraysize(fxsave->st_mm[st_mm_index].st); + for (size_t byte = 0; byte < ArraySize(fxsave->st_mm[st_mm_index].st); ++byte) { fxsave->st_mm[st_mm_index].st[byte] = static_cast<uint8_t>(value++); } for (size_t byte = 0; - byte < arraysize(fxsave->st_mm[st_mm_index].st_reserved); + byte < ArraySize(fxsave->st_mm[st_mm_index].st_reserved); ++byte) { fxsave->st_mm[st_mm_index].st_reserved[byte] = static_cast<uint8_t>(value); } } - for (size_t xmm_index = 0; xmm_index < arraysize(fxsave->xmm); ++xmm_index) { - for (size_t byte = 0; byte < arraysize(fxsave->xmm[xmm_index]); ++byte) { + for (size_t xmm_index = 0; xmm_index < ArraySize(fxsave->xmm); ++xmm_index) { + for (size_t byte = 0; byte < ArraySize(fxsave->xmm[xmm_index]); ++byte) { fxsave->xmm[xmm_index][byte] = static_cast<uint8_t>(value++); } } - for (size_t byte = 0; byte < arraysize(fxsave->reserved_4); ++byte) { + for (size_t byte = 0; byte < ArraySize(fxsave->reserved_4); ++byte) { fxsave->reserved_4[byte] = static_cast<uint8_t>(value++); } - for (size_t byte = 0; byte < arraysize(fxsave->available); ++byte) { + for (size_t byte = 0; byte < ArraySize(fxsave->available); ++byte) { fxsave->available[byte] = static_cast<uint8_t>(value++); } @@ -174,7 +174,7 @@ uint32_t value = seed; - for (size_t index = 0; index < arraysize(arm->regs); ++index) { + for (size_t index = 0; index < ArraySize(arm->regs); ++index) { arm->regs[index] = value++; } arm->fp = value++; @@ -185,7 +185,7 @@ arm->pc = value++; arm->cpsr = value++; - for (size_t index = 0; index < arraysize(arm->vfp_regs.vfp); ++index) { + for (size_t index = 0; index < ArraySize(arm->vfp_regs.vfp); ++index) { arm->vfp_regs.vfp[index] = value++; } arm->vfp_regs.fpscr = value++; @@ -205,14 +205,14 @@ uint32_t value = seed; - for (size_t index = 0; index < arraysize(arm64->regs); ++index) { + for (size_t index = 0; index < ArraySize(arm64->regs); ++index) { arm64->regs[index] = value++; } arm64->sp = value++; arm64->pc = value++; arm64->spsr = value++; - for (size_t index = 0; index < arraysize(arm64->fpsimd); ++index) { + for (size_t index = 0; index < ArraySize(arm64->fpsimd); ++index) { arm64->fpsimd[index].lo = value++; arm64->fpsimd[index].hi = value++; } @@ -231,7 +231,7 @@ uint32_t value = seed; - for (size_t index = 0; index < arraysize(mipsel->regs); ++index) { + for (size_t index = 0; index < ArraySize(mipsel->regs); ++index) { mipsel->regs[index] = value++; } @@ -242,7 +242,7 @@ mipsel->cp0_status = value++; mipsel->cp0_cause = value++; - for (size_t index = 0; index < arraysize(mipsel->fpregs.fregs); ++index) { + for (size_t index = 0; index < ArraySize(mipsel->fpregs.fregs); ++index) { mipsel->fpregs.fregs[index]._fp_fregs = static_cast<float>(value++); } @@ -267,7 +267,7 @@ uint64_t value = seed; - for (size_t index = 0; index < arraysize(mips64->regs); ++index) { + for (size_t index = 0; index < ArraySize(mips64->regs); ++index) { mips64->regs[index] = value++; } @@ -278,7 +278,7 @@ mips64->cp0_status = value++; mips64->cp0_cause = value++; - for (size_t index = 0; index < arraysize(mips64->fpregs.dregs); ++index) { + for (size_t index = 0; index < ArraySize(mips64->fpregs.dregs); ++index) { mips64->fpregs.dregs[index] = static_cast<double>(value++); }
diff --git a/third_party/crashpad/crashpad/snapshot/win/cpu_context_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/cpu_context_win_test.cc index aa2afe9..7f66f9d3 100644 --- a/third_party/crashpad/crashpad/snapshot/win/cpu_context_win_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/cpu_context_win_test.cc
@@ -16,11 +16,11 @@ #include <windows.h> -#include "base/macros.h" #include "build/build_config.h" #include "gtest/gtest.h" -#include "test/hex_string.h" #include "snapshot/cpu_context.h" +#include "test/hex_string.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -87,13 +87,13 @@ for (size_t st_mm = 0; st_mm < 7; ++st_mm) { EXPECT_EQ( BytesToHexString(cpu_context_x86.fxsave.st_mm[st_mm].st, - arraysize(cpu_context_x86.fxsave.st_mm[st_mm].st)), - std::string(arraysize(cpu_context_x86.fxsave.st_mm[st_mm].st) * 2, + ArraySize(cpu_context_x86.fxsave.st_mm[st_mm].st)), + std::string(ArraySize(cpu_context_x86.fxsave.st_mm[st_mm].st) * 2, '0')) << "st_mm " << st_mm; } EXPECT_EQ(BytesToHexString(cpu_context_x86.fxsave.st_mm[7].st, - arraysize(cpu_context_x86.fxsave.st_mm[7].st)), + ArraySize(cpu_context_x86.fxsave.st_mm[7].st)), "0000000000000080ff7f"); EXPECT_EQ(cpu_context_x86.dr0, 3u);
diff --git a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_image_reader.cc b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_image_reader.cc index 4ebd98e9..e6a9e5d 100644 --- a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_image_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_image_reader.cc
@@ -17,6 +17,7 @@ #include "base/logging.h" #include "client/crashpad_info.h" #include "util/file/file_io.h" +#include "util/misc/arraysize.h" #include "util/synchronization/semaphore.h" #include "util/win/scoped_handle.h" @@ -28,7 +29,7 @@ // Allocate a bunch of pointers to things on the stack. int* pointers[1000]; - for (size_t i = 0; i < arraysize(pointers); ++i) { + for (size_t i = 0; i < ArraySize(pointers); ++i) { pointers[i] = new int[2048]; } @@ -52,7 +53,7 @@ // verify the cap on pointed-to memory. crashpad::Semaphore semaphore(0); crashpad::ScopedKernelHANDLE threads[100]; - for (size_t i = 0; i < arraysize(threads); ++i) { + for (size_t i = 0; i < ArraySize(threads); ++i) { threads[i].reset(CreateThread(nullptr, 0, &LotsOfReferencesThreadProc, @@ -65,7 +66,7 @@ } } - for (size_t i = 0; i < arraysize(threads); ++i) { + for (size_t i = 0; i < ArraySize(threads); ++i) { semaphore.Wait(); }
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader_test.cc b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win_test.cc similarity index 87% rename from third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader_test.cc rename to third_party/crashpad/crashpad/snapshot/win/module_snapshot_win_test.cc index e102600..6a14cf5e 100644 --- a/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win_test.cc
@@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "snapshot/win/pe_image_annotations_reader.h" +#include "snapshot/win/module_snapshot_win.h" #include <stdlib.h> #include <string.h> @@ -74,20 +74,15 @@ std::map<std::string, std::string> all_annotations_simple_map; std::vector<AnnotationSnapshot> all_annotation_objects; for (const ProcessInfo::Module& module : modules) { - PEImageReader pe_image_reader; - pe_image_reader.Initialize(&process_reader, - module.dll_base, - module.size, - base::UTF16ToUTF8(module.name)); - PEImageAnnotationsReader module_annotations_reader( - &process_reader, &pe_image_reader, module.name); + internal::ModuleSnapshotWin module_snapshot; + module_snapshot.Initialize(&process_reader, module); std::map<std::string, std::string> module_annotations_simple_map = - module_annotations_reader.SimpleMap(); + module_snapshot.AnnotationsSimpleMap(); all_annotations_simple_map.insert(module_annotations_simple_map.begin(), module_annotations_simple_map.end()); - auto module_annotations_list = module_annotations_reader.AnnotationsList(); + auto module_annotations_list = module_snapshot.AnnotationObjects(); all_annotation_objects.insert(all_annotation_objects.end(), module_annotations_list.begin(), module_annotations_list.end()); @@ -146,16 +141,16 @@ EXPECT_EQ(child.WaitForExit(), expected_exit_code); } -TEST(PEImageAnnotationsReader, DontCrash) { +TEST(ModuleSnapshotWinTest, DontCrash) { TestAnnotationsOnCrash(kDontCrash, TestPaths::Architecture::kDefault); } -TEST(PEImageAnnotationsReader, CrashDebugBreak) { +TEST(ModuleSnapshotWinTest, CrashDebugBreak) { TestAnnotationsOnCrash(kCrashDebugBreak, TestPaths::Architecture::kDefault); } #if defined(ARCH_CPU_64_BITS) -TEST(PEImageAnnotationsReader, DontCrashWOW64) { +TEST(ModuleSnapshotWinTest, DontCrashWOW64) { if (!TestPaths::Has32BitBuildArtifacts()) { DISABLED_TEST(); } @@ -163,7 +158,7 @@ TestAnnotationsOnCrash(kDontCrash, TestPaths::Architecture::k32Bit); } -TEST(PEImageAnnotationsReader, CrashDebugBreakWOW64) { +TEST(ModuleSnapshotWinTest, CrashDebugBreakWOW64) { if (!TestPaths::Has32BitBuildArtifacts()) { DISABLED_TEST(); }
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader.cc b/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader.cc index 4c1f66f..c5e5373 100644 --- a/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader.cc
@@ -23,6 +23,7 @@ #include "snapshot/snapshot_constants.h" #include "snapshot/win/pe_image_reader.h" #include "snapshot/win/process_reader_win.h" +#include "util/misc/arraysize.h" #include "util/win/process_structs.h" namespace crashpad { @@ -155,7 +156,7 @@ snapshot.type = current.type; char name[Annotation::kNameMaxLength]; - if (!process_reader_->Memory()->Read(current.name, arraysize(name), name)) { + if (!process_reader_->Memory()->Read(current.name, ArraySize(name), name)) { LOG(WARNING) << "could not read annotation name at index " << index << " in " << base::UTF16ToUTF8(name_); continue;
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.cc b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.cc index e705bb5..094cf0fd 100644 --- a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.cc
@@ -24,6 +24,7 @@ #include "base/strings/stringprintf.h" #include "client/crashpad_info.h" #include "snapshot/win/pe_image_resource_reader.h" +#include "util/misc/arraysize.h" #include "util/misc/from_pointer_cast.h" #include "util/misc/pdb_structures.h" #include "util/win/process_structs.h" @@ -275,7 +276,7 @@ version_info.wType != 0 || wcsncmp(version_info.szKey, L"VS_VERSION_INFO", - arraysize(version_info.szKey)) != 0) { + ArraySize(version_info.szKey)) != 0) { LOG(WARNING) << "unexpected VS_VERSIONINFO in " << module_subrange_reader_.name(); return false;
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader_test.cc b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader_test.cc index ac456e2..161d9c8e 100644 --- a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader_test.cc
@@ -14,7 +14,9 @@ #include "snapshot/win/pe_image_reader.h" -#define PSAPI_VERSION 1 +#ifndef PSAPI_VERSION +#define PSAPI_VERSION 2 +#endif #include <psapi.h> #include "base/files/file_path.h"
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_reader_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/process_reader_win_test.cc index b0601e8..eca6f48 100644 --- a/third_party/crashpad/crashpad/snapshot/win/process_reader_win_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/process_reader_win_test.cc
@@ -19,6 +19,7 @@ #include "gtest/gtest.h" #include "test/win/win_multiprocess.h" +#include "util/misc/arraysize.h" #include "util/misc/from_pointer_cast.h" #include "util/synchronization/semaphore.h" #include "util/thread/thread.h" @@ -43,7 +44,7 @@ EXPECT_EQ(process_reader.GetProcessInfo().ProcessID(), GetCurrentProcessId()); static constexpr char kTestMemory[] = "Some test memory"; - char buffer[arraysize(kTestMemory)]; + char buffer[ArraySize(kTestMemory)]; ASSERT_TRUE(process_reader.Memory()->Read( reinterpret_cast<uintptr_t>(kTestMemory), sizeof(kTestMemory), &buffer)); EXPECT_STREQ(kTestMemory, buffer); @@ -184,7 +185,7 @@ // the pipe. CheckedReadFileAtEOF(ReadPipeHandle()); - for (size_t i = 0; i < arraysize(threads); ++i) + for (size_t i = 0; i < ArraySize(threads); ++i) done.Signal(); for (auto& thread : threads) thread.Join();
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.cc b/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.cc index 94dd22b..5d98a5f 100644 --- a/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.cc +++ b/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.cc
@@ -24,6 +24,7 @@ #include "base/numerics/safe_conversions.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "util/misc/arraysize.h" #include "util/misc/from_pointer_cast.h" #include "util/misc/time.h" #include "util/win/nt_internals.h" @@ -334,7 +335,7 @@ uet.TimeDateStamp, base::UTF16ToUTF8(base::StringPiece16( uet.ImageName, - wcsnlen(uet.ImageName, arraysize(uet.ImageName)))))); + wcsnlen(uet.ImageName, ArraySize(uet.ImageName)))))); } } } @@ -534,9 +535,9 @@ env_block.resize( static_cast<unsigned int>(bytes_read / sizeof(env_block[0]))); static constexpr wchar_t terminator[] = {0, 0}; - size_t at = env_block.find(std::wstring(terminator, arraysize(terminator))); + size_t at = env_block.find(std::wstring(terminator, ArraySize(terminator))); if (at != std::wstring::npos) - env_block.resize(at + arraysize(terminator)); + env_block.resize(at + ArraySize(terminator)); return env_block.size() * sizeof(env_block[0]); }
diff --git a/third_party/crashpad/crashpad/test/hex_string.h b/third_party/crashpad/crashpad/test/hex_string.h index 435a692..2d7801b 100644 --- a/third_party/crashpad/crashpad/test/hex_string.h +++ b/third_party/crashpad/crashpad/test/hex_string.h
@@ -29,8 +29,8 @@ //! uint8_t expected[10]; //! uint8_t observed[10]; //! // … -//! EXPECT_EQ(BytesToHexString(observed, arraysize(observed)), -//! BytesToHexString(expected, arraysize(expected))); +//! EXPECT_EQ(BytesToHexString(observed, ArraySize(observed)), +//! BytesToHexString(expected, ArraySize(expected))); //! \endcode std::string BytesToHexString(const void* bytes, size_t length);
diff --git a/third_party/crashpad/crashpad/test/hex_string_test.cc b/third_party/crashpad/crashpad/test/hex_string_test.cc index 68745e6..3d44cc9 100644 --- a/third_party/crashpad/crashpad/test/hex_string_test.cc +++ b/third_party/crashpad/crashpad/test/hex_string_test.cc
@@ -14,8 +14,8 @@ #include "test/hex_string.h" -#include "base/macros.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -25,7 +25,7 @@ EXPECT_EQ(BytesToHexString(nullptr, 0), ""); static constexpr char kBytes[] = "Abc123xyz \x0a\x7f\xf0\x9f\x92\xa9_"; - EXPECT_EQ(BytesToHexString(kBytes, arraysize(kBytes)), + EXPECT_EQ(BytesToHexString(kBytes, ArraySize(kBytes)), "41626331323378797a200a7ff09f92a95f00"); }
diff --git a/third_party/crashpad/crashpad/tools/crashpad_database_util.cc b/third_party/crashpad/crashpad/tools/crashpad_database_util.cc index b4c2a15b..d8274c5 100644 --- a/third_party/crashpad/crashpad/tools/crashpad_database_util.cc +++ b/third_party/crashpad/crashpad/tools/crashpad_database_util.cc
@@ -28,7 +28,6 @@ #include "base/files/file_path.h" #include "base/logging.h" -#include "base/macros.h" #include "base/numerics/safe_conversions.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -37,6 +36,7 @@ #include "tools/tool_support.h" #include "util/file/file_io.h" #include "util/file/file_reader.h" +#include "util/misc/arraysize.h" #include "util/misc/uuid.h" #include "util/stdlib/string_number_conversion.h" @@ -109,14 +109,14 @@ "set", }; - for (size_t index = 0; index < arraysize(kFalseWords); ++index) { + for (size_t index = 0; index < ArraySize(kFalseWords); ++index) { if (strcasecmp(string, kFalseWords[index]) == 0) { *boolean = false; return true; } } - for (size_t index = 0; index < arraysize(kTrueWords); ++index) { + for (size_t index = 0; index < ArraySize(kTrueWords); ++index) { if (strcasecmp(string, kTrueWords[index]) == 0) { *boolean = true; return true; @@ -159,7 +159,7 @@ "%+", }; - for (size_t index = 0; index < arraysize(kFormats); ++index) { + for (size_t index = 0; index < ArraySize(kFormats); ++index) { tm time_tm; const char* strptime_result = strptime(string, kFormats[index], &time_tm); if (strptime_result == end) { @@ -214,7 +214,7 @@ char string[64]; CHECK_NE( - strftime(string, arraysize(string), "%Y-%m-%d %H:%M:%S %Z", &time_tm), + strftime(string, ArraySize(string), "%Y-%m-%d %H:%M:%S %Z", &time_tm), 0u); return std::string(string);
diff --git a/third_party/crashpad/crashpad/util/BUILD.gn b/third_party/crashpad/crashpad/util/BUILD.gn index c7c6837..b5e1561a 100644 --- a/third_party/crashpad/crashpad/util/BUILD.gn +++ b/third_party/crashpad/crashpad/util/BUILD.gn
@@ -86,7 +86,7 @@ "file/string_file.h", "misc/address_sanitizer.h", "misc/address_types.h", - "misc/arraysize_unsafe.h", + "misc/arraysize.h", "misc/as_underlying_type.h", "misc/capture_context.h", "misc/clock.h", @@ -530,7 +530,7 @@ "file/file_reader_test.cc", "file/filesystem_test.cc", "file/string_file_test.cc", - "misc/arraysize_unsafe_test.cc", + "misc/arraysize_test.cc", "misc/capture_context_test.cc", "misc/capture_context_test_util.h", "misc/clock_test.cc",
diff --git a/third_party/crashpad/crashpad/util/file/delimited_file_reader.cc b/third_party/crashpad/crashpad/util/file/delimited_file_reader.cc index a55c2a7c..2a8678f0 100644 --- a/third_party/crashpad/crashpad/util/file/delimited_file_reader.cc +++ b/third_party/crashpad/crashpad/util/file/delimited_file_reader.cc
@@ -21,6 +21,7 @@ #include "base/logging.h" #include "base/numerics/safe_conversions.h" +#include "util/misc/arraysize.h" namespace crashpad { @@ -75,7 +76,7 @@ return Result::kEndOfFile; } - DCHECK_LE(static_cast<size_t>(read_result), arraysize(buf_)); + DCHECK_LE(static_cast<size_t>(read_result), ArraySize(buf_)); DCHECK( base::IsValueInRangeForNumericType<decltype(buf_len_)>(read_result)); buf_len_ = static_cast<decltype(buf_len_)>(read_result);
diff --git a/third_party/crashpad/crashpad/util/file/delimited_file_reader_test.cc b/third_party/crashpad/crashpad/util/file/delimited_file_reader_test.cc index 79e331f..b226f3d 100644 --- a/third_party/crashpad/crashpad/util/file/delimited_file_reader_test.cc +++ b/third_party/crashpad/crashpad/util/file/delimited_file_reader_test.cc
@@ -20,6 +20,7 @@ #include "base/strings/stringprintf.h" #include "gtest/gtest.h" #include "util/file/string_file.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -259,7 +260,7 @@ TEST(DelimitedFileReader, EmbeddedNUL) { static constexpr char kString[] = "embedded\0NUL\n"; StringFile string_file; - string_file.SetString(std::string(kString, arraysize(kString) - 1)); + string_file.SetString(std::string(kString, ArraySize(kString) - 1)); DelimitedFileReader delimited_file_reader(&string_file); std::string line; @@ -277,7 +278,7 @@ TEST(DelimitedFileReader, NULDelimiter) { static constexpr char kString[] = "aa\0b\0ccc\0"; StringFile string_file; - string_file.SetString(std::string(kString, arraysize(kString) - 1)); + string_file.SetString(std::string(kString, ArraySize(kString) - 1)); DelimitedFileReader delimited_file_reader(&string_file); std::string field; @@ -301,7 +302,7 @@ TEST(DelimitedFileReader, EdgeCases) { static constexpr size_t kSizes[] = {4094, 4095, 4096, 4097, 8190, 8191, 8192, 8193}; - for (size_t index = 0; index < arraysize(kSizes); ++index) { + for (size_t index = 0; index < ArraySize(kSizes); ++index) { size_t size = kSizes[index]; SCOPED_TRACE( base::StringPrintf("index %" PRIuS ", size %" PRIuS, index, size));
diff --git a/third_party/crashpad/crashpad/util/file/file_io_test.cc b/third_party/crashpad/crashpad/util/file/file_io_test.cc index 4446c320..d341a5d 100644 --- a/third_party/crashpad/crashpad/util/file/file_io_test.cc +++ b/third_party/crashpad/crashpad/util/file/file_io_test.cc
@@ -27,6 +27,7 @@ #include "test/errors.h" #include "test/file.h" #include "test/scoped_temp_dir.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" #include "util/thread/thread.h" @@ -612,7 +613,7 @@ LockingTestThread threads[20]; int expected_iterations = 0; - for (size_t index = 0; index < arraysize(threads); ++index) { + for (size_t index = 0; index < ArraySize(threads); ++index) { int iterations_for_this_thread = static_cast<int>(index * 10); threads[index].Init( (other_locks == FileLocking::kShared)
diff --git a/third_party/crashpad/crashpad/util/linux/direct_ptrace_connection.cc b/third_party/crashpad/crashpad/util/linux/direct_ptrace_connection.cc index ac44bf13..371bed2 100644 --- a/third_party/crashpad/crashpad/util/linux/direct_ptrace_connection.cc +++ b/third_party/crashpad/crashpad/util/linux/direct_ptrace_connection.cc
@@ -22,6 +22,7 @@ #include "base/strings/string_number_conversions.h" #include "util/file/directory_reader.h" #include "util/file/file_io.h" +#include "util/misc/arraysize.h" #include "util/misc/as_underlying_type.h" namespace crashpad { @@ -92,7 +93,7 @@ DCHECK(threads->empty()); char path[32]; - snprintf(path, arraysize(path), "/proc/%d/task", pid_); + snprintf(path, ArraySize(path), "/proc/%d/task", pid_); DirectoryReader reader; if (!reader.Open(base::FilePath(path))) { return false;
diff --git a/third_party/crashpad/crashpad/util/linux/proc_stat_reader.cc b/third_party/crashpad/crashpad/util/linux/proc_stat_reader.cc index 795e5139..60f1054 100644 --- a/third_party/crashpad/crashpad/util/linux/proc_stat_reader.cc +++ b/third_party/crashpad/crashpad/util/linux/proc_stat_reader.cc
@@ -21,6 +21,7 @@ #include "base/files/file_path.h" #include "base/logging.h" #include "util/file/file_io.h" +#include "util/misc/arraysize.h" #include "util/misc/lexing.h" #include "util/misc/time.h" @@ -47,7 +48,7 @@ INITIALIZATION_STATE_SET_INITIALIZING(initialized_); char path[32]; - snprintf(path, arraysize(path), "/proc/%d/stat", tid); + snprintf(path, ArraySize(path), "/proc/%d/stat", tid); if (!connection->ReadFileContents(base::FilePath(path), &contents_)) { return false; }
diff --git a/third_party/crashpad/crashpad/util/linux/ptrace_client.cc b/third_party/crashpad/crashpad/util/linux/ptrace_client.cc index 34fcbc3..e8afaa4 100644 --- a/third_party/crashpad/crashpad/util/linux/ptrace_client.cc +++ b/third_party/crashpad/crashpad/util/linux/ptrace_client.cc
@@ -23,6 +23,7 @@ #include "base/strings/string_number_conversions.h" #include "util/file/file_io.h" #include "util/linux/ptrace_broker.h" +#include "util/misc/arraysize.h" #include "util/process/process_memory_linux.h" namespace crashpad { @@ -270,7 +271,7 @@ threads->push_back(pid_); char path[32]; - snprintf(path, arraysize(path), "/proc/%d/task", pid_); + snprintf(path, ArraySize(path), "/proc/%d/task", pid_); PtraceBroker::Request request; request.type = PtraceBroker::Request::kTypeListDirectory;
diff --git a/third_party/crashpad/crashpad/util/mac/checked_mach_address_range_test.cc b/third_party/crashpad/crashpad/util/mac/checked_mach_address_range_test.cc index 089f6815..f2f8f54 100644 --- a/third_party/crashpad/crashpad/util/mac/checked_mach_address_range_test.cc +++ b/third_party/crashpad/crashpad/util/mac/checked_mach_address_range_test.cc
@@ -19,10 +19,10 @@ #include <limits> -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -116,7 +116,7 @@ {0xffffffffffffffff, 1, kInvalid}, }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& testcase = kTestData[index]; SCOPED_TRACE(base::StringPrintf("index %zu, base 0x%llx, size 0x%llx", index, @@ -166,7 +166,7 @@ CheckedMachAddressRange parent_range_32(false, 0x2000, 0x1000); ASSERT_TRUE(parent_range_32.IsValid()); - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& testcase = kTestData[index]; SCOPED_TRACE( base::StringPrintf("index %zu, value 0x%llx", index, testcase.value)); @@ -223,7 +223,7 @@ CheckedMachAddressRange parent_range_32(false, 0x2000, 0x1000); ASSERT_TRUE(parent_range_32.IsValid()); - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& testcase = kTestData[index]; SCOPED_TRACE(base::StringPrintf("index %zu, base 0x%llx, size 0x%llx", index,
diff --git a/third_party/crashpad/crashpad/util/mac/launchd_test.mm b/third_party/crashpad/crashpad/util/mac/launchd_test.mm index 12ed832..4a6402d 100644 --- a/third_party/crashpad/crashpad/util/mac/launchd_test.mm +++ b/third_party/crashpad/crashpad/util/mac/launchd_test.mm
@@ -23,8 +23,8 @@ #include <limits> #include "base/mac/scoped_launch_data.h" -#include "base/macros.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" #include "util/stdlib/objc.h" namespace crashpad { @@ -58,7 +58,7 @@ @0xfedcba9876543210, }; - for (size_t index = 0; index < arraysize(integer_nses); ++index) { + for (size_t index = 0; index < ArraySize(integer_nses); ++index) { NSNumber* integer_ns = integer_nses[index]; launch_data.reset(CFPropertyToLaunchData(integer_ns)); ASSERT_TRUE(launch_data.get()); @@ -88,7 +88,7 @@ [NSNumber numberWithDouble:std::numeric_limits<double>::signaling_NaN()], }; - for (size_t index = 0; index < arraysize(double_nses); ++index) { + for (size_t index = 0; index < ArraySize(double_nses); ++index) { NSNumber* double_ns = double_nses[index]; launch_data.reset(CFPropertyToLaunchData(double_ns)); ASSERT_TRUE(launch_data.get()); @@ -114,7 +114,7 @@ @YES, }; - for (size_t index = 0; index < arraysize(bool_nses); ++index) { + for (size_t index = 0; index < ArraySize(bool_nses); ++index) { NSNumber* bool_ns = bool_nses[index]; launch_data.reset(CFPropertyToLaunchData(bool_ns)); ASSERT_TRUE(launch_data.get()); @@ -138,7 +138,7 @@ @"Üñîçø∂é", }; - for (size_t index = 0; index < arraysize(string_nses); ++index) { + for (size_t index = 0; index < ArraySize(string_nses); ++index) { NSString* string_ns = string_nses[index]; launch_data.reset(CFPropertyToLaunchData(string_ns)); ASSERT_TRUE(launch_data.get());
diff --git a/third_party/crashpad/crashpad/util/mac/xattr.cc b/third_party/crashpad/crashpad/util/mac/xattr.cc index 75d7938..c63fc87 100644 --- a/third_party/crashpad/crashpad/util/mac/xattr.cc +++ b/third_party/crashpad/crashpad/util/mac/xattr.cc
@@ -20,7 +20,6 @@ #include <sys/xattr.h> #include "base/logging.h" -#include "base/macros.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h"
diff --git a/third_party/crashpad/crashpad/util/mach/child_port_handshake.cc b/third_party/crashpad/crashpad/util/mach/child_port_handshake.cc index 750d3cbe..721e560e 100644 --- a/third_party/crashpad/crashpad/util/mach/child_port_handshake.cc +++ b/third_party/crashpad/crashpad/util/mach/child_port_handshake.cc
@@ -38,6 +38,7 @@ #include "util/mach/mach_extensions.h" #include "util/mach/mach_message.h" #include "util/mach/mach_message_server.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" #include "util/misc/random_string.h" @@ -158,7 +159,7 @@ 0, nullptr); int rv = HANDLE_EINTR( - kevent(kq.get(), changelist, arraysize(changelist), nullptr, 0, nullptr)); + kevent(kq.get(), changelist, ArraySize(changelist), nullptr, 0, nullptr)); PCHECK(rv != -1) << "kevent"; ChildPortServer child_port_server(this);
diff --git a/third_party/crashpad/crashpad/util/mach/child_port_server.cc b/third_party/crashpad/crashpad/util/mach/child_port_server.cc index a322302..678d3b2 100644 --- a/third_party/crashpad/crashpad/util/mach/child_port_server.cc +++ b/third_party/crashpad/crashpad/util/mach/child_port_server.cc
@@ -17,6 +17,7 @@ #include "base/logging.h" #include "util/mach/child_portServer.h" #include "util/mach/mach_message.h" +#include "util/misc/arraysize.h" namespace { @@ -90,7 +91,7 @@ static constexpr mach_msg_id_t request_ids[] = {kMachMessageIDChildPortCheckIn}; return std::set<mach_msg_id_t>(&request_ids[0], - &request_ids[arraysize(request_ids)]); + &request_ids[ArraySize(request_ids)]); } mach_msg_size_t ChildPortServer::MachMessageServerRequestSize() {
diff --git a/third_party/crashpad/crashpad/util/mach/composite_mach_message_server_test.cc b/third_party/crashpad/crashpad/util/mach/composite_mach_message_server_test.cc index d45eca0..c2ed5d7 100644 --- a/third_party/crashpad/crashpad/util/mach/composite_mach_message_server_test.cc +++ b/third_party/crashpad/crashpad/util/mach/composite_mach_message_server_test.cc
@@ -20,6 +20,7 @@ #include "gtest/gtest.h" #include "test/gtest_death.h" #include "util/mach/mach_message.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -196,7 +197,7 @@ TestMachMessageHandler handlers[3]; std::set<mach_msg_id_t> expect_request_ids; - for (size_t index = 0; index < arraysize(kRequestIDs0); ++index) { + for (size_t index = 0; index < ArraySize(kRequestIDs0); ++index) { const mach_msg_id_t request_id = kRequestIDs0[index]; handlers[0].AddRequestID(request_id); expect_request_ids.insert(request_id); @@ -205,7 +206,7 @@ handlers[0].SetReplySize(sizeof(mig_reply_error_t)); handlers[0].SetReturnCodes(true, kReturnCode0, false); - for (size_t index = 0; index < arraysize(kRequestIDs1); ++index) { + for (size_t index = 0; index < ArraySize(kRequestIDs1); ++index) { const mach_msg_id_t request_id = kRequestIDs1[index]; handlers[1].AddRequestID(request_id); expect_request_ids.insert(request_id); @@ -214,7 +215,7 @@ handlers[1].SetReplySize(200); handlers[1].SetReturnCodes(false, kReturnCode1, true); - for (size_t index = 0; index < arraysize(kRequestIDs2); ++index) { + for (size_t index = 0; index < ArraySize(kRequestIDs2); ++index) { const mach_msg_id_t request_id = kRequestIDs2[index]; handlers[2].AddRequestID(request_id); expect_request_ids.insert(request_id); @@ -252,7 +253,7 @@ // Send messages with known request IDs. - for (size_t index = 0; index < arraysize(kRequestIDs0); ++index) { + for (size_t index = 0; index < ArraySize(kRequestIDs0); ++index) { request.header.msgh_id = kRequestIDs0[index]; SCOPED_TRACE(base::StringPrintf( "handler 0, index %zu, id %d", index, request.header.msgh_id)); @@ -263,7 +264,7 @@ EXPECT_FALSE(destroy_complex_request); } - for (size_t index = 0; index < arraysize(kRequestIDs1); ++index) { + for (size_t index = 0; index < ArraySize(kRequestIDs1); ++index) { request.header.msgh_id = kRequestIDs1[index]; SCOPED_TRACE(base::StringPrintf( "handler 1, index %zu, id %d", index, request.header.msgh_id)); @@ -274,7 +275,7 @@ EXPECT_TRUE(destroy_complex_request); } - for (size_t index = 0; index < arraysize(kRequestIDs2); ++index) { + for (size_t index = 0; index < ArraySize(kRequestIDs2); ++index) { request.header.msgh_id = kRequestIDs2[index]; SCOPED_TRACE(base::StringPrintf( "handler 2, index %zu, id %d", index, request.header.msgh_id));
diff --git a/third_party/crashpad/crashpad/util/mach/exc_client_variants_test.cc b/third_party/crashpad/crashpad/util/mach/exc_client_variants_test.cc index b7288563..7d1d00d 100644 --- a/third_party/crashpad/crashpad/util/mach/exc_client_variants_test.cc +++ b/third_party/crashpad/crashpad/util/mach/exc_client_variants_test.cc
@@ -29,6 +29,7 @@ #include "util/mach/mach_extensions.h" #include "util/mach/mach_message.h" #include "util/mach/mach_message_server.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" namespace crashpad { @@ -181,11 +182,11 @@ // These aren’t real flavors, it’s just for testing. flavor = exception_ + 10; flavor_p = &flavor; - for (size_t index = 0; index < arraysize(old_state); ++index) { + for (size_t index = 0; index < ArraySize(old_state); ++index) { old_state[index] = index; } old_state_p = reinterpret_cast<thread_state_t>(&old_state); - old_state_count = arraysize(old_state); + old_state_count = ArraySize(old_state); // new_state and new_state_count are out parameters that the server should // never see or use, so set them to bogus values. The call to the server @@ -202,7 +203,7 @@ task, exception, code, - arraysize(code), + ArraySize(code), flavor_p, old_state_p, old_state_count, @@ -273,7 +274,7 @@ kMachExceptionCodes | EXCEPTION_STATE_IDENTITY, }; - for (size_t index = 0; index < arraysize(kBehaviors); ++index) { + for (size_t index = 0; index < ArraySize(kBehaviors); ++index) { exception_behavior_t behavior = kBehaviors[index]; SCOPED_TRACE(base::StringPrintf("index %zu, behavior %d", index, behavior));
diff --git a/third_party/crashpad/crashpad/util/mach/exc_server_variants.cc b/third_party/crashpad/crashpad/util/mach/exc_server_variants.cc index e7174ac..f7b0b3d6 100644 --- a/third_party/crashpad/crashpad/util/mach/exc_server_variants.cc +++ b/third_party/crashpad/crashpad/util/mach/exc_server_variants.cc
@@ -29,6 +29,7 @@ #include "util/mach/mach_exc.h" #include "util/mach/mach_excServer.h" #include "util/mach/mach_message.h" +#include "util/misc/arraysize.h" namespace crashpad { @@ -242,7 +243,7 @@ Traits::kMachMessageIDExceptionRaiseStateIdentity, }; return std::set<mach_msg_id_t>(&request_ids[0], - &request_ids[arraysize(request_ids)]); + &request_ids[ArraySize(request_ids)]); } mach_msg_size_t MachMessageServerRequestSize() override { @@ -319,7 +320,7 @@ using Reply = typename Traits::ExceptionRaiseStateReply; Reply* out_reply = reinterpret_cast<Reply*>(out_header); out_reply->flavor = in_request_1->flavor; - out_reply->new_stateCnt = arraysize(out_reply->new_state); + out_reply->new_stateCnt = ArraySize(out_reply->new_state); out_reply->RetCode = interface_->CatchExceptionRaiseState(in_header->msgh_local_port, in_request->exception, @@ -362,7 +363,7 @@ using Reply = typename Traits::ExceptionRaiseStateIdentityReply; Reply* out_reply = reinterpret_cast<Reply*>(out_header); out_reply->flavor = in_request_1->flavor; - out_reply->new_stateCnt = arraysize(out_reply->new_state); + out_reply->new_stateCnt = ArraySize(out_reply->new_state); out_reply->RetCode = interface_->CatchExceptionRaiseStateIdentity( in_header->msgh_local_port, in_request->thread.name,
diff --git a/third_party/crashpad/crashpad/util/mach/exc_server_variants_test.cc b/third_party/crashpad/crashpad/util/mach/exc_server_variants_test.cc index 5e67bfe..b50ded1 100644 --- a/third_party/crashpad/crashpad/util/mach/exc_server_variants_test.cc +++ b/third_party/crashpad/crashpad/util/mach/exc_server_variants_test.cc
@@ -29,6 +29,7 @@ #include "util/mach/exception_behaviors.h" #include "util/mach/exception_types.h" #include "util/mach/mach_message.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" namespace crashpad { @@ -228,7 +229,7 @@ EXPECT_EQ(memcmp(&NDR, &NDR_record, sizeof(NDR)), 0); EXPECT_EQ(RetCode, KERN_SUCCESS); EXPECT_EQ(flavor, kThreadStateFlavor); - EXPECT_EQ(new_stateCnt, arraysize(new_state)); + EXPECT_EQ(new_stateCnt, ArraySize(new_state)); } mach_msg_header_t Head; @@ -659,7 +660,7 @@ AreExceptionCodes(kTestExceptonCodes[0], kTestExceptonCodes[1]), Pointee(Eq(kThreadStateFlavor)), IsThreadStateAndCount(kThreadStateFlavorCount), - IsThreadStateAndCount(arraysize(reply.new_state)), + IsThreadStateAndCount(ArraySize(reply.new_state)), Eq(request.Trailer()))) .WillOnce(Return(KERN_SUCCESS)) .RetiresOnSaturation(); @@ -708,7 +709,7 @@ AreExceptionCodes(kTestExceptonCodes[0], kTestExceptonCodes[1]), Pointee(Eq(kThreadStateFlavor)), IsThreadStateAndCount(kThreadStateFlavorCount), - IsThreadStateAndCount(arraysize(reply.new_state)), + IsThreadStateAndCount(ArraySize(reply.new_state)), Eq(request.Trailer()))) .WillOnce(Return(KERN_SUCCESS)) .RetiresOnSaturation(); @@ -802,7 +803,7 @@ kTestMachExceptionCodes[1]), Pointee(Eq(kThreadStateFlavor)), IsThreadStateAndCount(kThreadStateFlavorCount), - IsThreadStateAndCount(arraysize(reply.new_state)), + IsThreadStateAndCount(ArraySize(reply.new_state)), Eq(request.Trailer()))) .WillOnce(Return(KERN_SUCCESS)) .RetiresOnSaturation(); @@ -852,7 +853,7 @@ kTestMachExceptionCodes[1]), Pointee(Eq(kThreadStateFlavor)), IsThreadStateAndCount(kThreadStateFlavorCount), - IsThreadStateAndCount(arraysize(reply.new_state)), + IsThreadStateAndCount(ArraySize(reply.new_state)), Eq(request.Trailer()))) .WillOnce(Return(KERN_SUCCESS)) .RetiresOnSaturation(); @@ -906,7 +907,7 @@ 2508, }; - for (size_t index = 0; index < arraysize(unknown_ids); ++index) { + for (size_t index = 0; index < ArraySize(unknown_ids); ++index) { mach_msg_id_t id = unknown_ids[index]; SCOPED_TRACE(base::StringPrintf("unknown id %d", id)); @@ -1179,7 +1180,7 @@ #endif }; - for (size_t index = 0; index < arraysize(test_data); ++index) { + for (size_t index = 0; index < ArraySize(test_data); ++index) { const auto& test = test_data[index]; SCOPED_TRACE( base::StringPrintf("index %zu, flavor %d", index, test.flavor)); @@ -1252,7 +1253,7 @@ KERN_SUCCESS}, }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& test_data = kTestData[index]; SCOPED_TRACE( base::StringPrintf("index %zu, behavior %d, set_thread_state %s", @@ -1271,8 +1272,8 @@ static constexpr natural_t old_state[] = {1, 2, 3, 4, 5}; natural_t new_state[10] = {}; - constexpr mach_msg_type_number_t old_state_count = arraysize(old_state); - mach_msg_type_number_t new_state_count = arraysize(new_state); + constexpr mach_msg_type_number_t old_state_count = ArraySize(old_state); + mach_msg_type_number_t new_state_count = ArraySize(new_state); // EXCEPTION_DEFAULT (with or without MACH_EXCEPTION_CODES) is not // state-carrying. new_state and new_state_count should be untouched. @@ -1281,8 +1282,8 @@ old_state_count, new_state, &new_state_count); - EXPECT_EQ(new_state_count, arraysize(new_state)); - for (size_t i = 0; i < arraysize(new_state); ++i) { + EXPECT_EQ(new_state_count, ArraySize(new_state)); + for (size_t i = 0; i < ArraySize(new_state); ++i) { EXPECT_EQ(new_state[i], 0u) << "i " << i; } @@ -1291,8 +1292,8 @@ old_state_count, new_state, &new_state_count); - EXPECT_EQ(new_state_count, arraysize(new_state)); - for (size_t i = 0; i < arraysize(new_state); ++i) { + EXPECT_EQ(new_state_count, ArraySize(new_state)); + for (size_t i = 0; i < ArraySize(new_state); ++i) { EXPECT_EQ(new_state[i], 0u) << "i " << i; } @@ -1304,7 +1305,7 @@ for (size_t i = 0; i < copy_limit; ++i) { EXPECT_EQ(new_state[i], old_state[i]) << "i " << i; } - for (size_t i = copy_limit; i < arraysize(new_state); ++i) { + for (size_t i = copy_limit; i < ArraySize(new_state); ++i) { EXPECT_EQ(new_state[i], 0u) << "i " << i; } @@ -1320,23 +1321,23 @@ for (size_t i = 0; i < copy_limit; ++i) { EXPECT_EQ(new_state[i], old_state[i]) << "i " << i; } - for (size_t i = copy_limit; i < arraysize(new_state); ++i) { + for (size_t i = copy_limit; i < ArraySize(new_state); ++i) { EXPECT_EQ(new_state[i], 0u) << "i " << i; } // This is a state-carrying exception where all of old_state is copied to // new_state, which is large enough to receive it and then some. - new_state_count = arraysize(new_state); + new_state_count = ArraySize(new_state); ExcServerCopyState(MACH_EXCEPTION_CODES | EXCEPTION_STATE_IDENTITY, old_state, old_state_count, new_state, &new_state_count); EXPECT_EQ(new_state_count, old_state_count); - for (size_t i = 0; i < arraysize(old_state); ++i) { + for (size_t i = 0; i < ArraySize(old_state); ++i) { EXPECT_EQ(new_state[i], old_state[i]) << "i " << i; } - for (size_t i = arraysize(old_state); i < arraysize(new_state); ++i) { + for (size_t i = ArraySize(old_state); i < ArraySize(new_state); ++i) { EXPECT_EQ(new_state[i], 0u) << "i " << i; } }
diff --git a/third_party/crashpad/crashpad/util/mach/exception_behaviors_test.cc b/third_party/crashpad/crashpad/util/mach/exception_behaviors_test.cc index d45110d9..fd74d22 100644 --- a/third_party/crashpad/crashpad/util/mach/exception_behaviors_test.cc +++ b/third_party/crashpad/crashpad/util/mach/exception_behaviors_test.cc
@@ -16,10 +16,10 @@ #include <sys/types.h> -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "gtest/gtest.h" #include "util/mach/mach_extensions.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -53,7 +53,7 @@ EXCEPTION_STATE_IDENTITY}, }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& test_data = kTestData[index]; SCOPED_TRACE(base::StringPrintf( "index %zu, behavior %d", index, test_data.behavior));
diff --git a/third_party/crashpad/crashpad/util/mach/exception_types_test.cc b/third_party/crashpad/crashpad/util/mach/exception_types_test.cc index c24428a2..030c7f3 100644 --- a/third_party/crashpad/crashpad/util/mach/exception_types_test.cc +++ b/third_party/crashpad/crashpad/util/mach/exception_types_test.cc
@@ -20,11 +20,11 @@ #include <sys/types.h> #include <unistd.h> -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "gtest/gtest.h" #include "util/mac/mac_util.h" #include "util/mach/mach_extensions.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -67,7 +67,7 @@ {0, 0, 0, 0}, }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& test_data = kTestData[index]; SCOPED_TRACE(base::StringPrintf( "index %zu, code_0 0x%llx", index, test_data.code_0)); @@ -84,7 +84,7 @@ // Now make sure that ExcCrashRecoverOriginalException() properly ignores // optional arguments. - static_assert(arraysize(kTestData) >= 1, "must have something to test"); + static_assert(ArraySize(kTestData) >= 1, "must have something to test"); const auto& test_data = kTestData[0]; EXPECT_EQ( ExcCrashRecoverOriginalException(test_data.code_0, nullptr, nullptr), @@ -238,7 +238,7 @@ {0x00010000, 0x00010000, static_cast<int32_t>(0xffffffff)}, }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& test_data = kTestData[index]; SCOPED_TRACE(base::StringPrintf("index %zu, exception 0x%x, code_0 0x%llx", index,
diff --git a/third_party/crashpad/crashpad/util/mach/mach_message_server_test.cc b/third_party/crashpad/crashpad/util/mach/mach_message_server_test.cc index 16ba8f20..724d84e 100644 --- a/third_party/crashpad/crashpad/util/mach/mach_message_server_test.cc +++ b/third_party/crashpad/crashpad/util/mach/mach_message_server_test.cc
@@ -29,6 +29,7 @@ #include "util/file/file_io.h" #include "util/mach/mach_extensions.h" #include "util/mach/mach_message.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" namespace crashpad { @@ -281,7 +282,7 @@ std::set<mach_msg_id_t> MachMessageServerRequestIDs() override { static constexpr mach_msg_id_t request_ids[] = {kRequestMessageID}; return std::set<mach_msg_id_t>(&request_ids[0], - &request_ids[arraysize(request_ids)]); + &request_ids[ArraySize(request_ids)]); } mach_msg_size_t MachMessageServerRequestSize() override {
diff --git a/third_party/crashpad/crashpad/util/mach/mach_message_test.cc b/third_party/crashpad/crashpad/util/mach/mach_message_test.cc index d88ca85..b00b187 100644 --- a/third_party/crashpad/crashpad/util/mach/mach_message_test.cc +++ b/third_party/crashpad/crashpad/util/mach/mach_message_test.cc
@@ -17,6 +17,7 @@ #include <unistd.h> #include "base/mac/scoped_mach_port.h" +#include "base/macros.h" #include "gtest/gtest.h" #include "test/mac/mach_errors.h" #include "util/mach/mach_extensions.h"
diff --git a/third_party/crashpad/crashpad/util/mach/notify_server.cc b/third_party/crashpad/crashpad/util/mach/notify_server.cc index 711529b..5d0b3c0c 100644 --- a/third_party/crashpad/crashpad/util/mach/notify_server.cc +++ b/third_party/crashpad/crashpad/util/mach/notify_server.cc
@@ -17,6 +17,7 @@ #include "base/logging.h" #include "util/mach/mach_message.h" #include "util/mach/notifyServer.h" +#include "util/misc/arraysize.h" namespace { @@ -227,7 +228,7 @@ MACH_NOTIFY_DEAD_NAME, }; return std::set<mach_msg_id_t>(&request_ids[0], - &request_ids[arraysize(request_ids)]); + &request_ids[ArraySize(request_ids)]); } mach_msg_size_t NotifyServer::MachMessageServerRequestSize() {
diff --git a/third_party/crashpad/crashpad/util/mach/symbolic_constants_mach.cc b/third_party/crashpad/crashpad/util/mach/symbolic_constants_mach.cc index 98a2d203..fa6eefb 100644 --- a/third_party/crashpad/crashpad/util/mach/symbolic_constants_mach.cc +++ b/third_party/crashpad/crashpad/util/mach/symbolic_constants_mach.cc
@@ -17,10 +17,10 @@ #include <string.h> #include <sys/types.h> -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "util/mach/exception_behaviors.h" #include "util/mach/mach_extensions.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" #include "util/stdlib/string_number_conversion.h" @@ -45,7 +45,7 @@ "GUARD", "CORPSE_NOTIFY", }; -static_assert(arraysize(kExceptionNames) == EXC_TYPES_COUNT, +static_assert(ArraySize(kExceptionNames) == EXC_TYPES_COUNT, "kExceptionNames length"); constexpr char kExcPrefix[] = "EXC_"; @@ -170,8 +170,7 @@ {"_STATE32", "32"}, {"_STATE64", "64"}, }; - for (size_t suffix_index = 0; - suffix_index < arraysize(kStateSuffixes); + for (size_t suffix_index = 0; suffix_index < ArraySize(kStateSuffixes); ++suffix_index) { const char* suffix = kStateSuffixes[suffix_index].orig; size_t suffix_len = strlen(suffix); @@ -195,7 +194,7 @@ std::string ExceptionToString(exception_type_t exception, SymbolicConstantToStringOptions options) { const char* exception_name = - implicit_cast<size_t>(exception) < arraysize(kExceptionNames) + implicit_cast<size_t>(exception) < ArraySize(kExceptionNames) ? kExceptionNames[exception] : nullptr; if (!exception_name) { @@ -221,7 +220,7 @@ base::StringPiece short_string = can_match_full ? string.substr(strlen(kExcPrefix)) : string; for (exception_type_t index = 0; - index < implicit_cast<exception_type_t>(arraysize(kExceptionNames)); + index < implicit_cast<exception_type_t>(ArraySize(kExceptionNames)); ++index) { const char* exception_name = kExceptionNames[index]; if (!exception_name) { @@ -251,8 +250,7 @@ exception_mask_t local_exception_mask = exception_mask; std::string mask_string; bool has_forbidden_or = false; - for (size_t exception = 0; - exception < arraysize(kExceptionNames); + for (size_t exception = 0; exception < ArraySize(kExceptionNames); ++exception) { const char* exception_name = kExceptionNames[exception]; exception_mask_t exception_mask_value = 1 << exception; @@ -326,7 +324,7 @@ base::StringPiece short_string = can_match_full ? string.substr(strlen(kExcMaskPrefix)) : string; for (exception_type_t index = 0; - index < implicit_cast<exception_type_t>(arraysize(kExceptionNames)); + index < implicit_cast<exception_type_t>(ArraySize(kExceptionNames)); ++index) { const char* exception_name = kExceptionNames[index]; if (!exception_name) { @@ -365,7 +363,7 @@ const exception_behavior_t basic_behavior = ExceptionBehaviorBasic(behavior); const char* behavior_name = - implicit_cast<size_t>(basic_behavior) < arraysize(kBehaviorNames) + implicit_cast<size_t>(basic_behavior) < ArraySize(kBehaviorNames) ? kBehaviorNames[basic_behavior] : nullptr; if (!behavior_name) { @@ -432,7 +430,7 @@ base::StringPiece short_string = can_match_full ? sp.substr(strlen(kBehaviorPrefix)) : sp; for (exception_behavior_t index = 0; - index < implicit_cast<exception_behavior_t>(arraysize(kBehaviorNames)); + index < implicit_cast<exception_behavior_t>(ArraySize(kBehaviorNames)); ++index) { const char* behavior_name = kBehaviorNames[index]; if (!behavior_name) { @@ -468,13 +466,13 @@ std::string ThreadStateFlavorToString(thread_state_flavor_t flavor, SymbolicConstantToStringOptions options) { const char* flavor_name = - implicit_cast<size_t>(flavor) < arraysize(kFlavorNames) + implicit_cast<size_t>(flavor) < ArraySize(kFlavorNames) ? kFlavorNames[flavor] : nullptr; if (!flavor_name) { for (size_t generic_flavor_index = 0; - generic_flavor_index < arraysize(kGenericFlavorNames); + generic_flavor_index < ArraySize(kGenericFlavorNames); ++generic_flavor_index) { if (flavor == kGenericFlavorNames[generic_flavor_index].flavor) { flavor_name = kGenericFlavorNames[generic_flavor_index].name; @@ -501,7 +499,7 @@ thread_state_flavor_t* flavor) { if ((options & kAllowFullName) || (options & kAllowShortName)) { for (thread_state_flavor_t index = 0; - index < implicit_cast<thread_state_flavor_t>(arraysize(kFlavorNames)); + index < implicit_cast<thread_state_flavor_t>(ArraySize(kFlavorNames)); ++index) { const char* flavor_name = kFlavorNames[index]; if (!flavor_name) { @@ -521,7 +519,7 @@ } for (size_t generic_flavor_index = 0; - generic_flavor_index < arraysize(kGenericFlavorNames); + generic_flavor_index < ArraySize(kGenericFlavorNames); ++generic_flavor_index) { const char* flavor_name = kGenericFlavorNames[generic_flavor_index].name; thread_state_flavor_t flavor_number =
diff --git a/third_party/crashpad/crashpad/util/mach/symbolic_constants_mach_test.cc b/third_party/crashpad/crashpad/util/mach/symbolic_constants_mach_test.cc index 3bf5abb..4856f0ad 100644 --- a/third_party/crashpad/crashpad/util/mach/symbolic_constants_mach_test.cc +++ b/third_party/crashpad/crashpad/util/mach/symbolic_constants_mach_test.cc
@@ -18,14 +18,15 @@ #include <string.h> #include <sys/types.h> -#include "base/macros.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "gtest/gtest.h" #include "util/mach/mach_extensions.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" -#define NUL_TEST_DATA(string) { string, arraysize(string) - 1 } +#define NUL_TEST_DATA(string) \ + { string, ArraySize(string) - 1 } namespace crashpad { namespace test { @@ -159,7 +160,7 @@ } TEST(SymbolicConstantsMach, ExceptionToString) { - for (size_t index = 0; index < arraysize(kExceptionTestData); ++index) { + for (size_t index = 0; index < ArraySize(kExceptionTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); TestExceptionToString(kExceptionTestData[index].exception, kExceptionTestData[index].full_name, @@ -187,12 +188,11 @@ } TEST(SymbolicConstantsMach, StringToException) { - for (size_t option_index = 0; - option_index < arraysize(kNormalOptions); + for (size_t option_index = 0; option_index < ArraySize(kNormalOptions); ++option_index) { SCOPED_TRACE(base::StringPrintf("option_index %zu", option_index)); StringToSymbolicConstantOptions options = kNormalOptions[option_index]; - for (size_t index = 0; index < arraysize(kExceptionTestData); ++index) { + for (size_t index = 0; index < ArraySize(kExceptionTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); exception_type_t exception = kExceptionTestData[index].exception; { @@ -230,7 +230,7 @@ "", }; - for (size_t index = 0; index < arraysize(kNegativeTestData); ++index) { + for (size_t index = 0; index < ArraySize(kNegativeTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); TestStringToException(kNegativeTestData[index], options, false, 0); } @@ -251,7 +251,7 @@ NUL_TEST_DATA("1\0002"), }; - for (size_t index = 0; index < arraysize(kNULTestData); ++index) { + for (size_t index = 0; index < ArraySize(kNULTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); base::StringPiece string(kNULTestData[index].string, kNULTestData[index].length); @@ -334,7 +334,7 @@ } TEST(SymbolicConstantsMach, ExceptionMaskToString) { - for (size_t index = 0; index < arraysize(kExceptionMaskTestData); ++index) { + for (size_t index = 0; index < ArraySize(kExceptionMaskTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); TestExceptionMaskToString(kExceptionMaskTestData[index].exception_mask, kExceptionMaskTestData[index].full_name, @@ -389,12 +389,11 @@ kAllowFullName | kAllowShortName | kAllowNumber | kAllowOr, }; - for (size_t option_index = 0; - option_index < arraysize(kOptions); + for (size_t option_index = 0; option_index < ArraySize(kOptions); ++option_index) { SCOPED_TRACE(base::StringPrintf("option_index %zu", option_index)); StringToSymbolicConstantOptions options = kOptions[option_index]; - for (size_t index = 0; index < arraysize(kExceptionMaskTestData); ++index) { + for (size_t index = 0; index < ArraySize(kExceptionMaskTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); exception_mask_t exception_mask = kExceptionMaskTestData[index].exception_mask; @@ -445,7 +444,7 @@ "", }; - for (size_t index = 0; index < arraysize(kNegativeTestData); ++index) { + for (size_t index = 0; index < ArraySize(kNegativeTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); TestStringToExceptionMask(kNegativeTestData[index], options, false, 0); } @@ -471,7 +470,7 @@ NUL_TEST_DATA("ARITHMETIC|\0EMULATION"), }; - for (size_t index = 0; index < arraysize(kNULTestData); ++index) { + for (size_t index = 0; index < ArraySize(kNULTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); base::StringPiece string(kNULTestData[index].string, kNULTestData[index].length); @@ -506,7 +505,7 @@ EXC_MASK_SYSCALL | 0x100}, }; - for (size_t index = 0; index < arraysize(kNonCanonicalTestData); ++index) { + for (size_t index = 0; index < ArraySize(kNonCanonicalTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); TestStringToExceptionMask(kNonCanonicalTestData[index].string, kNonCanonicalTestData[index].options, @@ -577,8 +576,7 @@ } TEST(SymbolicConstantsMach, ExceptionBehaviorToString) { - for (size_t index = 0; - index < arraysize(kExceptionBehaviorTestData); + for (size_t index = 0; index < ArraySize(kExceptionBehaviorTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); TestExceptionBehaviorToString(kExceptionBehaviorTestData[index].behavior, @@ -608,13 +606,11 @@ } TEST(SymbolicConstantsMach, StringToExceptionBehavior) { - for (size_t option_index = 0; - option_index < arraysize(kNormalOptions); + for (size_t option_index = 0; option_index < ArraySize(kNormalOptions); ++option_index) { SCOPED_TRACE(base::StringPrintf("option_index %zu", option_index)); StringToSymbolicConstantOptions options = kNormalOptions[option_index]; - for (size_t index = 0; - index < arraysize(kExceptionBehaviorTestData); + for (size_t index = 0; index < ArraySize(kExceptionBehaviorTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); exception_behavior_t behavior = @@ -660,7 +656,7 @@ "", }; - for (size_t index = 0; index < arraysize(kNegativeTestData); ++index) { + for (size_t index = 0; index < ArraySize(kNegativeTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); TestStringToExceptionBehavior( kNegativeTestData[index], options, false, 0); @@ -686,7 +682,7 @@ NUL_TEST_DATA("STATE_IDENTITY|\0MACH"), }; - for (size_t index = 0; index < arraysize(kNULTestData); ++index) { + for (size_t index = 0; index < ArraySize(kNULTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); base::StringPiece string(kNULTestData[index].string, kNULTestData[index].length); @@ -723,7 +719,7 @@ implicit_cast<exception_behavior_t>(MACH_EXCEPTION_CODES | 0x2)}, }; - for (size_t index = 0; index < arraysize(kNonCanonicalTestData); ++index) { + for (size_t index = 0; index < ArraySize(kNonCanonicalTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); TestStringToExceptionBehavior(kNonCanonicalTestData[index].string, kNonCanonicalTestData[index].options, @@ -840,8 +836,7 @@ } TEST(SymbolicConstantsMach, ThreadStateFlavorToString) { - for (size_t index = 0; - index < arraysize(kThreadStateFlavorTestData); + for (size_t index = 0; index < ArraySize(kThreadStateFlavorTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); TestThreadStateFlavorToString(kThreadStateFlavorTestData[index].flavor, @@ -883,13 +878,11 @@ } TEST(SymbolicConstantsMach, StringToThreadStateFlavor) { - for (size_t option_index = 0; - option_index < arraysize(kNormalOptions); + for (size_t option_index = 0; option_index < ArraySize(kNormalOptions); ++option_index) { SCOPED_TRACE(base::StringPrintf("option_index %zu", option_index)); StringToSymbolicConstantOptions options = kNormalOptions[option_index]; - for (size_t index = 0; - index < arraysize(kThreadStateFlavorTestData); + for (size_t index = 0; index < ArraySize(kThreadStateFlavorTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); thread_state_flavor_t flavor = kThreadStateFlavorTestData[index].flavor; @@ -959,7 +952,7 @@ #endif }; - for (size_t index = 0; index < arraysize(kNegativeTestData); ++index) { + for (size_t index = 0; index < ArraySize(kNegativeTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); TestStringToThreadStateFlavor( kNegativeTestData[index], options, false, 0); @@ -1025,7 +1018,7 @@ #endif }; - for (size_t index = 0; index < arraysize(kNULTestData); ++index) { + for (size_t index = 0; index < ArraySize(kNULTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); base::StringPiece string(kNULTestData[index].string, kNULTestData[index].length);
diff --git a/third_party/crashpad/crashpad/util/misc/arraysize.h b/third_party/crashpad/crashpad/util/misc/arraysize.h new file mode 100644 index 0000000..d476edb --- /dev/null +++ b/third_party/crashpad/crashpad/util/misc/arraysize.h
@@ -0,0 +1,39 @@ +// Copyright 2019 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_UTIL_MISC_ARRAYSIZE_H_ +#define CRASHPAD_UTIL_MISC_ARRAYSIZE_H_ + +#include <sys/types.h> // For size_t. + +#include <type_traits> + +//! \file + +namespace crashpad { +namespace internal { + +//! \brief A helper to implement ArraySize. +template <typename ArrayType> +constexpr size_t ArraySizeHelper() noexcept { + return std::extent<typename std::remove_reference<ArrayType>::type>::value; +} + +} // namespace internal +} // namespace crashpad + +//! \brief A way of computing an array’s size. +#define ArraySize(array) crashpad::internal::ArraySizeHelper<decltype(array)>() + +#endif // CRASHPAD_UTIL_MISC_ARRAYSIZE_H_
diff --git a/third_party/crashpad/crashpad/util/misc/arraysize_unsafe_test.cc b/third_party/crashpad/crashpad/util/misc/arraysize_test.cc similarity index 68% rename from third_party/crashpad/crashpad/util/misc/arraysize_unsafe_test.cc rename to third_party/crashpad/crashpad/util/misc/arraysize_test.cc index a6660aee..ad8da09 100644 --- a/third_party/crashpad/crashpad/util/misc/arraysize_unsafe_test.cc +++ b/third_party/crashpad/crashpad/util/misc/arraysize_test.cc
@@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "util/misc/arraysize_unsafe.h" +#include "util/misc/arraysize.h" #include "base/compiler_specific.h" #include "gtest/gtest.h" @@ -21,37 +21,37 @@ namespace test { namespace { -TEST(ArraySizeUnsafe, ArraySizeUnsafe) { +TEST(ArraySize, ArraySize) { char c1[1]; - static_assert(ARRAYSIZE_UNSAFE(c1) == 1, "c1"); + static_assert(ArraySize(c1) == 1, "c1"); ALLOW_UNUSED_LOCAL(c1); char c2[2]; - static_assert(ARRAYSIZE_UNSAFE(c2) == 2, "c2"); + static_assert(ArraySize(c2) == 2, "c2"); ALLOW_UNUSED_LOCAL(c2); char c4[4]; - static_assert(ARRAYSIZE_UNSAFE(c4) == 4, "c4"); + static_assert(ArraySize(c4) == 4, "c4"); ALLOW_UNUSED_LOCAL(c4); int i1[1]; - static_assert(ARRAYSIZE_UNSAFE(i1) == 1, "i1"); + static_assert(ArraySize(i1) == 1, "i1"); ALLOW_UNUSED_LOCAL(i1); int i2[2]; - static_assert(ARRAYSIZE_UNSAFE(i2) == 2, "i2"); + static_assert(ArraySize(i2) == 2, "i2"); ALLOW_UNUSED_LOCAL(i2); int i4[4]; - static_assert(ARRAYSIZE_UNSAFE(i4) == 4, "i4"); + static_assert(ArraySize(i4) == 4, "i4"); ALLOW_UNUSED_LOCAL(i4); long l8[8]; - static_assert(ARRAYSIZE_UNSAFE(l8) == 8, "l8"); + static_assert(ArraySize(l8) == 8, "l8"); ALLOW_UNUSED_LOCAL(l8); int l9[9]; - static_assert(ARRAYSIZE_UNSAFE(l9) == 9, "l9"); + static_assert(ArraySize(l9) == 9, "l9"); ALLOW_UNUSED_LOCAL(l9); struct S { @@ -62,11 +62,11 @@ }; S s1[1]; - static_assert(ARRAYSIZE_UNSAFE(s1) == 1, "s1"); + static_assert(ArraySize(s1) == 1, "s1"); ALLOW_UNUSED_LOCAL(s1); S s10[10]; - static_assert(ARRAYSIZE_UNSAFE(s10) == 10, "s10"); + static_assert(ArraySize(s10) == 10, "s10"); ALLOW_UNUSED_LOCAL(s10); }
diff --git a/third_party/crashpad/crashpad/util/misc/arraysize_unsafe.h b/third_party/crashpad/crashpad/util/misc/arraysize_unsafe.h deleted file mode 100644 index e53c70b..0000000 --- a/third_party/crashpad/crashpad/util/misc/arraysize_unsafe.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2016 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CRASHPAD_UTIL_MISC_ARRAYSIZE_UNSAFE_H_ -#define CRASHPAD_UTIL_MISC_ARRAYSIZE_UNSAFE_H_ - -//! \file - -//! \brief Not the safest way of computing an array’s size… -//! -//! `#%include "base/macros.h"` and use its `arraysize()` instead. This macro -//! should only be used in rare situations where `arraysize()` does not -//! function. -#define ARRAYSIZE_UNSAFE(array) (sizeof(array) / sizeof(array[0])) - -#endif // CRASHPAD_UTIL_MISC_ARRAYSIZE_UNSAFE_H_
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test_util_win.cc b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_win.cc index 092449e..d8abd37 100644 --- a/third_party/crashpad/crashpad/util/misc/capture_context_test_util_win.cc +++ b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_win.cc
@@ -15,8 +15,8 @@ #include "util/misc/capture_context_test_util.h" #include "util/win/context_wrappers.h" -#include "base/macros.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -59,7 +59,7 @@ #if defined(ARCH_CPU_X86) // fxsave doesn’t write these bytes. - for (size_t i = 464; i < arraysize(context.ExtendedRegisters); ++i) { + for (size_t i = 464; i < ArraySize(context.ExtendedRegisters); ++i) { SCOPED_TRACE(i); EXPECT_EQ(context.ExtendedRegisters[i], 0); } @@ -69,7 +69,7 @@ EXPECT_EQ(context.FltSave.MxCsr, context.MxCsr); // fxsave doesn’t write these bytes. - for (size_t i = 0; i < arraysize(context.FltSave.Reserved4); ++i) { + for (size_t i = 0; i < ArraySize(context.FltSave.Reserved4); ++i) { SCOPED_TRACE(i); EXPECT_EQ(context.FltSave.Reserved4[i], 0); } @@ -81,7 +81,7 @@ EXPECT_EQ(context.P4Home, 0u); EXPECT_EQ(context.P5Home, 0u); EXPECT_EQ(context.P6Home, 0u); - for (size_t i = 0; i < arraysize(context.VectorRegister); ++i) { + for (size_t i = 0; i < ArraySize(context.VectorRegister); ++i) { SCOPED_TRACE(i); EXPECT_EQ(context.VectorRegister[i].Low, 0u); EXPECT_EQ(context.VectorRegister[i].High, 0u);
diff --git a/third_party/crashpad/crashpad/util/misc/clock_test.cc b/third_party/crashpad/crashpad/util/misc/clock_test.cc index 95330eb..ca4bf00 100644 --- a/third_party/crashpad/crashpad/util/misc/clock_test.cc +++ b/third_party/crashpad/crashpad/util/misc/clock_test.cc
@@ -20,9 +20,9 @@ #include "base/format_macros.h" #include "base/logging.h" -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -83,7 +83,7 @@ static_cast<uint64_t>(5E7), // 50 milliseconds }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const uint64_t nanoseconds = kTestData[index]; SCOPED_TRACE(base::StringPrintf( "index %zu, nanoseconds %" PRIu64, index, nanoseconds));
diff --git a/third_party/crashpad/crashpad/util/misc/paths_win.cc b/third_party/crashpad/crashpad/util/misc/paths_win.cc index 4c402fe..aa5c786e 100644 --- a/third_party/crashpad/crashpad/util/misc/paths_win.cc +++ b/third_party/crashpad/crashpad/util/misc/paths_win.cc
@@ -17,18 +17,19 @@ #include <windows.h> #include "base/logging.h" +#include "util/misc/arraysize.h" namespace crashpad { // static bool Paths::Executable(base::FilePath* path) { wchar_t executable_path[_MAX_PATH]; - unsigned int len = - GetModuleFileName(nullptr, executable_path, arraysize(executable_path)); + unsigned int len = GetModuleFileName( + nullptr, executable_path, static_cast<DWORD>(ArraySize(executable_path))); if (len == 0) { PLOG(ERROR) << "GetModuleFileName"; return false; - } else if (len >= arraysize(executable_path)) { + } else if (len >= ArraySize(executable_path)) { LOG(ERROR) << "GetModuleFileName"; return false; }
diff --git a/third_party/crashpad/crashpad/util/misc/random_string_test.cc b/third_party/crashpad/crashpad/util/misc/random_string_test.cc index b0866c0..5d9fad6 100644 --- a/third_party/crashpad/crashpad/util/misc/random_string_test.cc +++ b/third_party/crashpad/crashpad/util/misc/random_string_test.cc
@@ -18,8 +18,8 @@ #include <set> -#include "base/macros.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -33,7 +33,7 @@ const std::string allowed_characters("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); size_t character_counts[26] = {}; - ASSERT_EQ(allowed_characters.size(), arraysize(character_counts)); + ASSERT_EQ(allowed_characters.size(), ArraySize(character_counts)); std::set<std::string> strings; @@ -61,7 +61,7 @@ // Make sure every character appears at least once. It is possible, but // extremely unlikely, for a character to not appear at all. for (size_t character_index = 0; - character_index < arraysize(character_counts); + character_index < ArraySize(character_counts); ++character_index) { EXPECT_GT(character_counts[character_index], 0u) << allowed_characters[character_index];
diff --git a/third_party/crashpad/crashpad/util/misc/uuid_test.cc b/third_party/crashpad/crashpad/util/misc/uuid_test.cc index c05c5c1b..b851919 100644 --- a/third_party/crashpad/crashpad/util/misc/uuid_test.cc +++ b/third_party/crashpad/crashpad/util/misc/uuid_test.cc
@@ -20,10 +20,10 @@ #include <string> #include "base/format_macros.h" -#include "base/macros.h" #include "base/scoped_generic.h" #include "base/strings/stringprintf.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -95,12 +95,12 @@ ++uuid.data_3; EXPECT_NE(uuid, uuid_2); --uuid.data_3; - for (size_t index = 0; index < arraysize(uuid.data_4); ++index) { + for (size_t index = 0; index < ArraySize(uuid.data_4); ++index) { ++uuid.data_4[index]; EXPECT_NE(uuid, uuid_2); --uuid.data_4[index]; } - for (size_t index = 0; index < arraysize(uuid.data_5); ++index) { + for (size_t index = 0; index < ArraySize(uuid.data_5); ++index) { ++uuid.data_5[index]; EXPECT_NE(uuid, uuid_2); --uuid.data_5[index]; @@ -190,7 +190,7 @@ uuid_zero.InitializeToZero(); const std::string empty_uuid = uuid_zero.ToString(); - for (size_t index = 0; index < arraysize(kCases); ++index) { + for (size_t index = 0; index < ArraySize(kCases); ++index) { const TestCase& test_case = kCases[index]; SCOPED_TRACE(base::StringPrintf( "index %" PRIuS ": %s", index, test_case.uuid_string)); @@ -226,7 +226,7 @@ }; // clang-format on EXPECT_TRUE(uuid.InitializeFromString( - base::StringPiece16(kChar16UUID, arraysize(kChar16UUID)))); + base::StringPiece16(kChar16UUID, ArraySize(kChar16UUID)))); EXPECT_EQ(uuid.ToString(), "f32e5bdc-2681-4c73-a4e6-333ffd33b333"); #if defined(OS_WIN)
diff --git a/third_party/crashpad/crashpad/util/net/http_transport_socket.cc b/third_party/crashpad/crashpad/util/net/http_transport_socket.cc index 75ed38f..b390238 100644 --- a/third_party/crashpad/crashpad/util/net/http_transport_socket.cc +++ b/third_party/crashpad/crashpad/util/net/http_transport_socket.cc
@@ -27,6 +27,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "util/file/file_io.h" +#include "util/misc/arraysize.h" #include "util/net/http_body.h" #include "util/net/url.h" #include "util/stdlib/string_number_conversion.h" @@ -365,7 +366,7 @@ FileOperationResult data_bytes; do { - constexpr size_t kCRLFSize = arraysize(kCRLFTerminator) - 1; + constexpr size_t kCRLFSize = ArraySize(kCRLFTerminator) - 1; struct __attribute__((packed)) { char size[8]; char crlf[2];
diff --git a/third_party/crashpad/crashpad/util/net/http_transport_win.cc b/third_party/crashpad/crashpad/util/net/http_transport_win.cc index f86e459..06d0b7b 100644 --- a/third_party/crashpad/crashpad/util/net/http_transport_win.cc +++ b/third_party/crashpad/crashpad/util/net/http_transport_win.cc
@@ -31,8 +31,9 @@ #include "build/build_config.h" #include "package.h" #include "util/file/file_io.h" -#include "util/numeric/safe_assignment.h" +#include "util/misc/arraysize.h" #include "util/net/http_body.h" +#include "util/numeric/safe_assignment.h" #include "util/win/module_version.h" namespace crashpad { @@ -95,7 +96,7 @@ error_code, 0, msgbuf, - arraysize(msgbuf), + static_cast<DWORD>(ArraySize(msgbuf)), NULL); if (!len) { return base::StringPrintf("%s: error 0x%lx while retrieving error 0x%lx",
diff --git a/third_party/crashpad/crashpad/util/numeric/checked_address_range_test.cc b/third_party/crashpad/crashpad/util/numeric/checked_address_range_test.cc index e6bd9ecdf..f5dc8ad 100644 --- a/third_party/crashpad/crashpad/util/numeric/checked_address_range_test.cc +++ b/third_party/crashpad/crashpad/util/numeric/checked_address_range_test.cc
@@ -19,10 +19,10 @@ #include <limits> #include "base/format_macros.h" -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -119,7 +119,7 @@ {0xffffffffffffffff, 1, kInvalid}, }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& testcase = kTestData[index]; SCOPED_TRACE(base::StringPrintf("index %" PRIuS ", base 0x%" PRIx64 ", size 0x%" PRIx64, @@ -170,7 +170,7 @@ CheckedAddressRange parent_range_32(false, 0x2000, 0x1000); ASSERT_TRUE(parent_range_32.IsValid()); - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& testcase = kTestData[index]; SCOPED_TRACE(base::StringPrintf( "index %" PRIuS ", value 0x%" PRIx64, index, testcase.value)); @@ -227,7 +227,7 @@ CheckedAddressRange parent_range_32(false, 0x2000, 0x1000); ASSERT_TRUE(parent_range_32.IsValid()); - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& testcase = kTestData[index]; SCOPED_TRACE(base::StringPrintf("index %" PRIuS ", base 0x%" PRIx64 ", size 0x%" PRIx64,
diff --git a/third_party/crashpad/crashpad/util/numeric/checked_range_test.cc b/third_party/crashpad/crashpad/util/numeric/checked_range_test.cc index 04f6bb1f..2977b42e 100644 --- a/third_party/crashpad/crashpad/util/numeric/checked_range_test.cc +++ b/third_party/crashpad/crashpad/util/numeric/checked_range_test.cc
@@ -20,9 +20,9 @@ #include <limits> #include "base/format_macros.h" -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -78,7 +78,7 @@ {0xffffffff, 0xffffffff, false}, }; - for (size_t index = 0; index < arraysize(kUnsignedTestData); ++index) { + for (size_t index = 0; index < ArraySize(kUnsignedTestData); ++index) { const auto& testcase = kUnsignedTestData[index]; SCOPED_TRACE(base::StringPrintf("unsigned index %" PRIuS ", base 0x%x, size 0x%x", @@ -140,7 +140,7 @@ {-1, 0xffffffff, false}, }; - for (size_t index = 0; index < arraysize(kSignedTestData); ++index) { + for (size_t index = 0; index < ArraySize(kSignedTestData); ++index) { const auto& testcase = kSignedTestData[index]; SCOPED_TRACE(base::StringPrintf("signed index %" PRIuS ", base 0x%x, size 0x%x", @@ -186,7 +186,7 @@ CheckedRange<uint32_t> parent_range(0x2000, 0x1000); ASSERT_TRUE(parent_range.IsValid()); - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& testcase = kTestData[index]; SCOPED_TRACE(base::StringPrintf( "index %" PRIuS ", value 0x%x", index, testcase.value)); @@ -234,7 +234,7 @@ CheckedRange<uint32_t> parent_range(0x2000, 0x1000); ASSERT_TRUE(parent_range.IsValid()); - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& testcase = kTestData[index]; SCOPED_TRACE(base::StringPrintf("index %" PRIuS ", base 0x%x, size 0x%x", index, @@ -287,7 +287,7 @@ CheckedRange<uint32_t> first_range(0x2000, 0x1000); ASSERT_TRUE(first_range.IsValid()); - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto& testcase = kTestData[index]; SCOPED_TRACE(base::StringPrintf("index %" PRIuS ", base 0x%x, size 0x%x", index,
diff --git a/third_party/crashpad/crashpad/util/posix/close_multiple.cc b/third_party/crashpad/crashpad/util/posix/close_multiple.cc index 02c8a767..22f89f52 100644 --- a/third_party/crashpad/crashpad/util/posix/close_multiple.cc +++ b/third_party/crashpad/crashpad/util/posix/close_multiple.cc
@@ -28,6 +28,7 @@ #include "base/strings/string_number_conversions.h" #include "build/build_config.h" #include "util/file/directory_reader.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" #if defined(OS_MACOSX) @@ -152,7 +153,7 @@ int maxfilesperproc; size_t maxfilesperproc_size = sizeof(maxfilesperproc); if (sysctl(oid, - arraysize(oid), + ArraySize(oid), &maxfilesperproc, &maxfilesperproc_size, nullptr,
diff --git a/third_party/crashpad/crashpad/util/posix/close_stdio.cc b/third_party/crashpad/crashpad/util/posix/close_stdio.cc index cc9cdac..02bd4a9 100644 --- a/third_party/crashpad/crashpad/util/posix/close_stdio.cc +++ b/third_party/crashpad/crashpad/util/posix/close_stdio.cc
@@ -20,6 +20,7 @@ #include "base/files/scoped_file.h" #include "base/logging.h" +#include "base/macros.h" #include "base/posix/eintr_wrapper.h" namespace crashpad {
diff --git a/third_party/crashpad/crashpad/util/posix/process_info_mac.cc b/third_party/crashpad/crashpad/util/posix/process_info_mac.cc index fe9fb654..8b9a6ec0 100644 --- a/third_party/crashpad/crashpad/util/posix/process_info_mac.cc +++ b/third_party/crashpad/crashpad/util/posix/process_info_mac.cc
@@ -18,6 +18,7 @@ #include "base/logging.h" #include "base/mac/mach_logging.h" +#include "util/misc/arraysize.h" namespace crashpad { @@ -32,7 +33,7 @@ int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; size_t len = sizeof(kern_proc_info_); - if (sysctl(mib, arraysize(mib), &kern_proc_info_, &len, nullptr, 0) != 0) { + if (sysctl(mib, ArraySize(mib), &kern_proc_info_, &len, nullptr, 0) != 0) { PLOG(ERROR) << "sysctl for pid " << pid; return false; } @@ -111,7 +112,7 @@ const short ngroups = kern_proc_info_.kp_eproc.e_ucred.cr_ngroups; DCHECK_GE(ngroups, 0); DCHECK_LE(static_cast<size_t>(ngroups), - arraysize(kern_proc_info_.kp_eproc.e_ucred.cr_groups)); + ArraySize(kern_proc_info_.kp_eproc.e_ucred.cr_groups)); const gid_t* groups = kern_proc_info_.kp_eproc.e_ucred.cr_groups; return std::set<gid_t>(&groups[0], &groups[ngroups]); @@ -168,7 +169,7 @@ do { int mib[] = {CTL_KERN, KERN_PROCARGS2, pid}; int rv = - sysctl(mib, arraysize(mib), nullptr, &args_size_estimate, nullptr, 0); + sysctl(mib, ArraySize(mib), nullptr, &args_size_estimate, nullptr, 0); if (rv != 0) { PLOG(ERROR) << "sysctl (size) for pid " << pid; return false; @@ -176,7 +177,7 @@ args_size = args_size_estimate + 1; args.resize(args_size); - rv = sysctl(mib, arraysize(mib), &args[0], &args_size, nullptr, 0); + rv = sysctl(mib, ArraySize(mib), &args[0], &args_size, nullptr, 0); if (rv != 0) { PLOG(ERROR) << "sysctl (data) for pid " << pid; return false;
diff --git a/third_party/crashpad/crashpad/util/posix/scoped_mmap_test.cc b/third_party/crashpad/crashpad/util/posix/scoped_mmap_test.cc index 7312b84..0a6a1fa1 100644 --- a/third_party/crashpad/crashpad/util/posix/scoped_mmap_test.cc +++ b/third_party/crashpad/crashpad/util/posix/scoped_mmap_test.cc
@@ -23,6 +23,7 @@ #include "base/strings/stringprintf.h" #include "gtest/gtest.h" #include "test/gtest_death.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -150,7 +151,7 @@ EXPECT_EQ(mapping.len(), 3 * kPageSize); TestCookie cookies[3]; - for (size_t index = 0; index < arraysize(cookies); ++index) { + for (size_t index = 0; index < ArraySize(cookies); ++index) { cookies[index].SetUp(reinterpret_cast<uint64_t*>( mapping.addr_as<uintptr_t>() + index * kPageSize)); } @@ -185,7 +186,7 @@ EXPECT_EQ(mapping.len(), kPageSize); TestCookie cookies[3]; - for (size_t index = 0; index < arraysize(cookies); ++index) { + for (size_t index = 0; index < ArraySize(cookies); ++index) { cookies[index].SetUp(reinterpret_cast<uint64_t*>( reinterpret_cast<uintptr_t>(pages) + index * kPageSize)); } @@ -196,7 +197,7 @@ EXPECT_EQ(mapping.addr(), pages); EXPECT_EQ(mapping.len(), 3 * kPageSize); - for (size_t index = 0; index < arraysize(cookies); ++index) { + for (size_t index = 0; index < ArraySize(cookies); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); EXPECT_EQ(cookies[index].Observed(), cookies[index].Expected()); } @@ -217,7 +218,7 @@ EXPECT_EQ(mapping.len(), kPageSize); TestCookie cookies[3]; - for (size_t index = 0; index < arraysize(cookies); ++index) { + for (size_t index = 0; index < ArraySize(cookies); ++index) { cookies[index].SetUp(reinterpret_cast<uint64_t*>( reinterpret_cast<uintptr_t>(pages) + index * kPageSize)); } @@ -248,7 +249,7 @@ EXPECT_EQ(mapping.len(), 2 * kPageSize); TestCookie cookies[3]; - for (size_t index = 0; index < arraysize(cookies); ++index) { + for (size_t index = 0; index < ArraySize(cookies); ++index) { cookies[index].SetUp(reinterpret_cast<uint64_t*>( reinterpret_cast<uintptr_t>(pages) + index * kPageSize)); }
diff --git a/third_party/crashpad/crashpad/util/posix/signals.cc b/third_party/crashpad/crashpad/util/posix/signals.cc index 63764ab..69cdfca3 100644 --- a/third_party/crashpad/crashpad/util/posix/signals.cc +++ b/third_party/crashpad/crashpad/util/posix/signals.cc
@@ -19,6 +19,7 @@ #include <vector> #include "base/logging.h" +#include "util/misc/arraysize.h" namespace crashpad { @@ -118,7 +119,7 @@ struct sigaction* Signals::OldActions::ActionForSignal(int sig) { DCHECK_GT(sig, 0); const size_t slot = sig - 1; - DCHECK_LT(slot, arraysize(actions_)); + DCHECK_LT(slot, ArraySize(actions_)); return &actions_[slot]; } @@ -152,7 +153,7 @@ int flags, OldActions* old_actions) { return InstallHandlers( - std::vector<int>(kCrashSignals, kCrashSignals + arraysize(kCrashSignals)), + std::vector<int>(kCrashSignals, kCrashSignals + ArraySize(kCrashSignals)), handler, flags, old_actions); @@ -164,7 +165,7 @@ OldActions* old_actions) { return InstallHandlers( std::vector<int>(kTerminateSignals, - kTerminateSignals + arraysize(kTerminateSignals)), + kTerminateSignals + ArraySize(kTerminateSignals)), handler, flags, old_actions); @@ -279,12 +280,12 @@ // static bool Signals::IsCrashSignal(int sig) { - return IsSignalInSet(sig, kCrashSignals, arraysize(kCrashSignals)); + return IsSignalInSet(sig, kCrashSignals, ArraySize(kCrashSignals)); } // static bool Signals::IsTerminateSignal(int sig) { - return IsSignalInSet(sig, kTerminateSignals, arraysize(kTerminateSignals)); + return IsSignalInSet(sig, kTerminateSignals, ArraySize(kTerminateSignals)); } } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/posix/signals_test.cc b/third_party/crashpad/crashpad/util/posix/signals_test.cc index 75ff558..b0c8407 100644 --- a/third_party/crashpad/crashpad/util/posix/signals_test.cc +++ b/third_party/crashpad/crashpad/util/posix/signals_test.cc
@@ -32,6 +32,7 @@ #include "test/errors.h" #include "test/multiprocess.h" #include "test/scoped_temp_dir.h" +#include "util/misc/arraysize.h" #include "util/posix/scoped_mmap.h" namespace crashpad { @@ -340,7 +341,7 @@ {SIGHUP, SEGV_MAPERR, false}, {SIGINT, SI_USER, false}, }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { const auto test_data = kTestData[index]; SCOPED_TRACE(base::StringPrintf( "index %zu, sig %d, code %d", index, test_data.sig, test_data.code));
diff --git a/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix.cc b/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix.cc index 8008ffb6..f1fa87f0 100644 --- a/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix.cc +++ b/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix.cc
@@ -18,9 +18,9 @@ #include <string.h> #include <sys/types.h> -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" +#include "util/misc/arraysize.h" #include "util/misc/implicit_cast.h" #include "util/stdlib/string_number_conversion.h" @@ -137,9 +137,9 @@ }; #if defined(OS_LINUX) || defined(OS_ANDROID) // NSIG is 64 to account for real-time signals. -static_assert(arraysize(kSignalNames) == 32, "kSignalNames length"); +static_assert(ArraySize(kSignalNames) == 32, "kSignalNames length"); #else -static_assert(arraysize(kSignalNames) == NSIG, "kSignalNames length"); +static_assert(ArraySize(kSignalNames) == NSIG, "kSignalNames length"); #endif constexpr char kSigPrefix[] = "SIG"; @@ -151,7 +151,7 @@ std::string SignalToString(int signal, SymbolicConstantToStringOptions options) { const char* signal_name = - implicit_cast<size_t>(signal) < arraysize(kSignalNames) + implicit_cast<size_t>(signal) < ArraySize(kSignalNames) ? kSignalNames[signal] : nullptr; if (!signal_name) { @@ -176,8 +176,7 @@ string.substr(0, strlen(kSigPrefix)).compare(kSigPrefix) == 0; base::StringPiece short_string = can_match_full ? string.substr(strlen(kSigPrefix)) : string; - for (int index = 0; - index < implicit_cast<int>(arraysize(kSignalNames)); + for (int index = 0; index < implicit_cast<int>(ArraySize(kSignalNames)); ++index) { const char* signal_name = kSignalNames[index]; if (!signal_name) {
diff --git a/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix_test.cc b/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix_test.cc index 32c1d43..1a6e0b9 100644 --- a/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix_test.cc +++ b/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix_test.cc
@@ -17,13 +17,14 @@ #include <signal.h> #include <sys/types.h> -#include "base/macros.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" -#define NUL_TEST_DATA(string) { string, arraysize(string) - 1 } +#define NUL_TEST_DATA(string) \ + { string, ArraySize(string) - 1 } namespace crashpad { namespace test { @@ -115,7 +116,7 @@ } TEST(SymbolicConstantsPOSIX, SignalToString) { - for (size_t index = 0; index < arraysize(kSignalTestData); ++index) { + for (size_t index = 0; index < ArraySize(kSignalTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); TestSignalToString(kSignalTestData[index].signal, kSignalTestData[index].full_name, @@ -170,12 +171,11 @@ kAllowFullName | kAllowShortName | kAllowNumber, }; - for (size_t option_index = 0; - option_index < arraysize(kOptions); + for (size_t option_index = 0; option_index < ArraySize(kOptions); ++option_index) { SCOPED_TRACE(base::StringPrintf("option_index %zu", option_index)); StringToSymbolicConstantOptions options = kOptions[option_index]; - for (size_t index = 0; index < arraysize(kSignalTestData); ++index) { + for (size_t index = 0; index < ArraySize(kSignalTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); int signal = kSignalTestData[index].signal; { @@ -213,7 +213,7 @@ "", }; - for (size_t index = 0; index < arraysize(kNegativeTestData); ++index) { + for (size_t index = 0; index < ArraySize(kNegativeTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); TestStringToSignal(kNegativeTestData[index], options, false, 0); } @@ -234,7 +234,7 @@ NUL_TEST_DATA("1\0002"), }; - for (size_t index = 0; index < arraysize(kNULTestData); ++index) { + for (size_t index = 0; index < ArraySize(kNULTestData); ++index) { SCOPED_TRACE(base::StringPrintf("index %zu", index)); base::StringPiece string(kNULTestData[index].string, kNULTestData[index].length);
diff --git a/third_party/crashpad/crashpad/util/process/process_memory.cc b/third_party/crashpad/crashpad/util/process/process_memory.cc index c23af93e..ab87b94 100644 --- a/third_party/crashpad/crashpad/util/process/process_memory.cc +++ b/third_party/crashpad/crashpad/util/process/process_memory.cc
@@ -17,13 +17,20 @@ #include <algorithm> #include "base/logging.h" +#include "util/numeric/safe_assignment.h" namespace crashpad { -bool ProcessMemory::Read(VMAddress address, size_t size, void* buffer) const { +bool ProcessMemory::Read(VMAddress address, VMSize size, void* buffer) const { + size_t local_size; + if (!AssignIfInRange(&local_size, size)) { + LOG(ERROR) << "size " << size << " out of bounds for size_t"; + return false; + } + char* buffer_c = static_cast<char*>(buffer); - while (size > 0) { - ssize_t bytes_read = ReadUpTo(address, size, buffer_c); + while (local_size > 0) { + ssize_t bytes_read = ReadUpTo(address, local_size, buffer_c); if (bytes_read < 0) { return false; } @@ -31,8 +38,8 @@ LOG(ERROR) << "short read"; return false; } - DCHECK_LE(static_cast<size_t>(bytes_read), size); - size -= bytes_read; + DCHECK_LE(static_cast<size_t>(bytes_read), local_size); + local_size -= bytes_read; address += bytes_read; buffer_c += bytes_read; } @@ -41,15 +48,21 @@ bool ProcessMemory::ReadCStringInternal(VMAddress address, bool has_size, - size_t size, + VMSize size, std::string* string) const { + size_t local_size; + if (!AssignIfInRange(&local_size, size)) { + LOG(ERROR) << "size " << size << " out of bounds for size_t"; + return false; + } + string->clear(); char buffer[4096]; do { size_t read_size; if (has_size) { - read_size = std::min(sizeof(buffer), size); + read_size = std::min(sizeof(buffer), local_size); } else { read_size = sizeof(buffer); } @@ -70,8 +83,8 @@ string->append(buffer, bytes_read); address += bytes_read; - size -= bytes_read; - } while (!has_size || size > 0); + local_size -= bytes_read; + } while (!has_size || local_size > 0); LOG(ERROR) << "unterminated string"; return false;
diff --git a/third_party/crashpad/crashpad/util/process/process_memory.h b/third_party/crashpad/crashpad/util/process/process_memory.h index 5ea595e..32e7472f 100644 --- a/third_party/crashpad/crashpad/util/process/process_memory.h +++ b/third_party/crashpad/crashpad/util/process/process_memory.h
@@ -46,7 +46,7 @@ //! //! \return `true` on success, with \a buffer filled appropriately. `false` on //! failure, with a message logged. - bool Read(VMAddress address, size_t size, void* buffer) const; + bool Read(VMAddress address, VMSize size, void* buffer) const; //! \brief Reads a `NUL`-terminated C string from the target process into a //! string in the current process. @@ -79,7 +79,7 @@ //! a `NUL` terminator is not found within \a size bytes, or when //! encountering unmapped or unreadable pages. bool ReadCStringSizeLimited(VMAddress address, - size_t size, + VMSize size, std::string* string) const { return ReadCStringInternal(address, true, size, string); } @@ -124,7 +124,7 @@ //! encountering unmapped or unreadable pages. virtual bool ReadCStringInternal(VMAddress address, bool has_size, - size_t size, + VMSize size, std::string* string) const; };
diff --git a/third_party/crashpad/crashpad/util/process/process_memory_range.cc b/third_party/crashpad/crashpad/util/process/process_memory_range.cc index aee8c80..caa4315 100644 --- a/third_party/crashpad/crashpad/util/process/process_memory_range.cc +++ b/third_party/crashpad/crashpad/util/process/process_memory_range.cc
@@ -67,7 +67,7 @@ } bool ProcessMemoryRange::Read(VMAddress address, - size_t size, + VMSize size, void* buffer) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); CheckedVMAddressRange read_range(range_.Is64Bit(), address, size); @@ -79,14 +79,14 @@ } bool ProcessMemoryRange::ReadCStringSizeLimited(VMAddress address, - size_t size, + VMSize size, std::string* string) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); if (!range_.ContainsValue(address)) { LOG(ERROR) << "read out of range"; return false; } - size = std::min(size, base::checked_cast<size_t>(range_.End() - address)); + size = std::min(size, range_.End() - address); return memory_->ReadCStringSizeLimited(address, size, string); }
diff --git a/third_party/crashpad/crashpad/util/process/process_memory_range.h b/third_party/crashpad/crashpad/util/process/process_memory_range.h index 2b654ba1..aabee49 100644 --- a/third_party/crashpad/crashpad/util/process/process_memory_range.h +++ b/third_party/crashpad/crashpad/util/process/process_memory_range.h
@@ -97,7 +97,7 @@ //! //! \return `true` on success, with \a buffer filled appropriately. `false` on //! failure, with a message logged. - bool Read(VMAddress address, size_t size, void* buffer) const; + bool Read(VMAddress address, VMSize size, void* buffer) const; //! \brief Reads a `NUL`-terminated C string from the target process into a //! string in the current process. @@ -113,7 +113,7 @@ //! a `NUL` terminator is not found within \a size bytes, or when //! encountering unmapped or unreadable pages. bool ReadCStringSizeLimited(VMAddress address, - size_t size, + VMSize size, std::string* string) const; private:
diff --git a/third_party/crashpad/crashpad/util/process/process_memory_range_test.cc b/third_party/crashpad/crashpad/util/process/process_memory_range_test.cc index fa2a893..9431d442 100644 --- a/third_party/crashpad/crashpad/util/process/process_memory_range_test.cc +++ b/third_party/crashpad/crashpad/util/process/process_memory_range_test.cc
@@ -19,9 +19,10 @@ #include "base/logging.h" #include "build/build_config.h" #include "gtest/gtest.h" +#include "test/process_type.h" +#include "util/misc/arraysize.h" #include "util/misc/from_pointer_cast.h" #include "util/process/process_memory_native.h" -#include "test/process_type.h" namespace crashpad { namespace test { @@ -58,28 +59,28 @@ auto string1_addr = FromPointerCast<VMAddress>(kTestObject.string1); auto string2_addr = FromPointerCast<VMAddress>(kTestObject.string2); ASSERT_TRUE(range.ReadCStringSizeLimited( - string1_addr, arraysize(kTestObject.string1), &string)); + string1_addr, ArraySize(kTestObject.string1), &string)); EXPECT_STREQ(string.c_str(), kTestObject.string1); ASSERT_TRUE(range.ReadCStringSizeLimited( - string2_addr, arraysize(kTestObject.string2), &string)); + string2_addr, ArraySize(kTestObject.string2), &string)); EXPECT_STREQ(string.c_str(), kTestObject.string2); // Limit the range to remove access to string2. ProcessMemoryRange range2; ASSERT_TRUE(range2.Initialize(range)); ASSERT_TRUE( - range2.RestrictRange(string1_addr, arraysize(kTestObject.string1))); + range2.RestrictRange(string1_addr, ArraySize(kTestObject.string1))); EXPECT_TRUE(range2.ReadCStringSizeLimited( - string1_addr, arraysize(kTestObject.string1), &string)); + string1_addr, ArraySize(kTestObject.string1), &string)); EXPECT_FALSE(range2.ReadCStringSizeLimited( - string2_addr, arraysize(kTestObject.string2), &string)); + string2_addr, ArraySize(kTestObject.string2), &string)); EXPECT_FALSE(range2.Read(object_addr, sizeof(object), &object)); // String reads fail if the NUL terminator is outside the range. ASSERT_TRUE(range2.RestrictRange(string1_addr, strlen(kTestObject.string1))); EXPECT_FALSE(range2.ReadCStringSizeLimited( - string1_addr, arraysize(kTestObject.string1), &string)); + string1_addr, ArraySize(kTestObject.string1), &string)); // New range outside the old range. EXPECT_FALSE(range2.RestrictRange(string1_addr - 1, 1));
diff --git a/third_party/crashpad/crashpad/util/stdlib/string_number_conversion_test.cc b/third_party/crashpad/crashpad/util/stdlib/string_number_conversion_test.cc index d855c8d..ee19429 100644 --- a/third_party/crashpad/crashpad/util/stdlib/string_number_conversion_test.cc +++ b/third_party/crashpad/crashpad/util/stdlib/string_number_conversion_test.cc
@@ -18,8 +18,8 @@ #include <limits> -#include "base/macros.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -94,7 +94,7 @@ {"18446744073709551616", false, 0}, }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { int value; bool valid = StringToNumber(kTestData[index].string, &value); if (kTestData[index].valid) { @@ -114,7 +114,7 @@ // is split to avoid MSVC warning: // "decimal digit terminates octal escape sequence". static constexpr char input[] = "6\000" "6"; - std::string input_string(input, arraysize(input) - 1); + std::string input_string(input, ArraySize(input) - 1); int output; EXPECT_FALSE(StringToNumber(input_string, &output)); } @@ -188,7 +188,7 @@ {"18446744073709551616", false, 0}, }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { unsigned int value; bool valid = StringToNumber(kTestData[index].string, &value); if (kTestData[index].valid) { @@ -208,7 +208,7 @@ // is split to avoid MSVC warning: // "decimal digit terminates octal escape sequence". static constexpr char input[] = "6\000" "6"; - std::string input_string(input, arraysize(input) - 1); + std::string input_string(input, ArraySize(input) - 1); unsigned int output; EXPECT_FALSE(StringToNumber(input_string, &output)); } @@ -245,7 +245,7 @@ {"0x7Fffffffffffffff", true, std::numeric_limits<int64_t>::max()}, }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { int64_t value; bool valid = StringToNumber(kTestData[index].string, &value); if (kTestData[index].valid) { @@ -295,7 +295,7 @@ {"0xFfffffffffffffff", true, std::numeric_limits<uint64_t>::max()}, }; - for (size_t index = 0; index < arraysize(kTestData); ++index) { + for (size_t index = 0; index < ArraySize(kTestData); ++index) { uint64_t value; bool valid = StringToNumber(kTestData[index].string, &value); if (kTestData[index].valid) {
diff --git a/third_party/crashpad/crashpad/util/stdlib/strlcpy_test.cc b/third_party/crashpad/crashpad/util/stdlib/strlcpy_test.cc index 5d20e19..172a09ab 100644 --- a/third_party/crashpad/crashpad/util/stdlib/strlcpy_test.cc +++ b/third_party/crashpad/crashpad/util/stdlib/strlcpy_test.cc
@@ -20,10 +20,10 @@ #include <algorithm> #include "base/format_macros.h" -#include "base/macros.h" #include "base/strings/string16.h" #include "base/strings/stringprintf.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" namespace crashpad { namespace test { @@ -64,7 +64,7 @@ static constexpr base::char16 test_characters[] = {0x4d, 0xe9, 0x100, 0x151, 0x1e18}; - for (size_t index = 0; index < arraysize(test_characters); ++index) { + for (size_t index = 0; index < ArraySize(test_characters); ++index) { base::char16 test_character = test_characters[index]; SCOPED_TRACE(base::StringPrintf( "character index %" PRIuS ", character 0x%x", index, test_character)); @@ -78,13 +78,13 @@ EXPECT_EQ(c16lcpy(destination.data, test_string.c_str(), - arraysize(destination.data)), + ArraySize(destination.data)), length); // Make sure that the destination buffer is NUL-terminated, and that as // much of the test string was copied as could fit. size_t expected_destination_length = - std::min(length, arraysize(destination.data) - 1); + std::min(length, ArraySize(destination.data) - 1); EXPECT_EQ(destination.data[expected_destination_length], '\0'); EXPECT_EQ(C16Len(destination.data), expected_destination_length); @@ -97,15 +97,15 @@ // of the buffer passed to c16lcpy. EXPECT_TRUE(C16Memcmp(expected_untouched.lead_guard, destination.lead_guard, - arraysize(destination.lead_guard)) == 0); + ArraySize(destination.lead_guard)) == 0); size_t expected_untouched_length = - arraysize(destination.data) - expected_destination_length - 1; + ArraySize(destination.data) - expected_destination_length - 1; EXPECT_TRUE(C16Memcmp(expected_untouched.data, &destination.data[expected_destination_length + 1], expected_untouched_length) == 0); EXPECT_TRUE(C16Memcmp(expected_untouched.trail_guard, destination.trail_guard, - arraysize(destination.trail_guard)) == 0); + ArraySize(destination.trail_guard)) == 0); } } }
diff --git a/third_party/crashpad/crashpad/util/stdlib/thread_safe_vector_test.cc b/third_party/crashpad/crashpad/util/stdlib/thread_safe_vector_test.cc index 805360f4..183c6366 100644 --- a/third_party/crashpad/crashpad/util/stdlib/thread_safe_vector_test.cc +++ b/third_party/crashpad/crashpad/util/stdlib/thread_safe_vector_test.cc
@@ -15,6 +15,7 @@ #include "util/stdlib/thread_safe_vector.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" #include "util/thread/thread.h" namespace crashpad { @@ -53,12 +54,12 @@ EXPECT_TRUE(vector.empty()); ThreadSafeVectorTestThread threads[100]; - for (size_t index = 0; index < arraysize(threads); ++index) { + for (size_t index = 0; index < ArraySize(threads); ++index) { threads[index].SetTestParameters( &thread_safe_vector, static_cast<int>(index * kElementsPerThread)); } - for (size_t index = 0; index < arraysize(threads); ++index) { + for (size_t index = 0; index < ArraySize(threads); ++index) { threads[index].Start(); if (index % 10 == 0) { @@ -75,8 +76,8 @@ std::vector<int> drained = thread_safe_vector.Drain(); vector.insert(vector.end(), drained.begin(), drained.end()); - bool found[arraysize(threads) * kElementsPerThread] = {}; - EXPECT_EQ(vector.size(), arraysize(found)); + bool found[ArraySize(threads) * kElementsPerThread] = {}; + EXPECT_EQ(vector.size(), ArraySize(found)); for (int element : vector) { EXPECT_FALSE(found[element]) << element; found[element] = true;
diff --git a/third_party/crashpad/crashpad/util/synchronization/semaphore_test.cc b/third_party/crashpad/crashpad/util/synchronization/semaphore_test.cc index 10f7546..fedead1 100644 --- a/third_party/crashpad/crashpad/util/synchronization/semaphore_test.cc +++ b/third_party/crashpad/crashpad/util/synchronization/semaphore_test.cc
@@ -16,8 +16,8 @@ #include <sys/types.h> -#include "base/macros.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" #if defined(OS_POSIX) #include <pthread.h> @@ -126,7 +126,7 @@ Semaphore semaphore(5); ThreadMainInfo info[10]; size_t iterations = 0; - for (size_t index = 0; index < arraysize(info); ++index) { + for (size_t index = 0; index < ArraySize(info); ++index) { info[index].semaphore = &semaphore; info[index].iterations = index; iterations += info[index].iterations; @@ -138,7 +138,7 @@ semaphore.Signal(); } - for (size_t index = 0; index < arraysize(info); ++index) { + for (size_t index = 0; index < ArraySize(info); ++index) { JoinThread(&info[index]); } }
diff --git a/third_party/crashpad/crashpad/util/thread/thread_log_messages_test.cc b/third_party/crashpad/crashpad/util/thread/thread_log_messages_test.cc index 00b612c..f186ed2 100644 --- a/third_party/crashpad/crashpad/util/thread/thread_log_messages_test.cc +++ b/third_party/crashpad/crashpad/util/thread/thread_log_messages_test.cc
@@ -20,6 +20,7 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" #include "gtest/gtest.h" +#include "util/misc/arraysize.h" #include "util/thread/thread.h" namespace crashpad { @@ -93,8 +94,8 @@ const std::vector<std::string>& log_messages = thread_log_messages.log_messages(); - EXPECT_EQ(log_messages.size(), arraysize(kMessages)); - for (size_t index = 0; index < arraysize(kMessages); ++index) { + EXPECT_EQ(log_messages.size(), ArraySize(kMessages)); + for (size_t index = 0; index < ArraySize(kMessages); ++index) { EXPECT_EQ(MessageString(log_messages[index]), kMessages[index]) << "index " << index; } @@ -173,7 +174,7 @@ LoggingTestThread threads[20]; int start = 0; - for (size_t index = 0; index < arraysize(threads); ++index) { + for (size_t index = 0; index < ArraySize(threads); ++index) { threads[index].Initialize( index, static_cast<int>(start), static_cast<int>(index)); start += static_cast<int>(index);
diff --git a/third_party/crashpad/crashpad/util/thread/thread_test.cc b/third_party/crashpad/crashpad/util/thread/thread_test.cc index d92544b6..47a711c0 100644 --- a/third_party/crashpad/crashpad/util/thread/thread_test.cc +++ b/third_party/crashpad/crashpad/util/thread/thread_test.cc
@@ -14,7 +14,6 @@ #include "util/thread/thread.h" -#include "base/macros.h" #include "gtest/gtest.h" #include "util/synchronization/semaphore.h"
diff --git a/third_party/crashpad/crashpad/util/util.gyp b/third_party/crashpad/crashpad/util/util.gyp index dc82287e..32be8ba 100644 --- a/third_party/crashpad/crashpad/util/util.gyp +++ b/third_party/crashpad/crashpad/util/util.gyp
@@ -126,7 +126,7 @@ 'mach/task_for_pid.h', 'misc/address_sanitizer.h', 'misc/address_types.h', - 'misc/arraysize_unsafe.h', + 'misc/arraysize.h', 'misc/as_underlying_type.h', 'misc/capture_context.h', 'misc/capture_context_linux.S',
diff --git a/third_party/crashpad/crashpad/util/util_test.gyp b/third_party/crashpad/crashpad/util/util_test.gyp index b3c8d419..9edd3dcb 100644 --- a/third_party/crashpad/crashpad/util/util_test.gyp +++ b/third_party/crashpad/crashpad/util/util_test.gyp
@@ -65,7 +65,7 @@ 'mach/notify_server_test.cc', 'mach/scoped_task_suspend_test.cc', 'mach/symbolic_constants_mach_test.cc', - 'misc/arraysize_unsafe_test.cc', + 'misc/arraysize_test.cc', 'misc/capture_context_test.cc', 'misc/capture_context_test_util.h', 'misc/capture_context_test_util_linux.cc',
diff --git a/third_party/crashpad/crashpad/util/win/command_line_test.cc b/third_party/crashpad/crashpad/util/win/command_line_test.cc index 025ef8a7..e5ceef8 100644 --- a/third_party/crashpad/crashpad/util/win/command_line_test.cc +++ b/third_party/crashpad/crashpad/util/win/command_line_test.cc
@@ -19,10 +19,10 @@ #include <sys/types.h> #include "base/logging.h" -#include "base/macros.h" #include "base/scoped_generic.h" #include "gtest/gtest.h" #include "test/errors.h" +#include "util/misc/arraysize.h" #include "util/win/scoped_local_alloc.h" namespace crashpad { @@ -65,7 +65,7 @@ L"argument 1", L"argument 2", }; - AppendCommandLineArgumentTest(arraysize(kArguments), kArguments); + AppendCommandLineArgumentTest(ArraySize(kArguments), kArguments); } { @@ -77,7 +77,7 @@ L"argument 2", L"\\some\\path with\\spaces", }; - AppendCommandLineArgumentTest(arraysize(kArguments), kArguments); + AppendCommandLineArgumentTest(ArraySize(kArguments), kArguments); } { @@ -89,7 +89,7 @@ L"she said, \"you had me at hello\"", L"\\some\\path with\\spaces", }; - AppendCommandLineArgumentTest(arraysize(kArguments), kArguments); + AppendCommandLineArgumentTest(ArraySize(kArguments), kArguments); } { @@ -102,7 +102,7 @@ L"argument3", L"argument4", }; - AppendCommandLineArgumentTest(arraysize(kArguments), kArguments); + AppendCommandLineArgumentTest(ArraySize(kArguments), kArguments); } { @@ -113,7 +113,7 @@ L"\\some\\directory with\\spaces\\", L"argument2", }; - AppendCommandLineArgumentTest(arraysize(kArguments), kArguments); + AppendCommandLineArgumentTest(ArraySize(kArguments), kArguments); } { @@ -124,7 +124,7 @@ L"", L"argument2", }; - AppendCommandLineArgumentTest(arraysize(kArguments), kArguments); + AppendCommandLineArgumentTest(ArraySize(kArguments), kArguments); } { @@ -159,7 +159,7 @@ L"\"\"", L" \t\n\v\"", }; - AppendCommandLineArgumentTest(arraysize(kArguments), kArguments); + AppendCommandLineArgumentTest(ArraySize(kArguments), kArguments); } }
diff --git a/third_party/crashpad/crashpad/util/win/exception_handler_server.cc b/third_party/crashpad/crashpad/util/win/exception_handler_server.cc index 6642665..8ca3d25 100644 --- a/third_party/crashpad/crashpad/util/win/exception_handler_server.cc +++ b/third_party/crashpad/crashpad/util/win/exception_handler_server.cc
@@ -29,6 +29,7 @@ #include "snapshot/crashpad_info_client_options.h" #include "snapshot/win/process_snapshot_win.h" #include "util/file/file_writer.h" +#include "util/misc/arraysize.h" #include "util/misc/tri_state.h" #include "util/misc/uuid.h" #include "util/win/get_function.h" @@ -307,7 +308,7 @@ void ExceptionHandlerServer::Run(Delegate* delegate) { uint64_t shutdown_token = base::RandUint64(); ScopedKernelHANDLE thread_handles[kPipeInstances]; - for (size_t i = 0; i < arraysize(thread_handles); ++i) { + for (size_t i = 0; i < ArraySize(thread_handles); ++i) { HANDLE pipe; if (first_pipe_instance_.is_valid()) { pipe = first_pipe_instance_.release(); @@ -359,7 +360,7 @@ } // Signal to the named pipe instances that they should terminate. - for (size_t i = 0; i < arraysize(thread_handles); ++i) { + for (size_t i = 0; i < ArraySize(thread_handles); ++i) { ClientToServerMessage message; memset(&message, 0, sizeof(message)); message.type = ClientToServerMessage::kShutdown;
diff --git a/third_party/crashpad/crashpad/util/win/get_module_information.cc b/third_party/crashpad/crashpad/util/win/get_module_information.cc index 1a9fd0c..850bfe12 100644 --- a/third_party/crashpad/crashpad/util/win/get_module_information.cc +++ b/third_party/crashpad/crashpad/util/win/get_module_information.cc
@@ -22,9 +22,13 @@ HMODULE module, MODULEINFO* module_info, DWORD cb) { +#if PSAPI_VERSION == 1 static const auto get_module_information = - GET_FUNCTION_REQUIRED(L"psapi.dll", GetModuleInformation); + GET_FUNCTION_REQUIRED(L"psapi.dll", GetModuleInformation); return get_module_information(process, module, module_info, cb); +#elif PSAPI_VERSION == 2 + return GetModuleInformation(process, module, module_info, cb); +#endif } } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/win/get_module_information.h b/third_party/crashpad/crashpad/util/win/get_module_information.h index c7d1cf1..8fce0350 100644 --- a/third_party/crashpad/crashpad/util/win/get_module_information.h +++ b/third_party/crashpad/crashpad/util/win/get_module_information.h
@@ -17,7 +17,9 @@ #include <windows.h> -#define PSAPI_VERSION 1 +#ifndef PSAPI_VERSION +#define PSAPI_VERSION 2 +#endif #include <psapi.h> namespace crashpad {
diff --git a/third_party/crashpad/crashpad/util/win/ntstatus_logging.cc b/third_party/crashpad/crashpad/util/win/ntstatus_logging.cc index 442e49f4..118bfef 100644 --- a/third_party/crashpad/crashpad/util/win/ntstatus_logging.cc +++ b/third_party/crashpad/crashpad/util/win/ntstatus_logging.cc
@@ -17,6 +17,7 @@ #include <string> #include "base/strings/stringprintf.h" +#include "util/misc/arraysize.h" namespace { @@ -29,7 +30,7 @@ ntstatus, 0, msgbuf, - arraysize(msgbuf), + static_cast<DWORD>(ArraySize(msgbuf)), nullptr); if (len) { // Most system messages end in a period and a space. Remove the space if
diff --git a/third_party/crashpad/crashpad/util/win/registration_protocol_win.cc b/third_party/crashpad/crashpad/util/win/registration_protocol_win.cc index 4fb536d..412f8da 100644 --- a/third_party/crashpad/crashpad/util/win/registration_protocol_win.cc +++ b/third_party/crashpad/crashpad/util/win/registration_protocol_win.cc
@@ -18,7 +18,7 @@ #include <windows.h> #include "base/logging.h" -#include "base/macros.h" +#include "util/misc/arraysize.h" #include "util/win/exception_handler_server.h" #include "util/win/scoped_handle.h" @@ -168,7 +168,7 @@ ACL_REVISION, // AclRevision. 0, // Sbz1. sizeof(kSecDescBlob.sacl), // AclSize. - arraysize(kSecDescBlob.sacl.ace), // AceCount. + static_cast<WORD>(ArraySize(kSecDescBlob.sacl.ace)), // AceCount. 0, // Sbz2. }, @@ -188,8 +188,9 @@ // sid. { SID_REVISION, // Revision. - // SubAuthorityCount. - arraysize(kSecDescBlob.sacl.ace[0].sid.SubAuthority), + // SubAuthorityCount. + static_cast<BYTE>( + ArraySize(kSecDescBlob.sacl.ace[0].sid.SubAuthority)), // IdentifierAuthority. {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_UNTRUSTED_RID}, // SubAuthority.
diff --git a/third_party/crashpad/crashpad/util/win/safe_terminate_process_test.cc b/third_party/crashpad/crashpad/util/win/safe_terminate_process_test.cc index f9db161..a62fb14 100644 --- a/third_party/crashpad/crashpad/util/win/safe_terminate_process_test.cc +++ b/third_party/crashpad/crashpad/util/win/safe_terminate_process_test.cc
@@ -27,6 +27,7 @@ #include "test/errors.h" #include "test/test_paths.h" #include "test/win/child_launcher.h" +#include "util/misc/arraysize.h" #include "util/win/scoped_handle.h" namespace crashpad { @@ -148,7 +149,7 @@ }; void* target = reinterpret_cast<void*>(TerminateProcess); - ScopedExecutablePatch executable_patch(target, patch, arraysize(patch)); + ScopedExecutablePatch executable_patch(target, patch, ArraySize(patch)); // Make sure that SafeTerminateProcess() can be called. Since it’s been // patched with a no-op stub, GetLastError() shouldn’t be modified.
diff --git a/third_party/ink/LICENSE b/third_party/ink/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/third_party/ink/LICENSE
@@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
diff --git a/third_party/ink/OWNERS b/third_party/ink/OWNERS index d139e18e..6a73fc4 100644 --- a/third_party/ink/OWNERS +++ b/third_party/ink/OWNERS
@@ -1,3 +1,4 @@ +dstockwell@chromium.org dvallet@chromium.org fdegros@chromium.org martiw@chromium.org
diff --git a/third_party/ink/README.chromium b/third_party/ink/README.chromium new file mode 100644 index 0000000..1588626 --- /dev/null +++ b/third_party/ink/README.chromium
@@ -0,0 +1,8 @@ +Name: Google Ink +Short Name: ink +URL: https://github.com/google/ink +Version: none +License: Apache 2.0 +Security Critical: yes + +The build artifacts from Ink are downloaded to this directory via DEPS.
diff --git a/third_party/ink/README.md b/third_party/ink/README.md index a2f6a63..73f75c5f 100644 --- a/third_party/ink/README.md +++ b/third_party/ink/README.md
@@ -3,4 +3,4 @@ Ink is a software library enabling Google applications to let their users express themselves using freehand drawing and handwriting. -go/ink +https://github.com/google/ink
diff --git a/third_party/ink/closure/array/array.js b/third_party/ink/closure/array/array.js deleted file mode 100644 index 926df8a..0000000 --- a/third_party/ink/closure/array/array.js +++ /dev/null
@@ -1,1667 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for manipulating arrays. - * - * @author pupius@google.com (Daniel Pupius) - * @author arv@google.com (Erik Arvidsson) - * @author pallosp@google.com (Peter Pallos) - */ - - -goog.provide('goog.array'); - -goog.require('goog.asserts'); - - -/** - * @define {boolean} NATIVE_ARRAY_PROTOTYPES indicates whether the code should - * rely on Array.prototype functions, if available. - * - * The Array.prototype functions can be defined by external libraries like - * Prototype and setting this flag to false forces closure to use its own - * goog.array implementation. - * - * If your javascript can be loaded by a third party site and you are wary about - * relying on the prototype functions, specify - * "--define goog.NATIVE_ARRAY_PROTOTYPES=false" to the JSCompiler. - * - * Setting goog.TRUSTED_SITE to false will automatically set - * NATIVE_ARRAY_PROTOTYPES to false. - */ -goog.define('goog.NATIVE_ARRAY_PROTOTYPES', goog.TRUSTED_SITE); - - -/** - * @define {boolean} If true, JSCompiler will use the native implementation of - * array functions where appropriate (e.g., {@code Array#filter}) and remove the - * unused pure JS implementation. - */ -goog.define('goog.array.ASSUME_NATIVE_FUNCTIONS', false); - - -/** - * Returns the last element in an array without removing it. - * Same as goog.array.last. - * @param {IArrayLike<T>|string} array The array. - * @return {T} Last item in array. - * @template T - */ -goog.array.peek = function(array) { - return array[array.length - 1]; -}; - - -/** - * Returns the last element in an array without removing it. - * Same as goog.array.peek. - * @param {IArrayLike<T>|string} array The array. - * @return {T} Last item in array. - * @template T - */ -goog.array.last = goog.array.peek; - -// NOTE(arv): Since most of the array functions are generic it allows you to -// pass an array-like object. Strings have a length and are considered array- -// like. However, the 'in' operator does not work on strings so we cannot just -// use the array path even if the browser supports indexing into strings. We -// therefore end up splitting the string. - - -/** - * Returns the index of the first element of an array with a specified value, or - * -1 if the element is not present in the array. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-indexof} - * - * @param {IArrayLike<T>|string} arr The array to be searched. - * @param {T} obj The object for which we are searching. - * @param {number=} opt_fromIndex The index at which to start the search. If - * omitted the search starts at index 0. - * @return {number} The index of the first matching array element. - * @template T - */ -goog.array.indexOf = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.indexOf) ? - function(arr, obj, opt_fromIndex) { - goog.asserts.assert(arr.length != null); - - return Array.prototype.indexOf.call(arr, obj, opt_fromIndex); - } : - function(arr, obj, opt_fromIndex) { - var fromIndex = opt_fromIndex == null ? - 0 : - (opt_fromIndex < 0 ? Math.max(0, arr.length + opt_fromIndex) : - opt_fromIndex); - - if (goog.isString(arr)) { - // Array.prototype.indexOf uses === so only strings should be found. - if (!goog.isString(obj) || obj.length != 1) { - return -1; - } - return arr.indexOf(obj, fromIndex); - } - - for (var i = fromIndex; i < arr.length; i++) { - if (i in arr && arr[i] === obj) return i; - } - return -1; - }; - - -/** - * Returns the index of the last element of an array with a specified value, or - * -1 if the element is not present in the array. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-lastindexof} - * - * @param {!IArrayLike<T>|string} arr The array to be searched. - * @param {T} obj The object for which we are searching. - * @param {?number=} opt_fromIndex The index at which to start the search. If - * omitted the search starts at the end of the array. - * @return {number} The index of the last matching array element. - * @template T - */ -goog.array.lastIndexOf = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.lastIndexOf) ? - function(arr, obj, opt_fromIndex) { - goog.asserts.assert(arr.length != null); - - // Firefox treats undefined and null as 0 in the fromIndex argument which - // leads it to always return -1 - var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex; - return Array.prototype.lastIndexOf.call(arr, obj, fromIndex); - } : - function(arr, obj, opt_fromIndex) { - var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex; - - if (fromIndex < 0) { - fromIndex = Math.max(0, arr.length + fromIndex); - } - - if (goog.isString(arr)) { - // Array.prototype.lastIndexOf uses === so only strings should be found. - if (!goog.isString(obj) || obj.length != 1) { - return -1; - } - return arr.lastIndexOf(obj, fromIndex); - } - - for (var i = fromIndex; i >= 0; i--) { - if (i in arr && arr[i] === obj) return i; - } - return -1; - }; - - -/** - * Calls a function for each element in an array. Skips holes in the array. - * See {@link http://tinyurl.com/developer-mozilla-org-array-foreach} - * - * @param {IArrayLike<T>|string} arr Array or array like object over - * which to iterate. - * @param {?function(this: S, T, number, ?): ?} f The function to call for every - * element. This function takes 3 arguments (the element, the index and the - * array). The return value is ignored. - * @param {S=} opt_obj The object to be used as the value of 'this' within f. - * @template T,S - */ -goog.array.forEach = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.forEach) ? - function(arr, f, opt_obj) { - goog.asserts.assert(arr.length != null); - - Array.prototype.forEach.call(arr, f, opt_obj); - } : - function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = 0; i < l; i++) { - if (i in arr2) { - f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr); - } - } - }; - - -/** - * Calls a function for each element in an array, starting from the last - * element rather than the first. - * - * @param {IArrayLike<T>|string} arr Array or array - * like object over which to iterate. - * @param {?function(this: S, T, number, ?): ?} f The function to call for every - * element. This function - * takes 3 arguments (the element, the index and the array). The return - * value is ignored. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within f. - * @template T,S - */ -goog.array.forEachRight = function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = l - 1; i >= 0; --i) { - if (i in arr2) { - f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr); - } - } -}; - - -/** - * Calls a function for each element in an array, and if the function returns - * true adds the element to a new array. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-filter} - * - * @param {IArrayLike<T>|string} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?):boolean} f The function to call for - * every element. This function - * takes 3 arguments (the element, the index and the array) and must - * return a Boolean. If the return value is true the element is added to the - * result array. If it is false the element is not included. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within f. - * @return {!Array<T>} a new array in which only elements that passed the test - * are present. - * @template T,S - */ -goog.array.filter = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.filter) ? - function(arr, f, opt_obj) { - goog.asserts.assert(arr.length != null); - - return Array.prototype.filter.call(arr, f, opt_obj); - } : - function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var res = []; - var resLength = 0; - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = 0; i < l; i++) { - if (i in arr2) { - var val = arr2[i]; // in case f mutates arr2 - if (f.call(/** @type {?} */ (opt_obj), val, i, arr)) { - res[resLength++] = val; - } - } - } - return res; - }; - - -/** - * Calls a function for each element in an array and inserts the result into a - * new array. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-map} - * - * @param {IArrayLike<VALUE>|string} arr Array or array like object - * over which to iterate. - * @param {function(this:THIS, VALUE, number, ?): RESULT} f The function to call - * for every element. This function takes 3 arguments (the element, - * the index and the array) and should return something. The result will be - * inserted into a new array. - * @param {THIS=} opt_obj The object to be used as the value of 'this' within f. - * @return {!Array<RESULT>} a new array with the results from f. - * @template THIS, VALUE, RESULT - */ -goog.array.map = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.map) ? - function(arr, f, opt_obj) { - goog.asserts.assert(arr.length != null); - - return Array.prototype.map.call(arr, f, opt_obj); - } : - function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var res = new Array(l); - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = 0; i < l; i++) { - if (i in arr2) { - res[i] = f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr); - } - } - return res; - }; - - -/** - * Passes every element of an array into a function and accumulates the result. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-reduce} - * - * For example: - * var a = [1, 2, 3, 4]; - * goog.array.reduce(a, function(r, v, i, arr) {return r + v;}, 0); - * returns 10 - * - * @param {IArrayLike<T>|string} arr Array or array - * like object over which to iterate. - * @param {function(this:S, R, T, number, ?) : R} f The function to call for - * every element. This function - * takes 4 arguments (the function's previous result or the initial value, - * the value of the current array element, the current array index, and the - * array itself) - * function(previousValue, currentValue, index, array). - * @param {?} val The initial value to pass into the function on the first call. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within f. - * @return {R} Result of evaluating f repeatedly across the values of the array. - * @template T,S,R - */ -goog.array.reduce = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.reduce) ? - function(arr, f, val, opt_obj) { - goog.asserts.assert(arr.length != null); - if (opt_obj) { - f = goog.bind(f, opt_obj); - } - return Array.prototype.reduce.call(arr, f, val); - } : - function(arr, f, val, opt_obj) { - var rval = val; - goog.array.forEach(arr, function(val, index) { - rval = f.call(/** @type {?} */ (opt_obj), rval, val, index, arr); - }); - return rval; - }; - - -/** - * Passes every element of an array into a function and accumulates the result, - * starting from the last element and working towards the first. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-reduceright} - * - * For example: - * var a = ['a', 'b', 'c']; - * goog.array.reduceRight(a, function(r, v, i, arr) {return r + v;}, ''); - * returns 'cba' - * - * @param {IArrayLike<T>|string} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, R, T, number, ?) : R} f The function to call for - * every element. This function - * takes 4 arguments (the function's previous result or the initial value, - * the value of the current array element, the current array index, and the - * array itself) - * function(previousValue, currentValue, index, array). - * @param {?} val The initial value to pass into the function on the first call. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within f. - * @return {R} Object returned as a result of evaluating f repeatedly across the - * values of the array. - * @template T,S,R - */ -goog.array.reduceRight = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.reduceRight) ? - function(arr, f, val, opt_obj) { - goog.asserts.assert(arr.length != null); - goog.asserts.assert(f != null); - if (opt_obj) { - f = goog.bind(f, opt_obj); - } - return Array.prototype.reduceRight.call(arr, f, val); - } : - function(arr, f, val, opt_obj) { - var rval = val; - goog.array.forEachRight(arr, function(val, index) { - rval = f.call(/** @type {?} */ (opt_obj), rval, val, index, arr); - }); - return rval; - }; - - -/** - * Calls f for each element of an array. If any call returns true, some() - * returns true (without checking the remaining elements). If all calls - * return false, some() returns false. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-some} - * - * @param {IArrayLike<T>|string} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call for - * for every element. This function takes 3 arguments (the element, the - * index and the array) and should return a boolean. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within f. - * @return {boolean} true if any element passes the test. - * @template T,S - */ -goog.array.some = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.some) ? - function(arr, f, opt_obj) { - goog.asserts.assert(arr.length != null); - - return Array.prototype.some.call(arr, f, opt_obj); - } : - function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = 0; i < l; i++) { - if (i in arr2 && f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) { - return true; - } - } - return false; - }; - - -/** - * Call f for each element of an array. If all calls return true, every() - * returns true. If any call returns false, every() returns false and - * does not continue to check the remaining elements. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-every} - * - * @param {IArrayLike<T>|string} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call for - * for every element. This function takes 3 arguments (the element, the - * index and the array) and should return a boolean. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within f. - * @return {boolean} false if any element fails the test. - * @template T,S - */ -goog.array.every = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.every) ? - function(arr, f, opt_obj) { - goog.asserts.assert(arr.length != null); - - return Array.prototype.every.call(arr, f, opt_obj); - } : - function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = 0; i < l; i++) { - if (i in arr2 && !f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) { - return false; - } - } - return true; - }; - - -/** - * Counts the array elements that fulfill the predicate, i.e. for which the - * callback function returns true. Skips holes in the array. - * - * @param {!IArrayLike<T>|string} arr Array or array like object - * over which to iterate. - * @param {function(this: S, T, number, ?): boolean} f The function to call for - * every element. Takes 3 arguments (the element, the index and the array). - * @param {S=} opt_obj The object to be used as the value of 'this' within f. - * @return {number} The number of the matching elements. - * @template T,S - */ -goog.array.count = function(arr, f, opt_obj) { - var count = 0; - goog.array.forEach(arr, function(element, index, arr) { - if (f.call(/** @type {?} */ (opt_obj), element, index, arr)) { - ++count; - } - }, opt_obj); - return count; -}; - - -/** - * Search an array for the first element that satisfies a given condition and - * return that element. - * @param {IArrayLike<T>|string} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call - * for every element. This function takes 3 arguments (the element, the - * index and the array) and should return a boolean. - * @param {S=} opt_obj An optional "this" context for the function. - * @return {T|null} The first array element that passes the test, or null if no - * element is found. - * @template T,S - */ -goog.array.find = function(arr, f, opt_obj) { - var i = goog.array.findIndex(arr, f, opt_obj); - return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i]; -}; - - -/** - * Search an array for the first element that satisfies a given condition and - * return its index. - * @param {IArrayLike<T>|string} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call for - * every element. This function - * takes 3 arguments (the element, the index and the array) and should - * return a boolean. - * @param {S=} opt_obj An optional "this" context for the function. - * @return {number} The index of the first array element that passes the test, - * or -1 if no element is found. - * @template T,S - */ -goog.array.findIndex = function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = 0; i < l; i++) { - if (i in arr2 && f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) { - return i; - } - } - return -1; -}; - - -/** - * Search an array (in reverse order) for the last element that satisfies a - * given condition and return that element. - * @param {IArrayLike<T>|string} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call - * for every element. This function - * takes 3 arguments (the element, the index and the array) and should - * return a boolean. - * @param {S=} opt_obj An optional "this" context for the function. - * @return {T|null} The last array element that passes the test, or null if no - * element is found. - * @template T,S - */ -goog.array.findRight = function(arr, f, opt_obj) { - var i = goog.array.findIndexRight(arr, f, opt_obj); - return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i]; -}; - - -/** - * Search an array (in reverse order) for the last element that satisfies a - * given condition and return its index. - * @param {IArrayLike<T>|string} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call - * for every element. This function - * takes 3 arguments (the element, the index and the array) and should - * return a boolean. - * @param {S=} opt_obj An optional "this" context for the function. - * @return {number} The index of the last array element that passes the test, - * or -1 if no element is found. - * @template T,S - */ -goog.array.findIndexRight = function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = l - 1; i >= 0; i--) { - if (i in arr2 && f.call(/** @type {?} */ (opt_obj), arr2[i], i, arr)) { - return i; - } - } - return -1; -}; - - -/** - * Whether the array contains the given object. - * @param {IArrayLike<?>|string} arr The array to test for the presence of the - * element. - * @param {*} obj The object for which to test. - * @return {boolean} true if obj is present. - */ -goog.array.contains = function(arr, obj) { - return goog.array.indexOf(arr, obj) >= 0; -}; - - -/** - * Whether the array is empty. - * @param {IArrayLike<?>|string} arr The array to test. - * @return {boolean} true if empty. - */ -goog.array.isEmpty = function(arr) { - return arr.length == 0; -}; - - -/** - * Clears the array. - * @param {IArrayLike<?>} arr Array or array like object to clear. - */ -goog.array.clear = function(arr) { - // For non real arrays we don't have the magic length so we delete the - // indices. - if (!goog.isArray(arr)) { - for (var i = arr.length - 1; i >= 0; i--) { - delete arr[i]; - } - } - arr.length = 0; -}; - - -/** - * Pushes an item into an array, if it's not already in the array. - * @param {Array<T>} arr Array into which to insert the item. - * @param {T} obj Value to add. - * @template T - */ -goog.array.insert = function(arr, obj) { - if (!goog.array.contains(arr, obj)) { - arr.push(obj); - } -}; - - -/** - * Inserts an object at the given index of the array. - * @param {IArrayLike<?>} arr The array to modify. - * @param {*} obj The object to insert. - * @param {number=} opt_i The index at which to insert the object. If omitted, - * treated as 0. A negative index is counted from the end of the array. - */ -goog.array.insertAt = function(arr, obj, opt_i) { - goog.array.splice(arr, opt_i, 0, obj); -}; - - -/** - * Inserts at the given index of the array, all elements of another array. - * @param {IArrayLike<?>} arr The array to modify. - * @param {IArrayLike<?>} elementsToAdd The array of elements to add. - * @param {number=} opt_i The index at which to insert the object. If omitted, - * treated as 0. A negative index is counted from the end of the array. - */ -goog.array.insertArrayAt = function(arr, elementsToAdd, opt_i) { - goog.partial(goog.array.splice, arr, opt_i, 0).apply(null, elementsToAdd); -}; - - -/** - * Inserts an object into an array before a specified object. - * @param {Array<T>} arr The array to modify. - * @param {T} obj The object to insert. - * @param {T=} opt_obj2 The object before which obj should be inserted. If obj2 - * is omitted or not found, obj is inserted at the end of the array. - * @template T - */ -goog.array.insertBefore = function(arr, obj, opt_obj2) { - var i; - if (arguments.length == 2 || (i = goog.array.indexOf(arr, opt_obj2)) < 0) { - arr.push(obj); - } else { - goog.array.insertAt(arr, obj, i); - } -}; - - -/** - * Removes the first occurrence of a particular value from an array. - * @param {IArrayLike<T>} arr Array from which to remove - * value. - * @param {T} obj Object to remove. - * @return {boolean} True if an element was removed. - * @template T - */ -goog.array.remove = function(arr, obj) { - var i = goog.array.indexOf(arr, obj); - var rv; - if ((rv = i >= 0)) { - goog.array.removeAt(arr, i); - } - return rv; -}; - - -/** - * Removes the last occurrence of a particular value from an array. - * @param {!IArrayLike<T>} arr Array from which to remove value. - * @param {T} obj Object to remove. - * @return {boolean} True if an element was removed. - * @template T - */ -goog.array.removeLast = function(arr, obj) { - var i = goog.array.lastIndexOf(arr, obj); - if (i >= 0) { - goog.array.removeAt(arr, i); - return true; - } - return false; -}; - - -/** - * Removes from an array the element at index i - * @param {IArrayLike<?>} arr Array or array like object from which to - * remove value. - * @param {number} i The index to remove. - * @return {boolean} True if an element was removed. - */ -goog.array.removeAt = function(arr, i) { - goog.asserts.assert(arr.length != null); - - // use generic form of splice - // splice returns the removed items and if successful the length of that - // will be 1 - return Array.prototype.splice.call(arr, i, 1).length == 1; -}; - - -/** - * Removes the first value that satisfies the given condition. - * @param {IArrayLike<T>} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call - * for every element. This function - * takes 3 arguments (the element, the index and the array) and should - * return a boolean. - * @param {S=} opt_obj An optional "this" context for the function. - * @return {boolean} True if an element was removed. - * @template T,S - */ -goog.array.removeIf = function(arr, f, opt_obj) { - var i = goog.array.findIndex(arr, f, opt_obj); - if (i >= 0) { - goog.array.removeAt(arr, i); - return true; - } - return false; -}; - - -/** - * Removes all values that satisfy the given condition. - * @param {IArrayLike<T>} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call - * for every element. This function - * takes 3 arguments (the element, the index and the array) and should - * return a boolean. - * @param {S=} opt_obj An optional "this" context for the function. - * @return {number} The number of items removed - * @template T,S - */ -goog.array.removeAllIf = function(arr, f, opt_obj) { - var removedCount = 0; - goog.array.forEachRight(arr, function(val, index) { - if (f.call(/** @type {?} */ (opt_obj), val, index, arr)) { - if (goog.array.removeAt(arr, index)) { - removedCount++; - } - } - }); - return removedCount; -}; - - -/** - * Returns a new array that is the result of joining the arguments. If arrays - * are passed then their items are added, however, if non-arrays are passed they - * will be added to the return array as is. - * - * Note that ArrayLike objects will be added as is, rather than having their - * items added. - * - * goog.array.concat([1, 2], [3, 4]) -> [1, 2, 3, 4] - * goog.array.concat(0, [1, 2]) -> [0, 1, 2] - * goog.array.concat([1, 2], null) -> [1, 2, null] - * - * There is bug in all current versions of IE (6, 7 and 8) where arrays created - * in an iframe become corrupted soon (not immediately) after the iframe is - * destroyed. This is common if loading data via goog.net.IframeIo, for example. - * This corruption only affects the concat method which will start throwing - * Catastrophic Errors (#-2147418113). - * - * See http://endoflow.com/scratch/corrupted-arrays.html for a test case. - * - * Internally goog.array should use this, so that all methods will continue to - * work on these broken array objects. - * - * @param {...*} var_args Items to concatenate. Arrays will have each item - * added, while primitives and objects will be added as is. - * @return {!Array<?>} The new resultant array. - */ -goog.array.concat = function(var_args) { - return Array.prototype.concat.apply([], arguments); -}; - - -/** - * Returns a new array that contains the contents of all the arrays passed. - * @param {...!Array<T>} var_args - * @return {!Array<T>} - * @template T - */ -goog.array.join = function(var_args) { - return Array.prototype.concat.apply([], arguments); -}; - - -/** - * Converts an object to an array. - * @param {IArrayLike<T>|string} object The object to convert to an - * array. - * @return {!Array<T>} The object converted into an array. If object has a - * length property, every property indexed with a non-negative number - * less than length will be included in the result. If object does not - * have a length property, an empty array will be returned. - * @template T - */ -goog.array.toArray = function(object) { - var length = object.length; - - // If length is not a number the following it false. This case is kept for - // backwards compatibility since there are callers that pass objects that are - // not array like. - if (length > 0) { - var rv = new Array(length); - for (var i = 0; i < length; i++) { - rv[i] = object[i]; - } - return rv; - } - return []; -}; - - -/** - * Does a shallow copy of an array. - * @param {IArrayLike<T>|string} arr Array or array-like object to - * clone. - * @return {!Array<T>} Clone of the input array. - * @template T - */ -goog.array.clone = goog.array.toArray; - - -/** - * Extends an array with another array, element, or "array like" object. - * This function operates 'in-place', it does not create a new Array. - * - * Example: - * var a = []; - * goog.array.extend(a, [0, 1]); - * a; // [0, 1] - * goog.array.extend(a, 2); - * a; // [0, 1, 2] - * - * @param {Array<VALUE>} arr1 The array to modify. - * @param {...(Array<VALUE>|VALUE)} var_args The elements or arrays of elements - * to add to arr1. - * @template VALUE - */ -goog.array.extend = function(arr1, var_args) { - for (var i = 1; i < arguments.length; i++) { - var arr2 = arguments[i]; - if (goog.isArrayLike(arr2)) { - var len1 = arr1.length || 0; - var len2 = arr2.length || 0; - arr1.length = len1 + len2; - for (var j = 0; j < len2; j++) { - arr1[len1 + j] = arr2[j]; - } - } else { - arr1.push(arr2); - } - } -}; - - -/** - * Adds or removes elements from an array. This is a generic version of Array - * splice. This means that it might work on other objects similar to arrays, - * such as the arguments object. - * - * @param {IArrayLike<T>} arr The array to modify. - * @param {number|undefined} index The index at which to start changing the - * array. If not defined, treated as 0. - * @param {number} howMany How many elements to remove (0 means no removal. A - * value below 0 is treated as zero and so is any other non number. Numbers - * are floored). - * @param {...T} var_args Optional, additional elements to insert into the - * array. - * @return {!Array<T>} the removed elements. - * @template T - */ -goog.array.splice = function(arr, index, howMany, var_args) { - goog.asserts.assert(arr.length != null); - - return Array.prototype.splice.apply(arr, goog.array.slice(arguments, 1)); -}; - - -/** - * Returns a new array from a segment of an array. This is a generic version of - * Array slice. This means that it might work on other objects similar to - * arrays, such as the arguments object. - * - * @param {IArrayLike<T>|string} arr The array from - * which to copy a segment. - * @param {number} start The index of the first element to copy. - * @param {number=} opt_end The index after the last element to copy. - * @return {!Array<T>} A new array containing the specified segment of the - * original array. - * @template T - */ -goog.array.slice = function(arr, start, opt_end) { - goog.asserts.assert(arr.length != null); - - // passing 1 arg to slice is not the same as passing 2 where the second is - // null or undefined (in that case the second argument is treated as 0). - // we could use slice on the arguments object and then use apply instead of - // testing the length - if (arguments.length <= 2) { - return Array.prototype.slice.call(arr, start); - } else { - return Array.prototype.slice.call(arr, start, opt_end); - } -}; - - -/** - * Removes all duplicates from an array (retaining only the first - * occurrence of each array element). This function modifies the - * array in place and doesn't change the order of the non-duplicate items. - * - * For objects, duplicates are identified as having the same unique ID as - * defined by {@link goog.getUid}. - * - * Alternatively you can specify a custom hash function that returns a unique - * value for each item in the array it should consider unique. - * - * Runtime: N, - * Worstcase space: 2N (no dupes) - * - * @param {IArrayLike<T>} arr The array from which to remove - * duplicates. - * @param {Array=} opt_rv An optional array in which to return the results, - * instead of performing the removal inplace. If specified, the original - * array will remain unchanged. - * @param {function(T):string=} opt_hashFn An optional function to use to - * apply to every item in the array. This function should return a unique - * value for each item in the array it should consider unique. - * @template T - */ -goog.array.removeDuplicates = function(arr, opt_rv, opt_hashFn) { - var returnArray = opt_rv || arr; - var defaultHashFn = function(item) { - // Prefix each type with a single character representing the type to - // prevent conflicting keys (e.g. true and 'true'). - return goog.isObject(item) ? 'o' + goog.getUid(item) : - (typeof item).charAt(0) + item; - }; - var hashFn = opt_hashFn || defaultHashFn; - - var seen = {}, cursorInsert = 0, cursorRead = 0; - while (cursorRead < arr.length) { - var current = arr[cursorRead++]; - var key = hashFn(current); - if (!Object.prototype.hasOwnProperty.call(seen, key)) { - seen[key] = true; - returnArray[cursorInsert++] = current; - } - } - returnArray.length = cursorInsert; -}; - - -/** - * Searches the specified array for the specified target using the binary - * search algorithm. If no opt_compareFn is specified, elements are compared - * using <code>goog.array.defaultCompare</code>, which compares the elements - * using the built in < and > operators. This will produce the expected - * behavior for homogeneous arrays of String(s) and Number(s). The array - * specified <b>must</b> be sorted in ascending order (as defined by the - * comparison function). If the array is not sorted, results are undefined. - * If the array contains multiple instances of the specified target value, any - * of these instances may be found. - * - * Runtime: O(log n) - * - * @param {IArrayLike<VALUE>} arr The array to be searched. - * @param {TARGET} target The sought value. - * @param {function(TARGET, VALUE): number=} opt_compareFn Optional comparison - * function by which the array is ordered. Should take 2 arguments to - * compare, and return a negative number, zero, or a positive number - * depending on whether the first argument is less than, equal to, or - * greater than the second. - * @return {number} Lowest index of the target value if found, otherwise - * (-(insertion point) - 1). The insertion point is where the value should - * be inserted into arr to preserve the sorted property. Return value >= 0 - * iff target is found. - * @template TARGET, VALUE - */ -goog.array.binarySearch = function(arr, target, opt_compareFn) { - return goog.array.binarySearch_( - arr, opt_compareFn || goog.array.defaultCompare, false /* isEvaluator */, - target); -}; - - -/** - * Selects an index in the specified array using the binary search algorithm. - * The evaluator receives an element and determines whether the desired index - * is before, at, or after it. The evaluator must be consistent (formally, - * goog.array.map(goog.array.map(arr, evaluator, opt_obj), goog.math.sign) - * must be monotonically non-increasing). - * - * Runtime: O(log n) - * - * @param {IArrayLike<VALUE>} arr The array to be searched. - * @param {function(this:THIS, VALUE, number, ?): number} evaluator - * Evaluator function that receives 3 arguments (the element, the index and - * the array). Should return a negative number, zero, or a positive number - * depending on whether the desired index is before, at, or after the - * element passed to it. - * @param {THIS=} opt_obj The object to be used as the value of 'this' - * within evaluator. - * @return {number} Index of the leftmost element matched by the evaluator, if - * such exists; otherwise (-(insertion point) - 1). The insertion point is - * the index of the first element for which the evaluator returns negative, - * or arr.length if no such element exists. The return value is non-negative - * iff a match is found. - * @template THIS, VALUE - */ -goog.array.binarySelect = function(arr, evaluator, opt_obj) { - return goog.array.binarySearch_( - arr, evaluator, true /* isEvaluator */, undefined /* opt_target */, - opt_obj); -}; - - -/** - * Implementation of a binary search algorithm which knows how to use both - * comparison functions and evaluators. If an evaluator is provided, will call - * the evaluator with the given optional data object, conforming to the - * interface defined in binarySelect. Otherwise, if a comparison function is - * provided, will call the comparison function against the given data object. - * - * This implementation purposefully does not use goog.bind or goog.partial for - * performance reasons. - * - * Runtime: O(log n) - * - * @param {IArrayLike<?>} arr The array to be searched. - * @param {function(?, ?, ?): number | function(?, ?): number} compareFn - * Either an evaluator or a comparison function, as defined by binarySearch - * and binarySelect above. - * @param {boolean} isEvaluator Whether the function is an evaluator or a - * comparison function. - * @param {?=} opt_target If the function is a comparison function, then - * this is the target to binary search for. - * @param {Object=} opt_selfObj If the function is an evaluator, this is an - * optional this object for the evaluator. - * @return {number} Lowest index of the target value if found, otherwise - * (-(insertion point) - 1). The insertion point is where the value should - * be inserted into arr to preserve the sorted property. Return value >= 0 - * iff target is found. - * @private - */ -goog.array.binarySearch_ = function( - arr, compareFn, isEvaluator, opt_target, opt_selfObj) { - var left = 0; // inclusive - var right = arr.length; // exclusive - var found; - while (left < right) { - var middle = (left + right) >> 1; - var compareResult; - if (isEvaluator) { - compareResult = compareFn.call(opt_selfObj, arr[middle], middle, arr); - } else { - // NOTE(dimvar): To avoid this cast, we'd have to use function overloading - // for the type of binarySearch_, which the type system can't express yet. - compareResult = /** @type {function(?, ?): number} */ (compareFn)( - opt_target, arr[middle]); - } - if (compareResult > 0) { - left = middle + 1; - } else { - right = middle; - // We are looking for the lowest index so we can't return immediately. - found = !compareResult; - } - } - // left is the index if found, or the insertion point otherwise. - // ~left is a shorthand for -left - 1. - return found ? left : ~left; -}; - - -/** - * Sorts the specified array into ascending order. If no opt_compareFn is - * specified, elements are compared using - * <code>goog.array.defaultCompare</code>, which compares the elements using - * the built in < and > operators. This will produce the expected behavior - * for homogeneous arrays of String(s) and Number(s), unlike the native sort, - * but will give unpredictable results for heterogeneous lists of strings and - * numbers with different numbers of digits. - * - * This sort is not guaranteed to be stable. - * - * Runtime: Same as <code>Array.prototype.sort</code> - * - * @param {Array<T>} arr The array to be sorted. - * @param {?function(T,T):number=} opt_compareFn Optional comparison - * function by which the - * array is to be ordered. Should take 2 arguments to compare, and return a - * negative number, zero, or a positive number depending on whether the - * first argument is less than, equal to, or greater than the second. - * @template T - */ -goog.array.sort = function(arr, opt_compareFn) { - // TODO(arv): Update type annotation since null is not accepted. - arr.sort(opt_compareFn || goog.array.defaultCompare); -}; - - -/** - * Sorts the specified array into ascending order in a stable way. If no - * opt_compareFn is specified, elements are compared using - * <code>goog.array.defaultCompare</code>, which compares the elements using - * the built in < and > operators. This will produce the expected behavior - * for homogeneous arrays of String(s) and Number(s). - * - * Runtime: Same as <code>Array.prototype.sort</code>, plus an additional - * O(n) overhead of copying the array twice. - * - * @param {Array<T>} arr The array to be sorted. - * @param {?function(T, T): number=} opt_compareFn Optional comparison function - * by which the array is to be ordered. Should take 2 arguments to compare, - * and return a negative number, zero, or a positive number depending on - * whether the first argument is less than, equal to, or greater than the - * second. - * @template T - */ -goog.array.stableSort = function(arr, opt_compareFn) { - var compArr = new Array(arr.length); - for (var i = 0; i < arr.length; i++) { - compArr[i] = {index: i, value: arr[i]}; - } - var valueCompareFn = opt_compareFn || goog.array.defaultCompare; - function stableCompareFn(obj1, obj2) { - return valueCompareFn(obj1.value, obj2.value) || obj1.index - obj2.index; - } - goog.array.sort(compArr, stableCompareFn); - for (var i = 0; i < arr.length; i++) { - arr[i] = compArr[i].value; - } -}; - - -/** - * Sort the specified array into ascending order based on item keys - * returned by the specified key function. - * If no opt_compareFn is specified, the keys are compared in ascending order - * using <code>goog.array.defaultCompare</code>. - * - * Runtime: O(S(f(n)), where S is runtime of <code>goog.array.sort</code> - * and f(n) is runtime of the key function. - * - * @param {Array<T>} arr The array to be sorted. - * @param {function(T): K} keyFn Function taking array element and returning - * a key used for sorting this element. - * @param {?function(K, K): number=} opt_compareFn Optional comparison function - * by which the keys are to be ordered. Should take 2 arguments to compare, - * and return a negative number, zero, or a positive number depending on - * whether the first argument is less than, equal to, or greater than the - * second. - * @template T,K - */ -goog.array.sortByKey = function(arr, keyFn, opt_compareFn) { - var keyCompareFn = opt_compareFn || goog.array.defaultCompare; - goog.array.sort( - arr, function(a, b) { return keyCompareFn(keyFn(a), keyFn(b)); }); -}; - - -/** - * Sorts an array of objects by the specified object key and compare - * function. If no compare function is provided, the key values are - * compared in ascending order using <code>goog.array.defaultCompare</code>. - * This won't work for keys that get renamed by the compiler. So use - * {'foo': 1, 'bar': 2} rather than {foo: 1, bar: 2}. - * @param {Array<Object>} arr An array of objects to sort. - * @param {string} key The object key to sort by. - * @param {Function=} opt_compareFn The function to use to compare key - * values. - */ -goog.array.sortObjectsByKey = function(arr, key, opt_compareFn) { - goog.array.sortByKey(arr, function(obj) { return obj[key]; }, opt_compareFn); -}; - - -/** - * Tells if the array is sorted. - * @param {!Array<T>} arr The array. - * @param {?function(T,T):number=} opt_compareFn Function to compare the - * array elements. - * Should take 2 arguments to compare, and return a negative number, zero, - * or a positive number depending on whether the first argument is less - * than, equal to, or greater than the second. - * @param {boolean=} opt_strict If true no equal elements are allowed. - * @return {boolean} Whether the array is sorted. - * @template T - */ -goog.array.isSorted = function(arr, opt_compareFn, opt_strict) { - var compare = opt_compareFn || goog.array.defaultCompare; - for (var i = 1; i < arr.length; i++) { - var compareResult = compare(arr[i - 1], arr[i]); - if (compareResult > 0 || compareResult == 0 && opt_strict) { - return false; - } - } - return true; -}; - - -/** - * Compares two arrays for equality. Two arrays are considered equal if they - * have the same length and their corresponding elements are equal according to - * the comparison function. - * - * @param {IArrayLike<?>} arr1 The first array to compare. - * @param {IArrayLike<?>} arr2 The second array to compare. - * @param {Function=} opt_equalsFn Optional comparison function. - * Should take 2 arguments to compare, and return true if the arguments - * are equal. Defaults to {@link goog.array.defaultCompareEquality} which - * compares the elements using the built-in '===' operator. - * @return {boolean} Whether the two arrays are equal. - */ -goog.array.equals = function(arr1, arr2, opt_equalsFn) { - if (!goog.isArrayLike(arr1) || !goog.isArrayLike(arr2) || - arr1.length != arr2.length) { - return false; - } - var l = arr1.length; - var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality; - for (var i = 0; i < l; i++) { - if (!equalsFn(arr1[i], arr2[i])) { - return false; - } - } - return true; -}; - - -/** - * 3-way array compare function. - * @param {!IArrayLike<VALUE>} arr1 The first array to - * compare. - * @param {!IArrayLike<VALUE>} arr2 The second array to - * compare. - * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison - * function by which the array is to be ordered. Should take 2 arguments to - * compare, and return a negative number, zero, or a positive number - * depending on whether the first argument is less than, equal to, or - * greater than the second. - * @return {number} Negative number, zero, or a positive number depending on - * whether the first argument is less than, equal to, or greater than the - * second. - * @template VALUE - */ -goog.array.compare3 = function(arr1, arr2, opt_compareFn) { - var compare = opt_compareFn || goog.array.defaultCompare; - var l = Math.min(arr1.length, arr2.length); - for (var i = 0; i < l; i++) { - var result = compare(arr1[i], arr2[i]); - if (result != 0) { - return result; - } - } - return goog.array.defaultCompare(arr1.length, arr2.length); -}; - - -/** - * Compares its two arguments for order, using the built in < and > - * operators. - * @param {VALUE} a The first object to be compared. - * @param {VALUE} b The second object to be compared. - * @return {number} A negative number, zero, or a positive number as the first - * argument is less than, equal to, or greater than the second, - * respectively. - * @template VALUE - */ -goog.array.defaultCompare = function(a, b) { - return a > b ? 1 : a < b ? -1 : 0; -}; - - -/** - * Compares its two arguments for inverse order, using the built in < and > - * operators. - * @param {VALUE} a The first object to be compared. - * @param {VALUE} b The second object to be compared. - * @return {number} A negative number, zero, or a positive number as the first - * argument is greater than, equal to, or less than the second, - * respectively. - * @template VALUE - */ -goog.array.inverseDefaultCompare = function(a, b) { - return -goog.array.defaultCompare(a, b); -}; - - -/** - * Compares its two arguments for equality, using the built in === operator. - * @param {*} a The first object to compare. - * @param {*} b The second object to compare. - * @return {boolean} True if the two arguments are equal, false otherwise. - */ -goog.array.defaultCompareEquality = function(a, b) { - return a === b; -}; - - -/** - * Inserts a value into a sorted array. The array is not modified if the - * value is already present. - * @param {IArrayLike<VALUE>} array The array to modify. - * @param {VALUE} value The object to insert. - * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison - * function by which the array is ordered. Should take 2 arguments to - * compare, and return a negative number, zero, or a positive number - * depending on whether the first argument is less than, equal to, or - * greater than the second. - * @return {boolean} True if an element was inserted. - * @template VALUE - */ -goog.array.binaryInsert = function(array, value, opt_compareFn) { - var index = goog.array.binarySearch(array, value, opt_compareFn); - if (index < 0) { - goog.array.insertAt(array, value, -(index + 1)); - return true; - } - return false; -}; - - -/** - * Removes a value from a sorted array. - * @param {!IArrayLike<VALUE>} array The array to modify. - * @param {VALUE} value The object to remove. - * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison - * function by which the array is ordered. Should take 2 arguments to - * compare, and return a negative number, zero, or a positive number - * depending on whether the first argument is less than, equal to, or - * greater than the second. - * @return {boolean} True if an element was removed. - * @template VALUE - */ -goog.array.binaryRemove = function(array, value, opt_compareFn) { - var index = goog.array.binarySearch(array, value, opt_compareFn); - return (index >= 0) ? goog.array.removeAt(array, index) : false; -}; - - -/** - * Splits an array into disjoint buckets according to a splitting function. - * @param {Array<T>} array The array. - * @param {function(this:S, T, number, !Array<T>):?} sorter Function to call for - * every element. This takes 3 arguments (the element, the index and the - * array) and must return a valid object key (a string, number, etc), or - * undefined, if that object should not be placed in a bucket. - * @param {S=} opt_obj The object to be used as the value of 'this' within - * sorter. - * @return {!Object<!Array<T>>} An object, with keys being all of the unique - * return values of sorter, and values being arrays containing the items for - * which the splitter returned that key. - * @template T,S - */ -goog.array.bucket = function(array, sorter, opt_obj) { - var buckets = {}; - - for (var i = 0; i < array.length; i++) { - var value = array[i]; - var key = sorter.call(/** @type {?} */ (opt_obj), value, i, array); - if (goog.isDef(key)) { - // Push the value to the right bucket, creating it if necessary. - var bucket = buckets[key] || (buckets[key] = []); - bucket.push(value); - } - } - - return buckets; -}; - - -/** - * Creates a new object built from the provided array and the key-generation - * function. - * @param {IArrayLike<T>} arr Array or array like object over - * which to iterate whose elements will be the values in the new object. - * @param {?function(this:S, T, number, ?) : string} keyFunc The function to - * call for every element. This function takes 3 arguments (the element, the - * index and the array) and should return a string that will be used as the - * key for the element in the new object. If the function returns the same - * key for more than one element, the value for that key is - * implementation-defined. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within keyFunc. - * @return {!Object<T>} The new object. - * @template T,S - */ -goog.array.toObject = function(arr, keyFunc, opt_obj) { - var ret = {}; - goog.array.forEach(arr, function(element, index) { - ret[keyFunc.call(/** @type {?} */ (opt_obj), element, index, arr)] = - element; - }); - return ret; -}; - - -/** - * Creates a range of numbers in an arithmetic progression. - * - * Range takes 1, 2, or 3 arguments: - * <pre> - * range(5) is the same as range(0, 5, 1) and produces [0, 1, 2, 3, 4] - * range(2, 5) is the same as range(2, 5, 1) and produces [2, 3, 4] - * range(-2, -5, -1) produces [-2, -3, -4] - * range(-2, -5, 1) produces [], since stepping by 1 wouldn't ever reach -5. - * </pre> - * - * @param {number} startOrEnd The starting value of the range if an end argument - * is provided. Otherwise, the start value is 0, and this is the end value. - * @param {number=} opt_end The optional end value of the range. - * @param {number=} opt_step The step size between range values. Defaults to 1 - * if opt_step is undefined or 0. - * @return {!Array<number>} An array of numbers for the requested range. May be - * an empty array if adding the step would not converge toward the end - * value. - */ -goog.array.range = function(startOrEnd, opt_end, opt_step) { - var array = []; - var start = 0; - var end = startOrEnd; - var step = opt_step || 1; - if (opt_end !== undefined) { - start = startOrEnd; - end = opt_end; - } - - if (step * (end - start) < 0) { - // Sign mismatch: start + step will never reach the end value. - return []; - } - - if (step > 0) { - for (var i = start; i < end; i += step) { - array.push(i); - } - } else { - for (var i = start; i > end; i += step) { - array.push(i); - } - } - return array; -}; - - -/** - * Returns an array consisting of the given value repeated N times. - * - * @param {VALUE} value The value to repeat. - * @param {number} n The repeat count. - * @return {!Array<VALUE>} An array with the repeated value. - * @template VALUE - */ -goog.array.repeat = function(value, n) { - var array = []; - for (var i = 0; i < n; i++) { - array[i] = value; - } - return array; -}; - - -/** - * Returns an array consisting of every argument with all arrays - * expanded in-place recursively. - * - * @param {...*} var_args The values to flatten. - * @return {!Array<?>} An array containing the flattened values. - */ -goog.array.flatten = function(var_args) { - var CHUNK_SIZE = 8192; - - var result = []; - for (var i = 0; i < arguments.length; i++) { - var element = arguments[i]; - if (goog.isArray(element)) { - for (var c = 0; c < element.length; c += CHUNK_SIZE) { - var chunk = goog.array.slice(element, c, c + CHUNK_SIZE); - var recurseResult = goog.array.flatten.apply(null, chunk); - for (var r = 0; r < recurseResult.length; r++) { - result.push(recurseResult[r]); - } - } - } else { - result.push(element); - } - } - return result; -}; - - -/** - * Rotates an array in-place. After calling this method, the element at - * index i will be the element previously at index (i - n) % - * array.length, for all values of i between 0 and array.length - 1, - * inclusive. - * - * For example, suppose list comprises [t, a, n, k, s]. After invoking - * rotate(array, 1) (or rotate(array, -4)), array will comprise [s, t, a, n, k]. - * - * @param {!Array<T>} array The array to rotate. - * @param {number} n The amount to rotate. - * @return {!Array<T>} The array. - * @template T - */ -goog.array.rotate = function(array, n) { - goog.asserts.assert(array.length != null); - - if (array.length) { - n %= array.length; - if (n > 0) { - Array.prototype.unshift.apply(array, array.splice(-n, n)); - } else if (n < 0) { - Array.prototype.push.apply(array, array.splice(0, -n)); - } - } - return array; -}; - - -/** - * Moves one item of an array to a new position keeping the order of the rest - * of the items. Example use case: keeping a list of JavaScript objects - * synchronized with the corresponding list of DOM elements after one of the - * elements has been dragged to a new position. - * @param {!IArrayLike<?>} arr The array to modify. - * @param {number} fromIndex Index of the item to move between 0 and - * {@code arr.length - 1}. - * @param {number} toIndex Target index between 0 and {@code arr.length - 1}. - */ -goog.array.moveItem = function(arr, fromIndex, toIndex) { - goog.asserts.assert(fromIndex >= 0 && fromIndex < arr.length); - goog.asserts.assert(toIndex >= 0 && toIndex < arr.length); - // Remove 1 item at fromIndex. - var removedItems = Array.prototype.splice.call(arr, fromIndex, 1); - // Insert the removed item at toIndex. - Array.prototype.splice.call(arr, toIndex, 0, removedItems[0]); - // We don't use goog.array.insertAt and goog.array.removeAt, because they're - // significantly slower than splice. -}; - - -/** - * Creates a new array for which the element at position i is an array of the - * ith element of the provided arrays. The returned array will only be as long - * as the shortest array provided; additional values are ignored. For example, - * the result of zipping [1, 2] and [3, 4, 5] is [[1,3], [2, 4]]. - * - * This is similar to the zip() function in Python. See {@link - * http://docs.python.org/library/functions.html#zip} - * - * @param {...!IArrayLike<?>} var_args Arrays to be combined. - * @return {!Array<!Array<?>>} A new array of arrays created from - * provided arrays. - */ -goog.array.zip = function(var_args) { - if (!arguments.length) { - return []; - } - var result = []; - var minLen = arguments[0].length; - for (var i = 1; i < arguments.length; i++) { - if (arguments[i].length < minLen) { - minLen = arguments[i].length; - } - } - for (var i = 0; i < minLen; i++) { - var value = []; - for (var j = 0; j < arguments.length; j++) { - value.push(arguments[j][i]); - } - result.push(value); - } - return result; -}; - - -/** - * Shuffles the values in the specified array using the Fisher-Yates in-place - * shuffle (also known as the Knuth Shuffle). By default, calls Math.random() - * and so resets the state of that random number generator. Similarly, may reset - * the state of the any other specified random number generator. - * - * Runtime: O(n) - * - * @param {!Array<?>} arr The array to be shuffled. - * @param {function():number=} opt_randFn Optional random function to use for - * shuffling. - * Takes no arguments, and returns a random number on the interval [0, 1). - * Defaults to Math.random() using JavaScript's built-in Math library. - */ -goog.array.shuffle = function(arr, opt_randFn) { - var randFn = opt_randFn || Math.random; - - for (var i = arr.length - 1; i > 0; i--) { - // Choose a random array index in [0, i] (inclusive with i). - var j = Math.floor(randFn() * (i + 1)); - - var tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } -}; - - -/** - * Returns a new array of elements from arr, based on the indexes of elements - * provided by index_arr. For example, the result of index copying - * ['a', 'b', 'c'] with index_arr [1,0,0,2] is ['b', 'a', 'a', 'c']. - * - * @param {!Array<T>} arr The array to get a indexed copy from. - * @param {!Array<number>} index_arr An array of indexes to get from arr. - * @return {!Array<T>} A new array of elements from arr in index_arr order. - * @template T - */ -goog.array.copyByIndex = function(arr, index_arr) { - var result = []; - goog.array.forEach(index_arr, function(index) { result.push(arr[index]); }); - return result; -}; - - -/** - * Maps each element of the input array into zero or more elements of the output - * array. - * - * @param {!IArrayLike<VALUE>|string} arr Array or array like object - * over which to iterate. - * @param {function(this:THIS, VALUE, number, ?): !Array<RESULT>} f The function - * to call for every element. This function takes 3 arguments (the element, - * the index and the array) and should return an array. The result will be - * used to extend a new array. - * @param {THIS=} opt_obj The object to be used as the value of 'this' within f. - * @return {!Array<RESULT>} a new array with the concatenation of all arrays - * returned from f. - * @template THIS, VALUE, RESULT - */ -goog.array.concatMap = function(arr, f, opt_obj) { - return goog.array.concat.apply([], goog.array.map(arr, f, opt_obj)); -};
diff --git a/third_party/ink/closure/asserts/asserts.js b/third_party/ink/closure/asserts/asserts.js deleted file mode 100644 index 89cad0a..0000000 --- a/third_party/ink/closure/asserts/asserts.js +++ /dev/null
@@ -1,391 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities to check the preconditions, postconditions and - * invariants runtime. - * - * Methods in this package should be given special treatment by the compiler - * for type-inference. For example, <code>goog.asserts.assert(foo)</code> - * will restrict <code>foo</code> to a truthy value. - * - * The compiler has an option to disable asserts. So code like: - * <code> - * var x = goog.asserts.assert(foo()); goog.asserts.assert(bar()); - * </code> - * will be transformed into: - * <code> - * var x = foo(); - * </code> - * The compiler will leave in foo() (because its return value is used), - * but it will remove bar() because it assumes it does not have side-effects. - * - * @author pallosp@google.com (Peter Pallos) - * @author agrieve@google.com (Andrew Grieve) - */ - -goog.provide('goog.asserts'); -goog.provide('goog.asserts.AssertionError'); - -goog.require('goog.debug.Error'); -goog.require('goog.dom.NodeType'); -goog.require('goog.string'); - - -/** - * @define {boolean} Whether to strip out asserts or to leave them in. - */ -goog.define('goog.asserts.ENABLE_ASSERTS', goog.DEBUG); - - - -/** - * Error object for failed assertions. - * @param {string} messagePattern The pattern that was used to form message. - * @param {!Array<*>} messageArgs The items to substitute into the pattern. - * @constructor - * @extends {goog.debug.Error} - * @final - */ -goog.asserts.AssertionError = function(messagePattern, messageArgs) { - messageArgs.unshift(messagePattern); - goog.debug.Error.call(this, goog.string.subs.apply(null, messageArgs)); - // Remove the messagePattern afterwards to avoid permanently modifying the - // passed in array. - messageArgs.shift(); - - /** - * The message pattern used to format the error message. Error handlers can - * use this to uniquely identify the assertion. - * @type {string} - */ - this.messagePattern = messagePattern; -}; -goog.inherits(goog.asserts.AssertionError, goog.debug.Error); - - -/** @override */ -goog.asserts.AssertionError.prototype.name = 'AssertionError'; - - -/** - * The default error handler. - * @param {!goog.asserts.AssertionError} e The exception to be handled. - */ -goog.asserts.DEFAULT_ERROR_HANDLER = function(e) { - throw e; -}; - - -/** - * The handler responsible for throwing or logging assertion errors. - * @private {function(!goog.asserts.AssertionError)} - */ -goog.asserts.errorHandler_ = goog.asserts.DEFAULT_ERROR_HANDLER; - - -/** - * Throws an exception with the given message and "Assertion failed" prefixed - * onto it. - * @param {string} defaultMessage The message to use if givenMessage is empty. - * @param {Array<*>} defaultArgs The substitution arguments for defaultMessage. - * @param {string|undefined} givenMessage Message supplied by the caller. - * @param {Array<*>} givenArgs The substitution arguments for givenMessage. - * @throws {goog.asserts.AssertionError} When the value is not a number. - * @private - */ -goog.asserts.doAssertFailure_ = function( - defaultMessage, defaultArgs, givenMessage, givenArgs) { - var message = 'Assertion failed'; - if (givenMessage) { - message += ': ' + givenMessage; - var args = givenArgs; - } else if (defaultMessage) { - message += ': ' + defaultMessage; - args = defaultArgs; - } - // The '' + works around an Opera 10 bug in the unit tests. Without it, - // a stack trace is added to var message above. With this, a stack trace is - // not added until this line (it causes the extra garbage to be added after - // the assertion message instead of in the middle of it). - var e = new goog.asserts.AssertionError('' + message, args || []); - goog.asserts.errorHandler_(e); -}; - - -/** - * Sets a custom error handler that can be used to customize the behavior of - * assertion failures, for example by turning all assertion failures into log - * messages. - * @param {function(!goog.asserts.AssertionError)} errorHandler - */ -goog.asserts.setErrorHandler = function(errorHandler) { - if (goog.asserts.ENABLE_ASSERTS) { - goog.asserts.errorHandler_ = errorHandler; - } -}; - - -/** - * Checks if the condition evaluates to true if goog.asserts.ENABLE_ASSERTS is - * true. - * @template T - * @param {T} condition The condition to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {T} The value of the condition. - * @throws {goog.asserts.AssertionError} When the condition evaluates to false. - */ -goog.asserts.assert = function(condition, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !condition) { - goog.asserts.doAssertFailure_( - '', null, opt_message, Array.prototype.slice.call(arguments, 2)); - } - return condition; -}; - - -/** - * Fails if goog.asserts.ENABLE_ASSERTS is true. This function is useful in case - * when we want to add a check in the unreachable area like switch-case - * statement: - * - * <pre> - * switch(type) { - * case FOO: doSomething(); break; - * case BAR: doSomethingElse(); break; - * default: goog.asserts.fail('Unrecognized type: ' + type); - * // We have only 2 types - "default:" section is unreachable code. - * } - * </pre> - * - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @throws {goog.asserts.AssertionError} Failure. - */ -goog.asserts.fail = function(opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS) { - goog.asserts.errorHandler_( - new goog.asserts.AssertionError( - 'Failure' + (opt_message ? ': ' + opt_message : ''), - Array.prototype.slice.call(arguments, 1))); - } -}; - - -/** - * Checks if the value is a number if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {number} The value, guaranteed to be a number when asserts enabled. - * @throws {goog.asserts.AssertionError} When the value is not a number. - */ -goog.asserts.assertNumber = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !goog.isNumber(value)) { - goog.asserts.doAssertFailure_( - 'Expected number but got %s: %s.', [goog.typeOf(value), value], - opt_message, Array.prototype.slice.call(arguments, 2)); - } - return /** @type {number} */ (value); -}; - - -/** - * Checks if the value is a string if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {string} The value, guaranteed to be a string when asserts enabled. - * @throws {goog.asserts.AssertionError} When the value is not a string. - */ -goog.asserts.assertString = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !goog.isString(value)) { - goog.asserts.doAssertFailure_( - 'Expected string but got %s: %s.', [goog.typeOf(value), value], - opt_message, Array.prototype.slice.call(arguments, 2)); - } - return /** @type {string} */ (value); -}; - - -/** - * Checks if the value is a function if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {!Function} The value, guaranteed to be a function when asserts - * enabled. - * @throws {goog.asserts.AssertionError} When the value is not a function. - */ -goog.asserts.assertFunction = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !goog.isFunction(value)) { - goog.asserts.doAssertFailure_( - 'Expected function but got %s: %s.', [goog.typeOf(value), value], - opt_message, Array.prototype.slice.call(arguments, 2)); - } - return /** @type {!Function} */ (value); -}; - - -/** - * Checks if the value is an Object if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {!Object} The value, guaranteed to be a non-null object. - * @throws {goog.asserts.AssertionError} When the value is not an object. - */ -goog.asserts.assertObject = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !goog.isObject(value)) { - goog.asserts.doAssertFailure_( - 'Expected object but got %s: %s.', [goog.typeOf(value), value], - opt_message, Array.prototype.slice.call(arguments, 2)); - } - return /** @type {!Object} */ (value); -}; - - -/** - * Checks if the value is an Array if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {!Array<?>} The value, guaranteed to be a non-null array. - * @throws {goog.asserts.AssertionError} When the value is not an array. - */ -goog.asserts.assertArray = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !goog.isArray(value)) { - goog.asserts.doAssertFailure_( - 'Expected array but got %s: %s.', [goog.typeOf(value), value], - opt_message, Array.prototype.slice.call(arguments, 2)); - } - return /** @type {!Array<?>} */ (value); -}; - - -/** - * Checks if the value is a boolean if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {boolean} The value, guaranteed to be a boolean when asserts are - * enabled. - * @throws {goog.asserts.AssertionError} When the value is not a boolean. - */ -goog.asserts.assertBoolean = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !goog.isBoolean(value)) { - goog.asserts.doAssertFailure_( - 'Expected boolean but got %s: %s.', [goog.typeOf(value), value], - opt_message, Array.prototype.slice.call(arguments, 2)); - } - return /** @type {boolean} */ (value); -}; - - -/** - * Checks if the value is a DOM Element if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {!Element} The value, likely to be a DOM Element when asserts are - * enabled. - * @throws {goog.asserts.AssertionError} When the value is not an Element. - */ -goog.asserts.assertElement = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && - (!goog.isObject(value) || value.nodeType != goog.dom.NodeType.ELEMENT)) { - goog.asserts.doAssertFailure_( - 'Expected Element but got %s: %s.', [goog.typeOf(value), value], - opt_message, Array.prototype.slice.call(arguments, 2)); - } - return /** @type {!Element} */ (value); -}; - - -/** - * Checks if the value is an instance of the user-defined type if - * goog.asserts.ENABLE_ASSERTS is true. - * - * The compiler may tighten the type returned by this function. - * - * @param {?} value The value to check. - * @param {function(new: T, ...)} type A user-defined constructor. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @throws {goog.asserts.AssertionError} When the value is not an instance of - * type. - * @return {T} - * @template T - */ -goog.asserts.assertInstanceof = function(value, type, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !(value instanceof type)) { - goog.asserts.doAssertFailure_( - 'Expected instanceof %s but got %s.', - [goog.asserts.getType_(type), goog.asserts.getType_(value)], - opt_message, Array.prototype.slice.call(arguments, 3)); - } - return value; -}; - - -/** - * Checks whether the value is a finite number, if goog.asserts.ENABLE_ASSERTS - * is true. - * - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @throws {goog.asserts.AssertionError} When the value is not a number, or is - * a non-finite number such as NaN, Infinity or -Infinity. - * @return {number} The value initially passed in. - */ -goog.asserts.assertFinite = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && - (typeof value != 'number' || !isFinite(value))) { - goog.asserts.doAssertFailure_( - 'Expected %s to be a finite number but it is not.', [value], - opt_message, Array.prototype.slice.call(arguments, 2)); - } - return /** @type {number} */ (value); -}; - -/** - * Checks that no enumerable keys are present in Object.prototype. Such keys - * would break most code that use {@code for (var ... in ...)} loops. - */ -goog.asserts.assertObjectPrototypeIsIntact = function() { - for (var key in Object.prototype) { - goog.asserts.fail(key + ' should not be enumerable in Object.prototype.'); - } -}; - - -/** - * Returns the type of a value. If a constructor is passed, and a suitable - * string cannot be found, 'unknown type name' will be returned. - * @param {*} value A constructor, object, or primitive. - * @return {string} The best display name for the value, or 'unknown type name'. - * @private - */ -goog.asserts.getType_ = function(value) { - if (value instanceof Function) { - return value.displayName || value.name || 'unknown type name'; - } else if (value instanceof Object) { - return value.constructor.displayName || value.constructor.name || - Object.prototype.toString.call(value); - } else { - return value === null ? 'null' : typeof value; - } -};
diff --git a/third_party/ink/closure/base.js b/third_party/ink/closure/base.js deleted file mode 100644 index 4d46cd7..0000000 --- a/third_party/ink/closure/base.js +++ /dev/null
@@ -1,2962 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Bootstrap for the Google JS Library (Closure). - * - * In uncompiled mode base.js will attempt to load Closure's deps file, unless - * the global <code>CLOSURE_NO_DEPS</code> is set to true. This allows projects - * to include their own deps file(s) from different locations. - * - * Avoid including base.js more than once. This is strictly discouraged and not - * supported. goog.require(...) won't work properly in that case. - * - * @provideGoog - */ - - -/** - * @define {boolean} Overridden to true by the compiler. - */ -var COMPILED = false; - - -/** - * Base namespace for the Closure library. Checks to see goog is already - * defined in the current scope before assigning to prevent clobbering if - * base.js is loaded more than once. - * - * @const - */ -var goog = goog || {}; - - -/** - * Reference to the global context. In most cases this will be 'window'. - */ -goog.global = this; - - -/** - * A hook for overriding the define values in uncompiled mode. - * - * In uncompiled mode, {@code CLOSURE_UNCOMPILED_DEFINES} may be defined before - * loading base.js. If a key is defined in {@code CLOSURE_UNCOMPILED_DEFINES}, - * {@code goog.define} will use the value instead of the default value. This - * allows flags to be overwritten without compilation (this is normally - * accomplished with the compiler's "define" flag). - * - * Example: - * <pre> - * var CLOSURE_UNCOMPILED_DEFINES = {'goog.DEBUG': false}; - * </pre> - * - * @type {Object<string, (string|number|boolean)>|undefined} - */ -goog.global.CLOSURE_UNCOMPILED_DEFINES; - - -/** - * A hook for overriding the define values in uncompiled or compiled mode, - * like CLOSURE_UNCOMPILED_DEFINES but effective in compiled code. In - * uncompiled code CLOSURE_UNCOMPILED_DEFINES takes precedence. - * - * Also unlike CLOSURE_UNCOMPILED_DEFINES the values must be number, boolean or - * string literals or the compiler will emit an error. - * - * While any @define value may be set, only those set with goog.define will be - * effective for uncompiled code. - * - * Example: - * <pre> - * var CLOSURE_DEFINES = {'goog.DEBUG': false} ; - * </pre> - * - * @type {Object<string, (string|number|boolean)>|undefined} - */ -goog.global.CLOSURE_DEFINES; - - -/** - * Returns true if the specified value is not undefined. - * - * @param {?} val Variable to test. - * @return {boolean} Whether variable is defined. - */ -goog.isDef = function(val) { - // void 0 always evaluates to undefined and hence we do not need to depend on - // the definition of the global variable named 'undefined'. - return val !== void 0; -}; - -/** - * Returns true if the specified value is a string. - * @param {?} val Variable to test. - * @return {boolean} Whether variable is a string. - */ -goog.isString = function(val) { - return typeof val == 'string'; -}; - - -/** - * Returns true if the specified value is a boolean. - * @param {?} val Variable to test. - * @return {boolean} Whether variable is boolean. - */ -goog.isBoolean = function(val) { - return typeof val == 'boolean'; -}; - - -/** - * Returns true if the specified value is a number. - * @param {?} val Variable to test. - * @return {boolean} Whether variable is a number. - */ -goog.isNumber = function(val) { - return typeof val == 'number'; -}; - - -/** - * Builds an object structure for the provided namespace path, ensuring that - * names that already exist are not overwritten. For example: - * "a.b.c" -> a = {};a.b={};a.b.c={}; - * Used by goog.provide and goog.exportSymbol. - * @param {string} name name of the object that this file defines. - * @param {*=} opt_object the object to expose at the end of the path. - * @param {Object=} opt_objectToExportTo The object to add the path to; default - * is `goog.global`. - * @private - */ -goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) { - var parts = name.split('.'); - var cur = opt_objectToExportTo || goog.global; - - // Internet Explorer exhibits strange behavior when throwing errors from - // methods externed in this manner. See the testExportSymbolExceptions in - // base_test.html for an example. - if (!(parts[0] in cur) && cur.execScript) { - cur.execScript('var ' + parts[0]); - } - - for (var part; parts.length && (part = parts.shift());) { - if (!parts.length && goog.isDef(opt_object)) { - // last part and we have an object; use it - cur[part] = opt_object; - } else if (cur[part] && cur[part] !== Object.prototype[part]) { - cur = cur[part]; - } else { - cur = cur[part] = {}; - } - } -}; - - -/** - * Defines a named value. In uncompiled mode, the value is retrieved from - * CLOSURE_DEFINES or CLOSURE_UNCOMPILED_DEFINES if the object is defined and - * has the property specified, and otherwise used the defined defaultValue. - * When compiled the default can be overridden using the compiler - * options or the value set in the CLOSURE_DEFINES object. - * - * @param {string} name The distinguished name to provide. - * @param {string|number|boolean} defaultValue - */ -goog.define = function(name, defaultValue) { - var value = defaultValue; - if (!COMPILED) { - if (goog.global.CLOSURE_UNCOMPILED_DEFINES && - // Anti DOM-clobbering runtime check (b/37736576). - /** @type {?} */ (goog.global.CLOSURE_UNCOMPILED_DEFINES).nodeType === - undefined && - Object.prototype.hasOwnProperty.call( - goog.global.CLOSURE_UNCOMPILED_DEFINES, name)) { - value = goog.global.CLOSURE_UNCOMPILED_DEFINES[name]; - } else if ( - goog.global.CLOSURE_DEFINES && - // Anti DOM-clobbering runtime check (b/37736576). - /** @type {?} */ (goog.global.CLOSURE_DEFINES).nodeType === undefined && - Object.prototype.hasOwnProperty.call( - goog.global.CLOSURE_DEFINES, name)) { - value = goog.global.CLOSURE_DEFINES[name]; - } - } - goog.exportPath_(name, value); -}; - - -/** - * @define {boolean} DEBUG is provided as a convenience so that debugging code - * that should not be included in a production. It can be easily stripped - * by specifying --define goog.DEBUG=false to the Closure Compiler aka - * JSCompiler. For example, most toString() methods should be declared inside an - * "if (goog.DEBUG)" conditional because they are generally used for debugging - * purposes and it is difficult for the JSCompiler to statically determine - * whether they are used. - */ -goog.define('goog.DEBUG', true); - - -/** - * @define {string} LOCALE defines the locale being used for compilation. It is - * used to select locale specific data to be compiled in js binary. BUILD rule - * can specify this value by "--define goog.LOCALE=<locale_name>" as a compiler - * option. - * - * Take into account that the locale code format is important. You should use - * the canonical Unicode format with hyphen as a delimiter. Language must be - * lowercase, Language Script - Capitalized, Region - UPPERCASE. - * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN. - * - * See more info about locale codes here: - * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers - * - * For language codes you should use values defined by ISO 693-1. See it here - * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from - * this rule: the Hebrew language. For legacy reasons the old code (iw) should - * be used instead of the new code (he). - * - * MOE:begin_intracomment_strip - * See http://g3doc/i18n/identifiers/g3doc/synonyms. - * MOE:end_intracomment_strip - */ -goog.define('goog.LOCALE', 'en'); // default to en - - -/** - * @define {boolean} Whether this code is running on trusted sites. - * - * On untrusted sites, several native functions can be defined or overridden by - * external libraries like Prototype, Datejs, and JQuery and setting this flag - * to false forces closure to use its own implementations when possible. - * - * If your JavaScript can be loaded by a third party site and you are wary about - * relying on non-standard implementations, specify - * "--define goog.TRUSTED_SITE=false" to the compiler. - */ -goog.define('goog.TRUSTED_SITE', true); - - -/** - * @define {boolean} Whether a project is expected to be running in strict mode. - * - * This define can be used to trigger alternate implementations compatible with - * running in EcmaScript Strict mode or warn about unavailable functionality. - * @see https://goo.gl/PudQ4y - * - */ -goog.define('goog.STRICT_MODE_COMPATIBLE', false); - - -/** - * @define {boolean} Whether code that calls {@link goog.setTestOnly} should - * be disallowed in the compilation unit. - */ -goog.define('goog.DISALLOW_TEST_ONLY_CODE', COMPILED && !goog.DEBUG); - - -/** - * @define {boolean} Whether to use a Chrome app CSP-compliant method for - * loading scripts via goog.require. @see appendScriptSrcNode_. - */ -goog.define('goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING', false); - - -/** - * Defines a namespace in Closure. - * - * A namespace may only be defined once in a codebase. It may be defined using - * goog.provide() or goog.module(). - * - * The presence of one or more goog.provide() calls in a file indicates - * that the file defines the given objects/namespaces. - * Provided symbols must not be null or undefined. - * - * In addition, goog.provide() creates the object stubs for a namespace - * (for example, goog.provide("goog.foo.bar") will create the object - * goog.foo.bar if it does not already exist). - * - * Build tools also scan for provide/require/module statements - * to discern dependencies, build dependency files (see deps.js), etc. - * - * @see goog.require - * @see goog.module - * @param {string} name Namespace provided by this file in the form - * "goog.package.part". - */ -goog.provide = function(name) { - if (goog.isInModuleLoader_()) { - throw new Error('goog.provide can not be used within a goog.module.'); - } - if (!COMPILED) { - // Ensure that the same namespace isn't provided twice. - // A goog.module/goog.provide maps a goog.require to a specific file - if (goog.isProvided_(name)) { - throw new Error('Namespace "' + name + '" already declared.'); - } - } - - goog.constructNamespace_(name); -}; - - -/** - * @param {string} name Namespace provided by this file in the form - * "goog.package.part". - * @param {Object=} opt_obj The object to embed in the namespace. - * @private - */ -goog.constructNamespace_ = function(name, opt_obj) { - if (!COMPILED) { - delete goog.implicitNamespaces_[name]; - - var namespace = name; - while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) { - if (goog.getObjectByName(namespace)) { - break; - } - goog.implicitNamespaces_[namespace] = true; - } - } - - goog.exportPath_(name, opt_obj); -}; - - -/** - * Module identifier validation regexp. - * Note: This is a conservative check, it is very possible to be more lenient, - * the primary exclusion here is "/" and "\" and a leading ".", these - * restrictions are intended to leave the door open for using goog.require - * with relative file paths rather than module identifiers. - * @private - */ -goog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/; - - -/** - * Defines a module in Closure. - * - * Marks that this file must be loaded as a module and claims the namespace. - * - * A namespace may only be defined once in a codebase. It may be defined using - * goog.provide() or goog.module(). - * - * goog.module() has three requirements: - * - goog.module may not be used in the same file as goog.provide. - * - goog.module must be the first statement in the file. - * - only one goog.module is allowed per file. - * - * When a goog.module annotated file is loaded, it is enclosed in - * a strict function closure. This means that: - * - any variables declared in a goog.module file are private to the file - * (not global), though the compiler is expected to inline the module. - * - The code must obey all the rules of "strict" JavaScript. - * - the file will be marked as "use strict" - * - * NOTE: unlike goog.provide, goog.module does not declare any symbols by - * itself. If declared symbols are desired, use - * goog.module.declareLegacyNamespace(). - * - * MOE:begin_intracomment_strip - * See the goog.module announcement at http://go/goog.module-announce - * MOE:end_intracomment_strip - * - * See the public goog.module proposal: http://goo.gl/Va1hin - * - * @param {string} name Namespace provided by this file in the form - * "goog.package.part", is expected but not required. - * @return {void} - */ -goog.module = function(name) { - if (!goog.isString(name) || !name || - name.search(goog.VALID_MODULE_RE_) == -1) { - throw new Error('Invalid module identifier'); - } - if (!goog.isInModuleLoader_()) { - throw new Error( - 'Module ' + name + ' has been loaded incorrectly. Note, ' + - 'modules cannot be loaded as normal scripts. They require some kind of ' + - 'pre-processing step. You\'re likely trying to load a module via a ' + - 'script tag or as a part of a concatenated bundle without rewriting the ' + - 'module. For more info see: ' + - 'https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide.'); - } - if (goog.moduleLoaderState_.moduleName) { - throw new Error('goog.module may only be called once per module.'); - } - - // Store the module name for the loader. - goog.moduleLoaderState_.moduleName = name; - if (!COMPILED) { - // Ensure that the same namespace isn't provided twice. - // A goog.module/goog.provide maps a goog.require to a specific file - if (goog.isProvided_(name)) { - throw new Error('Namespace "' + name + '" already declared.'); - } - delete goog.implicitNamespaces_[name]; - } -}; - - -/** - * @param {string} name The module identifier. - * @return {?} The module exports for an already loaded module or null. - * - * Note: This is not an alternative to goog.require, it does not - * indicate a hard dependency, instead it is used to indicate - * an optional dependency or to access the exports of a module - * that has already been loaded. - * @suppress {missingProvide} - */ -goog.module.get = function(name) { - return goog.module.getInternal_(name); -}; - - -/** - * @param {string} name The module identifier. - * @return {?} The module exports for an already loaded module or null. - * @private - */ -goog.module.getInternal_ = function(name) { - if (!COMPILED) { - if (name in goog.loadedModules_) { - return goog.loadedModules_[name]; - } else if (!goog.implicitNamespaces_[name]) { - var ns = goog.getObjectByName(name); - return ns != null ? ns : null; - } - } - return null; -}; - - -/** - * @private {?{moduleName: (string|undefined), declareLegacyNamespace:boolean}} - */ -goog.moduleLoaderState_ = null; - - -/** - * @private - * @return {boolean} Whether a goog.module is currently being initialized. - */ -goog.isInModuleLoader_ = function() { - return goog.moduleLoaderState_ != null; -}; - - -/** - * Provide the module's exports as a globally accessible object under the - * module's declared name. This is intended to ease migration to goog.module - * for files that have existing usages. - * @suppress {missingProvide} - */ -goog.module.declareLegacyNamespace = function() { - if (!COMPILED && !goog.isInModuleLoader_()) { - throw new Error( - 'goog.module.declareLegacyNamespace must be called from ' + - 'within a goog.module'); - } - if (!COMPILED && !goog.moduleLoaderState_.moduleName) { - throw new Error( - 'goog.module must be called prior to ' + - 'goog.module.declareLegacyNamespace.'); - } - goog.moduleLoaderState_.declareLegacyNamespace = true; -}; - - -/** - * Marks that the current file should only be used for testing, and never for - * live code in production. - * - * In the case of unit tests, the message may optionally be an exact namespace - * for the test (e.g. 'goog.stringTest'). The linter will then ignore the extra - * provide (if not explicitly defined in the code). - * - * @param {string=} opt_message Optional message to add to the error that's - * raised when used in production code. - */ -goog.setTestOnly = function(opt_message) { - if (goog.DISALLOW_TEST_ONLY_CODE) { - opt_message = opt_message || ''; - throw new Error( - 'Importing test-only code into non-debug environment' + - (opt_message ? ': ' + opt_message : '.')); - } -}; - - -/** - * Forward declares a symbol. This is an indication to the compiler that the - * symbol may be used in the source yet is not required and may not be provided - * in compilation. - * - * The most common usage of forward declaration is code that takes a type as a - * function parameter but does not need to require it. By forward declaring - * instead of requiring, no hard dependency is made, and (if not required - * elsewhere) the namespace may never be required and thus, not be pulled - * into the JavaScript binary. If it is required elsewhere, it will be type - * checked as normal. - * - * Before using goog.forwardDeclare, please read the documentation at - * https://github.com/google/closure-compiler/wiki/Bad-Type-Annotation to - * understand the options and tradeoffs when working with forward declarations. - * - * @param {string} name The namespace to forward declare in the form of - * "goog.package.part". - */ -goog.forwardDeclare = function(name) {}; - - -/** - * Forward declare type information. Used to assign types to goog.global - * referenced object that would otherwise result in unknown type references - * and thus block property disambiguation. - */ -goog.forwardDeclare('Document'); -goog.forwardDeclare('HTMLScriptElement'); -goog.forwardDeclare('XMLHttpRequest'); - - -if (!COMPILED) { - /** - * Check if the given name has been goog.provided. This will return false for - * names that are available only as implicit namespaces. - * @param {string} name name of the object to look for. - * @return {boolean} Whether the name has been provided. - * @private - */ - goog.isProvided_ = function(name) { - return (name in goog.loadedModules_) || - (!goog.implicitNamespaces_[name] && - goog.isDefAndNotNull(goog.getObjectByName(name))); - }; - - /** - * Namespaces implicitly defined by goog.provide. For example, - * goog.provide('goog.events.Event') implicitly declares that 'goog' and - * 'goog.events' must be namespaces. - * - * @type {!Object<string, (boolean|undefined)>} - * @private - */ - goog.implicitNamespaces_ = {'goog.module': true}; - - // NOTE: We add goog.module as an implicit namespace as goog.module is defined - // here and because the existing module package has not been moved yet out of - // the goog.module namespace. This satisifies both the debug loader and - // ahead-of-time dependency management. -} - - -/** - * Returns an object based on its fully qualified external name. The object - * is not found if null or undefined. If you are using a compilation pass that - * renames property names beware that using this function will not find renamed - * properties. - * - * @param {string} name The fully qualified name. - * @param {Object=} opt_obj The object within which to look; default is - * |goog.global|. - * @return {?} The value (object or primitive) or, if not found, null. - */ -goog.getObjectByName = function(name, opt_obj) { - var parts = name.split('.'); - var cur = opt_obj || goog.global; - for (var i = 0; i < parts.length; i++) { - cur = cur[parts[i]]; - if (!goog.isDefAndNotNull(cur)) { - return null; - } - } - return cur; -}; - - -/** - * Globalizes a whole namespace, such as goog or goog.lang. - * - * @param {!Object} obj The namespace to globalize. - * @param {Object=} opt_global The object to add the properties to. - * @deprecated Properties may be explicitly exported to the global scope, but - * this should no longer be done in bulk. - */ -goog.globalize = function(obj, opt_global) { - var global = opt_global || goog.global; - for (var x in obj) { - global[x] = obj[x]; - } -}; - - -/** - * Adds a dependency from a file to the files it requires. - * @param {string} relPath The path to the js file. - * @param {!Array<string>} provides An array of strings with - * the names of the objects this file provides. - * @param {!Array<string>} requires An array of strings with - * the names of the objects this file requires. - * @param {boolean|!Object<string>=} opt_loadFlags Parameters indicating - * how the file must be loaded. The boolean 'true' is equivalent - * to {'module': 'goog'} for backwards-compatibility. Valid properties - * and values include {'module': 'goog'} and {'lang': 'es6'}. - */ -goog.addDependency = function(relPath, provides, requires, opt_loadFlags) { - if (goog.DEPENDENCIES_ENABLED) { - var provide, require; - var path = relPath.replace(/\\/g, '/'); - var deps = goog.dependencies_; - if (!opt_loadFlags || typeof opt_loadFlags === 'boolean') { - opt_loadFlags = opt_loadFlags ? {'module': 'goog'} : {}; - } - for (var i = 0; provide = provides[i]; i++) { - deps.nameToPath[provide] = path; - deps.loadFlags[path] = opt_loadFlags; - } - for (var j = 0; require = requires[j]; j++) { - if (!(path in deps.requires)) { - deps.requires[path] = {}; - } - deps.requires[path][require] = true; - } - } -}; - - -// MOE:begin_strip -/** - * Whether goog.require should throw an exception if it fails. - * @type {boolean} - */ -goog.useStrictRequires = false; - - -// MOE:end_strip - - -// NOTE(nnaze): The debug DOM loader was included in base.js as an original way -// to do "debug-mode" development. The dependency system can sometimes be -// confusing, as can the debug DOM loader's asynchronous nature. -// -// With the DOM loader, a call to goog.require() is not blocking -- the script -// will not load until some point after the current script. If a namespace is -// needed at runtime, it needs to be defined in a previous script, or loaded via -// require() with its registered dependencies. -// -// User-defined namespaces may need their own deps file. For a reference on -// creating a deps file, see: -// MOE:begin_strip -// Internally: http://go/deps-files and http://go/be#js_deps -// MOE:end_strip -// Externally: https://developers.google.com/closure/library/docs/depswriter -// -// Because of legacy clients, the DOM loader can't be easily removed from -// base.js. Work was done to make it disableable or replaceable for -// different environments (DOM-less JavaScript interpreters like Rhino or V8, -// for example). See bootstrap/ for more information. - - -/** - * @define {boolean} Whether to enable the debug loader. - * - * If enabled, a call to goog.require() will attempt to load the namespace by - * appending a script tag to the DOM (if the namespace has been registered). - * - * If disabled, goog.require() will simply assert that the namespace has been - * provided (and depend on the fact that some outside tool correctly ordered - * the script). - */ -goog.define('goog.ENABLE_DEBUG_LOADER', true); - - -/** - * @param {string} msg - * @private - */ -goog.logToConsole_ = function(msg) { - if (goog.global.console) { - goog.global.console['error'](msg); - } -}; - - -/** - * Implements a system for the dynamic resolution of dependencies that works in - * parallel with the BUILD system. Note that all calls to goog.require will be - * stripped by the compiler. - * @see goog.provide - * @param {string} name Namespace to include (as was given in goog.provide()) in - * the form "goog.package.part". - * @return {?} If called within a goog.module file, the associated namespace or - * module otherwise null. - */ -goog.require = function(name) { - // If the object already exists we do not need to do anything. - if (!COMPILED) { - if (goog.ENABLE_DEBUG_LOADER && goog.IS_OLD_IE_) { - goog.maybeProcessDeferredDep_(name); - } - - if (goog.isProvided_(name)) { - if (goog.isInModuleLoader_()) { - return goog.module.getInternal_(name); - } - } else if (goog.ENABLE_DEBUG_LOADER) { - var path = goog.getPathFromDeps_(name); - if (path) { - goog.writeScripts_(path); - } else { - var errorMessage = 'goog.require could not find: ' + name; - goog.logToConsole_(errorMessage); - - // MOE:begin_strip - - // NOTE(nicksantos): We could always throw an error, but this would - // break legacy users that depended on this failing silently. Instead, - // the compiler should warn us when there are invalid goog.require - // calls. For now, we simply give clients a way to turn strict mode on. - if (goog.useStrictRequires) { - throw new Error(errorMessage); - } - - // In external Closure, always error. - // MOE:end_strip_and_replace throw new Error(errorMessage); - } - } - - return null; - } -}; - - -/** - * Path for included scripts. - * @type {string} - */ -goog.basePath = ''; - - -/** - * A hook for overriding the base path. - * @type {string|undefined} - */ -goog.global.CLOSURE_BASE_PATH; - - -/** - * Whether to attempt to load Closure's deps file. By default, when uncompiled, - * deps files will attempt to be loaded. - * @type {boolean|undefined} - */ -goog.global.CLOSURE_NO_DEPS; - - -/** - * A function to import a single script. This is meant to be overridden when - * Closure is being run in non-HTML contexts, such as web workers. It's defined - * in the global scope so that it can be set before base.js is loaded, which - * allows deps.js to be imported properly. - * - * The function is passed the script source, which is a relative URI. It should - * return true if the script was imported, false otherwise. - * @type {(function(string): boolean)|undefined} - */ -goog.global.CLOSURE_IMPORT_SCRIPT; - - -/** - * Null function used for default values of callbacks, etc. - * @return {void} Nothing. - */ -goog.nullFunction = function() {}; - - -/** - * When defining a class Foo with an abstract method bar(), you can do: - * Foo.prototype.bar = goog.abstractMethod - * - * Now if a subclass of Foo fails to override bar(), an error will be thrown - * when bar() is invoked. - * - * @type {!Function} - * @throws {Error} when invoked to indicate the method should be overridden. - */ -goog.abstractMethod = function() { - throw new Error('unimplemented abstract method'); -}; - - -/** - * Adds a {@code getInstance} static method that always returns the same - * instance object. - * @param {!Function} ctor The constructor for the class to add the static - * method to. - */ -goog.addSingletonGetter = function(ctor) { - // instance_ is immediately set to prevent issues with sealed constructors - // such as are encountered when a constructor is returned as the export object - // of a goog.module in unoptimized code. - ctor.instance_ = undefined; - ctor.getInstance = function() { - if (ctor.instance_) { - return ctor.instance_; - } - if (goog.DEBUG) { - // NOTE: JSCompiler can't optimize away Array#push. - goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor; - } - return ctor.instance_ = new ctor; - }; -}; - - -/** - * All singleton classes that have been instantiated, for testing. Don't read - * it directly, use the {@code goog.testing.singleton} module. The compiler - * removes this variable if unused. - * @type {!Array<!Function>} - * @private - */ -goog.instantiatedSingletons_ = []; - - -/** - * @define {boolean} Whether to load goog.modules using {@code eval} when using - * the debug loader. This provides a better debugging experience as the - * source is unmodified and can be edited using Chrome Workspaces or similar. - * However in some environments the use of {@code eval} is banned - * so we provide an alternative. - */ -goog.define('goog.LOAD_MODULE_USING_EVAL', true); - - -/** - * @define {boolean} Whether the exports of goog.modules should be sealed when - * possible. - */ -goog.define('goog.SEAL_MODULE_EXPORTS', goog.DEBUG); - - -/** - * The registry of initialized modules: - * the module identifier to module exports map. - * @private @const {!Object<string, ?>} - */ -goog.loadedModules_ = {}; - - -/** - * True if goog.dependencies_ is available. - * @const {boolean} - */ -goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER; - - -/** - * @define {string} How to decide whether to transpile. Valid values - * are 'always', 'never', and 'detect'. The default ('detect') is to - * use feature detection to determine which language levels need - * transpilation. - */ -// NOTE(sdh): we could expand this to accept a language level to bypass -// detection: e.g. goog.TRANSPILE == 'es5' would transpile ES6 files but -// would leave ES3 and ES5 files alone. -goog.define('goog.TRANSPILE', 'detect'); - - -/** - * @define {string} Path to the transpiler. Executing the script at this - * path (relative to base.js) should define a function $jscomp.transpile. - */ -goog.define('goog.TRANSPILER', 'transpile.js'); - - -if (goog.DEPENDENCIES_ENABLED) { - /** - * This object is used to keep track of dependencies and other data that is - * used for loading scripts. - * @private - * @type {{ - * loadFlags: !Object<string, !Object<string, string>>, - * nameToPath: !Object<string, string>, - * requires: !Object<string, !Object<string, boolean>>, - * visited: !Object<string, boolean>, - * written: !Object<string, boolean>, - * deferred: !Object<string, string> - * }} - */ - goog.dependencies_ = { - loadFlags: {}, // 1 to 1 - - nameToPath: {}, // 1 to 1 - - requires: {}, // 1 to many - - // Used when resolving dependencies to prevent us from visiting file twice. - visited: {}, - - written: {}, // Used to keep track of script files we have written. - - deferred: {} // Used to track deferred module evaluations in old IEs - }; - - - /** - * Tries to detect whether is in the context of an HTML document. - * @return {boolean} True if it looks like HTML document. - * @private - */ - goog.inHtmlDocument_ = function() { - /** @type {Document} */ - var doc = goog.global.document; - return doc != null && 'write' in doc; // XULDocument misses write. - }; - - - /** - * Tries to detect the base path of base.js script that bootstraps Closure. - * @private - */ - goog.findBasePath_ = function() { - if (goog.isDef(goog.global.CLOSURE_BASE_PATH) && - // Anti DOM-clobbering runtime check (b/37736576). - goog.isString(goog.global.CLOSURE_BASE_PATH)) { - goog.basePath = goog.global.CLOSURE_BASE_PATH; - return; - } else if (!goog.inHtmlDocument_()) { - return; - } - /** @type {Document} */ - var doc = goog.global.document; - // If we have a currentScript available, use it exclusively. - var currentScript = doc.currentScript; - if (currentScript) { - var scripts = [currentScript]; - } else { - var scripts = doc.getElementsByTagName('SCRIPT'); - } - // Search backwards since the current script is in almost all cases the one - // that has base.js. - for (var i = scripts.length - 1; i >= 0; --i) { - var script = /** @type {!HTMLScriptElement} */ (scripts[i]); - var src = script.src; - var qmark = src.lastIndexOf('?'); - var l = qmark == -1 ? src.length : qmark; - if (src.substr(l - 7, 7) == 'base.js') { - goog.basePath = src.substr(0, l - 7); - return; - } - } - }; - - - /** - * Imports a script if, and only if, that script hasn't already been imported. - * (Must be called at execution time) - * @param {string} src Script source. - * @param {string=} opt_sourceText The optionally source text to evaluate - * @private - */ - goog.importScript_ = function(src, opt_sourceText) { - var importScript = - goog.global.CLOSURE_IMPORT_SCRIPT || goog.writeScriptTag_; - if (importScript(src, opt_sourceText)) { - goog.dependencies_.written[src] = true; - } - }; - - - /** - * Whether the browser is IE9 or earlier, which needs special handling - * for deferred modules. - * @const @private {boolean} - */ - goog.IS_OLD_IE_ = - !!(!goog.global.atob && goog.global.document && goog.global.document.all); - - - /** - * Whether IE9 or earlier is waiting on a dependency. This ensures that - * deferred modules that have no non-deferred dependencies actually get - * loaded, since if we defer them and then never pull in a non-deferred - * script, then `goog.loadQueuedModules_` will never be called. Instead, - * if not waiting on anything we simply don't defer in the first place. - * @private {boolean} - */ - goog.oldIeWaiting_ = false; - - - /** - * Given a URL initiate retrieval and execution of a script that needs - * pre-processing. - * @param {string} src Script source URL. - * @param {boolean} isModule Whether this is a goog.module. - * @param {boolean} needsTranspile Whether this source needs transpilation. - * @private - */ - goog.importProcessedScript_ = function(src, isModule, needsTranspile) { - // In an attempt to keep browsers from timing out loading scripts using - // synchronous XHRs, put each load in its own script block. - var bootstrap = 'goog.retrieveAndExec_("' + src + '", ' + isModule + ', ' + - needsTranspile + ');'; - - goog.importScript_('', bootstrap); - }; - - - /** @private {!Array<string>} */ - goog.queuedModules_ = []; - - - /** - * Return an appropriate module text. Suitable to insert into - * a script tag (that is unescaped). - * @param {string} srcUrl - * @param {string} scriptText - * @return {string} - * @private - */ - goog.wrapModule_ = function(srcUrl, scriptText) { - if (!goog.LOAD_MODULE_USING_EVAL || !goog.isDef(goog.global.JSON)) { - return '' + - 'goog.loadModule(function(exports) {' + - '"use strict";' + scriptText + - '\n' + // terminate any trailing single line comment. - ';return exports' + - '});' + - '\n//# sourceURL=' + srcUrl + '\n'; - } else { - return '' + - 'goog.loadModule(' + - goog.global.JSON.stringify( - scriptText + '\n//# sourceURL=' + srcUrl + '\n') + - ');'; - } - }; - - // On IE9 and earlier, it is necessary to handle - // deferred module loads. In later browsers, the - // code to be evaluated is simply inserted as a script - // block in the correct order. To eval deferred - // code at the right time, we piggy back on goog.require to call - // goog.maybeProcessDeferredDep_. - // - // The goog.requires are used both to bootstrap - // the loading process (when no deps are available) and - // declare that they should be available. - // - // Here we eval the sources, if all the deps are available - // either already eval'd or goog.require'd. This will - // be the case when all the dependencies have already - // been loaded, and the dependent module is loaded. - // - // But this alone isn't sufficient because it is also - // necessary to handle the case where there is no root - // that is not deferred. For that there we register for an event - // and trigger goog.loadQueuedModules_ handle any remaining deferred - // evaluations. - - /** - * Handle any remaining deferred goog.module evals. - * @private - */ - goog.loadQueuedModules_ = function() { - var count = goog.queuedModules_.length; - if (count > 0) { - var queue = goog.queuedModules_; - goog.queuedModules_ = []; - for (var i = 0; i < count; i++) { - var path = queue[i]; - goog.maybeProcessDeferredPath_(path); - } - } - goog.oldIeWaiting_ = false; - }; - - - /** - * Eval the named module if its dependencies are - * available. - * @param {string} name The module to load. - * @private - */ - goog.maybeProcessDeferredDep_ = function(name) { - if (goog.isDeferredModule_(name) && goog.allDepsAreAvailable_(name)) { - var path = goog.getPathFromDeps_(name); - goog.maybeProcessDeferredPath_(goog.basePath + path); - } - }; - - /** - * @param {string} name The module to check. - * @return {boolean} Whether the name represents a - * module whose evaluation has been deferred. - * @private - */ - goog.isDeferredModule_ = function(name) { - var path = goog.getPathFromDeps_(name); - var loadFlags = path && goog.dependencies_.loadFlags[path] || {}; - var languageLevel = loadFlags['lang'] || 'es3'; - if (path && (loadFlags['module'] == 'goog' || - goog.needsTranspile_(languageLevel))) { - var abspath = goog.basePath + path; - return (abspath) in goog.dependencies_.deferred; - } - return false; - }; - - /** - * @param {string} name The module to check. - * @return {boolean} Whether the name represents a - * module whose declared dependencies have all been loaded - * (eval'd or a deferred module load) - * @private - */ - goog.allDepsAreAvailable_ = function(name) { - var path = goog.getPathFromDeps_(name); - if (path && (path in goog.dependencies_.requires)) { - for (var requireName in goog.dependencies_.requires[path]) { - if (!goog.isProvided_(requireName) && - !goog.isDeferredModule_(requireName)) { - return false; - } - } - } - return true; - }; - - - /** - * @param {string} abspath - * @private - */ - goog.maybeProcessDeferredPath_ = function(abspath) { - if (abspath in goog.dependencies_.deferred) { - var src = goog.dependencies_.deferred[abspath]; - delete goog.dependencies_.deferred[abspath]; - goog.globalEval(src); - } - }; - - - /** - * Load a goog.module from the provided URL. This is not a general purpose - * code loader and does not support late loading code, that is it should only - * be used during page load. This method exists to support unit tests and - * "debug" loaders that would otherwise have inserted script tags. Under the - * hood this needs to use a synchronous XHR and is not recommeneded for - * production code. - * - * The module's goog.requires must have already been satisified; an exception - * will be thrown if this is not the case. This assumption is that no - * "deps.js" file exists, so there is no way to discover and locate the - * module-to-be-loaded's dependencies and no attempt is made to do so. - * - * There should only be one attempt to load a module. If - * "goog.loadModuleFromUrl" is called for an already loaded module, an - * exception will be throw. - * - * @param {string} url The URL from which to attempt to load the goog.module. - */ - goog.loadModuleFromUrl = function(url) { - // Because this executes synchronously, we don't need to do any additional - // bookkeeping. When "goog.loadModule" the namespace will be marked as - // having been provided which is sufficient. - goog.retrieveAndExec_(url, true, false); - }; - - - /** - * Writes a new script pointing to {@code src} directly into the DOM. - * - * NOTE: This method is not CSP-compliant. @see goog.appendScriptSrcNode_ for - * the fallback mechanism. - * - * @param {string} src The script URL. - * @private - */ - goog.writeScriptSrcNode_ = function(src) { - goog.global.document.write( - '<script type="text/javascript" src="' + src + '"></' + - 'script>'); - }; - - - /** - * Appends a new script node to the DOM using a CSP-compliant mechanism. This - * method exists as a fallback for document.write (which is not allowed in a - * strict CSP context, e.g., Chrome apps). - * - * NOTE: This method is not analogous to using document.write to insert a - * <script> tag; specifically, the user agent will execute a script added by - * document.write immediately after the current script block finishes - * executing, whereas the DOM-appended script node will not be executed until - * the entire document is parsed and executed. That is to say, this script is - * added to the end of the script execution queue. - * - * The page must not attempt to call goog.required entities until after the - * document has loaded, e.g., in or after the window.onload callback. - * - * @param {string} src The script URL. - * @private - */ - goog.appendScriptSrcNode_ = function(src) { - /** @type {Document} */ - var doc = goog.global.document; - var scriptEl = - /** @type {HTMLScriptElement} */ (doc.createElement('script')); - scriptEl.type = 'text/javascript'; - scriptEl.src = src; - scriptEl.defer = false; - scriptEl.async = false; - doc.head.appendChild(scriptEl); - }; - - - /** - * The default implementation of the import function. Writes a script tag to - * import the script. - * - * @param {string} src The script url. - * @param {string=} opt_sourceText The optionally source text to evaluate - * @return {boolean} True if the script was imported, false otherwise. - * @private - */ - goog.writeScriptTag_ = function(src, opt_sourceText) { - if (goog.inHtmlDocument_()) { - /** @type {!HTMLDocument} */ - var doc = goog.global.document; - - // If the user tries to require a new symbol after document load, - // something has gone terribly wrong. Doing a document.write would - // wipe out the page. This does not apply to the CSP-compliant method - // of writing script tags. - if (!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING && - doc.readyState == 'complete') { - // Certain test frameworks load base.js multiple times, which tries - // to write deps.js each time. If that happens, just fail silently. - // These frameworks wipe the page between each load of base.js, so this - // is OK. - var isDeps = /\bdeps.js$/.test(src); - if (isDeps) { - return false; - } else { - throw new Error('Cannot write "' + src + '" after document load'); - } - } - - if (opt_sourceText === undefined) { - if (!goog.IS_OLD_IE_) { - if (goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING) { - goog.appendScriptSrcNode_(src); - } else { - goog.writeScriptSrcNode_(src); - } - } else { - goog.oldIeWaiting_ = true; - var state = ' onreadystatechange=\'goog.onScriptLoad_(this, ' + - ++goog.lastNonModuleScriptIndex_ + ')\' '; - doc.write( - '<script type="text/javascript" src="' + src + '"' + state + - '></' + - 'script>'); - } - } else { - doc.write( - '<script type="text/javascript">' + - goog.protectScriptTag_(opt_sourceText) + '</' + - 'script>'); - } - return true; - } else { - return false; - } - }; - - /** - * Rewrites closing script tags in input to avoid ending an enclosing script - * tag. - * - * @param {string} str - * @return {string} - * @private - */ - goog.protectScriptTag_ = function(str) { - return str.replace(/<\/(SCRIPT)/ig, '\\x3c/$1'); - }; - - /** - * Determines whether the given language needs to be transpiled. - * @param {string} lang - * @return {boolean} - * @private - */ - goog.needsTranspile_ = function(lang) { - if (goog.TRANSPILE == 'always') { - return true; - } else if (goog.TRANSPILE == 'never') { - return false; - } else if (!goog.requiresTranspilation_) { - goog.requiresTranspilation_ = goog.createRequiresTranspilation_(); - } - if (lang in goog.requiresTranspilation_) { - return goog.requiresTranspilation_[lang]; - } else { - throw new Error('Unknown language mode: ' + lang); - } - }; - - /** @private {?Object<string, boolean>} */ - goog.requiresTranspilation_ = null; - - - /** @private {number} */ - goog.lastNonModuleScriptIndex_ = 0; - - - /** - * A readystatechange handler for legacy IE - * @param {?} script - * @param {number} scriptIndex - * @return {boolean} - * @private - */ - goog.onScriptLoad_ = function(script, scriptIndex) { - // for now load the modules when we reach the last script, - // later allow more inter-mingling. - if (script.readyState == 'complete' && - goog.lastNonModuleScriptIndex_ == scriptIndex) { - goog.loadQueuedModules_(); - } - return true; - }; - - /** - * Resolves dependencies based on the dependencies added using addDependency - * and calls importScript_ in the correct order. - * @param {string} pathToLoad The path from which to start discovering - * dependencies. - * @private - */ - goog.writeScripts_ = function(pathToLoad) { - /** @type {!Array<string>} The scripts we need to write this time. */ - var scripts = []; - var seenScript = {}; - var deps = goog.dependencies_; - - /** @param {string} path */ - function visitNode(path) { - if (path in deps.written) { - return; - } - - // We have already visited this one. We can get here if we have cyclic - // dependencies. - if (path in deps.visited) { - return; - } - - deps.visited[path] = true; - - if (path in deps.requires) { - for (var requireName in deps.requires[path]) { - // If the required name is defined, we assume that it was already - // bootstrapped by other means. - if (!goog.isProvided_(requireName)) { - if (requireName in deps.nameToPath) { - visitNode(deps.nameToPath[requireName]); - } else { - throw new Error('Undefined nameToPath for ' + requireName); - } - } - } - } - - if (!(path in seenScript)) { - seenScript[path] = true; - scripts.push(path); - } - } - - visitNode(pathToLoad); - - // record that we are going to load all these scripts. - for (var i = 0; i < scripts.length; i++) { - var path = scripts[i]; - goog.dependencies_.written[path] = true; - } - - // If a module is loaded synchronously then we need to - // clear the current inModuleLoader value, and restore it when we are - // done loading the current "requires". - var moduleState = goog.moduleLoaderState_; - goog.moduleLoaderState_ = null; - - for (var i = 0; i < scripts.length; i++) { - var path = scripts[i]; - if (path) { - var loadFlags = deps.loadFlags[path] || {}; - var languageLevel = loadFlags['lang'] || 'es3'; - var needsTranspile = goog.needsTranspile_(languageLevel); - if (loadFlags['module'] == 'goog' || needsTranspile) { - goog.importProcessedScript_( - goog.basePath + path, loadFlags['module'] == 'goog', - needsTranspile); - } else { - goog.importScript_(goog.basePath + path); - } - } else { - goog.moduleLoaderState_ = moduleState; - throw new Error('Undefined script input'); - } - } - - // restore the current "module loading state" - goog.moduleLoaderState_ = moduleState; - }; - - - /** - * Looks at the dependency rules and tries to determine the script file that - * fulfills a particular rule. - * @param {string} rule In the form goog.namespace.Class or project.script. - * @return {?string} Url corresponding to the rule, or null. - * @private - */ - goog.getPathFromDeps_ = function(rule) { - if (rule in goog.dependencies_.nameToPath) { - return goog.dependencies_.nameToPath[rule]; - } else { - return null; - } - }; - - goog.findBasePath_(); - - // Allow projects to manage the deps files themselves. - if (!goog.global.CLOSURE_NO_DEPS) { - goog.importScript_(goog.basePath + 'deps.js'); - } -} - - -/** - * @package {?boolean} - * Visible for testing. - */ -goog.hasBadLetScoping = null; - - -/** - * @return {boolean} - * @package Visible for testing. - */ -goog.useSafari10Workaround = function() { - if (goog.hasBadLetScoping == null) { - var hasBadLetScoping; - try { - hasBadLetScoping = !eval( - '"use strict";' + - 'let x = 1; function f() { return typeof x; };' + - 'f() == "number";'); - } catch (e) { - // Assume that ES6 syntax isn't supported. - hasBadLetScoping = false; - } - goog.hasBadLetScoping = hasBadLetScoping; - } - return goog.hasBadLetScoping; -}; - - -/** - * @param {string} moduleDef - * @return {string} - * @package Visible for testing. - */ -goog.workaroundSafari10EvalBug = function(moduleDef) { - return '(function(){' + moduleDef + - '\n' + // Terminate any trailing single line comment. - ';' + // Terminate any trailing expression. - '})();\n'; -}; - - -/** - * @param {function(?):?|string} moduleDef The module definition. - */ -goog.loadModule = function(moduleDef) { - // NOTE: we allow function definitions to be either in the from - // of a string to eval (which keeps the original source intact) or - // in a eval forbidden environment (CSP) we allow a function definition - // which in its body must call {@code goog.module}, and return the exports - // of the module. - var previousState = goog.moduleLoaderState_; - try { - goog.moduleLoaderState_ = { - moduleName: undefined, - declareLegacyNamespace: false - }; - var exports; - if (goog.isFunction(moduleDef)) { - exports = moduleDef.call(undefined, {}); - } else if (goog.isString(moduleDef)) { - if (goog.useSafari10Workaround()) { - moduleDef = goog.workaroundSafari10EvalBug(moduleDef); - } - - exports = goog.loadModuleFromSource_.call(undefined, moduleDef); - } else { - throw new Error('Invalid module definition'); - } - - var moduleName = goog.moduleLoaderState_.moduleName; - if (!goog.isString(moduleName) || !moduleName) { - throw new Error('Invalid module name \"' + moduleName + '\"'); - } - - // Don't seal legacy namespaces as they may be uses as a parent of - // another namespace - if (goog.moduleLoaderState_.declareLegacyNamespace) { - goog.constructNamespace_(moduleName, exports); - } else if ( - goog.SEAL_MODULE_EXPORTS && Object.seal && typeof exports == 'object' && - exports != null) { - Object.seal(exports); - } - - goog.loadedModules_[moduleName] = exports; - } finally { - goog.moduleLoaderState_ = previousState; - } -}; - - -/** - * @private @const - */ -goog.loadModuleFromSource_ = /** @type {function(string):?} */ (function() { - // NOTE: we avoid declaring parameters or local variables here to avoid - // masking globals or leaking values into the module definition. - 'use strict'; - var exports = {}; - eval(arguments[0]); - return exports; -}); - - -/** - * Normalize a file path by removing redundant ".." and extraneous "." file - * path components. - * @param {string} path - * @return {string} - * @private - */ -goog.normalizePath_ = function(path) { - var components = path.split('/'); - var i = 0; - while (i < components.length) { - if (components[i] == '.') { - components.splice(i, 1); - } else if ( - i && components[i] == '..' && components[i - 1] && - components[i - 1] != '..') { - components.splice(--i, 2); - } else { - i++; - } - } - return components.join('/'); -}; - - -/** - * Provides a hook for loading a file when using Closure's goog.require() API - * with goog.modules. In particular this hook is provided to support Node.js. - * - * @type {(function(string):string)|undefined} - */ -goog.global.CLOSURE_LOAD_FILE_SYNC; - - -/** - * Loads file by synchronous XHR. Should not be used in production environments. - * @param {string} src Source URL. - * @return {?string} File contents, or null if load failed. - * @private - */ -goog.loadFileSync_ = function(src) { - if (goog.global.CLOSURE_LOAD_FILE_SYNC) { - return goog.global.CLOSURE_LOAD_FILE_SYNC(src); - } else { - try { - /** @type {XMLHttpRequest} */ - var xhr = new goog.global['XMLHttpRequest'](); - xhr.open('get', src, false); - xhr.send(); - // NOTE: Successful http: requests have a status of 200, but successful - // file: requests may have a status of zero. Any other status, or a - // thrown exception (particularly in case of file: requests) indicates - // some sort of error, which we treat as a missing or unavailable file. - return xhr.status == 0 || xhr.status == 200 ? xhr.responseText : null; - } catch (err) { - // No need to rethrow or log, since errors should show up on their own. - return null; - } - } -}; - - -/** - * Retrieve and execute a script that needs some sort of wrapping. - * @param {string} src Script source URL. - * @param {boolean} isModule Whether to load as a module. - * @param {boolean} needsTranspile Whether to transpile down to ES3. - * @private - */ -goog.retrieveAndExec_ = function(src, isModule, needsTranspile) { - if (!COMPILED) { - // The full but non-canonicalized URL for later use. - var originalPath = src; - // Canonicalize the path, removing any /./ or /../ since Chrome's debugging - // console doesn't auto-canonicalize XHR loads as it does <script> srcs. - src = goog.normalizePath_(src); - - var importScript = - goog.global.CLOSURE_IMPORT_SCRIPT || goog.writeScriptTag_; - - var scriptText = goog.loadFileSync_(src); - if (scriptText == null) { - throw new Error('Load of "' + src + '" failed'); - } - - if (needsTranspile) { - scriptText = goog.transpile_.call(goog.global, scriptText, src); - } - - if (isModule) { - scriptText = goog.wrapModule_(src, scriptText); - } else { - scriptText += '\n//# sourceURL=' + src; - } - var isOldIE = goog.IS_OLD_IE_; - if (isOldIE && goog.oldIeWaiting_) { - goog.dependencies_.deferred[originalPath] = scriptText; - goog.queuedModules_.push(originalPath); - } else { - importScript(src, scriptText); - } - } -}; - - -/** - * Lazily retrieves the transpiler and applies it to the source. - * @param {string} code JS code. - * @param {string} path Path to the code. - * @return {string} The transpiled code. - * @private - */ -goog.transpile_ = function(code, path) { - var jscomp = goog.global['$jscomp']; - if (!jscomp) { - goog.global['$jscomp'] = jscomp = {}; - } - var transpile = jscomp.transpile; - if (!transpile) { - var transpilerPath = goog.basePath + goog.TRANSPILER; - var transpilerCode = goog.loadFileSync_(transpilerPath); - if (transpilerCode) { - // This must be executed synchronously, since by the time we know we - // need it, we're about to load and write the ES6 code synchronously, - // so a normal script-tag load will be too slow. - eval(transpilerCode + '\n//# sourceURL=' + transpilerPath); - // Even though the transpiler is optional, if $gwtExport is found, it's - // a sign the transpiler was loaded and the $jscomp.transpile *should* - // be there. - if (goog.global['$gwtExport'] && goog.global['$gwtExport']['$jscomp'] && - !goog.global['$gwtExport']['$jscomp']['transpile']) { - throw new Error( - 'The transpiler did not properly export the "transpile" ' + - 'method. $gwtExport: ' + JSON.stringify(goog.global['$gwtExport'])); - } - // transpile.js only exports a single $jscomp function, transpile. We - // grab just that and add it to the existing definition of $jscomp which - // contains the polyfills. - goog.global['$jscomp'].transpile = - goog.global['$gwtExport']['$jscomp']['transpile']; - jscomp = goog.global['$jscomp']; - transpile = jscomp.transpile; - } - } - if (!transpile) { - // The transpiler is an optional component. If it's not available then - // replace it with a pass-through function that simply logs. - var suffix = ' requires transpilation but no transpiler was found.'; - // MOE:begin_strip - suffix += // Provide a more appropriate message internally. - ' Please add "//javascript/closure:transpiler" as a data ' + - 'dependency to ensure it is included.'; - // MOE:end_strip - transpile = jscomp.transpile = function(code, path) { - // TODO(sdh): figure out some way to get this error to show up - // in test results, noting that the failure may occur in many - // different ways, including in loadModule() before the test - // runner even comes up. - goog.logToConsole_(path + suffix); - return code; - }; - } - // Note: any transpilation errors/warnings will be logged to the console. - return transpile(code, path); -}; - - -//============================================================================== -// Language Enhancements -//============================================================================== - - -/** - * This is a "fixed" version of the typeof operator. It differs from the typeof - * operator in such a way that null returns 'null' and arrays return 'array'. - * @param {?} value The value to get the type of. - * @return {string} The name of the type. - */ -goog.typeOf = function(value) { - var s = typeof value; - if (s == 'object') { - if (value) { - // Check these first, so we can avoid calling Object.prototype.toString if - // possible. - // - // IE improperly marshals typeof across execution contexts, but a - // cross-context object will still return false for "instanceof Object". - if (value instanceof Array) { - return 'array'; - } else if (value instanceof Object) { - return s; - } - - // HACK: In order to use an Object prototype method on the arbitrary - // value, the compiler requires the value be cast to type Object, - // even though the ECMA spec explicitly allows it. - var className = Object.prototype.toString.call( - /** @type {!Object} */ (value)); - // In Firefox 3.6, attempting to access iframe window objects' length - // property throws an NS_ERROR_FAILURE, so we need to special-case it - // here. - if (className == '[object Window]') { - return 'object'; - } - - // We cannot always use constructor == Array or instanceof Array because - // different frames have different Array objects. In IE6, if the iframe - // where the array was created is destroyed, the array loses its - // prototype. Then dereferencing val.splice here throws an exception, so - // we can't use goog.isFunction. Calling typeof directly returns 'unknown' - // so that will work. In this case, this function will return false and - // most array functions will still work because the array is still - // array-like (supports length and []) even though it has lost its - // prototype. - // Mark Miller noticed that Object.prototype.toString - // allows access to the unforgeable [[Class]] property. - // 15.2.4.2 Object.prototype.toString ( ) - // When the toString method is called, the following steps are taken: - // 1. Get the [[Class]] property of this object. - // 2. Compute a string value by concatenating the three strings - // "[object ", Result(1), and "]". - // 3. Return Result(2). - // and this behavior survives the destruction of the execution context. - if ((className == '[object Array]' || - // In IE all non value types are wrapped as objects across window - // boundaries (not iframe though) so we have to do object detection - // for this edge case. - typeof value.length == 'number' && - typeof value.splice != 'undefined' && - typeof value.propertyIsEnumerable != 'undefined' && - !value.propertyIsEnumerable('splice') - - )) { - return 'array'; - } - // HACK: There is still an array case that fails. - // function ArrayImpostor() {} - // ArrayImpostor.prototype = []; - // var impostor = new ArrayImpostor; - // this can be fixed by getting rid of the fast path - // (value instanceof Array) and solely relying on - // (value && Object.prototype.toString.vall(value) === '[object Array]') - // but that would require many more function calls and is not warranted - // unless closure code is receiving objects from untrusted sources. - - // IE in cross-window calls does not correctly marshal the function type - // (it appears just as an object) so we cannot use just typeof val == - // 'function'. However, if the object has a call property, it is a - // function. - if ((className == '[object Function]' || - typeof value.call != 'undefined' && - typeof value.propertyIsEnumerable != 'undefined' && - !value.propertyIsEnumerable('call'))) { - return 'function'; - } - - } else { - return 'null'; - } - - } else if (s == 'function' && typeof value.call == 'undefined') { - // In Safari typeof nodeList returns 'function', and on Firefox typeof - // behaves similarly for HTML{Applet,Embed,Object}, Elements and RegExps. We - // would like to return object for those and we can detect an invalid - // function by making sure that the function object has a call method. - return 'object'; - } - return s; -}; - - -/** - * Returns true if the specified value is null. - * @param {?} val Variable to test. - * @return {boolean} Whether variable is null. - */ -goog.isNull = function(val) { - return val === null; -}; - - -/** - * Returns true if the specified value is defined and not null. - * @param {?} val Variable to test. - * @return {boolean} Whether variable is defined and not null. - */ -goog.isDefAndNotNull = function(val) { - // Note that undefined == null. - return val != null; -}; - - -/** - * Returns true if the specified value is an array. - * @param {?} val Variable to test. - * @return {boolean} Whether variable is an array. - */ -goog.isArray = function(val) { - return goog.typeOf(val) == 'array'; -}; - - -/** - * Returns true if the object looks like an array. To qualify as array like - * the value needs to be either a NodeList or an object with a Number length - * property. As a special case, a function value is not array like, because its - * length property is fixed to correspond to the number of expected arguments. - * @param {?} val Variable to test. - * @return {boolean} Whether variable is an array. - */ -goog.isArrayLike = function(val) { - var type = goog.typeOf(val); - // We do not use goog.isObject here in order to exclude function values. - return type == 'array' || type == 'object' && typeof val.length == 'number'; -}; - - -/** - * Returns true if the object looks like a Date. To qualify as Date-like the - * value needs to be an object and have a getFullYear() function. - * @param {?} val Variable to test. - * @return {boolean} Whether variable is a like a Date. - */ -goog.isDateLike = function(val) { - return goog.isObject(val) && typeof val.getFullYear == 'function'; -}; - - -/** - * Returns true if the specified value is a function. - * @param {?} val Variable to test. - * @return {boolean} Whether variable is a function. - */ -goog.isFunction = function(val) { - return goog.typeOf(val) == 'function'; -}; - - -/** - * Returns true if the specified value is an object. This includes arrays and - * functions. - * @param {?} val Variable to test. - * @return {boolean} Whether variable is an object. - */ -goog.isObject = function(val) { - var type = typeof val; - return type == 'object' && val != null || type == 'function'; - // return Object(val) === val also works, but is slower, especially if val is - // not an object. -}; - - -/** - * Gets a unique ID for an object. This mutates the object so that further calls - * with the same object as a parameter returns the same value. The unique ID is - * guaranteed to be unique across the current session amongst objects that are - * passed into {@code getUid}. There is no guarantee that the ID is unique or - * consistent across sessions. It is unsafe to generate unique ID for function - * prototypes. - * - * @param {Object} obj The object to get the unique ID for. - * @return {number} The unique ID for the object. - */ -goog.getUid = function(obj) { - // TODO(arv): Make the type stricter, do not accept null. - - // In Opera window.hasOwnProperty exists but always returns false so we avoid - // using it. As a consequence the unique ID generated for BaseClass.prototype - // and SubClass.prototype will be the same. - return obj[goog.UID_PROPERTY_] || - (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_); -}; - - -/** - * Whether the given object is already assigned a unique ID. - * - * This does not modify the object. - * - * @param {!Object} obj The object to check. - * @return {boolean} Whether there is an assigned unique id for the object. - */ -goog.hasUid = function(obj) { - return !!obj[goog.UID_PROPERTY_]; -}; - - -/** - * Removes the unique ID from an object. This is useful if the object was - * previously mutated using {@code goog.getUid} in which case the mutation is - * undone. - * @param {Object} obj The object to remove the unique ID field from. - */ -goog.removeUid = function(obj) { - // TODO(arv): Make the type stricter, do not accept null. - - // In IE, DOM nodes are not instances of Object and throw an exception if we - // try to delete. Instead we try to use removeAttribute. - if (obj !== null && 'removeAttribute' in obj) { - obj.removeAttribute(goog.UID_PROPERTY_); - } - - try { - delete obj[goog.UID_PROPERTY_]; - } catch (ex) { - } -}; - - -/** - * Name for unique ID property. Initialized in a way to help avoid collisions - * with other closure JavaScript on the same page. - * @type {string} - * @private - */ -goog.UID_PROPERTY_ = 'closure_uid_' + ((Math.random() * 1e9) >>> 0); - - -/** - * Counter for UID. - * @type {number} - * @private - */ -goog.uidCounter_ = 0; - - -/** - * Adds a hash code field to an object. The hash code is unique for the - * given object. - * @param {Object} obj The object to get the hash code for. - * @return {number} The hash code for the object. - * @deprecated Use goog.getUid instead. - */ -goog.getHashCode = goog.getUid; - - -/** - * Removes the hash code field from an object. - * @param {Object} obj The object to remove the field from. - * @deprecated Use goog.removeUid instead. - */ -goog.removeHashCode = goog.removeUid; - - -/** - * Clones a value. The input may be an Object, Array, or basic type. Objects and - * arrays will be cloned recursively. - * - * WARNINGS: - * <code>goog.cloneObject</code> does not detect reference loops. Objects that - * refer to themselves will cause infinite recursion. - * - * <code>goog.cloneObject</code> is unaware of unique identifiers, and copies - * UIDs created by <code>getUid</code> into cloned results. - * - * @param {*} obj The value to clone. - * @return {*} A clone of the input value. - * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods. - */ -goog.cloneObject = function(obj) { - var type = goog.typeOf(obj); - if (type == 'object' || type == 'array') { - if (obj.clone) { - return obj.clone(); - } - var clone = type == 'array' ? [] : {}; - for (var key in obj) { - clone[key] = goog.cloneObject(obj[key]); - } - return clone; - } - - return obj; -}; - - -/** - * A native implementation of goog.bind. - * @param {?function(this:T, ...)} fn A function to partially apply. - * @param {T} selfObj Specifies the object which this should point to when the - * function is run. - * @param {...*} var_args Additional arguments that are partially applied to the - * function. - * @return {!Function} A partially-applied form of the function goog.bind() was - * invoked as a method of. - * @template T - * @private - */ -goog.bindNative_ = function(fn, selfObj, var_args) { - return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments)); -}; - - -/** - * A pure-JS implementation of goog.bind. - * @param {?function(this:T, ...)} fn A function to partially apply. - * @param {T} selfObj Specifies the object which this should point to when the - * function is run. - * @param {...*} var_args Additional arguments that are partially applied to the - * function. - * @return {!Function} A partially-applied form of the function goog.bind() was - * invoked as a method of. - * @template T - * @private - */ -goog.bindJs_ = function(fn, selfObj, var_args) { - if (!fn) { - throw new Error(); - } - - if (arguments.length > 2) { - var boundArgs = Array.prototype.slice.call(arguments, 2); - return function() { - // Prepend the bound arguments to the current arguments. - var newArgs = Array.prototype.slice.call(arguments); - Array.prototype.unshift.apply(newArgs, boundArgs); - return fn.apply(selfObj, newArgs); - }; - - } else { - return function() { - return fn.apply(selfObj, arguments); - }; - } -}; - - -/** - * Partially applies this function to a particular 'this object' and zero or - * more arguments. The result is a new function with some arguments of the first - * function pre-filled and the value of this 'pre-specified'. - * - * Remaining arguments specified at call-time are appended to the pre-specified - * ones. - * - * Also see: {@link #partial}. - * - * Usage: - * <pre>var barMethBound = goog.bind(myFunction, myObj, 'arg1', 'arg2'); - * barMethBound('arg3', 'arg4');</pre> - * - * @param {?function(this:T, ...)} fn A function to partially apply. - * @param {T} selfObj Specifies the object which this should point to when the - * function is run. - * @param {...*} var_args Additional arguments that are partially applied to the - * function. - * @return {!Function} A partially-applied form of the function goog.bind() was - * invoked as a method of. - * @template T - * @suppress {deprecated} See above. - */ -goog.bind = function(fn, selfObj, var_args) { - // TODO(nicksantos): narrow the type signature. - if (Function.prototype.bind && - // NOTE(nicksantos): Somebody pulled base.js into the default Chrome - // extension environment. This means that for Chrome extensions, they get - // the implementation of Function.prototype.bind that calls goog.bind - // instead of the native one. Even worse, we don't want to introduce a - // circular dependency between goog.bind and Function.prototype.bind, so - // we have to hack this to make sure it works correctly. - Function.prototype.bind.toString().indexOf('native code') != -1) { - goog.bind = goog.bindNative_; - } else { - goog.bind = goog.bindJs_; - } - return goog.bind.apply(null, arguments); -}; - - -/** - * Like goog.bind(), except that a 'this object' is not required. Useful when - * the target function is already bound. - * - * Usage: - * var g = goog.partial(f, arg1, arg2); - * g(arg3, arg4); - * - * @param {Function} fn A function to partially apply. - * @param {...*} var_args Additional arguments that are partially applied to fn. - * @return {!Function} A partially-applied form of the function goog.partial() - * was invoked as a method of. - */ -goog.partial = function(fn, var_args) { - var args = Array.prototype.slice.call(arguments, 1); - return function() { - // Clone the array (with slice()) and append additional arguments - // to the existing arguments. - var newArgs = args.slice(); - newArgs.push.apply(newArgs, arguments); - return fn.apply(this, newArgs); - }; -}; - - -/** - * Copies all the members of a source object to a target object. This method - * does not work on all browsers for all objects that contain keys such as - * toString or hasOwnProperty. Use goog.object.extend for this purpose. - * @param {Object} target Target. - * @param {Object} source Source. - */ -goog.mixin = function(target, source) { - for (var x in source) { - target[x] = source[x]; - } - - // For IE7 or lower, the for-in-loop does not contain any properties that are - // not enumerable on the prototype object (for example, isPrototypeOf from - // Object.prototype) but also it will not include 'replace' on objects that - // extend String and change 'replace' (not that it is common for anyone to - // extend anything except Object). -}; - - -/** - * @return {number} An integer value representing the number of milliseconds - * between midnight, January 1, 1970 and the current time. - */ -goog.now = (goog.TRUSTED_SITE && Date.now) || (function() { - // Unary plus operator converts its operand to a number which in - // the case of - // a date is done by calling getTime(). - return +new Date(); - }); - - -/** - * Evals JavaScript in the global scope. In IE this uses execScript, other - * browsers use goog.global.eval. If goog.global.eval does not evaluate in the - * global scope (for example, in Safari), appends a script tag instead. - * Throws an exception if neither execScript or eval is defined. - * @param {string} script JavaScript string. - */ -goog.globalEval = function(script) { - if (goog.global.execScript) { - goog.global.execScript(script, 'JavaScript'); - } else if (goog.global.eval) { - // Test to see if eval works - if (goog.evalWorksForGlobals_ == null) { - goog.global.eval('var _evalTest_ = 1;'); - if (typeof goog.global['_evalTest_'] != 'undefined') { - try { - delete goog.global['_evalTest_']; - } catch (ignore) { - // Microsoft edge fails the deletion above in strict mode. - } - goog.evalWorksForGlobals_ = true; - } else { - goog.evalWorksForGlobals_ = false; - } - } - - if (goog.evalWorksForGlobals_) { - goog.global.eval(script); - } else { - /** @type {Document} */ - var doc = goog.global.document; - var scriptElt = - /** @type {!HTMLScriptElement} */ (doc.createElement('SCRIPT')); - scriptElt.type = 'text/javascript'; - scriptElt.defer = false; - // Note(pupius): can't use .innerHTML since "t('<test>')" will fail and - // .text doesn't work in Safari 2. Therefore we append a text node. - scriptElt.appendChild(doc.createTextNode(script)); - doc.body.appendChild(scriptElt); - doc.body.removeChild(scriptElt); - } - } else { - throw new Error('goog.globalEval not available'); - } -}; - - -/** - * Indicates whether or not we can call 'eval' directly to eval code in the - * global scope. Set to a Boolean by the first call to goog.globalEval (which - * empirically tests whether eval works for globals). @see goog.globalEval - * @type {?boolean} - * @private - */ -goog.evalWorksForGlobals_ = null; - - -/** - * Optional map of CSS class names to obfuscated names used with - * goog.getCssName(). - * @private {!Object<string, string>|undefined} - * @see goog.setCssNameMapping - */ -goog.cssNameMapping_; - - -/** - * Optional obfuscation style for CSS class names. Should be set to either - * 'BY_WHOLE' or 'BY_PART' if defined. - * @type {string|undefined} - * @private - * @see goog.setCssNameMapping - */ -goog.cssNameMappingStyle_; - - - -/** - * A hook for modifying the default behavior goog.getCssName. The function - * if present, will recieve the standard output of the goog.getCssName as - * its input. - * - * @type {(function(string):string)|undefined} - */ -goog.global.CLOSURE_CSS_NAME_MAP_FN; - - -/** - * Handles strings that are intended to be used as CSS class names. - * - * This function works in tandem with @see goog.setCssNameMapping. - * - * Without any mapping set, the arguments are simple joined with a hyphen and - * passed through unaltered. - * - * When there is a mapping, there are two possible styles in which these - * mappings are used. In the BY_PART style, each part (i.e. in between hyphens) - * of the passed in css name is rewritten according to the map. In the BY_WHOLE - * style, the full css name is looked up in the map directly. If a rewrite is - * not specified by the map, the compiler will output a warning. - * - * When the mapping is passed to the compiler, it will replace calls to - * goog.getCssName with the strings from the mapping, e.g. - * var x = goog.getCssName('foo'); - * var y = goog.getCssName(this.baseClass, 'active'); - * becomes: - * var x = 'foo'; - * var y = this.baseClass + '-active'; - * - * If one argument is passed it will be processed, if two are passed only the - * modifier will be processed, as it is assumed the first argument was generated - * as a result of calling goog.getCssName. - * - * @param {string} className The class name. - * @param {string=} opt_modifier A modifier to be appended to the class name. - * @return {string} The class name or the concatenation of the class name and - * the modifier. - */ -goog.getCssName = function(className, opt_modifier) { - // String() is used for compatibility with compiled soy where the passed - // className can be non-string objects. - if (String(className).charAt(0) == '.') { - throw new Error( - 'className passed in goog.getCssName must not start with ".".' + - ' You passed: ' + className); - } - - var getMapping = function(cssName) { - return goog.cssNameMapping_[cssName] || cssName; - }; - - var renameByParts = function(cssName) { - // Remap all the parts individually. - var parts = cssName.split('-'); - var mapped = []; - for (var i = 0; i < parts.length; i++) { - mapped.push(getMapping(parts[i])); - } - return mapped.join('-'); - }; - - var rename; - if (goog.cssNameMapping_) { - rename = - goog.cssNameMappingStyle_ == 'BY_WHOLE' ? getMapping : renameByParts; - } else { - rename = function(a) { - return a; - }; - } - - var result = - opt_modifier ? className + '-' + rename(opt_modifier) : rename(className); - - // The special CLOSURE_CSS_NAME_MAP_FN allows users to specify further - // processing of the class name. - if (goog.global.CLOSURE_CSS_NAME_MAP_FN) { - return goog.global.CLOSURE_CSS_NAME_MAP_FN(result); - } - - return result; -}; - - -/** - * Sets the map to check when returning a value from goog.getCssName(). Example: - * <pre> - * goog.setCssNameMapping({ - * "goog": "a", - * "disabled": "b", - * }); - * - * var x = goog.getCssName('goog'); - * // The following evaluates to: "a a-b". - * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled') - * </pre> - * When declared as a map of string literals to string literals, the JSCompiler - * will replace all calls to goog.getCssName() using the supplied map if the - * --process_closure_primitives flag is set. - * - * @param {!Object} mapping A map of strings to strings where keys are possible - * arguments to goog.getCssName() and values are the corresponding values - * that should be returned. - * @param {string=} opt_style The style of css name mapping. There are two valid - * options: 'BY_PART', and 'BY_WHOLE'. - * @see goog.getCssName for a description. - */ -goog.setCssNameMapping = function(mapping, opt_style) { - goog.cssNameMapping_ = mapping; - goog.cssNameMappingStyle_ = opt_style; -}; - - -/** - * To use CSS renaming in compiled mode, one of the input files should have a - * call to goog.setCssNameMapping() with an object literal that the JSCompiler - * can extract and use to replace all calls to goog.getCssName(). In uncompiled - * mode, JavaScript code should be loaded before this base.js file that declares - * a global variable, CLOSURE_CSS_NAME_MAPPING, which is used below. This is - * to ensure that the mapping is loaded before any calls to goog.getCssName() - * are made in uncompiled mode. - * - * A hook for overriding the CSS name mapping. - * @type {!Object<string, string>|undefined} - */ -goog.global.CLOSURE_CSS_NAME_MAPPING; - - -if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) { - // This does not call goog.setCssNameMapping() because the JSCompiler - // requires that goog.setCssNameMapping() be called with an object literal. - goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING; -} - - -/** - * Gets a localized message. - * - * This function is a compiler primitive. If you give the compiler a localized - * message bundle, it will replace the string at compile-time with a localized - * version, and expand goog.getMsg call to a concatenated string. - * - * Messages must be initialized in the form: - * <code> - * var MSG_NAME = goog.getMsg('Hello {$placeholder}', {'placeholder': 'world'}); - * </code> - * - * This function produces a string which should be treated as plain text. Use - * {@link goog.html.SafeHtmlFormatter} in conjunction with goog.getMsg to - * produce SafeHtml. - * - * @param {string} str Translatable string, places holders in the form {$foo}. - * @param {Object<string, string>=} opt_values Maps place holder name to value. - * @return {string} message with placeholders filled. - */ -goog.getMsg = function(str, opt_values) { - if (opt_values) { - str = str.replace(/\{\$([^}]+)}/g, function(match, key) { - return (opt_values != null && key in opt_values) ? opt_values[key] : - match; - }); - } - return str; -}; - - -/** - * Gets a localized message. If the message does not have a translation, gives a - * fallback message. - * - * This is useful when introducing a new message that has not yet been - * translated into all languages. - * - * This function is a compiler primitive. Must be used in the form: - * <code>var x = goog.getMsgWithFallback(MSG_A, MSG_B);</code> - * where MSG_A and MSG_B were initialized with goog.getMsg. - * - * @param {string} a The preferred message. - * @param {string} b The fallback message. - * @return {string} The best translated message. - */ -goog.getMsgWithFallback = function(a, b) { - return a; -}; - - -/** - * Exposes an unobfuscated global namespace path for the given object. - * Note that fields of the exported object *will* be obfuscated, unless they are - * exported in turn via this function or goog.exportProperty. - * - * Also handy for making public items that are defined in anonymous closures. - * - * ex. goog.exportSymbol('public.path.Foo', Foo); - * - * ex. goog.exportSymbol('public.path.Foo.staticFunction', Foo.staticFunction); - * public.path.Foo.staticFunction(); - * - * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod', - * Foo.prototype.myMethod); - * new public.path.Foo().myMethod(); - * - * @param {string} publicPath Unobfuscated name to export. - * @param {*} object Object the name should point to. - * @param {Object=} opt_objectToExportTo The object to add the path to; default - * is goog.global. - */ -goog.exportSymbol = function(publicPath, object, opt_objectToExportTo) { - goog.exportPath_(publicPath, object, opt_objectToExportTo); -}; - - -/** - * Exports a property unobfuscated into the object's namespace. - * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction); - * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod); - * @param {Object} object Object whose static property is being exported. - * @param {string} publicName Unobfuscated name to export. - * @param {*} symbol Object the name should point to. - */ -goog.exportProperty = function(object, publicName, symbol) { - object[publicName] = symbol; -}; - - -/** - * Inherit the prototype methods from one constructor into another. - * - * Usage: - * <pre> - * function ParentClass(a, b) { } - * ParentClass.prototype.foo = function(a) { }; - * - * function ChildClass(a, b, c) { - * ChildClass.base(this, 'constructor', a, b); - * } - * goog.inherits(ChildClass, ParentClass); - * - * var child = new ChildClass('a', 'b', 'see'); - * child.foo(); // This works. - * </pre> - * - * @param {!Function} childCtor Child class. - * @param {!Function} parentCtor Parent class. - */ -goog.inherits = function(childCtor, parentCtor) { - /** @constructor */ - function tempCtor() {} - tempCtor.prototype = parentCtor.prototype; - childCtor.superClass_ = parentCtor.prototype; - childCtor.prototype = new tempCtor(); - /** @override */ - childCtor.prototype.constructor = childCtor; - - /** - * Calls superclass constructor/method. - * - * This function is only available if you use goog.inherits to - * express inheritance relationships between classes. - * - * NOTE: This is a replacement for goog.base and for superClass_ - * property defined in childCtor. - * - * @param {!Object} me Should always be "this". - * @param {string} methodName The method name to call. Calling - * superclass constructor can be done with the special string - * 'constructor'. - * @param {...*} var_args The arguments to pass to superclass - * method/constructor. - * @return {*} The return value of the superclass method/constructor. - */ - childCtor.base = function(me, methodName, var_args) { - // Copying using loop to avoid deop due to passing arguments object to - // function. This is faster in many JS engines as of late 2014. - var args = new Array(arguments.length - 2); - for (var i = 2; i < arguments.length; i++) { - args[i - 2] = arguments[i]; - } - return parentCtor.prototype[methodName].apply(me, args); - }; -}; - - -/** - * Call up to the superclass. - * - * If this is called from a constructor, then this calls the superclass - * constructor with arguments 1-N. - * - * If this is called from a prototype method, then you must pass the name of the - * method as the second argument to this function. If you do not, you will get a - * runtime error. This calls the superclass' method with arguments 2-N. - * - * This function only works if you use goog.inherits to express inheritance - * relationships between your classes. - * - * This function is a compiler primitive. At compile-time, the compiler will do - * macro expansion to remove a lot of the extra overhead that this function - * introduces. The compiler will also enforce a lot of the assumptions that this - * function makes, and treat it as a compiler error if you break them. - * - * @param {!Object} me Should always be "this". - * @param {*=} opt_methodName The method name if calling a super method. - * @param {...*} var_args The rest of the arguments. - * @return {*} The return value of the superclass method. - * @suppress {es5Strict} This method can not be used in strict mode, but - * all Closure Library consumers must depend on this file. - * @deprecated goog.base is not strict mode compatible. Prefer the static - * "base" method added to the constructor by goog.inherits - * or ES6 classes and the "super" keyword. - */ -goog.base = function(me, opt_methodName, var_args) { - var caller = arguments.callee.caller; - - if (goog.STRICT_MODE_COMPATIBLE || (goog.DEBUG && !caller)) { - throw new Error( - 'arguments.caller not defined. goog.base() cannot be used ' + - 'with strict mode code. See ' + - 'http://www.ecma-international.org/ecma-262/5.1/#sec-C'); - } - - if (caller.superClass_) { - // Copying using loop to avoid deop due to passing arguments object to - // function. This is faster in many JS engines as of late 2014. - var ctorArgs = new Array(arguments.length - 1); - for (var i = 1; i < arguments.length; i++) { - ctorArgs[i - 1] = arguments[i]; - } - // This is a constructor. Call the superclass constructor. - return caller.superClass_.constructor.apply(me, ctorArgs); - } - - // Copying using loop to avoid deop due to passing arguments object to - // function. This is faster in many JS engines as of late 2014. - var args = new Array(arguments.length - 2); - for (var i = 2; i < arguments.length; i++) { - args[i - 2] = arguments[i]; - } - var foundCaller = false; - for (var ctor = me.constructor; ctor; - ctor = ctor.superClass_ && ctor.superClass_.constructor) { - if (ctor.prototype[opt_methodName] === caller) { - foundCaller = true; - } else if (foundCaller) { - return ctor.prototype[opt_methodName].apply(me, args); - } - } - - // If we did not find the caller in the prototype chain, then one of two - // things happened: - // 1) The caller is an instance method. - // 2) This method was not called by the right caller. - if (me[opt_methodName] === caller) { - return me.constructor.prototype[opt_methodName].apply(me, args); - } else { - throw new Error( - 'goog.base called from a method of one name ' + - 'to a method of a different name'); - } -}; - - -/** - * Allow for aliasing within scope functions. This function exists for - * uncompiled code - in compiled code the calls will be inlined and the aliases - * applied. In uncompiled code the function is simply run since the aliases as - * written are valid JavaScript. - * - * MOE:begin_intracomment_strip - * See the goog.scope document at http://go/goog.scope - * MOE:end_intracomment_strip - * - * @param {function()} fn Function to call. This function can contain aliases - * to namespaces (e.g. "var dom = goog.dom") or classes - * (e.g. "var Timer = goog.Timer"). - */ -goog.scope = function(fn) { - if (goog.isInModuleLoader_()) { - throw new Error('goog.scope is not supported within a goog.module.'); - } - fn.call(goog.global); -}; - - -/* - * To support uncompiled, strict mode bundles that use eval to divide source - * like so: - * eval('someSource;//# sourceUrl sourcefile.js'); - * We need to export the globally defined symbols "goog" and "COMPILED". - * Exporting "goog" breaks the compiler optimizations, so we required that - * be defined externally. - * NOTE: We don't use goog.exportSymbol here because we don't want to trigger - * extern generation when that compiler option is enabled. - */ -if (!COMPILED) { - goog.global['COMPILED'] = COMPILED; -} - - -//============================================================================== -// goog.defineClass implementation -//============================================================================== - - -/** - * Creates a restricted form of a Closure "class": - * - from the compiler's perspective, the instance returned from the - * constructor is sealed (no new properties may be added). This enables - * better checks. - * - the compiler will rewrite this definition to a form that is optimal - * for type checking and optimization (initially this will be a more - * traditional form). - * - * @param {Function} superClass The superclass, Object or null. - * @param {goog.defineClass.ClassDescriptor} def - * An object literal describing - * the class. It may have the following properties: - * "constructor": the constructor function - * "statics": an object literal containing methods to add to the constructor - * as "static" methods or a function that will receive the constructor - * function as its only parameter to which static properties can - * be added. - * all other properties are added to the prototype. - * @return {!Function} The class constructor. - */ -goog.defineClass = function(superClass, def) { - // TODO(johnlenz): consider making the superClass an optional parameter. - var constructor = def.constructor; - var statics = def.statics; - // Wrap the constructor prior to setting up the prototype and static methods. - if (!constructor || constructor == Object.prototype.constructor) { - constructor = function() { - throw new Error( - 'cannot instantiate an interface (no constructor defined).'); - }; - } - - var cls = goog.defineClass.createSealingConstructor_(constructor, superClass); - if (superClass) { - goog.inherits(cls, superClass); - } - - // Remove all the properties that should not be copied to the prototype. - delete def.constructor; - delete def.statics; - - goog.defineClass.applyProperties_(cls.prototype, def); - if (statics != null) { - if (statics instanceof Function) { - statics(cls); - } else { - goog.defineClass.applyProperties_(cls, statics); - } - } - - return cls; -}; - - -/** - * @typedef {{ - * constructor: (!Function|undefined), - * statics: (Object|undefined|function(Function):void) - * }} - */ -goog.defineClass.ClassDescriptor; - - -/** - * @define {boolean} Whether the instances returned by goog.defineClass should - * be sealed when possible. - * - * When sealing is disabled the constructor function will not be wrapped by - * goog.defineClass, making it incompatible with ES6 class methods. - */ -goog.define('goog.defineClass.SEAL_CLASS_INSTANCES', goog.DEBUG); - - -/** - * If goog.defineClass.SEAL_CLASS_INSTANCES is enabled and Object.seal is - * defined, this function will wrap the constructor in a function that seals the - * results of the provided constructor function. - * - * @param {!Function} ctr The constructor whose results maybe be sealed. - * @param {Function} superClass The superclass constructor. - * @return {!Function} The replacement constructor. - * @private - */ -goog.defineClass.createSealingConstructor_ = function(ctr, superClass) { - if (!goog.defineClass.SEAL_CLASS_INSTANCES) { - // Do now wrap the constructor when sealing is disabled. Angular code - // depends on this for injection to work properly. - return ctr; - } - - // Compute whether the constructor is sealable at definition time, rather - // than when the instance is being constructed. - var superclassSealable = !goog.defineClass.isUnsealable_(superClass); - - /** - * @this {Object} - * @return {?} - */ - var wrappedCtr = function() { - // Don't seal an instance of a subclass when it calls the constructor of - // its super class as there is most likely still setup to do. - var instance = ctr.apply(this, arguments) || this; - instance[goog.UID_PROPERTY_] = instance[goog.UID_PROPERTY_]; - - if (this.constructor === wrappedCtr && superclassSealable && - Object.seal instanceof Function) { - Object.seal(instance); - } - return instance; - }; - - return wrappedCtr; -}; - - -/** - * @param {Function} ctr The constructor to test. - * @return {boolean} Whether the constructor has been tagged as unsealable - * using goog.tagUnsealableClass. - * @private - */ -goog.defineClass.isUnsealable_ = function(ctr) { - return ctr && ctr.prototype && - ctr.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_]; -}; - - -// TODO(johnlenz): share these values with the goog.object -/** - * The names of the fields that are defined on Object.prototype. - * @type {!Array<string>} - * @private - * @const - */ -goog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = [ - 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', - 'toLocaleString', 'toString', 'valueOf' -]; - - -// TODO(johnlenz): share this function with the goog.object -/** - * @param {!Object} target The object to add properties to. - * @param {!Object} source The object to copy properties from. - * @private - */ -goog.defineClass.applyProperties_ = function(target, source) { - // TODO(johnlenz): update this to support ES5 getters/setters - - var key; - for (key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - - // For IE the for-in-loop does not contain any properties that are not - // enumerable on the prototype object (for example isPrototypeOf from - // Object.prototype) and it will also not include 'replace' on objects that - // extend String and change 'replace' (not that it is common for anyone to - // extend anything except Object). - for (var i = 0; i < goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length; i++) { - key = goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[i]; - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } -}; - - -/** - * Sealing classes breaks the older idiom of assigning properties on the - * prototype rather than in the constructor. As such, goog.defineClass - * must not seal subclasses of these old-style classes until they are fixed. - * Until then, this marks a class as "broken", instructing defineClass - * not to seal subclasses. - * @param {!Function} ctr The legacy constructor to tag as unsealable. - */ -goog.tagUnsealableClass = function(ctr) { - if (!COMPILED && goog.defineClass.SEAL_CLASS_INSTANCES) { - ctr.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_] = true; - } -}; - - -/** - * Name for unsealable tag property. - * @const @private {string} - */ -goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_ = 'goog_defineClass_legacy_unsealable'; - - -/** - * Returns a newly created map from language mode string to a boolean - * indicating whether transpilation should be done for that mode. - * - * Guaranteed invariant: - * For any two modes, l1 and l2 where l2 is a newer mode than l1, - * `map[l1] == true` implies that `map[l2] == true`. - * @private - * @return {!Object<string, boolean>} - */ -goog.createRequiresTranspilation_ = function() { - var /** !Object<string, boolean> */ requiresTranspilation = {'es3': false}; - var transpilationRequiredForAllLaterModes = false; - - /** - * Adds an entry to requiresTranspliation for the given language mode. - * - * IMPORTANT: Calls must be made in order from oldest to newest language - * mode. - * @param {string} modeName - * @param {function(): boolean} isSupported Returns true if the JS engine - * supports the given mode. - */ - function addNewerLanguageTranspilationCheck(modeName, isSupported) { - if (transpilationRequiredForAllLaterModes) { - requiresTranspilation[modeName] = true; - } else if (isSupported()) { - requiresTranspilation[modeName] = false; - } else { - requiresTranspilation[modeName] = true; - transpilationRequiredForAllLaterModes = true; - } - } - - /** - * Does the given code evaluate without syntax errors and return a truthy - * result? - */ - function /** boolean */ evalCheck(/** string */ code) { - try { - return !!eval(code); - } catch (ignored) { - return false; - } - } - - var userAgent = goog.global.navigator && goog.global.navigator.userAgent ? - goog.global.navigator.userAgent : - ''; - - // Identify ES3-only browsers by their incorrect treatment of commas. - addNewerLanguageTranspilationCheck('es5', function() { - return evalCheck('[1,].length==1'); - }); - addNewerLanguageTranspilationCheck('es6', function() { - // Edge has a non-deterministic (i.e., not reproducible) bug with ES6: - // https://github.com/Microsoft/ChakraCore/issues/1496. - // MOE:begin_strip - // TODO(joeltine): Our internal web-testing version of Edge will need to be - // updated before we can remove this check. See http://b/34945376. - // MOE:end_strip - var re = /Edge\/(\d+)(\.\d)*/i; - var edgeUserAgent = userAgent.match(re); - if (edgeUserAgent && Number(edgeUserAgent[1]) < 15) { - return false; - } - // Test es6: [FF50 (?), Edge 14 (?), Chrome 50] - // (a) default params (specifically shadowing locals), - // (b) destructuring, (c) block-scoped functions, - // (d) for-of (const), (e) new.target/Reflect.construct - var es6fullTest = - 'class X{constructor(){if(new.target!=String)throw 1;this.x=42}}' + - 'let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof ' + - 'String))throw 1;for(const a of[2,3]){if(a==2)continue;function ' + - 'f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()' + - '==3}'; - - return evalCheck('(()=>{"use strict";' + es6fullTest + '})()'); - }); - // TODO(joeltine): Remove es6-impl references for b/31340605. - // Consider es6-impl (widely-implemented es6 features) to be supported - // whenever es6 is supported. Technically es6-impl is a lower level of - // support than es6, but we don't have tests specifically for it. - addNewerLanguageTranspilationCheck('es6-impl', function() { - return true; - }); - // ** and **= are the only new features in 'es7' - addNewerLanguageTranspilationCheck('es7', function() { - return evalCheck('2 ** 2 == 4'); - }); - // async functions are the only new features in 'es8' - addNewerLanguageTranspilationCheck('es8', function() { - return evalCheck('async () => 1, true'); - }); - return requiresTranspilation; -};
diff --git a/third_party/ink/closure/crypt/base64.js b/third_party/ink/closure/crypt/base64.js deleted file mode 100644 index 026aa956..0000000 --- a/third_party/ink/closure/crypt/base64.js +++ /dev/null
@@ -1,370 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Base64 en/decoding. Not much to say here except that we - * work with decoded values in arrays of bytes. By "byte" I mean a number - * in [0, 255]. - * - * @author doughtie@google.com (Gavin Doughtie) - * @author fschneider@google.com (Fritz Schneider) - */ - -goog.provide('goog.crypt.base64'); - -goog.require('goog.asserts'); -goog.require('goog.crypt'); -goog.require('goog.string'); -goog.require('goog.userAgent'); -goog.require('goog.userAgent.product'); - -// Static lookup maps, lazily populated by init_() - - -/** - * Maps bytes to characters. - * @type {Object} - * @private - */ -goog.crypt.base64.byteToCharMap_ = null; - - -/** - * Maps characters to bytes. Used for normal and websafe characters. - * @type {Object} - * @private - */ -goog.crypt.base64.charToByteMap_ = null; - - -/** - * Maps bytes to websafe characters. - * @type {Object} - * @private - */ -goog.crypt.base64.byteToCharMapWebSafe_ = null; - - -/** - * Our default alphabet, shared between - * ENCODED_VALS and ENCODED_VALS_WEBSAFE - * @type {string} - */ -goog.crypt.base64.ENCODED_VALS_BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + - 'abcdefghijklmnopqrstuvwxyz' + - '0123456789'; - - -/** - * Our default alphabet. Value 64 (=) is special; it means "nothing." - * @type {string} - */ -goog.crypt.base64.ENCODED_VALS = goog.crypt.base64.ENCODED_VALS_BASE + '+/='; - - -/** - * Our websafe alphabet. - * @type {string} - */ -goog.crypt.base64.ENCODED_VALS_WEBSAFE = - goog.crypt.base64.ENCODED_VALS_BASE + '-_.'; - - -/** - * White list of implementations with known-good native atob and btoa functions. - * Listing these explicitly (via the ASSUME_* wrappers) benefits dead-code - * removal in per-browser compilations. - * @private {boolean} - */ -goog.crypt.base64.ASSUME_NATIVE_SUPPORT_ = goog.userAgent.GECKO || - (goog.userAgent.WEBKIT && !goog.userAgent.product.SAFARI) || - goog.userAgent.OPERA; - - -/** - * Does this browser have a working btoa function? - * @private {boolean} - */ -goog.crypt.base64.HAS_NATIVE_ENCODE_ = - goog.crypt.base64.ASSUME_NATIVE_SUPPORT_ || - typeof(goog.global.btoa) == 'function'; - - -/** - * Does this browser have a working atob function? - * We blacklist known-bad implementations: - * - IE (10+) added atob() but it does not tolerate whitespace on the input. - * @private {boolean} - */ -goog.crypt.base64.HAS_NATIVE_DECODE_ = - goog.crypt.base64.ASSUME_NATIVE_SUPPORT_ || - (!goog.userAgent.product.SAFARI && !goog.userAgent.IE && - typeof(goog.global.atob) == 'function'); - - -/** - * Base64-encode an array of bytes. - * - * @param {Array<number>|Uint8Array} input An array of bytes (numbers with - * value in [0, 255]) to encode. - * @param {boolean=} opt_webSafe True indicates we should use the alternative - * alphabet, which does not require escaping for use in URLs. - * @return {string} The base64 encoded string. - */ -goog.crypt.base64.encodeByteArray = function(input, opt_webSafe) { - // Assert avoids runtime dependency on goog.isArrayLike, which helps reduce - // size of jscompiler output, and which yields slight performance increase. - goog.asserts.assert( - goog.isArrayLike(input), 'encodeByteArray takes an array as a parameter'); - - goog.crypt.base64.init_(); - - var byteToCharMap = opt_webSafe ? goog.crypt.base64.byteToCharMapWebSafe_ : - goog.crypt.base64.byteToCharMap_; - - var output = []; - - for (var i = 0; i < input.length; i += 3) { - var byte1 = input[i]; - var haveByte2 = i + 1 < input.length; - var byte2 = haveByte2 ? input[i + 1] : 0; - var haveByte3 = i + 2 < input.length; - var byte3 = haveByte3 ? input[i + 2] : 0; - - var outByte1 = byte1 >> 2; - var outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4); - var outByte3 = ((byte2 & 0x0F) << 2) | (byte3 >> 6); - var outByte4 = byte3 & 0x3F; - - if (!haveByte3) { - outByte4 = 64; - - if (!haveByte2) { - outByte3 = 64; - } - } - - output.push( - byteToCharMap[outByte1], byteToCharMap[outByte2], - byteToCharMap[outByte3], byteToCharMap[outByte4]); - } - - return output.join(''); -}; - - -/** - * Base64-encode a string. - * - * @param {string} input A string to encode. - * @param {boolean=} opt_webSafe True indicates we should use the alternative - * alphabet, which does not require escaping for use in URLs. - * @return {string} The base64 encoded string. - */ -goog.crypt.base64.encodeString = function(input, opt_webSafe) { - // Shortcut for browsers that implement - // a native base64 encoder in the form of "btoa/atob" - if (goog.crypt.base64.HAS_NATIVE_ENCODE_ && !opt_webSafe) { - return goog.global.btoa(input); - } - return goog.crypt.base64.encodeByteArray( - goog.crypt.stringToByteArray(input), opt_webSafe); -}; - - -/** - * Base64-decode a string. - * - * @param {string} input Input to decode. Any whitespace is ignored, and the - * input maybe encoded with either supported alphabet (or a mix thereof). - * @param {boolean=} opt_webSafe True indicates we should use the alternative - * alphabet, which does not require escaping for use in URLs. Note that - * passing false may also still allow webSafe input decoding, when the - * fallback decoder is used on browsers without native support. - * @return {string} string representing the decoded value. - */ -goog.crypt.base64.decodeString = function(input, opt_webSafe) { - // Shortcut for browsers that implement - // a native base64 encoder in the form of "btoa/atob" - if (goog.crypt.base64.HAS_NATIVE_DECODE_ && !opt_webSafe) { - return goog.global.atob(input); - } - var output = ''; - function pushByte(b) { output += String.fromCharCode(b); } - - goog.crypt.base64.decodeStringInternal_(input, pushByte); - - return output; -}; - - -/** - * Base64-decode a string to an Array of numbers. - * - * In base-64 decoding, groups of four characters are converted into three - * bytes. If the encoder did not apply padding, the input length may not - * be a multiple of 4. - * - * In this case, the last group will have fewer than 4 characters, and - * padding will be inferred. If the group has one or two characters, it decodes - * to one byte. If the group has three characters, it decodes to two bytes. - * - * @param {string} input Input to decode. Any whitespace is ignored, and the - * input maybe encoded with either supported alphabet (or a mix thereof). - * @param {boolean=} opt_ignored Unused parameter, retained for compatibility. - * @return {!Array<number>} bytes representing the decoded value. - */ -goog.crypt.base64.decodeStringToByteArray = function(input, opt_ignored) { - var output = []; - function pushByte(b) { output.push(b); } - - goog.crypt.base64.decodeStringInternal_(input, pushByte); - - return output; -}; - - -/** - * Base64-decode a string to a Uint8Array. - * - * Note that Uint8Array is not supported on older browsers, e.g. IE < 10. - * @see http://caniuse.com/uint8array - * - * In base-64 decoding, groups of four characters are converted into three - * bytes. If the encoder did not apply padding, the input length may not - * be a multiple of 4. - * - * In this case, the last group will have fewer than 4 characters, and - * padding will be inferred. If the group has one or two characters, it decodes - * to one byte. If the group has three characters, it decodes to two bytes. - * - * @param {string} input Input to decode. Any whitespace is ignored, and the - * input maybe encoded with either supported alphabet (or a mix thereof). - * @return {!Uint8Array} bytes representing the decoded value. - */ -goog.crypt.base64.decodeStringToUint8Array = function(input) { - goog.asserts.assert( - !goog.userAgent.IE || goog.userAgent.isVersionOrHigher('10'), - 'Browser does not support typed arrays'); - var len = input.length; - // Check if there are trailing '=' as padding in the b64 string. - var placeholders = 0; - if (input[len - 2] === '=') { - placeholders = 2; - } else if (input[len - 1] === '=') { - placeholders = 1; - } - var output = new Uint8Array(Math.ceil(len * 3 / 4) - placeholders); - var outLen = 0; - function pushByte(b) { - output[outLen++] = b; - } - - goog.crypt.base64.decodeStringInternal_(input, pushByte); - - return output.subarray(0, outLen); -}; - - -/** - * @param {string} input Input to decode. - * @param {function(number):void} pushByte result accumulator. - * @private - */ -goog.crypt.base64.decodeStringInternal_ = function(input, pushByte) { - goog.crypt.base64.init_(); - - var nextCharIndex = 0; - /** - * @param {number} default_val Used for end-of-input. - * @return {number} The next 6-bit value, or the default for end-of-input. - */ - function getByte(default_val) { - while (nextCharIndex < input.length) { - var ch = input.charAt(nextCharIndex++); - var b = goog.crypt.base64.charToByteMap_[ch]; - if (b != null) { - return b; // Common case: decoded the char. - } - if (!goog.string.isEmptyOrWhitespace(ch)) { - throw new Error('Unknown base64 encoding at char: ' + ch); - } - // We encountered whitespace: loop around to the next input char. - } - return default_val; // No more input remaining. - } - - while (true) { - var byte1 = getByte(-1); - var byte2 = getByte(0); - var byte3 = getByte(64); - var byte4 = getByte(64); - - // The common case is that all four bytes are present, so if we have byte4 - // we can skip over the truncated input special case handling. - if (byte4 === 64) { - if (byte1 === -1) { - return; // Terminal case: no input left to decode. - } - // Here we know an intermediate number of bytes are missing. - // The defaults for byte2, byte3 and byte4 apply the inferred padding - // rules per the public API documentation. i.e: 1 byte - // missing should yield 2 bytes of output, but 2 or 3 missing bytes yield - // a single byte of output. (Recall that 64 corresponds the padding char). - } - - var outByte1 = (byte1 << 2) | (byte2 >> 4); - pushByte(outByte1); - - if (byte3 != 64) { - var outByte2 = ((byte2 << 4) & 0xF0) | (byte3 >> 2); - pushByte(outByte2); - - if (byte4 != 64) { - var outByte3 = ((byte3 << 6) & 0xC0) | byte4; - pushByte(outByte3); - } - } - } -}; - - -/** - * Lazy static initialization function. Called before - * accessing any of the static map variables. - * @private - */ -goog.crypt.base64.init_ = function() { - if (!goog.crypt.base64.byteToCharMap_) { - goog.crypt.base64.byteToCharMap_ = {}; - goog.crypt.base64.charToByteMap_ = {}; - goog.crypt.base64.byteToCharMapWebSafe_ = {}; - - // We want quick mappings back and forth, so we precompute two maps. - for (var i = 0; i < goog.crypt.base64.ENCODED_VALS.length; i++) { - goog.crypt.base64.byteToCharMap_[i] = - goog.crypt.base64.ENCODED_VALS.charAt(i); - goog.crypt.base64.charToByteMap_[goog.crypt.base64.byteToCharMap_[i]] = i; - goog.crypt.base64.byteToCharMapWebSafe_[i] = - goog.crypt.base64.ENCODED_VALS_WEBSAFE.charAt(i); - - // Be forgiving when decoding and correctly decode both encodings. - if (i >= goog.crypt.base64.ENCODED_VALS_BASE.length) { - goog.crypt.base64 - .charToByteMap_[goog.crypt.base64.ENCODED_VALS_WEBSAFE.charAt(i)] = - i; - } - } - } -};
diff --git a/third_party/ink/closure/crypt/crypt.js b/third_party/ink/closure/crypt/crypt.js deleted file mode 100644 index a0e4f02..0000000 --- a/third_party/ink/closure/crypt/crypt.js +++ /dev/null
@@ -1,196 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Namespace with crypto related helper functions. - * @author pupius@google.com (Daniel Pupius) - */ - -goog.provide('goog.crypt'); - -goog.require('goog.array'); -goog.require('goog.asserts'); - - -/** - * Turns a string into an array of bytes; a "byte" being a JS number in the - * range 0-255. Multi-byte characters are written as little-endian. - * @param {string} str String value to arrify. - * @return {!Array<number>} Array of numbers corresponding to the - * UCS character codes of each character in str. - */ -goog.crypt.stringToByteArray = function(str) { - var output = [], p = 0; - for (var i = 0; i < str.length; i++) { - var c = str.charCodeAt(i); - // NOTE: c <= 0xffff since JavaScript strings are UTF-16. - if (c > 0xff) { - output[p++] = c & 0xff; - c >>= 8; - } - output[p++] = c; - } - return output; -}; - - -/** - * Turns an array of numbers into the string given by the concatenation of the - * characters to which the numbers correspond. - * @param {!Uint8Array|!Array<number>} bytes Array of numbers representing - * characters. - * @return {string} Stringification of the array. - */ -goog.crypt.byteArrayToString = function(bytes) { - var CHUNK_SIZE = 8192; - - // Special-case the simple case for speed's sake. - if (bytes.length <= CHUNK_SIZE) { - return String.fromCharCode.apply(null, bytes); - } - - // The remaining logic splits conversion by chunks since - // Function#apply() has a maximum parameter count. - // See discussion: http://goo.gl/LrWmZ9 - - var str = ''; - for (var i = 0; i < bytes.length; i += CHUNK_SIZE) { - var chunk = goog.array.slice(bytes, i, i + CHUNK_SIZE); - str += String.fromCharCode.apply(null, chunk); - } - return str; -}; - - -/** - * Turns an array of numbers into the hex string given by the concatenation of - * the hex values to which the numbers correspond. - * @param {Uint8Array|Array<number>} array Array of numbers representing - * characters. - * @return {string} Hex string. - */ -goog.crypt.byteArrayToHex = function(array) { - return goog.array - .map( - array, - function(numByte) { - var hexByte = numByte.toString(16); - return hexByte.length > 1 ? hexByte : '0' + hexByte; - }) - .join(''); -}; - - -/** - * Converts a hex string into an integer array. - * @param {string} hexString Hex string of 16-bit integers (two characters - * per integer). - * @return {!Array<number>} Array of {0,255} integers for the given string. - */ -goog.crypt.hexToByteArray = function(hexString) { - goog.asserts.assert( - hexString.length % 2 == 0, 'Key string length must be multiple of 2'); - var arr = []; - for (var i = 0; i < hexString.length; i += 2) { - arr.push(parseInt(hexString.substring(i, i + 2), 16)); - } - return arr; -}; - - -/** - * Converts a JS string to a UTF-8 "byte" array. - * @param {string} str 16-bit unicode string. - * @return {!Array<number>} UTF-8 byte array. - */ -goog.crypt.stringToUtf8ByteArray = function(str) { - // TODO(pupius): Use native implementations if/when available - var out = [], p = 0; - for (var i = 0; i < str.length; i++) { - var c = str.charCodeAt(i); - if (c < 128) { - out[p++] = c; - } else if (c < 2048) { - out[p++] = (c >> 6) | 192; - out[p++] = (c & 63) | 128; - } else if ( - ((c & 0xFC00) == 0xD800) && (i + 1) < str.length && - ((str.charCodeAt(i + 1) & 0xFC00) == 0xDC00)) { - // Surrogate Pair - c = 0x10000 + ((c & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF); - out[p++] = (c >> 18) | 240; - out[p++] = ((c >> 12) & 63) | 128; - out[p++] = ((c >> 6) & 63) | 128; - out[p++] = (c & 63) | 128; - } else { - out[p++] = (c >> 12) | 224; - out[p++] = ((c >> 6) & 63) | 128; - out[p++] = (c & 63) | 128; - } - } - return out; -}; - - -/** - * Converts a UTF-8 byte array to JavaScript's 16-bit Unicode. - * @param {Uint8Array|Array<number>} bytes UTF-8 byte array. - * @return {string} 16-bit Unicode string. - */ -goog.crypt.utf8ByteArrayToString = function(bytes) { - // TODO(pupius): Use native implementations if/when available - var out = [], pos = 0, c = 0; - while (pos < bytes.length) { - var c1 = bytes[pos++]; - if (c1 < 128) { - out[c++] = String.fromCharCode(c1); - } else if (c1 > 191 && c1 < 224) { - var c2 = bytes[pos++]; - out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63); - } else if (c1 > 239 && c1 < 365) { - // Surrogate Pair - var c2 = bytes[pos++]; - var c3 = bytes[pos++]; - var c4 = bytes[pos++]; - var u = ((c1 & 7) << 18 | (c2 & 63) << 12 | (c3 & 63) << 6 | c4 & 63) - - 0x10000; - out[c++] = String.fromCharCode(0xD800 + (u >> 10)); - out[c++] = String.fromCharCode(0xDC00 + (u & 1023)); - } else { - var c2 = bytes[pos++]; - var c3 = bytes[pos++]; - out[c++] = - String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63); - } - } - return out.join(''); -}; - - -/** - * XOR two byte arrays. - * @param {!Uint8Array|!Int8Array|!Array<number>} bytes1 Byte array 1. - * @param {!Uint8Array|!Int8Array|!Array<number>} bytes2 Byte array 2. - * @return {!Array<number>} Resulting XOR of the two byte arrays. - */ -goog.crypt.xorByteArray = function(bytes1, bytes2) { - goog.asserts.assert( - bytes1.length == bytes2.length, 'XOR array lengths must match'); - - var result = []; - for (var i = 0; i < bytes1.length; i++) { - result.push(bytes1[i] ^ bytes2[i]); - } - return result; -};
diff --git a/third_party/ink/closure/debug/debug.js b/third_party/ink/closure/debug/debug.js deleted file mode 100644 index 92d1945..0000000 --- a/third_party/ink/closure/debug/debug.js +++ /dev/null
@@ -1,666 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Logging and debugging utilities. - * - * @author pupius@google.com (Daniel Pupius) - * @see ../demos/debug.html - */ - -goog.provide('goog.debug'); - -goog.require('goog.array'); -goog.require('goog.debug.errorcontext'); -goog.require('goog.userAgent'); - - -/** @define {boolean} Whether logging should be enabled. */ -goog.define('goog.debug.LOGGING_ENABLED', goog.DEBUG); - - -/** @define {boolean} Whether to force "sloppy" stack building. */ -goog.define('goog.debug.FORCE_SLOPPY_STACKS', false); - - -/** - * Catches onerror events fired by windows and similar objects. - * @param {function(Object)} logFunc The function to call with the error - * information. - * @param {boolean=} opt_cancel Whether to stop the error from reaching the - * browser. - * @param {Object=} opt_target Object that fires onerror events. - */ -goog.debug.catchErrors = function(logFunc, opt_cancel, opt_target) { - var target = opt_target || goog.global; - var oldErrorHandler = target.onerror; - var retVal = !!opt_cancel; - - // Chrome interprets onerror return value backwards (http://crbug.com/92062) - // until it was fixed in webkit revision r94061 (Webkit 535.3). This - // workaround still needs to be skipped in Safari after the webkit change - // gets pushed out in Safari. - // See https://bugs.webkit.org/show_bug.cgi?id=67119 - if (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('535.3')) { - retVal = !retVal; - } - - /** - * New onerror handler for this target. This onerror handler follows the spec - * according to - * http://www.whatwg.org/specs/web-apps/current-work/#runtime-script-errors - * The spec was changed in August 2013 to support receiving column information - * and an error object for all scripts on the same origin or cross origin - * scripts with the proper headers. See - * https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror - * - * @param {string} message The error message. For cross-origin errors, this - * will be scrubbed to just "Script error.". For new browsers that have - * updated to follow the latest spec, errors that come from origins that - * have proper cross origin headers will not be scrubbed. - * @param {string} url The URL of the script that caused the error. The URL - * will be scrubbed to "" for cross origin scripts unless the script has - * proper cross origin headers and the browser has updated to the latest - * spec. - * @param {number} line The line number in the script that the error - * occurred on. - * @param {number=} opt_col The optional column number that the error - * occurred on. Only browsers that have updated to the latest spec will - * include this. - * @param {Error=} opt_error The optional actual error object for this - * error that should include the stack. Only browsers that have updated - * to the latest spec will inlude this parameter. - * @return {boolean} Whether to prevent the error from reaching the browser. - */ - target.onerror = function(message, url, line, opt_col, opt_error) { - if (oldErrorHandler) { - oldErrorHandler(message, url, line, opt_col, opt_error); - } - logFunc({ - message: message, - fileName: url, - line: line, - lineNumber: line, - col: opt_col, - error: opt_error - }); - return retVal; - }; -}; - - -/** - * Creates a string representing an object and all its properties. - * @param {Object|null|undefined} obj Object to expose. - * @param {boolean=} opt_showFn Show the functions as well as the properties, - * default is false. - * @return {string} The string representation of {@code obj}. - */ -goog.debug.expose = function(obj, opt_showFn) { - if (typeof obj == 'undefined') { - return 'undefined'; - } - if (obj == null) { - return 'NULL'; - } - var str = []; - - for (var x in obj) { - if (!opt_showFn && goog.isFunction(obj[x])) { - continue; - } - var s = x + ' = '; - - try { - s += obj[x]; - } catch (e) { - s += '*** ' + e + ' ***'; - } - str.push(s); - } - return str.join('\n'); -}; - - -/** - * Creates a string representing a given primitive or object, and for an - * object, all its properties and nested objects. NOTE: The output will include - * Uids on all objects that were exposed. Any added Uids will be removed before - * returning. - * @param {*} obj Object to expose. - * @param {boolean=} opt_showFn Also show properties that are functions (by - * default, functions are omitted). - * @return {string} A string representation of {@code obj}. - */ -goog.debug.deepExpose = function(obj, opt_showFn) { - var str = []; - - // Track any objects where deepExpose added a Uid, so they can be cleaned up - // before return. We do this globally, rather than only on ancestors so that - // if the same object appears in the output, you can see it. - var uidsToCleanup = []; - var ancestorUids = {}; - - var helper = function(obj, space) { - var nestspace = space + ' '; - - var indentMultiline = function(str) { - return str.replace(/\n/g, '\n' + space); - }; - - - try { - if (!goog.isDef(obj)) { - str.push('undefined'); - } else if (goog.isNull(obj)) { - str.push('NULL'); - } else if (goog.isString(obj)) { - str.push('"' + indentMultiline(obj) + '"'); - } else if (goog.isFunction(obj)) { - str.push(indentMultiline(String(obj))); - } else if (goog.isObject(obj)) { - // Add a Uid if needed. The struct calls implicitly adds them. - if (!goog.hasUid(obj)) { - uidsToCleanup.push(obj); - } - var uid = goog.getUid(obj); - if (ancestorUids[uid]) { - str.push('*** reference loop detected (id=' + uid + ') ***'); - } else { - ancestorUids[uid] = true; - str.push('{'); - for (var x in obj) { - if (!opt_showFn && goog.isFunction(obj[x])) { - continue; - } - str.push('\n'); - str.push(nestspace); - str.push(x + ' = '); - helper(obj[x], nestspace); - } - str.push('\n' + space + '}'); - delete ancestorUids[uid]; - } - } else { - str.push(obj); - } - } catch (e) { - str.push('*** ' + e + ' ***'); - } - }; - - helper(obj, ''); - - // Cleanup any Uids that were added by the deepExpose. - for (var i = 0; i < uidsToCleanup.length; i++) { - goog.removeUid(uidsToCleanup[i]); - } - - return str.join(''); -}; - - -/** - * Recursively outputs a nested array as a string. - * @param {Array<?>} arr The array. - * @return {string} String representing nested array. - */ -goog.debug.exposeArray = function(arr) { - var str = []; - for (var i = 0; i < arr.length; i++) { - if (goog.isArray(arr[i])) { - str.push(goog.debug.exposeArray(arr[i])); - } else { - str.push(arr[i]); - } - } - return '[ ' + str.join(', ') + ' ]'; -}; - - -/** - * Normalizes the error/exception object between browsers. - * @param {*} err Raw error object. - * @return {!{ - * message: (?|undefined), - * name: (?|undefined), - * lineNumber: (?|undefined), - * fileName: (?|undefined), - * stack: (?|undefined) - * }} Normalized error object. - */ -goog.debug.normalizeErrorObject = function(err) { - var href = goog.getObjectByName('window.location.href'); - if (goog.isString(err)) { - return { - 'message': err, - 'name': 'Unknown error', - 'lineNumber': 'Not available', - 'fileName': href, - 'stack': 'Not available' - }; - } - - var lineNumber, fileName; - var threwError = false; - - try { - lineNumber = err.lineNumber || err.line || 'Not available'; - } catch (e) { - // Firefox 2 sometimes throws an error when accessing 'lineNumber': - // Message: Permission denied to get property UnnamedClass.lineNumber - lineNumber = 'Not available'; - threwError = true; - } - - try { - fileName = err.fileName || err.filename || err.sourceURL || - // $googDebugFname may be set before a call to eval to set the filename - // that the eval is supposed to present. - goog.global['$googDebugFname'] || href; - } catch (e) { - // Firefox 2 may also throw an error when accessing 'filename'. - fileName = 'Not available'; - threwError = true; - } - - // The IE Error object contains only the name and the message. - // The Safari Error object uses the line and sourceURL fields. - if (threwError || !err.lineNumber || !err.fileName || !err.stack || - !err.message || !err.name) { - return { - 'message': err.message || 'Not available', - 'name': err.name || 'UnknownError', - 'lineNumber': lineNumber, - 'fileName': fileName, - 'stack': err.stack || 'Not available' - }; - } - - // Standards error object - // Typed !Object. Should be a subtype of the return type, but it's not. - return /** @type {?} */ (err); -}; - - -/** - * Converts an object to an Error using the object's toString if it's not - * already an Error, adds a stacktrace if there isn't one, and optionally adds - * an extra message. - * @param {*} err The original thrown error, object, or string. - * @param {string=} opt_message optional additional message to add to the - * error. - * @return {!Error} If err is an Error, it is enhanced and returned. Otherwise, - * it is converted to an Error which is enhanced and returned. - */ -goog.debug.enhanceError = function(err, opt_message) { - var error; - if (!(err instanceof Error)) { - error = Error(err); - if (Error.captureStackTrace) { - // Trim this function off the call stack, if we can. - Error.captureStackTrace(error, goog.debug.enhanceError); - } - } else { - error = err; - } - - if (!error.stack) { - error.stack = goog.debug.getStacktrace(goog.debug.enhanceError); - } - if (opt_message) { - // find the first unoccupied 'messageX' property - var x = 0; - while (error['message' + x]) { - ++x; - } - error['message' + x] = String(opt_message); - } - return error; -}; - - -/** - * Converts an object to an Error using the object's toString if it's not - * already an Error, adds a stacktrace if there isn't one, and optionally adds - * context to the Error, which is reported by the closure error reporter. - * @param {*} err The original thrown error, object, or string. - * @param {!Object<string, string>=} opt_context Key-value context to add to the - * Error. - * @return {!Error} If err is an Error, it is enhanced and returned. Otherwise, - * it is converted to an Error which is enhanced and returned. - */ -goog.debug.enhanceErrorWithContext = function(err, opt_context) { - var error = goog.debug.enhanceError(err); - if (opt_context) { - for (var key in opt_context) { - goog.debug.errorcontext.addErrorContext(error, key, opt_context[key]); - } - } - return error; -}; - - -/** - * Gets the current stack trace. Simple and iterative - doesn't worry about - * catching circular references or getting the args. - * @param {number=} opt_depth Optional maximum depth to trace back to. - * @return {string} A string with the function names of all functions in the - * stack, separated by \n. - * @suppress {es5Strict} - */ -goog.debug.getStacktraceSimple = function(opt_depth) { - if (!goog.debug.FORCE_SLOPPY_STACKS) { - var stack = goog.debug.getNativeStackTrace_(goog.debug.getStacktraceSimple); - if (stack) { - return stack; - } - // NOTE: browsers that have strict mode support also have native "stack" - // properties. Fall-through for legacy browser support. - } - - var sb = []; - var fn = arguments.callee.caller; - var depth = 0; - - while (fn && (!opt_depth || depth < opt_depth)) { - sb.push(goog.debug.getFunctionName(fn)); - sb.push('()\n'); - - try { - fn = fn.caller; - } catch (e) { - sb.push('[exception trying to get caller]\n'); - break; - } - depth++; - if (depth >= goog.debug.MAX_STACK_DEPTH) { - sb.push('[...long stack...]'); - break; - } - } - if (opt_depth && depth >= opt_depth) { - sb.push('[...reached max depth limit...]'); - } else { - sb.push('[end]'); - } - - return sb.join(''); -}; - - -/** - * Max length of stack to try and output - * @type {number} - */ -goog.debug.MAX_STACK_DEPTH = 50; - - -/** - * @param {Function} fn The function to start getting the trace from. - * @return {?string} - * @private - */ -goog.debug.getNativeStackTrace_ = function(fn) { - var tempErr = new Error(); - if (Error.captureStackTrace) { - Error.captureStackTrace(tempErr, fn); - return String(tempErr.stack); - } else { - // IE10, only adds stack traces when an exception is thrown. - try { - throw tempErr; - } catch (e) { - tempErr = e; - } - var stack = tempErr.stack; - if (stack) { - return String(stack); - } - } - return null; -}; - - -/** - * Gets the current stack trace, either starting from the caller or starting - * from a specified function that's currently on the call stack. - * @param {?Function=} fn If provided, when collecting the stack trace all - * frames above the topmost call to this function, including that call, - * will be left out of the stack trace. - * @return {string} Stack trace. - * @suppress {es5Strict} - */ -goog.debug.getStacktrace = function(fn) { - var stack; - if (!goog.debug.FORCE_SLOPPY_STACKS) { - // Try to get the stack trace from the environment if it is available. - var contextFn = fn || goog.debug.getStacktrace; - stack = goog.debug.getNativeStackTrace_(contextFn); - } - if (!stack) { - // NOTE: browsers that have strict mode support also have native "stack" - // properties. This function will throw in strict mode. - stack = goog.debug.getStacktraceHelper_(fn || arguments.callee.caller, []); - } - return stack; -}; - - -/** - * Private helper for getStacktrace(). - * @param {?Function} fn If provided, when collecting the stack trace all - * frames above the topmost call to this function, including that call, - * will be left out of the stack trace. - * @param {Array<!Function>} visited List of functions visited so far. - * @return {string} Stack trace starting from function fn. - * @suppress {es5Strict} - * @private - */ -goog.debug.getStacktraceHelper_ = function(fn, visited) { - var sb = []; - - // Circular reference, certain functions like bind seem to cause a recursive - // loop so we need to catch circular references - if (goog.array.contains(visited, fn)) { - sb.push('[...circular reference...]'); - - // Traverse the call stack until function not found or max depth is reached - } else if (fn && visited.length < goog.debug.MAX_STACK_DEPTH) { - sb.push(goog.debug.getFunctionName(fn) + '('); - var args = fn.arguments; - // Args may be null for some special functions such as host objects or eval. - for (var i = 0; args && i < args.length; i++) { - if (i > 0) { - sb.push(', '); - } - var argDesc; - var arg = args[i]; - switch (typeof arg) { - case 'object': - argDesc = arg ? 'object' : 'null'; - break; - - case 'string': - argDesc = arg; - break; - - case 'number': - argDesc = String(arg); - break; - - case 'boolean': - argDesc = arg ? 'true' : 'false'; - break; - - case 'function': - argDesc = goog.debug.getFunctionName(arg); - argDesc = argDesc ? argDesc : '[fn]'; - break; - - case 'undefined': - default: - argDesc = typeof arg; - break; - } - - if (argDesc.length > 40) { - argDesc = argDesc.substr(0, 40) + '...'; - } - sb.push(argDesc); - } - visited.push(fn); - sb.push(')\n'); - - try { - sb.push(goog.debug.getStacktraceHelper_(fn.caller, visited)); - } catch (e) { - sb.push('[exception trying to get caller]\n'); - } - - } else if (fn) { - sb.push('[...long stack...]'); - } else { - sb.push('[end]'); - } - return sb.join(''); -}; - - -/** - * Set a custom function name resolver. - * @param {function(Function): string} resolver Resolves functions to their - * names. - */ -goog.debug.setFunctionResolver = function(resolver) { - goog.debug.fnNameResolver_ = resolver; -}; - - -/** - * Gets a function name - * @param {Function} fn Function to get name of. - * @return {string} Function's name. - */ -goog.debug.getFunctionName = function(fn) { - if (goog.debug.fnNameCache_[fn]) { - return goog.debug.fnNameCache_[fn]; - } - if (goog.debug.fnNameResolver_) { - var name = goog.debug.fnNameResolver_(fn); - if (name) { - goog.debug.fnNameCache_[fn] = name; - return name; - } - } - - // Heuristically determine function name based on code. - var functionSource = String(fn); - if (!goog.debug.fnNameCache_[functionSource]) { - var matches = /function ([^\(]+)/.exec(functionSource); - if (matches) { - var method = matches[1]; - goog.debug.fnNameCache_[functionSource] = method; - } else { - goog.debug.fnNameCache_[functionSource] = '[Anonymous]'; - } - } - - return goog.debug.fnNameCache_[functionSource]; -}; - - -/** - * Makes whitespace visible by replacing it with printable characters. - * This is useful in finding diffrences between the expected and the actual - * output strings of a testcase. - * @param {string} string whose whitespace needs to be made visible. - * @return {string} string whose whitespace is made visible. - */ -goog.debug.makeWhitespaceVisible = function(string) { - return string.replace(/ /g, '[_]') - .replace(/\f/g, '[f]') - .replace(/\n/g, '[n]\n') - .replace(/\r/g, '[r]') - .replace(/\t/g, '[t]'); -}; - - -/** - * Returns the type of a value. If a constructor is passed, and a suitable - * string cannot be found, 'unknown type name' will be returned. - * - * <p>Forked rather than moved from {@link goog.asserts.getType_} - * to avoid adding a dependency to goog.asserts. - * @param {*} value A constructor, object, or primitive. - * @return {string} The best display name for the value, or 'unknown type name'. - */ -goog.debug.runtimeType = function(value) { - if (value instanceof Function) { - return value.displayName || value.name || 'unknown type name'; - } else if (value instanceof Object) { - return value.constructor.displayName || value.constructor.name || - Object.prototype.toString.call(value); - } else { - return value === null ? 'null' : typeof value; - } -}; - - -/** - * Hash map for storing function names that have already been looked up. - * @type {Object} - * @private - */ -goog.debug.fnNameCache_ = {}; - - -/** - * Resolves functions to their names. Resolved function names will be cached. - * @type {function(Function):string} - * @private - */ -goog.debug.fnNameResolver_; - - -/** - * Private internal function to support goog.debug.freeze. - * @param {T} arg - * @return {T} - * @template T - * @private - */ -goog.debug.freezeInternal_ = goog.DEBUG && Object.freeze || function(arg) { - return arg; -}; - - -/** - * Freezes the given object, but only in debug mode (and in browsers that - * support it). Note that this is a shallow freeze, so for deeply nested - * objects it must be called at every level to ensure deep immutability. - * @param {T} arg - * @return {T} - * @template T - */ -goog.debug.freeze = function(arg) { - // NOTE: this compiles to nothing, but hides the possible side effect of - // freezeInternal_ from the compiler so that the entire call can be - // removed if the result is not used. - return { - valueOf: function() { - return goog.debug.freezeInternal_(arg); - } - }.valueOf(); -};
diff --git a/third_party/ink/closure/debug/entrypointregistry.js b/third_party/ink/closure/debug/entrypointregistry.js deleted file mode 100644 index 336e1468..0000000 --- a/third_party/ink/closure/debug/entrypointregistry.js +++ /dev/null
@@ -1,159 +0,0 @@ -// Copyright 2010 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A global registry for entry points into a program, - * so that they can be instrumented. Each module should register their - * entry points with this registry. Designed to be compiled out - * if no instrumentation is requested. - * - * Entry points may be registered before or after a call to - * goog.debug.entryPointRegistry.monitorAll. If an entry point is registered - * later, the existing monitor will instrument the new entry point. - * - * @author nicksantos@google.com (Nick Santos) - */ - -goog.provide('goog.debug.EntryPointMonitor'); -goog.provide('goog.debug.entryPointRegistry'); - -goog.require('goog.asserts'); - - - -/** - * @interface - */ -goog.debug.EntryPointMonitor = function() {}; - - -/** - * Instruments a function. - * - * @param {!Function} fn A function to instrument. - * @return {!Function} The instrumented function. - */ -goog.debug.EntryPointMonitor.prototype.wrap; - - -/** - * Try to remove an instrumentation wrapper created by this monitor. - * If the function passed to unwrap is not a wrapper created by this - * monitor, then we will do nothing. - * - * Notice that some wrappers may not be unwrappable. For example, if other - * monitors have applied their own wrappers, then it will be impossible to - * unwrap them because their wrappers will have captured our wrapper. - * - * So it is important that entry points are unwrapped in the reverse - * order that they were wrapped. - * - * @param {!Function} fn A function to unwrap. - * @return {!Function} The unwrapped function, or {@code fn} if it was not - * a wrapped function created by this monitor. - */ -goog.debug.EntryPointMonitor.prototype.unwrap; - - -/** - * An array of entry point callbacks. - * @type {!Array<function(!Function)>} - * @private - */ -goog.debug.entryPointRegistry.refList_ = []; - - -/** - * Monitors that should wrap all the entry points. - * @type {!Array<!goog.debug.EntryPointMonitor>} - * @private - */ -goog.debug.entryPointRegistry.monitors_ = []; - - -/** - * Whether goog.debug.entryPointRegistry.monitorAll has ever been called. - * Checking this allows the compiler to optimize out the registrations. - * @type {boolean} - * @private - */ -goog.debug.entryPointRegistry.monitorsMayExist_ = false; - - -/** - * Register an entry point with this module. - * - * The entry point will be instrumented when a monitor is passed to - * goog.debug.entryPointRegistry.monitorAll. If this has already occurred, the - * entry point is instrumented immediately. - * - * @param {function(!Function)} callback A callback function which is called - * with a transforming function to instrument the entry point. The callback - * is responsible for wrapping the relevant entry point with the - * transforming function. - */ -goog.debug.entryPointRegistry.register = function(callback) { - // Don't use push(), so that this can be compiled out. - goog.debug.entryPointRegistry - .refList_[goog.debug.entryPointRegistry.refList_.length] = callback; - // If no one calls monitorAll, this can be compiled out. - if (goog.debug.entryPointRegistry.monitorsMayExist_) { - var monitors = goog.debug.entryPointRegistry.monitors_; - for (var i = 0; i < monitors.length; i++) { - callback(goog.bind(monitors[i].wrap, monitors[i])); - } - } -}; - - -/** - * Configures a monitor to wrap all entry points. - * - * Entry points that have already been registered are immediately wrapped by - * the monitor. When an entry point is registered in the future, it will also - * be wrapped by the monitor when it is registered. - * - * @param {!goog.debug.EntryPointMonitor} monitor An entry point monitor. - */ -goog.debug.entryPointRegistry.monitorAll = function(monitor) { - goog.debug.entryPointRegistry.monitorsMayExist_ = true; - var transformer = goog.bind(monitor.wrap, monitor); - for (var i = 0; i < goog.debug.entryPointRegistry.refList_.length; i++) { - goog.debug.entryPointRegistry.refList_[i](transformer); - } - goog.debug.entryPointRegistry.monitors_.push(monitor); -}; - - -/** - * Try to unmonitor all the entry points that have already been registered. If - * an entry point is registered in the future, it will not be wrapped by the - * monitor when it is registered. Note that this may fail if the entry points - * have additional wrapping. - * - * @param {!goog.debug.EntryPointMonitor} monitor The last monitor to wrap - * the entry points. - * @throws {Error} If the monitor is not the most recently configured monitor. - */ -goog.debug.entryPointRegistry.unmonitorAllIfPossible = function(monitor) { - var monitors = goog.debug.entryPointRegistry.monitors_; - goog.asserts.assert( - monitor == monitors[monitors.length - 1], - 'Only the most recent monitor can be unwrapped.'); - var transformer = goog.bind(monitor.unwrap, monitor); - for (var i = 0; i < goog.debug.entryPointRegistry.refList_.length; i++) { - goog.debug.entryPointRegistry.refList_[i](transformer); - } - monitors.length--; -};
diff --git a/third_party/ink/closure/debug/error.js b/third_party/ink/closure/debug/error.js deleted file mode 100644 index 2099b56..0000000 --- a/third_party/ink/closure/debug/error.js +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2009 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Provides a base class for custom Error objects such that the - * stack is correctly maintained. - * - * You should never need to throw goog.debug.Error(msg) directly, Error(msg) is - * sufficient. - * - * @author pupius@google.com (Daniel Pupius) - */ - -goog.provide('goog.debug.Error'); - - - -/** - * Base class for custom error objects. - * @param {*=} opt_msg The message associated with the error. - * @constructor - * @extends {Error} - */ -goog.debug.Error = function(opt_msg) { - - // Attempt to ensure there is a stack trace. - if (Error.captureStackTrace) { - Error.captureStackTrace(this, goog.debug.Error); - } else { - var stack = new Error().stack; - if (stack) { - /** @override */ - this.stack = stack; - } - } - - if (opt_msg) { - /** @override */ - this.message = String(opt_msg); - } - - /** - * Whether to report this error to the server. Setting this to false will - * cause the error reporter to not report the error back to the server, - * which can be useful if the client knows that the error has already been - * logged on the server. - * @type {boolean} - */ - this.reportErrorToServer = true; -}; -goog.inherits(goog.debug.Error, Error); - - -/** @override */ -goog.debug.Error.prototype.name = 'CustomError';
diff --git a/third_party/ink/closure/debug/errorcontext.js b/third_party/ink/closure/debug/errorcontext.js deleted file mode 100644 index 683454a3..0000000 --- a/third_party/ink/closure/debug/errorcontext.js +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2017 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Provides methods dealing with context on error objects. - */ - -goog.provide('goog.debug.errorcontext'); - - -/** - * Adds key-value context to the error. - * @param {!Error} err The error to add context to. - * @param {string} contextKey Key for the context to be added. - * @param {string} contextValue Value for the context to be added. - */ -goog.debug.errorcontext.addErrorContext = function( - err, contextKey, contextValue) { - if (!err[goog.debug.errorcontext.CONTEXT_KEY_]) { - err[goog.debug.errorcontext.CONTEXT_KEY_] = {}; - } - err[goog.debug.errorcontext.CONTEXT_KEY_][contextKey] = contextValue; -}; - - -/** - * @param {!Error} err The error to get context from. - * @return {!Object<string, string>} The context of the provided error. - */ -goog.debug.errorcontext.getErrorContext = function(err) { - return err[goog.debug.errorcontext.CONTEXT_KEY_] || {}; -}; - - -// TODO(aaronsn): convert this to a Symbol once goog.debug.ErrorReporter is -// able to use ES6. -/** @private @const {string} */ -goog.debug.errorcontext.CONTEXT_KEY_ = '__closure__error__context__984382';
diff --git a/third_party/ink/closure/disposable/disposable.js b/third_party/ink/closure/disposable/disposable.js deleted file mode 100644 index b3e8138..0000000 --- a/third_party/ink/closure/disposable/disposable.js +++ /dev/null
@@ -1,305 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Implements the disposable interface. The dispose method is used - * to clean up references and resources. - * @author arv@google.com (Erik Arvidsson) - */ - - -goog.provide('goog.Disposable'); -goog.provide('goog.dispose'); -goog.provide('goog.disposeAll'); - -goog.require('goog.disposable.IDisposable'); - - - -/** - * Class that provides the basic implementation for disposable objects. If your - * class holds one or more references to COM objects, DOM nodes, or other - * disposable objects, it should extend this class or implement the disposable - * interface (defined in goog.disposable.IDisposable). - * @constructor - * @implements {goog.disposable.IDisposable} - */ -goog.Disposable = function() { - /** - * If monitoring the goog.Disposable instances is enabled, stores the creation - * stack trace of the Disposable instance. - * @type {string|undefined} - */ - this.creationStack; - - if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) { - if (goog.Disposable.INCLUDE_STACK_ON_CREATION) { - this.creationStack = new Error().stack; - } - goog.Disposable.instances_[goog.getUid(this)] = this; - } - // Support sealing - this.disposed_ = this.disposed_; - this.onDisposeCallbacks_ = this.onDisposeCallbacks_; -}; - - -/** - * @enum {number} Different monitoring modes for Disposable. - */ -goog.Disposable.MonitoringMode = { - /** - * No monitoring. - */ - OFF: 0, - /** - * Creating and disposing the goog.Disposable instances is monitored. All - * disposable objects need to call the {@code goog.Disposable} base - * constructor. The PERMANENT mode must be switched on before creating any - * goog.Disposable instances. - */ - PERMANENT: 1, - /** - * INTERACTIVE mode can be switched on and off on the fly without producing - * errors. It also doesn't warn if the disposable objects don't call the - * {@code goog.Disposable} base constructor. - */ - INTERACTIVE: 2 -}; - - -/** - * @define {number} The monitoring mode of the goog.Disposable - * instances. Default is OFF. Switching on the monitoring is only - * recommended for debugging because it has a significant impact on - * performance and memory usage. If switched off, the monitoring code - * compiles down to 0 bytes. - */ -goog.define('goog.Disposable.MONITORING_MODE', 0); - - -/** - * @define {boolean} Whether to attach creation stack to each created disposable - * instance; This is only relevant for when MonitoringMode != OFF. - */ -goog.define('goog.Disposable.INCLUDE_STACK_ON_CREATION', true); - - -/** - * Maps the unique ID of every undisposed {@code goog.Disposable} object to - * the object itself. - * @type {!Object<number, !goog.Disposable>} - * @private - */ -goog.Disposable.instances_ = {}; - - -/** - * @return {!Array<!goog.Disposable>} All {@code goog.Disposable} objects that - * haven't been disposed of. - */ -goog.Disposable.getUndisposedObjects = function() { - var ret = []; - for (var id in goog.Disposable.instances_) { - if (goog.Disposable.instances_.hasOwnProperty(id)) { - ret.push(goog.Disposable.instances_[Number(id)]); - } - } - return ret; -}; - - -/** - * Clears the registry of undisposed objects but doesn't dispose of them. - */ -goog.Disposable.clearUndisposedObjects = function() { - goog.Disposable.instances_ = {}; -}; - - -/** - * Whether the object has been disposed of. - * @type {boolean} - * @private - */ -goog.Disposable.prototype.disposed_ = false; - - -/** - * Callbacks to invoke when this object is disposed. - * @type {Array<!Function>} - * @private - */ -goog.Disposable.prototype.onDisposeCallbacks_; - - -/** - * @return {boolean} Whether the object has been disposed of. - * @override - */ -goog.Disposable.prototype.isDisposed = function() { - return this.disposed_; -}; - - -/** - * @return {boolean} Whether the object has been disposed of. - * @deprecated Use {@link #isDisposed} instead. - */ -goog.Disposable.prototype.getDisposed = goog.Disposable.prototype.isDisposed; - - -/** - * Disposes of the object. If the object hasn't already been disposed of, calls - * {@link #disposeInternal}. Classes that extend {@code goog.Disposable} should - * override {@link #disposeInternal} in order to delete references to COM - * objects, DOM nodes, and other disposable objects. Reentrant. - * - * @return {void} Nothing. - * @override - */ -goog.Disposable.prototype.dispose = function() { - if (!this.disposed_) { - // Set disposed_ to true first, in case during the chain of disposal this - // gets disposed recursively. - this.disposed_ = true; - this.disposeInternal(); - if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) { - var uid = goog.getUid(this); - if (goog.Disposable.MONITORING_MODE == - goog.Disposable.MonitoringMode.PERMANENT && - !goog.Disposable.instances_.hasOwnProperty(uid)) { - throw new Error( - this + ' did not call the goog.Disposable base ' + - 'constructor or was disposed of after a clearUndisposedObjects ' + - 'call'); - } - delete goog.Disposable.instances_[uid]; - } - } -}; - - -/** - * Associates a disposable object with this object so that they will be disposed - * together. - * @param {goog.disposable.IDisposable} disposable that will be disposed when - * this object is disposed. - */ -goog.Disposable.prototype.registerDisposable = function(disposable) { - this.addOnDisposeCallback(goog.partial(goog.dispose, disposable)); -}; - - -/** - * Invokes a callback function when this object is disposed. Callbacks are - * invoked in the order in which they were added. If a callback is added to - * an already disposed Disposable, it will be called immediately. - * @param {function(this:T):?} callback The callback function. - * @param {T=} opt_scope An optional scope to call the callback in. - * @template T - */ -goog.Disposable.prototype.addOnDisposeCallback = function(callback, opt_scope) { - if (this.disposed_) { - goog.isDef(opt_scope) ? callback.call(opt_scope) : callback(); - return; - } - if (!this.onDisposeCallbacks_) { - this.onDisposeCallbacks_ = []; - } - - this.onDisposeCallbacks_.push( - goog.isDef(opt_scope) ? goog.bind(callback, opt_scope) : callback); -}; - - -/** - * Deletes or nulls out any references to COM objects, DOM nodes, or other - * disposable objects. Classes that extend {@code goog.Disposable} should - * override this method. - * Not reentrant. To avoid calling it twice, it must only be called from the - * subclass' {@code disposeInternal} method. Everywhere else the public - * {@code dispose} method must be used. - * For example: - * <pre> - * mypackage.MyClass = function() { - * mypackage.MyClass.base(this, 'constructor'); - * // Constructor logic specific to MyClass. - * ... - * }; - * goog.inherits(mypackage.MyClass, goog.Disposable); - * - * mypackage.MyClass.prototype.disposeInternal = function() { - * // Dispose logic specific to MyClass. - * ... - * // Call superclass's disposeInternal at the end of the subclass's, like - * // in C++, to avoid hard-to-catch issues. - * mypackage.MyClass.base(this, 'disposeInternal'); - * }; - * </pre> - * @protected - */ -goog.Disposable.prototype.disposeInternal = function() { - if (this.onDisposeCallbacks_) { - while (this.onDisposeCallbacks_.length) { - this.onDisposeCallbacks_.shift()(); - } - } -}; - - -/** - * Returns True if we can verify the object is disposed. - * Calls {@code isDisposed} on the argument if it supports it. If obj - * is not an object with an isDisposed() method, return false. - * @param {*} obj The object to investigate. - * @return {boolean} True if we can verify the object is disposed. - */ -goog.Disposable.isDisposed = function(obj) { - if (obj && typeof obj.isDisposed == 'function') { - return obj.isDisposed(); - } - return false; -}; - - -/** - * Calls {@code dispose} on the argument if it supports it. If obj is not an - * object with a dispose() method, this is a no-op. - * @param {*} obj The object to dispose of. - */ -goog.dispose = function(obj) { - if (obj && typeof obj.dispose == 'function') { - obj.dispose(); - } -}; - - -/** - * Calls {@code dispose} on each member of the list that supports it. (If the - * member is an ArrayLike, then {@code goog.disposeAll()} will be called - * recursively on each of its members.) If the member is not an object with a - * {@code dispose()} method, then it is ignored. - * @param {...*} var_args The list. - */ -goog.disposeAll = function(var_args) { - for (var i = 0, len = arguments.length; i < len; ++i) { - var disposable = arguments[i]; - if (goog.isArrayLike(disposable)) { - goog.disposeAll.apply(null, disposable); - } else { - goog.dispose(disposable); - } - } -};
diff --git a/third_party/ink/closure/disposable/idisposable.js b/third_party/ink/closure/disposable/idisposable.js deleted file mode 100644 index b539eb6..0000000 --- a/third_party/ink/closure/disposable/idisposable.js +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Definition of the disposable interface. A disposable object - * has a dispose method to to clean up references and resources. - * @author nnaze@google.com (Nathan Naze) - */ - - -goog.provide('goog.disposable.IDisposable'); - - - -/** - * Interface for a disposable object. If a instance requires cleanup - * (references COM objects, DOM nodes, or other disposable objects), it should - * implement this interface (it may subclass goog.Disposable). - * @record - */ -goog.disposable.IDisposable = function() {}; - - -/** - * Disposes of the object and its resources. - * @return {void} Nothing. - */ -goog.disposable.IDisposable.prototype.dispose = goog.abstractMethod; - - -/** - * @return {boolean} Whether the object has been disposed of. - */ -goog.disposable.IDisposable.prototype.isDisposed = goog.abstractMethod;
diff --git a/third_party/ink/closure/dom/asserts.js b/third_party/ink/closure/dom/asserts.js deleted file mode 100644 index e891440..0000000 --- a/third_party/ink/closure/dom/asserts.js +++ /dev/null
@@ -1,299 +0,0 @@ -// Copyright 2017 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.asserts'); - -goog.require('goog.asserts'); - -/** - * @fileoverview Custom assertions to ensure that an element has the appropriate - * type. - * - * Using a goog.dom.safe wrapper on an object on the incorrect type (via an - * incorrect static type cast) can result in security bugs: For instance, - * g.d.s.setAnchorHref ensures that the URL assigned to the .href attribute - * satisfies the SafeUrl contract, i.e., is safe to dereference as a hyperlink. - * However, the value assigned to a HTMLLinkElement's .href property requires - * the stronger TrustedResourceUrl contract, since it can refer to a stylesheet. - * Thus, using g.d.s.setAnchorHref on an (incorrectly statically typed) object - * of type HTMLLinkElement can result in a security vulnerability. - * Assertions of the correct run-time type help prevent such incorrect use. - * - * In some cases, code using the DOM API is tested using mock objects (e.g., a - * plain object such as {'href': url} instead of an actual Location object). - * To allow such mocking, the assertions permit objects of types that are not - * relevant DOM API objects at all (for instance, not Element or Location). - * - * Note that instanceof checks don't work straightforwardly in older versions of - * IE, or across frames (see, - * http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object, - * http://stackoverflow.com/questions/26248599/instanceof-htmlelement-in-iframe-is-not-element-or-object). - * - * Hence, these assertions may pass vacuously in such scenarios. The resulting - * risk of security bugs is limited by the following factors: - * - A bug can only arise in scenarios involving incorrect static typing (the - * wrapper methods are statically typed to demand objects of the appropriate, - * precise type). - * - Typically, code is tested and exercised in multiple browsers. - */ - -/** - * Asserts that a given object is a Location. - * - * To permit this assertion to pass in the context of tests where DOM APIs might - * be mocked, also accepts any other type except for subtypes of {!Element}. - * This is to ensure that, for instance, HTMLLinkElement is not being used in - * place of a Location, since this could result in security bugs due to stronger - * contracts required for assignments to the href property of the latter. - * - * @param {?Object} o The object whose type to assert. - * @return {!Location} - */ -goog.dom.asserts.assertIsLocation = function(o) { - if (goog.asserts.ENABLE_ASSERTS) { - var win = goog.dom.asserts.getWindow_(o); - if (typeof win.Location != 'undefined' && - typeof win.Element != 'undefined') { - goog.asserts.assert( - o && (o instanceof win.Location || !(o instanceof win.Element)), - 'Argument is not a Location (or a non-Element mock); got: %s', - goog.dom.asserts.debugStringForType_(o)); - } - } - return /** @type {!Location} */ (o); -}; - - -/** - * Asserts that a given object is either the given subtype of Element - * or a non-Element, non-Location Mock. - * - * To permit this assertion to pass in the context of tests where DOM - * APIs might be mocked, also accepts any other type except for - * subtypes of {!Element}. This is to ensure that, for instance, - * HTMLScriptElement is not being used in place of a HTMLImageElement, - * since this could result in security bugs due to stronger contracts - * required for assignments to the src property of the latter. - * - * The DOM type is looked up in the window the object belongs to. In - * some contexts, this might not be possible (e.g. when running tests - * outside a browser, cross-domain lookup). In this case, the - * assertions are skipped. - * - * @param {?Object} o The object whose type to assert. - * @param {string} typename The name of the DOM type. - * @return {!Element} The object. - * @private - */ -// TODO(bangert): Make an analog of goog.dom.TagName to correctly handle casts? -goog.dom.asserts.assertIsElementType_ = function(o, typename) { - if (goog.asserts.ENABLE_ASSERTS) { - var win = goog.dom.asserts.getWindow_(o); - if (typeof win[typename] != 'undefined' && - typeof win.Location != 'undefined' && - typeof win.Element != 'undefined') { - goog.asserts.assert( - o && - (o instanceof win[typename] || - !((o instanceof win.Location) || (o instanceof win.Element))), - 'Argument is not a %s (or a non-Element, non-Location mock); got: %s', - typename, goog.dom.asserts.debugStringForType_(o)); - } - } - return /** @type {!Element} */ (o); -}; - -/** - * Asserts that a given object is a HTMLAnchorElement. - * - * To permit this assertion to pass in the context of tests where elements might - * be mocked, also accepts objects that are not of type Location nor a subtype - * of Element. - * - * @param {?Object} o The object whose type to assert. - * @return {!HTMLAnchorElement} - */ -goog.dom.asserts.assertIsHTMLAnchorElement = function(o) { - return /** @type {!HTMLAnchorElement} */ ( - goog.dom.asserts.assertIsElementType_(o, 'HTMLAnchorElement')); -}; - -/** - * Asserts that a given object is a HTMLButtonElement. - * - * To permit this assertion to pass in the context of tests where elements might - * be mocked, also accepts objects that are not a subtype of Element. - * - * @param {?Object} o The object whose type to assert. - * @return {!HTMLButtonElement} - */ -goog.dom.asserts.assertIsHTMLButtonElement = function(o) { - return /** @type {!HTMLButtonElement} */ ( - goog.dom.asserts.assertIsElementType_(o, 'HTMLButtonElement')); -}; - -/** - * Asserts that a given object is a HTMLLinkElement. - * - * To permit this assertion to pass in the context of tests where elements might - * be mocked, also accepts objects that are not a subtype of Element. - * - * @param {?Object} o The object whose type to assert. - * @return {!HTMLLinkElement} - */ -goog.dom.asserts.assertIsHTMLLinkElement = function(o) { - return /** @type {!HTMLLinkElement} */ ( - goog.dom.asserts.assertIsElementType_(o, 'HTMLLinkElement')); -}; - -/** - * Asserts that a given object is a HTMLImageElement. - * - * To permit this assertion to pass in the context of tests where elements might - * be mocked, also accepts objects that are not a subtype of Element. - * - * @param {?Object} o The object whose type to assert. - * @return {!HTMLImageElement} - */ -goog.dom.asserts.assertIsHTMLImageElement = function(o) { - return /** @type {!HTMLImageElement} */ ( - goog.dom.asserts.assertIsElementType_(o, 'HTMLImageElement')); -}; - -/** - * Asserts that a given object is a HTMLInputElement. - * - * To permit this assertion to pass in the context of tests where elements might - * be mocked, also accepts objects that are not a subtype of Element. - * - * @param {?Object} o The object whose type to assert. - * @return {!HTMLInputElement} - */ -goog.dom.asserts.assertIsHTMLInputElement = function(o) { - return /** @type {!HTMLInputElement} */ ( - goog.dom.asserts.assertIsElementType_(o, 'HTMLInputElement')); -}; - -/** - * Asserts that a given object is a HTMLEmbedElement. - * - * To permit this assertion to pass in the context of tests where elements might - * be mocked, also accepts objects that are not a subtype of Element. - * - * @param {?Object} o The object whose type to assert. - * @return {!HTMLEmbedElement} - */ -goog.dom.asserts.assertIsHTMLEmbedElement = function(o) { - return /** @type {!HTMLEmbedElement} */ ( - goog.dom.asserts.assertIsElementType_(o, 'HTMLEmbedElement')); -}; - -/** - * Asserts that a given object is a HTMLFormElement. - * - * To permit this assertion to pass in the context of tests where elements might - * be mocked, also accepts objects that are not a subtype of Element. - * - * @param {?Object} o The object whose type to assert. - * @return {!HTMLFormElement} - */ -goog.dom.asserts.assertIsHTMLFormElement = function(o) { - return /** @type {!HTMLFormElement} */ ( - goog.dom.asserts.assertIsElementType_(o, 'HTMLFormElement')); -}; - -/** - * Asserts that a given object is a HTMLFrameElement. - * - * To permit this assertion to pass in the context of tests where elements might - * be mocked, also accepts objects that are not a subtype of Element. - * - * @param {?Object} o The object whose type to assert. - * @return {!HTMLFrameElement} - */ -goog.dom.asserts.assertIsHTMLFrameElement = function(o) { - return /** @type {!HTMLFrameElement} */ ( - goog.dom.asserts.assertIsElementType_(o, 'HTMLFrameElement')); -}; - -/** - * Asserts that a given object is a HTMLIFrameElement. - * - * To permit this assertion to pass in the context of tests where elements might - * be mocked, also accepts objects that are not a subtype of Element. - * - * @param {?Object} o The object whose type to assert. - * @return {!HTMLIFrameElement} - */ -goog.dom.asserts.assertIsHTMLIFrameElement = function(o) { - return /** @type {!HTMLIFrameElement} */ ( - goog.dom.asserts.assertIsElementType_(o, 'HTMLIFrameElement')); -}; - -/** - * Asserts that a given object is a HTMLObjectElement. - * - * To permit this assertion to pass in the context of tests where elements might - * be mocked, also accepts objects that are not a subtype of Element. - * - * @param {?Object} o The object whose type to assert. - * @return {!HTMLObjectElement} - */ -goog.dom.asserts.assertIsHTMLObjectElement = function(o) { - return /** @type {!HTMLObjectElement} */ ( - goog.dom.asserts.assertIsElementType_(o, 'HTMLObjectElement')); -}; - -/** - * Asserts that a given object is a HTMLScriptElement. - * - * To permit this assertion to pass in the context of tests where elements might - * be mocked, also accepts objects that are not a subtype of Element. - * - * @param {?Object} o The object whose type to assert. - * @return {!HTMLScriptElement} - */ -goog.dom.asserts.assertIsHTMLScriptElement = function(o) { - return /** @type {!HTMLScriptElement} */ ( - goog.dom.asserts.assertIsElementType_(o, 'HTMLScriptElement')); -}; - -/** - * Returns a string representation of a value's type. - * - * @param {*} value An object, or primitive. - * @return {string} The best display name for the value. - * @private - */ -goog.dom.asserts.debugStringForType_ = function(value) { - if (goog.isObject(value)) { - return value.constructor.displayName || value.constructor.name || - Object.prototype.toString.call(value); - } else { - return value === undefined ? 'undefined' : - value === null ? 'null' : typeof value; - } -}; - -/** - * Gets window of element. - * @param {?Object} o - * @return {!Window} - * @private - */ -goog.dom.asserts.getWindow_ = function(o) { - var doc = o && o.ownerDocument; - var win = doc && /** @type {?Window} */ (doc.defaultView || doc.parentWindow); - return win || /** @type {!Window} */ (goog.global); -};
diff --git a/third_party/ink/closure/dom/browserfeature.js b/third_party/ink/closure/dom/browserfeature.js deleted file mode 100644 index 2d418ea..0000000 --- a/third_party/ink/closure/dom/browserfeature.js +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2010 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Browser capability checks for the dom package. - * - * @author zhyder@google.com (Zohair Hyder) - */ - - -goog.provide('goog.dom.BrowserFeature'); - -goog.require('goog.userAgent'); - - -/** - * Enum of browser capabilities. - * @enum {boolean} - */ -goog.dom.BrowserFeature = { - /** - * Whether attributes 'name' and 'type' can be added to an element after it's - * created. False in Internet Explorer prior to version 9. - */ - CAN_ADD_NAME_OR_TYPE_ATTRIBUTES: - !goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9), - - /** - * Whether we can use element.children to access an element's Element - * children. Available since Gecko 1.9.1, IE 9. (IE<9 also includes comment - * nodes in the collection.) - */ - CAN_USE_CHILDREN_ATTRIBUTE: !goog.userAgent.GECKO && !goog.userAgent.IE || - goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9) || - goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9.1'), - - /** - * Opera, Safari 3, and Internet Explorer 9 all support innerText but they - * include text nodes in script and style tags. Not document-mode-dependent. - */ - CAN_USE_INNER_TEXT: - (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')), - - /** - * MSIE, Opera, and Safari>=4 support element.parentElement to access an - * element's parent if it is an Element. - */ - CAN_USE_PARENT_ELEMENT_PROPERTY: - goog.userAgent.IE || goog.userAgent.OPERA || goog.userAgent.WEBKIT, - - /** - * Whether NoScope elements need a scoped element written before them in - * innerHTML. - * MSDN: http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx#1 - */ - INNER_HTML_NEEDS_SCOPED_ELEMENT: goog.userAgent.IE, - - /** - * Whether we use legacy IE range API. - */ - LEGACY_IE_RANGES: - goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9) -};
diff --git a/third_party/ink/closure/dom/classlist.js b/third_party/ink/closure/dom/classlist.js deleted file mode 100644 index 0d7afbf..0000000 --- a/third_party/ink/closure/dom/classlist.js +++ /dev/null
@@ -1,276 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for detecting, adding and removing classes. Prefer - * this over goog.dom.classes for new code since it attempts to use classList - * (DOMTokenList: http://dom.spec.whatwg.org/#domtokenlist) which is faster - * and requires less code. - * - * Note: these utilities are meant to operate on HTMLElements - * and may have unexpected behavior on elements with differing interfaces - * (such as SVGElements). - */ - - -goog.provide('goog.dom.classlist'); - -goog.require('goog.array'); - - -/** - * Override this define at build-time if you know your target supports it. - * @define {boolean} Whether to use the classList property (DOMTokenList). - */ -goog.define('goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST', false); - - -/** - * Gets an array-like object of class names on an element. - * @param {Element} element DOM node to get the classes of. - * @return {!IArrayLike<?>} Class names on {@code element}. - */ -goog.dom.classlist.get = function(element) { - if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) { - return element.classList; - } - - var className = element.className; - // Some types of elements don't have a className in IE (e.g. iframes). - // Furthermore, in Firefox, className is not a string when the element is - // an SVG element. - return goog.isString(className) && className.match(/\S+/g) || []; -}; - - -/** - * Sets the entire class name of an element. - * @param {Element} element DOM node to set class of. - * @param {string} className Class name(s) to apply to element. - */ -goog.dom.classlist.set = function(element, className) { - element.className = className; -}; - - -/** - * Returns true if an element has a class. This method may throw a DOM - * exception for an invalid or empty class name if DOMTokenList is used. - * @param {Element} element DOM node to test. - * @param {string} className Class name to test for. - * @return {boolean} Whether element has the class. - */ -goog.dom.classlist.contains = function(element, className) { - if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) { - return element.classList.contains(className); - } - return goog.array.contains(goog.dom.classlist.get(element), className); -}; - - -/** - * Adds a class to an element. Does not add multiples of class names. This - * method may throw a DOM exception for an invalid or empty class name if - * DOMTokenList is used. - * @param {Element} element DOM node to add class to. - * @param {string} className Class name to add. - */ -goog.dom.classlist.add = function(element, className) { - if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) { - element.classList.add(className); - return; - } - - if (!goog.dom.classlist.contains(element, className)) { - // Ensure we add a space if this is not the first class name added. - element.className += - element.className.length > 0 ? (' ' + className) : className; - } -}; - - -/** - * Convenience method to add a number of class names at once. - * @param {Element} element The element to which to add classes. - * @param {IArrayLike<string>} classesToAdd An array-like object - * containing a collection of class names to add to the element. - * This method may throw a DOM exception if classesToAdd contains invalid - * or empty class names. - */ -goog.dom.classlist.addAll = function(element, classesToAdd) { - if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) { - goog.array.forEach(classesToAdd, function(className) { - goog.dom.classlist.add(element, className); - }); - return; - } - - var classMap = {}; - - // Get all current class names into a map. - goog.array.forEach(goog.dom.classlist.get(element), function(className) { - classMap[className] = true; - }); - - // Add new class names to the map. - goog.array.forEach( - classesToAdd, function(className) { classMap[className] = true; }); - - // Flatten the keys of the map into the className. - element.className = ''; - for (var className in classMap) { - element.className += - element.className.length > 0 ? (' ' + className) : className; - } -}; - - -/** - * Removes a class from an element. This method may throw a DOM exception - * for an invalid or empty class name if DOMTokenList is used. - * @param {Element} element DOM node to remove class from. - * @param {string} className Class name to remove. - */ -goog.dom.classlist.remove = function(element, className) { - if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) { - element.classList.remove(className); - return; - } - - if (goog.dom.classlist.contains(element, className)) { - // Filter out the class name. - element.className = goog.array - .filter( - goog.dom.classlist.get(element), - function(c) { return c != className; }) - .join(' '); - } -}; - - -/** - * Removes a set of classes from an element. Prefer this call to - * repeatedly calling {@code goog.dom.classlist.remove} if you want to remove - * a large set of class names at once. - * @param {Element} element The element from which to remove classes. - * @param {IArrayLike<string>} classesToRemove An array-like object - * containing a collection of class names to remove from the element. - * This method may throw a DOM exception if classesToRemove contains invalid - * or empty class names. - */ -goog.dom.classlist.removeAll = function(element, classesToRemove) { - if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) { - goog.array.forEach(classesToRemove, function(className) { - goog.dom.classlist.remove(element, className); - }); - return; - } - // Filter out those classes in classesToRemove. - element.className = - goog.array - .filter( - goog.dom.classlist.get(element), - function(className) { - // If this class is not one we are trying to remove, - // add it to the array of new class names. - return !goog.array.contains(classesToRemove, className); - }) - .join(' '); -}; - - -/** - * Adds or removes a class depending on the enabled argument. This method - * may throw a DOM exception for an invalid or empty class name if DOMTokenList - * is used. - * @param {Element} element DOM node to add or remove the class on. - * @param {string} className Class name to add or remove. - * @param {boolean} enabled Whether to add or remove the class (true adds, - * false removes). - */ -goog.dom.classlist.enable = function(element, className, enabled) { - if (enabled) { - goog.dom.classlist.add(element, className); - } else { - goog.dom.classlist.remove(element, className); - } -}; - - -/** - * Adds or removes a set of classes depending on the enabled argument. This - * method may throw a DOM exception for an invalid or empty class name if - * DOMTokenList is used. - * @param {!Element} element DOM node to add or remove the class on. - * @param {?IArrayLike<string>} classesToEnable An array-like object - * containing a collection of class names to add or remove from the element. - * @param {boolean} enabled Whether to add or remove the classes (true adds, - * false removes). - */ -goog.dom.classlist.enableAll = function(element, classesToEnable, enabled) { - var f = enabled ? goog.dom.classlist.addAll : goog.dom.classlist.removeAll; - f(element, classesToEnable); -}; - - -/** - * Switches a class on an element from one to another without disturbing other - * classes. If the fromClass isn't removed, the toClass won't be added. This - * method may throw a DOM exception if the class names are empty or invalid. - * @param {Element} element DOM node to swap classes on. - * @param {string} fromClass Class to remove. - * @param {string} toClass Class to add. - * @return {boolean} Whether classes were switched. - */ -goog.dom.classlist.swap = function(element, fromClass, toClass) { - if (goog.dom.classlist.contains(element, fromClass)) { - goog.dom.classlist.remove(element, fromClass); - goog.dom.classlist.add(element, toClass); - return true; - } - return false; -}; - - -/** - * Removes a class if an element has it, and adds it the element doesn't have - * it. Won't affect other classes on the node. This method may throw a DOM - * exception if the class name is empty or invalid. - * @param {Element} element DOM node to toggle class on. - * @param {string} className Class to toggle. - * @return {boolean} True if class was added, false if it was removed - * (in other words, whether element has the class after this function has - * been called). - */ -goog.dom.classlist.toggle = function(element, className) { - var add = !goog.dom.classlist.contains(element, className); - goog.dom.classlist.enable(element, className, add); - return add; -}; - - -/** - * Adds and removes a class of an element. Unlike - * {@link goog.dom.classlist.swap}, this method adds the classToAdd regardless - * of whether the classToRemove was present and had been removed. This method - * may throw a DOM exception if the class names are empty or invalid. - * - * @param {Element} element DOM node to swap classes on. - * @param {string} classToRemove Class to remove. - * @param {string} classToAdd Class to add. - */ -goog.dom.classlist.addRemove = function(element, classToRemove, classToAdd) { - goog.dom.classlist.remove(element, classToRemove); - goog.dom.classlist.add(element, classToAdd); -};
diff --git a/third_party/ink/closure/dom/dom.js b/third_party/ink/closure/dom/dom.js deleted file mode 100644 index a330b4c..0000000 --- a/third_party/ink/closure/dom/dom.js +++ /dev/null
@@ -1,3234 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for manipulating the browser's Document Object Model - * Inspiration taken *heavily* from mochikit (http://mochikit.com/). - * - * You can use {@link goog.dom.DomHelper} to create new dom helpers that refer - * to a different document object. This is useful if you are working with - * frames or multiple windows. - * - * @author pupius@google.com (Daniel Pupius) - * @author arv@google.com (Erik Arvidsson) - */ - - -// TODO(arv): Rename/refactor getTextContent and getRawTextContent. The problem -// is that getTextContent should mimic the DOM3 textContent. We should add a -// getInnerText (or getText) which tries to return the visible text, innerText. - - -goog.provide('goog.dom'); -goog.provide('goog.dom.Appendable'); -goog.provide('goog.dom.DomHelper'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.dom.BrowserFeature'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.safe'); -goog.require('goog.html.SafeHtml'); -goog.require('goog.html.uncheckedconversions'); -goog.require('goog.math.Coordinate'); -goog.require('goog.math.Size'); -goog.require('goog.object'); -goog.require('goog.string'); -goog.require('goog.string.Unicode'); -goog.require('goog.userAgent'); - - -/** - * @define {boolean} Whether we know at compile time that the browser is in - * quirks mode. - */ -goog.define('goog.dom.ASSUME_QUIRKS_MODE', false); - - -/** - * @define {boolean} Whether we know at compile time that the browser is in - * standards compliance mode. - */ -goog.define('goog.dom.ASSUME_STANDARDS_MODE', false); - - -/** - * Whether we know the compatibility mode at compile time. - * @type {boolean} - * @private - */ -goog.dom.COMPAT_MODE_KNOWN_ = - goog.dom.ASSUME_QUIRKS_MODE || goog.dom.ASSUME_STANDARDS_MODE; - - -/** - * Gets the DomHelper object for the document where the element resides. - * @param {(Node|Window)=} opt_element If present, gets the DomHelper for this - * element. - * @return {!goog.dom.DomHelper} The DomHelper. - */ -goog.dom.getDomHelper = function(opt_element) { - return opt_element ? - new goog.dom.DomHelper(goog.dom.getOwnerDocument(opt_element)) : - (goog.dom.defaultDomHelper_ || - (goog.dom.defaultDomHelper_ = new goog.dom.DomHelper())); -}; - - -/** - * Cached default DOM helper. - * @type {!goog.dom.DomHelper|undefined} - * @private - */ -goog.dom.defaultDomHelper_; - - -/** - * Gets the document object being used by the dom library. - * @return {!Document} Document object. - */ -goog.dom.getDocument = function() { - return document; -}; - - -/** - * Gets an element from the current document by element id. - * - * If an Element is passed in, it is returned. - * - * @param {string|Element} element Element ID or a DOM node. - * @return {Element} The element with the given ID, or the node passed in. - */ -goog.dom.getElement = function(element) { - return goog.dom.getElementHelper_(document, element); -}; - - -/** - * Gets an element by id from the given document (if present). - * If an element is given, it is returned. - * @param {!Document} doc - * @param {string|Element} element Element ID or a DOM node. - * @return {Element} The resulting element. - * @private - */ -goog.dom.getElementHelper_ = function(doc, element) { - return goog.isString(element) ? doc.getElementById(element) : element; -}; - - -/** - * Gets an element by id, asserting that the element is found. - * - * This is used when an element is expected to exist, and should fail with - * an assertion error if it does not (if assertions are enabled). - * - * @param {string} id Element ID. - * @return {!Element} The element with the given ID, if it exists. - */ -goog.dom.getRequiredElement = function(id) { - return goog.dom.getRequiredElementHelper_(document, id); -}; - - -/** - * Helper function for getRequiredElementHelper functions, both static and - * on DomHelper. Asserts the element with the given id exists. - * @param {!Document} doc - * @param {string} id - * @return {!Element} The element with the given ID, if it exists. - * @private - */ -goog.dom.getRequiredElementHelper_ = function(doc, id) { - // To prevent users passing in Elements as is permitted in getElement(). - goog.asserts.assertString(id); - var element = goog.dom.getElementHelper_(doc, id); - element = - goog.asserts.assertElement(element, 'No element found with id: ' + id); - return element; -}; - - -/** - * Alias for getElement. - * @param {string|Element} element Element ID or a DOM node. - * @return {Element} The element with the given ID, or the node passed in. - * @deprecated Use {@link goog.dom.getElement} instead. - */ -goog.dom.$ = goog.dom.getElement; - - -/** - * Gets elements by tag name. - * @param {!goog.dom.TagName<T>} tagName - * @param {(!Document|!Element)=} opt_parent Parent element or document where to - * look for elements. Defaults to document. - * @return {!NodeList<R>} List of elements. The members of the list are - * {!Element} if tagName is not a member of goog.dom.TagName or more - * specific types if it is (e.g. {!HTMLAnchorElement} for - * goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.getElementsByTagName = function(tagName, opt_parent) { - var parent = opt_parent || document; - return parent.getElementsByTagName(String(tagName)); -}; - - -/** - * Looks up elements by both tag and class name, using browser native functions - * ({@code querySelectorAll}, {@code getElementsByTagName} or - * {@code getElementsByClassName}) where possible. This function - * is a useful, if limited, way of collecting a list of DOM elements - * with certain characteristics. {@code goog.dom.query} offers a - * more powerful and general solution which allows matching on CSS3 - * selector expressions, but at increased cost in code size. If all you - * need is particular tags belonging to a single class, this function - * is fast and sleek. - * - * Note that tag names are case sensitive in the SVG namespace, and this - * function converts opt_tag to uppercase for comparisons. For queries in the - * SVG namespace you should use querySelector or querySelectorAll instead. - * https://bugzilla.mozilla.org/show_bug.cgi?id=963870 - * https://bugs.webkit.org/show_bug.cgi?id=83438 - * - * @see {goog.dom.query} - * - * @param {(string|?goog.dom.TagName<T>)=} opt_tag Element tag name. - * @param {?string=} opt_class Optional class name. - * @param {(Document|Element)=} opt_el Optional element to look in. - * @return {!IArrayLike<R>} Array-like list of elements (only a length property - * and numerical indices are guaranteed to exist). The members of the array - * are {!Element} if opt_tag is not a member of goog.dom.TagName or more - * specific types if it is (e.g. {!HTMLAnchorElement} for - * goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) { - return goog.dom.getElementsByTagNameAndClass_( - document, opt_tag, opt_class, opt_el); -}; - - -/** - * Gets the first element matching the tag and the class. - * - * @param {(string|?goog.dom.TagName<T>)=} opt_tag Element tag name. - * @param {?string=} opt_class Optional class name. - * @param {(Document|Element)=} opt_el Optional element to look in. - * @return {?R} Reference to a DOM node. The return type is {?Element} if - * tagName is a string or a more specific type if it is a member of - * goog.dom.TagName (e.g. {?HTMLAnchorElement} for goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.getElementByTagNameAndClass = function(opt_tag, opt_class, opt_el) { - return goog.dom.getElementByTagNameAndClass_( - document, opt_tag, opt_class, opt_el); -}; - - -/** - * Returns a static, array-like list of the elements with the provided - * className. - * @see {goog.dom.query} - * @param {string} className the name of the class to look for. - * @param {(Document|Element)=} opt_el Optional element to look in. - * @return {!IArrayLike<!Element>} The items found with the class name provided. - */ -goog.dom.getElementsByClass = function(className, opt_el) { - var parent = opt_el || document; - if (goog.dom.canUseQuerySelector_(parent)) { - return parent.querySelectorAll('.' + className); - } - return goog.dom.getElementsByTagNameAndClass_( - document, '*', className, opt_el); -}; - - -/** - * Returns the first element with the provided className. - * @see {goog.dom.query} - * @param {string} className the name of the class to look for. - * @param {Element|Document=} opt_el Optional element to look in. - * @return {Element} The first item with the class name provided. - */ -goog.dom.getElementByClass = function(className, opt_el) { - var parent = opt_el || document; - var retVal = null; - if (parent.getElementsByClassName) { - retVal = parent.getElementsByClassName(className)[0]; - } else { - retVal = - goog.dom.getElementByTagNameAndClass_(document, '*', className, opt_el); - } - return retVal || null; -}; - - -/** - * Ensures an element with the given className exists, and then returns the - * first element with the provided className. - * @see {goog.dom.query} - * @param {string} className the name of the class to look for. - * @param {!Element|!Document=} opt_root Optional element or document to look - * in. - * @return {!Element} The first item with the class name provided. - * @throws {goog.asserts.AssertionError} Thrown if no element is found. - */ -goog.dom.getRequiredElementByClass = function(className, opt_root) { - var retValue = goog.dom.getElementByClass(className, opt_root); - return goog.asserts.assert( - retValue, 'No element found with className: ' + className); -}; - - -/** - * Prefer the standardized (http://www.w3.org/TR/selectors-api/), native and - * fast W3C Selectors API. - * @param {!(Element|Document)} parent The parent document object. - * @return {boolean} whether or not we can use parent.querySelector* APIs. - * @private - */ -goog.dom.canUseQuerySelector_ = function(parent) { - return !!(parent.querySelectorAll && parent.querySelector); -}; - - -/** - * Helper for {@code getElementsByTagNameAndClass}. - * @param {!Document} doc The document to get the elements in. - * @param {(string|?goog.dom.TagName<T>)=} opt_tag Element tag name. - * @param {?string=} opt_class Optional class name. - * @param {(Document|Element)=} opt_el Optional element to look in. - * @return {!IArrayLike<R>} Array-like list of elements (only a length property - * and numerical indices are guaranteed to exist). The members of the array - * are {!Element} if opt_tag is not a member of goog.dom.TagName or more - * specific types if it is (e.g. {!HTMLAnchorElement} for - * goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - * @private - */ -goog.dom.getElementsByTagNameAndClass_ = function( - doc, opt_tag, opt_class, opt_el) { - var parent = opt_el || doc; - var tagName = - (opt_tag && opt_tag != '*') ? String(opt_tag).toUpperCase() : ''; - - if (goog.dom.canUseQuerySelector_(parent) && (tagName || opt_class)) { - var query = tagName + (opt_class ? '.' + opt_class : ''); - return parent.querySelectorAll(query); - } - - // Use the native getElementsByClassName if available, under the assumption - // that even when the tag name is specified, there will be fewer elements to - // filter through when going by class than by tag name - if (opt_class && parent.getElementsByClassName) { - var els = parent.getElementsByClassName(opt_class); - - if (tagName) { - var arrayLike = {}; - var len = 0; - - // Filter for specific tags if requested. - for (var i = 0, el; el = els[i]; i++) { - if (tagName == el.nodeName) { - arrayLike[len++] = el; - } - } - arrayLike.length = len; - - return /** @type {!IArrayLike<!Element>} */ (arrayLike); - } else { - return els; - } - } - - var els = parent.getElementsByTagName(tagName || '*'); - - if (opt_class) { - var arrayLike = {}; - var len = 0; - for (var i = 0, el; el = els[i]; i++) { - var className = el.className; - // Check if className has a split function since SVG className does not. - if (typeof className.split == 'function' && - goog.array.contains(className.split(/\s+/), opt_class)) { - arrayLike[len++] = el; - } - } - arrayLike.length = len; - return /** @type {!IArrayLike<!Element>} */ (arrayLike); - } else { - return els; - } -}; - - -/** - * Helper for goog.dom.getElementByTagNameAndClass. - * - * @param {!Document} doc The document to get the elements in. - * @param {(string|?goog.dom.TagName<T>)=} opt_tag Element tag name. - * @param {?string=} opt_class Optional class name. - * @param {(Document|Element)=} opt_el Optional element to look in. - * @return {?R} Reference to a DOM node. The return type is {?Element} if - * tagName is a string or a more specific type if it is a member of - * goog.dom.TagName (e.g. {?HTMLAnchorElement} for goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - * @private - */ -goog.dom.getElementByTagNameAndClass_ = function( - doc, opt_tag, opt_class, opt_el) { - var parent = opt_el || doc; - var tag = (opt_tag && opt_tag != '*') ? String(opt_tag).toUpperCase() : ''; - if (goog.dom.canUseQuerySelector_(parent) && (tag || opt_class)) { - return parent.querySelector(tag + (opt_class ? '.' + opt_class : '')); - } - var elements = - goog.dom.getElementsByTagNameAndClass_(doc, opt_tag, opt_class, opt_el); - return elements[0] || null; -}; - - - -/** - * Alias for {@code getElementsByTagNameAndClass}. - * @param {(string|?goog.dom.TagName<T>)=} opt_tag Element tag name. - * @param {?string=} opt_class Optional class name. - * @param {Element=} opt_el Optional element to look in. - * @return {!IArrayLike<R>} Array-like list of elements (only a length property - * and numerical indices are guaranteed to exist). The members of the array - * are {!Element} if opt_tag is not a member of goog.dom.TagName or more - * specific types if it is (e.g. {!HTMLAnchorElement} for - * goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - * @deprecated Use {@link goog.dom.getElementsByTagNameAndClass} instead. - */ -goog.dom.$$ = goog.dom.getElementsByTagNameAndClass; - - -/** - * Sets multiple properties, and sometimes attributes, on an element. Note that - * properties are simply object properties on the element instance, while - * attributes are visible in the DOM. Many properties map to attributes with the - * same names, some with different names, and there are also unmappable cases. - * - * This method sets properties by default (which means that custom attributes - * are not supported). These are the exeptions (some of which is legacy): - * - "style": Even though this is an attribute name, it is translated to a - * property, "style.cssText". Note that this property sanitizes and formats - * its value, unlike the attribute. - * - "class": This is an attribute name, it is translated to the "className" - * property. - * - "for": This is an attribute name, it is translated to the "htmlFor" - * property. - * - Entries in {@see goog.dom.DIRECT_ATTRIBUTE_MAP_} are set as attributes, - * this is probably due to browser quirks. - * - "aria-*", "data-*": Always set as attributes, they have no property - * counterparts. - * - * @param {Element} element DOM node to set properties on. - * @param {Object} properties Hash of property:value pairs. - * Property values can be strings or goog.string.TypedString values (such as - * goog.html.SafeUrl). - */ -goog.dom.setProperties = function(element, properties) { - goog.object.forEach(properties, function(val, key) { - if (val && val.implementsGoogStringTypedString) { - val = val.getTypedStringValue(); - } - if (key == 'style') { - element.style.cssText = val; - } else if (key == 'class') { - element.className = val; - } else if (key == 'for') { - element.htmlFor = val; - } else if (goog.dom.DIRECT_ATTRIBUTE_MAP_.hasOwnProperty(key)) { - element.setAttribute(goog.dom.DIRECT_ATTRIBUTE_MAP_[key], val); - } else if ( - goog.string.startsWith(key, 'aria-') || - goog.string.startsWith(key, 'data-')) { - element.setAttribute(key, val); - } else { - element[key] = val; - } - }); -}; - - -/** - * Map of attributes that should be set using - * element.setAttribute(key, val) instead of element[key] = val. Used - * by goog.dom.setProperties. - * - * @private {!Object<string, string>} - * @const - */ -goog.dom.DIRECT_ATTRIBUTE_MAP_ = { - 'cellpadding': 'cellPadding', - 'cellspacing': 'cellSpacing', - 'colspan': 'colSpan', - 'frameborder': 'frameBorder', - 'height': 'height', - 'maxlength': 'maxLength', - 'nonce': 'nonce', - 'role': 'role', - 'rowspan': 'rowSpan', - 'type': 'type', - 'usemap': 'useMap', - 'valign': 'vAlign', - 'width': 'width' -}; - - -/** - * Gets the dimensions of the viewport. - * - * Gecko Standards mode: - * docEl.clientWidth Width of viewport excluding scrollbar. - * win.innerWidth Width of viewport including scrollbar. - * body.clientWidth Width of body element. - * - * docEl.clientHeight Height of viewport excluding scrollbar. - * win.innerHeight Height of viewport including scrollbar. - * body.clientHeight Height of document. - * - * Gecko Backwards compatible mode: - * docEl.clientWidth Width of viewport excluding scrollbar. - * win.innerWidth Width of viewport including scrollbar. - * body.clientWidth Width of viewport excluding scrollbar. - * - * docEl.clientHeight Height of document. - * win.innerHeight Height of viewport including scrollbar. - * body.clientHeight Height of viewport excluding scrollbar. - * - * IE6/7 Standards mode: - * docEl.clientWidth Width of viewport excluding scrollbar. - * win.innerWidth Undefined. - * body.clientWidth Width of body element. - * - * docEl.clientHeight Height of viewport excluding scrollbar. - * win.innerHeight Undefined. - * body.clientHeight Height of document element. - * - * IE5 + IE6/7 Backwards compatible mode: - * docEl.clientWidth 0. - * win.innerWidth Undefined. - * body.clientWidth Width of viewport excluding scrollbar. - * - * docEl.clientHeight 0. - * win.innerHeight Undefined. - * body.clientHeight Height of viewport excluding scrollbar. - * - * Opera 9 Standards and backwards compatible mode: - * docEl.clientWidth Width of viewport excluding scrollbar. - * win.innerWidth Width of viewport including scrollbar. - * body.clientWidth Width of viewport excluding scrollbar. - * - * docEl.clientHeight Height of document. - * win.innerHeight Height of viewport including scrollbar. - * body.clientHeight Height of viewport excluding scrollbar. - * - * WebKit: - * Safari 2 - * docEl.clientHeight Same as scrollHeight. - * docEl.clientWidth Same as innerWidth. - * win.innerWidth Width of viewport excluding scrollbar. - * win.innerHeight Height of the viewport including scrollbar. - * frame.innerHeight Height of the viewport exluding scrollbar. - * - * Safari 3 (tested in 522) - * - * docEl.clientWidth Width of viewport excluding scrollbar. - * docEl.clientHeight Height of viewport excluding scrollbar in strict mode. - * body.clientHeight Height of viewport excluding scrollbar in quirks mode. - * - * @param {Window=} opt_window Optional window element to test. - * @return {!goog.math.Size} Object with values 'width' and 'height'. - */ -goog.dom.getViewportSize = function(opt_window) { - // TODO(arv): This should not take an argument - return goog.dom.getViewportSize_(opt_window || window); -}; - - -/** - * Helper for {@code getViewportSize}. - * @param {Window} win The window to get the view port size for. - * @return {!goog.math.Size} Object with values 'width' and 'height'. - * @private - */ -goog.dom.getViewportSize_ = function(win) { - var doc = win.document; - var el = goog.dom.isCss1CompatMode_(doc) ? doc.documentElement : doc.body; - return new goog.math.Size(el.clientWidth, el.clientHeight); -}; - - -/** - * Calculates the height of the document. - * - * @return {number} The height of the current document. - */ -goog.dom.getDocumentHeight = function() { - return goog.dom.getDocumentHeight_(window); -}; - -/** - * Calculates the height of the document of the given window. - * - * @param {!Window} win The window whose document height to retrieve. - * @return {number} The height of the document of the given window. - */ -goog.dom.getDocumentHeightForWindow = function(win) { - return goog.dom.getDocumentHeight_(win); -}; - -/** - * Calculates the height of the document of the given window. - * - * Function code copied from the opensocial gadget api: - * gadgets.window.adjustHeight(opt_height) - * - * @private - * @param {!Window} win The window whose document height to retrieve. - * @return {number} The height of the document of the given window. - */ -goog.dom.getDocumentHeight_ = function(win) { - // NOTE(eae): This method will return the window size rather than the document - // size in webkit quirks mode. - var doc = win.document; - var height = 0; - - if (doc) { - // Calculating inner content height is hard and different between - // browsers rendering in Strict vs. Quirks mode. We use a combination of - // three properties within document.body and document.documentElement: - // - scrollHeight - // - offsetHeight - // - clientHeight - // These values differ significantly between browsers and rendering modes. - // But there are patterns. It just takes a lot of time and persistence - // to figure out. - - var body = doc.body; - var docEl = /** @type {!HTMLElement} */ (doc.documentElement); - if (!(docEl && body)) { - return 0; - } - - // Get the height of the viewport - var vh = goog.dom.getViewportSize_(win).height; - if (goog.dom.isCss1CompatMode_(doc) && docEl.scrollHeight) { - // In Strict mode: - // The inner content height is contained in either: - // document.documentElement.scrollHeight - // document.documentElement.offsetHeight - // Based on studying the values output by different browsers, - // use the value that's NOT equal to the viewport height found above. - height = - docEl.scrollHeight != vh ? docEl.scrollHeight : docEl.offsetHeight; - } else { - // In Quirks mode: - // documentElement.clientHeight is equal to documentElement.offsetHeight - // except in IE. In most browsers, document.documentElement can be used - // to calculate the inner content height. - // However, in other browsers (e.g. IE), document.body must be used - // instead. How do we know which one to use? - // If document.documentElement.clientHeight does NOT equal - // document.documentElement.offsetHeight, then use document.body. - var sh = docEl.scrollHeight; - var oh = docEl.offsetHeight; - if (docEl.clientHeight != oh) { - sh = body.scrollHeight; - oh = body.offsetHeight; - } - - // Detect whether the inner content height is bigger or smaller - // than the bounding box (viewport). If bigger, take the larger - // value. If smaller, take the smaller value. - if (sh > vh) { - // Content is larger - height = sh > oh ? sh : oh; - } else { - // Content is smaller - height = sh < oh ? sh : oh; - } - } - } - - return height; -}; - - -/** - * Gets the page scroll distance as a coordinate object. - * - * @param {Window=} opt_window Optional window element to test. - * @return {!goog.math.Coordinate} Object with values 'x' and 'y'. - * @deprecated Use {@link goog.dom.getDocumentScroll} instead. - */ -goog.dom.getPageScroll = function(opt_window) { - var win = opt_window || goog.global || window; - return goog.dom.getDomHelper(win.document).getDocumentScroll(); -}; - - -/** - * Gets the document scroll distance as a coordinate object. - * - * @return {!goog.math.Coordinate} Object with values 'x' and 'y'. - */ -goog.dom.getDocumentScroll = function() { - return goog.dom.getDocumentScroll_(document); -}; - - -/** - * Helper for {@code getDocumentScroll}. - * - * @param {!Document} doc The document to get the scroll for. - * @return {!goog.math.Coordinate} Object with values 'x' and 'y'. - * @private - */ -goog.dom.getDocumentScroll_ = function(doc) { - var el = goog.dom.getDocumentScrollElement_(doc); - var win = goog.dom.getWindow_(doc); - if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher('10') && - win.pageYOffset != el.scrollTop) { - // The keyboard on IE10 touch devices shifts the page using the pageYOffset - // without modifying scrollTop. For this case, we want the body scroll - // offsets. - return new goog.math.Coordinate(el.scrollLeft, el.scrollTop); - } - return new goog.math.Coordinate( - win.pageXOffset || el.scrollLeft, win.pageYOffset || el.scrollTop); -}; - - -/** - * Gets the document scroll element. - * @return {!Element} Scrolling element. - */ -goog.dom.getDocumentScrollElement = function() { - return goog.dom.getDocumentScrollElement_(document); -}; - - -/** - * Helper for {@code getDocumentScrollElement}. - * @param {!Document} doc The document to get the scroll element for. - * @return {!Element} Scrolling element. - * @private - */ -goog.dom.getDocumentScrollElement_ = function(doc) { - // Old WebKit needs body.scrollLeft in both quirks mode and strict mode. We - // also default to the documentElement if the document does not have a body - // (e.g. a SVG document). - // Uses http://dev.w3.org/csswg/cssom-view/#dom-document-scrollingelement to - // avoid trying to guess about browser behavior from the UA string. - if (doc.scrollingElement) { - return doc.scrollingElement; - } - if (!goog.userAgent.WEBKIT && goog.dom.isCss1CompatMode_(doc)) { - return doc.documentElement; - } - return doc.body || doc.documentElement; -}; - - -/** - * Gets the window object associated with the given document. - * - * @param {Document=} opt_doc Document object to get window for. - * @return {!Window} The window associated with the given document. - */ -goog.dom.getWindow = function(opt_doc) { - // TODO(arv): This should not take an argument. - return opt_doc ? goog.dom.getWindow_(opt_doc) : window; -}; - - -/** - * Helper for {@code getWindow}. - * - * @param {!Document} doc Document object to get window for. - * @return {!Window} The window associated with the given document. - * @private - */ -goog.dom.getWindow_ = function(doc) { - return /** @type {!Window} */ (doc.parentWindow || doc.defaultView); -}; - - -/** - * Returns a dom node with a set of attributes. This function accepts varargs - * for subsequent nodes to be added. Subsequent nodes will be added to the - * first node as childNodes. - * - * So: - * <code>createDom(goog.dom.TagName.DIV, null, createDom(goog.dom.TagName.P), - * createDom(goog.dom.TagName.P));</code> would return a div with two child - * paragraphs - * - * For passing properties, please see {@link goog.dom.setProperties} for more - * information. - * - * @param {string|!goog.dom.TagName<T>} tagName Tag to create. - * @param {?Object|?Array<string>|string=} opt_attributes If object, then a map - * of name-value pairs for attributes. If a string, then this is the - * className of the new element. If an array, the elements will be joined - * together as the className of the new element. - * @param {...(Object|string|Array|NodeList)} var_args Further DOM nodes or - * strings for text nodes. If one of the var_args is an array or NodeList, - * its elements will be added as childNodes instead. - * @return {R} Reference to a DOM node. The return type is {!Element} if tagName - * is a string or a more specific type if it is a member of - * goog.dom.TagName (e.g. {!HTMLAnchorElement} for goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.createDom = function(tagName, opt_attributes, var_args) { - return goog.dom.createDom_(document, arguments); -}; - - -/** - * Helper for {@code createDom}. - * @param {!Document} doc The document to create the DOM in. - * @param {!Arguments} args Argument object passed from the callers. See - * {@code goog.dom.createDom} for details. - * @return {!Element} Reference to a DOM node. - * @private - */ -goog.dom.createDom_ = function(doc, args) { - var tagName = String(args[0]); - var attributes = args[1]; - - // Internet Explorer is dumb: - // name: https://msdn.microsoft.com/en-us/library/ms534184(v=vs.85).aspx - // type: https://msdn.microsoft.com/en-us/library/ms534700(v=vs.85).aspx - // Also does not allow setting of 'type' attribute on 'input' or 'button'. - if (!goog.dom.BrowserFeature.CAN_ADD_NAME_OR_TYPE_ATTRIBUTES && attributes && - (attributes.name || attributes.type)) { - var tagNameArr = ['<', tagName]; - if (attributes.name) { - tagNameArr.push(' name="', goog.string.htmlEscape(attributes.name), '"'); - } - if (attributes.type) { - tagNameArr.push(' type="', goog.string.htmlEscape(attributes.type), '"'); - - // Clone attributes map to remove 'type' without mutating the input. - var clone = {}; - goog.object.extend(clone, attributes); - - // JSCompiler can't see how goog.object.extend added this property, - // because it was essentially added by reflection. - // So it needs to be quoted. - delete clone['type']; - - attributes = clone; - } - tagNameArr.push('>'); - tagName = tagNameArr.join(''); - } - - var element = doc.createElement(tagName); - - if (attributes) { - if (goog.isString(attributes)) { - element.className = attributes; - } else if (goog.isArray(attributes)) { - element.className = attributes.join(' '); - } else { - goog.dom.setProperties(element, attributes); - } - } - - if (args.length > 2) { - goog.dom.append_(doc, element, args, 2); - } - - return element; -}; - - -/** - * Appends a node with text or other nodes. - * @param {!Document} doc The document to create new nodes in. - * @param {!Node} parent The node to append nodes to. - * @param {!Arguments} args The values to add. See {@code goog.dom.append}. - * @param {number} startIndex The index of the array to start from. - * @private - */ -goog.dom.append_ = function(doc, parent, args, startIndex) { - function childHandler(child) { - // TODO(pupius): More coercion, ala MochiKit? - if (child) { - parent.appendChild( - goog.isString(child) ? doc.createTextNode(child) : child); - } - } - - for (var i = startIndex; i < args.length; i++) { - var arg = args[i]; - // TODO(attila): Fix isArrayLike to return false for a text node. - if (goog.isArrayLike(arg) && !goog.dom.isNodeLike(arg)) { - // If the argument is a node list, not a real array, use a clone, - // because forEach can't be used to mutate a NodeList. - goog.array.forEach( - goog.dom.isNodeList(arg) ? goog.array.toArray(arg) : arg, - childHandler); - } else { - childHandler(arg); - } - } -}; - - -/** - * Alias for {@code createDom}. - * @param {string|!goog.dom.TagName<T>} tagName Tag to create. - * @param {?Object|?Array<string>|string=} opt_attributes If object, then a map - * of name-value pairs for attributes. If a string, then this is the - * className of the new element. If an array, the elements will be joined - * together as the className of the new element. - * @param {...(Object|string|Array|NodeList)} var_args Further DOM nodes or - * strings for text nodes. If one of the var_args is an array, its - * children will be added as childNodes instead. - * @return {R} Reference to a DOM node. The return type is {!Element} if tagName - * is a string or a more specific type if it is a member of - * goog.dom.TagName (e.g. {!HTMLAnchorElement} for goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - * @deprecated Use {@link goog.dom.createDom} instead. - */ -goog.dom.$dom = goog.dom.createDom; - - -/** - * Creates a new element. - * @param {string|!goog.dom.TagName<T>} name Tag to create. - * @return {R} The new element. The return type is {!Element} if name is - * a string or a more specific type if it is a member of goog.dom.TagName - * (e.g. {!HTMLAnchorElement} for goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.createElement = function(name) { - return goog.dom.createElement_(document, name); -}; - - -/** - * Creates a new element. - * @param {!Document} doc The document to create the element in. - * @param {string|!goog.dom.TagName<T>} name Tag to create. - * @return {R} The new element. The return type is {!Element} if name is - * a string or a more specific type if it is a member of goog.dom.TagName - * (e.g. {!HTMLAnchorElement} for goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - * @private - */ -goog.dom.createElement_ = function(doc, name) { - return doc.createElement(String(name)); -}; - - -/** - * Creates a new text node. - * @param {number|string} content Content. - * @return {!Text} The new text node. - */ -goog.dom.createTextNode = function(content) { - return document.createTextNode(String(content)); -}; - - -/** - * Create a table. - * @param {number} rows The number of rows in the table. Must be >= 1. - * @param {number} columns The number of columns in the table. Must be >= 1. - * @param {boolean=} opt_fillWithNbsp If true, fills table entries with - * {@code goog.string.Unicode.NBSP} characters. - * @return {!Element} The created table. - */ -goog.dom.createTable = function(rows, columns, opt_fillWithNbsp) { - // TODO(mlourenco): Return HTMLTableElement, also in prototype function. - // Callers need to be updated to e.g. not assign numbers to table.cellSpacing. - return goog.dom.createTable_(document, rows, columns, !!opt_fillWithNbsp); -}; - - -/** - * Create a table. - * @param {!Document} doc Document object to use to create the table. - * @param {number} rows The number of rows in the table. Must be >= 1. - * @param {number} columns The number of columns in the table. Must be >= 1. - * @param {boolean} fillWithNbsp If true, fills table entries with - * {@code goog.string.Unicode.NBSP} characters. - * @return {!HTMLTableElement} The created table. - * @private - */ -goog.dom.createTable_ = function(doc, rows, columns, fillWithNbsp) { - var table = goog.dom.createElement_(doc, goog.dom.TagName.TABLE); - var tbody = - table.appendChild(goog.dom.createElement_(doc, goog.dom.TagName.TBODY)); - for (var i = 0; i < rows; i++) { - var tr = goog.dom.createElement_(doc, goog.dom.TagName.TR); - for (var j = 0; j < columns; j++) { - var td = goog.dom.createElement_(doc, goog.dom.TagName.TD); - // IE <= 9 will create a text node if we set text content to the empty - // string, so we avoid doing it unless necessary. This ensures that the - // same DOM tree is returned on all browsers. - if (fillWithNbsp) { - goog.dom.setTextContent(td, goog.string.Unicode.NBSP); - } - tr.appendChild(td); - } - tbody.appendChild(tr); - } - return table; -}; - - - -/** - * Creates a new Node from constant strings of HTML markup. - * @param {...!goog.string.Const} var_args The HTML strings to concatenate then - * convert into a node. - * @return {!Node} - */ -goog.dom.constHtmlToNode = function(var_args) { - var stringArray = goog.array.map(arguments, goog.string.Const.unwrap); - var safeHtml = - goog.html.uncheckedconversions - .safeHtmlFromStringKnownToSatisfyTypeContract( - goog.string.Const.from( - 'Constant HTML string, that gets turned into a ' + - 'Node later, so it will be automatically balanced.'), - stringArray.join('')); - return goog.dom.safeHtmlToNode(safeHtml); -}; - - -/** - * Converts HTML markup into a node. This is a safe version of - * {@code goog.dom.htmlToDocumentFragment} which is now deleted. - * @param {!goog.html.SafeHtml} html The HTML markup to convert. - * @return {!Node} The resulting node. - */ -goog.dom.safeHtmlToNode = function(html) { - return goog.dom.safeHtmlToNode_(document, html); -}; - - -/** - * Helper for {@code safeHtmlToNode}. - * @param {!Document} doc The document. - * @param {!goog.html.SafeHtml} html The HTML markup to convert. - * @return {!Node} The resulting node. - * @private - */ -goog.dom.safeHtmlToNode_ = function(doc, html) { - var tempDiv = goog.dom.createElement_(doc, goog.dom.TagName.DIV); - if (goog.dom.BrowserFeature.INNER_HTML_NEEDS_SCOPED_ELEMENT) { - goog.dom.safe.setInnerHtml( - tempDiv, goog.html.SafeHtml.concat(goog.html.SafeHtml.BR, html)); - tempDiv.removeChild(tempDiv.firstChild); - } else { - goog.dom.safe.setInnerHtml(tempDiv, html); - } - return goog.dom.childrenToNode_(doc, tempDiv); -}; - - -/** - * Helper for {@code safeHtmlToNode_}. - * @param {!Document} doc The document. - * @param {!Node} tempDiv The input node. - * @return {!Node} The resulting node. - * @private - */ -goog.dom.childrenToNode_ = function(doc, tempDiv) { - if (tempDiv.childNodes.length == 1) { - return tempDiv.removeChild(tempDiv.firstChild); - } else { - var fragment = doc.createDocumentFragment(); - while (tempDiv.firstChild) { - fragment.appendChild(tempDiv.firstChild); - } - return fragment; - } -}; - - -/** - * Returns true if the browser is in "CSS1-compatible" (standards-compliant) - * mode, false otherwise. - * @return {boolean} True if in CSS1-compatible mode. - */ -goog.dom.isCss1CompatMode = function() { - return goog.dom.isCss1CompatMode_(document); -}; - - -/** - * Returns true if the browser is in "CSS1-compatible" (standards-compliant) - * mode, false otherwise. - * @param {!Document} doc The document to check. - * @return {boolean} True if in CSS1-compatible mode. - * @private - */ -goog.dom.isCss1CompatMode_ = function(doc) { - if (goog.dom.COMPAT_MODE_KNOWN_) { - return goog.dom.ASSUME_STANDARDS_MODE; - } - - return doc.compatMode == 'CSS1Compat'; -}; - - -/** - * Determines if the given node can contain children, intended to be used for - * HTML generation. - * - * IE natively supports node.canHaveChildren but has inconsistent behavior. - * Prior to IE8 the base tag allows children and in IE9 all nodes return true - * for canHaveChildren. - * - * In practice all non-IE browsers allow you to add children to any node, but - * the behavior is inconsistent: - * - * <pre> - * var a = goog.dom.createElement(goog.dom.TagName.BR); - * a.appendChild(document.createTextNode('foo')); - * a.appendChild(document.createTextNode('bar')); - * console.log(a.childNodes.length); // 2 - * console.log(a.innerHTML); // Chrome: "", IE9: "foobar", FF3.5: "foobar" - * </pre> - * - * For more information, see: - * http://dev.w3.org/html5/markup/syntax.html#syntax-elements - * - * TODO(pupius): Rename shouldAllowChildren() ? - * - * @param {Node} node The node to check. - * @return {boolean} Whether the node can contain children. - */ -goog.dom.canHaveChildren = function(node) { - if (node.nodeType != goog.dom.NodeType.ELEMENT) { - return false; - } - switch (/** @type {!Element} */ (node).tagName) { - case String(goog.dom.TagName.APPLET): - case String(goog.dom.TagName.AREA): - case String(goog.dom.TagName.BASE): - case String(goog.dom.TagName.BR): - case String(goog.dom.TagName.COL): - case String(goog.dom.TagName.COMMAND): - case String(goog.dom.TagName.EMBED): - case String(goog.dom.TagName.FRAME): - case String(goog.dom.TagName.HR): - case String(goog.dom.TagName.IMG): - case String(goog.dom.TagName.INPUT): - case String(goog.dom.TagName.IFRAME): - case String(goog.dom.TagName.ISINDEX): - case String(goog.dom.TagName.KEYGEN): - case String(goog.dom.TagName.LINK): - case String(goog.dom.TagName.NOFRAMES): - case String(goog.dom.TagName.NOSCRIPT): - case String(goog.dom.TagName.META): - case String(goog.dom.TagName.OBJECT): - case String(goog.dom.TagName.PARAM): - case String(goog.dom.TagName.SCRIPT): - case String(goog.dom.TagName.SOURCE): - case String(goog.dom.TagName.STYLE): - case String(goog.dom.TagName.TRACK): - case String(goog.dom.TagName.WBR): - return false; - } - return true; -}; - - -/** - * Appends a child to a node. - * @param {Node} parent Parent. - * @param {Node} child Child. - */ -goog.dom.appendChild = function(parent, child) { - parent.appendChild(child); -}; - - -/** - * Appends a node with text or other nodes. - * @param {!Node} parent The node to append nodes to. - * @param {...goog.dom.Appendable} var_args The things to append to the node. - * If this is a Node it is appended as is. - * If this is a string then a text node is appended. - * If this is an array like object then fields 0 to length - 1 are appended. - */ -goog.dom.append = function(parent, var_args) { - goog.dom.append_(goog.dom.getOwnerDocument(parent), parent, arguments, 1); -}; - - -/** - * Removes all the child nodes on a DOM node. - * @param {Node} node Node to remove children from. - */ -goog.dom.removeChildren = function(node) { - // Note: Iterations over live collections can be slow, this is the fastest - // we could find. The double parenthesis are used to prevent JsCompiler and - // strict warnings. - var child; - while ((child = node.firstChild)) { - node.removeChild(child); - } -}; - - -/** - * Inserts a new node before an existing reference node (i.e. as the previous - * sibling). If the reference node has no parent, then does nothing. - * @param {Node} newNode Node to insert. - * @param {Node} refNode Reference node to insert before. - */ -goog.dom.insertSiblingBefore = function(newNode, refNode) { - if (refNode.parentNode) { - refNode.parentNode.insertBefore(newNode, refNode); - } -}; - - -/** - * Inserts a new node after an existing reference node (i.e. as the next - * sibling). If the reference node has no parent, then does nothing. - * @param {Node} newNode Node to insert. - * @param {Node} refNode Reference node to insert after. - */ -goog.dom.insertSiblingAfter = function(newNode, refNode) { - if (refNode.parentNode) { - refNode.parentNode.insertBefore(newNode, refNode.nextSibling); - } -}; - - -/** - * Insert a child at a given index. If index is larger than the number of child - * nodes that the parent currently has, the node is inserted as the last child - * node. - * @param {Element} parent The element into which to insert the child. - * @param {Node} child The element to insert. - * @param {number} index The index at which to insert the new child node. Must - * not be negative. - */ -goog.dom.insertChildAt = function(parent, child, index) { - // Note that if the second argument is null, insertBefore - // will append the child at the end of the list of children. - parent.insertBefore(child, parent.childNodes[index] || null); -}; - - -/** - * Removes a node from its parent. - * @param {Node} node The node to remove. - * @return {Node} The node removed if removed; else, null. - */ -goog.dom.removeNode = function(node) { - return node && node.parentNode ? node.parentNode.removeChild(node) : null; -}; - - -/** - * Replaces a node in the DOM tree. Will do nothing if {@code oldNode} has no - * parent. - * @param {Node} newNode Node to insert. - * @param {Node} oldNode Node to replace. - */ -goog.dom.replaceNode = function(newNode, oldNode) { - var parent = oldNode.parentNode; - if (parent) { - parent.replaceChild(newNode, oldNode); - } -}; - - -/** - * Flattens an element. That is, removes it and replace it with its children. - * Does nothing if the element is not in the document. - * @param {Element} element The element to flatten. - * @return {Element|undefined} The original element, detached from the document - * tree, sans children; or undefined, if the element was not in the document - * to begin with. - */ -goog.dom.flattenElement = function(element) { - var child, parent = element.parentNode; - if (parent && parent.nodeType != goog.dom.NodeType.DOCUMENT_FRAGMENT) { - // Use IE DOM method (supported by Opera too) if available - if (element.removeNode) { - return /** @type {Element} */ (element.removeNode(false)); - } else { - // Move all children of the original node up one level. - while ((child = element.firstChild)) { - parent.insertBefore(child, element); - } - - // Detach the original element. - return /** @type {Element} */ (goog.dom.removeNode(element)); - } - } -}; - - -/** - * Returns an array containing just the element children of the given element. - * @param {Element} element The element whose element children we want. - * @return {!(Array<!Element>|NodeList<!Element>)} An array or array-like list - * of just the element children of the given element. - */ -goog.dom.getChildren = function(element) { - // We check if the children attribute is supported for child elements - // since IE8 misuses the attribute by also including comments. - if (goog.dom.BrowserFeature.CAN_USE_CHILDREN_ATTRIBUTE && - element.children != undefined) { - return element.children; - } - // Fall back to manually filtering the element's child nodes. - return goog.array.filter(element.childNodes, function(node) { - return node.nodeType == goog.dom.NodeType.ELEMENT; - }); -}; - - -/** - * Returns the first child node that is an element. - * @param {Node} node The node to get the first child element of. - * @return {Element} The first child node of {@code node} that is an element. - */ -goog.dom.getFirstElementChild = function(node) { - if (goog.isDef(node.firstElementChild)) { - return /** @type {!Element} */ (node).firstElementChild; - } - return goog.dom.getNextElementNode_(node.firstChild, true); -}; - - -/** - * Returns the last child node that is an element. - * @param {Node} node The node to get the last child element of. - * @return {Element} The last child node of {@code node} that is an element. - */ -goog.dom.getLastElementChild = function(node) { - if (goog.isDef(node.lastElementChild)) { - return /** @type {!Element} */ (node).lastElementChild; - } - return goog.dom.getNextElementNode_(node.lastChild, false); -}; - - -/** - * Returns the first next sibling that is an element. - * @param {Node} node The node to get the next sibling element of. - * @return {Element} The next sibling of {@code node} that is an element. - */ -goog.dom.getNextElementSibling = function(node) { - if (goog.isDef(node.nextElementSibling)) { - return /** @type {!Element} */ (node).nextElementSibling; - } - return goog.dom.getNextElementNode_(node.nextSibling, true); -}; - - -/** - * Returns the first previous sibling that is an element. - * @param {Node} node The node to get the previous sibling element of. - * @return {Element} The first previous sibling of {@code node} that is - * an element. - */ -goog.dom.getPreviousElementSibling = function(node) { - if (goog.isDef(node.previousElementSibling)) { - return /** @type {!Element} */ (node).previousElementSibling; - } - return goog.dom.getNextElementNode_(node.previousSibling, false); -}; - - -/** - * Returns the first node that is an element in the specified direction, - * starting with {@code node}. - * @param {Node} node The node to get the next element from. - * @param {boolean} forward Whether to look forwards or backwards. - * @return {Element} The first element. - * @private - */ -goog.dom.getNextElementNode_ = function(node, forward) { - while (node && node.nodeType != goog.dom.NodeType.ELEMENT) { - node = forward ? node.nextSibling : node.previousSibling; - } - - return /** @type {Element} */ (node); -}; - - -/** - * Returns the next node in source order from the given node. - * @param {Node} node The node. - * @return {Node} The next node in the DOM tree, or null if this was the last - * node. - */ -goog.dom.getNextNode = function(node) { - if (!node) { - return null; - } - - if (node.firstChild) { - return node.firstChild; - } - - while (node && !node.nextSibling) { - node = node.parentNode; - } - - return node ? node.nextSibling : null; -}; - - -/** - * Returns the previous node in source order from the given node. - * @param {Node} node The node. - * @return {Node} The previous node in the DOM tree, or null if this was the - * first node. - */ -goog.dom.getPreviousNode = function(node) { - if (!node) { - return null; - } - - if (!node.previousSibling) { - return node.parentNode; - } - - node = node.previousSibling; - while (node && node.lastChild) { - node = node.lastChild; - } - - return node; -}; - - -/** - * Whether the object looks like a DOM node. - * @param {?} obj The object being tested for node likeness. - * @return {boolean} Whether the object looks like a DOM node. - */ -goog.dom.isNodeLike = function(obj) { - return goog.isObject(obj) && obj.nodeType > 0; -}; - - -/** - * Whether the object looks like an Element. - * @param {?} obj The object being tested for Element likeness. - * @return {boolean} Whether the object looks like an Element. - */ -goog.dom.isElement = function(obj) { - return goog.isObject(obj) && obj.nodeType == goog.dom.NodeType.ELEMENT; -}; - - -/** - * Returns true if the specified value is a Window object. This includes the - * global window for HTML pages, and iframe windows. - * @param {?} obj Variable to test. - * @return {boolean} Whether the variable is a window. - */ -goog.dom.isWindow = function(obj) { - return goog.isObject(obj) && obj['window'] == obj; -}; - - -/** - * Returns an element's parent, if it's an Element. - * @param {Element} element The DOM element. - * @return {Element} The parent, or null if not an Element. - */ -goog.dom.getParentElement = function(element) { - var parent; - if (goog.dom.BrowserFeature.CAN_USE_PARENT_ELEMENT_PROPERTY) { - var isIe9 = goog.userAgent.IE && goog.userAgent.isVersionOrHigher('9') && - !goog.userAgent.isVersionOrHigher('10'); - // SVG elements in IE9 can't use the parentElement property. - // goog.global['SVGElement'] is not defined in IE9 quirks mode. - if (!(isIe9 && goog.global['SVGElement'] && - element instanceof goog.global['SVGElement'])) { - parent = element.parentElement; - if (parent) { - return parent; - } - } - } - parent = element.parentNode; - return goog.dom.isElement(parent) ? /** @type {!Element} */ (parent) : null; -}; - - -/** - * Whether a node contains another node. - * @param {?Node|undefined} parent The node that should contain the other node. - * @param {?Node|undefined} descendant The node to test presence of. - * @return {boolean} Whether the parent node contains the descendent node. - */ -goog.dom.contains = function(parent, descendant) { - if (!parent || !descendant) { - return false; - } - // We use browser specific methods for this if available since it is faster - // that way. - - // IE DOM - if (parent.contains && descendant.nodeType == goog.dom.NodeType.ELEMENT) { - return parent == descendant || parent.contains(descendant); - } - - // W3C DOM Level 3 - if (typeof parent.compareDocumentPosition != 'undefined') { - return parent == descendant || - Boolean(parent.compareDocumentPosition(descendant) & 16); - } - - // W3C DOM Level 1 - while (descendant && parent != descendant) { - descendant = descendant.parentNode; - } - return descendant == parent; -}; - - -/** - * Compares the document order of two nodes, returning 0 if they are the same - * node, a negative number if node1 is before node2, and a positive number if - * node2 is before node1. Note that we compare the order the tags appear in the - * document so in the tree <b><i>text</i></b> the B node is considered to be - * before the I node. - * - * @param {Node} node1 The first node to compare. - * @param {Node} node2 The second node to compare. - * @return {number} 0 if the nodes are the same node, a negative number if node1 - * is before node2, and a positive number if node2 is before node1. - */ -goog.dom.compareNodeOrder = function(node1, node2) { - // Fall out quickly for equality. - if (node1 == node2) { - return 0; - } - - // Use compareDocumentPosition where available - if (node1.compareDocumentPosition) { - // 4 is the bitmask for FOLLOWS. - return node1.compareDocumentPosition(node2) & 2 ? 1 : -1; - } - - // Special case for document nodes on IE 7 and 8. - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) { - if (node1.nodeType == goog.dom.NodeType.DOCUMENT) { - return -1; - } - if (node2.nodeType == goog.dom.NodeType.DOCUMENT) { - return 1; - } - } - - // Process in IE using sourceIndex - we check to see if the first node has - // a source index or if its parent has one. - if ('sourceIndex' in node1 || - (node1.parentNode && 'sourceIndex' in node1.parentNode)) { - var isElement1 = node1.nodeType == goog.dom.NodeType.ELEMENT; - var isElement2 = node2.nodeType == goog.dom.NodeType.ELEMENT; - - if (isElement1 && isElement2) { - return node1.sourceIndex - node2.sourceIndex; - } else { - var parent1 = node1.parentNode; - var parent2 = node2.parentNode; - - if (parent1 == parent2) { - return goog.dom.compareSiblingOrder_(node1, node2); - } - - if (!isElement1 && goog.dom.contains(parent1, node2)) { - return -1 * goog.dom.compareParentsDescendantNodeIe_(node1, node2); - } - - - if (!isElement2 && goog.dom.contains(parent2, node1)) { - return goog.dom.compareParentsDescendantNodeIe_(node2, node1); - } - - return (isElement1 ? node1.sourceIndex : parent1.sourceIndex) - - (isElement2 ? node2.sourceIndex : parent2.sourceIndex); - } - } - - // For Safari, we compare ranges. - var doc = goog.dom.getOwnerDocument(node1); - - var range1, range2; - range1 = doc.createRange(); - range1.selectNode(node1); - range1.collapse(true); - - range2 = doc.createRange(); - range2.selectNode(node2); - range2.collapse(true); - - return range1.compareBoundaryPoints( - goog.global['Range'].START_TO_END, range2); -}; - - -/** - * Utility function to compare the position of two nodes, when - * {@code textNode}'s parent is an ancestor of {@code node}. If this entry - * condition is not met, this function will attempt to reference a null object. - * @param {!Node} textNode The textNode to compare. - * @param {Node} node The node to compare. - * @return {number} -1 if node is before textNode, +1 otherwise. - * @private - */ -goog.dom.compareParentsDescendantNodeIe_ = function(textNode, node) { - var parent = textNode.parentNode; - if (parent == node) { - // If textNode is a child of node, then node comes first. - return -1; - } - var sibling = node; - while (sibling.parentNode != parent) { - sibling = sibling.parentNode; - } - return goog.dom.compareSiblingOrder_(sibling, textNode); -}; - - -/** - * Utility function to compare the position of two nodes known to be non-equal - * siblings. - * @param {Node} node1 The first node to compare. - * @param {!Node} node2 The second node to compare. - * @return {number} -1 if node1 is before node2, +1 otherwise. - * @private - */ -goog.dom.compareSiblingOrder_ = function(node1, node2) { - var s = node2; - while ((s = s.previousSibling)) { - if (s == node1) { - // We just found node1 before node2. - return -1; - } - } - - // Since we didn't find it, node1 must be after node2. - return 1; -}; - - -/** - * Find the deepest common ancestor of the given nodes. - * @param {...Node} var_args The nodes to find a common ancestor of. - * @return {Node} The common ancestor of the nodes, or null if there is none. - * null will only be returned if two or more of the nodes are from different - * documents. - */ -goog.dom.findCommonAncestor = function(var_args) { - var i, count = arguments.length; - if (!count) { - return null; - } else if (count == 1) { - return arguments[0]; - } - - var paths = []; - var minLength = Infinity; - for (i = 0; i < count; i++) { - // Compute the list of ancestors. - var ancestors = []; - var node = arguments[i]; - while (node) { - ancestors.unshift(node); - node = node.parentNode; - } - - // Save the list for comparison. - paths.push(ancestors); - minLength = Math.min(minLength, ancestors.length); - } - var output = null; - for (i = 0; i < minLength; i++) { - var first = paths[0][i]; - for (var j = 1; j < count; j++) { - if (first != paths[j][i]) { - return output; - } - } - output = first; - } - return output; -}; - - -/** - * Returns the owner document for a node. - * @param {Node|Window} node The node to get the document for. - * @return {!Document} The document owning the node. - */ -goog.dom.getOwnerDocument = function(node) { - // TODO(nnaze): Update param signature to be non-nullable. - goog.asserts.assert(node, 'Node cannot be null or undefined.'); - return /** @type {!Document} */ ( - node.nodeType == goog.dom.NodeType.DOCUMENT ? node : node.ownerDocument || - node.document); -}; - - -/** - * Cross-browser function for getting the document element of a frame or iframe. - * @param {Element} frame Frame element. - * @return {!Document} The frame content document. - */ -goog.dom.getFrameContentDocument = function(frame) { - return frame.contentDocument || - /** @type {!HTMLFrameElement} */ (frame).contentWindow.document; -}; - - -/** - * Cross-browser function for getting the window of a frame or iframe. - * @param {Element} frame Frame element. - * @return {Window} The window associated with the given frame, or null if none - * exists. - */ -goog.dom.getFrameContentWindow = function(frame) { - try { - return frame.contentWindow || - (frame.contentDocument ? goog.dom.getWindow(frame.contentDocument) : - null); - } catch (e) { - // NOTE(jfedor): In IE8, checking the contentWindow or contentDocument - // properties will throw a "Unspecified Error" exception if the iframe is - // not inserted in the DOM. If we get this we can be sure that no window - // exists, so return null. - } - return null; -}; - - -/** - * Sets the text content of a node, with cross-browser support. - * @param {Node} node The node to change the text content of. - * @param {string|number} text The value that should replace the node's content. - */ -goog.dom.setTextContent = function(node, text) { - goog.asserts.assert( - node != null, - 'goog.dom.setTextContent expects a non-null value for node'); - - if ('textContent' in node) { - node.textContent = text; - } else if (node.nodeType == goog.dom.NodeType.TEXT) { - /** @type {!Text} */ (node).data = String(text); - } else if ( - node.firstChild && node.firstChild.nodeType == goog.dom.NodeType.TEXT) { - // If the first child is a text node we just change its data and remove the - // rest of the children. - while (node.lastChild != node.firstChild) { - node.removeChild(node.lastChild); - } - /** @type {!Text} */ (node.firstChild).data = String(text); - } else { - goog.dom.removeChildren(node); - var doc = goog.dom.getOwnerDocument(node); - node.appendChild(doc.createTextNode(String(text))); - } -}; - - -/** - * Gets the outerHTML of a node, which islike innerHTML, except that it - * actually contains the HTML of the node itself. - * @param {Element} element The element to get the HTML of. - * @return {string} The outerHTML of the given element. - */ -goog.dom.getOuterHtml = function(element) { - goog.asserts.assert( - element !== null, - 'goog.dom.getOuterHtml expects a non-null value for element'); - // IE, Opera and WebKit all have outerHTML. - if ('outerHTML' in element) { - return element.outerHTML; - } else { - var doc = goog.dom.getOwnerDocument(element); - var div = goog.dom.createElement_(doc, goog.dom.TagName.DIV); - div.appendChild(element.cloneNode(true)); - return div.innerHTML; - } -}; - - -/** - * Finds the first descendant node that matches the filter function, using - * a depth first search. This function offers the most general purpose way - * of finding a matching element. You may also wish to consider - * {@code goog.dom.query} which can express many matching criteria using - * CSS selector expressions. These expressions often result in a more - * compact representation of the desired result. - * @see goog.dom.query - * - * @param {Node} root The root of the tree to search. - * @param {function(Node) : boolean} p The filter function. - * @return {Node|undefined} The found node or undefined if none is found. - */ -goog.dom.findNode = function(root, p) { - var rv = []; - var found = goog.dom.findNodes_(root, p, rv, true); - return found ? rv[0] : undefined; -}; - - -/** - * Finds all the descendant nodes that match the filter function, using a - * a depth first search. This function offers the most general-purpose way - * of finding a set of matching elements. You may also wish to consider - * {@code goog.dom.query} which can express many matching criteria using - * CSS selector expressions. These expressions often result in a more - * compact representation of the desired result. - - * @param {Node} root The root of the tree to search. - * @param {function(Node) : boolean} p The filter function. - * @return {!Array<!Node>} The found nodes or an empty array if none are found. - */ -goog.dom.findNodes = function(root, p) { - var rv = []; - goog.dom.findNodes_(root, p, rv, false); - return rv; -}; - - -/** - * Finds the first or all the descendant nodes that match the filter function, - * using a depth first search. - * @param {Node} root The root of the tree to search. - * @param {function(Node) : boolean} p The filter function. - * @param {!Array<!Node>} rv The found nodes are added to this array. - * @param {boolean} findOne If true we exit after the first found node. - * @return {boolean} Whether the search is complete or not. True in case findOne - * is true and the node is found. False otherwise. - * @private - */ -goog.dom.findNodes_ = function(root, p, rv, findOne) { - if (root != null) { - var child = root.firstChild; - while (child) { - if (p(child)) { - rv.push(child); - if (findOne) { - return true; - } - } - if (goog.dom.findNodes_(child, p, rv, findOne)) { - return true; - } - child = child.nextSibling; - } - } - return false; -}; - - -/** - * Map of tags whose content to ignore when calculating text length. - * @private {!Object<string, number>} - * @const - */ -goog.dom.TAGS_TO_IGNORE_ = { - 'SCRIPT': 1, - 'STYLE': 1, - 'HEAD': 1, - 'IFRAME': 1, - 'OBJECT': 1 -}; - - -/** - * Map of tags which have predefined values with regard to whitespace. - * @private {!Object<string, string>} - * @const - */ -goog.dom.PREDEFINED_TAG_VALUES_ = { - 'IMG': ' ', - 'BR': '\n' -}; - - -/** - * Returns true if the element has a tab index that allows it to receive - * keyboard focus (tabIndex >= 0), false otherwise. Note that some elements - * natively support keyboard focus, even if they have no tab index. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element has a tab index that allows keyboard - * focus. - */ -goog.dom.isFocusableTabIndex = function(element) { - return goog.dom.hasSpecifiedTabIndex_(element) && - goog.dom.isTabIndexFocusable_(element); -}; - - -/** - * Enables or disables keyboard focus support on the element via its tab index. - * Only elements for which {@link goog.dom.isFocusableTabIndex} returns true - * (or elements that natively support keyboard focus, like form elements) can - * receive keyboard focus. See http://go/tabindex for more info. - * @param {Element} element Element whose tab index is to be changed. - * @param {boolean} enable Whether to set or remove a tab index on the element - * that supports keyboard focus. - */ -goog.dom.setFocusableTabIndex = function(element, enable) { - if (enable) { - element.tabIndex = 0; - } else { - // Set tabIndex to -1 first, then remove it. This is a workaround for - // Safari (confirmed in version 4 on Windows). When removing the attribute - // without setting it to -1 first, the element remains keyboard focusable - // despite not having a tabIndex attribute anymore. - element.tabIndex = -1; - element.removeAttribute('tabIndex'); // Must be camelCase! - } -}; - - -/** - * Returns true if the element can be focused, i.e. it has a tab index that - * allows it to receive keyboard focus (tabIndex >= 0), or it is an element - * that natively supports keyboard focus. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element allows keyboard focus. - */ -goog.dom.isFocusable = function(element) { - var focusable; - // Some elements can have unspecified tab index and still receive focus. - if (goog.dom.nativelySupportsFocus_(element)) { - // Make sure the element is not disabled ... - focusable = !element.disabled && - // ... and if a tab index is specified, it allows focus. - (!goog.dom.hasSpecifiedTabIndex_(element) || - goog.dom.isTabIndexFocusable_(element)); - } else { - focusable = goog.dom.isFocusableTabIndex(element); - } - - // IE requires elements to be visible in order to focus them. - return focusable && goog.userAgent.IE ? - goog.dom.hasNonZeroBoundingRect_(/** @type {!HTMLElement} */ (element)) : - focusable; -}; - - -/** - * Returns true if the element has a specified tab index. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element has a specified tab index. - * @private - */ -goog.dom.hasSpecifiedTabIndex_ = function(element) { - // IE8 and below don't support hasAttribute(), instead check whether the - // 'tabindex' attributeNode is specified. Otherwise check hasAttribute(). - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')) { - var attrNode = element.getAttributeNode('tabindex'); // Must be lowercase! - return goog.isDefAndNotNull(attrNode) && attrNode.specified; - } else { - return element.hasAttribute('tabindex'); - } -}; - - -/** - * Returns true if the element's tab index allows the element to be focused. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element's tab index allows focus. - * @private - */ -goog.dom.isTabIndexFocusable_ = function(element) { - var index = /** @type {!HTMLElement} */ (element).tabIndex; - // NOTE: IE9 puts tabIndex in 16-bit int, e.g. -2 is 65534. - return goog.isNumber(index) && index >= 0 && index < 32768; -}; - - -/** - * Returns true if the element is focusable even when tabIndex is not set. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element natively supports focus. - * @private - */ -goog.dom.nativelySupportsFocus_ = function(element) { - return element.tagName == goog.dom.TagName.A || - element.tagName == goog.dom.TagName.INPUT || - element.tagName == goog.dom.TagName.TEXTAREA || - element.tagName == goog.dom.TagName.SELECT || - element.tagName == goog.dom.TagName.BUTTON; -}; - - -/** - * Returns true if the element has a bounding rectangle that would be visible - * (i.e. its width and height are greater than zero). - * @param {!HTMLElement} element Element to check. - * @return {boolean} Whether the element has a non-zero bounding rectangle. - * @private - */ -goog.dom.hasNonZeroBoundingRect_ = function(element) { - var rect; - if (!goog.isFunction(element['getBoundingClientRect']) || - // In IE, getBoundingClientRect throws on detached nodes. - (goog.userAgent.IE && element.parentElement == null)) { - rect = {'height': element.offsetHeight, 'width': element.offsetWidth}; - } else { - rect = element.getBoundingClientRect(); - } - return goog.isDefAndNotNull(rect) && rect.height > 0 && rect.width > 0; -}; - - -/** - * Returns the text content of the current node, without markup and invisible - * symbols. New lines are stripped and whitespace is collapsed, - * such that each character would be visible. - * - * In browsers that support it, innerText is used. Other browsers attempt to - * simulate it via node traversal. Line breaks are canonicalized in IE. - * - * @param {Node} node The node from which we are getting content. - * @return {string} The text content. - */ -goog.dom.getTextContent = function(node) { - var textContent; - // Note(arv): IE9, Opera, and Safari 3 support innerText but they include - // text nodes in script tags. So we revert to use a user agent test here. - if (goog.dom.BrowserFeature.CAN_USE_INNER_TEXT && node !== null && - ('innerText' in node)) { - textContent = goog.string.canonicalizeNewlines(node.innerText); - // Unfortunately .innerText() returns text with ­ symbols - // We need to filter it out and then remove duplicate whitespaces - } else { - var buf = []; - goog.dom.getTextContent_(node, buf, true); - textContent = buf.join(''); - } - - // Strip ­ entities. goog.format.insertWordBreaks inserts them in Opera. - textContent = textContent.replace(/ \xAD /g, ' ').replace(/\xAD/g, ''); - // Strip ​ entities. goog.format.insertWordBreaks inserts them in IE8. - textContent = textContent.replace(/\u200B/g, ''); - - // Skip this replacement on old browsers with working innerText, which - // automatically turns into ' ' and / +/ into ' ' when reading - // innerText. - if (!goog.dom.BrowserFeature.CAN_USE_INNER_TEXT) { - textContent = textContent.replace(/ +/g, ' '); - } - if (textContent != ' ') { - textContent = textContent.replace(/^\s*/, ''); - } - - return textContent; -}; - - -/** - * Returns the text content of the current node, without markup. - * - * Unlike {@code getTextContent} this method does not collapse whitespaces - * or normalize lines breaks. - * - * @param {Node} node The node from which we are getting content. - * @return {string} The raw text content. - */ -goog.dom.getRawTextContent = function(node) { - var buf = []; - goog.dom.getTextContent_(node, buf, false); - - return buf.join(''); -}; - - -/** - * Recursive support function for text content retrieval. - * - * @param {Node} node The node from which we are getting content. - * @param {Array<string>} buf string buffer. - * @param {boolean} normalizeWhitespace Whether to normalize whitespace. - * @private - */ -goog.dom.getTextContent_ = function(node, buf, normalizeWhitespace) { - if (node.nodeName in goog.dom.TAGS_TO_IGNORE_) { - // ignore certain tags - } else if (node.nodeType == goog.dom.NodeType.TEXT) { - if (normalizeWhitespace) { - buf.push(String(node.nodeValue).replace(/(\r\n|\r|\n)/g, '')); - } else { - buf.push(node.nodeValue); - } - } else if (node.nodeName in goog.dom.PREDEFINED_TAG_VALUES_) { - buf.push(goog.dom.PREDEFINED_TAG_VALUES_[node.nodeName]); - } else { - var child = node.firstChild; - while (child) { - goog.dom.getTextContent_(child, buf, normalizeWhitespace); - child = child.nextSibling; - } - } -}; - - -/** - * Returns the text length of the text contained in a node, without markup. This - * is equivalent to the selection length if the node was selected, or the number - * of cursor movements to traverse the node. Images & BRs take one space. New - * lines are ignored. - * - * @param {Node} node The node whose text content length is being calculated. - * @return {number} The length of {@code node}'s text content. - */ -goog.dom.getNodeTextLength = function(node) { - return goog.dom.getTextContent(node).length; -}; - - -/** - * Returns the text offset of a node relative to one of its ancestors. The text - * length is the same as the length calculated by goog.dom.getNodeTextLength. - * - * @param {Node} node The node whose offset is being calculated. - * @param {Node=} opt_offsetParent The node relative to which the offset will - * be calculated. Defaults to the node's owner document's body. - * @return {number} The text offset. - */ -goog.dom.getNodeTextOffset = function(node, opt_offsetParent) { - var root = opt_offsetParent || goog.dom.getOwnerDocument(node).body; - var buf = []; - while (node && node != root) { - var cur = node; - while ((cur = cur.previousSibling)) { - buf.unshift(goog.dom.getTextContent(cur)); - } - node = node.parentNode; - } - // Trim left to deal with FF cases when there might be line breaks and empty - // nodes at the front of the text - return goog.string.trimLeft(buf.join('')).replace(/ +/g, ' ').length; -}; - - -/** - * Returns the node at a given offset in a parent node. If an object is - * provided for the optional third parameter, the node and the remainder of the - * offset will stored as properties of this object. - * @param {Node} parent The parent node. - * @param {number} offset The offset into the parent node. - * @param {Object=} opt_result Object to be used to store the return value. The - * return value will be stored in the form {node: Node, remainder: number} - * if this object is provided. - * @return {Node} The node at the given offset. - */ -goog.dom.getNodeAtOffset = function(parent, offset, opt_result) { - var stack = [parent], pos = 0, cur = null; - while (stack.length > 0 && pos < offset) { - cur = stack.pop(); - if (cur.nodeName in goog.dom.TAGS_TO_IGNORE_) { - // ignore certain tags - } else if (cur.nodeType == goog.dom.NodeType.TEXT) { - var text = cur.nodeValue.replace(/(\r\n|\r|\n)/g, '').replace(/ +/g, ' '); - pos += text.length; - } else if (cur.nodeName in goog.dom.PREDEFINED_TAG_VALUES_) { - pos += goog.dom.PREDEFINED_TAG_VALUES_[cur.nodeName].length; - } else { - for (var i = cur.childNodes.length - 1; i >= 0; i--) { - stack.push(cur.childNodes[i]); - } - } - } - if (goog.isObject(opt_result)) { - opt_result.remainder = cur ? cur.nodeValue.length + offset - pos - 1 : 0; - opt_result.node = cur; - } - - return cur; -}; - - -/** - * Returns true if the object is a {@code NodeList}. To qualify as a NodeList, - * the object must have a numeric length property and an item function (which - * has type 'string' on IE for some reason). - * @param {Object} val Object to test. - * @return {boolean} Whether the object is a NodeList. - */ -goog.dom.isNodeList = function(val) { - // TODO(attila): Now the isNodeList is part of goog.dom we can use - // goog.userAgent to make this simpler. - // A NodeList must have a length property of type 'number' on all platforms. - if (val && typeof val.length == 'number') { - // A NodeList is an object everywhere except Safari, where it's a function. - if (goog.isObject(val)) { - // A NodeList must have an item function (on non-IE platforms) or an item - // property of type 'string' (on IE). - return typeof val.item == 'function' || typeof val.item == 'string'; - } else if (goog.isFunction(val)) { - // On Safari, a NodeList is a function with an item property that is also - // a function. - return typeof val.item == 'function'; - } - } - - // Not a NodeList. - return false; -}; - - -/** - * Walks up the DOM hierarchy returning the first ancestor that has the passed - * tag name and/or class name. If the passed element matches the specified - * criteria, the element itself is returned. - * @param {Node} element The DOM node to start with. - * @param {?(goog.dom.TagName<T>|string)=} opt_tag The tag name to match (or - * null/undefined to match only based on class name). - * @param {?string=} opt_class The class name to match (or null/undefined to - * match only based on tag name). - * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the - * dom. - * @return {?R} The first ancestor that matches the passed criteria, or - * null if no match is found. The return type is {?Element} if opt_tag is - * not a member of goog.dom.TagName or a more specific type if it is (e.g. - * {?HTMLAnchorElement} for goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.getAncestorByTagNameAndClass = function( - element, opt_tag, opt_class, opt_maxSearchSteps) { - if (!opt_tag && !opt_class) { - return null; - } - var tagName = opt_tag ? String(opt_tag).toUpperCase() : null; - return /** @type {Element} */ (goog.dom.getAncestor(element, function(node) { - return (!tagName || node.nodeName == tagName) && - (!opt_class || - goog.isString(node.className) && - goog.array.contains(node.className.split(/\s+/), opt_class)); - }, true, opt_maxSearchSteps)); -}; - - -/** - * Walks up the DOM hierarchy returning the first ancestor that has the passed - * class name. If the passed element matches the specified criteria, the - * element itself is returned. - * @param {Node} element The DOM node to start with. - * @param {string} className The class name to match. - * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the - * dom. - * @return {Element} The first ancestor that matches the passed criteria, or - * null if none match. - */ -goog.dom.getAncestorByClass = function(element, className, opt_maxSearchSteps) { - return goog.dom.getAncestorByTagNameAndClass( - element, null, className, opt_maxSearchSteps); -}; - - -/** - * Walks up the DOM hierarchy returning the first ancestor that passes the - * matcher function. - * @param {Node} element The DOM node to start with. - * @param {function(Node) : boolean} matcher A function that returns true if the - * passed node matches the desired criteria. - * @param {boolean=} opt_includeNode If true, the node itself is included in - * the search (the first call to the matcher will pass startElement as - * the node to test). - * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the - * dom. - * @return {Node} DOM node that matched the matcher, or null if there was - * no match. - */ -goog.dom.getAncestor = function( - element, matcher, opt_includeNode, opt_maxSearchSteps) { - if (element && !opt_includeNode) { - element = element.parentNode; - } - var steps = 0; - while (element && - (opt_maxSearchSteps == null || steps <= opt_maxSearchSteps)) { - goog.asserts.assert(element.name != 'parentNode'); - if (matcher(element)) { - return element; - } - element = element.parentNode; - steps++; - } - // Reached the root of the DOM without a match - return null; -}; - - -/** - * Determines the active element in the given document. - * @param {Document} doc The document to look in. - * @return {Element} The active element. - */ -goog.dom.getActiveElement = function(doc) { - try { - return doc && doc.activeElement; - } catch (e) { - // NOTE(nicksantos): Sometimes, evaluating document.activeElement in IE - // throws an exception. I'm not 100% sure why, but I suspect it chokes - // on document.activeElement if the activeElement has been recently - // removed from the DOM by a JS operation. - // - // We assume that an exception here simply means - // "there is no active element." - } - - return null; -}; - - -/** - * Gives the current devicePixelRatio. - * - * By default, this is the value of window.devicePixelRatio (which should be - * preferred if present). - * - * If window.devicePixelRatio is not present, the ratio is calculated with - * window.matchMedia, if present. Otherwise, gives 1.0. - * - * Some browsers (including Chrome) consider the browser zoom level in the pixel - * ratio, so the value may change across multiple calls. - * - * @return {number} The number of actual pixels per virtual pixel. - */ -goog.dom.getPixelRatio = function() { - var win = goog.dom.getWindow(); - if (goog.isDef(win.devicePixelRatio)) { - return win.devicePixelRatio; - } else if (win.matchMedia) { - // Should be for IE10 and FF6-17 (this basically clamps to lower) - // Note that the order of these statements is important - return goog.dom.matchesPixelRatio_(3) || goog.dom.matchesPixelRatio_(2) || - goog.dom.matchesPixelRatio_(1.5) || goog.dom.matchesPixelRatio_(1) || - .75; - } - return 1; -}; - - -/** - * Calculates a mediaQuery to check if the current device supports the - * given actual to virtual pixel ratio. - * @param {number} pixelRatio The ratio of actual pixels to virtual pixels. - * @return {number} pixelRatio if applicable, otherwise 0. - * @private - */ -goog.dom.matchesPixelRatio_ = function(pixelRatio) { - var win = goog.dom.getWindow(); - /** - * Due to the 1:96 fixed ratio of CSS in to CSS px, 1dppx is equivalent to - * 96dpi. - * @const {number} - */ - var dpiPerDppx = 96; - var query = - // FF16-17 - '(min-resolution: ' + pixelRatio + 'dppx),' + - // FF6-15 - '(min--moz-device-pixel-ratio: ' + pixelRatio + '),' + - // IE10 (this works for the two browsers above too but I don't want to - // trust the 1:96 fixed ratio magic) - '(min-resolution: ' + (pixelRatio * dpiPerDppx) + 'dpi)'; - return win.matchMedia(query).matches ? pixelRatio : 0; -}; - - -/** - * Gets '2d' context of a canvas. Shortcut for canvas.getContext('2d') with a - * type information. - * @param {!HTMLCanvasElement} canvas - * @return {!CanvasRenderingContext2D} - */ -goog.dom.getCanvasContext2D = function(canvas) { - return /** @type {!CanvasRenderingContext2D} */ (canvas.getContext('2d')); -}; - - - -/** - * Create an instance of a DOM helper with a new document object. - * @param {Document=} opt_document Document object to associate with this - * DOM helper. - * @constructor - */ -goog.dom.DomHelper = function(opt_document) { - /** - * Reference to the document object to use - * @type {!Document} - * @private - */ - this.document_ = opt_document || goog.global.document || document; -}; - - -/** - * Gets the dom helper object for the document where the element resides. - * @param {Node=} opt_node If present, gets the DomHelper for this node. - * @return {!goog.dom.DomHelper} The DomHelper. - */ -goog.dom.DomHelper.prototype.getDomHelper = goog.dom.getDomHelper; - - -/** - * Sets the document object. - * @param {!Document} document Document object. - */ -goog.dom.DomHelper.prototype.setDocument = function(document) { - this.document_ = document; -}; - - -/** - * Gets the document object being used by the dom library. - * @return {!Document} Document object. - */ -goog.dom.DomHelper.prototype.getDocument = function() { - return this.document_; -}; - - -/** - * Alias for {@code getElementById}. If a DOM node is passed in then we just - * return that. - * @param {string|Element} element Element ID or a DOM node. - * @return {Element} The element with the given ID, or the node passed in. - */ -goog.dom.DomHelper.prototype.getElement = function(element) { - return goog.dom.getElementHelper_(this.document_, element); -}; - - -/** - * Gets an element by id, asserting that the element is found. - * - * This is used when an element is expected to exist, and should fail with - * an assertion error if it does not (if assertions are enabled). - * - * @param {string} id Element ID. - * @return {!Element} The element with the given ID, if it exists. - */ -goog.dom.DomHelper.prototype.getRequiredElement = function(id) { - return goog.dom.getRequiredElementHelper_(this.document_, id); -}; - - -/** - * Alias for {@code getElement}. - * @param {string|Element} element Element ID or a DOM node. - * @return {Element} The element with the given ID, or the node passed in. - * @deprecated Use {@link goog.dom.DomHelper.prototype.getElement} instead. - */ -goog.dom.DomHelper.prototype.$ = goog.dom.DomHelper.prototype.getElement; - - -/** - * Gets elements by tag name. - * @param {!goog.dom.TagName<T>} tagName - * @param {(!Document|!Element)=} opt_parent Parent element or document where to - * look for elements. Defaults to document of this DomHelper. - * @return {!NodeList<R>} List of elements. The members of the list are - * {!Element} if tagName is not a member of goog.dom.TagName or more - * specific types if it is (e.g. {!HTMLAnchorElement} for - * goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.DomHelper.prototype.getElementsByTagName = - function(tagName, opt_parent) { - var parent = opt_parent || this.document_; - return parent.getElementsByTagName(String(tagName)); -}; - - -/** - * Looks up elements by both tag and class name, using browser native functions - * ({@code querySelectorAll}, {@code getElementsByTagName} or - * {@code getElementsByClassName}) where possible. The returned array is a live - * NodeList or a static list depending on the code path taken. - * - * @see goog.dom.query - * - * @param {(string|?goog.dom.TagName<T>)=} opt_tag Element tag name or * for all - * tags. - * @param {?string=} opt_class Optional class name. - * @param {(Document|Element)=} opt_el Optional element to look in. - * @return {!IArrayLike<R>} Array-like list of elements (only a length property - * and numerical indices are guaranteed to exist). The members of the array - * are {!Element} if opt_tag is not a member of goog.dom.TagName or more - * specific types if it is (e.g. {!HTMLAnchorElement} for - * goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.DomHelper.prototype.getElementsByTagNameAndClass = function( - opt_tag, opt_class, opt_el) { - return goog.dom.getElementsByTagNameAndClass_( - this.document_, opt_tag, opt_class, opt_el); -}; - - -/** - * Gets the first element matching the tag and the class. - * - * @param {(string|?goog.dom.TagName<T>)=} opt_tag Element tag name. - * @param {?string=} opt_class Optional class name. - * @param {(Document|Element)=} opt_el Optional element to look in. - * @return {?R} Reference to a DOM node. The return type is {?Element} if - * tagName is a string or a more specific type if it is a member of - * goog.dom.TagName (e.g. {?HTMLAnchorElement} for goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.DomHelper.prototype.getElementByTagNameAndClass = function( - opt_tag, opt_class, opt_el) { - return goog.dom.getElementByTagNameAndClass_( - this.document_, opt_tag, opt_class, opt_el); -}; - - -/** - * Returns an array of all the elements with the provided className. - * @see {goog.dom.query} - * @param {string} className the name of the class to look for. - * @param {Element|Document=} opt_el Optional element to look in. - * @return {!IArrayLike<!Element>} The items found with the class name provided. - */ -goog.dom.DomHelper.prototype.getElementsByClass = function(className, opt_el) { - var doc = opt_el || this.document_; - return goog.dom.getElementsByClass(className, doc); -}; - - -/** - * Returns the first element we find matching the provided class name. - * @see {goog.dom.query} - * @param {string} className the name of the class to look for. - * @param {(Element|Document)=} opt_el Optional element to look in. - * @return {Element} The first item found with the class name provided. - */ -goog.dom.DomHelper.prototype.getElementByClass = function(className, opt_el) { - var doc = opt_el || this.document_; - return goog.dom.getElementByClass(className, doc); -}; - - -/** - * Ensures an element with the given className exists, and then returns the - * first element with the provided className. - * @see {goog.dom.query} - * @param {string} className the name of the class to look for. - * @param {(!Element|!Document)=} opt_root Optional element or document to look - * in. - * @return {!Element} The first item found with the class name provided. - * @throws {goog.asserts.AssertionError} Thrown if no element is found. - */ -goog.dom.DomHelper.prototype.getRequiredElementByClass = function( - className, opt_root) { - var root = opt_root || this.document_; - return goog.dom.getRequiredElementByClass(className, root); -}; - - -/** - * Alias for {@code getElementsByTagNameAndClass}. - * @deprecated Use DomHelper getElementsByTagNameAndClass. - * @see goog.dom.query - * - * @param {(string|?goog.dom.TagName<T>)=} opt_tag Element tag name. - * @param {?string=} opt_class Optional class name. - * @param {Element=} opt_el Optional element to look in. - * @return {!IArrayLike<R>} Array-like list of elements (only a length property - * and numerical indices are guaranteed to exist). The members of the array - * are {!Element} if opt_tag is a string or more specific types if it is - * a member of goog.dom.TagName (e.g. {!HTMLAnchorElement} for - * goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.DomHelper.prototype.$$ = - goog.dom.DomHelper.prototype.getElementsByTagNameAndClass; - - -/** - * Sets a number of properties on a node. - * @param {Element} element DOM node to set properties on. - * @param {Object} properties Hash of property:value pairs. - */ -goog.dom.DomHelper.prototype.setProperties = goog.dom.setProperties; - - -/** - * Gets the dimensions of the viewport. - * @param {Window=} opt_window Optional window element to test. Defaults to - * the window of the Dom Helper. - * @return {!goog.math.Size} Object with values 'width' and 'height'. - */ -goog.dom.DomHelper.prototype.getViewportSize = function(opt_window) { - // TODO(arv): This should not take an argument. That breaks the rule of a - // a DomHelper representing a single frame/window/document. - return goog.dom.getViewportSize(opt_window || this.getWindow()); -}; - - -/** - * Calculates the height of the document. - * - * @return {number} The height of the document. - */ -goog.dom.DomHelper.prototype.getDocumentHeight = function() { - return goog.dom.getDocumentHeight_(this.getWindow()); -}; - - -/** - * Typedef for use with goog.dom.createDom and goog.dom.append. - * @typedef {Object|string|Array|NodeList} - */ -goog.dom.Appendable; - - -/** - * Returns a dom node with a set of attributes. This function accepts varargs - * for subsequent nodes to be added. Subsequent nodes will be added to the - * first node as childNodes. - * - * So: - * <code>createDom(goog.dom.TagName.DIV, null, createDom(goog.dom.TagName.P), - * createDom(goog.dom.TagName.P));</code> would return a div with two child - * paragraphs - * - * An easy way to move all child nodes of an existing element to a new parent - * element is: - * <code>createDom(goog.dom.TagName.DIV, null, oldElement.childNodes);</code> - * which will remove all child nodes from the old element and add them as - * child nodes of the new DIV. - * - * @param {string|!goog.dom.TagName<T>} tagName Tag to create. - * @param {?Object|?Array<string>|string=} opt_attributes If object, then a map - * of name-value pairs for attributes. If a string, then this is the - * className of the new element. If an array, the elements will be joined - * together as the className of the new element. - * @param {...goog.dom.Appendable} var_args Further DOM nodes or - * strings for text nodes. If one of the var_args is an array or - * NodeList, its elements will be added as childNodes instead. - * @return {R} Reference to a DOM node. The return type is {!Element} if tagName - * is a string or a more specific type if it is a member of - * goog.dom.TagName (e.g. {!HTMLAnchorElement} for goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.DomHelper.prototype.createDom = function( - tagName, opt_attributes, var_args) { - return goog.dom.createDom_(this.document_, arguments); -}; - - -/** - * Alias for {@code createDom}. - * @param {string|!goog.dom.TagName<T>} tagName Tag to create. - * @param {?Object|?Array<string>|string=} opt_attributes If object, then a map - * of name-value pairs for attributes. If a string, then this is the - * className of the new element. If an array, the elements will be joined - * together as the className of the new element. - * @param {...goog.dom.Appendable} var_args Further DOM nodes or strings for - * text nodes. If one of the var_args is an array, its children will be - * added as childNodes instead. - * @return {R} Reference to a DOM node. The return type is {!Element} if tagName - * is a string or a more specific type if it is a member of - * goog.dom.TagName (e.g. {!HTMLAnchorElement} for goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - * @deprecated Use {@link goog.dom.DomHelper.prototype.createDom} instead. - */ -goog.dom.DomHelper.prototype.$dom = goog.dom.DomHelper.prototype.createDom; - - -/** - * Creates a new element. - * @param {string|!goog.dom.TagName<T>} name Tag to create. - * @return {R} The new element. The return type is {!Element} if name is - * a string or a more specific type if it is a member of goog.dom.TagName - * (e.g. {!HTMLAnchorElement} for goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.DomHelper.prototype.createElement = function(name) { - return goog.dom.createElement_(this.document_, name); -}; - - -/** - * Creates a new text node. - * @param {number|string} content Content. - * @return {!Text} The new text node. - */ -goog.dom.DomHelper.prototype.createTextNode = function(content) { - return this.document_.createTextNode(String(content)); -}; - - -/** - * Create a table. - * @param {number} rows The number of rows in the table. Must be >= 1. - * @param {number} columns The number of columns in the table. Must be >= 1. - * @param {boolean=} opt_fillWithNbsp If true, fills table entries with - * {@code goog.string.Unicode.NBSP} characters. - * @return {!HTMLElement} The created table. - */ -goog.dom.DomHelper.prototype.createTable = function( - rows, columns, opt_fillWithNbsp) { - return goog.dom.createTable_( - this.document_, rows, columns, !!opt_fillWithNbsp); -}; - - -/** - * Converts an HTML into a node or a document fragment. A single Node is used if - * {@code html} only generates a single node. If {@code html} generates multiple - * nodes then these are put inside a {@code DocumentFragment}. This is a safe - * version of {@code goog.dom.DomHelper#htmlToDocumentFragment} which is now - * deleted. - * @param {!goog.html.SafeHtml} html The HTML markup to convert. - * @return {!Node} The resulting node. - */ -goog.dom.DomHelper.prototype.safeHtmlToNode = function(html) { - return goog.dom.safeHtmlToNode_(this.document_, html); -}; - - -/** - * Returns true if the browser is in "CSS1-compatible" (standards-compliant) - * mode, false otherwise. - * @return {boolean} True if in CSS1-compatible mode. - */ -goog.dom.DomHelper.prototype.isCss1CompatMode = function() { - return goog.dom.isCss1CompatMode_(this.document_); -}; - - -/** - * Gets the window object associated with the document. - * @return {!Window} The window associated with the given document. - */ -goog.dom.DomHelper.prototype.getWindow = function() { - return goog.dom.getWindow_(this.document_); -}; - - -/** - * Gets the document scroll element. - * @return {!Element} Scrolling element. - */ -goog.dom.DomHelper.prototype.getDocumentScrollElement = function() { - return goog.dom.getDocumentScrollElement_(this.document_); -}; - - -/** - * Gets the document scroll distance as a coordinate object. - * @return {!goog.math.Coordinate} Object with properties 'x' and 'y'. - */ -goog.dom.DomHelper.prototype.getDocumentScroll = function() { - return goog.dom.getDocumentScroll_(this.document_); -}; - - -/** - * Determines the active element in the given document. - * @param {Document=} opt_doc The document to look in. - * @return {Element} The active element. - */ -goog.dom.DomHelper.prototype.getActiveElement = function(opt_doc) { - return goog.dom.getActiveElement(opt_doc || this.document_); -}; - - -/** - * Appends a child to a node. - * @param {Node} parent Parent. - * @param {Node} child Child. - */ -goog.dom.DomHelper.prototype.appendChild = goog.dom.appendChild; - - -/** - * Appends a node with text or other nodes. - * @param {!Node} parent The node to append nodes to. - * @param {...goog.dom.Appendable} var_args The things to append to the node. - * If this is a Node it is appended as is. - * If this is a string then a text node is appended. - * If this is an array like object then fields 0 to length - 1 are appended. - */ -goog.dom.DomHelper.prototype.append = goog.dom.append; - - -/** - * Determines if the given node can contain children, intended to be used for - * HTML generation. - * - * @param {Node} node The node to check. - * @return {boolean} Whether the node can contain children. - */ -goog.dom.DomHelper.prototype.canHaveChildren = goog.dom.canHaveChildren; - - -/** - * Removes all the child nodes on a DOM node. - * @param {Node} node Node to remove children from. - */ -goog.dom.DomHelper.prototype.removeChildren = goog.dom.removeChildren; - - -/** - * Inserts a new node before an existing reference node (i.e., as the previous - * sibling). If the reference node has no parent, then does nothing. - * @param {Node} newNode Node to insert. - * @param {Node} refNode Reference node to insert before. - */ -goog.dom.DomHelper.prototype.insertSiblingBefore = goog.dom.insertSiblingBefore; - - -/** - * Inserts a new node after an existing reference node (i.e., as the next - * sibling). If the reference node has no parent, then does nothing. - * @param {Node} newNode Node to insert. - * @param {Node} refNode Reference node to insert after. - */ -goog.dom.DomHelper.prototype.insertSiblingAfter = goog.dom.insertSiblingAfter; - - -/** - * Insert a child at a given index. If index is larger than the number of child - * nodes that the parent currently has, the node is inserted as the last child - * node. - * @param {Element} parent The element into which to insert the child. - * @param {Node} child The element to insert. - * @param {number} index The index at which to insert the new child node. Must - * not be negative. - */ -goog.dom.DomHelper.prototype.insertChildAt = goog.dom.insertChildAt; - - -/** - * Removes a node from its parent. - * @param {Node} node The node to remove. - * @return {Node} The node removed if removed; else, null. - */ -goog.dom.DomHelper.prototype.removeNode = goog.dom.removeNode; - - -/** - * Replaces a node in the DOM tree. Will do nothing if {@code oldNode} has no - * parent. - * @param {Node} newNode Node to insert. - * @param {Node} oldNode Node to replace. - */ -goog.dom.DomHelper.prototype.replaceNode = goog.dom.replaceNode; - - -/** - * Flattens an element. That is, removes it and replace it with its children. - * @param {Element} element The element to flatten. - * @return {Element|undefined} The original element, detached from the document - * tree, sans children, or undefined if the element was already not in the - * document. - */ -goog.dom.DomHelper.prototype.flattenElement = goog.dom.flattenElement; - - -/** - * Returns an array containing just the element children of the given element. - * @param {Element} element The element whose element children we want. - * @return {!(Array<!Element>|NodeList<!Element>)} An array or array-like list - * of just the element children of the given element. - */ -goog.dom.DomHelper.prototype.getChildren = goog.dom.getChildren; - - -/** - * Returns the first child node that is an element. - * @param {Node} node The node to get the first child element of. - * @return {Element} The first child node of {@code node} that is an element. - */ -goog.dom.DomHelper.prototype.getFirstElementChild = - goog.dom.getFirstElementChild; - - -/** - * Returns the last child node that is an element. - * @param {Node} node The node to get the last child element of. - * @return {Element} The last child node of {@code node} that is an element. - */ -goog.dom.DomHelper.prototype.getLastElementChild = goog.dom.getLastElementChild; - - -/** - * Returns the first next sibling that is an element. - * @param {Node} node The node to get the next sibling element of. - * @return {Element} The next sibling of {@code node} that is an element. - */ -goog.dom.DomHelper.prototype.getNextElementSibling = - goog.dom.getNextElementSibling; - - -/** - * Returns the first previous sibling that is an element. - * @param {Node} node The node to get the previous sibling element of. - * @return {Element} The first previous sibling of {@code node} that is - * an element. - */ -goog.dom.DomHelper.prototype.getPreviousElementSibling = - goog.dom.getPreviousElementSibling; - - -/** - * Returns the next node in source order from the given node. - * @param {Node} node The node. - * @return {Node} The next node in the DOM tree, or null if this was the last - * node. - */ -goog.dom.DomHelper.prototype.getNextNode = goog.dom.getNextNode; - - -/** - * Returns the previous node in source order from the given node. - * @param {Node} node The node. - * @return {Node} The previous node in the DOM tree, or null if this was the - * first node. - */ -goog.dom.DomHelper.prototype.getPreviousNode = goog.dom.getPreviousNode; - - -/** - * Whether the object looks like a DOM node. - * @param {?} obj The object being tested for node likeness. - * @return {boolean} Whether the object looks like a DOM node. - */ -goog.dom.DomHelper.prototype.isNodeLike = goog.dom.isNodeLike; - - -/** - * Whether the object looks like an Element. - * @param {?} obj The object being tested for Element likeness. - * @return {boolean} Whether the object looks like an Element. - */ -goog.dom.DomHelper.prototype.isElement = goog.dom.isElement; - - -/** - * Returns true if the specified value is a Window object. This includes the - * global window for HTML pages, and iframe windows. - * @param {?} obj Variable to test. - * @return {boolean} Whether the variable is a window. - */ -goog.dom.DomHelper.prototype.isWindow = goog.dom.isWindow; - - -/** - * Returns an element's parent, if it's an Element. - * @param {Element} element The DOM element. - * @return {Element} The parent, or null if not an Element. - */ -goog.dom.DomHelper.prototype.getParentElement = goog.dom.getParentElement; - - -/** - * Whether a node contains another node. - * @param {Node} parent The node that should contain the other node. - * @param {Node} descendant The node to test presence of. - * @return {boolean} Whether the parent node contains the descendent node. - */ -goog.dom.DomHelper.prototype.contains = goog.dom.contains; - - -/** - * Compares the document order of two nodes, returning 0 if they are the same - * node, a negative number if node1 is before node2, and a positive number if - * node2 is before node1. Note that we compare the order the tags appear in the - * document so in the tree <b><i>text</i></b> the B node is considered to be - * before the I node. - * - * @param {Node} node1 The first node to compare. - * @param {Node} node2 The second node to compare. - * @return {number} 0 if the nodes are the same node, a negative number if node1 - * is before node2, and a positive number if node2 is before node1. - */ -goog.dom.DomHelper.prototype.compareNodeOrder = goog.dom.compareNodeOrder; - - -/** - * Find the deepest common ancestor of the given nodes. - * @param {...Node} var_args The nodes to find a common ancestor of. - * @return {Node} The common ancestor of the nodes, or null if there is none. - * null will only be returned if two or more of the nodes are from different - * documents. - */ -goog.dom.DomHelper.prototype.findCommonAncestor = goog.dom.findCommonAncestor; - - -/** - * Returns the owner document for a node. - * @param {Node} node The node to get the document for. - * @return {!Document} The document owning the node. - */ -goog.dom.DomHelper.prototype.getOwnerDocument = goog.dom.getOwnerDocument; - - -/** - * Cross browser function for getting the document element of an iframe. - * @param {Element} iframe Iframe element. - * @return {!Document} The frame content document. - */ -goog.dom.DomHelper.prototype.getFrameContentDocument = - goog.dom.getFrameContentDocument; - - -/** - * Cross browser function for getting the window of a frame or iframe. - * @param {Element} frame Frame element. - * @return {Window} The window associated with the given frame. - */ -goog.dom.DomHelper.prototype.getFrameContentWindow = - goog.dom.getFrameContentWindow; - - -/** - * Sets the text content of a node, with cross-browser support. - * @param {Node} node The node to change the text content of. - * @param {string|number} text The value that should replace the node's content. - */ -goog.dom.DomHelper.prototype.setTextContent = goog.dom.setTextContent; - - -/** - * Gets the outerHTML of a node, which islike innerHTML, except that it - * actually contains the HTML of the node itself. - * @param {Element} element The element to get the HTML of. - * @return {string} The outerHTML of the given element. - */ -goog.dom.DomHelper.prototype.getOuterHtml = goog.dom.getOuterHtml; - - -/** - * Finds the first descendant node that matches the filter function. This does - * a depth first search. - * @param {Node} root The root of the tree to search. - * @param {function(Node) : boolean} p The filter function. - * @return {Node|undefined} The found node or undefined if none is found. - */ -goog.dom.DomHelper.prototype.findNode = goog.dom.findNode; - - -/** - * Finds all the descendant nodes that matches the filter function. This does a - * depth first search. - * @param {Node} root The root of the tree to search. - * @param {function(Node) : boolean} p The filter function. - * @return {Array<Node>} The found nodes or an empty array if none are found. - */ -goog.dom.DomHelper.prototype.findNodes = goog.dom.findNodes; - - -/** - * Returns true if the element has a tab index that allows it to receive - * keyboard focus (tabIndex >= 0), false otherwise. Note that some elements - * natively support keyboard focus, even if they have no tab index. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element has a tab index that allows keyboard - * focus. - */ -goog.dom.DomHelper.prototype.isFocusableTabIndex = goog.dom.isFocusableTabIndex; - - -/** - * Enables or disables keyboard focus support on the element via its tab index. - * Only elements for which {@link goog.dom.isFocusableTabIndex} returns true - * (or elements that natively support keyboard focus, like form elements) can - * receive keyboard focus. See http://go/tabindex for more info. - * @param {Element} element Element whose tab index is to be changed. - * @param {boolean} enable Whether to set or remove a tab index on the element - * that supports keyboard focus. - */ -goog.dom.DomHelper.prototype.setFocusableTabIndex = - goog.dom.setFocusableTabIndex; - - -/** - * Returns true if the element can be focused, i.e. it has a tab index that - * allows it to receive keyboard focus (tabIndex >= 0), or it is an element - * that natively supports keyboard focus. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element allows keyboard focus. - */ -goog.dom.DomHelper.prototype.isFocusable = goog.dom.isFocusable; - - -/** - * Returns the text contents of the current node, without markup. New lines are - * stripped and whitespace is collapsed, such that each character would be - * visible. - * - * In browsers that support it, innerText is used. Other browsers attempt to - * simulate it via node traversal. Line breaks are canonicalized in IE. - * - * @param {Node} node The node from which we are getting content. - * @return {string} The text content. - */ -goog.dom.DomHelper.prototype.getTextContent = goog.dom.getTextContent; - - -/** - * Returns the text length of the text contained in a node, without markup. This - * is equivalent to the selection length if the node was selected, or the number - * of cursor movements to traverse the node. Images & BRs take one space. New - * lines are ignored. - * - * @param {Node} node The node whose text content length is being calculated. - * @return {number} The length of {@code node}'s text content. - */ -goog.dom.DomHelper.prototype.getNodeTextLength = goog.dom.getNodeTextLength; - - -/** - * Returns the text offset of a node relative to one of its ancestors. The text - * length is the same as the length calculated by - * {@code goog.dom.getNodeTextLength}. - * - * @param {Node} node The node whose offset is being calculated. - * @param {Node=} opt_offsetParent Defaults to the node's owner document's body. - * @return {number} The text offset. - */ -goog.dom.DomHelper.prototype.getNodeTextOffset = goog.dom.getNodeTextOffset; - - -/** - * Returns the node at a given offset in a parent node. If an object is - * provided for the optional third parameter, the node and the remainder of the - * offset will stored as properties of this object. - * @param {Node} parent The parent node. - * @param {number} offset The offset into the parent node. - * @param {Object=} opt_result Object to be used to store the return value. The - * return value will be stored in the form {node: Node, remainder: number} - * if this object is provided. - * @return {Node} The node at the given offset. - */ -goog.dom.DomHelper.prototype.getNodeAtOffset = goog.dom.getNodeAtOffset; - - -/** - * Returns true if the object is a {@code NodeList}. To qualify as a NodeList, - * the object must have a numeric length property and an item function (which - * has type 'string' on IE for some reason). - * @param {Object} val Object to test. - * @return {boolean} Whether the object is a NodeList. - */ -goog.dom.DomHelper.prototype.isNodeList = goog.dom.isNodeList; - - -/** - * Walks up the DOM hierarchy returning the first ancestor that has the passed - * tag name and/or class name. If the passed element matches the specified - * criteria, the element itself is returned. - * @param {Node} element The DOM node to start with. - * @param {?(goog.dom.TagName<T>|string)=} opt_tag The tag name to match (or - * null/undefined to match only based on class name). - * @param {?string=} opt_class The class name to match (or null/undefined to - * match only based on tag name). - * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the - * dom. - * @return {?R} The first ancestor that matches the passed criteria, or - * null if no match is found. The return type is {?Element} if opt_tag is - * not a member of goog.dom.TagName or a more specific type if it is (e.g. - * {?HTMLAnchorElement} for goog.dom.TagName.A). - * @template T - * @template R := cond(isUnknown(T), 'Element', T) =: - */ -goog.dom.DomHelper.prototype.getAncestorByTagNameAndClass = - goog.dom.getAncestorByTagNameAndClass; - - -/** - * Walks up the DOM hierarchy returning the first ancestor that has the passed - * class name. If the passed element matches the specified criteria, the - * element itself is returned. - * @param {Node} element The DOM node to start with. - * @param {string} class The class name to match. - * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the - * dom. - * @return {Element} The first ancestor that matches the passed criteria, or - * null if none match. - */ -goog.dom.DomHelper.prototype.getAncestorByClass = goog.dom.getAncestorByClass; - - -/** - * Walks up the DOM hierarchy returning the first ancestor that passes the - * matcher function. - * @param {Node} element The DOM node to start with. - * @param {function(Node) : boolean} matcher A function that returns true if the - * passed node matches the desired criteria. - * @param {boolean=} opt_includeNode If true, the node itself is included in - * the search (the first call to the matcher will pass startElement as - * the node to test). - * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the - * dom. - * @return {Node} DOM node that matched the matcher, or null if there was - * no match. - */ -goog.dom.DomHelper.prototype.getAncestor = goog.dom.getAncestor; - - -/** - * Gets '2d' context of a canvas. Shortcut for canvas.getContext('2d') with a - * type information. - * @param {!HTMLCanvasElement} canvas - * @return {!CanvasRenderingContext2D} - */ -goog.dom.DomHelper.prototype.getCanvasContext2D = goog.dom.getCanvasContext2D;
diff --git a/third_party/ink/closure/dom/htmlelement.js b/third_party/ink/closure/dom/htmlelement.js deleted file mode 100644 index c48f753..0000000 --- a/third_party/ink/closure/dom/htmlelement.js +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2017 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.HtmlElement'); - - - -/** - * This subclass of HTMLElement is used when only a HTMLElement is possible and - * not any of its subclasses. Normally, a type can refer to an instance of - * itself or an instance of any subtype. More concretely, if HTMLElement is used - * then the compiler must assume that it might still be e.g. HTMLScriptElement. - * With this, the type check knows that it couldn't be any special element. - * - * @constructor - * @extends {HTMLElement} - */ -goog.dom.HtmlElement = function() {};
diff --git a/third_party/ink/closure/dom/nodetype.js b/third_party/ink/closure/dom/nodetype.js deleted file mode 100644 index cccb470..0000000 --- a/third_party/ink/closure/dom/nodetype.js +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Definition of goog.dom.NodeType. - */ - -goog.provide('goog.dom.NodeType'); - - -/** - * Constants for the nodeType attribute in the Node interface. - * - * These constants match those specified in the Node interface. These are - * usually present on the Node object in recent browsers, but not in older - * browsers (specifically, early IEs) and thus are given here. - * - * In some browsers (early IEs), these are not defined on the Node object, - * so they are provided here. - * - * See http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-1950641247 - * @enum {number} - */ -goog.dom.NodeType = { - ELEMENT: 1, - ATTRIBUTE: 2, - TEXT: 3, - CDATA_SECTION: 4, - ENTITY_REFERENCE: 5, - ENTITY: 6, - PROCESSING_INSTRUCTION: 7, - COMMENT: 8, - DOCUMENT: 9, - DOCUMENT_TYPE: 10, - DOCUMENT_FRAGMENT: 11, - NOTATION: 12 -};
diff --git a/third_party/ink/closure/dom/safe.js b/third_party/ink/closure/dom/safe.js deleted file mode 100644 index a869e1b..0000000 --- a/third_party/ink/closure/dom/safe.js +++ /dev/null
@@ -1,458 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Type-safe wrappers for unsafe DOM APIs. - * - * This file provides type-safe wrappers for DOM APIs that can result in - * cross-site scripting (XSS) vulnerabilities, if the API is supplied with - * untrusted (attacker-controlled) input. Instead of plain strings, the type - * safe wrappers consume values of types from the goog.html package whose - * contract promises that values are safe to use in the corresponding context. - * - * Hence, a program that exclusively uses the wrappers in this file (i.e., whose - * only reference to security-sensitive raw DOM APIs are in this file) is - * guaranteed to be free of XSS due to incorrect use of such DOM APIs (modulo - * correctness of code that produces values of the respective goog.html types, - * and absent code that violates type safety). - * - * For example, assigning to an element's .innerHTML property a string that is - * derived (even partially) from untrusted input typically results in an XSS - * vulnerability. The type-safe wrapper goog.dom.safe.setInnerHtml consumes a - * value of type goog.html.SafeHtml, whose contract states that using its values - * in a HTML context will not result in XSS. Hence a program that is free of - * direct assignments to any element's innerHTML property (with the exception of - * the assignment to .innerHTML in this file) is guaranteed to be free of XSS - * due to assignment of untrusted strings to the innerHTML property. - */ - -goog.provide('goog.dom.safe'); -goog.provide('goog.dom.safe.InsertAdjacentHtmlPosition'); - -goog.require('goog.asserts'); -goog.require('goog.dom.asserts'); -goog.require('goog.html.SafeHtml'); -goog.require('goog.html.SafeScript'); -goog.require('goog.html.SafeStyle'); -goog.require('goog.html.SafeUrl'); -goog.require('goog.html.TrustedResourceUrl'); -goog.require('goog.string'); -goog.require('goog.string.Const'); - - -/** @enum {string} */ -goog.dom.safe.InsertAdjacentHtmlPosition = { - AFTERBEGIN: 'afterbegin', - AFTEREND: 'afterend', - BEFOREBEGIN: 'beforebegin', - BEFOREEND: 'beforeend' -}; - - -/** - * Inserts known-safe HTML into a Node, at the specified position. - * @param {!Node} node The node on which to call insertAdjacentHTML. - * @param {!goog.dom.safe.InsertAdjacentHtmlPosition} position Position where - * to insert the HTML. - * @param {!goog.html.SafeHtml} html The known-safe HTML to insert. - */ -goog.dom.safe.insertAdjacentHtml = function(node, position, html) { - node.insertAdjacentHTML(position, goog.html.SafeHtml.unwrap(html)); -}; - - -/** - * Tags not allowed in goog.dom.safe.setInnerHtml. - * @private @const {!Object<string, boolean>} - */ -goog.dom.safe.SET_INNER_HTML_DISALLOWED_TAGS_ = { - 'MATH': true, - 'SCRIPT': true, - 'STYLE': true, - 'SVG': true, - 'TEMPLATE': true -}; - - -/** - * Assigns known-safe HTML to an element's innerHTML property. - * @param {!Element} elem The element whose innerHTML is to be assigned to. - * @param {!goog.html.SafeHtml} html The known-safe HTML to assign. - * @throws {Error} If called with one of these tags: math, script, style, svg, - * template. - */ -goog.dom.safe.setInnerHtml = function(elem, html) { - if (goog.asserts.ENABLE_ASSERTS) { - var tagName = elem.tagName.toUpperCase(); - if (goog.dom.safe.SET_INNER_HTML_DISALLOWED_TAGS_[tagName]) { - throw new Error( - 'goog.dom.safe.setInnerHtml cannot be used to set content of ' + - elem.tagName + '.'); - } - } - elem.innerHTML = goog.html.SafeHtml.unwrap(html); -}; - - -/** - * Assigns known-safe HTML to an element's outerHTML property. - * @param {!Element} elem The element whose outerHTML is to be assigned to. - * @param {!goog.html.SafeHtml} html The known-safe HTML to assign. - */ -goog.dom.safe.setOuterHtml = function(elem, html) { - elem.outerHTML = goog.html.SafeHtml.unwrap(html); -}; - - -/** - * Sets the given element's style property to the contents of the provided - * SafeStyle object. - * @param {!Element} elem - * @param {!goog.html.SafeStyle} style - */ -goog.dom.safe.setStyle = function(elem, style) { - elem.style.cssText = goog.html.SafeStyle.unwrap(style); -}; - - -/** - * Writes known-safe HTML to a document. - * @param {!Document} doc The document to be written to. - * @param {!goog.html.SafeHtml} html The known-safe HTML to assign. - */ -goog.dom.safe.documentWrite = function(doc, html) { - doc.write(goog.html.SafeHtml.unwrap(html)); -}; - - -/** - * Safely assigns a URL to an anchor element's href property. - * - * If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to - * anchor's href property. If url is of type string however, it is first - * sanitized using goog.html.SafeUrl.sanitize. - * - * Example usage: - * goog.dom.safe.setAnchorHref(anchorEl, url); - * which is a safe alternative to - * anchorEl.href = url; - * The latter can result in XSS vulnerabilities if url is a - * user-/attacker-controlled value. - * - * @param {!HTMLAnchorElement} anchor The anchor element whose href property - * is to be assigned to. - * @param {string|!goog.html.SafeUrl} url The URL to assign. - * @see goog.html.SafeUrl#sanitize - */ -goog.dom.safe.setAnchorHref = function(anchor, url) { - goog.dom.asserts.assertIsHTMLAnchorElement(anchor); - /** @type {!goog.html.SafeUrl} */ - var safeUrl; - if (url instanceof goog.html.SafeUrl) { - safeUrl = url; - } else { - safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url); - } - anchor.href = goog.html.SafeUrl.unwrap(safeUrl); -}; - - -/** - * Safely assigns a URL to an image element's src property. - * - * If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to - * image's src property. If url is of type string however, it is first - * sanitized using goog.html.SafeUrl.sanitize. - * - * @param {!HTMLImageElement} imageElement The image element whose src property - * is to be assigned to. - * @param {string|!goog.html.SafeUrl} url The URL to assign. - * @see goog.html.SafeUrl#sanitize - */ -goog.dom.safe.setImageSrc = function(imageElement, url) { - goog.dom.asserts.assertIsHTMLImageElement(imageElement); - /** @type {!goog.html.SafeUrl} */ - var safeUrl; - if (url instanceof goog.html.SafeUrl) { - safeUrl = url; - } else { - safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url); - } - imageElement.src = goog.html.SafeUrl.unwrap(safeUrl); -}; - - -/** - * Safely assigns a URL to an embed element's src property. - * - * Example usage: - * goog.dom.safe.setEmbedSrc(embedEl, url); - * which is a safe alternative to - * embedEl.src = url; - * The latter can result in loading untrusted code unless it is ensured that - * the URL refers to a trustworthy resource. - * - * @param {!HTMLEmbedElement} embed The embed element whose src property - * is to be assigned to. - * @param {!goog.html.TrustedResourceUrl} url The URL to assign. - */ -goog.dom.safe.setEmbedSrc = function(embed, url) { - goog.dom.asserts.assertIsHTMLEmbedElement(embed); - embed.src = goog.html.TrustedResourceUrl.unwrap(url); -}; - - -/** - * Safely assigns a URL to a frame element's src property. - * - * Example usage: - * goog.dom.safe.setFrameSrc(frameEl, url); - * which is a safe alternative to - * frameEl.src = url; - * The latter can result in loading untrusted code unless it is ensured that - * the URL refers to a trustworthy resource. - * - * @param {!HTMLFrameElement} frame The frame element whose src property - * is to be assigned to. - * @param {!goog.html.TrustedResourceUrl} url The URL to assign. - */ -goog.dom.safe.setFrameSrc = function(frame, url) { - goog.dom.asserts.assertIsHTMLFrameElement(frame); - frame.src = goog.html.TrustedResourceUrl.unwrap(url); -}; - - -/** - * Safely assigns a URL to an iframe element's src property. - * - * Example usage: - * goog.dom.safe.setIframeSrc(iframeEl, url); - * which is a safe alternative to - * iframeEl.src = url; - * The latter can result in loading untrusted code unless it is ensured that - * the URL refers to a trustworthy resource. - * - * @param {!HTMLIFrameElement} iframe The iframe element whose src property - * is to be assigned to. - * @param {!goog.html.TrustedResourceUrl} url The URL to assign. - */ -goog.dom.safe.setIframeSrc = function(iframe, url) { - goog.dom.asserts.assertIsHTMLIFrameElement(iframe); - iframe.src = goog.html.TrustedResourceUrl.unwrap(url); -}; - - -/** - * Safely assigns HTML to an iframe element's srcdoc property. - * - * Example usage: - * goog.dom.safe.setIframeSrcdoc(iframeEl, safeHtml); - * which is a safe alternative to - * iframeEl.srcdoc = html; - * The latter can result in loading untrusted code. - * - * @param {!HTMLIFrameElement} iframe The iframe element whose srcdoc property - * is to be assigned to. - * @param {!goog.html.SafeHtml} html The HTML to assign. - */ -goog.dom.safe.setIframeSrcdoc = function(iframe, html) { - goog.dom.asserts.assertIsHTMLIFrameElement(iframe); - iframe.srcdoc = goog.html.SafeHtml.unwrap(html); -}; - - -/** - * Safely sets a link element's href and rel properties. Whether or not - * the URL assigned to href has to be a goog.html.TrustedResourceUrl - * depends on the value of the rel property. If rel contains "stylesheet" - * then a TrustedResourceUrl is required. - * - * Example usage: - * goog.dom.safe.setLinkHrefAndRel(linkEl, url, 'stylesheet'); - * which is a safe alternative to - * linkEl.rel = 'stylesheet'; - * linkEl.href = url; - * The latter can result in loading untrusted code unless it is ensured that - * the URL refers to a trustworthy resource. - * - * @param {!HTMLLinkElement} link The link element whose href property - * is to be assigned to. - * @param {string|!goog.html.SafeUrl|!goog.html.TrustedResourceUrl} url The URL - * to assign to the href property. Must be a TrustedResourceUrl if the - * value assigned to rel contains "stylesheet". A string value is - * sanitized with goog.html.SafeUrl.sanitize. - * @param {string} rel The value to assign to the rel property. - * @throws {Error} if rel contains "stylesheet" and url is not a - * TrustedResourceUrl - * @see goog.html.SafeUrl#sanitize - */ -goog.dom.safe.setLinkHrefAndRel = function(link, url, rel) { - goog.dom.asserts.assertIsHTMLLinkElement(link); - link.rel = rel; - if (goog.string.caseInsensitiveContains(rel, 'stylesheet')) { - goog.asserts.assert( - url instanceof goog.html.TrustedResourceUrl, - 'URL must be TrustedResourceUrl because "rel" contains "stylesheet"'); - link.href = goog.html.TrustedResourceUrl.unwrap(url); - } else if (url instanceof goog.html.TrustedResourceUrl) { - link.href = goog.html.TrustedResourceUrl.unwrap(url); - } else if (url instanceof goog.html.SafeUrl) { - link.href = goog.html.SafeUrl.unwrap(url); - } else { // string - // SafeUrl.sanitize must return legitimate SafeUrl when passed a string. - link.href = - goog.html.SafeUrl.sanitizeAssertUnchanged(url).getTypedStringValue(); - } -}; - - -/** - * Safely assigns a URL to an object element's data property. - * - * Example usage: - * goog.dom.safe.setObjectData(objectEl, url); - * which is a safe alternative to - * objectEl.data = url; - * The latter can result in loading untrusted code unless setit is ensured that - * the URL refers to a trustworthy resource. - * - * @param {!HTMLObjectElement} object The object element whose data property - * is to be assigned to. - * @param {!goog.html.TrustedResourceUrl} url The URL to assign. - */ -goog.dom.safe.setObjectData = function(object, url) { - goog.dom.asserts.assertIsHTMLObjectElement(object); - object.data = goog.html.TrustedResourceUrl.unwrap(url); -}; - - -/** - * Safely assigns a URL to a script element's src property. - * - * Example usage: - * goog.dom.safe.setScriptSrc(scriptEl, url); - * which is a safe alternative to - * scriptEl.src = url; - * The latter can result in loading untrusted code unless it is ensured that - * the URL refers to a trustworthy resource. - * - * @param {!HTMLScriptElement} script The script element whose src property - * is to be assigned to. - * @param {!goog.html.TrustedResourceUrl} url The URL to assign. - */ -goog.dom.safe.setScriptSrc = function(script, url) { - goog.dom.asserts.assertIsHTMLScriptElement(script); - script.src = goog.html.TrustedResourceUrl.unwrap(url); -}; - - -/** - * Safely assigns a value to a script element's content. - * - * Example usage: - * goog.dom.safe.setScriptContent(scriptEl, content); - * which is a safe alternative to - * scriptEl.text = content; - * The latter can result in executing untrusted code unless it is ensured that - * the code is loaded from a trustworthy resource. - * - * @param {!HTMLScriptElement} script The script element whose content is being - * set. - * @param {!goog.html.SafeScript} content The content to assign. - */ -goog.dom.safe.setScriptContent = function(script, content) { - goog.dom.asserts.assertIsHTMLScriptElement(script); - script.text = goog.html.SafeScript.unwrap(content); -}; - - -/** - * Safely assigns a URL to a Location object's href property. - * - * If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to - * loc's href property. If url is of type string however, it is first sanitized - * using goog.html.SafeUrl.sanitize. - * - * Example usage: - * goog.dom.safe.setLocationHref(document.location, redirectUrl); - * which is a safe alternative to - * document.location.href = redirectUrl; - * The latter can result in XSS vulnerabilities if redirectUrl is a - * user-/attacker-controlled value. - * - * @param {!Location} loc The Location object whose href property is to be - * assigned to. - * @param {string|!goog.html.SafeUrl} url The URL to assign. - * @see goog.html.SafeUrl#sanitize - */ -goog.dom.safe.setLocationHref = function(loc, url) { - goog.dom.asserts.assertIsLocation(loc); - /** @type {!goog.html.SafeUrl} */ - var safeUrl; - if (url instanceof goog.html.SafeUrl) { - safeUrl = url; - } else { - safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url); - } - loc.href = goog.html.SafeUrl.unwrap(safeUrl); -}; - - -/** - * Safely opens a URL in a new window (via window.open). - * - * If url is of type goog.html.SafeUrl, its value is unwrapped and passed in to - * window.open. If url is of type string however, it is first sanitized - * using goog.html.SafeUrl.sanitize. - * - * Note that this function does not prevent leakages via the referer that is - * sent by window.open. It is advised to only use this to open 1st party URLs. - * - * Example usage: - * goog.dom.safe.openInWindow(url); - * which is a safe alternative to - * window.open(url); - * The latter can result in XSS vulnerabilities if redirectUrl is a - * user-/attacker-controlled value. - * - * @param {string|!goog.html.SafeUrl} url The URL to open. - * @param {Window=} opt_openerWin Window of which to call the .open() method. - * Defaults to the global window. - * @param {!goog.string.Const=} opt_name Name of the window to open in. Can be - * _top, etc as allowed by window.open(). - * @param {string=} opt_specs Comma-separated list of specifications, same as - * in window.open(). - * @param {boolean=} opt_replace Whether to replace the current entry in browser - * history, same as in window.open(). - * @return {Window} Window the url was opened in. - */ -goog.dom.safe.openInWindow = function( - url, opt_openerWin, opt_name, opt_specs, opt_replace) { - /** @type {!goog.html.SafeUrl} */ - var safeUrl; - if (url instanceof goog.html.SafeUrl) { - safeUrl = url; - } else { - safeUrl = goog.html.SafeUrl.sanitizeAssertUnchanged(url); - } - var win = opt_openerWin || window; - return win.open( - goog.html.SafeUrl.unwrap(safeUrl), - // If opt_name is undefined, simply passing that in to open() causes IE to - // reuse the current window instead of opening a new one. Thus we pass '' - // in instead, which according to spec opens a new window. See - // https://html.spec.whatwg.org/multipage/browsers.html#dom-open . - opt_name ? goog.string.Const.unwrap(opt_name) : '', opt_specs, - opt_replace); -};
diff --git a/third_party/ink/closure/dom/tagname.js b/third_party/ink/closure/dom/tagname.js deleted file mode 100644 index b3808ad1..0000000 --- a/third_party/ink/closure/dom/tagname.js +++ /dev/null
@@ -1,562 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Defines the goog.dom.TagName class. Its constants enumerate - * all HTML tag names specified in either the the W3C HTML 4.01 index of - * elements or the HTML5 draft specification. - * - * References: - * http://www.w3.org/TR/html401/index/elements.html - * http://dev.w3.org/html5/spec/section-index.html - */ -goog.provide('goog.dom.TagName'); - -goog.require('goog.dom.HtmlElement'); - - -/** - * A tag name with the type of the element stored in the generic. - * @param {string} tagName - * @constructor - * @template T - */ -goog.dom.TagName = function(tagName) { - /** @private {string} */ - this.tagName_ = tagName; -}; - - -/** - * Returns the tag name. - * @return {string} - * @override - */ -goog.dom.TagName.prototype.toString = function() { - return this.tagName_; -}; - - -// Closure Compiler unconditionally converts the following constants to their -// string value (goog.dom.TagName.A -> 'A'). These are the consequences: -// 1. Don't add any members or static members to goog.dom.TagName as they -// couldn't be accessed after this optimization. -// 2. Keep the constant name and its string value the same: -// goog.dom.TagName.X = new goog.dom.TagName('Y'); -// is converted to 'X', not 'Y'. - - -/** @type {!goog.dom.TagName<!HTMLAnchorElement>} */ -goog.dom.TagName.A = new goog.dom.TagName('A'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.ABBR = new goog.dom.TagName('ABBR'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.ACRONYM = new goog.dom.TagName('ACRONYM'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.ADDRESS = new goog.dom.TagName('ADDRESS'); - - -/** @type {!goog.dom.TagName<!HTMLAppletElement>} */ -goog.dom.TagName.APPLET = new goog.dom.TagName('APPLET'); - - -/** @type {!goog.dom.TagName<!HTMLAreaElement>} */ -goog.dom.TagName.AREA = new goog.dom.TagName('AREA'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.ARTICLE = new goog.dom.TagName('ARTICLE'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.ASIDE = new goog.dom.TagName('ASIDE'); - - -/** @type {!goog.dom.TagName<!HTMLAudioElement>} */ -goog.dom.TagName.AUDIO = new goog.dom.TagName('AUDIO'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.B = new goog.dom.TagName('B'); - - -/** @type {!goog.dom.TagName<!HTMLBaseElement>} */ -goog.dom.TagName.BASE = new goog.dom.TagName('BASE'); - - -/** @type {!goog.dom.TagName<!HTMLBaseFontElement>} */ -goog.dom.TagName.BASEFONT = new goog.dom.TagName('BASEFONT'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.BDI = new goog.dom.TagName('BDI'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.BDO = new goog.dom.TagName('BDO'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.BIG = new goog.dom.TagName('BIG'); - - -/** @type {!goog.dom.TagName<!HTMLQuoteElement>} */ -goog.dom.TagName.BLOCKQUOTE = new goog.dom.TagName('BLOCKQUOTE'); - - -/** @type {!goog.dom.TagName<!HTMLBodyElement>} */ -goog.dom.TagName.BODY = new goog.dom.TagName('BODY'); - - -/** @type {!goog.dom.TagName<!HTMLBRElement>} */ -goog.dom.TagName.BR = new goog.dom.TagName('BR'); - - -/** @type {!goog.dom.TagName<!HTMLButtonElement>} */ -goog.dom.TagName.BUTTON = new goog.dom.TagName('BUTTON'); - - -/** @type {!goog.dom.TagName<!HTMLCanvasElement>} */ -goog.dom.TagName.CANVAS = new goog.dom.TagName('CANVAS'); - - -/** @type {!goog.dom.TagName<!HTMLTableCaptionElement>} */ -goog.dom.TagName.CAPTION = new goog.dom.TagName('CAPTION'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.CENTER = new goog.dom.TagName('CENTER'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.CITE = new goog.dom.TagName('CITE'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.CODE = new goog.dom.TagName('CODE'); - - -/** @type {!goog.dom.TagName<!HTMLTableColElement>} */ -goog.dom.TagName.COL = new goog.dom.TagName('COL'); - - -/** @type {!goog.dom.TagName<!HTMLTableColElement>} */ -goog.dom.TagName.COLGROUP = new goog.dom.TagName('COLGROUP'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.COMMAND = new goog.dom.TagName('COMMAND'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.DATA = new goog.dom.TagName('DATA'); - - -/** @type {!goog.dom.TagName<!HTMLDataListElement>} */ -goog.dom.TagName.DATALIST = new goog.dom.TagName('DATALIST'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.DD = new goog.dom.TagName('DD'); - - -/** @type {!goog.dom.TagName<!HTMLModElement>} */ -goog.dom.TagName.DEL = new goog.dom.TagName('DEL'); - - -/** @type {!goog.dom.TagName<!HTMLDetailsElement>} */ -goog.dom.TagName.DETAILS = new goog.dom.TagName('DETAILS'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.DFN = new goog.dom.TagName('DFN'); - - -/** @type {!goog.dom.TagName<!HTMLDialogElement>} */ -goog.dom.TagName.DIALOG = new goog.dom.TagName('DIALOG'); - - -/** @type {!goog.dom.TagName<!HTMLDirectoryElement>} */ -goog.dom.TagName.DIR = new goog.dom.TagName('DIR'); - - -/** @type {!goog.dom.TagName<!HTMLDivElement>} */ -goog.dom.TagName.DIV = new goog.dom.TagName('DIV'); - - -/** @type {!goog.dom.TagName<!HTMLDListElement>} */ -goog.dom.TagName.DL = new goog.dom.TagName('DL'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.DT = new goog.dom.TagName('DT'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.EM = new goog.dom.TagName('EM'); - - -/** @type {!goog.dom.TagName<!HTMLEmbedElement>} */ -goog.dom.TagName.EMBED = new goog.dom.TagName('EMBED'); - - -/** @type {!goog.dom.TagName<!HTMLFieldSetElement>} */ -goog.dom.TagName.FIELDSET = new goog.dom.TagName('FIELDSET'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.FIGCAPTION = new goog.dom.TagName('FIGCAPTION'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.FIGURE = new goog.dom.TagName('FIGURE'); - - -/** @type {!goog.dom.TagName<!HTMLFontElement>} */ -goog.dom.TagName.FONT = new goog.dom.TagName('FONT'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.FOOTER = new goog.dom.TagName('FOOTER'); - - -/** @type {!goog.dom.TagName<!HTMLFormElement>} */ -goog.dom.TagName.FORM = new goog.dom.TagName('FORM'); - - -/** @type {!goog.dom.TagName<!HTMLFrameElement>} */ -goog.dom.TagName.FRAME = new goog.dom.TagName('FRAME'); - - -/** @type {!goog.dom.TagName<!HTMLFrameSetElement>} */ -goog.dom.TagName.FRAMESET = new goog.dom.TagName('FRAMESET'); - - -/** @type {!goog.dom.TagName<!HTMLHeadingElement>} */ -goog.dom.TagName.H1 = new goog.dom.TagName('H1'); - - -/** @type {!goog.dom.TagName<!HTMLHeadingElement>} */ -goog.dom.TagName.H2 = new goog.dom.TagName('H2'); - - -/** @type {!goog.dom.TagName<!HTMLHeadingElement>} */ -goog.dom.TagName.H3 = new goog.dom.TagName('H3'); - - -/** @type {!goog.dom.TagName<!HTMLHeadingElement>} */ -goog.dom.TagName.H4 = new goog.dom.TagName('H4'); - - -/** @type {!goog.dom.TagName<!HTMLHeadingElement>} */ -goog.dom.TagName.H5 = new goog.dom.TagName('H5'); - - -/** @type {!goog.dom.TagName<!HTMLHeadingElement>} */ -goog.dom.TagName.H6 = new goog.dom.TagName('H6'); - - -/** @type {!goog.dom.TagName<!HTMLHeadElement>} */ -goog.dom.TagName.HEAD = new goog.dom.TagName('HEAD'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.HEADER = new goog.dom.TagName('HEADER'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.HGROUP = new goog.dom.TagName('HGROUP'); - - -/** @type {!goog.dom.TagName<!HTMLHRElement>} */ -goog.dom.TagName.HR = new goog.dom.TagName('HR'); - - -/** @type {!goog.dom.TagName<!HTMLHtmlElement>} */ -goog.dom.TagName.HTML = new goog.dom.TagName('HTML'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.I = new goog.dom.TagName('I'); - - -/** @type {!goog.dom.TagName<!HTMLIFrameElement>} */ -goog.dom.TagName.IFRAME = new goog.dom.TagName('IFRAME'); - - -/** @type {!goog.dom.TagName<!HTMLImageElement>} */ -goog.dom.TagName.IMG = new goog.dom.TagName('IMG'); - - -/** @type {!goog.dom.TagName<!HTMLInputElement>} */ -goog.dom.TagName.INPUT = new goog.dom.TagName('INPUT'); - - -/** @type {!goog.dom.TagName<!HTMLModElement>} */ -goog.dom.TagName.INS = new goog.dom.TagName('INS'); - - -/** @type {!goog.dom.TagName<!HTMLIsIndexElement>} */ -goog.dom.TagName.ISINDEX = new goog.dom.TagName('ISINDEX'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.KBD = new goog.dom.TagName('KBD'); - - -// HTMLKeygenElement is deprecated. -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.KEYGEN = new goog.dom.TagName('KEYGEN'); - - -/** @type {!goog.dom.TagName<!HTMLLabelElement>} */ -goog.dom.TagName.LABEL = new goog.dom.TagName('LABEL'); - - -/** @type {!goog.dom.TagName<!HTMLLegendElement>} */ -goog.dom.TagName.LEGEND = new goog.dom.TagName('LEGEND'); - - -/** @type {!goog.dom.TagName<!HTMLLIElement>} */ -goog.dom.TagName.LI = new goog.dom.TagName('LI'); - - -/** @type {!goog.dom.TagName<!HTMLLinkElement>} */ -goog.dom.TagName.LINK = new goog.dom.TagName('LINK'); - - -/** @type {!goog.dom.TagName<!HTMLMapElement>} */ -goog.dom.TagName.MAP = new goog.dom.TagName('MAP'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.MARK = new goog.dom.TagName('MARK'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.MATH = new goog.dom.TagName('MATH'); - - -/** @type {!goog.dom.TagName<!HTMLMenuElement>} */ -goog.dom.TagName.MENU = new goog.dom.TagName('MENU'); - - -/** @type {!goog.dom.TagName<!HTMLMetaElement>} */ -goog.dom.TagName.META = new goog.dom.TagName('META'); - - -/** @type {!goog.dom.TagName<!HTMLMeterElement>} */ -goog.dom.TagName.METER = new goog.dom.TagName('METER'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.NAV = new goog.dom.TagName('NAV'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.NOFRAMES = new goog.dom.TagName('NOFRAMES'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.NOSCRIPT = new goog.dom.TagName('NOSCRIPT'); - - -/** @type {!goog.dom.TagName<!HTMLObjectElement>} */ -goog.dom.TagName.OBJECT = new goog.dom.TagName('OBJECT'); - - -/** @type {!goog.dom.TagName<!HTMLOListElement>} */ -goog.dom.TagName.OL = new goog.dom.TagName('OL'); - - -/** @type {!goog.dom.TagName<!HTMLOptGroupElement>} */ -goog.dom.TagName.OPTGROUP = new goog.dom.TagName('OPTGROUP'); - - -/** @type {!goog.dom.TagName<!HTMLOptionElement>} */ -goog.dom.TagName.OPTION = new goog.dom.TagName('OPTION'); - - -/** @type {!goog.dom.TagName<!HTMLOutputElement>} */ -goog.dom.TagName.OUTPUT = new goog.dom.TagName('OUTPUT'); - - -/** @type {!goog.dom.TagName<!HTMLParagraphElement>} */ -goog.dom.TagName.P = new goog.dom.TagName('P'); - - -/** @type {!goog.dom.TagName<!HTMLParamElement>} */ -goog.dom.TagName.PARAM = new goog.dom.TagName('PARAM'); - - -/** @type {!goog.dom.TagName<!HTMLPreElement>} */ -goog.dom.TagName.PRE = new goog.dom.TagName('PRE'); - - -/** @type {!goog.dom.TagName<!HTMLProgressElement>} */ -goog.dom.TagName.PROGRESS = new goog.dom.TagName('PROGRESS'); - - -/** @type {!goog.dom.TagName<!HTMLQuoteElement>} */ -goog.dom.TagName.Q = new goog.dom.TagName('Q'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.RP = new goog.dom.TagName('RP'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.RT = new goog.dom.TagName('RT'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.RUBY = new goog.dom.TagName('RUBY'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.S = new goog.dom.TagName('S'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.SAMP = new goog.dom.TagName('SAMP'); - - -/** @type {!goog.dom.TagName<!HTMLScriptElement>} */ -goog.dom.TagName.SCRIPT = new goog.dom.TagName('SCRIPT'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.SECTION = new goog.dom.TagName('SECTION'); - - -/** @type {!goog.dom.TagName<!HTMLSelectElement>} */ -goog.dom.TagName.SELECT = new goog.dom.TagName('SELECT'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.SMALL = new goog.dom.TagName('SMALL'); - - -/** @type {!goog.dom.TagName<!HTMLSourceElement>} */ -goog.dom.TagName.SOURCE = new goog.dom.TagName('SOURCE'); - - -/** @type {!goog.dom.TagName<!HTMLSpanElement>} */ -goog.dom.TagName.SPAN = new goog.dom.TagName('SPAN'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.STRIKE = new goog.dom.TagName('STRIKE'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.STRONG = new goog.dom.TagName('STRONG'); - - -/** @type {!goog.dom.TagName<!HTMLStyleElement>} */ -goog.dom.TagName.STYLE = new goog.dom.TagName('STYLE'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.SUB = new goog.dom.TagName('SUB'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.SUMMARY = new goog.dom.TagName('SUMMARY'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.SUP = new goog.dom.TagName('SUP'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.SVG = new goog.dom.TagName('SVG'); - - -/** @type {!goog.dom.TagName<!HTMLTableElement>} */ -goog.dom.TagName.TABLE = new goog.dom.TagName('TABLE'); - - -/** @type {!goog.dom.TagName<!HTMLTableSectionElement>} */ -goog.dom.TagName.TBODY = new goog.dom.TagName('TBODY'); - - -/** @type {!goog.dom.TagName<!HTMLTableCellElement>} */ -goog.dom.TagName.TD = new goog.dom.TagName('TD'); - - -/** @type {!goog.dom.TagName<!HTMLTemplateElement>} */ -goog.dom.TagName.TEMPLATE = new goog.dom.TagName('TEMPLATE'); - - -/** @type {!goog.dom.TagName<!HTMLTextAreaElement>} */ -goog.dom.TagName.TEXTAREA = new goog.dom.TagName('TEXTAREA'); - - -/** @type {!goog.dom.TagName<!HTMLTableSectionElement>} */ -goog.dom.TagName.TFOOT = new goog.dom.TagName('TFOOT'); - - -/** @type {!goog.dom.TagName<!HTMLTableCellElement>} */ -goog.dom.TagName.TH = new goog.dom.TagName('TH'); - - -/** @type {!goog.dom.TagName<!HTMLTableSectionElement>} */ -goog.dom.TagName.THEAD = new goog.dom.TagName('THEAD'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.TIME = new goog.dom.TagName('TIME'); - - -/** @type {!goog.dom.TagName<!HTMLTitleElement>} */ -goog.dom.TagName.TITLE = new goog.dom.TagName('TITLE'); - - -/** @type {!goog.dom.TagName<!HTMLTableRowElement>} */ -goog.dom.TagName.TR = new goog.dom.TagName('TR'); - - -/** @type {!goog.dom.TagName<!HTMLTrackElement>} */ -goog.dom.TagName.TRACK = new goog.dom.TagName('TRACK'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.TT = new goog.dom.TagName('TT'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.U = new goog.dom.TagName('U'); - - -/** @type {!goog.dom.TagName<!HTMLUListElement>} */ -goog.dom.TagName.UL = new goog.dom.TagName('UL'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.VAR = new goog.dom.TagName('VAR'); - - -/** @type {!goog.dom.TagName<!HTMLVideoElement>} */ -goog.dom.TagName.VIDEO = new goog.dom.TagName('VIDEO'); - - -/** @type {!goog.dom.TagName<!goog.dom.HtmlElement>} */ -goog.dom.TagName.WBR = new goog.dom.TagName('WBR');
diff --git a/third_party/ink/closure/dom/tags.js b/third_party/ink/closure/dom/tags.js deleted file mode 100644 index 7c12938..0000000 --- a/third_party/ink/closure/dom/tags.js +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for HTML element tag names. - */ -goog.provide('goog.dom.tags'); - -goog.require('goog.object'); - - -/** - * The void elements specified by - * http://www.w3.org/TR/html-markup/syntax.html#void-elements. - * @const @private {!Object<string, boolean>} - */ -goog.dom.tags.VOID_TAGS_ = goog.object.createSet( - 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', - 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'); - - -/** - * Checks whether the tag is void (with no contents allowed and no legal end - * tag), for example 'br'. - * @param {string} tagName The tag name in lower case. - * @return {boolean} - */ -goog.dom.tags.isVoidTag = function(tagName) { - return goog.dom.tags.VOID_TAGS_[tagName] === true; -};
diff --git a/third_party/ink/closure/dom/vendor.js b/third_party/ink/closure/dom/vendor.js deleted file mode 100644 index 28b173d..0000000 --- a/third_party/ink/closure/dom/vendor.js +++ /dev/null
@@ -1,97 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Vendor prefix getters. - */ - -goog.provide('goog.dom.vendor'); - -goog.require('goog.string'); -goog.require('goog.userAgent'); - - -/** - * Returns the JS vendor prefix used in CSS properties. Different vendors - * use different methods of changing the case of the property names. - * - * @return {?string} The JS vendor prefix or null if there is none. - */ -goog.dom.vendor.getVendorJsPrefix = function() { - if (goog.userAgent.WEBKIT) { - return 'Webkit'; - } else if (goog.userAgent.GECKO) { - return 'Moz'; - } else if (goog.userAgent.IE) { - return 'ms'; - } else if (goog.userAgent.OPERA) { - return 'O'; - } - - return null; -}; - - -/** - * Returns the vendor prefix used in CSS properties. - * - * @return {?string} The vendor prefix or null if there is none. - */ -goog.dom.vendor.getVendorPrefix = function() { - if (goog.userAgent.WEBKIT) { - return '-webkit'; - } else if (goog.userAgent.GECKO) { - return '-moz'; - } else if (goog.userAgent.IE) { - return '-ms'; - } else if (goog.userAgent.OPERA) { - return '-o'; - } - - return null; -}; - - -/** - * @param {string} propertyName A property name. - * @param {!Object=} opt_object If provided, we verify if the property exists in - * the object. - * @return {?string} A vendor prefixed property name, or null if it does not - * exist. - */ -goog.dom.vendor.getPrefixedPropertyName = function(propertyName, opt_object) { - // We first check for a non-prefixed property, if available. - if (opt_object && propertyName in opt_object) { - return propertyName; - } - var prefix = goog.dom.vendor.getVendorJsPrefix(); - if (prefix) { - prefix = prefix.toLowerCase(); - var prefixedPropertyName = prefix + goog.string.toTitleCase(propertyName); - return (!goog.isDef(opt_object) || prefixedPropertyName in opt_object) ? - prefixedPropertyName : - null; - } - return null; -}; - - -/** - * @param {string} eventType An event type. - * @return {string} A lower-cased vendor prefixed event type. - */ -goog.dom.vendor.getPrefixedEventType = function(eventType) { - var prefix = goog.dom.vendor.getVendorJsPrefix() || ''; - return (prefix + eventType).toLowerCase(); -};
diff --git a/third_party/ink/closure/events/browserevent.js b/third_party/ink/closure/events/browserevent.js deleted file mode 100644 index 3c557ca..0000000 --- a/third_party/ink/closure/events/browserevent.js +++ /dev/null
@@ -1,470 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A patched, standardized event object for browser events. - * - * <pre> - * The patched event object contains the following members: - * - type {string} Event type, e.g. 'click' - * - target {Object} The element that actually triggered the event - * - currentTarget {Object} The element the listener is attached to - * - relatedTarget {Object} For mouseover and mouseout, the previous object - * - offsetX {number} X-coordinate relative to target - * - offsetY {number} Y-coordinate relative to target - * - clientX {number} X-coordinate relative to viewport - * - clientY {number} Y-coordinate relative to viewport - * - screenX {number} X-coordinate relative to the edge of the screen - * - screenY {number} Y-coordinate relative to the edge of the screen - * - button {number} Mouse button. Use isButton() to test. - * - keyCode {number} Key-code - * - ctrlKey {boolean} Was ctrl key depressed - * - altKey {boolean} Was alt key depressed - * - shiftKey {boolean} Was shift key depressed - * - metaKey {boolean} Was meta key depressed - * - pointerId {number} Pointer ID - * - pointerType {string} Pointer type, e.g. 'mouse', 'pen', or 'touch' - * - defaultPrevented {boolean} Whether the default action has been prevented - * - state {Object} History state object - * - * NOTE: The keyCode member contains the raw browser keyCode. For normalized - * key and character code use {@link goog.events.KeyHandler}. - * </pre> - * - * @author pupius@google.com (Daniel Pupius) - * @author arv@google.com (Erik Arvidsson) - */ - -goog.provide('goog.events.BrowserEvent'); -goog.provide('goog.events.BrowserEvent.MouseButton'); -goog.provide('goog.events.BrowserEvent.PointerType'); - -goog.require('goog.debug'); -goog.require('goog.events.BrowserFeature'); -goog.require('goog.events.Event'); -goog.require('goog.events.EventType'); -goog.require('goog.reflect'); -goog.require('goog.userAgent'); - - - -/** - * Accepts a browser event object and creates a patched, cross browser event - * object. - * The content of this object will not be initialized if no event object is - * provided. If this is the case, init() needs to be invoked separately. - * @param {Event=} opt_e Browser event object. - * @param {EventTarget=} opt_currentTarget Current target for event. - * @constructor - * @extends {goog.events.Event} - */ -goog.events.BrowserEvent = function(opt_e, opt_currentTarget) { - goog.events.BrowserEvent.base(this, 'constructor', opt_e ? opt_e.type : ''); - - /** - * Target that fired the event. - * @override - * @type {Node} - */ - this.target = null; - - /** - * Node that had the listener attached. - * @override - * @type {Node|undefined} - */ - this.currentTarget = null; - - /** - * For mouseover and mouseout events, the related object for the event. - * @type {Node} - */ - this.relatedTarget = null; - - /** - * X-coordinate relative to target. - * @type {number} - */ - this.offsetX = 0; - - /** - * Y-coordinate relative to target. - * @type {number} - */ - this.offsetY = 0; - - /** - * X-coordinate relative to the window. - * @type {number} - */ - this.clientX = 0; - - /** - * Y-coordinate relative to the window. - * @type {number} - */ - this.clientY = 0; - - /** - * X-coordinate relative to the monitor. - * @type {number} - */ - this.screenX = 0; - - /** - * Y-coordinate relative to the monitor. - * @type {number} - */ - this.screenY = 0; - - /** - * Which mouse button was pressed. - * @type {number} - */ - this.button = 0; - - /** - * Key of key press. - * @type {string} - */ - this.key = ''; - - /** - * Keycode of key press. - * @type {number} - */ - this.keyCode = 0; - - /** - * Keycode of key press. - * @type {number} - */ - this.charCode = 0; - - /** - * Whether control was pressed at time of event. - * @type {boolean} - */ - this.ctrlKey = false; - - /** - * Whether alt was pressed at time of event. - * @type {boolean} - */ - this.altKey = false; - - /** - * Whether shift was pressed at time of event. - * @type {boolean} - */ - this.shiftKey = false; - - /** - * Whether the meta key was pressed at time of event. - * @type {boolean} - */ - this.metaKey = false; - - /** - * History state object, only set for PopState events where it's a copy of the - * state object provided to pushState or replaceState. - * @type {Object} - */ - this.state = null; - - /** - * Whether the default platform modifier key was pressed at time of event. - * (This is control for all platforms except Mac, where it's Meta.) - * @type {boolean} - */ - this.platformModifierKey = false; - - /** - * @type {number} - */ - this.pointerId = 0; - - /** - * @type {string} - */ - this.pointerType = ''; - - /** - * The browser event object. - * @private {Event} - */ - this.event_ = null; - - if (opt_e) { - this.init(opt_e, opt_currentTarget); - } -}; -goog.inherits(goog.events.BrowserEvent, goog.events.Event); - - -/** - * Normalized button constants for the mouse. - * @enum {number} - */ -goog.events.BrowserEvent.MouseButton = { - LEFT: 0, - MIDDLE: 1, - RIGHT: 2 -}; - - -/** - * Normalized pointer type constants for pointer events. - * @enum {string} - */ -goog.events.BrowserEvent.PointerType = { - MOUSE: 'mouse', - PEN: 'pen', - TOUCH: 'touch' -}; - - -/** - * Static data for mapping mouse buttons. - * @type {!Array<number>} - * @deprecated Use {@code goog.events.BrowserEvent.IE_BUTTON_MAP} instead. - */ -goog.events.BrowserEvent.IEButtonMap = goog.debug.freeze([ - 1, // LEFT - 4, // MIDDLE - 2 // RIGHT -]); - - -/** - * Static data for mapping mouse buttons. - * @const {!Array<number>} - */ -goog.events.BrowserEvent.IE_BUTTON_MAP = goog.events.BrowserEvent.IEButtonMap; - - -/** - * Static data for mapping MSPointerEvent types to PointerEvent types. - * @const {!Object<number, goog.events.BrowserEvent.PointerType>} - */ -goog.events.BrowserEvent.IE_POINTER_TYPE_MAP = goog.debug.freeze({ - 2: goog.events.BrowserEvent.PointerType.TOUCH, - 3: goog.events.BrowserEvent.PointerType.PEN, - 4: goog.events.BrowserEvent.PointerType.MOUSE -}); - - -/** - * Accepts a browser event object and creates a patched, cross browser event - * object. - * @param {Event} e Browser event object. - * @param {EventTarget=} opt_currentTarget Current target for event. - */ -goog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) { - var type = this.type = e.type; - - /** - * On touch devices use the first "changed touch" as the relevant touch. - * @type {Touch} - */ - var relevantTouch = e.changedTouches ? e.changedTouches[0] : null; - - // TODO(nicksantos): Change this.target to type EventTarget. - this.target = /** @type {Node} */ (e.target) || e.srcElement; - - // TODO(nicksantos): Change this.currentTarget to type EventTarget. - this.currentTarget = /** @type {Node} */ (opt_currentTarget); - - var relatedTarget = /** @type {Node} */ (e.relatedTarget); - if (relatedTarget) { - // There's a bug in FireFox where sometimes, relatedTarget will be a - // chrome element, and accessing any property of it will get a permission - // denied exception. See: - // https://bugzilla.mozilla.org/show_bug.cgi?id=497780 - if (goog.userAgent.GECKO) { - if (!goog.reflect.canAccessProperty(relatedTarget, 'nodeName')) { - relatedTarget = null; - } - } - } else if (type == goog.events.EventType.MOUSEOVER) { - relatedTarget = e.fromElement; - } else if (type == goog.events.EventType.MOUSEOUT) { - relatedTarget = e.toElement; - } - - this.relatedTarget = relatedTarget; - - if (!goog.isNull(relevantTouch)) { - this.clientX = relevantTouch.clientX !== undefined ? relevantTouch.clientX : - relevantTouch.pageX; - this.clientY = relevantTouch.clientY !== undefined ? relevantTouch.clientY : - relevantTouch.pageY; - this.screenX = relevantTouch.screenX || 0; - this.screenY = relevantTouch.screenY || 0; - } else { - // Webkit emits a lame warning whenever layerX/layerY is accessed. - // http://code.google.com/p/chromium/issues/detail?id=101733 - this.offsetX = (goog.userAgent.WEBKIT || e.offsetX !== undefined) ? - e.offsetX : - e.layerX; - this.offsetY = (goog.userAgent.WEBKIT || e.offsetY !== undefined) ? - e.offsetY : - e.layerY; - this.clientX = e.clientX !== undefined ? e.clientX : e.pageX; - this.clientY = e.clientY !== undefined ? e.clientY : e.pageY; - this.screenX = e.screenX || 0; - this.screenY = e.screenY || 0; - } - - this.button = e.button; - - this.keyCode = e.keyCode || 0; - this.key = e.key || ''; - this.charCode = e.charCode || (type == 'keypress' ? e.keyCode : 0); - this.ctrlKey = e.ctrlKey; - this.altKey = e.altKey; - this.shiftKey = e.shiftKey; - this.metaKey = e.metaKey; - this.platformModifierKey = goog.userAgent.MAC ? e.metaKey : e.ctrlKey; - this.pointerId = e.pointerId || 0; - this.pointerType = goog.events.BrowserEvent.getPointerType_(e); - this.state = e.state; - this.event_ = e; - if (e.defaultPrevented) { - this.preventDefault(); - } -}; - - -/** - * Tests to see which button was pressed during the event. This is really only - * useful in IE and Gecko browsers. And in IE, it's only useful for - * mousedown/mouseup events, because click only fires for the left mouse button. - * - * Safari 2 only reports the left button being clicked, and uses the value '1' - * instead of 0. Opera only reports a mousedown event for the middle button, and - * no mouse events for the right button. Opera has default behavior for left and - * middle click that can only be overridden via a configuration setting. - * - * There's a nice table of this mess at http://www.unixpapa.com/js/mouse.html. - * - * @param {goog.events.BrowserEvent.MouseButton} button The button - * to test for. - * @return {boolean} True if button was pressed. - */ -goog.events.BrowserEvent.prototype.isButton = function(button) { - if (!goog.events.BrowserFeature.HAS_W3C_BUTTON) { - if (this.type == 'click') { - return button == goog.events.BrowserEvent.MouseButton.LEFT; - } else { - return !!( - this.event_.button & goog.events.BrowserEvent.IE_BUTTON_MAP[button]); - } - } else { - return this.event_.button == button; - } -}; - - -/** - * Whether this has an "action"-producing mouse button. - * - * By definition, this includes left-click on windows/linux, and left-click - * without the ctrl key on Macs. - * - * @return {boolean} The result. - */ -goog.events.BrowserEvent.prototype.isMouseActionButton = function() { - // Webkit does not ctrl+click to be a right-click, so we - // normalize it to behave like Gecko and Opera. - return this.isButton(goog.events.BrowserEvent.MouseButton.LEFT) && - !(goog.userAgent.WEBKIT && goog.userAgent.MAC && this.ctrlKey); -}; - - -/** - * @override - */ -goog.events.BrowserEvent.prototype.stopPropagation = function() { - goog.events.BrowserEvent.superClass_.stopPropagation.call(this); - if (this.event_.stopPropagation) { - this.event_.stopPropagation(); - } else { - this.event_.cancelBubble = true; - } -}; - - -/** - * @override - */ -goog.events.BrowserEvent.prototype.preventDefault = function() { - goog.events.BrowserEvent.superClass_.preventDefault.call(this); - var be = this.event_; - if (!be.preventDefault) { - be.returnValue = false; - if (goog.events.BrowserFeature.SET_KEY_CODE_TO_PREVENT_DEFAULT) { - - try { - // Most keys can be prevented using returnValue. Some special keys - // require setting the keyCode to -1 as well: - // - // In IE7: - // F3, F5, F10, F11, Ctrl+P, Crtl+O, Ctrl+F (these are taken from IE6) - // - // In IE8: - // Ctrl+P, Crtl+O, Ctrl+F (F1-F12 cannot be stopped through the event) - // - // We therefore do this for all function keys as well as when Ctrl key - // is pressed. - var VK_F1 = 112; - var VK_F12 = 123; - if (be.ctrlKey || be.keyCode >= VK_F1 && be.keyCode <= VK_F12) { - be.keyCode = -1; - } - } catch (ex) { - // IE throws an 'access denied' exception when trying to change - // keyCode in some situations (e.g. srcElement is input[type=file], - // or srcElement is an anchor tag rewritten by parent's innerHTML). - // Do nothing in this case. - } - } - } else { - be.preventDefault(); - } -}; - - -/** - * @return {Event} The underlying browser event object. - */ -goog.events.BrowserEvent.prototype.getBrowserEvent = function() { - return this.event_; -}; - - -/** - * Extracts the pointer type from the given event. - * @param {!Event} e - * @return {string} The pointer type, e.g. 'mouse', 'pen', or 'touch'. - * @private - */ -goog.events.BrowserEvent.getPointerType_ = function(e) { - if (goog.isString(e.pointerType)) { - return e.pointerType; - } - // IE10 uses integer codes for pointer type. - // https://msdn.microsoft.com/en-us/library/hh772359(v=vs.85).aspx - return goog.events.BrowserEvent.IE_POINTER_TYPE_MAP[e.pointerType] || ''; -};
diff --git a/third_party/ink/closure/events/browserfeature.js b/third_party/ink/closure/events/browserfeature.js deleted file mode 100644 index 10ef20d..0000000 --- a/third_party/ink/closure/events/browserfeature.js +++ /dev/null
@@ -1,140 +0,0 @@ -// Copyright 2010 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Browser capability checks for the events package. - * - * @author zhyder@google.com (Zohair Hyder) - */ - - -goog.provide('goog.events.BrowserFeature'); - -goog.require('goog.userAgent'); -goog.scope(function() { - - - -/** - * Enum of browser capabilities. - * @enum {boolean} - */ -goog.events.BrowserFeature = { - /** - * Whether the button attribute of the event is W3C compliant. False in - * Internet Explorer prior to version 9; document-version dependent. - */ - HAS_W3C_BUTTON: - !goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9), - - /** - * Whether the browser supports full W3C event model. - */ - HAS_W3C_EVENT_SUPPORT: - !goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9), - - /** - * To prevent default in IE7-8 for certain keydown events we need set the - * keyCode to -1. - */ - SET_KEY_CODE_TO_PREVENT_DEFAULT: - goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9'), - - /** - * Whether the {@code navigator.onLine} property is supported. - */ - HAS_NAVIGATOR_ONLINE_PROPERTY: - !goog.userAgent.WEBKIT || goog.userAgent.isVersionOrHigher('528'), - - /** - * Whether HTML5 network online/offline events are supported. - */ - HAS_HTML5_NETWORK_EVENT_SUPPORT: - goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9b') || - goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8') || - goog.userAgent.OPERA && goog.userAgent.isVersionOrHigher('9.5') || - goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('528'), - - /** - * Whether HTML5 network events fire on document.body, or otherwise the - * window. - */ - HTML5_NETWORK_EVENTS_FIRE_ON_BODY: - goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('8') || - goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9'), - - /** - * Whether touch is enabled in the browser. - */ - TOUCH_ENABLED: - ('ontouchstart' in goog.global || - !!(goog.global['document'] && document.documentElement && - 'ontouchstart' in document.documentElement) || - // IE10 uses non-standard touch events, so it has a different check. - !!(goog.global['navigator'] && - (goog.global['navigator']['maxTouchPoints'] || - goog.global['navigator']['msMaxTouchPoints']))), - - /** - * Whether addEventListener supports W3C standard pointer events. - * http://www.w3.org/TR/pointerevents/ - */ - POINTER_EVENTS: ('PointerEvent' in goog.global), - - /** - * Whether addEventListener supports MSPointer events (only used in IE10). - * http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx - * http://msdn.microsoft.com/library/hh673557(v=vs.85).aspx - */ - MSPOINTER_EVENTS: - ('MSPointerEvent' in goog.global && - !!(goog.global['navigator'] && - goog.global['navigator']['msPointerEnabled'])), - - /** - * Whether addEventListener supports {passive: true}. - * https://developers.google.com/web/updates/2016/06/passive-event-listeners - */ - PASSIVE_EVENTS: purify(function() { - // If we're in a web worker or other custom environment, we can't tell. - if (!goog.global.addEventListener || !Object.defineProperty) { // IE 8 - return false; - } - - var passive = false; - var options = Object.defineProperty({}, 'passive', { - get: function() { - passive = true; - } - }); - goog.global.addEventListener('test', goog.nullFunction, options); - goog.global.removeEventListener('test', goog.nullFunction, options); - - return passive; - }) -}; - - -/** - * Tricks Closure Compiler into believing that a function is pure. The compiler - * assumes that any `valueOf` function is pure, without analyzing its contents. - * - * @param {function(): T} fn - * @return {T} - * @template T - */ -function purify(fn) { - return ({valueOf: fn}).valueOf(); -} -}); // goog.scope
diff --git a/third_party/ink/closure/events/event.js b/third_party/ink/closure/events/event.js deleted file mode 100644 index 22efba9..0000000 --- a/third_party/ink/closure/events/event.js +++ /dev/null
@@ -1,144 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A base class for event objects. - * - * @author pupius@google.com (Daniel Pupius) - */ - - -goog.provide('goog.events.Event'); -goog.provide('goog.events.EventLike'); - -/** - * goog.events.Event no longer depends on goog.Disposable. Keep requiring - * goog.Disposable here to not break projects which assume this dependency. - * @suppress {extraRequire} - */ -goog.require('goog.Disposable'); -goog.require('goog.events.EventId'); - - -/** - * A typedef for event like objects that are dispatchable via the - * goog.events.dispatchEvent function. strings are treated as the type for a - * goog.events.Event. Objects are treated as an extension of a new - * goog.events.Event with the type property of the object being used as the type - * of the Event. - * @typedef {string|Object|goog.events.Event|goog.events.EventId} - */ -goog.events.EventLike; - - - -/** - * A base class for event objects, so that they can support preventDefault and - * stopPropagation. - * - * @suppress {underscore} Several properties on this class are technically - * public, but referencing these properties outside this package is strongly - * discouraged. - * - * @param {string|!goog.events.EventId} type Event Type. - * @param {Object=} opt_target Reference to the object that is the target of - * this event. It has to implement the {@code EventTarget} interface - * declared at {@link http://developer.mozilla.org/en/DOM/EventTarget}. - * @constructor - */ -goog.events.Event = function(type, opt_target) { - /** - * Event type. - * @type {string} - */ - this.type = type instanceof goog.events.EventId ? String(type) : type; - - /** - * TODO(tbreisacher): The type should probably be - * EventTarget|goog.events.EventTarget. - * - * Target of the event. - * @type {Object|undefined} - */ - this.target = opt_target; - - /** - * Object that had the listener attached. - * @type {Object|undefined} - */ - this.currentTarget = this.target; - - /** - * Whether to cancel the event in internal capture/bubble processing for IE. - * @type {boolean} - * @public - */ - this.propagationStopped_ = false; - - /** - * Whether the default action has been prevented. - * This is a property to match the W3C specification at - * {@link http://www.w3.org/TR/DOM-Level-3-Events/ - * #events-event-type-defaultPrevented}. - * Must be treated as read-only outside the class. - * @type {boolean} - */ - this.defaultPrevented = false; - - /** - * Return value for in internal capture/bubble processing for IE. - * @type {boolean} - * @public - */ - this.returnValue_ = true; -}; - - -/** - * Stops event propagation. - */ -goog.events.Event.prototype.stopPropagation = function() { - this.propagationStopped_ = true; -}; - - -/** - * Prevents the default action, for example a link redirecting to a url. - */ -goog.events.Event.prototype.preventDefault = function() { - this.defaultPrevented = true; - this.returnValue_ = false; -}; - - -/** - * Stops the propagation of the event. It is equivalent to - * {@code e.stopPropagation()}, but can be used as the callback argument of - * {@link goog.events.listen} without declaring another function. - * @param {!goog.events.Event} e An event. - */ -goog.events.Event.stopPropagation = function(e) { - e.stopPropagation(); -}; - - -/** - * Prevents the default action. It is equivalent to - * {@code e.preventDefault()}, but can be used as the callback argument of - * {@link goog.events.listen} without declaring another function. - * @param {!goog.events.Event} e An event. - */ -goog.events.Event.preventDefault = function(e) { - e.preventDefault(); -};
diff --git a/third_party/ink/closure/events/eventhandler.js b/third_party/ink/closure/events/eventhandler.js deleted file mode 100644 index 6a887f9..0000000 --- a/third_party/ink/closure/events/eventhandler.js +++ /dev/null
@@ -1,479 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Class to create objects which want to handle multiple events - * and have their listeners easily cleaned up via a dispose method. - * - * Example: - * <pre> - * function Something() { - * Something.base(this); - * - * ... set up object ... - * - * // Add event listeners - * this.listen(this.starEl, goog.events.EventType.CLICK, this.handleStar); - * this.listen(this.headerEl, goog.events.EventType.CLICK, this.expand); - * this.listen(this.collapseEl, goog.events.EventType.CLICK, this.collapse); - * this.listen(this.infoEl, goog.events.EventType.MOUSEOVER, this.showHover); - * this.listen(this.infoEl, goog.events.EventType.MOUSEOUT, this.hideHover); - * } - * goog.inherits(Something, goog.events.EventHandler); - * - * Something.prototype.disposeInternal = function() { - * Something.base(this, 'disposeInternal'); - * goog.dom.removeNode(this.container); - * }; - * - * - * // Then elsewhere: - * - * var activeSomething = null; - * function openSomething() { - * activeSomething = new Something(); - * } - * - * function closeSomething() { - * if (activeSomething) { - * activeSomething.dispose(); // Remove event listeners - * activeSomething = null; - * } - * } - * </pre> - * - * @author pupius@google.com (Daniel Pupius) - */ - -goog.provide('goog.events.EventHandler'); - -goog.require('goog.Disposable'); -goog.require('goog.events'); -goog.require('goog.object'); - -goog.forwardDeclare('goog.events.EventWrapper'); - - - -/** - * Super class for objects that want to easily manage a number of event - * listeners. It allows a short cut to listen and also provides a quick way - * to remove all events listeners belonging to this object. - * @param {SCOPE=} opt_scope Object in whose scope to call the listeners. - * @constructor - * @extends {goog.Disposable} - * @template SCOPE - */ -goog.events.EventHandler = function(opt_scope) { - goog.Disposable.call(this); - // TODO(mknichel): Rename this to this.scope_ and fix the classes in google3 - // that access this private variable. :( - this.handler_ = opt_scope; - - /** - * Keys for events that are being listened to. - * @type {!Object<!goog.events.Key>} - * @private - */ - this.keys_ = {}; -}; -goog.inherits(goog.events.EventHandler, goog.Disposable); - - -/** - * Utility array used to unify the cases of listening for an array of types - * and listening for a single event, without using recursion or allocating - * an array each time. - * @type {!Array<string>} - * @const - * @private - */ -goog.events.EventHandler.typeArray_ = []; - - -/** - * Listen to an event on a Listenable. If the function is omitted then the - * EventHandler's handleEvent method will be used. - * @param {goog.events.ListenableType} src Event source. - * @param {string|Array<string>| - * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>} - * type Event type to listen for or array of event types. - * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=} - * opt_fn Optional callback function to be used as the listener or an object - * with handleEvent function. - * @param {(boolean|!AddEventListenerOptions)=} opt_options - * @return {THIS} This object, allowing for chaining of calls. - * @this {THIS} - * @template EVENTOBJ, THIS - */ -goog.events.EventHandler.prototype.listen = function( - src, type, opt_fn, opt_options) { - var self = /** @type {!goog.events.EventHandler} */ (this); - return self.listen_(src, type, opt_fn, opt_options); -}; - - -/** - * Listen to an event on a Listenable. If the function is omitted then the - * EventHandler's handleEvent method will be used. - * @param {goog.events.ListenableType} src Event source. - * @param {string|Array<string>| - * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>} - * type Event type to listen for or array of event types. - * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}| - * null|undefined} fn Optional callback function to be used as the - * listener or an object with handleEvent function. - * @param {boolean|!AddEventListenerOptions|undefined} options - * @param {T} scope Object in whose scope to call the listener. - * @return {THIS} This object, allowing for chaining of calls. - * @this {THIS} - * @template T, EVENTOBJ, THIS - */ -goog.events.EventHandler.prototype.listenWithScope = function( - src, type, fn, options, scope) { - var self = /** @type {!goog.events.EventHandler} */ (this); - // TODO(mknichel): Deprecate this function. - return self.listen_(src, type, fn, options, scope); -}; - - -/** - * Listen to an event on a Listenable. If the function is omitted then the - * EventHandler's handleEvent method will be used. - * @param {goog.events.ListenableType} src Event source. - * @param {string|Array<string>| - * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>} - * type Event type to listen for or array of event types. - * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn - * Optional callback function to be used as the listener or an object with - * handleEvent function. - * @param {(boolean|!AddEventListenerOptions)=} opt_options - * @param {Object=} opt_scope Object in whose scope to call the listener. - * @return {THIS} This object, allowing for chaining of calls. - * @this {THIS} - * @template EVENTOBJ, THIS - * @private - */ -goog.events.EventHandler.prototype.listen_ = function( - src, type, opt_fn, opt_options, opt_scope) { - var self = /** @type {!goog.events.EventHandler} */ (this); - if (!goog.isArray(type)) { - if (type) { - goog.events.EventHandler.typeArray_[0] = type.toString(); - } - type = goog.events.EventHandler.typeArray_; - } - for (var i = 0; i < type.length; i++) { - var listenerObj = goog.events.listen( - src, type[i], opt_fn || self.handleEvent, opt_options || false, - opt_scope || self.handler_ || self); - - if (!listenerObj) { - // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT - // (goog.events.CaptureSimulationMode) in IE8-, it will return null - // value. - return self; - } - - var key = listenerObj.key; - self.keys_[key] = listenerObj; - } - - return self; -}; - - -/** - * Listen to an event on a Listenable. If the function is omitted, then the - * EventHandler's handleEvent method will be used. After the event has fired the - * event listener is removed from the target. If an array of event types is - * provided, each event type will be listened to once. - * @param {goog.events.ListenableType} src Event source. - * @param {string|Array<string>| - * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>} - * type Event type to listen for or array of event types. - * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=} - * opt_fn - * Optional callback function to be used as the listener or an object with - * handleEvent function. - * @param {(boolean|!AddEventListenerOptions)=} opt_options - * @return {THIS} This object, allowing for chaining of calls. - * @this {THIS} - * @template EVENTOBJ, THIS - */ -goog.events.EventHandler.prototype.listenOnce = function( - src, type, opt_fn, opt_options) { - var self = /** @type {!goog.events.EventHandler} */ (this); - return self.listenOnce_(src, type, opt_fn, opt_options); -}; - - -/** - * Listen to an event on a Listenable. If the function is omitted, then the - * EventHandler's handleEvent method will be used. After the event has fired the - * event listener is removed from the target. If an array of event types is - * provided, each event type will be listened to once. - * @param {goog.events.ListenableType} src Event source. - * @param {string|Array<string>| - * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>} - * type Event type to listen for or array of event types. - * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}| - * null|undefined} fn Optional callback function to be used as the - * listener or an object with handleEvent function. - * @param {boolean|undefined} capture Optional whether to use capture phase. - * @param {T} scope Object in whose scope to call the listener. - * @return {THIS} This object, allowing for chaining of calls. - * @this {THIS} - * @template T, EVENTOBJ, THIS - */ -goog.events.EventHandler.prototype.listenOnceWithScope = function( - src, type, fn, capture, scope) { - var self = /** @type {!goog.events.EventHandler} */ (this); - // TODO(mknichel): Deprecate this function. - return self.listenOnce_(src, type, fn, capture, scope); -}; - - -/** - * Listen to an event on a Listenable. If the function is omitted, then the - * EventHandler's handleEvent method will be used. After the event has fired - * the event listener is removed from the target. If an array of event types is - * provided, each event type will be listened to once. - * @param {goog.events.ListenableType} src Event source. - * @param {string|Array<string>| - * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>} - * type Event type to listen for or array of event types. - * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn - * Optional callback function to be used as the listener or an object with - * handleEvent function. - * @param {(boolean|!AddEventListenerOptions)=} opt_options - * @param {Object=} opt_scope Object in whose scope to call the listener. - * @return {THIS} This object, allowing for chaining of calls. - * @this {THIS} - * @template EVENTOBJ, THIS - * @private - */ -goog.events.EventHandler.prototype.listenOnce_ = function( - src, type, opt_fn, opt_options, opt_scope) { - var self = /** @type {!goog.events.EventHandler} */ (this); - if (goog.isArray(type)) { - for (var i = 0; i < type.length; i++) { - self.listenOnce_(src, type[i], opt_fn, opt_options, opt_scope); - } - } else { - var listenerObj = goog.events.listenOnce( - src, type, opt_fn || self.handleEvent, opt_options, - opt_scope || self.handler_ || self); - if (!listenerObj) { - // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT - // (goog.events.CaptureSimulationMode) in IE8-, it will return null - // value. - return self; - } - - var key = listenerObj.key; - self.keys_[key] = listenerObj; - } - - return self; -}; - - -/** - * Adds an event listener with a specific event wrapper on a DOM Node or an - * object that has implemented {@link goog.events.EventTarget}. A listener can - * only be added once to an object. - * - * @param {EventTarget|goog.events.EventTarget} src The node to listen to - * events on. - * @param {goog.events.EventWrapper} wrapper Event wrapper to use. - * @param {function(this:SCOPE, ?):?|{handleEvent:function(?):?}|null} listener - * Callback method, or an object with a handleEvent function. - * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to - * false). - * @return {THIS} This object, allowing for chaining of calls. - * @this {THIS} - * @template THIS - */ -goog.events.EventHandler.prototype.listenWithWrapper = function( - src, wrapper, listener, opt_capt) { - var self = /** @type {!goog.events.EventHandler} */ (this); - // TODO(mknichel): Remove the opt_scope from this function and then - // templatize it. - return self.listenWithWrapper_(src, wrapper, listener, opt_capt); -}; - - -/** - * Adds an event listener with a specific event wrapper on a DOM Node or an - * object that has implemented {@link goog.events.EventTarget}. A listener can - * only be added once to an object. - * - * @param {EventTarget|goog.events.EventTarget} src The node to listen to - * events on. - * @param {goog.events.EventWrapper} wrapper Event wrapper to use. - * @param {function(this:T, ?):?|{handleEvent:function(this:T, ?):?}|null} - * listener Optional callback function to be used as the - * listener or an object with handleEvent function. - * @param {boolean|undefined} capture Optional whether to use capture phase. - * @param {T} scope Object in whose scope to call the listener. - * @return {THIS} This object, allowing for chaining of calls. - * @this {THIS} - * @template T, THIS - */ -goog.events.EventHandler.prototype.listenWithWrapperAndScope = function( - src, wrapper, listener, capture, scope) { - var self = /** @type {!goog.events.EventHandler} */ (this); - // TODO(mknichel): Deprecate this function. - return self.listenWithWrapper_(src, wrapper, listener, capture, scope); -}; - - -/** - * Adds an event listener with a specific event wrapper on a DOM Node or an - * object that has implemented {@link goog.events.EventTarget}. A listener can - * only be added once to an object. - * - * @param {EventTarget|goog.events.EventTarget} src The node to listen to - * events on. - * @param {goog.events.EventWrapper} wrapper Event wrapper to use. - * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback - * method, or an object with a handleEvent function. - * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to - * false). - * @param {Object=} opt_scope Element in whose scope to call the listener. - * @return {THIS} This object, allowing for chaining of calls. - * @this {THIS} - * @template THIS - * @private - */ -goog.events.EventHandler.prototype.listenWithWrapper_ = function( - src, wrapper, listener, opt_capt, opt_scope) { - var self = /** @type {!goog.events.EventHandler} */ (this); - wrapper.listen( - src, listener, opt_capt, opt_scope || self.handler_ || self, self); - return self; -}; - - -/** - * @return {number} Number of listeners registered by this handler. - */ -goog.events.EventHandler.prototype.getListenerCount = function() { - var count = 0; - for (var key in this.keys_) { - if (Object.prototype.hasOwnProperty.call(this.keys_, key)) { - count++; - } - } - return count; -}; - - -/** - * Unlistens on an event. - * @param {goog.events.ListenableType} src Event source. - * @param {string|Array<string>| - * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>} - * type Event type or array of event types to unlisten to. - * @param {function(this:?, EVENTOBJ):?|{handleEvent:function(?):?}|null=} - * opt_fn Optional callback function to be used as the listener or an object - * with handleEvent function. - * @param {(boolean|!EventListenerOptions)=} opt_options - * @param {Object=} opt_scope Object in whose scope to call the listener. - * @return {THIS} This object, allowing for chaining of calls. - * @this {THIS} - * @template EVENTOBJ, THIS - */ -goog.events.EventHandler.prototype.unlisten = function( - src, type, opt_fn, opt_options, opt_scope) { - var self = /** @type {!goog.events.EventHandler} */ (this); - if (goog.isArray(type)) { - for (var i = 0; i < type.length; i++) { - self.unlisten(src, type[i], opt_fn, opt_options, opt_scope); - } - } else { - var capture = - goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options; - var listener = goog.events.getListener( - src, type, opt_fn || self.handleEvent, capture, - opt_scope || self.handler_ || self); - - if (listener) { - goog.events.unlistenByKey(listener); - delete self.keys_[listener.key]; - } - } - - return self; -}; - - -/** - * Removes an event listener which was added with listenWithWrapper(). - * - * @param {EventTarget|goog.events.EventTarget} src The target to stop - * listening to events on. - * @param {goog.events.EventWrapper} wrapper Event wrapper to use. - * @param {function(?):?|{handleEvent:function(?):?}|null} listener The - * listener function to remove. - * @param {boolean=} opt_capt In DOM-compliant browsers, this determines - * whether the listener is fired during the capture or bubble phase of the - * event. - * @param {Object=} opt_scope Element in whose scope to call the listener. - * @return {THIS} This object, allowing for chaining of calls. - * @this {THIS} - * @template THIS - */ -goog.events.EventHandler.prototype.unlistenWithWrapper = function( - src, wrapper, listener, opt_capt, opt_scope) { - var self = /** @type {!goog.events.EventHandler} */ (this); - wrapper.unlisten( - src, listener, opt_capt, opt_scope || self.handler_ || self, self); - return self; -}; - - -/** - * Unlistens to all events. - */ -goog.events.EventHandler.prototype.removeAll = function() { - goog.object.forEach(this.keys_, function(listenerObj, key) { - if (this.keys_.hasOwnProperty(key)) { - goog.events.unlistenByKey(listenerObj); - } - }, this); - - this.keys_ = {}; -}; - - -/** - * Disposes of this EventHandler and removes all listeners that it registered. - * @override - * @protected - */ -goog.events.EventHandler.prototype.disposeInternal = function() { - goog.events.EventHandler.superClass_.disposeInternal.call(this); - this.removeAll(); -}; - - -/** - * Default event handler - * @param {goog.events.Event} e Event object. - */ -goog.events.EventHandler.prototype.handleEvent = function(e) { - throw new Error('EventHandler.handleEvent not implemented'); -};
diff --git a/third_party/ink/closure/events/eventid.js b/third_party/ink/closure/events/eventid.js deleted file mode 100644 index 9ff9e40..0000000 --- a/third_party/ink/closure/events/eventid.js +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.events.EventId'); - - - -/** - * A templated class that is used when registering for events. Typical usage: - * - * /** @type {goog.events.EventId<MyEventObj>} *\ - * var myEventId = new goog.events.EventId( - * goog.events.getUniqueId(('someEvent')); - * - * // No need to cast or declare here since the compiler knows the - * // correct type of 'evt' (MyEventObj). - * something.listen(myEventId, function(evt) {}); - * - * @param {string} eventId - * @template T - * @constructor - * @struct - * @final - */ -goog.events.EventId = function(eventId) { - /** @const */ this.id = eventId; -}; - - -/** - * @override - */ -goog.events.EventId.prototype.toString = function() { - return this.id; -};
diff --git a/third_party/ink/closure/events/events.js b/third_party/ink/closure/events/events.js deleted file mode 100644 index 4466923..0000000 --- a/third_party/ink/closure/events/events.js +++ /dev/null
@@ -1,1006 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview An event manager for both native browser event - * targets and custom JavaScript event targets - * ({@code goog.events.Listenable}). This provides an abstraction - * over browsers' event systems. - * - * It also provides a simulation of W3C event model's capture phase in - * Internet Explorer (IE 8 and below). Caveat: the simulation does not - * interact well with listeners registered directly on the elements - * (bypassing goog.events) or even with listeners registered via - * goog.events in a separate JS binary. In these cases, we provide - * no ordering guarantees. - * - * The listeners will receive a "patched" event object. Such event object - * contains normalized values for certain event properties that differs in - * different browsers. - * - * Example usage: - * <pre> - * goog.events.listen(myNode, 'click', function(e) { alert('woo') }); - * goog.events.listen(myNode, 'mouseover', mouseHandler, true); - * goog.events.unlisten(myNode, 'mouseover', mouseHandler, true); - * goog.events.removeAll(myNode); - * </pre> - * - * @author aa@google.com (Aaron Boodman) [Original implementation of listen()] - * @author pupius@google.com (Daniel Pupius) [Port to closure plus capture phase - * in IE and event object patching] - * @author arv@google.com (Erik Arvidsson) - * - * @see ../demos/events.html - * @see ../demos/event-propagation.html - * @see ../demos/stopevent.html - */ - -// IMPLEMENTATION NOTES: -// goog.events stores an auxiliary data structure on each EventTarget -// source being listened on. This allows us to take advantage of GC, -// having the data structure GC'd when the EventTarget is GC'd. This -// GC behavior is equivalent to using W3C DOM Events directly. - -goog.provide('goog.events'); -goog.provide('goog.events.CaptureSimulationMode'); -goog.provide('goog.events.Key'); -goog.provide('goog.events.ListenableType'); - -goog.require('goog.asserts'); -goog.require('goog.debug.entryPointRegistry'); -goog.require('goog.events.BrowserEvent'); -goog.require('goog.events.BrowserFeature'); -goog.require('goog.events.Listenable'); -goog.require('goog.events.ListenerMap'); - -goog.forwardDeclare('goog.debug.ErrorHandler'); -goog.forwardDeclare('goog.events.EventWrapper'); - - -/** - * @typedef {number|goog.events.ListenableKey} - */ -goog.events.Key; - - -/** - * @typedef {EventTarget|goog.events.Listenable} - */ -goog.events.ListenableType; - - -/** - * Property name on a native event target for the listener map - * associated with the event target. - * @private @const {string} - */ -goog.events.LISTENER_MAP_PROP_ = 'closure_lm_' + ((Math.random() * 1e6) | 0); - - -/** - * String used to prepend to IE event types. - * @const - * @private - */ -goog.events.onString_ = 'on'; - - -/** - * Map of computed "on<eventname>" strings for IE event types. Caching - * this removes an extra object allocation in goog.events.listen which - * improves IE6 performance. - * @const - * @dict - * @private - */ -goog.events.onStringMap_ = {}; - - -/** - * @enum {number} Different capture simulation mode for IE8-. - */ -goog.events.CaptureSimulationMode = { - /** - * Does not perform capture simulation. Will asserts in IE8- when you - * add capture listeners. - */ - OFF_AND_FAIL: 0, - - /** - * Does not perform capture simulation, silently ignore capture - * listeners. - */ - OFF_AND_SILENT: 1, - - /** - * Performs capture simulation. - */ - ON: 2 -}; - - -/** - * @define {number} The capture simulation mode for IE8-. By default, - * this is ON. - */ -goog.define('goog.events.CAPTURE_SIMULATION_MODE', 2); - - -/** - * Estimated count of total native listeners. - * @private {number} - */ -goog.events.listenerCountEstimate_ = 0; - - -/** - * Adds an event listener for a specific event on a native event - * target (such as a DOM element) or an object that has implemented - * {@link goog.events.Listenable}. A listener can only be added once - * to an object and if it is added again the key for the listener is - * returned. Note that if the existing listener is a one-off listener - * (registered via listenOnce), it will no longer be a one-off - * listener after a call to listen(). - * - * @param {EventTarget|goog.events.Listenable} src The node to listen - * to events on. - * @param {string|Array<string>| - * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>} - * type Event type or array of event types. - * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null} - * listener Callback method, or an object with a handleEvent function. - * WARNING: passing an Object is now softly deprecated. - * @param {(boolean|!AddEventListenerOptions)=} opt_options - * @param {T=} opt_handler Element in whose scope to call the listener. - * @return {goog.events.Key} Unique key for the listener. - * @template T,EVENTOBJ - */ -goog.events.listen = function(src, type, listener, opt_options, opt_handler) { - if (opt_options && opt_options.once) { - return goog.events.listenOnce( - src, type, listener, opt_options, opt_handler); - } - if (goog.isArray(type)) { - for (var i = 0; i < type.length; i++) { - goog.events.listen(src, type[i], listener, opt_options, opt_handler); - } - return null; - } - - listener = goog.events.wrapListener(listener); - if (goog.events.Listenable.isImplementedBy(src)) { - var capture = - goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options; - return src.listen( - /** @type {string|!goog.events.EventId} */ (type), listener, capture, - opt_handler); - } else { - return goog.events.listen_( - /** @type {!EventTarget} */ (src), type, listener, - /* callOnce */ false, opt_options, opt_handler); - } -}; - - -/** - * Adds an event listener for a specific event on a native event - * target. A listener can only be added once to an object and if it - * is added again the key for the listener is returned. - * - * Note that a one-off listener will not change an existing listener, - * if any. On the other hand a normal listener will change existing - * one-off listener to become a normal listener. - * - * @param {EventTarget} src The node to listen to events on. - * @param {string|?goog.events.EventId<EVENTOBJ>} type Event type. - * @param {!Function} listener Callback function. - * @param {boolean} callOnce Whether the listener is a one-off - * listener or otherwise. - * @param {(boolean|!AddEventListenerOptions)=} opt_options - * @param {Object=} opt_handler Element in whose scope to call the listener. - * @return {goog.events.ListenableKey} Unique key for the listener. - * @template EVENTOBJ - * @private - */ -goog.events.listen_ = function( - src, type, listener, callOnce, opt_options, opt_handler) { - if (!type) { - throw new Error('Invalid event type'); - } - - var capture = - goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options; - if (capture && !goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) { - if (goog.events.CAPTURE_SIMULATION_MODE == - goog.events.CaptureSimulationMode.OFF_AND_FAIL) { - goog.asserts.fail('Can not register capture listener in IE8-.'); - return null; - } else if ( - goog.events.CAPTURE_SIMULATION_MODE == - goog.events.CaptureSimulationMode.OFF_AND_SILENT) { - return null; - } - } - - var listenerMap = goog.events.getListenerMap_(src); - if (!listenerMap) { - src[goog.events.LISTENER_MAP_PROP_] = listenerMap = - new goog.events.ListenerMap(src); - } - - var listenerObj = /** @type {goog.events.Listener} */ ( - listenerMap.add(type, listener, callOnce, capture, opt_handler)); - - // If the listenerObj already has a proxy, it has been set up - // previously. We simply return. - if (listenerObj.proxy) { - return listenerObj; - } - - var proxy = goog.events.getProxy(); - listenerObj.proxy = proxy; - - proxy.src = src; - proxy.listener = listenerObj; - - // Attach the proxy through the browser's API - if (src.addEventListener) { - // Don't pass an object as `capture` if the browser doesn't support that. - if (!goog.events.BrowserFeature.PASSIVE_EVENTS) { - opt_options = capture; - } - // Don't break tests that expect a boolean. - if (opt_options === undefined) opt_options = false; - src.addEventListener(type.toString(), proxy, opt_options); - } else if (src.attachEvent) { - // The else if above used to be an unconditional else. It would call - // attachEvent come gws or high water. This would sometimes throw an - // exception on IE11, spoiling the day of some callers. The previous - // incarnation of this code, from 2007, indicates that it replaced an - // earlier still version that caused excess allocations on IE6. - src.attachEvent(goog.events.getOnString_(type.toString()), proxy); - } else { - throw new Error('addEventListener and attachEvent are unavailable.'); - } - - goog.events.listenerCountEstimate_++; - return listenerObj; -}; - - -/** - * Helper function for returning a proxy function. - * @return {!Function} A new or reused function object. - */ -goog.events.getProxy = function() { - var proxyCallbackFunction = goog.events.handleBrowserEvent_; - // Use a local var f to prevent one allocation. - var f = - goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT ? function(eventObject) { - return proxyCallbackFunction.call(f.src, f.listener, eventObject); - } : function(eventObject) { - var v = proxyCallbackFunction.call(f.src, f.listener, eventObject); - // NOTE(chrishenry): In IE, we hack in a capture phase. However, if - // there is inline event handler which tries to prevent default (for - // example <a href="..." onclick="return false">...</a>) in a - // descendant element, the prevent default will be overridden - // by this listener if this listener were to return true. Hence, we - // return undefined. - if (!v) return v; - }; - return f; -}; - - -/** - * Adds an event listener for a specific event on a native event - * target (such as a DOM element) or an object that has implemented - * {@link goog.events.Listenable}. After the event has fired the event - * listener is removed from the target. - * - * If an existing listener already exists, listenOnce will do - * nothing. In particular, if the listener was previously registered - * via listen(), listenOnce() will not turn the listener into a - * one-off listener. Similarly, if there is already an existing - * one-off listener, listenOnce does not modify the listeners (it is - * still a once listener). - * - * @param {EventTarget|goog.events.Listenable} src The node to listen - * to events on. - * @param {string|Array<string>| - * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>} - * type Event type or array of event types. - * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null} - * listener Callback method. - * @param {(boolean|!AddEventListenerOptions)=} opt_options - * @param {T=} opt_handler Element in whose scope to call the listener. - * @return {goog.events.Key} Unique key for the listener. - * @template T,EVENTOBJ - */ -goog.events.listenOnce = function( - src, type, listener, opt_options, opt_handler) { - if (goog.isArray(type)) { - for (var i = 0; i < type.length; i++) { - goog.events.listenOnce(src, type[i], listener, opt_options, opt_handler); - } - return null; - } - - listener = goog.events.wrapListener(listener); - if (goog.events.Listenable.isImplementedBy(src)) { - var capture = - goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options; - return src.listenOnce( - /** @type {string|!goog.events.EventId} */ (type), listener, capture, - opt_handler); - } else { - return goog.events.listen_( - /** @type {!EventTarget} */ (src), type, listener, - /* callOnce */ true, opt_options, opt_handler); - } -}; - - -/** - * Adds an event listener with a specific event wrapper on a DOM Node or an - * object that has implemented {@link goog.events.Listenable}. A listener can - * only be added once to an object. - * - * @param {EventTarget|goog.events.Listenable} src The target to - * listen to events on. - * @param {goog.events.EventWrapper} wrapper Event wrapper to use. - * @param {function(this:T, ?):?|{handleEvent:function(?):?}|null} listener - * Callback method, or an object with a handleEvent function. - * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to - * false). - * @param {T=} opt_handler Element in whose scope to call the listener. - * @template T - */ -goog.events.listenWithWrapper = function( - src, wrapper, listener, opt_capt, opt_handler) { - wrapper.listen(src, listener, opt_capt, opt_handler); -}; - - -/** - * Removes an event listener which was added with listen(). - * - * @param {EventTarget|goog.events.Listenable} src The target to stop - * listening to events on. - * @param {string|Array<string>| - * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>} - * type Event type or array of event types to unlisten to. - * @param {function(?):?|{handleEvent:function(?):?}|null} listener The - * listener function to remove. - * @param {(boolean|!EventListenerOptions)=} opt_options - * whether the listener is fired during the capture or bubble phase of the - * event. - * @param {Object=} opt_handler Element in whose scope to call the listener. - * @return {?boolean} indicating whether the listener was there to remove. - * @template EVENTOBJ - */ -goog.events.unlisten = function(src, type, listener, opt_options, opt_handler) { - if (goog.isArray(type)) { - for (var i = 0; i < type.length; i++) { - goog.events.unlisten(src, type[i], listener, opt_options, opt_handler); - } - return null; - } - var capture = - goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options; - - listener = goog.events.wrapListener(listener); - if (goog.events.Listenable.isImplementedBy(src)) { - return src.unlisten( - /** @type {string|!goog.events.EventId} */ (type), listener, capture, - opt_handler); - } - - if (!src) { - // TODO(chrishenry): We should tighten the API to only accept - // non-null objects, or add an assertion here. - return false; - } - - var listenerMap = goog.events.getListenerMap_( - /** @type {!EventTarget} */ (src)); - if (listenerMap) { - var listenerObj = listenerMap.getListener( - /** @type {string|!goog.events.EventId} */ (type), listener, capture, - opt_handler); - if (listenerObj) { - return goog.events.unlistenByKey(listenerObj); - } - } - - return false; -}; - - -/** - * Removes an event listener which was added with listen() by the key - * returned by listen(). - * - * @param {goog.events.Key} key The key returned by listen() for this - * event listener. - * @return {boolean} indicating whether the listener was there to remove. - */ -goog.events.unlistenByKey = function(key) { - // TODO(chrishenry): Remove this check when tests that rely on this - // are fixed. - if (goog.isNumber(key)) { - return false; - } - - var listener = key; - if (!listener || listener.removed) { - return false; - } - - var src = listener.src; - if (goog.events.Listenable.isImplementedBy(src)) { - return /** @type {!goog.events.Listenable} */ (src).unlistenByKey(listener); - } - - var type = listener.type; - var proxy = listener.proxy; - if (src.removeEventListener) { - src.removeEventListener(type, proxy, listener.capture); - } else if (src.detachEvent) { - src.detachEvent(goog.events.getOnString_(type), proxy); - } - goog.events.listenerCountEstimate_--; - - var listenerMap = goog.events.getListenerMap_( - /** @type {!EventTarget} */ (src)); - // TODO(chrishenry): Try to remove this conditional and execute the - // first branch always. This should be safe. - if (listenerMap) { - listenerMap.removeByKey(listener); - if (listenerMap.getTypeCount() == 0) { - // Null the src, just because this is simple to do (and useful - // for IE <= 7). - listenerMap.src = null; - // We don't use delete here because IE does not allow delete - // on a window object. - src[goog.events.LISTENER_MAP_PROP_] = null; - } - } else { - /** @type {!goog.events.Listener} */ (listener).markAsRemoved(); - } - - return true; -}; - - -/** - * Removes an event listener which was added with listenWithWrapper(). - * - * @param {EventTarget|goog.events.Listenable} src The target to stop - * listening to events on. - * @param {goog.events.EventWrapper} wrapper Event wrapper to use. - * @param {function(?):?|{handleEvent:function(?):?}|null} listener The - * listener function to remove. - * @param {boolean=} opt_capt In DOM-compliant browsers, this determines - * whether the listener is fired during the capture or bubble phase of the - * event. - * @param {Object=} opt_handler Element in whose scope to call the listener. - */ -goog.events.unlistenWithWrapper = function( - src, wrapper, listener, opt_capt, opt_handler) { - wrapper.unlisten(src, listener, opt_capt, opt_handler); -}; - - -/** - * Removes all listeners from an object. You can also optionally - * remove listeners of a particular type. - * - * @param {Object|undefined} obj Object to remove listeners from. Must be an - * EventTarget or a goog.events.Listenable. - * @param {string|!goog.events.EventId=} opt_type Type of event to remove. - * Default is all types. - * @return {number} Number of listeners removed. - */ -goog.events.removeAll = function(obj, opt_type) { - // TODO(chrishenry): Change the type of obj to - // (!EventTarget|!goog.events.Listenable). - - if (!obj) { - return 0; - } - - if (goog.events.Listenable.isImplementedBy(obj)) { - return /** @type {?} */ (obj).removeAllListeners(opt_type); - } - - var listenerMap = goog.events.getListenerMap_( - /** @type {!EventTarget} */ (obj)); - if (!listenerMap) { - return 0; - } - - var count = 0; - var typeStr = opt_type && opt_type.toString(); - for (var type in listenerMap.listeners) { - if (!typeStr || type == typeStr) { - // Clone so that we don't need to worry about unlistenByKey - // changing the content of the ListenerMap. - var listeners = listenerMap.listeners[type].concat(); - for (var i = 0; i < listeners.length; ++i) { - if (goog.events.unlistenByKey(listeners[i])) { - ++count; - } - } - } - } - return count; -}; - - -/** - * Gets the listeners for a given object, type and capture phase. - * - * @param {Object} obj Object to get listeners for. - * @param {string|!goog.events.EventId} type Event type. - * @param {boolean} capture Capture phase?. - * @return {Array<!goog.events.Listener>} Array of listener objects. - */ -goog.events.getListeners = function(obj, type, capture) { - if (goog.events.Listenable.isImplementedBy(obj)) { - return /** @type {!goog.events.Listenable} */ (obj).getListeners( - type, capture); - } else { - if (!obj) { - // TODO(chrishenry): We should tighten the API to accept - // !EventTarget|goog.events.Listenable, and add an assertion here. - return []; - } - - var listenerMap = goog.events.getListenerMap_( - /** @type {!EventTarget} */ (obj)); - return listenerMap ? listenerMap.getListeners(type, capture) : []; - } -}; - - -/** - * Gets the goog.events.Listener for the event or null if no such listener is - * in use. - * - * @param {EventTarget|goog.events.Listenable} src The target from - * which to get listeners. - * @param {?string|!goog.events.EventId<EVENTOBJ>} type The type of the event. - * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null} listener The - * listener function to get. - * @param {boolean=} opt_capt In DOM-compliant browsers, this determines - * whether the listener is fired during the - * capture or bubble phase of the event. - * @param {Object=} opt_handler Element in whose scope to call the listener. - * @return {goog.events.ListenableKey} the found listener or null if not found. - * @template EVENTOBJ - */ -goog.events.getListener = function(src, type, listener, opt_capt, opt_handler) { - // TODO(chrishenry): Change type from ?string to string, or add assertion. - type = /** @type {string} */ (type); - listener = goog.events.wrapListener(listener); - var capture = !!opt_capt; - if (goog.events.Listenable.isImplementedBy(src)) { - return src.getListener(type, listener, capture, opt_handler); - } - - if (!src) { - // TODO(chrishenry): We should tighten the API to only accept - // non-null objects, or add an assertion here. - return null; - } - - var listenerMap = goog.events.getListenerMap_( - /** @type {!EventTarget} */ (src)); - if (listenerMap) { - return listenerMap.getListener(type, listener, capture, opt_handler); - } - return null; -}; - - -/** - * Returns whether an event target has any active listeners matching the - * specified signature. If either the type or capture parameters are - * unspecified, the function will match on the remaining criteria. - * - * @param {EventTarget|goog.events.Listenable} obj Target to get - * listeners for. - * @param {string|!goog.events.EventId=} opt_type Event type. - * @param {boolean=} opt_capture Whether to check for capture or bubble-phase - * listeners. - * @return {boolean} Whether an event target has one or more listeners matching - * the requested type and/or capture phase. - */ -goog.events.hasListener = function(obj, opt_type, opt_capture) { - if (goog.events.Listenable.isImplementedBy(obj)) { - return obj.hasListener(opt_type, opt_capture); - } - - var listenerMap = goog.events.getListenerMap_( - /** @type {!EventTarget} */ (obj)); - return !!listenerMap && listenerMap.hasListener(opt_type, opt_capture); -}; - - -/** - * Provides a nice string showing the normalized event objects public members - * @param {Object} e Event Object. - * @return {string} String of the public members of the normalized event object. - */ -goog.events.expose = function(e) { - var str = []; - for (var key in e) { - if (e[key] && e[key].id) { - str.push(key + ' = ' + e[key] + ' (' + e[key].id + ')'); - } else { - str.push(key + ' = ' + e[key]); - } - } - return str.join('\n'); -}; - - -/** - * Returns a string with on prepended to the specified type. This is used for IE - * which expects "on" to be prepended. This function caches the string in order - * to avoid extra allocations in steady state. - * @param {string} type Event type. - * @return {string} The type string with 'on' prepended. - * @private - */ -goog.events.getOnString_ = function(type) { - if (type in goog.events.onStringMap_) { - return goog.events.onStringMap_[type]; - } - return goog.events.onStringMap_[type] = goog.events.onString_ + type; -}; - - -/** - * Fires an object's listeners of a particular type and phase - * - * @param {Object} obj Object whose listeners to call. - * @param {string|!goog.events.EventId} type Event type. - * @param {boolean} capture Which event phase. - * @param {Object} eventObject Event object to be passed to listener. - * @return {boolean} True if all listeners returned true else false. - */ -goog.events.fireListeners = function(obj, type, capture, eventObject) { - if (goog.events.Listenable.isImplementedBy(obj)) { - return /** @type {!goog.events.Listenable} */ (obj).fireListeners( - type, capture, eventObject); - } - - return goog.events.fireListeners_(obj, type, capture, eventObject); -}; - - -/** - * Fires an object's listeners of a particular type and phase. - * @param {Object} obj Object whose listeners to call. - * @param {string|!goog.events.EventId} type Event type. - * @param {boolean} capture Which event phase. - * @param {Object} eventObject Event object to be passed to listener. - * @return {boolean} True if all listeners returned true else false. - * @private - */ -goog.events.fireListeners_ = function(obj, type, capture, eventObject) { - /** @type {boolean} */ - var retval = true; - - var listenerMap = goog.events.getListenerMap_( - /** @type {EventTarget} */ (obj)); - if (listenerMap) { - // TODO(chrishenry): Original code avoids array creation when there - // is no listener, so we do the same. If this optimization turns - // out to be not required, we can replace this with - // listenerMap.getListeners(type, capture) instead, which is simpler. - var listenerArray = listenerMap.listeners[type.toString()]; - if (listenerArray) { - listenerArray = listenerArray.concat(); - for (var i = 0; i < listenerArray.length; i++) { - var listener = listenerArray[i]; - // We might not have a listener if the listener was removed. - if (listener && listener.capture == capture && !listener.removed) { - var result = goog.events.fireListener(listener, eventObject); - retval = retval && (result !== false); - } - } - } - } - return retval; -}; - - -/** - * Fires a listener with a set of arguments - * - * @param {goog.events.Listener} listener The listener object to call. - * @param {Object} eventObject The event object to pass to the listener. - * @return {*} Result of listener. - */ -goog.events.fireListener = function(listener, eventObject) { - var listenerFn = listener.listener; - var listenerHandler = listener.handler || listener.src; - - if (listener.callOnce) { - goog.events.unlistenByKey(listener); - } - return listenerFn.call(listenerHandler, eventObject); -}; - - -/** - * Gets the total number of listeners currently in the system. - * @return {number} Number of listeners. - * @deprecated This returns estimated count, now that Closure no longer - * stores a central listener registry. We still return an estimation - * to keep existing listener-related tests passing. In the near future, - * this function will be removed. - */ -goog.events.getTotalListenerCount = function() { - return goog.events.listenerCountEstimate_; -}; - - -/** - * Dispatches an event (or event like object) and calls all listeners - * listening for events of this type. The type of the event is decided by the - * type property on the event object. - * - * If any of the listeners returns false OR calls preventDefault then this - * function will return false. If one of the capture listeners calls - * stopPropagation, then the bubble listeners won't fire. - * - * @param {goog.events.Listenable} src The event target. - * @param {goog.events.EventLike} e Event object. - * @return {boolean} If anyone called preventDefault on the event object (or - * if any of the handlers returns false) this will also return false. - * If there are no handlers, or if all handlers return true, this returns - * true. - */ -goog.events.dispatchEvent = function(src, e) { - goog.asserts.assert( - goog.events.Listenable.isImplementedBy(src), - 'Can not use goog.events.dispatchEvent with ' + - 'non-goog.events.Listenable instance.'); - return src.dispatchEvent(e); -}; - - -/** - * Installs exception protection for the browser event entry point using the - * given error handler. - * - * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to - * protect the entry point. - */ -goog.events.protectBrowserEventEntryPoint = function(errorHandler) { - goog.events.handleBrowserEvent_ = - errorHandler.protectEntryPoint(goog.events.handleBrowserEvent_); -}; - - -/** - * Handles an event and dispatches it to the correct listeners. This - * function is a proxy for the real listener the user specified. - * - * @param {goog.events.Listener} listener The listener object. - * @param {Event=} opt_evt Optional event object that gets passed in via the - * native event handlers. - * @return {*} Result of the event handler. - * @this {EventTarget} The object or Element that fired the event. - * @private - */ -goog.events.handleBrowserEvent_ = function(listener, opt_evt) { - if (listener.removed) { - return true; - } - - // Synthesize event propagation if the browser does not support W3C - // event model. - if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) { - var ieEvent = opt_evt || - /** @type {Event} */ (goog.getObjectByName('window.event')); - var evt = new goog.events.BrowserEvent(ieEvent, this); - /** @type {*} */ - var retval = true; - - if (goog.events.CAPTURE_SIMULATION_MODE == - goog.events.CaptureSimulationMode.ON) { - // If we have not marked this event yet, we should perform capture - // simulation. - if (!goog.events.isMarkedIeEvent_(ieEvent)) { - goog.events.markIeEvent_(ieEvent); - - var ancestors = []; - for (var parent = evt.currentTarget; parent; - parent = parent.parentNode) { - ancestors.push(parent); - } - - // Fire capture listeners. - var type = listener.type; - for (var i = ancestors.length - 1; !evt.propagationStopped_ && i >= 0; - i--) { - evt.currentTarget = ancestors[i]; - var result = - goog.events.fireListeners_(ancestors[i], type, true, evt); - retval = retval && result; - } - - // Fire bubble listeners. - // - // We can technically rely on IE to perform bubble event - // propagation. However, it turns out that IE fires events in - // opposite order of attachEvent registration, which broke - // some code and tests that rely on the order. (While W3C DOM - // Level 2 Events TR leaves the event ordering unspecified, - // modern browsers and W3C DOM Level 3 Events Working Draft - // actually specify the order as the registration order.) - for (var i = 0; !evt.propagationStopped_ && i < ancestors.length; i++) { - evt.currentTarget = ancestors[i]; - var result = - goog.events.fireListeners_(ancestors[i], type, false, evt); - retval = retval && result; - } - } - } else { - retval = goog.events.fireListener(listener, evt); - } - return retval; - } - - // Otherwise, simply fire the listener. - return goog.events.fireListener( - listener, new goog.events.BrowserEvent(opt_evt, this)); -}; - - -/** - * This is used to mark the IE event object so we do not do the Closure pass - * twice for a bubbling event. - * @param {Event} e The IE browser event. - * @private - */ -goog.events.markIeEvent_ = function(e) { - // Only the keyCode and the returnValue can be changed. We use keyCode for - // non keyboard events. - // event.returnValue is a bit more tricky. It is undefined by default. A - // boolean false prevents the default action. In a window.onbeforeunload and - // the returnValue is non undefined it will be alerted. However, we will only - // modify the returnValue for keyboard events. We can get a problem if non - // closure events sets the keyCode or the returnValue - - var useReturnValue = false; - - if (e.keyCode == 0) { - // We cannot change the keyCode in case that srcElement is input[type=file]. - // We could test that that is the case but that would allocate 3 objects. - // If we use try/catch we will only allocate extra objects in the case of a - // failure. - - try { - e.keyCode = -1; - return; - } catch (ex) { - useReturnValue = true; - } - } - - if (useReturnValue || - /** @type {boolean|undefined} */ (e.returnValue) == undefined) { - e.returnValue = true; - } -}; - - -/** - * This is used to check if an IE event has already been handled by the Closure - * system so we do not do the Closure pass twice for a bubbling event. - * @param {Event} e The IE browser event. - * @return {boolean} True if the event object has been marked. - * @private - */ -goog.events.isMarkedIeEvent_ = function(e) { - return e.keyCode < 0 || e.returnValue != undefined; -}; - - -/** - * Counter to create unique event ids. - * @private {number} - */ -goog.events.uniqueIdCounter_ = 0; - - -/** - * Creates a unique event id. - * - * @param {string} identifier The identifier. - * @return {string} A unique identifier. - * @idGenerator {unique} - */ -goog.events.getUniqueId = function(identifier) { - return identifier + '_' + goog.events.uniqueIdCounter_++; -}; - - -/** - * @param {EventTarget} src The source object. - * @return {goog.events.ListenerMap} A listener map for the given - * source object, or null if none exists. - * @private - */ -goog.events.getListenerMap_ = function(src) { - var listenerMap = src[goog.events.LISTENER_MAP_PROP_]; - // IE serializes the property as well (e.g. when serializing outer - // HTML). So we must check that the value is of the correct type. - return listenerMap instanceof goog.events.ListenerMap ? listenerMap : null; -}; - - -/** - * Expando property for listener function wrapper for Object with - * handleEvent. - * @private @const {string} - */ -goog.events.LISTENER_WRAPPER_PROP_ = - '__closure_events_fn_' + ((Math.random() * 1e9) >>> 0); - - -/** - * @param {Object|Function} listener The listener function or an - * object that contains handleEvent method. - * @return {!Function} Either the original function or a function that - * calls obj.handleEvent. If the same listener is passed to this - * function more than once, the same function is guaranteed to be - * returned. - */ -goog.events.wrapListener = function(listener) { - goog.asserts.assert(listener, 'Listener can not be null.'); - - if (goog.isFunction(listener)) { - return listener; - } - - goog.asserts.assert( - listener.handleEvent, 'An object listener must have handleEvent method.'); - if (!listener[goog.events.LISTENER_WRAPPER_PROP_]) { - listener[goog.events.LISTENER_WRAPPER_PROP_] = function(e) { - return /** @type {?} */ (listener).handleEvent(e); - }; - } - return listener[goog.events.LISTENER_WRAPPER_PROP_]; -}; - - -// Register the browser event handler as an entry point, so that -// it can be monitored for exception handling, etc. -goog.debug.entryPointRegistry.register( - /** - * @param {function(!Function): !Function} transformer The transforming - * function. - */ - function(transformer) { - goog.events.handleBrowserEvent_ = - transformer(goog.events.handleBrowserEvent_); - });
diff --git a/third_party/ink/closure/events/eventtarget.js b/third_party/ink/closure/events/eventtarget.js deleted file mode 100644 index b8adcaee..0000000 --- a/third_party/ink/closure/events/eventtarget.js +++ /dev/null
@@ -1,395 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A disposable implementation of a custom - * listenable/event target. See also: documentation for - * {@code goog.events.Listenable}. - * - * @author arv@google.com (Erik Arvidsson) [Original implementation] - * @author pupius@google.com (Daniel Pupius) [Port to use goog.events] - * @see ../demos/eventtarget.html - * @see goog.events.Listenable - */ - -goog.provide('goog.events.EventTarget'); - -goog.require('goog.Disposable'); -goog.require('goog.asserts'); -goog.require('goog.events'); -goog.require('goog.events.Event'); -goog.require('goog.events.Listenable'); -goog.require('goog.events.ListenerMap'); -goog.require('goog.object'); - - - -/** - * An implementation of {@code goog.events.Listenable} with full W3C - * EventTarget-like support (capture/bubble mechanism, stopping event - * propagation, preventing default actions). - * - * You may subclass this class to turn your class into a Listenable. - * - * Unless propagation is stopped, an event dispatched by an - * EventTarget will bubble to the parent returned by - * {@code getParentEventTarget}. To set the parent, call - * {@code setParentEventTarget}. Subclasses that don't support - * changing the parent can override the setter to throw an error. - * - * Example usage: - * <pre> - * var source = new goog.events.EventTarget(); - * function handleEvent(e) { - * alert('Type: ' + e.type + '; Target: ' + e.target); - * } - * source.listen('foo', handleEvent); - * // Or: goog.events.listen(source, 'foo', handleEvent); - * ... - * source.dispatchEvent('foo'); // will call handleEvent - * ... - * source.unlisten('foo', handleEvent); - * // Or: goog.events.unlisten(source, 'foo', handleEvent); - * </pre> - * - * @constructor - * @extends {goog.Disposable} - * @implements {goog.events.Listenable} - */ -goog.events.EventTarget = function() { - goog.Disposable.call(this); - - /** - * Maps of event type to an array of listeners. - * @private {!goog.events.ListenerMap} - */ - this.eventTargetListeners_ = new goog.events.ListenerMap(this); - - /** - * The object to use for event.target. Useful when mixing in an - * EventTarget to another object. - * @private {!Object} - */ - this.actualEventTarget_ = this; - - /** - * Parent event target, used during event bubbling. - * - * TODO(chrishenry): Change this to goog.events.Listenable. This - * currently breaks people who expect getParentEventTarget to return - * goog.events.EventTarget. - * - * @private {goog.events.EventTarget} - */ - this.parentEventTarget_ = null; -}; -goog.inherits(goog.events.EventTarget, goog.Disposable); -goog.events.Listenable.addImplementation(goog.events.EventTarget); - - -/** - * An artificial cap on the number of ancestors you can have. This is mainly - * for loop detection. - * @const {number} - * @private - */ -goog.events.EventTarget.MAX_ANCESTORS_ = 1000; - - -/** - * Returns the parent of this event target to use for bubbling. - * - * @return {goog.events.EventTarget} The parent EventTarget or null if - * there is no parent. - * @override - */ -goog.events.EventTarget.prototype.getParentEventTarget = function() { - return this.parentEventTarget_; -}; - - -/** - * Sets the parent of this event target to use for capture/bubble - * mechanism. - * @param {goog.events.EventTarget} parent Parent listenable (null if none). - */ -goog.events.EventTarget.prototype.setParentEventTarget = function(parent) { - this.parentEventTarget_ = parent; -}; - - -/** - * Adds an event listener to the event target. The same handler can only be - * added once per the type. Even if you add the same handler multiple times - * using the same type then it will only be called once when the event is - * dispatched. - * - * @param {string|!goog.events.EventId} type The type of the event to listen for - * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function - * to handle the event. The handler can also be an object that implements - * the handleEvent method which takes the event object as argument. - * @param {boolean=} opt_capture In DOM-compliant browsers, this determines - * whether the listener is fired during the capture or bubble phase - * of the event. - * @param {Object=} opt_handlerScope Object in whose scope to call - * the listener. - * @deprecated Use {@code #listen} instead, when possible. Otherwise, use - * {@code goog.events.listen} if you are passing Object - * (instead of Function) as handler. - */ -goog.events.EventTarget.prototype.addEventListener = function( - type, handler, opt_capture, opt_handlerScope) { - goog.events.listen(this, type, handler, opt_capture, opt_handlerScope); -}; - - -/** - * Removes an event listener from the event target. The handler must be the - * same object as the one added. If the handler has not been added then - * nothing is done. - * - * @param {string} type The type of the event to listen for. - * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function - * to handle the event. The handler can also be an object that implements - * the handleEvent method which takes the event object as argument. - * @param {boolean=} opt_capture In DOM-compliant browsers, this determines - * whether the listener is fired during the capture or bubble phase - * of the event. - * @param {Object=} opt_handlerScope Object in whose scope to call - * the listener. - * @deprecated Use {@code #unlisten} instead, when possible. Otherwise, use - * {@code goog.events.unlisten} if you are passing Object - * (instead of Function) as handler. - */ -goog.events.EventTarget.prototype.removeEventListener = function( - type, handler, opt_capture, opt_handlerScope) { - goog.events.unlisten(this, type, handler, opt_capture, opt_handlerScope); -}; - - -/** @override */ -goog.events.EventTarget.prototype.dispatchEvent = function(e) { - this.assertInitialized_(); - - var ancestorsTree, ancestor = this.getParentEventTarget(); - if (ancestor) { - ancestorsTree = []; - var ancestorCount = 1; - for (; ancestor; ancestor = ancestor.getParentEventTarget()) { - ancestorsTree.push(ancestor); - goog.asserts.assert( - (++ancestorCount < goog.events.EventTarget.MAX_ANCESTORS_), - 'infinite loop'); - } - } - - return goog.events.EventTarget.dispatchEventInternal_( - this.actualEventTarget_, e, ancestorsTree); -}; - - -/** - * Removes listeners from this object. Classes that extend EventTarget may - * need to override this method in order to remove references to DOM Elements - * and additional listeners. - * @override - */ -goog.events.EventTarget.prototype.disposeInternal = function() { - goog.events.EventTarget.superClass_.disposeInternal.call(this); - - this.removeAllListeners(); - this.parentEventTarget_ = null; -}; - - -/** @override */ -goog.events.EventTarget.prototype.listen = function( - type, listener, opt_useCapture, opt_listenerScope) { - this.assertInitialized_(); - return this.eventTargetListeners_.add( - String(type), listener, false /* callOnce */, opt_useCapture, - opt_listenerScope); -}; - - -/** @override */ -goog.events.EventTarget.prototype.listenOnce = function( - type, listener, opt_useCapture, opt_listenerScope) { - return this.eventTargetListeners_.add( - String(type), listener, true /* callOnce */, opt_useCapture, - opt_listenerScope); -}; - - -/** @override */ -goog.events.EventTarget.prototype.unlisten = function( - type, listener, opt_useCapture, opt_listenerScope) { - return this.eventTargetListeners_.remove( - String(type), listener, opt_useCapture, opt_listenerScope); -}; - - -/** @override */ -goog.events.EventTarget.prototype.unlistenByKey = function(key) { - return this.eventTargetListeners_.removeByKey(key); -}; - - -/** @override */ -goog.events.EventTarget.prototype.removeAllListeners = function(opt_type) { - // TODO(chrishenry): Previously, removeAllListeners can be called on - // uninitialized EventTarget, so we preserve that behavior. We - // should remove this when usages that rely on that fact are purged. - if (!this.eventTargetListeners_) { - return 0; - } - return this.eventTargetListeners_.removeAll(opt_type); -}; - - -/** @override */ -goog.events.EventTarget.prototype.fireListeners = function( - type, capture, eventObject) { - // TODO(chrishenry): Original code avoids array creation when there - // is no listener, so we do the same. If this optimization turns - // out to be not required, we can replace this with - // getListeners(type, capture) instead, which is simpler. - var listenerArray = this.eventTargetListeners_.listeners[String(type)]; - if (!listenerArray) { - return true; - } - listenerArray = listenerArray.concat(); - - var rv = true; - for (var i = 0; i < listenerArray.length; ++i) { - var listener = listenerArray[i]; - // We might not have a listener if the listener was removed. - if (listener && !listener.removed && listener.capture == capture) { - var listenerFn = listener.listener; - var listenerHandler = listener.handler || listener.src; - - if (listener.callOnce) { - this.unlistenByKey(listener); - } - rv = listenerFn.call(listenerHandler, eventObject) !== false && rv; - } - } - - return rv && eventObject.returnValue_ != false; -}; - - -/** @override */ -goog.events.EventTarget.prototype.getListeners = function(type, capture) { - return this.eventTargetListeners_.getListeners(String(type), capture); -}; - - -/** @override */ -goog.events.EventTarget.prototype.getListener = function( - type, listener, capture, opt_listenerScope) { - return this.eventTargetListeners_.getListener( - String(type), listener, capture, opt_listenerScope); -}; - - -/** @override */ -goog.events.EventTarget.prototype.hasListener = function( - opt_type, opt_capture) { - var id = goog.isDef(opt_type) ? String(opt_type) : undefined; - return this.eventTargetListeners_.hasListener(id, opt_capture); -}; - - -/** - * Sets the target to be used for {@code event.target} when firing - * event. Mainly used for testing. For example, see - * {@code goog.testing.events.mixinListenable}. - * @param {!Object} target The target. - */ -goog.events.EventTarget.prototype.setTargetForTesting = function(target) { - this.actualEventTarget_ = target; -}; - - -/** - * Asserts that the event target instance is initialized properly. - * @private - */ -goog.events.EventTarget.prototype.assertInitialized_ = function() { - goog.asserts.assert( - this.eventTargetListeners_, - 'Event target is not initialized. Did you call the superclass ' + - '(goog.events.EventTarget) constructor?'); -}; - - -/** - * Dispatches the given event on the ancestorsTree. - * - * @param {!Object} target The target to dispatch on. - * @param {goog.events.Event|Object|string} e The event object. - * @param {Array<goog.events.Listenable>=} opt_ancestorsTree The ancestors - * tree of the target, in reverse order from the closest ancestor - * to the root event target. May be null if the target has no ancestor. - * @return {boolean} If anyone called preventDefault on the event object (or - * if any of the listeners returns false) this will also return false. - * @private - */ -goog.events.EventTarget.dispatchEventInternal_ = function( - target, e, opt_ancestorsTree) { - var type = e.type || /** @type {string} */ (e); - - // If accepting a string or object, create a custom event object so that - // preventDefault and stopPropagation work with the event. - if (goog.isString(e)) { - e = new goog.events.Event(e, target); - } else if (!(e instanceof goog.events.Event)) { - var oldEvent = e; - e = new goog.events.Event(type, target); - goog.object.extend(e, oldEvent); - } else { - e.target = e.target || target; - } - - var rv = true, currentTarget; - - // Executes all capture listeners on the ancestors, if any. - if (opt_ancestorsTree) { - for (var i = opt_ancestorsTree.length - 1; !e.propagationStopped_ && i >= 0; - i--) { - currentTarget = e.currentTarget = opt_ancestorsTree[i]; - rv = currentTarget.fireListeners(type, true, e) && rv; - } - } - - // Executes capture and bubble listeners on the target. - if (!e.propagationStopped_) { - currentTarget = /** @type {?} */ (e.currentTarget = target); - rv = currentTarget.fireListeners(type, true, e) && rv; - if (!e.propagationStopped_) { - rv = currentTarget.fireListeners(type, false, e) && rv; - } - } - - // Executes all bubble listeners on the ancestors, if any. - if (opt_ancestorsTree) { - for (i = 0; !e.propagationStopped_ && i < opt_ancestorsTree.length; i++) { - currentTarget = e.currentTarget = opt_ancestorsTree[i]; - rv = currentTarget.fireListeners(type, false, e) && rv; - } - } - - return rv; -};
diff --git a/third_party/ink/closure/events/eventtype.js b/third_party/ink/closure/events/eventtype.js deleted file mode 100644 index 801d7f9..0000000 --- a/third_party/ink/closure/events/eventtype.js +++ /dev/null
@@ -1,360 +0,0 @@ -// Copyright 2010 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Event Types. - * - * @author arv@google.com (Erik Arvidsson) - * @author mirkov@google.com (Mirko Visontai) - */ - - -goog.provide('goog.events.EventType'); -goog.provide('goog.events.PointerFallbackEventType'); - -goog.require('goog.events.BrowserFeature'); -goog.require('goog.userAgent'); - - -/** - * Returns a prefixed event name for the current browser. - * @param {string} eventName The name of the event. - * @return {string} The prefixed event name. - * @suppress {missingRequire|missingProvide} - * @private - */ -goog.events.getVendorPrefixedName_ = function(eventName) { - return goog.userAgent.WEBKIT ? - 'webkit' + eventName : - (goog.userAgent.OPERA ? 'o' + eventName.toLowerCase() : - eventName.toLowerCase()); -}; - - -/** - * Constants for event names. - * @enum {string} - */ -goog.events.EventType = { - // Mouse events - CLICK: 'click', - RIGHTCLICK: 'rightclick', - DBLCLICK: 'dblclick', - MOUSEDOWN: 'mousedown', - MOUSEUP: 'mouseup', - MOUSEOVER: 'mouseover', - MOUSEOUT: 'mouseout', - MOUSEMOVE: 'mousemove', - MOUSEENTER: 'mouseenter', - MOUSELEAVE: 'mouseleave', - - // Selection events. - // https://www.w3.org/TR/selection-api/ - SELECTIONCHANGE: 'selectionchange', - SELECTSTART: 'selectstart', // IE, Safari, Chrome - - // Wheel events - // http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents - WHEEL: 'wheel', - - // Key events - KEYPRESS: 'keypress', - KEYDOWN: 'keydown', - KEYUP: 'keyup', - - // Focus - BLUR: 'blur', - FOCUS: 'focus', - DEACTIVATE: 'deactivate', // IE only - // NOTE: The following two events are not stable in cross-browser usage. - // WebKit and Opera implement DOMFocusIn/Out. - // IE implements focusin/out. - // Gecko implements neither see bug at - // https://bugzilla.mozilla.org/show_bug.cgi?id=396927. - // The DOM Events Level 3 Draft deprecates DOMFocusIn in favor of focusin: - // http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html - // You can use FOCUS in Capture phase until implementations converge. - FOCUSIN: goog.userAgent.IE ? 'focusin' : 'DOMFocusIn', - FOCUSOUT: goog.userAgent.IE ? 'focusout' : 'DOMFocusOut', - - // Forms - CHANGE: 'change', - RESET: 'reset', - SELECT: 'select', - SUBMIT: 'submit', - INPUT: 'input', - PROPERTYCHANGE: 'propertychange', // IE only - - // Drag and drop - DRAGSTART: 'dragstart', - DRAG: 'drag', - DRAGENTER: 'dragenter', - DRAGOVER: 'dragover', - DRAGLEAVE: 'dragleave', - DROP: 'drop', - DRAGEND: 'dragend', - - // Touch events - // Note that other touch events exist, but we should follow the W3C list here. - // http://www.w3.org/TR/touch-events/#list-of-touchevent-types - TOUCHSTART: 'touchstart', - TOUCHMOVE: 'touchmove', - TOUCHEND: 'touchend', - TOUCHCANCEL: 'touchcancel', - - // Misc - BEFOREUNLOAD: 'beforeunload', - CONSOLEMESSAGE: 'consolemessage', - CONTEXTMENU: 'contextmenu', - DEVICEMOTION: 'devicemotion', - DEVICEORIENTATION: 'deviceorientation', - DOMCONTENTLOADED: 'DOMContentLoaded', - ERROR: 'error', - HELP: 'help', - LOAD: 'load', - LOSECAPTURE: 'losecapture', - ORIENTATIONCHANGE: 'orientationchange', - READYSTATECHANGE: 'readystatechange', - RESIZE: 'resize', - SCROLL: 'scroll', - UNLOAD: 'unload', - - // Media events - CANPLAY: 'canplay', - CANPLAYTHROUGH: 'canplaythrough', - DURATIONCHANGE: 'durationchange', - EMPTIED: 'emptied', - ENDED: 'ended', - LOADEDDATA: 'loadeddata', - LOADEDMETADATA: 'loadedmetadata', - PAUSE: 'pause', - PLAY: 'play', - PLAYING: 'playing', - RATECHANGE: 'ratechange', - SEEKED: 'seeked', - SEEKING: 'seeking', - STALLED: 'stalled', - SUSPEND: 'suspend', - TIMEUPDATE: 'timeupdate', - VOLUMECHANGE: 'volumechange', - WAITING: 'waiting', - - // Media Source Extensions events - // https://www.w3.org/TR/media-source/#mediasource-events - SOURCEOPEN: 'sourceopen', - SOURCEENDED: 'sourceended', - SOURCECLOSED: 'sourceclosed', - // https://www.w3.org/TR/media-source/#sourcebuffer-events - ABORT: 'abort', - UPDATE: 'update', - UPDATESTART: 'updatestart', - UPDATEEND: 'updateend', - - // HTML 5 History events - // See http://www.w3.org/TR/html5/browsers.html#event-definitions-0 - HASHCHANGE: 'hashchange', - PAGEHIDE: 'pagehide', - PAGESHOW: 'pageshow', - POPSTATE: 'popstate', - - // Copy and Paste - // Support is limited. Make sure it works on your favorite browser - // before using. - // http://www.quirksmode.org/dom/events/cutcopypaste.html - COPY: 'copy', - PASTE: 'paste', - CUT: 'cut', - BEFORECOPY: 'beforecopy', - BEFORECUT: 'beforecut', - BEFOREPASTE: 'beforepaste', - - // HTML5 online/offline events. - // http://www.w3.org/TR/offline-webapps/#related - ONLINE: 'online', - OFFLINE: 'offline', - - // HTML 5 worker events - MESSAGE: 'message', - CONNECT: 'connect', - - // Service Worker Events - ServiceWorkerGlobalScope context - // See https://w3c.github.io/ServiceWorker/#execution-context-events - // Note: message event defined in worker events section - INSTALL: 'install', - ACTIVATE: 'activate', - FETCH: 'fetch', - FOREIGNFETCH: 'foreignfetch', - MESSAGEERROR: 'messageerror', - - // Service Worker Events - Document context - // See https://w3c.github.io/ServiceWorker/#document-context-events - STATECHANGE: 'statechange', - UPDATEFOUND: 'updatefound', - CONTROLLERCHANGE: 'controllerchange', - - // CSS animation events. - /** @suppress {missingRequire} */ - ANIMATIONSTART: goog.events.getVendorPrefixedName_('AnimationStart'), - /** @suppress {missingRequire} */ - ANIMATIONEND: goog.events.getVendorPrefixedName_('AnimationEnd'), - /** @suppress {missingRequire} */ - ANIMATIONITERATION: goog.events.getVendorPrefixedName_('AnimationIteration'), - - // CSS transition events. Based on the browser support described at: - // https://developer.mozilla.org/en/css/css_transitions#Browser_compatibility - /** @suppress {missingRequire} */ - TRANSITIONEND: goog.events.getVendorPrefixedName_('TransitionEnd'), - - // W3C Pointer Events - // http://www.w3.org/TR/pointerevents/ - POINTERDOWN: 'pointerdown', - POINTERUP: 'pointerup', - POINTERCANCEL: 'pointercancel', - POINTERMOVE: 'pointermove', - POINTEROVER: 'pointerover', - POINTEROUT: 'pointerout', - POINTERENTER: 'pointerenter', - POINTERLEAVE: 'pointerleave', - GOTPOINTERCAPTURE: 'gotpointercapture', - LOSTPOINTERCAPTURE: 'lostpointercapture', - - // IE specific events. - // See http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx - // Note: these events will be supplanted in IE11. - MSGESTURECHANGE: 'MSGestureChange', - MSGESTUREEND: 'MSGestureEnd', - MSGESTUREHOLD: 'MSGestureHold', - MSGESTURESTART: 'MSGestureStart', - MSGESTURETAP: 'MSGestureTap', - MSGOTPOINTERCAPTURE: 'MSGotPointerCapture', - MSINERTIASTART: 'MSInertiaStart', - MSLOSTPOINTERCAPTURE: 'MSLostPointerCapture', - MSPOINTERCANCEL: 'MSPointerCancel', - MSPOINTERDOWN: 'MSPointerDown', - MSPOINTERENTER: 'MSPointerEnter', - MSPOINTERHOVER: 'MSPointerHover', - MSPOINTERLEAVE: 'MSPointerLeave', - MSPOINTERMOVE: 'MSPointerMove', - MSPOINTEROUT: 'MSPointerOut', - MSPOINTEROVER: 'MSPointerOver', - MSPOINTERUP: 'MSPointerUp', - - // Native IMEs/input tools events. - TEXT: 'text', - // The textInput event is supported in IE9+, but only in lower case. All other - // browsers use the camel-case event name. - TEXTINPUT: goog.userAgent.IE ? 'textinput' : 'textInput', - COMPOSITIONSTART: 'compositionstart', - COMPOSITIONUPDATE: 'compositionupdate', - COMPOSITIONEND: 'compositionend', - - // The beforeinput event is initially only supported in Safari. See - // https://bugs.chromium.org/p/chromium/issues/detail?id=342670 for Chrome - // implementation tracking. - BEFOREINPUT: 'beforeinput', - - // Webview tag events - // See http://developer.chrome.com/dev/apps/webview_tag.html - EXIT: 'exit', - LOADABORT: 'loadabort', - LOADCOMMIT: 'loadcommit', - LOADREDIRECT: 'loadredirect', - LOADSTART: 'loadstart', - LOADSTOP: 'loadstop', - RESPONSIVE: 'responsive', - SIZECHANGED: 'sizechanged', - UNRESPONSIVE: 'unresponsive', - - // HTML5 Page Visibility API. See details at - // {@code goog.labs.dom.PageVisibilityMonitor}. - VISIBILITYCHANGE: 'visibilitychange', - - // LocalStorage event. - STORAGE: 'storage', - - // DOM Level 2 mutation events (deprecated). - DOMSUBTREEMODIFIED: 'DOMSubtreeModified', - DOMNODEINSERTED: 'DOMNodeInserted', - DOMNODEREMOVED: 'DOMNodeRemoved', - DOMNODEREMOVEDFROMDOCUMENT: 'DOMNodeRemovedFromDocument', - DOMNODEINSERTEDINTODOCUMENT: 'DOMNodeInsertedIntoDocument', - DOMATTRMODIFIED: 'DOMAttrModified', - DOMCHARACTERDATAMODIFIED: 'DOMCharacterDataModified', - - // Print events. - BEFOREPRINT: 'beforeprint', - AFTERPRINT: 'afterprint' -}; - - -/** - * Returns one of the given pointer fallback event names in order of preference: - * 1. pointerEventName - * 2. msPointerEventName - * 3. mouseEventName - * @param {string} pointerEventName - * @param {string} msPointerEventName - * @param {string} mouseEventName - * @return {string} The supported pointer or mouse event name. - * @private - */ -goog.events.getPointerFallbackEventName_ = function( - pointerEventName, msPointerEventName, mouseEventName) { - if (goog.events.BrowserFeature.POINTER_EVENTS) { - return pointerEventName; - } - if (goog.events.BrowserFeature.MSPOINTER_EVENTS) { - return msPointerEventName; - } - return mouseEventName; -}; - - -/** - * Constants for pointer event names that fall back to corresponding mouse event - * names on unsupported platforms. These are intended to be drop-in replacements - * for corresponding values in {@code goog.events.EventType}. - * @enum {string} - */ -goog.events.PointerFallbackEventType = { - POINTERDOWN: goog.events.getPointerFallbackEventName_( - goog.events.EventType.POINTERDOWN, goog.events.EventType.MSPOINTERDOWN, - goog.events.EventType.MOUSEDOWN), - POINTERUP: goog.events.getPointerFallbackEventName_( - goog.events.EventType.POINTERUP, goog.events.EventType.MSPOINTERUP, - goog.events.EventType.MOUSEUP), - POINTERCANCEL: goog.events.getPointerFallbackEventName_( - goog.events.EventType.POINTERCANCEL, - goog.events.EventType.MSPOINTERCANCEL, - // When falling back to mouse events, there is no MOUSECANCEL equivalent - // of POINTERCANCEL. In this case POINTERUP already falls back to MOUSEUP - // which represents both UP and CANCEL. POINTERCANCEL does not fall back - // to MOUSEUP to prevent listening twice on the same event. - 'mousecancel'), // non-existent event; will never fire - POINTERMOVE: goog.events.getPointerFallbackEventName_( - goog.events.EventType.POINTERMOVE, goog.events.EventType.MSPOINTERMOVE, - goog.events.EventType.MOUSEMOVE), - POINTEROVER: goog.events.getPointerFallbackEventName_( - goog.events.EventType.POINTEROVER, goog.events.EventType.MSPOINTEROVER, - goog.events.EventType.MOUSEOVER), - POINTEROUT: goog.events.getPointerFallbackEventName_( - goog.events.EventType.POINTEROUT, goog.events.EventType.MSPOINTEROUT, - goog.events.EventType.MOUSEOUT), - POINTERENTER: goog.events.getPointerFallbackEventName_( - goog.events.EventType.POINTERENTER, goog.events.EventType.MSPOINTERENTER, - goog.events.EventType.MOUSEENTER), - POINTERLEAVE: goog.events.getPointerFallbackEventName_( - goog.events.EventType.POINTERLEAVE, goog.events.EventType.MSPOINTERLEAVE, - goog.events.EventType.MOUSELEAVE) -};
diff --git a/third_party/ink/closure/events/keycodes.js b/third_party/ink/closure/events/keycodes.js deleted file mode 100644 index 745a6995..0000000 --- a/third_party/ink/closure/events/keycodes.js +++ /dev/null
@@ -1,439 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Constant declarations for common key codes. - * - * @author eae@google.com (Emil A Eklund) - * @see ../demos/keyhandler.html - */ - -goog.provide('goog.events.KeyCodes'); - -goog.require('goog.userAgent'); - -goog.forwardDeclare('goog.events.BrowserEvent'); - - -/** - * Key codes for common characters. - * - * This list is not localized and therefore some of the key codes are not - * correct for non US keyboard layouts. See comments below. - * - * @enum {number} - */ -goog.events.KeyCodes = { - WIN_KEY_FF_LINUX: 0, - MAC_ENTER: 3, - BACKSPACE: 8, - TAB: 9, - NUM_CENTER: 12, // NUMLOCK on FF/Safari Mac - ENTER: 13, - SHIFT: 16, - CTRL: 17, - ALT: 18, - PAUSE: 19, - CAPS_LOCK: 20, - ESC: 27, - SPACE: 32, - PAGE_UP: 33, // also NUM_NORTH_EAST - PAGE_DOWN: 34, // also NUM_SOUTH_EAST - END: 35, // also NUM_SOUTH_WEST - HOME: 36, // also NUM_NORTH_WEST - LEFT: 37, // also NUM_WEST - UP: 38, // also NUM_NORTH - RIGHT: 39, // also NUM_EAST - DOWN: 40, // also NUM_SOUTH - PLUS_SIGN: 43, // NOT numpad plus - PRINT_SCREEN: 44, - INSERT: 45, // also NUM_INSERT - DELETE: 46, // also NUM_DELETE - ZERO: 48, - ONE: 49, - TWO: 50, - THREE: 51, - FOUR: 52, - FIVE: 53, - SIX: 54, - SEVEN: 55, - EIGHT: 56, - NINE: 57, - FF_SEMICOLON: 59, // Firefox (Gecko) fires this for semicolon instead of 186 - FF_EQUALS: 61, // Firefox (Gecko) fires this for equals instead of 187 - FF_DASH: 173, // Firefox (Gecko) fires this for dash instead of 189 - QUESTION_MARK: 63, // needs localization - AT_SIGN: 64, - A: 65, - B: 66, - C: 67, - D: 68, - E: 69, - F: 70, - G: 71, - H: 72, - I: 73, - J: 74, - K: 75, - L: 76, - M: 77, - N: 78, - O: 79, - P: 80, - Q: 81, - R: 82, - S: 83, - T: 84, - U: 85, - V: 86, - W: 87, - X: 88, - Y: 89, - Z: 90, - META: 91, // WIN_KEY_LEFT - WIN_KEY_RIGHT: 92, - CONTEXT_MENU: 93, - NUM_ZERO: 96, - NUM_ONE: 97, - NUM_TWO: 98, - NUM_THREE: 99, - NUM_FOUR: 100, - NUM_FIVE: 101, - NUM_SIX: 102, - NUM_SEVEN: 103, - NUM_EIGHT: 104, - NUM_NINE: 105, - NUM_MULTIPLY: 106, - NUM_PLUS: 107, - NUM_MINUS: 109, - NUM_PERIOD: 110, - NUM_DIVISION: 111, - F1: 112, - F2: 113, - F3: 114, - F4: 115, - F5: 116, - F6: 117, - F7: 118, - F8: 119, - F9: 120, - F10: 121, - F11: 122, - F12: 123, - NUMLOCK: 144, - SCROLL_LOCK: 145, - - // OS-specific media keys like volume controls and browser controls. - FIRST_MEDIA_KEY: 166, - LAST_MEDIA_KEY: 183, - - SEMICOLON: 186, // needs localization - DASH: 189, // needs localization - EQUALS: 187, // needs localization - COMMA: 188, // needs localization - PERIOD: 190, // needs localization - SLASH: 191, // needs localization - APOSTROPHE: 192, // needs localization - TILDE: 192, // needs localization - SINGLE_QUOTE: 222, // needs localization - OPEN_SQUARE_BRACKET: 219, // needs localization - BACKSLASH: 220, // needs localization - CLOSE_SQUARE_BRACKET: 221, // needs localization - WIN_KEY: 224, - MAC_FF_META: - 224, // Firefox (Gecko) fires this for the meta key instead of 91 - MAC_WK_CMD_LEFT: 91, // WebKit Left Command key fired, same as META - MAC_WK_CMD_RIGHT: 93, // WebKit Right Command key fired, different from META - WIN_IME: 229, - - // "Reserved for future use". Some programs (e.g. the SlingPlayer 2.4 ActiveX - // control) fire this as a hacky way to disable screensavers. - VK_NONAME: 252, - - // We've seen users whose machines fire this keycode at regular one - // second intervals. The common thread among these users is that - // they're all using Dell Inspiron laptops, so we suspect that this - // indicates a hardware/bios problem. - // http://en.community.dell.com/support-forums/laptop/f/3518/p/19285957/19523128.aspx - PHANTOM: 255 -}; - - -/** - * Returns false if the event does not contain a text modifying key. - * - * When it returns true, the event might be text modifying. It is infeasible to - * say for sure because of the many different keyboard layouts, so this method - * errs on the side of assuming a key event is text-modifiable if we cannot be - * certain it is not. As an example, it will return true for ctrl+a, though in - * many standard keyboard layouts that key combination would mean "select all", - * and not actually modify the text. - * - * @param {goog.events.BrowserEvent} e A key event. - * @return {boolean} Whether it's a text modifying key. - */ -goog.events.KeyCodes.isTextModifyingKeyEvent = function(e) { - if (e.altKey && !e.ctrlKey || e.metaKey || - // Function keys don't generate text - e.keyCode >= goog.events.KeyCodes.F1 && - e.keyCode <= goog.events.KeyCodes.F12) { - return false; - } - - // The following keys are quite harmless, even in combination with - // CTRL, ALT or SHIFT. - switch (e.keyCode) { - case goog.events.KeyCodes.ALT: - case goog.events.KeyCodes.CAPS_LOCK: - case goog.events.KeyCodes.CONTEXT_MENU: - case goog.events.KeyCodes.CTRL: - case goog.events.KeyCodes.DOWN: - case goog.events.KeyCodes.END: - case goog.events.KeyCodes.ESC: - case goog.events.KeyCodes.HOME: - case goog.events.KeyCodes.INSERT: - case goog.events.KeyCodes.LEFT: - case goog.events.KeyCodes.MAC_FF_META: - case goog.events.KeyCodes.META: - case goog.events.KeyCodes.NUMLOCK: - case goog.events.KeyCodes.NUM_CENTER: - case goog.events.KeyCodes.PAGE_DOWN: - case goog.events.KeyCodes.PAGE_UP: - case goog.events.KeyCodes.PAUSE: - case goog.events.KeyCodes.PHANTOM: - case goog.events.KeyCodes.PRINT_SCREEN: - case goog.events.KeyCodes.RIGHT: - case goog.events.KeyCodes.SCROLL_LOCK: - case goog.events.KeyCodes.SHIFT: - case goog.events.KeyCodes.UP: - case goog.events.KeyCodes.VK_NONAME: - case goog.events.KeyCodes.WIN_KEY: - case goog.events.KeyCodes.WIN_KEY_RIGHT: - return false; - case goog.events.KeyCodes.WIN_KEY_FF_LINUX: - return !goog.userAgent.GECKO; - default: - return e.keyCode < goog.events.KeyCodes.FIRST_MEDIA_KEY || - e.keyCode > goog.events.KeyCodes.LAST_MEDIA_KEY; - } -}; - - -/** - * Returns true if the key fires a keypress event in the current browser. - * - * Accoridng to MSDN [1] IE only fires keypress events for the following keys: - * - Letters: A - Z (uppercase and lowercase) - * - Numerals: 0 - 9 - * - Symbols: ! @ # $ % ^ & * ( ) _ - + = < [ ] { } , . / ? \ | ' ` " ~ - * - System: ESC, SPACEBAR, ENTER - * - * That's not entirely correct though, for instance there's no distinction - * between upper and lower case letters. - * - * [1] http://msdn2.microsoft.com/en-us/library/ms536939(VS.85).aspx) - * - * Safari is similar to IE, but does not fire keypress for ESC. - * - * Additionally, IE6 does not fire keydown or keypress events for letters when - * the control or alt keys are held down and the shift key is not. IE7 does - * fire keydown in these cases, though, but not keypress. - * - * @param {number} keyCode A key code. - * @param {number=} opt_heldKeyCode Key code of a currently-held key. - * @param {boolean=} opt_shiftKey Whether the shift key is held down. - * @param {boolean=} opt_ctrlKey Whether the control key is held down. - * @param {boolean=} opt_altKey Whether the alt key is held down. - * @param {boolean=} opt_metaKey Whether the meta key is held down. - * @return {boolean} Whether it's a key that fires a keypress event. - */ -goog.events.KeyCodes.firesKeyPressEvent = function( - keyCode, opt_heldKeyCode, opt_shiftKey, opt_ctrlKey, opt_altKey, - opt_metaKey) { - if (!goog.userAgent.IE && !goog.userAgent.EDGE && - !(goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525'))) { - return true; - } - - if (goog.userAgent.MAC && opt_altKey) { - return goog.events.KeyCodes.isCharacterKey(keyCode); - } - - // Alt but not AltGr which is represented as Alt+Ctrl. - if (opt_altKey && !opt_ctrlKey) { - return false; - } - - // Saves Ctrl or Alt + key for IE and WebKit 525+, which won't fire keypress. - // Non-IE browsers and WebKit prior to 525 won't get this far so no need to - // check the user agent. - if (goog.isNumber(opt_heldKeyCode)) { - opt_heldKeyCode = goog.events.KeyCodes.normalizeKeyCode(opt_heldKeyCode); - } - var heldKeyIsModifier = opt_heldKeyCode == goog.events.KeyCodes.CTRL || - opt_heldKeyCode == goog.events.KeyCodes.ALT || - goog.userAgent.MAC && opt_heldKeyCode == goog.events.KeyCodes.META; - // The Shift key blocks keypresses on Mac iff accompanied by another modifier. - var modifiedShiftKey = opt_heldKeyCode == goog.events.KeyCodes.SHIFT && - (opt_ctrlKey || opt_metaKey); - if ((!opt_shiftKey || goog.userAgent.MAC) && heldKeyIsModifier || - goog.userAgent.MAC && modifiedShiftKey) { - return false; - } - - // Some keys with Ctrl/Shift do not issue keypress in WEBKIT. - if ((goog.userAgent.WEBKIT || goog.userAgent.EDGE) && opt_ctrlKey && - opt_shiftKey) { - switch (keyCode) { - case goog.events.KeyCodes.BACKSLASH: - case goog.events.KeyCodes.OPEN_SQUARE_BRACKET: - case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET: - case goog.events.KeyCodes.TILDE: - case goog.events.KeyCodes.SEMICOLON: - case goog.events.KeyCodes.DASH: - case goog.events.KeyCodes.EQUALS: - case goog.events.KeyCodes.COMMA: - case goog.events.KeyCodes.PERIOD: - case goog.events.KeyCodes.SLASH: - case goog.events.KeyCodes.APOSTROPHE: - case goog.events.KeyCodes.SINGLE_QUOTE: - return false; - } - } - - // When Ctrl+<somekey> is held in IE, it only fires a keypress once, but it - // continues to fire keydown events as the event repeats. - if (goog.userAgent.IE && opt_ctrlKey && opt_heldKeyCode == keyCode) { - return false; - } - - switch (keyCode) { - case goog.events.KeyCodes.ENTER: - return true; - case goog.events.KeyCodes.ESC: - return !(goog.userAgent.WEBKIT || goog.userAgent.EDGE); - } - - return goog.events.KeyCodes.isCharacterKey(keyCode); -}; - - -/** - * Returns true if the key produces a character. - * This does not cover characters on non-US keyboards (Russian, Hebrew, etc.). - * - * @param {number} keyCode A key code. - * @return {boolean} Whether it's a character key. - */ -goog.events.KeyCodes.isCharacterKey = function(keyCode) { - if (keyCode >= goog.events.KeyCodes.ZERO && - keyCode <= goog.events.KeyCodes.NINE) { - return true; - } - - if (keyCode >= goog.events.KeyCodes.NUM_ZERO && - keyCode <= goog.events.KeyCodes.NUM_MULTIPLY) { - return true; - } - - if (keyCode >= goog.events.KeyCodes.A && keyCode <= goog.events.KeyCodes.Z) { - return true; - } - - // Safari sends zero key code for non-latin characters. - if ((goog.userAgent.WEBKIT || goog.userAgent.EDGE) && keyCode == 0) { - return true; - } - - switch (keyCode) { - case goog.events.KeyCodes.SPACE: - case goog.events.KeyCodes.PLUS_SIGN: - case goog.events.KeyCodes.QUESTION_MARK: - case goog.events.KeyCodes.AT_SIGN: - case goog.events.KeyCodes.NUM_PLUS: - case goog.events.KeyCodes.NUM_MINUS: - case goog.events.KeyCodes.NUM_PERIOD: - case goog.events.KeyCodes.NUM_DIVISION: - case goog.events.KeyCodes.SEMICOLON: - case goog.events.KeyCodes.FF_SEMICOLON: - case goog.events.KeyCodes.DASH: - case goog.events.KeyCodes.EQUALS: - case goog.events.KeyCodes.FF_EQUALS: - case goog.events.KeyCodes.COMMA: - case goog.events.KeyCodes.PERIOD: - case goog.events.KeyCodes.SLASH: - case goog.events.KeyCodes.APOSTROPHE: - case goog.events.KeyCodes.SINGLE_QUOTE: - case goog.events.KeyCodes.OPEN_SQUARE_BRACKET: - case goog.events.KeyCodes.BACKSLASH: - case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET: - return true; - default: - return false; - } -}; - - -/** - * Normalizes key codes from OS/Browser-specific value to the general one. - * @param {number} keyCode The native key code. - * @return {number} The normalized key code. - */ -goog.events.KeyCodes.normalizeKeyCode = function(keyCode) { - if (goog.userAgent.GECKO) { - return goog.events.KeyCodes.normalizeGeckoKeyCode(keyCode); - } else if (goog.userAgent.MAC && goog.userAgent.WEBKIT) { - return goog.events.KeyCodes.normalizeMacWebKitKeyCode(keyCode); - } else { - return keyCode; - } -}; - - -/** - * Normalizes key codes from their Gecko-specific value to the general one. - * @param {number} keyCode The native key code. - * @return {number} The normalized key code. - */ -goog.events.KeyCodes.normalizeGeckoKeyCode = function(keyCode) { - switch (keyCode) { - case goog.events.KeyCodes.FF_EQUALS: - return goog.events.KeyCodes.EQUALS; - case goog.events.KeyCodes.FF_SEMICOLON: - return goog.events.KeyCodes.SEMICOLON; - case goog.events.KeyCodes.FF_DASH: - return goog.events.KeyCodes.DASH; - case goog.events.KeyCodes.MAC_FF_META: - return goog.events.KeyCodes.META; - case goog.events.KeyCodes.WIN_KEY_FF_LINUX: - return goog.events.KeyCodes.WIN_KEY; - default: - return keyCode; - } -}; - - -/** - * Normalizes key codes from their Mac WebKit-specific value to the general one. - * @param {number} keyCode The native key code. - * @return {number} The normalized key code. - */ -goog.events.KeyCodes.normalizeMacWebKitKeyCode = function(keyCode) { - switch (keyCode) { - case goog.events.KeyCodes.MAC_WK_CMD_RIGHT: // 93 - return goog.events.KeyCodes.META; // 91 - default: - return keyCode; - } -};
diff --git a/third_party/ink/closure/events/listenable.js b/third_party/ink/closure/events/listenable.js deleted file mode 100644 index 0f29d81..0000000 --- a/third_party/ink/closure/events/listenable.js +++ /dev/null
@@ -1,338 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview An interface for a listenable JavaScript object. - * @author chrishenry@google.com (Chris Henry) - */ - -goog.provide('goog.events.Listenable'); -goog.provide('goog.events.ListenableKey'); - -/** @suppress {extraRequire} */ -goog.require('goog.events.EventId'); - -goog.forwardDeclare('goog.events.EventLike'); -goog.forwardDeclare('goog.events.EventTarget'); - - - -/** - * A listenable interface. A listenable is an object with the ability - * to dispatch/broadcast events to "event listeners" registered via - * listen/listenOnce. - * - * The interface allows for an event propagation mechanism similar - * to one offered by native browser event targets, such as - * capture/bubble mechanism, stopping propagation, and preventing - * default actions. Capture/bubble mechanism depends on the ancestor - * tree constructed via {@code #getParentEventTarget}; this tree - * must be directed acyclic graph. The meaning of default action(s) - * in preventDefault is specific to a particular use case. - * - * Implementations that do not support capture/bubble or can not have - * a parent listenable can simply not implement any ability to set the - * parent listenable (and have {@code #getParentEventTarget} return - * null). - * - * Implementation of this class can be used with or independently from - * goog.events. - * - * Implementation must call {@code #addImplementation(implClass)}. - * - * @interface - * @see goog.events - * @see http://www.w3.org/TR/DOM-Level-2-Events/events.html - */ -goog.events.Listenable = function() {}; - - -/** - * An expando property to indicate that an object implements - * goog.events.Listenable. - * - * See addImplementation/isImplementedBy. - * - * @type {string} - * @const - */ -goog.events.Listenable.IMPLEMENTED_BY_PROP = - 'closure_listenable_' + ((Math.random() * 1e6) | 0); - - -/** - * Marks a given class (constructor) as an implementation of - * Listenable, do that we can query that fact at runtime. The class - * must have already implemented the interface. - * @param {!function(new:goog.events.Listenable,...)} cls The class constructor. - * The corresponding class must have already implemented the interface. - */ -goog.events.Listenable.addImplementation = function(cls) { - cls.prototype[goog.events.Listenable.IMPLEMENTED_BY_PROP] = true; -}; - - -/** - * @param {Object} obj The object to check. - * @return {boolean} Whether a given instance implements Listenable. The - * class/superclass of the instance must call addImplementation. - */ -goog.events.Listenable.isImplementedBy = function(obj) { - return !!(obj && obj[goog.events.Listenable.IMPLEMENTED_BY_PROP]); -}; - - -/** - * Adds an event listener. A listener can only be added once to an - * object and if it is added again the key for the listener is - * returned. Note that if the existing listener is a one-off listener - * (registered via listenOnce), it will no longer be a one-off - * listener after a call to listen(). - * - * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id. - * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback - * method. - * @param {boolean=} opt_useCapture Whether to fire in capture phase - * (defaults to false). - * @param {SCOPE=} opt_listenerScope Object in whose scope to call the - * listener. - * @return {!goog.events.ListenableKey} Unique key for the listener. - * @template SCOPE,EVENTOBJ - */ -goog.events.Listenable.prototype.listen; - - -/** - * Adds an event listener that is removed automatically after the - * listener fired once. - * - * If an existing listener already exists, listenOnce will do - * nothing. In particular, if the listener was previously registered - * via listen(), listenOnce() will not turn the listener into a - * one-off listener. Similarly, if there is already an existing - * one-off listener, listenOnce does not modify the listeners (it is - * still a once listener). - * - * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id. - * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback - * method. - * @param {boolean=} opt_useCapture Whether to fire in capture phase - * (defaults to false). - * @param {SCOPE=} opt_listenerScope Object in whose scope to call the - * listener. - * @return {!goog.events.ListenableKey} Unique key for the listener. - * @template SCOPE,EVENTOBJ - */ -goog.events.Listenable.prototype.listenOnce; - - -/** - * Removes an event listener which was added with listen() or listenOnce(). - * - * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id. - * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback - * method. - * @param {boolean=} opt_useCapture Whether to fire in capture phase - * (defaults to false). - * @param {SCOPE=} opt_listenerScope Object in whose scope to call - * the listener. - * @return {boolean} Whether any listener was removed. - * @template SCOPE,EVENTOBJ - */ -goog.events.Listenable.prototype.unlisten; - - -/** - * Removes an event listener which was added with listen() by the key - * returned by listen(). - * - * @param {!goog.events.ListenableKey} key The key returned by - * listen() or listenOnce(). - * @return {boolean} Whether any listener was removed. - */ -goog.events.Listenable.prototype.unlistenByKey; - - -/** - * Dispatches an event (or event like object) and calls all listeners - * listening for events of this type. The type of the event is decided by the - * type property on the event object. - * - * If any of the listeners returns false OR calls preventDefault then this - * function will return false. If one of the capture listeners calls - * stopPropagation, then the bubble listeners won't fire. - * - * @param {goog.events.EventLike} e Event object. - * @return {boolean} If anyone called preventDefault on the event object (or - * if any of the listeners returns false) this will also return false. - */ -goog.events.Listenable.prototype.dispatchEvent; - - -/** - * Removes all listeners from this listenable. If type is specified, - * it will only remove listeners of the particular type. otherwise all - * registered listeners will be removed. - * - * @param {string=} opt_type Type of event to remove, default is to - * remove all types. - * @return {number} Number of listeners removed. - */ -goog.events.Listenable.prototype.removeAllListeners; - - -/** - * Returns the parent of this event target to use for capture/bubble - * mechanism. - * - * NOTE(chrishenry): The name reflects the original implementation of - * custom event target ({@code goog.events.EventTarget}). We decided - * that changing the name is not worth it. - * - * @return {goog.events.Listenable} The parent EventTarget or null if - * there is no parent. - */ -goog.events.Listenable.prototype.getParentEventTarget; - - -/** - * Fires all registered listeners in this listenable for the given - * type and capture mode, passing them the given eventObject. This - * does not perform actual capture/bubble. Only implementors of the - * interface should be using this. - * - * @param {string|!goog.events.EventId<EVENTOBJ>} type The type of the - * listeners to fire. - * @param {boolean} capture The capture mode of the listeners to fire. - * @param {EVENTOBJ} eventObject The event object to fire. - * @return {boolean} Whether all listeners succeeded without - * attempting to prevent default behavior. If any listener returns - * false or called goog.events.Event#preventDefault, this returns - * false. - * @template EVENTOBJ - */ -goog.events.Listenable.prototype.fireListeners; - - -/** - * Gets all listeners in this listenable for the given type and - * capture mode. - * - * @param {string|!goog.events.EventId} type The type of the listeners to fire. - * @param {boolean} capture The capture mode of the listeners to fire. - * @return {!Array<!goog.events.ListenableKey>} An array of registered - * listeners. - * @template EVENTOBJ - */ -goog.events.Listenable.prototype.getListeners; - - -/** - * Gets the goog.events.ListenableKey for the event or null if no such - * listener is in use. - * - * @param {string|!goog.events.EventId<EVENTOBJ>} type The name of the event - * without the 'on' prefix. - * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener The - * listener function to get. - * @param {boolean} capture Whether the listener is a capturing listener. - * @param {SCOPE=} opt_listenerScope Object in whose scope to call the - * listener. - * @return {goog.events.ListenableKey} the found listener or null if not found. - * @template SCOPE,EVENTOBJ - */ -goog.events.Listenable.prototype.getListener; - - -/** - * Whether there is any active listeners matching the specified - * signature. If either the type or capture parameters are - * unspecified, the function will match on the remaining criteria. - * - * @param {string|!goog.events.EventId<EVENTOBJ>=} opt_type Event type. - * @param {boolean=} opt_capture Whether to check for capture or bubble - * listeners. - * @return {boolean} Whether there is any active listeners matching - * the requested type and/or capture phase. - * @template EVENTOBJ - */ -goog.events.Listenable.prototype.hasListener; - - - -/** - * An interface that describes a single registered listener. - * @interface - */ -goog.events.ListenableKey = function() {}; - - -/** - * Counter used to create a unique key - * @type {number} - * @private - */ -goog.events.ListenableKey.counter_ = 0; - - -/** - * Reserves a key to be used for ListenableKey#key field. - * @return {number} A number to be used to fill ListenableKey#key - * field. - */ -goog.events.ListenableKey.reserveKey = function() { - return ++goog.events.ListenableKey.counter_; -}; - - -/** - * The source event target. - * @type {Object|goog.events.Listenable|goog.events.EventTarget} - */ -goog.events.ListenableKey.prototype.src; - - -/** - * The event type the listener is listening to. - * @type {string} - */ -goog.events.ListenableKey.prototype.type; - - -/** - * The listener function. - * @type {function(?):?|{handleEvent:function(?):?}|null} - */ -goog.events.ListenableKey.prototype.listener; - - -/** - * Whether the listener works on capture phase. - * @type {boolean} - */ -goog.events.ListenableKey.prototype.capture; - - -/** - * The 'this' object for the listener function's scope. - * @type {Object|undefined} - */ -goog.events.ListenableKey.prototype.handler; - - -/** - * A globally unique number to identify the key. - * @type {number} - */ -goog.events.ListenableKey.prototype.key;
diff --git a/third_party/ink/closure/events/listener.js b/third_party/ink/closure/events/listener.js deleted file mode 100644 index 282c69fc..0000000 --- a/third_party/ink/closure/events/listener.js +++ /dev/null
@@ -1,129 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Listener object. - * @author pupius@google.com (Daniel Pupius) - * @see ../demos/events.html - */ - -goog.provide('goog.events.Listener'); - -goog.require('goog.events.ListenableKey'); - - - -/** - * Simple class that stores information about a listener - * @param {function(?):?} listener Callback function. - * @param {Function} proxy Wrapper for the listener that patches the event. - * @param {EventTarget|goog.events.Listenable} src Source object for - * the event. - * @param {string} type Event type. - * @param {boolean} capture Whether in capture or bubble phase. - * @param {Object=} opt_handler Object in whose context to execute the callback. - * @implements {goog.events.ListenableKey} - * @constructor - */ -goog.events.Listener = function( - listener, proxy, src, type, capture, opt_handler) { - if (goog.events.Listener.ENABLE_MONITORING) { - this.creationStack = new Error().stack; - } - - /** @override */ - this.listener = listener; - - /** - * A wrapper over the original listener. This is used solely to - * handle native browser events (it is used to simulate the capture - * phase and to patch the event object). - * @type {Function} - */ - this.proxy = proxy; - - /** - * Object or node that callback is listening to - * @type {EventTarget|goog.events.Listenable} - */ - this.src = src; - - /** - * The event type. - * @const {string} - */ - this.type = type; - - /** - * Whether the listener is being called in the capture or bubble phase - * @const {boolean} - */ - this.capture = !!capture; - - /** - * Optional object whose context to execute the listener in - * @type {Object|undefined} - */ - this.handler = opt_handler; - - /** - * The key of the listener. - * @const {number} - * @override - */ - this.key = goog.events.ListenableKey.reserveKey(); - - /** - * Whether to remove the listener after it has been called. - * @type {boolean} - */ - this.callOnce = false; - - /** - * Whether the listener has been removed. - * @type {boolean} - */ - this.removed = false; -}; - - -/** - * @define {boolean} Whether to enable the monitoring of the - * goog.events.Listener instances. Switching on the monitoring is only - * recommended for debugging because it has a significant impact on - * performance and memory usage. If switched off, the monitoring code - * compiles down to 0 bytes. - */ -goog.define('goog.events.Listener.ENABLE_MONITORING', false); - - -/** - * If monitoring the goog.events.Listener instances is enabled, stores the - * creation stack trace of the Disposable instance. - * @type {string} - */ -goog.events.Listener.prototype.creationStack; - - -/** - * Marks this listener as removed. This also remove references held by - * this listener object (such as listener and event source). - */ -goog.events.Listener.prototype.markAsRemoved = function() { - this.removed = true; - this.listener = null; - this.proxy = null; - this.src = null; - this.handler = null; -};
diff --git a/third_party/ink/closure/events/listenermap.js b/third_party/ink/closure/events/listenermap.js deleted file mode 100644 index 30fea18..0000000 --- a/third_party/ink/closure/events/listenermap.js +++ /dev/null
@@ -1,307 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A map of listeners that provides utility functions to - * deal with listeners on an event target. Used by - * {@code goog.events.EventTarget}. - * - * WARNING: Do not use this class from outside goog.events package. - * - * @visibility {//javascript/closure/bin/sizetests:__pkg__} - * @visibility {//javascript/closure:__pkg__} - * @visibility {//javascript/closure/events:__pkg__} - * @visibility {//javascript/closure/labs/events:__pkg__} - */ - -goog.provide('goog.events.ListenerMap'); - -goog.require('goog.array'); -goog.require('goog.events.Listener'); -goog.require('goog.object'); - - - -/** - * Creates a new listener map. - * @param {EventTarget|goog.events.Listenable} src The src object. - * @constructor - * @final - */ -goog.events.ListenerMap = function(src) { - /** @type {EventTarget|goog.events.Listenable} */ - this.src = src; - - /** - * Maps of event type to an array of listeners. - * @type {!Object<string, !Array<!goog.events.Listener>>} - */ - this.listeners = {}; - - /** - * The count of types in this map that have registered listeners. - * @private {number} - */ - this.typeCount_ = 0; -}; - - -/** - * @return {number} The count of event types in this map that actually - * have registered listeners. - */ -goog.events.ListenerMap.prototype.getTypeCount = function() { - return this.typeCount_; -}; - - -/** - * @return {number} Total number of registered listeners. - */ -goog.events.ListenerMap.prototype.getListenerCount = function() { - var count = 0; - for (var type in this.listeners) { - count += this.listeners[type].length; - } - return count; -}; - - -/** - * Adds an event listener. A listener can only be added once to an - * object and if it is added again the key for the listener is - * returned. - * - * Note that a one-off listener will not change an existing listener, - * if any. On the other hand a normal listener will change existing - * one-off listener to become a normal listener. - * - * @param {string|!goog.events.EventId} type The listener event type. - * @param {!Function} listener This listener callback method. - * @param {boolean} callOnce Whether the listener is a one-off - * listener. - * @param {boolean=} opt_useCapture The capture mode of the listener. - * @param {Object=} opt_listenerScope Object in whose scope to call the - * listener. - * @return {!goog.events.ListenableKey} Unique key for the listener. - */ -goog.events.ListenerMap.prototype.add = function( - type, listener, callOnce, opt_useCapture, opt_listenerScope) { - var typeStr = type.toString(); - var listenerArray = this.listeners[typeStr]; - if (!listenerArray) { - listenerArray = this.listeners[typeStr] = []; - this.typeCount_++; - } - - var listenerObj; - var index = goog.events.ListenerMap.findListenerIndex_( - listenerArray, listener, opt_useCapture, opt_listenerScope); - if (index > -1) { - listenerObj = listenerArray[index]; - if (!callOnce) { - // Ensure that, if there is an existing callOnce listener, it is no - // longer a callOnce listener. - listenerObj.callOnce = false; - } - } else { - listenerObj = new goog.events.Listener( - listener, null, this.src, typeStr, !!opt_useCapture, opt_listenerScope); - listenerObj.callOnce = callOnce; - listenerArray.push(listenerObj); - } - return listenerObj; -}; - - -/** - * Removes a matching listener. - * @param {string|!goog.events.EventId} type The listener event type. - * @param {!Function} listener This listener callback method. - * @param {boolean=} opt_useCapture The capture mode of the listener. - * @param {Object=} opt_listenerScope Object in whose scope to call the - * listener. - * @return {boolean} Whether any listener was removed. - */ -goog.events.ListenerMap.prototype.remove = function( - type, listener, opt_useCapture, opt_listenerScope) { - var typeStr = type.toString(); - if (!(typeStr in this.listeners)) { - return false; - } - - var listenerArray = this.listeners[typeStr]; - var index = goog.events.ListenerMap.findListenerIndex_( - listenerArray, listener, opt_useCapture, opt_listenerScope); - if (index > -1) { - var listenerObj = listenerArray[index]; - listenerObj.markAsRemoved(); - goog.array.removeAt(listenerArray, index); - if (listenerArray.length == 0) { - delete this.listeners[typeStr]; - this.typeCount_--; - } - return true; - } - return false; -}; - - -/** - * Removes the given listener object. - * @param {!goog.events.ListenableKey} listener The listener to remove. - * @return {boolean} Whether the listener is removed. - */ -goog.events.ListenerMap.prototype.removeByKey = function(listener) { - var type = listener.type; - if (!(type in this.listeners)) { - return false; - } - - var removed = goog.array.remove(this.listeners[type], listener); - if (removed) { - /** @type {!goog.events.Listener} */ (listener).markAsRemoved(); - if (this.listeners[type].length == 0) { - delete this.listeners[type]; - this.typeCount_--; - } - } - return removed; -}; - - -/** - * Removes all listeners from this map. If opt_type is provided, only - * listeners that match the given type are removed. - * @param {string|!goog.events.EventId=} opt_type Type of event to remove. - * @return {number} Number of listeners removed. - */ -goog.events.ListenerMap.prototype.removeAll = function(opt_type) { - var typeStr = opt_type && opt_type.toString(); - var count = 0; - for (var type in this.listeners) { - if (!typeStr || type == typeStr) { - var listenerArray = this.listeners[type]; - for (var i = 0; i < listenerArray.length; i++) { - ++count; - listenerArray[i].markAsRemoved(); - } - delete this.listeners[type]; - this.typeCount_--; - } - } - return count; -}; - - -/** - * Gets all listeners that match the given type and capture mode. The - * returned array is a copy (but the listener objects are not). - * @param {string|!goog.events.EventId} type The type of the listeners - * to retrieve. - * @param {boolean} capture The capture mode of the listeners to retrieve. - * @return {!Array<!goog.events.ListenableKey>} An array of matching - * listeners. - */ -goog.events.ListenerMap.prototype.getListeners = function(type, capture) { - var listenerArray = this.listeners[type.toString()]; - var rv = []; - if (listenerArray) { - for (var i = 0; i < listenerArray.length; ++i) { - var listenerObj = listenerArray[i]; - if (listenerObj.capture == capture) { - rv.push(listenerObj); - } - } - } - return rv; -}; - - -/** - * Gets the goog.events.ListenableKey for the event or null if no such - * listener is in use. - * - * @param {string|!goog.events.EventId} type The type of the listener - * to retrieve. - * @param {!Function} listener The listener function to get. - * @param {boolean} capture Whether the listener is a capturing listener. - * @param {Object=} opt_listenerScope Object in whose scope to call the - * listener. - * @return {goog.events.ListenableKey} the found listener or null if not found. - */ -goog.events.ListenerMap.prototype.getListener = function( - type, listener, capture, opt_listenerScope) { - var listenerArray = this.listeners[type.toString()]; - var i = -1; - if (listenerArray) { - i = goog.events.ListenerMap.findListenerIndex_( - listenerArray, listener, capture, opt_listenerScope); - } - return i > -1 ? listenerArray[i] : null; -}; - - -/** - * Whether there is a matching listener. If either the type or capture - * parameters are unspecified, the function will match on the - * remaining criteria. - * - * @param {string|!goog.events.EventId=} opt_type The type of the listener. - * @param {boolean=} opt_capture The capture mode of the listener. - * @return {boolean} Whether there is an active listener matching - * the requested type and/or capture phase. - */ -goog.events.ListenerMap.prototype.hasListener = function( - opt_type, opt_capture) { - var hasType = goog.isDef(opt_type); - var typeStr = hasType ? opt_type.toString() : ''; - var hasCapture = goog.isDef(opt_capture); - - return goog.object.some(this.listeners, function(listenerArray, type) { - for (var i = 0; i < listenerArray.length; ++i) { - if ((!hasType || listenerArray[i].type == typeStr) && - (!hasCapture || listenerArray[i].capture == opt_capture)) { - return true; - } - } - - return false; - }); -}; - - -/** - * Finds the index of a matching goog.events.Listener in the given - * listenerArray. - * @param {!Array<!goog.events.Listener>} listenerArray Array of listener. - * @param {!Function} listener The listener function. - * @param {boolean=} opt_useCapture The capture flag for the listener. - * @param {Object=} opt_listenerScope The listener scope. - * @return {number} The index of the matching listener within the - * listenerArray. - * @private - */ -goog.events.ListenerMap.findListenerIndex_ = function( - listenerArray, listener, opt_useCapture, opt_listenerScope) { - for (var i = 0; i < listenerArray.length; ++i) { - var listenerObj = listenerArray[i]; - if (!listenerObj.removed && listenerObj.listener == listener && - listenerObj.capture == !!opt_useCapture && - listenerObj.handler == opt_listenerScope) { - return i; - } - } - return -1; -};
diff --git a/third_party/ink/closure/events/wheelevent.js b/third_party/ink/closure/events/wheelevent.js deleted file mode 100644 index 770724a..0000000 --- a/third_party/ink/closure/events/wheelevent.js +++ /dev/null
@@ -1,170 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview This class aims to smooth out inconsistencies between browser - * handling of wheel events by providing an event that is similar to that - * defined in the standard, but also easier to consume. - * - * It is based upon the WheelEvent, which allows for up to 3 dimensional - * scrolling events that come in units of either pixels, lines or pages. - * http://www.w3.org/TR/2014/WD-DOM-Level-3-Events-20140925/#interface-WheelEvent - * - * The significant difference here is that it also provides reasonable pixel - * deltas for clients that do not want to treat line and page scrolling events - * specially. - * - * Clients of this code should be aware that some input devices only fire a few - * discrete events (such as a mouse wheel without acceleration) whereas some can - * generate a large number of events for a single interaction (such as a - * touchpad with acceleration). There is no signal in the events to reliably - * distinguish between these. - * - * @author joshuawilder@google.com (Joshua Wilder) - * @see ../demos/wheelhandler.html - */ - -goog.provide('goog.events.WheelEvent'); - -goog.require('goog.asserts'); -goog.require('goog.events.BrowserEvent'); - - - -/** - * A common class for wheel events. This is used with the WheelHandler. - * - * @param {Event} browserEvent Browser event object. - * @param {goog.events.WheelEvent.DeltaMode} deltaMode The delta mode units of - * the wheel event. - * @param {number} deltaX The number of delta units the user in the X axis. - * @param {number} deltaY The number of delta units the user in the Y axis. - * @param {number} deltaZ The number of delta units the user in the Z axis. - * @constructor - * @extends {goog.events.BrowserEvent} - * @final - */ -goog.events.WheelEvent = function( - browserEvent, deltaMode, deltaX, deltaY, deltaZ) { - goog.events.WheelEvent.base(this, 'constructor', browserEvent); - goog.asserts.assert(browserEvent, 'Expecting a non-null browserEvent'); - - /** @type {goog.events.WheelEvent.EventType} */ - this.type = goog.events.WheelEvent.EventType.WHEEL; - - /** - * An enum corresponding to the units of this event. - * @type {goog.events.WheelEvent.DeltaMode} - */ - this.deltaMode = deltaMode; - - /** - * The number of delta units in the X axis. - * @type {number} - */ - this.deltaX = deltaX; - - /** - * The number of delta units in the Y axis. - * @type {number} - */ - this.deltaY = deltaY; - - /** - * The number of delta units in the Z axis. - * @type {number} - */ - this.deltaZ = deltaZ; - - // Ratio between delta and pixel values. - var pixelRatio = 1; // Value for DeltaMode.PIXEL - switch (deltaMode) { - case goog.events.WheelEvent.DeltaMode.PAGE: - pixelRatio *= goog.events.WheelEvent.PIXELS_PER_PAGE_; - break; - case goog.events.WheelEvent.DeltaMode.LINE: - pixelRatio *= goog.events.WheelEvent.PIXELS_PER_LINE_; - break; - } - - /** - * The number of delta pixels in the X axis. Code that doesn't want to handle - * different deltaMode units can just look here. - * @type {number} - */ - this.pixelDeltaX = this.deltaX * pixelRatio; - - /** - * The number of pixels in the Y axis. Code that doesn't want to - * handle different deltaMode units can just look here. - * @type {number} - */ - this.pixelDeltaY = this.deltaY * pixelRatio; - - /** - * The number of pixels scrolled in the Z axis. Code that doesn't want to - * handle different deltaMode units can just look here. - * @type {number} - */ - this.pixelDeltaZ = this.deltaZ * pixelRatio; -}; -goog.inherits(goog.events.WheelEvent, goog.events.BrowserEvent); - - -/** - * Enum type for the events fired by the wheel handler. - * @enum {string} - */ -goog.events.WheelEvent.EventType = { - /** The user has provided wheel-based input. */ - WHEEL: 'wheel' -}; - - -/** - * Units for the deltas in a WheelEvent. - * @enum {number} - */ -goog.events.WheelEvent.DeltaMode = { - /** The units are in pixels. From DOM_DELTA_PIXEL. */ - PIXEL: 0, - /** The units are in lines. From DOM_DELTA_LINE. */ - LINE: 1, - /** The units are in pages. From DOM_DELTA_PAGE. */ - PAGE: 2 -}; - - -/** - * A conversion number between line scroll units and pixel scroll units. The - * actual value per line can vary a lot between devices and font sizes. This - * number can not be perfect, but it should be reasonable for converting lines - * scroll events into pixels. - * @const {number} - * @private - */ -goog.events.WheelEvent.PIXELS_PER_LINE_ = 15; - - -/** - * A conversion number between page scroll units and pixel scroll units. The - * actual value per page can vary a lot as many different devices have different - * screen sizes, and the window might not be taking up the full screen. This - * number can not be perfect, but it should be reasonable for converting page - * scroll events into pixels. - * @const {number} - * @private - */ -goog.events.WheelEvent.PIXELS_PER_PAGE_ = - 30 * goog.events.WheelEvent.PIXELS_PER_LINE_;
diff --git a/third_party/ink/closure/format/format.js b/third_party/ink/closure/format/format.js deleted file mode 100644 index b938905..0000000 --- a/third_party/ink/closure/format/format.js +++ /dev/null
@@ -1,503 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Provides utility functions for formatting strings, numbers etc. - * - * @author pupius@google.com (Daniel Pupius) - */ - -goog.provide('goog.format'); - -goog.require('goog.i18n.GraphemeBreak'); -goog.require('goog.string'); -goog.require('goog.userAgent'); - - -/** - * Formats a number of bytes in human readable form. - * 54, 450K, 1.3M, 5G etc. - * @param {number} bytes The number of bytes to show. - * @param {number=} opt_decimals The number of decimals to use. Defaults to 2. - * @return {string} The human readable form of the byte size. - */ -goog.format.fileSize = function(bytes, opt_decimals) { - return goog.format.numBytesToString(bytes, opt_decimals, false); -}; - - -/** - * Checks whether string value containing scaling units (K, M, G, T, P, m, - * u, n) can be converted to a number. - * - * Where there is a decimal, there must be a digit to the left of the - * decimal point. - * - * Negative numbers are valid. - * - * Examples: - * 0, 1, 1.0, 10.4K, 2.3M, -0.3P, 1.2m - * - * @param {string} val String value to check. - * @return {boolean} True if string could be converted to a numeric value. - */ -goog.format.isConvertableScaledNumber = function(val) { - return goog.format.SCALED_NUMERIC_RE_.test(val); -}; - - -/** - * Converts a string to numeric value, taking into account the units. - * If string ends in 'B', use binary conversion. - * @param {string} stringValue String to be converted to numeric value. - * @return {number} Numeric value for string. - */ -goog.format.stringToNumericValue = function(stringValue) { - if (goog.string.endsWith(stringValue, 'B')) { - return goog.format.stringToNumericValue_( - stringValue, goog.format.NUMERIC_SCALES_BINARY_); - } - return goog.format.stringToNumericValue_( - stringValue, goog.format.NUMERIC_SCALES_SI_); -}; - - -/** - * Converts a string to number of bytes, taking into account the units. - * Binary conversion. - * @param {string} stringValue String to be converted to numeric value. - * @return {number} Numeric value for string. - */ -goog.format.stringToNumBytes = function(stringValue) { - return goog.format.stringToNumericValue_( - stringValue, goog.format.NUMERIC_SCALES_BINARY_); -}; - - -/** - * Converts a numeric value to string representation. SI conversion. - * @param {number} val Value to be converted. - * @param {number=} opt_decimals The number of decimals to use. Defaults to 2. - * @return {string} String representation of number. - */ -goog.format.numericValueToString = function(val, opt_decimals) { - return goog.format.numericValueToString_( - val, goog.format.NUMERIC_SCALES_SI_, opt_decimals); -}; - - -/** - * Converts number of bytes to string representation. Binary conversion. - * Default is to return the additional 'B' suffix only for scales greater than - * 1K, e.g. '10.5KB' to minimize confusion with counts that are scaled by powers - * of 1000. Otherwise, suffix is empty string. - * @param {number} val Value to be converted. - * @param {number=} opt_decimals The number of decimals to use. Defaults to 2. - * @param {boolean=} opt_suffix If true, include trailing 'B' in returned - * string. Default is true. - * @param {boolean=} opt_useSeparator If true, number and scale will be - * separated by a no break space. Default is false. - * @return {string} String representation of number of bytes. - */ -goog.format.numBytesToString = function( - val, opt_decimals, opt_suffix, opt_useSeparator) { - var suffix = ''; - if (!goog.isDef(opt_suffix) || opt_suffix) { - suffix = 'B'; - } - return goog.format.numericValueToString_( - val, goog.format.NUMERIC_SCALES_BINARY_, opt_decimals, suffix, - opt_useSeparator); -}; - - -/** - * Converts a string to numeric value, taking into account the units. - * @param {string} stringValue String to be converted to numeric value. - * @param {Object} conversion Dictionary of conversion scales. - * @return {number} Numeric value for string. If it cannot be converted, - * returns NaN. - * @private - */ -goog.format.stringToNumericValue_ = function(stringValue, conversion) { - var match = stringValue.match(goog.format.SCALED_NUMERIC_RE_); - if (!match) { - return NaN; - } - var val = Number(match[1]) * conversion[match[2]]; - return val; -}; - - -/** - * Converts a numeric value to string, using specified conversion - * scales. - * @param {number} val Value to be converted. - * @param {Object} conversion Dictionary of scaling factors. - * @param {number=} opt_decimals The number of decimals to use. Default is 2. - * @param {string=} opt_suffix Optional suffix to append. - * @param {boolean=} opt_useSeparator If true, number and scale will be - * separated by a space. Default is false. - * @return {string} The human readable form of the byte size. - * @private - */ -goog.format.numericValueToString_ = function( - val, conversion, opt_decimals, opt_suffix, opt_useSeparator) { - var prefixes = goog.format.NUMERIC_SCALE_PREFIXES_; - var orig_val = val; - var symbol = ''; - var separator = ''; - var scale = 1; - if (val < 0) { - val = -val; - } - for (var i = 0; i < prefixes.length; i++) { - var unit = prefixes[i]; - scale = conversion[unit]; - if (val >= scale || (scale <= 1 && val > 0.1 * scale)) { - // Treat values less than 1 differently, allowing 0.5 to be "0.5" rather - // than "500m" - symbol = unit; - break; - } - } - if (!symbol) { - scale = 1; - } else { - if (opt_suffix) { - symbol += opt_suffix; - } - if (opt_useSeparator) { - separator = ' '; - } - } - var ex = Math.pow(10, goog.isDef(opt_decimals) ? opt_decimals : 2); - return Math.round(orig_val / scale * ex) / ex + separator + symbol; -}; - - -/** - * Regular expression for detecting scaling units, such as K, M, G, etc. for - * converting a string representation to a numeric value. - * - * Also allow 'k' to be aliased to 'K'. These could be used for SI (powers - * of 1000) or Binary (powers of 1024) conversions. - * - * Also allow final 'B' to be interpreted as byte-count, implicitly triggering - * binary conversion (e.g., '10.2MB'). - * - * @type {RegExp} - * @private - */ -goog.format.SCALED_NUMERIC_RE_ = - /^([-]?\d+\.?\d*)([K,M,G,T,P,E,Z,Y,k,m,u,n]?)[B]?$/; - - -/** - * Ordered list of scaling prefixes in decreasing order. - * @private {Array<string>} - */ -goog.format.NUMERIC_SCALE_PREFIXES_ = - ['Y', 'Z', 'E', 'P', 'T', 'G', 'M', 'K', '', 'm', 'u', 'n']; - - -/** - * Scaling factors for conversion of numeric value to string. SI conversion. - * @type {Object} - * @private - */ -goog.format.NUMERIC_SCALES_SI_ = { - '': 1, - 'n': 1e-9, - 'u': 1e-6, - 'm': 1e-3, - 'k': 1e3, - 'K': 1e3, - 'M': 1e6, - 'G': 1e9, - 'T': 1e12, - 'P': 1e15, - 'E': 1e18, - 'Z': 1e21, - 'Y': 1e24 -}; - - -/** - * Scaling factors for conversion of numeric value to string. Binary - * conversion. - * @type {Object} - * @private - */ -goog.format.NUMERIC_SCALES_BINARY_ = { - '': 1, - 'n': Math.pow(1024, -3), - 'u': Math.pow(1024, -2), - 'm': 1.0 / 1024, - 'k': 1024, - 'K': 1024, - 'M': Math.pow(1024, 2), - 'G': Math.pow(1024, 3), - 'T': Math.pow(1024, 4), - 'P': Math.pow(1024, 5), - 'E': Math.pow(1024, 6), - 'Z': Math.pow(1024, 7), - 'Y': Math.pow(1024, 8) -}; - - -/** - * First Unicode code point that has the Mark property. - * @type {number} - * @private - */ -goog.format.FIRST_GRAPHEME_EXTEND_ = 0x300; - - -/** - * Returns true if and only if given character should be treated as a breaking - * space. All ASCII control characters, the main Unicode range of spacing - * characters (U+2000 to U+200B inclusive except for U+2007), and several other - * Unicode space characters are treated as breaking spaces. - * @param {number} charCode The character code under consideration. - * @return {boolean} True if the character is a breaking space. - * @private - */ -goog.format.isTreatedAsBreakingSpace_ = function(charCode) { - return (charCode <= goog.format.WbrToken_.SPACE) || - (charCode >= 0x1000 && - ((charCode >= 0x2000 && charCode <= 0x2006) || - (charCode >= 0x2008 && charCode <= 0x200B) || charCode == 0x1680 || - charCode == 0x180E || charCode == 0x2028 || charCode == 0x2029 || - charCode == 0x205f || charCode == 0x3000)); -}; - - -/** - * Returns true if and only if given character is an invisible formatting - * character. - * @param {number} charCode The character code under consideration. - * @return {boolean} True if the character is an invisible formatting character. - * @private - */ -goog.format.isInvisibleFormattingCharacter_ = function(charCode) { - // See: http://unicode.org/charts/PDF/U2000.pdf - return (charCode >= 0x200C && charCode <= 0x200F) || - (charCode >= 0x202A && charCode <= 0x202E); -}; - - -/** - * Inserts word breaks into an HTML string at a given interval. The counter is - * reset if a space or a character which behaves like a space is encountered, - * but it isn't incremented if an invisible formatting character is encountered. - * WBRs aren't inserted into HTML tags or entities. Entities count towards the - * character count, HTML tags do not. - * - * With common strings aliased, objects allocations are constant based on the - * length of the string: N + 3. This guarantee does not hold if the string - * contains an element >= U+0300 and hasGraphemeBreak is non-trivial. - * - * @param {string} str HTML to insert word breaks into. - * @param {function(number, number, boolean): boolean} hasGraphemeBreak A - * function determining if there is a grapheme break between two characters, - * in the same signature as goog.i18n.GraphemeBreak.hasGraphemeBreak. - * @param {number=} opt_maxlen Maximum length after which to ensure - * there is a break. Default is 10 characters. - * @return {string} The string including word breaks. - * @private - */ -goog.format.insertWordBreaksGeneric_ = function( - str, hasGraphemeBreak, opt_maxlen) { - var maxlen = opt_maxlen || 10; - if (maxlen > str.length) return str; - - var rv = []; - var n = 0; // The length of the current token - - // This will contain the ampersand or less-than character if one of the - // two has been seen; otherwise, the value is zero. - var nestingCharCode = 0; - - // First character position from input string that has not been outputted. - var lastDumpPosition = 0; - - var charCode = 0; - for (var i = 0; i < str.length; i++) { - // Using charCodeAt versus charAt avoids allocating new string objects. - var lastCharCode = charCode; - charCode = str.charCodeAt(i); - - // Don't add a WBR before characters that might be grapheme extending. - var isPotentiallyGraphemeExtending = - charCode >= goog.format.FIRST_GRAPHEME_EXTEND_ && - !hasGraphemeBreak(lastCharCode, charCode, true); - - // Don't add a WBR at the end of a word. For the purposes of determining - // work breaks, all ASCII control characters and some commonly encountered - // Unicode spacing characters are treated as breaking spaces. - if (n >= maxlen && !goog.format.isTreatedAsBreakingSpace_(charCode) && - !isPotentiallyGraphemeExtending) { - // Flush everything seen so far, and append a word break. - rv.push(str.substring(lastDumpPosition, i), goog.format.WORD_BREAK_HTML); - lastDumpPosition = i; - n = 0; - } - - if (!nestingCharCode) { - // Not currently within an HTML tag or entity - - if (charCode == goog.format.WbrToken_.LT || - charCode == goog.format.WbrToken_.AMP) { - // Entering an HTML Entity '&' or open tag '<' - nestingCharCode = charCode; - } else if (goog.format.isTreatedAsBreakingSpace_(charCode)) { - // A space or control character -- reset the token length - n = 0; - } else if (!goog.format.isInvisibleFormattingCharacter_(charCode)) { - // A normal flow character - increment. For grapheme extending - // characters, this is not *technically* a new character. However, - // since the grapheme break detector might be overly conservative, - // we have to continue incrementing, or else we won't even be able - // to add breaks when we get to things like punctuation. For the - // case where we have a full grapheme break detector, it is okay if - // we occasionally break slightly early. - n++; - } - } else if ( - charCode == goog.format.WbrToken_.GT && - nestingCharCode == goog.format.WbrToken_.LT) { - // Leaving an HTML tag, treat the tag as zero-length - nestingCharCode = 0; - } else if ( - charCode == goog.format.WbrToken_.SEMI_COLON && - nestingCharCode == goog.format.WbrToken_.AMP) { - // Leaving an HTML entity, treat it as length one - nestingCharCode = 0; - n++; - } - } - - // Take care of anything we haven't flushed so far. - rv.push(str.substr(lastDumpPosition)); - - return rv.join(''); -}; - - -/** - * Inserts word breaks into an HTML string at a given interval. - * - * This method is as aggressive as possible, using a full table of Unicode - * characters where it is legal to insert word breaks; however, this table - * comes at a 2.5k pre-gzip (~1k post-gzip) size cost. Consider using - * insertWordBreaksBasic to minimize the size impact. - * - * @param {string} str HTML to insert word breaks into. - * @param {number=} opt_maxlen Maximum length after which to ensure there is a - * break. Default is 10 characters. - * @return {string} The string including word breaks. - * @deprecated Prefer wrapping with CSS word-wrap: break-word. - */ -goog.format.insertWordBreaks = function(str, opt_maxlen) { - return goog.format.insertWordBreaksGeneric_( - str, goog.i18n.GraphemeBreak.hasGraphemeBreak, opt_maxlen); -}; - - -/** - * Determines conservatively if a character has a Grapheme break. - * - * Conforms to a similar signature as goog.i18n.GraphemeBreak, but is overly - * conservative, returning true only for characters in common scripts that - * are simple to account for. - * - * @param {number} lastCharCode The previous character code. Ignored. - * @param {number} charCode The character code under consideration. It must be - * at least \u0300 as a precondition -- this case is covered by - * insertWordBreaksGeneric_. - * @param {boolean=} opt_extended Ignored, to conform with the interface. - * @return {boolean} Whether it is one of the recognized subsets of characters - * with a grapheme break. - * @private - */ -goog.format.conservativelyHasGraphemeBreak_ = function( - lastCharCode, charCode, opt_extended) { - // Return false for everything except the most common Cyrillic characters. - // Don't worry about Latin characters, because insertWordBreaksGeneric_ - // itself already handles those. - // TODO(gboyer): Also account for Greek, Armenian, and Georgian if it is - // simple to do so. - return charCode >= 0x400 && charCode < 0x523; -}; - - -// TODO(gboyer): Consider using a compile-time flag to switch implementations -// rather than relying on the developers to toggle implementations. -/** - * Inserts word breaks into an HTML string at a given interval. - * - * This method is less aggressive than insertWordBreaks, only inserting - * breaks next to punctuation and between Latin or Cyrillic characters. - * However, this is good enough for the common case of URLs. It also - * works for all Latin and Cyrillic languages, plus CJK has no need for word - * breaks. When this method is used, goog.i18n.GraphemeBreak may be dead - * code eliminated. - * - * @param {string} str HTML to insert word breaks into. - * @param {number=} opt_maxlen Maximum length after which to ensure there is a - * break. Default is 10 characters. - * @return {string} The string including word breaks. - * @deprecated Prefer wrapping with CSS word-wrap: break-word. - */ -goog.format.insertWordBreaksBasic = function(str, opt_maxlen) { - return goog.format.insertWordBreaksGeneric_( - str, goog.format.conservativelyHasGraphemeBreak_, opt_maxlen); -}; - - -/** - * True iff the current userAgent is IE8 or above. - * @type {boolean} - * @private - */ -goog.format.IS_IE8_OR_ABOVE_ = - goog.userAgent.IE && goog.userAgent.isVersionOrHigher(8); - - -/** - * Constant for the WBR replacement used by insertWordBreaks. Safari requires - * <wbr></wbr>, Opera needs the ­ entity, though this will give a visible - * hyphen at breaks. IE8 uses a zero width space. - * Other browsers just use <wbr>. - * @type {string} - */ -goog.format.WORD_BREAK_HTML = - goog.userAgent.WEBKIT ? '<wbr></wbr>' : goog.userAgent.OPERA ? - '­' : - goog.format.IS_IE8_OR_ABOVE_ ? '​' : '<wbr>'; - - -/** - * Tokens used within insertWordBreaks. - * @private - * @enum {number} - */ -goog.format.WbrToken_ = { - LT: 60, // '<'.charCodeAt(0) - GT: 62, // '>'.charCodeAt(0) - AMP: 38, // '&'.charCodeAt(0) - SEMI_COLON: 59, // ';'.charCodeAt(0) - SPACE: 32 // ' '.charCodeAt(0) -};
diff --git a/third_party/ink/closure/fs/url.js b/third_party/ink/closure/fs/url.js deleted file mode 100644 index 1204908..0000000 --- a/third_party/ink/closure/fs/url.js +++ /dev/null
@@ -1,106 +0,0 @@ -// Copyright 2015 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Wrapper for URL and its createObjectUrl and revokeObjectUrl - * methods that are part of the HTML5 File API. - */ - -goog.provide('goog.fs.url'); - - -/** - * Creates a blob URL for a blob object. - * Throws an error if the browser does not support Object Urls. - * - * @param {!Blob} blob The object for which to create the URL. - * @return {string} The URL for the object. - */ -goog.fs.url.createObjectUrl = function(blob) { - return goog.fs.url.getUrlObject_().createObjectURL(blob); -}; - - -/** - * Revokes a URL created by {@link goog.fs.url.createObjectUrl}. - * Throws an error if the browser does not support Object Urls. - * - * @param {string} url The URL to revoke. - */ -goog.fs.url.revokeObjectUrl = function(url) { - goog.fs.url.getUrlObject_().revokeObjectURL(url); -}; - - -/** - * @typedef {{createObjectURL: (function(!Blob): string), - * revokeObjectURL: function(string): void}} - */ -goog.fs.url.UrlObject_; - - -/** - * Get the object that has the createObjectURL and revokeObjectURL functions for - * this browser. - * - * @return {goog.fs.url.UrlObject_} The object for this browser. - * @private - */ -goog.fs.url.getUrlObject_ = function() { - var urlObject = goog.fs.url.findUrlObject_(); - if (urlObject != null) { - return urlObject; - } else { - throw new Error('This browser doesn\'t seem to support blob URLs'); - } -}; - - -/** - * Finds the object that has the createObjectURL and revokeObjectURL functions - * for this browser. - * - * @return {?goog.fs.url.UrlObject_} The object for this browser or null if the - * browser does not support Object Urls. - * @private - */ -goog.fs.url.findUrlObject_ = function() { - // This is what the spec says to do - // http://dev.w3.org/2006/webapi/FileAPI/#dfn-createObjectURL - if (goog.isDef(goog.global.URL) && - goog.isDef(goog.global.URL.createObjectURL)) { - return /** @type {goog.fs.url.UrlObject_} */ (goog.global.URL); - // This is what Chrome does (as of 10.0.648.6 dev) - } else if ( - goog.isDef(goog.global.webkitURL) && - goog.isDef(goog.global.webkitURL.createObjectURL)) { - return /** @type {goog.fs.url.UrlObject_} */ (goog.global.webkitURL); - // This is what the spec used to say to do - } else if (goog.isDef(goog.global.createObjectURL)) { - return /** @type {goog.fs.url.UrlObject_} */ (goog.global); - } else { - return null; - } -}; - - -/** - * Checks whether this browser supports Object Urls. If not, calls to - * createObjectUrl and revokeObjectUrl will result in an error. - * - * @return {boolean} True if this browser supports Object Urls. - */ -goog.fs.url.browserSupportsObjectUrls = function() { - return goog.fs.url.findUrlObject_() != null; -};
diff --git a/third_party/ink/closure/functions/functions.js b/third_party/ink/closure/functions/functions.js deleted file mode 100644 index f735888..0000000 --- a/third_party/ink/closure/functions/functions.js +++ /dev/null
@@ -1,485 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for creating functions. Loosely inspired by the - * java classes: http://goo.gl/GM0Hmu and http://goo.gl/6k7nI8. - * - * @author nicksantos@google.com (Nick Santos) - */ - - -goog.provide('goog.functions'); - - -/** - * Creates a function that always returns the same value. - * @param {T} retValue The value to return. - * @return {function():T} The new function. - * @template T - */ -goog.functions.constant = function(retValue) { - return function() { return retValue; }; -}; - - -/** - * Always returns false. - * @type {function(...): boolean} - */ -goog.functions.FALSE = goog.functions.constant(false); - - -/** - * Always returns true. - * @type {function(...): boolean} - */ -goog.functions.TRUE = goog.functions.constant(true); - - -/** - * Always returns NULL. - * @type {function(...): null} - */ -goog.functions.NULL = goog.functions.constant(null); - - -/** - * A simple function that returns the first argument of whatever is passed - * into it. - * @param {T=} opt_returnValue The single value that will be returned. - * @param {...*} var_args Optional trailing arguments. These are ignored. - * @return {T} The first argument passed in, or undefined if nothing was passed. - * @template T - */ -goog.functions.identity = function(opt_returnValue, var_args) { - return opt_returnValue; -}; - - -/** - * Creates a function that always throws an error with the given message. - * @param {string} message The error message. - * @return {!Function} The error-throwing function. - */ -goog.functions.error = function(message) { - return function() { - throw new Error(message); - }; -}; - - -/** - * Creates a function that throws the given object. - * @param {*} err An object to be thrown. - * @return {!Function} The error-throwing function. - */ -goog.functions.fail = function(err) { - return function() { throw err; }; -}; - - -/** - * Given a function, create a function that keeps opt_numArgs arguments and - * silently discards all additional arguments. - * @param {Function} f The original function. - * @param {number=} opt_numArgs The number of arguments to keep. Defaults to 0. - * @return {!Function} A version of f that only keeps the first opt_numArgs - * arguments. - */ -goog.functions.lock = function(f, opt_numArgs) { - opt_numArgs = opt_numArgs || 0; - return function() { - return f.apply(this, Array.prototype.slice.call(arguments, 0, opt_numArgs)); - }; -}; - - -/** - * Creates a function that returns its nth argument. - * @param {number} n The position of the return argument. - * @return {!Function} A new function. - */ -goog.functions.nth = function(n) { - return function() { return arguments[n]; }; -}; - - -/** - * Like goog.partial(), except that arguments are added after arguments to the - * returned function. - * - * Usage: - * function f(arg1, arg2, arg3, arg4) { ... } - * var g = goog.functions.partialRight(f, arg3, arg4); - * g(arg1, arg2); - * - * @param {!Function} fn A function to partially apply. - * @param {...*} var_args Additional arguments that are partially applied to fn - * at the end. - * @return {!Function} A partially-applied form of the function goog.partial() - * was invoked as a method of. - */ -goog.functions.partialRight = function(fn, var_args) { - var rightArgs = Array.prototype.slice.call(arguments, 1); - return function() { - var newArgs = Array.prototype.slice.call(arguments); - newArgs.push.apply(newArgs, rightArgs); - return fn.apply(this, newArgs); - }; -}; - - -/** - * Given a function, create a new function that swallows its return value - * and replaces it with a new one. - * @param {Function} f A function. - * @param {T} retValue A new return value. - * @return {function(...?):T} A new function. - * @template T - */ -goog.functions.withReturnValue = function(f, retValue) { - return goog.functions.sequence(f, goog.functions.constant(retValue)); -}; - - -/** - * Creates a function that returns whether its argument equals the given value. - * - * Example: - * var key = goog.object.findKey(obj, goog.functions.equalTo('needle')); - * - * @param {*} value The value to compare to. - * @param {boolean=} opt_useLooseComparison Whether to use a loose (==) - * comparison rather than a strict (===) one. Defaults to false. - * @return {function(*):boolean} The new function. - */ -goog.functions.equalTo = function(value, opt_useLooseComparison) { - return function(other) { - return opt_useLooseComparison ? (value == other) : (value === other); - }; -}; - - -/** - * Creates the composition of the functions passed in. - * For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)). - * @param {function(...?):T} fn The final function. - * @param {...Function} var_args A list of functions. - * @return {function(...?):T} The composition of all inputs. - * @template T - */ -goog.functions.compose = function(fn, var_args) { - var functions = arguments; - var length = functions.length; - return function() { - var result; - if (length) { - result = functions[length - 1].apply(this, arguments); - } - - for (var i = length - 2; i >= 0; i--) { - result = functions[i].call(this, result); - } - return result; - }; -}; - - -/** - * Creates a function that calls the functions passed in in sequence, and - * returns the value of the last function. For example, - * (goog.functions.sequence(f, g))(x) is equivalent to f(x),g(x). - * @param {...Function} var_args A list of functions. - * @return {!Function} A function that calls all inputs in sequence. - */ -goog.functions.sequence = function(var_args) { - var functions = arguments; - var length = functions.length; - return function() { - var result; - for (var i = 0; i < length; i++) { - result = functions[i].apply(this, arguments); - } - return result; - }; -}; - - -/** - * Creates a function that returns true if each of its components evaluates - * to true. The components are evaluated in order, and the evaluation will be - * short-circuited as soon as a function returns false. - * For example, (goog.functions.and(f, g))(x) is equivalent to f(x) && g(x). - * @param {...Function} var_args A list of functions. - * @return {function(...?):boolean} A function that ANDs its component - * functions. - */ -goog.functions.and = function(var_args) { - var functions = arguments; - var length = functions.length; - return function() { - for (var i = 0; i < length; i++) { - if (!functions[i].apply(this, arguments)) { - return false; - } - } - return true; - }; -}; - - -/** - * Creates a function that returns true if any of its components evaluates - * to true. The components are evaluated in order, and the evaluation will be - * short-circuited as soon as a function returns true. - * For example, (goog.functions.or(f, g))(x) is equivalent to f(x) || g(x). - * @param {...Function} var_args A list of functions. - * @return {function(...?):boolean} A function that ORs its component - * functions. - */ -goog.functions.or = function(var_args) { - var functions = arguments; - var length = functions.length; - return function() { - for (var i = 0; i < length; i++) { - if (functions[i].apply(this, arguments)) { - return true; - } - } - return false; - }; -}; - - -/** - * Creates a function that returns the Boolean opposite of a provided function. - * For example, (goog.functions.not(f))(x) is equivalent to !f(x). - * @param {!Function} f The original function. - * @return {function(...?):boolean} A function that delegates to f and returns - * opposite. - */ -goog.functions.not = function(f) { - return function() { return !f.apply(this, arguments); }; -}; - - -/** - * Generic factory function to construct an object given the constructor - * and the arguments. Intended to be bound to create object factories. - * - * Example: - * - * var factory = goog.partial(goog.functions.create, Class); - * - * @param {function(new:T, ...)} constructor The constructor for the Object. - * @param {...*} var_args The arguments to be passed to the constructor. - * @return {T} A new instance of the class given in {@code constructor}. - * @template T - */ -goog.functions.create = function(constructor, var_args) { - /** - * @constructor - * @final - */ - var temp = function() {}; - temp.prototype = constructor.prototype; - - // obj will have constructor's prototype in its chain and - // 'obj instanceof constructor' will be true. - var obj = new temp(); - - // obj is initialized by constructor. - // arguments is only array-like so lacks shift(), but can be used with - // the Array prototype function. - constructor.apply(obj, Array.prototype.slice.call(arguments, 1)); - return obj; -}; - - -/** - * @define {boolean} Whether the return value cache should be used. - * This should only be used to disable caches when testing. - */ -goog.define('goog.functions.CACHE_RETURN_VALUE', true); - - -/** - * Gives a wrapper function that caches the return value of a parameterless - * function when first called. - * - * When called for the first time, the given function is called and its - * return value is cached (thus this is only appropriate for idempotent - * functions). Subsequent calls will return the cached return value. This - * allows the evaluation of expensive functions to be delayed until first used. - * - * To cache the return values of functions with parameters, see goog.memoize. - * - * @param {function():T} fn A function to lazily evaluate. - * @return {function():T} A wrapped version the function. - * @template T - */ -goog.functions.cacheReturnValue = function(fn) { - var called = false; - var value; - - return function() { - if (!goog.functions.CACHE_RETURN_VALUE) { - return fn(); - } - - if (!called) { - value = fn(); - called = true; - } - - return value; - }; -}; - - -/** - * Wraps a function to allow it to be called, at most, once. All - * additional calls are no-ops. - * - * This is particularly useful for initialization functions - * that should be called, at most, once. - * - * @param {function():*} f Function to call. - * @return {function():undefined} Wrapped function. - */ -goog.functions.once = function(f) { - // Keep a reference to the function that we null out when we're done with - // it -- that way, the function can be GC'd when we're done with it. - var inner = f; - return function() { - if (inner) { - var tmp = inner; - inner = null; - tmp(); - } - }; -}; - - -/** - * Wraps a function to allow it to be called, at most, once per interval - * (specified in milliseconds). If the wrapper function is called N times within - * that interval, only the Nth call will go through. - * - * This is particularly useful for batching up repeated actions where the - * last action should win. This can be used, for example, for refreshing an - * autocomplete pop-up every so often rather than updating with every keystroke, - * since the final text typed by the user is the one that should produce the - * final autocomplete results. For more stateful debouncing with support for - * pausing, resuming, and canceling debounced actions, use {@code - * goog.async.Debouncer}. - * - * @param {function(this:SCOPE, ...?)} f Function to call. - * @param {number} interval Interval over which to debounce. The function will - * only be called after the full interval has elapsed since the last call. - * @param {SCOPE=} opt_scope Object in whose scope to call the function. - * @return {function(...?): undefined} Wrapped function. - * @template SCOPE - */ -goog.functions.debounce = function(f, interval, opt_scope) { - var timeout = 0; - return /** @type {function(...?)} */ (function(var_args) { - goog.global.clearTimeout(timeout); - var args = arguments; - timeout = goog.global.setTimeout(function() { - f.apply(opt_scope, args); - }, interval); - }); -}; - - -/** - * Wraps a function to allow it to be called, at most, once per interval - * (specified in milliseconds). If the wrapper function is called N times in - * that interval, both the 1st and the Nth calls will go through. - * - * This is particularly useful for limiting repeated user requests where the - * the last action should win, but you also don't want to wait until the end of - * the interval before sending a request out, as it leads to a perception of - * slowness for the user. - * - * @param {function(this:SCOPE, ...?)} f Function to call. - * @param {number} interval Interval over which to throttle. The function can - * only be called once per interval. - * @param {SCOPE=} opt_scope Object in whose scope to call the function. - * @return {function(...?): undefined} Wrapped function. - * @template SCOPE - */ -goog.functions.throttle = function(f, interval, opt_scope) { - var timeout = 0; - var shouldFire = false; - var args = []; - - var handleTimeout = function() { - timeout = 0; - if (shouldFire) { - shouldFire = false; - fire(); - } - }; - - var fire = function() { - timeout = goog.global.setTimeout(handleTimeout, interval); - f.apply(opt_scope, args); - }; - - return /** @type {function(...?)} */ (function(var_args) { - args = arguments; - if (!timeout) { - fire(); - } else { - shouldFire = true; - } - }); -}; - - -/** - * Wraps a function to allow it to be called, at most, once per interval - * (specified in milliseconds). If the wrapper function is called N times within - * that interval, only the 1st call will go through. - * - * This is particularly useful for limiting repeated user requests where the - * first request is guaranteed to have all the data required to perform the - * final action, so there's no need to wait until the end of the interval before - * sending the request out. - * - * @param {function(this:SCOPE, ...?)} f Function to call. - * @param {number} interval Interval over which to rate-limit. The function will - * only be called once per interval, and ignored for the remainer of the - * interval. - * @param {SCOPE=} opt_scope Object in whose scope to call the function. - * @return {function(...?): undefined} Wrapped function. - * @template SCOPE - */ -goog.functions.rateLimit = function(f, interval, opt_scope) { - var timeout = 0; - - var handleTimeout = function() { - timeout = 0; - }; - - return /** @type {function(...?)} */ (function(var_args) { - if (!timeout) { - timeout = goog.global.setTimeout(handleTimeout, interval); - f.apply(opt_scope, arguments); - } - }); -};
diff --git a/third_party/ink/closure/html/legacyconversions.js b/third_party/ink/closure/html/legacyconversions.js deleted file mode 100644 index 0148977..0000000 --- a/third_party/ink/closure/html/legacyconversions.js +++ /dev/null
@@ -1,204 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Transitional utilities to unsafely trust random strings as - * goog.html types. Intended for temporary use when upgrading a library that - * used to accept plain strings to use safe types, but where it's not - * practical to transitively update callers. - * - * IMPORTANT: No new code should use the conversion functions in this file, - * they are intended for refactoring old code to use goog.html types. New code - * should construct goog.html types via their APIs, template systems or - * sanitizers. If that’s not possible it should use - * goog.html.uncheckedconversions and undergo security review. - - * MOE:begin_intracomment_strip - * At Google goog.html.legacyconversions are restricted via both BUILD - * visibility and Conformance rules. The goal is to allow us to progressively - * get rid of using strings to represent HTML-related data which is passed to - * DOM APIs that execute script (like innerHTML or Anchor.href), while avoiding - * regressions. Please carefully read the documentation below before using - * these functions. If you have questions contact ise-hardening@ and we’ll - * gladly help. - * MOE:end_intracomment_strip - * - * The semantics of the conversions in goog.html.legacyconversions are very - * different from the ones provided by goog.html.uncheckedconversions. The - * latter are for use in code where it has been established through manual - * security review that the value produced by a piece of code will always - * satisfy the SafeHtml contract (e.g., the output of a secure HTML sanitizer). - * In uses of goog.html.legacyconversions, this guarantee is not given -- the - * value in question originates in unreviewed legacy code and there is no - * guarantee that it satisfies the SafeHtml contract. - * - * There are only three valid uses of legacyconversions: - * - * 1. Introducing a goog.html version of a function which currently consumes - * string and passes that string to a DOM API which can execute script - and - * hence cause XSS - like innerHTML. For example, Dialog might expose a - * setContent method which takes a string and sets the innerHTML property of - * an element with it. In this case a setSafeHtmlContent function could be - * added, consuming goog.html.SafeHtml instead of string, and using - * goog.dom.safe.setInnerHtml instead of directly setting innerHTML. - * setContent could then internally use legacyconversions to create a SafeHtml - * from string and pass the SafeHtml to setSafeHtmlContent. In this scenario - * remember to document the use of legacyconversions in the modified setContent - * and consider deprecating it as well. - * - * 2. Automated refactoring of application code which handles HTML as string - * but needs to call a function which only takes goog.html types. For example, - * in the Dialog scenario from (1) an alternative option would be to refactor - * setContent to accept goog.html.SafeHtml instead of string and then refactor - * all current callers to use legacyconversions to pass SafeHtml. This is - * generally preferable to (1) because it keeps the library clean of - * legacyconversions, and makes code sites in application code that are - * potentially vulnerable to XSS more apparent. - * - * 3. Old code which needs to call APIs which consume goog.html types and for - * which it is prohibitively expensive to refactor to use goog.html types. - * Generally, this is code where safety from XSS is either hopeless or - * unimportant. - * - * @visibility {//javascript/closure/html:approved_for_legacy_conversion} - * @visibility {//javascript/closure/bin/sizetests:__pkg__} - */ - - -goog.provide('goog.html.legacyconversions'); - -goog.require('goog.html.SafeHtml'); -goog.require('goog.html.SafeScript'); -goog.require('goog.html.SafeStyle'); -goog.require('goog.html.SafeStyleSheet'); -goog.require('goog.html.SafeUrl'); -goog.require('goog.html.TrustedResourceUrl'); - - -/** - * Performs an "unchecked conversion" from string to SafeHtml for legacy API - * purposes. - * - * Please read fileoverview documentation before using. - * - * @param {string} html A string to be converted to SafeHtml. - * @return {!goog.html.SafeHtml} The value of html, wrapped in a SafeHtml - * object. - */ -goog.html.legacyconversions.safeHtmlFromString = function(html) { - goog.html.legacyconversions.reportCallback_(); - return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( - html, null /* dir */); -}; - - -/** - * Performs an "unchecked conversion" from string to SafeScript for legacy API - * purposes. - * - * Please read fileoverview documentation before using. - * - * @param {string} script A string to be converted to SafeScript. - * @return {!goog.html.SafeScript} The value of script, wrapped in a SafeScript - * object. - */ -goog.html.legacyconversions.safeScriptFromString = function(script) { - goog.html.legacyconversions.reportCallback_(); - return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse( - script); -}; - - -/** - * Performs an "unchecked conversion" from string to SafeStyle for legacy API - * purposes. - * - * Please read fileoverview documentation before using. - * - * @param {string} style A string to be converted to SafeStyle. - * @return {!goog.html.SafeStyle} The value of style, wrapped in a SafeStyle - * object. - */ -goog.html.legacyconversions.safeStyleFromString = function(style) { - goog.html.legacyconversions.reportCallback_(); - return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse( - style); -}; - - -/** - * Performs an "unchecked conversion" from string to SafeStyleSheet for legacy - * API purposes. - * - * Please read fileoverview documentation before using. - * - * @param {string} styleSheet A string to be converted to SafeStyleSheet. - * @return {!goog.html.SafeStyleSheet} The value of style sheet, wrapped in - * a SafeStyleSheet object. - */ -goog.html.legacyconversions.safeStyleSheetFromString = function(styleSheet) { - goog.html.legacyconversions.reportCallback_(); - return goog.html.SafeStyleSheet - .createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheet); -}; - - -/** - * Performs an "unchecked conversion" from string to SafeUrl for legacy API - * purposes. - * - * Please read fileoverview documentation before using. - * - * @param {string} url A string to be converted to SafeUrl. - * @return {!goog.html.SafeUrl} The value of url, wrapped in a SafeUrl - * object. - */ -goog.html.legacyconversions.safeUrlFromString = function(url) { - goog.html.legacyconversions.reportCallback_(); - return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url); -}; - - -/** - * Performs an "unchecked conversion" from string to TrustedResourceUrl for - * legacy API purposes. - * - * Please read fileoverview documentation before using. - * - * @param {string} url A string to be converted to TrustedResourceUrl. - * @return {!goog.html.TrustedResourceUrl} The value of url, wrapped in a - * TrustedResourceUrl object. - */ -goog.html.legacyconversions.trustedResourceUrlFromString = function(url) { - goog.html.legacyconversions.reportCallback_(); - return goog.html.TrustedResourceUrl - .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(url); -}; - -/** - * @private {function(): undefined} - */ -goog.html.legacyconversions.reportCallback_ = goog.nullFunction; - - -/** - * Sets a function that will be called every time a legacy conversion is - * performed. The function is called with no parameters but it can use - * goog.debug.getStacktrace to get a stacktrace. - * - * @param {function(): undefined} callback Error callback as defined above. - */ -goog.html.legacyconversions.setReportCallback = function(callback) { - goog.html.legacyconversions.reportCallback_ = callback; -};
diff --git a/third_party/ink/closure/html/safehtml.js b/third_party/ink/closure/html/safehtml.js deleted file mode 100644 index 088e014..0000000 --- a/third_party/ink/closure/html/safehtml.js +++ /dev/null
@@ -1,994 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -/** - * @fileoverview The SafeHtml type and its builders. - * - * TODO(xtof): Link to document stating type contract. - */ - -goog.provide('goog.html.SafeHtml'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.tags'); -goog.require('goog.html.SafeScript'); -goog.require('goog.html.SafeStyle'); -goog.require('goog.html.SafeStyleSheet'); -goog.require('goog.html.SafeUrl'); -goog.require('goog.html.TrustedResourceUrl'); -goog.require('goog.i18n.bidi.Dir'); -goog.require('goog.i18n.bidi.DirectionalString'); -goog.require('goog.labs.userAgent.browser'); -goog.require('goog.object'); -goog.require('goog.string'); -goog.require('goog.string.Const'); -goog.require('goog.string.TypedString'); - - - -/** - * A string that is safe to use in HTML context in DOM APIs and HTML documents. - * - * A SafeHtml is a string-like object that carries the security type contract - * that its value as a string will not cause untrusted script execution when - * evaluated as HTML in a browser. - * - * Values of this type are guaranteed to be safe to use in HTML contexts, - * such as, assignment to the innerHTML DOM property, or interpolation into - * a HTML template in HTML PC_DATA context, in the sense that the use will not - * result in a Cross-Site-Scripting vulnerability. - * - * Instances of this type must be created via the factory methods - * ({@code goog.html.SafeHtml.create}, {@code goog.html.SafeHtml.htmlEscape}), - * etc and not by invoking its constructor. The constructor intentionally - * takes no parameters and the type is immutable; hence only a default instance - * corresponding to the empty string can be obtained via constructor invocation. - * - * @see goog.html.SafeHtml#create - * @see goog.html.SafeHtml#htmlEscape - * @constructor - * @final - * @struct - * @implements {goog.i18n.bidi.DirectionalString} - * @implements {goog.string.TypedString} - */ -goog.html.SafeHtml = function() { - /** - * The contained value of this SafeHtml. The field has a purposely ugly - * name to make (non-compiled) code that attempts to directly access this - * field stand out. - * @private {string} - */ - this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = ''; - - /** - * A type marker used to implement additional run-time type checking. - * @see goog.html.SafeHtml#unwrap - * @const {!Object} - * @private - */ - this.SAFE_HTML_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = - goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_; - - /** - * This SafeHtml's directionality, or null if unknown. - * @private {?goog.i18n.bidi.Dir} - */ - this.dir_ = null; -}; - - -/** - * @override - * @const - */ -goog.html.SafeHtml.prototype.implementsGoogI18nBidiDirectionalString = true; - - -/** @override */ -goog.html.SafeHtml.prototype.getDirection = function() { - return this.dir_; -}; - - -/** - * @override - * @const - */ -goog.html.SafeHtml.prototype.implementsGoogStringTypedString = true; - - -/** - * Returns this SafeHtml's value as string. - * - * IMPORTANT: In code where it is security relevant that an object's type is - * indeed {@code SafeHtml}, use {@code goog.html.SafeHtml.unwrap} instead of - * this method. If in doubt, assume that it's security relevant. In particular, - * note that goog.html functions which return a goog.html type do not guarantee - * that the returned instance is of the right type. For example: - * - * <pre> - * var fakeSafeHtml = new String('fake'); - * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype; - * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml); - * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by - * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml - * // instanceof goog.html.SafeHtml. - * </pre> - * - * @see goog.html.SafeHtml#unwrap - * @override - */ -goog.html.SafeHtml.prototype.getTypedStringValue = function() { - return this.privateDoNotAccessOrElseSafeHtmlWrappedValue_; -}; - - -if (goog.DEBUG) { - /** - * Returns a debug string-representation of this value. - * - * To obtain the actual string value wrapped in a SafeHtml, use - * {@code goog.html.SafeHtml.unwrap}. - * - * @see goog.html.SafeHtml#unwrap - * @override - */ - goog.html.SafeHtml.prototype.toString = function() { - return 'SafeHtml{' + this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ + - '}'; - }; -} - - -/** - * Performs a runtime check that the provided object is indeed a SafeHtml - * object, and returns its value. - * @param {!goog.html.SafeHtml} safeHtml The object to extract from. - * @return {string} The SafeHtml object's contained string, unless the run-time - * type check fails. In that case, {@code unwrap} returns an innocuous - * string, or, if assertions are enabled, throws - * {@code goog.asserts.AssertionError}. - */ -goog.html.SafeHtml.unwrap = function(safeHtml) { - // Perform additional run-time type-checking to ensure that safeHtml is indeed - // an instance of the expected type. This provides some additional protection - // against security bugs due to application code that disables type checks. - // Specifically, the following checks are performed: - // 1. The object is an instance of the expected type. - // 2. The object is not an instance of a subclass. - // 3. The object carries a type marker for the expected type. "Faking" an - // object requires a reference to the type marker, which has names intended - // to stand out in code reviews. - if (safeHtml instanceof goog.html.SafeHtml && - safeHtml.constructor === goog.html.SafeHtml && - safeHtml.SAFE_HTML_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ === - goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) { - return safeHtml.privateDoNotAccessOrElseSafeHtmlWrappedValue_; - } else { - goog.asserts.fail('expected object of type SafeHtml, got \'' + - safeHtml + '\' of type ' + goog.typeOf(safeHtml)); - return 'type_error:SafeHtml'; - } -}; - - -/** - * Shorthand for union of types that can sensibly be converted to strings - * or might already be SafeHtml (as SafeHtml is a goog.string.TypedString). - * @private - * @typedef {string|number|boolean|!goog.string.TypedString| - * !goog.i18n.bidi.DirectionalString} - */ -goog.html.SafeHtml.TextOrHtml_; - - -/** - * Returns HTML-escaped text as a SafeHtml object. - * - * If text is of a type that implements - * {@code goog.i18n.bidi.DirectionalString}, the directionality of the new - * {@code SafeHtml} object is set to {@code text}'s directionality, if known. - * Otherwise, the directionality of the resulting SafeHtml is unknown (i.e., - * {@code null}). - * - * @param {!goog.html.SafeHtml.TextOrHtml_} textOrHtml The text to escape. If - * the parameter is of type SafeHtml it is returned directly (no escaping - * is done). - * @return {!goog.html.SafeHtml} The escaped text, wrapped as a SafeHtml. - */ -goog.html.SafeHtml.htmlEscape = function(textOrHtml) { - if (textOrHtml instanceof goog.html.SafeHtml) { - return textOrHtml; - } - var dir = null; - if (textOrHtml.implementsGoogI18nBidiDirectionalString) { - dir = textOrHtml.getDirection(); - } - var textAsString; - if (textOrHtml.implementsGoogStringTypedString) { - textAsString = textOrHtml.getTypedStringValue(); - } else { - textAsString = String(textOrHtml); - } - return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( - goog.string.htmlEscape(textAsString), dir); -}; - - -/** - * Returns HTML-escaped text as a SafeHtml object, with newlines changed to - * <br>. - * @param {!goog.html.SafeHtml.TextOrHtml_} textOrHtml The text to escape. If - * the parameter is of type SafeHtml it is returned directly (no escaping - * is done). - * @return {!goog.html.SafeHtml} The escaped text, wrapped as a SafeHtml. - */ -goog.html.SafeHtml.htmlEscapePreservingNewlines = function(textOrHtml) { - if (textOrHtml instanceof goog.html.SafeHtml) { - return textOrHtml; - } - var html = goog.html.SafeHtml.htmlEscape(textOrHtml); - return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( - goog.string.newLineToBr(goog.html.SafeHtml.unwrap(html)), - html.getDirection()); -}; - - -/** - * Returns HTML-escaped text as a SafeHtml object, with newlines changed to - * <br> and escaping whitespace to preserve spatial formatting. Character - * entity #160 is used to make it safer for XML. - * @param {!goog.html.SafeHtml.TextOrHtml_} textOrHtml The text to escape. If - * the parameter is of type SafeHtml it is returned directly (no escaping - * is done). - * @return {!goog.html.SafeHtml} The escaped text, wrapped as a SafeHtml. - */ -goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces = function( - textOrHtml) { - if (textOrHtml instanceof goog.html.SafeHtml) { - return textOrHtml; - } - var html = goog.html.SafeHtml.htmlEscape(textOrHtml); - return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( - goog.string.whitespaceEscape(goog.html.SafeHtml.unwrap(html)), - html.getDirection()); -}; - - -/** - * Coerces an arbitrary object into a SafeHtml object. - * - * If {@code textOrHtml} is already of type {@code goog.html.SafeHtml}, the same - * object is returned. Otherwise, {@code textOrHtml} is coerced to string, and - * HTML-escaped. If {@code textOrHtml} is of a type that implements - * {@code goog.i18n.bidi.DirectionalString}, its directionality, if known, is - * preserved. - * - * @param {!goog.html.SafeHtml.TextOrHtml_} textOrHtml The text or SafeHtml to - * coerce. - * @return {!goog.html.SafeHtml} The resulting SafeHtml object. - * @deprecated Use goog.html.SafeHtml.htmlEscape. - */ -goog.html.SafeHtml.from = goog.html.SafeHtml.htmlEscape; - - -/** - * @const - * @private - */ -goog.html.SafeHtml.VALID_NAMES_IN_TAG_ = /^[a-zA-Z0-9-]+$/; - - -/** - * Set of attributes containing URL as defined at - * http://www.w3.org/TR/html5/index.html#attributes-1. - * @private @const {!Object<string,boolean>} - */ -goog.html.SafeHtml.URL_ATTRIBUTES_ = goog.object.createSet( - 'action', 'cite', 'data', 'formaction', 'href', 'manifest', 'poster', - 'src'); - - -/** - * Tags which are unsupported via create(). They might be supported via a - * tag-specific create method. These are tags which might require a - * TrustedResourceUrl in one of their attributes or a restricted type for - * their content. - * @private @const {!Object<string,boolean>} - */ -goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_ = goog.object.createSet( - goog.dom.TagName.APPLET, goog.dom.TagName.BASE, goog.dom.TagName.EMBED, - goog.dom.TagName.IFRAME, goog.dom.TagName.LINK, goog.dom.TagName.MATH, - goog.dom.TagName.META, goog.dom.TagName.OBJECT, goog.dom.TagName.SCRIPT, - goog.dom.TagName.STYLE, goog.dom.TagName.SVG, goog.dom.TagName.TEMPLATE); - - -/** - * @typedef {string|number|goog.string.TypedString| - * goog.html.SafeStyle.PropertyMap|undefined} - */ -goog.html.SafeHtml.AttributeValue; - - -/** - * Creates a SafeHtml content consisting of a tag with optional attributes and - * optional content. - * - * For convenience tag names and attribute names are accepted as regular - * strings, instead of goog.string.Const. Nevertheless, you should not pass - * user-controlled values to these parameters. Note that these parameters are - * syntactically validated at runtime, and invalid values will result in - * an exception. - * - * Example usage: - * - * goog.html.SafeHtml.create('br'); - * goog.html.SafeHtml.create('div', {'class': 'a'}); - * goog.html.SafeHtml.create('p', {}, 'a'); - * goog.html.SafeHtml.create('p', {}, goog.html.SafeHtml.create('br')); - * - * goog.html.SafeHtml.create('span', { - * 'style': {'margin': '0'} - * }); - * - * To guarantee SafeHtml's type contract is upheld there are restrictions on - * attribute values and tag names. - * - * - For attributes which contain script code (on*), a goog.string.Const is - * required. - * - For attributes which contain style (style), a goog.html.SafeStyle or a - * goog.html.SafeStyle.PropertyMap is required. - * - For attributes which are interpreted as URLs (e.g. src, href) a - * goog.html.SafeUrl, goog.string.Const or string is required. If a string - * is passed, it will be sanitized with SafeUrl.sanitize(). - * - For tags which can load code or set security relevant page metadata, - * more specific goog.html.SafeHtml.create*() functions must be used. Tags - * which are not supported by this function are applet, base, embed, iframe, - * link, math, object, script, style, svg, and template. - * - * @param {!goog.dom.TagName|string} tagName The name of the tag. Only tag names - * consisting of [a-zA-Z0-9-] are allowed. Tag names documented above are - * disallowed. - * @param {?Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes - * Mapping from attribute names to their values. Only attribute names - * consisting of [a-zA-Z0-9-] are allowed. Value of null or undefined causes - * the attribute to be omitted. - * @param {!goog.html.SafeHtml.TextOrHtml_| - * !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content Content to - * HTML-escape and put inside the tag. This must be empty for void tags - * like <br>. Array elements are concatenated. - * @return {!goog.html.SafeHtml} The SafeHtml content with the tag. - * @throws {Error} If invalid tag name, attribute name, or attribute value is - * provided. - * @throws {goog.asserts.AssertionError} If content for void tag is provided. - */ -goog.html.SafeHtml.create = function(tagName, opt_attributes, opt_content) { - goog.html.SafeHtml.verifyTagName(String(tagName)); - return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse( - String(tagName), opt_attributes, opt_content); -}; - - -/** - * Verifies if the tag name is valid and if it doesn't change the context. - * E.g. STRONG is fine but SCRIPT throws because it changes context. See - * goog.html.SafeHtml.create for an explanation of allowed tags. - * @param {string} tagName - * @throws {Error} If invalid tag name is provided. - * @package - */ -goog.html.SafeHtml.verifyTagName = function(tagName) { - if (!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(tagName)) { - throw new Error('Invalid tag name <' + tagName + '>.'); - } - if (tagName.toUpperCase() in goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_) { - throw new Error('Tag name <' + tagName + '> is not allowed for SafeHtml.'); - } -}; - - -/** - * Creates a SafeHtml representing an iframe tag. - * - * This by default restricts the iframe as much as possible by setting the - * sandbox attribute to the empty string. If the iframe requires less - * restrictions, set the sandbox attribute as tight as possible, but do not rely - * on the sandbox as a security feature because it is not supported by older - * browsers. If a sandbox is essential to security (e.g. for third-party - * frames), use createSandboxIframe which checks for browser support. - * - * @see https://developer.mozilla.org/en/docs/Web/HTML/Element/iframe#attr-sandbox - * - * @param {?goog.html.TrustedResourceUrl=} opt_src The value of the src - * attribute. If null or undefined src will not be set. - * @param {?goog.html.SafeHtml=} opt_srcdoc The value of the srcdoc attribute. - * If null or undefined srcdoc will not be set. - * @param {?Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes - * Mapping from attribute names to their values. Only attribute names - * consisting of [a-zA-Z0-9-] are allowed. Value of null or undefined causes - * the attribute to be omitted. - * @param {!goog.html.SafeHtml.TextOrHtml_| - * !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content Content to - * HTML-escape and put inside the tag. Array elements are concatenated. - * @return {!goog.html.SafeHtml} The SafeHtml content with the tag. - * @throws {Error} If invalid tag name, attribute name, or attribute value is - * provided. If opt_attributes contains the src or srcdoc attributes. - */ -goog.html.SafeHtml.createIframe = function( - opt_src, opt_srcdoc, opt_attributes, opt_content) { - if (opt_src) { - // Check whether this is really TrustedResourceUrl. - goog.html.TrustedResourceUrl.unwrap(opt_src); - } - - var fixedAttributes = {}; - fixedAttributes['src'] = opt_src || null; - fixedAttributes['srcdoc'] = - opt_srcdoc && goog.html.SafeHtml.unwrap(opt_srcdoc); - var defaultAttributes = {'sandbox': ''}; - var attributes = goog.html.SafeHtml.combineAttributes( - fixedAttributes, defaultAttributes, opt_attributes); - return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse( - 'iframe', attributes, opt_content); -}; - - -/** - * Creates a SafeHtml representing a sandboxed iframe tag. - * - * The sandbox attribute is enforced in its most restrictive mode, an empty - * string. Consequently, the security requirements for the src and srcdoc - * attributes are relaxed compared to SafeHtml.createIframe. This function - * will throw on browsers that do not support the sandbox attribute, as - * determined by SafeHtml.canUseSandboxIframe. - * - * The SafeHtml returned by this function can trigger downloads with no - * user interaction on Chrome (though only a few, further attempts are blocked). - * Firefox and IE will block all downloads from the sandbox. - * - * @see https://developer.mozilla.org/en/docs/Web/HTML/Element/iframe#attr-sandbox - * @see https://lists.w3.org/Archives/Public/public-whatwg-archive/2013Feb/0112.html - * - * @param {string|!goog.html.SafeUrl=} opt_src The value of the src - * attribute. If null or undefined src will not be set. - * @param {string=} opt_srcdoc The value of the srcdoc attribute. - * If null or undefined srcdoc will not be set. Will not be sanitized. - * @param {!Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes - * Mapping from attribute names to their values. Only attribute names - * consisting of [a-zA-Z0-9-] are allowed. Value of null or undefined causes - * the attribute to be omitted. - * @param {!goog.html.SafeHtml.TextOrHtml_| - * !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content Content to - * HTML-escape and put inside the tag. Array elements are concatenated. - * @return {!goog.html.SafeHtml} The SafeHtml content with the tag. - * @throws {Error} If invalid tag name, attribute name, or attribute value is - * provided. If opt_attributes contains the src, srcdoc or sandbox - * attributes. If browser does not support the sandbox attribute on iframe. - */ -goog.html.SafeHtml.createSandboxIframe = function( - opt_src, opt_srcdoc, opt_attributes, opt_content) { - if (!goog.html.SafeHtml.canUseSandboxIframe()) { - throw new Error('The browser does not support sandboxed iframes.'); - } - - var fixedAttributes = {}; - if (opt_src) { - // Note that sanitize is a no-op on SafeUrl. - fixedAttributes['src'] = - goog.html.SafeUrl.unwrap(goog.html.SafeUrl.sanitize(opt_src)); - } else { - fixedAttributes['src'] = null; - } - fixedAttributes['srcdoc'] = opt_srcdoc || null; - fixedAttributes['sandbox'] = ''; - var attributes = - goog.html.SafeHtml.combineAttributes(fixedAttributes, {}, opt_attributes); - return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse( - 'iframe', attributes, opt_content); -}; - - -/** - * Checks if the user agent supports sandboxed iframes. - * @return {boolean} - */ -goog.html.SafeHtml.canUseSandboxIframe = function() { - return goog.global['HTMLIFrameElement'] && - ('sandbox' in goog.global['HTMLIFrameElement'].prototype); -}; - - -/** - * Creates a SafeHtml representing a script tag with the src attribute. - * @param {!goog.html.TrustedResourceUrl} src The value of the src - * attribute. - * @param {?Object<string, ?goog.html.SafeHtml.AttributeValue>=} - * opt_attributes - * Mapping from attribute names to their values. Only attribute names - * consisting of [a-zA-Z0-9-] are allowed. Value of null or undefined - * causes the attribute to be omitted. - * @return {!goog.html.SafeHtml} The SafeHtml content with the tag. - * @throws {Error} If invalid attribute name or value is provided. If - * opt_attributes contains the src attribute. - */ -goog.html.SafeHtml.createScriptSrc = function(src, opt_attributes) { - // TODO(mlourenco): The charset attribute should probably be blocked. If - // its value is attacker controlled, the script contains attacker controlled - // sub-strings (even if properly escaped) and the server does not set charset - // then XSS is likely possible. - // https://html.spec.whatwg.org/multipage/scripting.html#dom-script-charset - - // Check whether this is really TrustedResourceUrl. - goog.html.TrustedResourceUrl.unwrap(src); - - var fixedAttributes = {'src': src}; - var defaultAttributes = {}; - var attributes = goog.html.SafeHtml.combineAttributes( - fixedAttributes, defaultAttributes, opt_attributes); - return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse( - 'script', attributes); -}; - - -/** - * Creates a SafeHtml representing a script tag. Does not allow the language, - * src, text or type attributes to be set. - * @param {!goog.html.SafeScript|!Array<!goog.html.SafeScript>} - * script Content to put inside the tag. Array elements are - * concatenated. - * @param {?Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes - * Mapping from attribute names to their values. Only attribute names - * consisting of [a-zA-Z0-9-] are allowed. Value of null or undefined causes - * the attribute to be omitted. - * @return {!goog.html.SafeHtml} The SafeHtml content with the tag. - * @throws {Error} If invalid attribute name or attribute value is provided. If - * opt_attributes contains the language, src, text or type attribute. - */ -goog.html.SafeHtml.createScript = function(script, opt_attributes) { - for (var attr in opt_attributes) { - var attrLower = attr.toLowerCase(); - if (attrLower == 'language' || attrLower == 'src' || attrLower == 'text' || - attrLower == 'type') { - throw new Error('Cannot set "' + attrLower + '" attribute'); - } - } - - var content = ''; - script = goog.array.concat(script); - for (var i = 0; i < script.length; i++) { - content += goog.html.SafeScript.unwrap(script[i]); - } - // Convert to SafeHtml so that it's not HTML-escaped. This is safe because - // as part of its contract, SafeScript should have no dangerous '<'. - var htmlContent = - goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( - content, goog.i18n.bidi.Dir.NEUTRAL); - return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse( - 'script', opt_attributes, htmlContent); -}; - - -/** - * Creates a SafeHtml representing a style tag. The type attribute is set - * to "text/css". - * @param {!goog.html.SafeStyleSheet|!Array<!goog.html.SafeStyleSheet>} - * styleSheet Content to put inside the tag. Array elements are - * concatenated. - * @param {?Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes - * Mapping from attribute names to their values. Only attribute names - * consisting of [a-zA-Z0-9-] are allowed. Value of null or undefined causes - * the attribute to be omitted. - * @return {!goog.html.SafeHtml} The SafeHtml content with the tag. - * @throws {Error} If invalid attribute name or attribute value is provided. If - * opt_attributes contains the type attribute. - */ -goog.html.SafeHtml.createStyle = function(styleSheet, opt_attributes) { - var fixedAttributes = {'type': 'text/css'}; - var defaultAttributes = {}; - var attributes = goog.html.SafeHtml.combineAttributes( - fixedAttributes, defaultAttributes, opt_attributes); - - var content = ''; - styleSheet = goog.array.concat(styleSheet); - for (var i = 0; i < styleSheet.length; i++) { - content += goog.html.SafeStyleSheet.unwrap(styleSheet[i]); - } - // Convert to SafeHtml so that it's not HTML-escaped. This is safe because - // as part of its contract, SafeStyleSheet should have no dangerous '<'. - var htmlContent = - goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( - content, goog.i18n.bidi.Dir.NEUTRAL); - return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse( - 'style', attributes, htmlContent); -}; - - -/** - * Creates a SafeHtml representing a meta refresh tag. - * @param {!goog.html.SafeUrl|string} url Where to redirect. If a string is - * passed, it will be sanitized with SafeUrl.sanitize(). - * @param {number=} opt_secs Number of seconds until the page should be - * reloaded. Will be set to 0 if unspecified. - * @return {!goog.html.SafeHtml} The SafeHtml content with the tag. - */ -goog.html.SafeHtml.createMetaRefresh = function(url, opt_secs) { - - // Note that sanitize is a no-op on SafeUrl. - var unwrappedUrl = goog.html.SafeUrl.unwrap(goog.html.SafeUrl.sanitize(url)); - - if (goog.labs.userAgent.browser.isIE() || - goog.labs.userAgent.browser.isEdge()) { - // IE/EDGE can't parse the content attribute if the url contains a - // semicolon. We can fix this by adding quotes around the url, but then we - // can't parse quotes in the URL correctly. Also, it seems that IE/EDGE - // did not unescape semicolons in these URLs at some point in the past. We - // take a best-effort approach. - // - // If the URL has semicolons (which may happen in some cases, see - // http://www.w3.org/TR/1999/REC-html401-19991224/appendix/notes.html#h-B.2 - // for instance), wrap it in single quotes to protect the semicolons. - // If the URL has semicolons and single quotes, url-encode the single quotes - // as well. - // - // This is imperfect. Notice that both ' and ; are reserved characters in - // URIs, so this could do the wrong thing, but at least it will do the wrong - // thing in only rare cases. - if (goog.string.contains(unwrappedUrl, ';')) { - unwrappedUrl = "'" + unwrappedUrl.replace(/'/g, '%27') + "'"; - } - } - var attributes = { - 'http-equiv': 'refresh', - 'content': (opt_secs || 0) + '; url=' + unwrappedUrl - }; - - // This function will handle the HTML escaping for attributes. - return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse( - 'meta', attributes); -}; - - -/** - * @param {string} tagName The tag name. - * @param {string} name The attribute name. - * @param {!goog.html.SafeHtml.AttributeValue} value The attribute value. - * @return {string} A "name=value" string. - * @throws {Error} If attribute value is unsafe for the given tag and attribute. - * @private - */ -goog.html.SafeHtml.getAttrNameAndValue_ = function(tagName, name, value) { - // If it's goog.string.Const, allow any valid attribute name. - if (value instanceof goog.string.Const) { - value = goog.string.Const.unwrap(value); - } else if (name.toLowerCase() == 'style') { - value = goog.html.SafeHtml.getStyleValue_(value); - } else if (/^on/i.test(name)) { - // TODO(jakubvrana): Disallow more attributes with a special meaning. - throw new Error( - 'Attribute "' + name + '" requires goog.string.Const value, "' + value + - '" given.'); - // URL attributes handled differently according to tag. - } else if (name.toLowerCase() in goog.html.SafeHtml.URL_ATTRIBUTES_) { - if (value instanceof goog.html.TrustedResourceUrl) { - value = goog.html.TrustedResourceUrl.unwrap(value); - } else if (value instanceof goog.html.SafeUrl) { - value = goog.html.SafeUrl.unwrap(value); - } else if (goog.isString(value)) { - value = goog.html.SafeUrl.sanitize(value).getTypedStringValue(); - } else { - throw new Error( - 'Attribute "' + name + '" on tag "' + tagName + - '" requires goog.html.SafeUrl, goog.string.Const, or string,' + - ' value "' + value + '" given.'); - } - } - - // Accept SafeUrl, TrustedResourceUrl, etc. for attributes which only require - // HTML-escaping. - if (value.implementsGoogStringTypedString) { - // Ok to call getTypedStringValue() since there's no reliance on the type - // contract for security here. - value = value.getTypedStringValue(); - } - - goog.asserts.assert( - goog.isString(value) || goog.isNumber(value), - 'String or number value expected, got ' + (typeof value) + - ' with value: ' + value); - return name + '="' + goog.string.htmlEscape(String(value)) + '"'; -}; - - -/** - * Gets value allowed in "style" attribute. - * @param {!goog.html.SafeHtml.AttributeValue} value It could be SafeStyle or a - * map which will be passed to goog.html.SafeStyle.create. - * @return {string} Unwrapped value. - * @throws {Error} If string value is given. - * @private - */ -goog.html.SafeHtml.getStyleValue_ = function(value) { - if (!goog.isObject(value)) { - throw new Error( - 'The "style" attribute requires goog.html.SafeStyle or map ' + - 'of style properties, ' + (typeof value) + ' given: ' + value); - } - if (!(value instanceof goog.html.SafeStyle)) { - // Process the property bag into a style object. - value = goog.html.SafeStyle.create(value); - } - return goog.html.SafeStyle.unwrap(value); -}; - - -/** - * Creates a SafeHtml content with known directionality consisting of a tag with - * optional attributes and optional content. - * @param {!goog.i18n.bidi.Dir} dir Directionality. - * @param {string} tagName - * @param {?Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes - * @param {!goog.html.SafeHtml.TextOrHtml_| - * !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content - * @return {!goog.html.SafeHtml} The SafeHtml content with the tag. - */ -goog.html.SafeHtml.createWithDir = function( - dir, tagName, opt_attributes, opt_content) { - var html = goog.html.SafeHtml.create(tagName, opt_attributes, opt_content); - html.dir_ = dir; - return html; -}; - - -/** - * Creates a new SafeHtml object by concatenating values. - * @param {...(!goog.html.SafeHtml.TextOrHtml_| - * !Array<!goog.html.SafeHtml.TextOrHtml_>)} var_args Values to concatenate. - * @return {!goog.html.SafeHtml} - */ -goog.html.SafeHtml.concat = function(var_args) { - var dir = goog.i18n.bidi.Dir.NEUTRAL; - var content = ''; - - /** - * @param {!goog.html.SafeHtml.TextOrHtml_| - * !Array<!goog.html.SafeHtml.TextOrHtml_>} argument - */ - var addArgument = function(argument) { - if (goog.isArray(argument)) { - goog.array.forEach(argument, addArgument); - } else { - var html = goog.html.SafeHtml.htmlEscape(argument); - content += goog.html.SafeHtml.unwrap(html); - var htmlDir = html.getDirection(); - if (dir == goog.i18n.bidi.Dir.NEUTRAL) { - dir = htmlDir; - } else if (htmlDir != goog.i18n.bidi.Dir.NEUTRAL && dir != htmlDir) { - dir = null; - } - } - }; - - goog.array.forEach(arguments, addArgument); - return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( - content, dir); -}; - - -/** - * Creates a new SafeHtml object with known directionality by concatenating the - * values. - * @param {!goog.i18n.bidi.Dir} dir Directionality. - * @param {...(!goog.html.SafeHtml.TextOrHtml_| - * !Array<!goog.html.SafeHtml.TextOrHtml_>)} var_args Elements of array - * arguments would be processed recursively. - * @return {!goog.html.SafeHtml} - */ -goog.html.SafeHtml.concatWithDir = function(dir, var_args) { - var html = goog.html.SafeHtml.concat(goog.array.slice(arguments, 1)); - html.dir_ = dir; - return html; -}; - - -/** - * Type marker for the SafeHtml type, used to implement additional run-time - * type checking. - * @const {!Object} - * @private - */ -goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}; - - -/** - * Package-internal utility method to create SafeHtml instances. - * - * @param {string} html The string to initialize the SafeHtml object with. - * @param {?goog.i18n.bidi.Dir} dir The directionality of the SafeHtml to be - * constructed, or null if unknown. - * @return {!goog.html.SafeHtml} The initialized SafeHtml object. - * @package - */ -goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse = function( - html, dir) { - return new goog.html.SafeHtml().initSecurityPrivateDoNotAccessOrElse_( - html, dir); -}; - - -/** - * Called from createSafeHtmlSecurityPrivateDoNotAccessOrElse(). This - * method exists only so that the compiler can dead code eliminate static - * fields (like EMPTY) when they're not accessed. - * @param {string} html - * @param {?goog.i18n.bidi.Dir} dir - * @return {!goog.html.SafeHtml} - * @private - */ -goog.html.SafeHtml.prototype.initSecurityPrivateDoNotAccessOrElse_ = function( - html, dir) { - this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = html; - this.dir_ = dir; - return this; -}; - - -/** - * Like create() but does not restrict which tags can be constructed. - * - * @param {string} tagName Tag name. Set or validated by caller. - * @param {?Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes - * @param {(!goog.html.SafeHtml.TextOrHtml_| - * !Array<!goog.html.SafeHtml.TextOrHtml_>)=} opt_content - * @return {!goog.html.SafeHtml} - * @throws {Error} If invalid or unsafe attribute name or value is provided. - * @throws {goog.asserts.AssertionError} If content for void tag is provided. - * @package - */ -goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse = function( - tagName, opt_attributes, opt_content) { - var dir = null; - var result = '<' + tagName; - result += goog.html.SafeHtml.stringifyAttributes(tagName, opt_attributes); - - var content = opt_content; - if (!goog.isDefAndNotNull(content)) { - content = []; - } else if (!goog.isArray(content)) { - content = [content]; - } - - if (goog.dom.tags.isVoidTag(tagName.toLowerCase())) { - goog.asserts.assert( - !content.length, 'Void tag <' + tagName + '> does not allow content.'); - result += '>'; - } else { - var html = goog.html.SafeHtml.concat(content); - result += '>' + goog.html.SafeHtml.unwrap(html) + '</' + tagName + '>'; - dir = html.getDirection(); - } - - var dirAttribute = opt_attributes && opt_attributes['dir']; - if (dirAttribute) { - if (/^(ltr|rtl|auto)$/i.test(dirAttribute)) { - // If the tag has the "dir" attribute specified then its direction is - // neutral because it can be safely used in any context. - dir = goog.i18n.bidi.Dir.NEUTRAL; - } else { - dir = null; - } - } - - return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( - result, dir); -}; - - -/** - * Creates a string with attributes to insert after tagName. - * @param {string} tagName - * @param {?Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes - * @return {string} Returns an empty string if there are no attributes, returns - * a string starting with a space otherwise. - * @throws {Error} If attribute value is unsafe for the given tag and attribute. - * @package - */ -goog.html.SafeHtml.stringifyAttributes = function(tagName, opt_attributes) { - var result = ''; - if (opt_attributes) { - for (var name in opt_attributes) { - if (!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(name)) { - throw new Error('Invalid attribute name "' + name + '".'); - } - var value = opt_attributes[name]; - if (!goog.isDefAndNotNull(value)) { - continue; - } - result += - ' ' + goog.html.SafeHtml.getAttrNameAndValue_(tagName, name, value); - } - } - return result; -}; - - -/** - * @param {!Object<string, ?goog.html.SafeHtml.AttributeValue>} fixedAttributes - * @param {!Object<string, string>} defaultAttributes - * @param {?Object<string, ?goog.html.SafeHtml.AttributeValue>=} opt_attributes - * Optional attributes passed to create*(). - * @return {!Object<string, ?goog.html.SafeHtml.AttributeValue>} - * @throws {Error} If opt_attributes contains an attribute with the same name - * as an attribute in fixedAttributes. - * @package - */ -goog.html.SafeHtml.combineAttributes = function( - fixedAttributes, defaultAttributes, opt_attributes) { - var combinedAttributes = {}; - var name; - - for (name in fixedAttributes) { - goog.asserts.assert(name.toLowerCase() == name, 'Must be lower case'); - combinedAttributes[name] = fixedAttributes[name]; - } - for (name in defaultAttributes) { - goog.asserts.assert(name.toLowerCase() == name, 'Must be lower case'); - combinedAttributes[name] = defaultAttributes[name]; - } - - for (name in opt_attributes) { - var nameLower = name.toLowerCase(); - if (nameLower in fixedAttributes) { - throw new Error( - 'Cannot override "' + nameLower + '" attribute, got "' + name + - '" with value "' + opt_attributes[name] + '"'); - } - if (nameLower in defaultAttributes) { - delete combinedAttributes[nameLower]; - } - combinedAttributes[name] = opt_attributes[name]; - } - - return combinedAttributes; -}; - - -/** - * A SafeHtml instance corresponding to the HTML doctype: "<!DOCTYPE html>". - * @const {!goog.html.SafeHtml} - */ -goog.html.SafeHtml.DOCTYPE_HTML = - goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( - '<!DOCTYPE html>', goog.i18n.bidi.Dir.NEUTRAL); - - -/** - * A SafeHtml instance corresponding to the empty string. - * @const {!goog.html.SafeHtml} - */ -goog.html.SafeHtml.EMPTY = - goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( - '', goog.i18n.bidi.Dir.NEUTRAL); - - -/** - * A SafeHtml instance corresponding to the <br> tag. - * @const {!goog.html.SafeHtml} - */ -goog.html.SafeHtml.BR = - goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( - '<br>', goog.i18n.bidi.Dir.NEUTRAL);
diff --git a/third_party/ink/closure/html/safescript.js b/third_party/ink/closure/html/safescript.js deleted file mode 100644 index 7a945eb..0000000 --- a/third_party/ink/closure/html/safescript.js +++ /dev/null
@@ -1,234 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview The SafeScript type and its builders. - * - * TODO(xtof): Link to document stating type contract. - */ - -goog.provide('goog.html.SafeScript'); - -goog.require('goog.asserts'); -goog.require('goog.string.Const'); -goog.require('goog.string.TypedString'); - - - -/** - * A string-like object which represents JavaScript code and that carries the - * security type contract that its value, as a string, will not cause execution - * of unconstrained attacker controlled code (XSS) when evaluated as JavaScript - * in a browser. - * - * Instances of this type must be created via the factory method - * {@code goog.html.SafeScript.fromConstant} and not by invoking its - * constructor. The constructor intentionally takes no parameters and the type - * is immutable; hence only a default instance corresponding to the empty string - * can be obtained via constructor invocation. - * - * A SafeScript's string representation can safely be interpolated as the - * content of a script element within HTML. The SafeScript string should not be - * escaped before interpolation. - * - * Note that the SafeScript might contain text that is attacker-controlled but - * that text should have been interpolated with appropriate escaping, - * sanitization and/or validation into the right location in the script, such - * that it is highly constrained in its effect (for example, it had to match a - * set of whitelisted words). - * - * A SafeScript can be constructed via security-reviewed unchecked - * conversions. In this case producers of SafeScript must ensure themselves that - * the SafeScript does not contain unsafe script. Note in particular that - * {@code <} is dangerous, even when inside JavaScript strings, and so should - * always be forbidden or JavaScript escaped in user controlled input. For - * example, if {@code </script><script>evil</script>"} were - * interpolated inside a JavaScript string, it would break out of the context - * of the original script element and {@code evil} would execute. Also note - * that within an HTML script (raw text) element, HTML character references, - * such as "<" are not allowed. See - * http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements. - * - * @see goog.html.SafeScript#fromConstant - * @constructor - * @final - * @struct - * @implements {goog.string.TypedString} - */ -goog.html.SafeScript = function() { - /** - * The contained value of this SafeScript. The field has a purposely - * ugly name to make (non-compiled) code that attempts to directly access this - * field stand out. - * @private {string} - */ - this.privateDoNotAccessOrElseSafeScriptWrappedValue_ = ''; - - /** - * A type marker used to implement additional run-time type checking. - * @see goog.html.SafeScript#unwrap - * @const {!Object} - * @private - */ - this.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = - goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_; -}; - - -/** - * @override - * @const - */ -goog.html.SafeScript.prototype.implementsGoogStringTypedString = true; - - -/** - * Type marker for the SafeScript type, used to implement additional - * run-time type checking. - * @const {!Object} - * @private - */ -goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}; - - -/** - * Creates a SafeScript object from a compile-time constant string. - * - * @param {!goog.string.Const} script A compile-time-constant string from which - * to create a SafeScript. - * @return {!goog.html.SafeScript} A SafeScript object initialized to - * {@code script}. - */ -goog.html.SafeScript.fromConstant = function(script) { - var scriptString = goog.string.Const.unwrap(script); - if (scriptString.length === 0) { - return goog.html.SafeScript.EMPTY; - } - return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse( - scriptString); -}; - - -/** - * Returns this SafeScript's value as a string. - * - * IMPORTANT: In code where it is security relevant that an object's type is - * indeed {@code SafeScript}, use {@code goog.html.SafeScript.unwrap} instead of - * this method. If in doubt, assume that it's security relevant. In particular, - * note that goog.html functions which return a goog.html type do not guarantee - * the returned instance is of the right type. For example: - * - * <pre> - * var fakeSafeHtml = new String('fake'); - * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype; - * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml); - * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by - * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml - * // instanceof goog.html.SafeHtml. - * </pre> - * - * @see goog.html.SafeScript#unwrap - * @override - */ -goog.html.SafeScript.prototype.getTypedStringValue = function() { - return this.privateDoNotAccessOrElseSafeScriptWrappedValue_; -}; - - -if (goog.DEBUG) { - /** - * Returns a debug string-representation of this value. - * - * To obtain the actual string value wrapped in a SafeScript, use - * {@code goog.html.SafeScript.unwrap}. - * - * @see goog.html.SafeScript#unwrap - * @override - */ - goog.html.SafeScript.prototype.toString = function() { - return 'SafeScript{' + - this.privateDoNotAccessOrElseSafeScriptWrappedValue_ + '}'; - }; -} - - -/** - * Performs a runtime check that the provided object is indeed a - * SafeScript object, and returns its value. - * - * @param {!goog.html.SafeScript} safeScript The object to extract from. - * @return {string} The safeScript object's contained string, unless - * the run-time type check fails. In that case, {@code unwrap} returns an - * innocuous string, or, if assertions are enabled, throws - * {@code goog.asserts.AssertionError}. - */ -goog.html.SafeScript.unwrap = function(safeScript) { - // Perform additional Run-time type-checking to ensure that - // safeScript is indeed an instance of the expected type. This - // provides some additional protection against security bugs due to - // application code that disables type checks. - // Specifically, the following checks are performed: - // 1. The object is an instance of the expected type. - // 2. The object is not an instance of a subclass. - // 3. The object carries a type marker for the expected type. "Faking" an - // object requires a reference to the type marker, which has names intended - // to stand out in code reviews. - if (safeScript instanceof goog.html.SafeScript && - safeScript.constructor === goog.html.SafeScript && - safeScript.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ === - goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) { - return safeScript.privateDoNotAccessOrElseSafeScriptWrappedValue_; - } else { - goog.asserts.fail('expected object of type SafeScript, got \'' + - safeScript + '\' of type ' + goog.typeOf(safeScript)); - return 'type_error:SafeScript'; - } -}; - - -/** - * Package-internal utility method to create SafeScript instances. - * - * @param {string} script The string to initialize the SafeScript object with. - * @return {!goog.html.SafeScript} The initialized SafeScript object. - * @package - */ -goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse = - function(script) { - return new goog.html.SafeScript().initSecurityPrivateDoNotAccessOrElse_( - script); -}; - - -/** - * Called from createSafeScriptSecurityPrivateDoNotAccessOrElse(). This - * method exists only so that the compiler can dead code eliminate static - * fields (like EMPTY) when they're not accessed. - * @param {string} script - * @return {!goog.html.SafeScript} - * @private - */ -goog.html.SafeScript.prototype.initSecurityPrivateDoNotAccessOrElse_ = function( - script) { - this.privateDoNotAccessOrElseSafeScriptWrappedValue_ = script; - return this; -}; - - -/** - * A SafeScript instance corresponding to the empty string. - * @const {!goog.html.SafeScript} - */ -goog.html.SafeScript.EMPTY = - goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse('');
diff --git a/third_party/ink/closure/html/safestyle.js b/third_party/ink/closure/html/safestyle.js deleted file mode 100644 index 95ff10c1..0000000 --- a/third_party/ink/closure/html/safestyle.js +++ /dev/null
@@ -1,560 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview The SafeStyle type and its builders. - * - * TODO(xtof): Link to document stating type contract. - */ - -goog.provide('goog.html.SafeStyle'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.html.SafeUrl'); -goog.require('goog.string'); -goog.require('goog.string.Const'); -goog.require('goog.string.TypedString'); - - - -/** - * A string-like object which represents a sequence of CSS declarations - * ({@code propertyName1: propertyvalue1; propertyName2: propertyValue2; ...}) - * and that carries the security type contract that its value, as a string, - * will not cause untrusted script execution (XSS) when evaluated as CSS in a - * browser. - * - * Instances of this type must be created via the factory methods - * ({@code goog.html.SafeStyle.create} or - * {@code goog.html.SafeStyle.fromConstant}) and not by invoking its - * constructor. The constructor intentionally takes no parameters and the type - * is immutable; hence only a default instance corresponding to the empty string - * can be obtained via constructor invocation. - * - * SafeStyle's string representation can safely be: - * <ul> - * <li>Interpolated as the content of a *quoted* HTML style attribute. - * However, the SafeStyle string *must be HTML-attribute-escaped* before - * interpolation. - * <li>Interpolated as the content of a {}-wrapped block within a stylesheet. - * '<' characters in the SafeStyle string *must be CSS-escaped* before - * interpolation. The SafeStyle string is also guaranteed not to be able - * to introduce new properties or elide existing ones. - * <li>Interpolated as the content of a {}-wrapped block within an HTML - * <style> element. '<' characters in the SafeStyle string - * *must be CSS-escaped* before interpolation. - * <li>Assigned to the style property of a DOM node. The SafeStyle string - * should not be escaped before being assigned to the property. - * </ul> - * - * A SafeStyle may never contain literal angle brackets. Otherwise, it could - * be unsafe to place a SafeStyle into a <style> tag (where it can't - * be HTML escaped). For example, if the SafeStyle containing - * "{@code font: 'foo <style/><script>evil</script>'}" were - * interpolated within a <style> tag, this would then break out of the - * style context into HTML. - * - * A SafeStyle may contain literal single or double quotes, and as such the - * entire style string must be escaped when used in a style attribute (if - * this were not the case, the string could contain a matching quote that - * would escape from the style attribute). - * - * Values of this type must be composable, i.e. for any two values - * {@code style1} and {@code style2} of this type, - * {@code goog.html.SafeStyle.unwrap(style1) + - * goog.html.SafeStyle.unwrap(style2)} must itself be a value that satisfies - * the SafeStyle type constraint. This requirement implies that for any value - * {@code style} of this type, {@code goog.html.SafeStyle.unwrap(style)} must - * not end in a "property value" or "property name" context. For example, - * a value of {@code background:url("} or {@code font-} would not satisfy the - * SafeStyle contract. This is because concatenating such strings with a - * second value that itself does not contain unsafe CSS can result in an - * overall string that does. For example, if {@code javascript:evil())"} is - * appended to {@code background:url("}, the resulting string may result in - * the execution of a malicious script. - * - * TODO(mlourenco): Consider whether we should implement UTF-8 interchange - * validity checks and blacklisting of newlines (including Unicode ones) and - * other whitespace characters (\t, \f). Document here if so and also update - * SafeStyle.fromConstant(). - * - * The following example values comply with this type's contract: - * <ul> - * <li><pre>width: 1em;</pre> - * <li><pre>height:1em;</pre> - * <li><pre>width: 1em;height: 1em;</pre> - * <li><pre>background:url('http://url');</pre> - * </ul> - * In addition, the empty string is safe for use in a CSS attribute. - * - * The following example values do NOT comply with this type's contract: - * <ul> - * <li><pre>background: red</pre> (missing a trailing semi-colon) - * <li><pre>background:</pre> (missing a value and a trailing semi-colon) - * <li><pre>1em</pre> (missing an attribute name, which provides context for - * the value) - * </ul> - * - * @see goog.html.SafeStyle#create - * @see goog.html.SafeStyle#fromConstant - * @see http://www.w3.org/TR/css3-syntax/ - * @constructor - * @final - * @struct - * @implements {goog.string.TypedString} - */ -goog.html.SafeStyle = function() { - /** - * The contained value of this SafeStyle. The field has a purposely - * ugly name to make (non-compiled) code that attempts to directly access this - * field stand out. - * @private {string} - */ - this.privateDoNotAccessOrElseSafeStyleWrappedValue_ = ''; - - /** - * A type marker used to implement additional run-time type checking. - * @see goog.html.SafeStyle#unwrap - * @const {!Object} - * @private - */ - this.SAFE_STYLE_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = - goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_; -}; - - -/** - * @override - * @const - */ -goog.html.SafeStyle.prototype.implementsGoogStringTypedString = true; - - -/** - * Type marker for the SafeStyle type, used to implement additional - * run-time type checking. - * @const {!Object} - * @private - */ -goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}; - - -/** - * Creates a SafeStyle object from a compile-time constant string. - * - * {@code style} should be in the format - * {@code name: value; [name: value; ...]} and must not have any < or > - * characters in it. This is so that SafeStyle's contract is preserved, - * allowing the SafeStyle to correctly be interpreted as a sequence of CSS - * declarations and without affecting the syntactic structure of any - * surrounding CSS and HTML. - * - * This method performs basic sanity checks on the format of {@code style} - * but does not constrain the format of {@code name} and {@code value}, except - * for disallowing tag characters. - * - * @param {!goog.string.Const} style A compile-time-constant string from which - * to create a SafeStyle. - * @return {!goog.html.SafeStyle} A SafeStyle object initialized to - * {@code style}. - */ -goog.html.SafeStyle.fromConstant = function(style) { - var styleString = goog.string.Const.unwrap(style); - if (styleString.length === 0) { - return goog.html.SafeStyle.EMPTY; - } - goog.html.SafeStyle.checkStyle_(styleString); - goog.asserts.assert( - goog.string.endsWith(styleString, ';'), - 'Last character of style string is not \';\': ' + styleString); - goog.asserts.assert( - goog.string.contains(styleString, ':'), - 'Style string must contain at least one \':\', to ' + - 'specify a "name: value" pair: ' + styleString); - return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse( - styleString); -}; - - -/** - * Checks if the style definition is valid. - * @param {string} style - * @private - */ -goog.html.SafeStyle.checkStyle_ = function(style) { - goog.asserts.assert( - !/[<>]/.test(style), 'Forbidden characters in style string: ' + style); -}; - - -/** - * Returns this SafeStyle's value as a string. - * - * IMPORTANT: In code where it is security relevant that an object's type is - * indeed {@code SafeStyle}, use {@code goog.html.SafeStyle.unwrap} instead of - * this method. If in doubt, assume that it's security relevant. In particular, - * note that goog.html functions which return a goog.html type do not guarantee - * the returned instance is of the right type. For example: - * - * <pre> - * var fakeSafeHtml = new String('fake'); - * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype; - * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml); - * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by - * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml - * // instanceof goog.html.SafeHtml. - * </pre> - * - * @see goog.html.SafeStyle#unwrap - * @override - */ -goog.html.SafeStyle.prototype.getTypedStringValue = function() { - return this.privateDoNotAccessOrElseSafeStyleWrappedValue_; -}; - - -if (goog.DEBUG) { - /** - * Returns a debug string-representation of this value. - * - * To obtain the actual string value wrapped in a SafeStyle, use - * {@code goog.html.SafeStyle.unwrap}. - * - * @see goog.html.SafeStyle#unwrap - * @override - */ - goog.html.SafeStyle.prototype.toString = function() { - return 'SafeStyle{' + this.privateDoNotAccessOrElseSafeStyleWrappedValue_ + - '}'; - }; -} - - -/** - * Performs a runtime check that the provided object is indeed a - * SafeStyle object, and returns its value. - * - * @param {!goog.html.SafeStyle} safeStyle The object to extract from. - * @return {string} The safeStyle object's contained string, unless - * the run-time type check fails. In that case, {@code unwrap} returns an - * innocuous string, or, if assertions are enabled, throws - * {@code goog.asserts.AssertionError}. - */ -goog.html.SafeStyle.unwrap = function(safeStyle) { - // Perform additional Run-time type-checking to ensure that - // safeStyle is indeed an instance of the expected type. This - // provides some additional protection against security bugs due to - // application code that disables type checks. - // Specifically, the following checks are performed: - // 1. The object is an instance of the expected type. - // 2. The object is not an instance of a subclass. - // 3. The object carries a type marker for the expected type. "Faking" an - // object requires a reference to the type marker, which has names intended - // to stand out in code reviews. - if (safeStyle instanceof goog.html.SafeStyle && - safeStyle.constructor === goog.html.SafeStyle && - safeStyle.SAFE_STYLE_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ === - goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) { - return safeStyle.privateDoNotAccessOrElseSafeStyleWrappedValue_; - } else { - goog.asserts.fail('expected object of type SafeStyle, got \'' + - safeStyle + '\' of type ' + goog.typeOf(safeStyle)); - return 'type_error:SafeStyle'; - } -}; - - -/** - * Package-internal utility method to create SafeStyle instances. - * - * @param {string} style The string to initialize the SafeStyle object with. - * @return {!goog.html.SafeStyle} The initialized SafeStyle object. - * @package - */ -goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse = function( - style) { - return new goog.html.SafeStyle().initSecurityPrivateDoNotAccessOrElse_(style); -}; - - -/** - * Called from createSafeStyleSecurityPrivateDoNotAccessOrElse(). This - * method exists only so that the compiler can dead code eliminate static - * fields (like EMPTY) when they're not accessed. - * @param {string} style - * @return {!goog.html.SafeStyle} - * @private - */ -goog.html.SafeStyle.prototype.initSecurityPrivateDoNotAccessOrElse_ = function( - style) { - this.privateDoNotAccessOrElseSafeStyleWrappedValue_ = style; - return this; -}; - - -/** - * A SafeStyle instance corresponding to the empty string. - * @const {!goog.html.SafeStyle} - */ -goog.html.SafeStyle.EMPTY = - goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(''); - - -/** - * The innocuous string generated by goog.html.SafeStyle.create when passed - * an unsafe value. - * @const {string} - */ -goog.html.SafeStyle.INNOCUOUS_STRING = 'zClosurez'; - - -/** - * A single property value. - * @typedef {string|!goog.string.Const|!goog.html.SafeUrl} - */ -goog.html.SafeStyle.PropertyValue; - - -/** - * Mapping of property names to their values. - * We don't support numbers even though some values might be numbers (e.g. - * line-height or 0 for any length). The reason is that most numeric values need - * units (e.g. '1px') and allowing numbers could cause users forgetting about - * them. - * @typedef {!Object<string, ?goog.html.SafeStyle.PropertyValue| - * ?Array<!goog.html.SafeStyle.PropertyValue>>} - */ -goog.html.SafeStyle.PropertyMap; - - -/** - * Creates a new SafeStyle object from the properties specified in the map. - * @param {goog.html.SafeStyle.PropertyMap} map Mapping of property names to - * their values, for example {'margin': '1px'}. Names must consist of - * [-_a-zA-Z0-9]. Values might be strings consisting of - * [-,.'"%_!# a-zA-Z0-9], where " and ' must be properly balanced. We also - * allow simple functions like rgb() and url() which sanitizes its contents. - * Other values must be wrapped in goog.string.Const. URLs might be passed - * as goog.html.SafeUrl which will be wrapped into url(""). We also support - * array whose elements are joined with ' '. Null value causes skipping the - * property. - * @return {!goog.html.SafeStyle} - * @throws {Error} If invalid name is provided. - * @throws {goog.asserts.AssertionError} If invalid value is provided. With - * disabled assertions, invalid value is replaced by - * goog.html.SafeStyle.INNOCUOUS_STRING. - */ -goog.html.SafeStyle.create = function(map) { - var style = ''; - for (var name in map) { - if (!/^[-_a-zA-Z0-9]+$/.test(name)) { - throw new Error('Name allows only [-_a-zA-Z0-9], got: ' + name); - } - var value = map[name]; - if (value == null) { - continue; - } - if (goog.isArray(value)) { - value = goog.array.map(value, goog.html.SafeStyle.sanitizePropertyValue_) - .join(' '); - } else { - value = goog.html.SafeStyle.sanitizePropertyValue_(value); - } - style += name + ':' + value + ';'; - } - if (!style) { - return goog.html.SafeStyle.EMPTY; - } - goog.html.SafeStyle.checkStyle_(style); - return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse( - style); -}; - - -/** - * Checks and converts value to string. - * @param {!goog.html.SafeStyle.PropertyValue} value - * @return {string} - * @private - */ -goog.html.SafeStyle.sanitizePropertyValue_ = function(value) { - if (value instanceof goog.html.SafeUrl) { - var url = goog.html.SafeUrl.unwrap(value); - return 'url("' + url.replace(/</g, '%3c').replace(/[\\"]/g, '\\$&') + '")'; - } - var result = value instanceof goog.string.Const ? - goog.string.Const.unwrap(value) : - goog.html.SafeStyle.sanitizePropertyValueString_(String(value)); - // These characters can be used to change context and we don't want that even - // with const values. - goog.asserts.assert(!/[{;}]/.test(result), 'Value does not allow [{;}].'); - return result; -}; - - -/** - * Checks string value. - * @param {string} value - * @return {string} - * @private - */ -goog.html.SafeStyle.sanitizePropertyValueString_ = function(value) { - var valueWithoutFunctions = - value.replace(goog.html.SafeUrl.FUNCTIONS_RE_, '$1') - .replace(goog.html.SafeUrl.URL_RE_, 'url'); - if (!goog.html.SafeStyle.VALUE_RE_.test(valueWithoutFunctions)) { - goog.asserts.fail( - 'String value allows only ' + goog.html.SafeStyle.VALUE_ALLOWED_CHARS_ + - ' and simple functions, got: ' + value); - return goog.html.SafeStyle.INNOCUOUS_STRING; - } else if (!goog.html.SafeStyle.hasBalancedQuotes_(value)) { - goog.asserts.fail('String value requires balanced quotes, got: ' + value); - return goog.html.SafeStyle.INNOCUOUS_STRING; - } - return goog.html.SafeStyle.sanitizeUrl_(value); -}; - - -/** - * Checks that quotes (" and ') are properly balanced inside a string. Assumes - * that neither escape (\) nor any other character that could result in - * breaking out of a string parsing context are allowed; - * see http://www.w3.org/TR/css3-syntax/#string-token-diagram. - * @param {string} value Untrusted CSS property value. - * @return {boolean} True if property value is safe with respect to quote - * balancedness. - * @private - */ -goog.html.SafeStyle.hasBalancedQuotes_ = function(value) { - var outsideSingle = true; - var outsideDouble = true; - for (var i = 0; i < value.length; i++) { - var c = value.charAt(i); - if (c == "'" && outsideDouble) { - outsideSingle = !outsideSingle; - } else if (c == '"' && outsideSingle) { - outsideDouble = !outsideDouble; - } - } - return outsideSingle && outsideDouble; -}; - - -/** - * Characters allowed in goog.html.SafeStyle.VALUE_RE_. - * @private {string} - */ -goog.html.SafeStyle.VALUE_ALLOWED_CHARS_ = '[-,."\'%_!# a-zA-Z0-9]'; - - -/** - * Regular expression for safe values. - * - * Quotes (" and ') are allowed, but a check must be done elsewhere to ensure - * they're balanced. - * - * ',' allows multiple values to be assigned to the same property - * (e.g. background-attachment or font-family) and hence could allow - * multiple values to get injected, but that should pose no risk of XSS. - * - * The expression checks only for XSS safety, not for CSS validity. - * @const {!RegExp} - * @private - */ -goog.html.SafeStyle.VALUE_RE_ = - new RegExp('^' + goog.html.SafeStyle.VALUE_ALLOWED_CHARS_ + '+$'); - - -/** - * Regular expression for url(). We support URLs allowed by - * https://www.w3.org/TR/css-syntax-3/#url-token-diagram without using escape - * sequences. Use percent-encoding if you need to use special characters like - * backslash. - * @private @const {!RegExp} - */ -goog.html.SafeUrl.URL_RE_ = new RegExp( - '\\b(url\\([ \t\n]*)(' + - '\'[ -&(-\\[\\]-~]*\'' + // Printable characters except ' and \. - '|"[ !#-\\[\\]-~]*"' + // Printable characters except " and \. - '|[!#-&*-\\[\\]-~]*' + // Printable characters except [ "'()\\]. - ')([ \t\n]*\\))', - 'g'); - - -/** - * Regular expression for simple functions. - * @private @const {!RegExp} - */ -goog.html.SafeUrl.FUNCTIONS_RE_ = new RegExp( - '\\b(hsl|hsla|rgb|rgba|(rotate|scale|translate)(X|Y|Z|3d)?)' + - '\\([-0-9a-z.%, ]+\\)', - 'g'); - - -/** - * Sanitize URLs inside url(). - * - * NOTE: We could also consider using CSS.escape once that's available in the - * browsers. However, loosely matching URL e.g. with url\(.*\) and then escaping - * the contents would result in a slightly different language than CSS leading - * to confusion of users. E.g. url(")") is valid in CSS but it would be invalid - * as seen by our parser. On the other hand, url(\) is invalid in CSS but our - * parser would be fine with it. - * - * @param {string} value Untrusted CSS property value. - * @return {string} - * @private - */ -goog.html.SafeStyle.sanitizeUrl_ = function(value) { - return value.replace( - goog.html.SafeUrl.URL_RE_, function(match, before, url, after) { - var quote = ''; - url = url.replace(/^(['"])(.*)\1$/, function(match, start, inside) { - quote = start; - return inside; - }); - var sanitized = goog.html.SafeUrl.sanitize(url).getTypedStringValue(); - return before + quote + sanitized + quote + after; - }); -}; - - -/** - * Creates a new SafeStyle object by concatenating the values. - * @param {...(!goog.html.SafeStyle|!Array<!goog.html.SafeStyle>)} var_args - * SafeStyles to concatenate. - * @return {!goog.html.SafeStyle} - */ -goog.html.SafeStyle.concat = function(var_args) { - var style = ''; - - /** - * @param {!goog.html.SafeStyle|!Array<!goog.html.SafeStyle>} argument - */ - var addArgument = function(argument) { - if (goog.isArray(argument)) { - goog.array.forEach(argument, addArgument); - } else { - style += goog.html.SafeStyle.unwrap(argument); - } - }; - - goog.array.forEach(arguments, addArgument); - if (!style) { - return goog.html.SafeStyle.EMPTY; - } - return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse( - style); -};
diff --git a/third_party/ink/closure/html/safestylesheet.js b/third_party/ink/closure/html/safestylesheet.js deleted file mode 100644 index f690dbda..0000000 --- a/third_party/ink/closure/html/safestylesheet.js +++ /dev/null
@@ -1,344 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview The SafeStyleSheet type and its builders. - * - * TODO(xtof): Link to document stating type contract. - */ - -goog.provide('goog.html.SafeStyleSheet'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.html.SafeStyle'); -goog.require('goog.object'); -goog.require('goog.string'); -goog.require('goog.string.Const'); -goog.require('goog.string.TypedString'); - - - -/** - * A string-like object which represents a CSS style sheet and that carries the - * security type contract that its value, as a string, will not cause untrusted - * script execution (XSS) when evaluated as CSS in a browser. - * - * Instances of this type must be created via the factory method - * {@code goog.html.SafeStyleSheet.fromConstant} and not by invoking its - * constructor. The constructor intentionally takes no parameters and the type - * is immutable; hence only a default instance corresponding to the empty string - * can be obtained via constructor invocation. - * - * A SafeStyleSheet's string representation can safely be interpolated as the - * content of a style element within HTML. The SafeStyleSheet string should - * not be escaped before interpolation. - * - * Values of this type must be composable, i.e. for any two values - * {@code styleSheet1} and {@code styleSheet2} of this type, - * {@code goog.html.SafeStyleSheet.unwrap(styleSheet1) + - * goog.html.SafeStyleSheet.unwrap(styleSheet2)} must itself be a value that - * satisfies the SafeStyleSheet type constraint. This requirement implies that - * for any value {@code styleSheet} of this type, - * {@code goog.html.SafeStyleSheet.unwrap(styleSheet1)} must end in - * "beginning of rule" context. - - * A SafeStyleSheet can be constructed via security-reviewed unchecked - * conversions. In this case producers of SafeStyleSheet must ensure themselves - * that the SafeStyleSheet does not contain unsafe script. Note in particular - * that {@code <} is dangerous, even when inside CSS strings, and so should - * always be forbidden or CSS-escaped in user controlled input. For example, if - * {@code </style><script>evil</script>"} were interpolated - * inside a CSS string, it would break out of the context of the original - * style element and {@code evil} would execute. Also note that within an HTML - * style (raw text) element, HTML character references, such as - * {@code &lt;}, are not allowed. See - * - http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements - * (similar considerations apply to the style element). - * - * @see goog.html.SafeStyleSheet#fromConstant - * @constructor - * @final - * @struct - * @implements {goog.string.TypedString} - */ -goog.html.SafeStyleSheet = function() { - /** - * The contained value of this SafeStyleSheet. The field has a purposely - * ugly name to make (non-compiled) code that attempts to directly access this - * field stand out. - * @private {string} - */ - this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ = ''; - - /** - * A type marker used to implement additional run-time type checking. - * @see goog.html.SafeStyleSheet#unwrap - * @const {!Object} - * @private - */ - this.SAFE_STYLE_SHEET_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = - goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_; -}; - - -/** - * @override - * @const - */ -goog.html.SafeStyleSheet.prototype.implementsGoogStringTypedString = true; - - -/** - * Type marker for the SafeStyleSheet type, used to implement additional - * run-time type checking. - * @const {!Object} - * @private - */ -goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}; - - -/** - * Creates a style sheet consisting of one selector and one style definition. - * Use {@link goog.html.SafeStyleSheet.concat} to create longer style sheets. - * This function doesn't support @import, @media and similar constructs. - * @param {string} selector CSS selector, e.g. '#id' or 'tag .class, #id'. We - * support CSS3 selectors: https://w3.org/TR/css3-selectors/#selectors. - * @param {!goog.html.SafeStyle.PropertyMap|!goog.html.SafeStyle} style Style - * definition associated with the selector. - * @return {!goog.html.SafeStyleSheet} - * @throws {Error} If invalid selector is provided. - */ -goog.html.SafeStyleSheet.createRule = function(selector, style) { - if (goog.string.contains(selector, '<')) { - throw new Error('Selector does not allow \'<\', got: ' + selector); - } - - // Remove strings. - var selectorToCheck = - selector.replace(/('|")((?!\1)[^\r\n\f\\]|\\[\s\S])*\1/g, ''); - - // Check characters allowed in CSS3 selectors. - if (!/^[-_a-zA-Z0-9#.:* ,>+~[\]()=^$|]+$/.test(selectorToCheck)) { - throw new Error( - 'Selector allows only [-_a-zA-Z0-9#.:* ,>+~[\\]()=^$|] and ' + - 'strings, got: ' + selector); - } - - // Check balanced () and []. - if (!goog.html.SafeStyleSheet.hasBalancedBrackets_(selectorToCheck)) { - throw new Error('() and [] in selector must be balanced, got: ' + selector); - } - - if (!(style instanceof goog.html.SafeStyle)) { - style = goog.html.SafeStyle.create(style); - } - var styleSheet = selector + '{' + goog.html.SafeStyle.unwrap(style) + '}'; - return goog.html.SafeStyleSheet - .createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheet); -}; - - -/** - * Checks if a string has balanced () and [] brackets. - * @param {string} s String to check. - * @return {boolean} - * @private - */ -goog.html.SafeStyleSheet.hasBalancedBrackets_ = function(s) { - var brackets = {'(': ')', '[': ']'}; - var expectedBrackets = []; - for (var i = 0; i < s.length; i++) { - var ch = s[i]; - if (brackets[ch]) { - expectedBrackets.push(brackets[ch]); - } else if (goog.object.contains(brackets, ch)) { - if (expectedBrackets.pop() != ch) { - return false; - } - } - } - return expectedBrackets.length == 0; -}; - - -/** - * Creates a new SafeStyleSheet object by concatenating values. - * @param {...(!goog.html.SafeStyleSheet|!Array<!goog.html.SafeStyleSheet>)} - * var_args Values to concatenate. - * @return {!goog.html.SafeStyleSheet} - */ -goog.html.SafeStyleSheet.concat = function(var_args) { - var result = ''; - - /** - * @param {!goog.html.SafeStyleSheet|!Array<!goog.html.SafeStyleSheet>} - * argument - */ - var addArgument = function(argument) { - if (goog.isArray(argument)) { - goog.array.forEach(argument, addArgument); - } else { - result += goog.html.SafeStyleSheet.unwrap(argument); - } - }; - - goog.array.forEach(arguments, addArgument); - return goog.html.SafeStyleSheet - .createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(result); -}; - - -/** - * Creates a SafeStyleSheet object from a compile-time constant string. - * - * {@code styleSheet} must not have any < characters in it, so that - * the syntactic structure of the surrounding HTML is not affected. - * - * @param {!goog.string.Const} styleSheet A compile-time-constant string from - * which to create a SafeStyleSheet. - * @return {!goog.html.SafeStyleSheet} A SafeStyleSheet object initialized to - * {@code styleSheet}. - */ -goog.html.SafeStyleSheet.fromConstant = function(styleSheet) { - var styleSheetString = goog.string.Const.unwrap(styleSheet); - if (styleSheetString.length === 0) { - return goog.html.SafeStyleSheet.EMPTY; - } - // > is a valid character in CSS selectors and there's no strict need to - // block it if we already block <. - goog.asserts.assert( - !goog.string.contains(styleSheetString, '<'), - "Forbidden '<' character in style sheet string: " + styleSheetString); - return goog.html.SafeStyleSheet - .createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheetString); -}; - - -/** - * Returns this SafeStyleSheet's value as a string. - * - * IMPORTANT: In code where it is security relevant that an object's type is - * indeed {@code SafeStyleSheet}, use {@code goog.html.SafeStyleSheet.unwrap} - * instead of this method. If in doubt, assume that it's security relevant. In - * particular, note that goog.html functions which return a goog.html type do - * not guarantee the returned instance is of the right type. For example: - * - * <pre> - * var fakeSafeHtml = new String('fake'); - * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype; - * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml); - * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by - * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml - * // instanceof goog.html.SafeHtml. - * </pre> - * - * @see goog.html.SafeStyleSheet#unwrap - * @override - */ -goog.html.SafeStyleSheet.prototype.getTypedStringValue = function() { - return this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_; -}; - - -if (goog.DEBUG) { - /** - * Returns a debug string-representation of this value. - * - * To obtain the actual string value wrapped in a SafeStyleSheet, use - * {@code goog.html.SafeStyleSheet.unwrap}. - * - * @see goog.html.SafeStyleSheet#unwrap - * @override - */ - goog.html.SafeStyleSheet.prototype.toString = function() { - return 'SafeStyleSheet{' + - this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ + '}'; - }; -} - - -/** - * Performs a runtime check that the provided object is indeed a - * SafeStyleSheet object, and returns its value. - * - * @param {!goog.html.SafeStyleSheet} safeStyleSheet The object to extract from. - * @return {string} The safeStyleSheet object's contained string, unless - * the run-time type check fails. In that case, {@code unwrap} returns an - * innocuous string, or, if assertions are enabled, throws - * {@code goog.asserts.AssertionError}. - */ -goog.html.SafeStyleSheet.unwrap = function(safeStyleSheet) { - // Perform additional Run-time type-checking to ensure that - // safeStyleSheet is indeed an instance of the expected type. This - // provides some additional protection against security bugs due to - // application code that disables type checks. - // Specifically, the following checks are performed: - // 1. The object is an instance of the expected type. - // 2. The object is not an instance of a subclass. - // 3. The object carries a type marker for the expected type. "Faking" an - // object requires a reference to the type marker, which has names intended - // to stand out in code reviews. - if (safeStyleSheet instanceof goog.html.SafeStyleSheet && - safeStyleSheet.constructor === goog.html.SafeStyleSheet && - safeStyleSheet - .SAFE_STYLE_SHEET_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ === - goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) { - return safeStyleSheet.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_; - } else { - goog.asserts.fail('expected object of type SafeStyleSheet, got \'' + - safeStyleSheet + '\' of type ' + goog.typeOf(safeStyleSheet)); - return 'type_error:SafeStyleSheet'; - } -}; - - -/** - * Package-internal utility method to create SafeStyleSheet instances. - * - * @param {string} styleSheet The string to initialize the SafeStyleSheet - * object with. - * @return {!goog.html.SafeStyleSheet} The initialized SafeStyleSheet object. - * @package - */ -goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse = - function(styleSheet) { - return new goog.html.SafeStyleSheet().initSecurityPrivateDoNotAccessOrElse_( - styleSheet); -}; - - -/** - * Called from createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(). This - * method exists only so that the compiler can dead code eliminate static - * fields (like EMPTY) when they're not accessed. - * @param {string} styleSheet - * @return {!goog.html.SafeStyleSheet} - * @private - */ -goog.html.SafeStyleSheet.prototype.initSecurityPrivateDoNotAccessOrElse_ = - function(styleSheet) { - this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ = styleSheet; - return this; -}; - - -/** - * A SafeStyleSheet instance corresponding to the empty string. - * @const {!goog.html.SafeStyleSheet} - */ -goog.html.SafeStyleSheet.EMPTY = - goog.html.SafeStyleSheet - .createSafeStyleSheetSecurityPrivateDoNotAccessOrElse('');
diff --git a/third_party/ink/closure/html/safeurl.js b/third_party/ink/closure/html/safeurl.js deleted file mode 100644 index 3d1ee112..0000000 --- a/third_party/ink/closure/html/safeurl.js +++ /dev/null
@@ -1,454 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview The SafeUrl type and its builders. - * - * TODO(xtof): Link to document stating type contract. - */ - -goog.provide('goog.html.SafeUrl'); - -goog.require('goog.asserts'); -goog.require('goog.fs.url'); -goog.require('goog.html.TrustedResourceUrl'); -goog.require('goog.i18n.bidi.Dir'); -goog.require('goog.i18n.bidi.DirectionalString'); -goog.require('goog.string'); -goog.require('goog.string.Const'); -goog.require('goog.string.TypedString'); - - - -/** - * A string that is safe to use in URL context in DOM APIs and HTML documents. - * - * A SafeUrl is a string-like object that carries the security type contract - * that its value as a string will not cause untrusted script execution - * when evaluated as a hyperlink URL in a browser. - * - * Values of this type are guaranteed to be safe to use in URL/hyperlink - * contexts, such as assignment to URL-valued DOM properties, in the sense that - * the use will not result in a Cross-Site-Scripting vulnerability. Similarly, - * SafeUrls can be interpolated into the URL context of an HTML template (e.g., - * inside a href attribute). However, appropriate HTML-escaping must still be - * applied. - * - * Note that, as documented in {@code goog.html.SafeUrl.unwrap}, this type's - * contract does not guarantee that instances are safe to interpolate into HTML - * without appropriate escaping. - * - * Note also that this type's contract does not imply any guarantees regarding - * the resource the URL refers to. In particular, SafeUrls are <b>not</b> - * safe to use in a context where the referred-to resource is interpreted as - * trusted code, e.g., as the src of a script tag. - * - * Instances of this type must be created via the factory methods - * ({@code goog.html.SafeUrl.fromConstant}, {@code goog.html.SafeUrl.sanitize}), - * etc and not by invoking its constructor. The constructor intentionally - * takes no parameters and the type is immutable; hence only a default instance - * corresponding to the empty string can be obtained via constructor invocation. - * - * @see goog.html.SafeUrl#fromConstant - * @see goog.html.SafeUrl#from - * @see goog.html.SafeUrl#sanitize - * @constructor - * @final - * @struct - * @implements {goog.i18n.bidi.DirectionalString} - * @implements {goog.string.TypedString} - */ -goog.html.SafeUrl = function() { - /** - * The contained value of this SafeUrl. The field has a purposely ugly - * name to make (non-compiled) code that attempts to directly access this - * field stand out. - * @private {string} - */ - this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = ''; - - /** - * A type marker used to implement additional run-time type checking. - * @see goog.html.SafeUrl#unwrap - * @const {!Object} - * @private - */ - this.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = - goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_; -}; - - -/** - * The innocuous string generated by goog.html.SafeUrl.sanitize when passed - * an unsafe URL. - * - * about:invalid is registered in - * http://www.w3.org/TR/css3-values/#about-invalid. - * http://tools.ietf.org/html/rfc6694#section-2.2.1 permits about URLs to - * contain a fragment, which is not to be considered when determining if an - * about URL is well-known. - * - * Using about:invalid seems preferable to using a fixed data URL, since - * browsers might choose to not report CSP violations on it, as legitimate - * CSS function calls to attr() can result in this URL being produced. It is - * also a standard URL which matches exactly the semantics we need: - * "The about:invalid URI references a non-existent document with a generic - * error condition. It can be used when a URI is necessary, but the default - * value shouldn't be resolveable as any type of document". - * - * @const {string} - */ -goog.html.SafeUrl.INNOCUOUS_STRING = 'about:invalid#zClosurez'; - - -/** - * @override - * @const - */ -goog.html.SafeUrl.prototype.implementsGoogStringTypedString = true; - - -/** - * Returns this SafeUrl's value a string. - * - * IMPORTANT: In code where it is security relevant that an object's type is - * indeed {@code SafeUrl}, use {@code goog.html.SafeUrl.unwrap} instead of this - * method. If in doubt, assume that it's security relevant. In particular, note - * that goog.html functions which return a goog.html type do not guarantee that - * the returned instance is of the right type. For example: - * - * <pre> - * var fakeSafeHtml = new String('fake'); - * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype; - * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml); - * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by - * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml instanceof - * // goog.html.SafeHtml. - * </pre> - * - * IMPORTANT: The guarantees of the SafeUrl type contract only extend to the - * behavior of browsers when interpreting URLs. Values of SafeUrl objects MUST - * be appropriately escaped before embedding in a HTML document. Note that the - * required escaping is context-sensitive (e.g. a different escaping is - * required for embedding a URL in a style property within a style - * attribute, as opposed to embedding in a href attribute). - * - * @see goog.html.SafeUrl#unwrap - * @override - */ -goog.html.SafeUrl.prototype.getTypedStringValue = function() { - return this.privateDoNotAccessOrElseSafeHtmlWrappedValue_; -}; - - -/** - * @override - * @const - */ -goog.html.SafeUrl.prototype.implementsGoogI18nBidiDirectionalString = true; - - -/** - * Returns this URLs directionality, which is always {@code LTR}. - * @override - */ -goog.html.SafeUrl.prototype.getDirection = function() { - return goog.i18n.bidi.Dir.LTR; -}; - - -if (goog.DEBUG) { - /** - * Returns a debug string-representation of this value. - * - * To obtain the actual string value wrapped in a SafeUrl, use - * {@code goog.html.SafeUrl.unwrap}. - * - * @see goog.html.SafeUrl#unwrap - * @override - */ - goog.html.SafeUrl.prototype.toString = function() { - return 'SafeUrl{' + this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ + - '}'; - }; -} - - -/** - * Performs a runtime check that the provided object is indeed a SafeUrl - * object, and returns its value. - * - * IMPORTANT: The guarantees of the SafeUrl type contract only extend to the - * behavior of browsers when interpreting URLs. Values of SafeUrl objects MUST - * be appropriately escaped before embedding in a HTML document. Note that the - * required escaping is context-sensitive (e.g. a different escaping is - * required for embedding a URL in a style property within a style - * attribute, as opposed to embedding in a href attribute). - * - * @param {!goog.html.SafeUrl} safeUrl The object to extract from. - * @return {string} The SafeUrl object's contained string, unless the run-time - * type check fails. In that case, {@code unwrap} returns an innocuous - * string, or, if assertions are enabled, throws - * {@code goog.asserts.AssertionError}. - */ -goog.html.SafeUrl.unwrap = function(safeUrl) { - // Perform additional Run-time type-checking to ensure that safeUrl is indeed - // an instance of the expected type. This provides some additional protection - // against security bugs due to application code that disables type checks. - // Specifically, the following checks are performed: - // 1. The object is an instance of the expected type. - // 2. The object is not an instance of a subclass. - // 3. The object carries a type marker for the expected type. "Faking" an - // object requires a reference to the type marker, which has names intended - // to stand out in code reviews. - if (safeUrl instanceof goog.html.SafeUrl && - safeUrl.constructor === goog.html.SafeUrl && - safeUrl.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ === - goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) { - return safeUrl.privateDoNotAccessOrElseSafeHtmlWrappedValue_; - } else { - goog.asserts.fail('expected object of type SafeUrl, got \'' + - safeUrl + '\' of type ' + goog.typeOf(safeUrl)); - return 'type_error:SafeUrl'; - } -}; - - -/** - * Creates a SafeUrl object from a compile-time constant string. - * - * Compile-time constant strings are inherently program-controlled and hence - * trusted. - * - * @param {!goog.string.Const} url A compile-time-constant string from which to - * create a SafeUrl. - * @return {!goog.html.SafeUrl} A SafeUrl object initialized to {@code url}. - */ -goog.html.SafeUrl.fromConstant = function(url) { - return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse( - goog.string.Const.unwrap(url)); -}; - - -/** - * A pattern that matches Blob or data types that can have SafeUrls created - * from URL.createObjectURL(blob) or via a data: URI. - * @const - * @private - */ -goog.html.SAFE_MIME_TYPE_PATTERN_ = new RegExp( - '^(?:audio/(?:3gpp|3gpp2|aac|midi|mp4|mpeg|ogg|x-m4a|x-wav|webm)|' + - 'image/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|' + - 'text/csv|' + - 'video/(?:mpeg|mp4|ogg|webm))$', - 'i'); - - -/** - * Creates a SafeUrl wrapping a blob URL for the given {@code blob}. - * - * The blob URL is created with {@code URL.createObjectURL}. If the MIME type - * for {@code blob} is not of a known safe audio, image or video MIME type, - * then the SafeUrl will wrap {@link #INNOCUOUS_STRING}. - * - * @see http://www.w3.org/TR/FileAPI/#url - * @param {!Blob} blob - * @return {!goog.html.SafeUrl} The blob URL, or an innocuous string wrapped - * as a SafeUrl. - */ -goog.html.SafeUrl.fromBlob = function(blob) { - var url = goog.html.SAFE_MIME_TYPE_PATTERN_.test(blob.type) ? - goog.fs.url.createObjectUrl(blob) : - goog.html.SafeUrl.INNOCUOUS_STRING; - return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url); -}; - - -/** - * Matches a base-64 data URL, with the first match group being the MIME type. - * @const - * @private - */ -goog.html.DATA_URL_PATTERN_ = /^data:([^;,]*);base64,[a-z0-9+\/]+=*$/i; - - -/** - * Creates a SafeUrl wrapping a data: URL, after validating it matches a - * known-safe audio, image or video MIME type. - * - * @param {string} dataUrl A valid base64 data URL with one of the whitelisted - * audio, image or video MIME types. - * @return {!goog.html.SafeUrl} A matching safe URL, or {@link INNOCUOUS_STRING} - * wrapped as a SafeUrl if it does not pass. - */ -goog.html.SafeUrl.fromDataUrl = function(dataUrl) { - // There's a slight risk here that a browser sniffs the content type if it - // doesn't know the MIME type and executes HTML within the data: URL. For this - // to cause XSS it would also have to execute the HTML in the same origin - // of the page with the link. It seems unlikely that both of these will - // happen, particularly in not really old IEs. - var match = dataUrl.match(goog.html.DATA_URL_PATTERN_); - var valid = match && goog.html.SAFE_MIME_TYPE_PATTERN_.test(match[1]); - return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse( - valid ? dataUrl : goog.html.SafeUrl.INNOCUOUS_STRING); -}; - - -/** - * Creates a SafeUrl wrapping a tel: URL. - * - * @param {string} telUrl A tel URL. - * @return {!goog.html.SafeUrl} A matching safe URL, or {@link INNOCUOUS_STRING} - * wrapped as a SafeUrl if it does not pass. - */ -goog.html.SafeUrl.fromTelUrl = function(telUrl) { - // There's a risk that a tel: URL could immediately place a call once - // clicked, without requiring user confirmation. For that reason it is - // handled in this separate function. - if (!goog.string.caseInsensitiveStartsWith(telUrl, 'tel:')) { - telUrl = goog.html.SafeUrl.INNOCUOUS_STRING; - } - return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse( - telUrl); -}; - - -/** - * Creates a SafeUrl from TrustedResourceUrl. This is safe because - * TrustedResourceUrl is more tightly restricted than SafeUrl. - * - * @param {!goog.html.TrustedResourceUrl} trustedResourceUrl - * @return {!goog.html.SafeUrl} - */ -goog.html.SafeUrl.fromTrustedResourceUrl = function(trustedResourceUrl) { - return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse( - goog.html.TrustedResourceUrl.unwrap(trustedResourceUrl)); -}; - - -/** - * A pattern that recognizes a commonly useful subset of URLs that satisfy - * the SafeUrl contract. - * - * This regular expression matches a subset of URLs that will not cause script - * execution if used in URL context within a HTML document. Specifically, this - * regular expression matches if (comment from here on and regex copied from - * Soy's EscapingConventions): - * (1) Either a protocol in a whitelist (http, https, mailto or ftp). - * (2) or no protocol. A protocol must be followed by a colon. The below - * allows that by allowing colons only after one of the characters [/?#]. - * A colon after a hash (#) must be in the fragment. - * Otherwise, a colon after a (?) must be in a query. - * Otherwise, a colon after a single solidus (/) must be in a path. - * Otherwise, a colon after a double solidus (//) must be in the authority - * (before port). - * - * @private - * @const {!RegExp} - */ -goog.html.SAFE_URL_PATTERN_ = - /^(?:(?:https?|mailto|ftp):|[^:/?#]*(?:[/?#]|$))/i; - - -/** - * Creates a SafeUrl object from {@code url}. If {@code url} is a - * goog.html.SafeUrl then it is simply returned. Otherwise the input string is - * validated to match a pattern of commonly used safe URLs. - * - * {@code url} may be a URL with the http, https, mailto or ftp scheme, - * or a relative URL (i.e., a URL without a scheme; specifically, a - * scheme-relative, absolute-path-relative, or path-relative URL). - * - * @see http://url.spec.whatwg.org/#concept-relative-url - * @param {string|!goog.string.TypedString} url The URL to validate. - * @return {!goog.html.SafeUrl} The validated URL, wrapped as a SafeUrl. - */ -goog.html.SafeUrl.sanitize = function(url) { - if (url instanceof goog.html.SafeUrl) { - return url; - } else if (url.implementsGoogStringTypedString) { - url = url.getTypedStringValue(); - } else { - url = String(url); - } - if (!goog.html.SAFE_URL_PATTERN_.test(url)) { - url = goog.html.SafeUrl.INNOCUOUS_STRING; - } - return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url); -}; - -/** - * Creates a SafeUrl object from {@code url}. If {@code url} is a - * goog.html.SafeUrl then it is simply returned. Otherwise the input string is - * validated to match a pattern of commonly used safe URLs. - * - * {@code url} may be a URL with the http, https, mailto or ftp scheme, - * or a relative URL (i.e., a URL without a scheme; specifically, a - * scheme-relative, absolute-path-relative, or path-relative URL). - * - * This function asserts (using goog.asserts) that the URL matches this pattern. - * If it does not, in addition to failing the assert, an innocous URL will be - * returned. - * - * @see http://url.spec.whatwg.org/#concept-relative-url - * @param {string|!goog.string.TypedString} url The URL to validate. - * @return {!goog.html.SafeUrl} The validated URL, wrapped as a SafeUrl. - */ -goog.html.SafeUrl.sanitizeAssertUnchanged = function(url) { - if (url instanceof goog.html.SafeUrl) { - return url; - } else if (url.implementsGoogStringTypedString) { - url = url.getTypedStringValue(); - } else { - url = String(url); - } - if (!goog.asserts.assert(goog.html.SAFE_URL_PATTERN_.test(url))) { - url = goog.html.SafeUrl.INNOCUOUS_STRING; - } - return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url); -}; - - - -/** - * Type marker for the SafeUrl type, used to implement additional run-time - * type checking. - * @const {!Object} - * @private - */ -goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}; - - -/** - * Package-internal utility method to create SafeUrl instances. - * - * @param {string} url The string to initialize the SafeUrl object with. - * @return {!goog.html.SafeUrl} The initialized SafeUrl object. - * @package - */ -goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse = function( - url) { - var safeUrl = new goog.html.SafeUrl(); - safeUrl.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = url; - return safeUrl; -}; - - -/** - * A SafeUrl corresponding to the special about:blank url. - * @const {!goog.html.SafeUrl} - */ -goog.html.SafeUrl.ABOUT_BLANK = - goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse( - 'about:blank');
diff --git a/third_party/ink/closure/html/trustedresourceurl.js b/third_party/ink/closure/html/trustedresourceurl.js deleted file mode 100644 index b7a67bc..0000000 --- a/third_party/ink/closure/html/trustedresourceurl.js +++ /dev/null
@@ -1,412 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview The TrustedResourceUrl type and its builders. - * - * TODO(xtof): Link to document stating type contract. - */ - -goog.provide('goog.html.TrustedResourceUrl'); - -goog.require('goog.asserts'); -goog.require('goog.i18n.bidi.Dir'); -goog.require('goog.i18n.bidi.DirectionalString'); -goog.require('goog.string.Const'); -goog.require('goog.string.TypedString'); - - - -/** - * A URL which is under application control and from which script, CSS, and - * other resources that represent executable code, can be fetched. - * - * Given that the URL can only be constructed from strings under application - * control and is used to load resources, bugs resulting in a malformed URL - * should not have a security impact and are likely to be easily detectable - * during testing. Given the wide number of non-RFC compliant URLs in use, - * stricter validation could prevent some applications from being able to use - * this type. - * - * Instances of this type must be created via the factory method, - * ({@code fromConstant}, {@code fromConstants}, {@code format} or {@code - * formatWithParams}), and not by invoking its constructor. The constructor - * intentionally takes no parameters and the type is immutable; hence only a - * default instance corresponding to the empty string can be obtained via - * constructor invocation. - * - * @see goog.html.TrustedResourceUrl#fromConstant - * @constructor - * @final - * @struct - * @implements {goog.i18n.bidi.DirectionalString} - * @implements {goog.string.TypedString} - */ -goog.html.TrustedResourceUrl = function() { - /** - * The contained value of this TrustedResourceUrl. The field has a purposely - * ugly name to make (non-compiled) code that attempts to directly access this - * field stand out. - * @private {string} - */ - this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ = ''; - - /** - * A type marker used to implement additional run-time type checking. - * @see goog.html.TrustedResourceUrl#unwrap - * @const {!Object} - * @private - */ - this.TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = - goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_; -}; - - -/** - * @override - * @const - */ -goog.html.TrustedResourceUrl.prototype.implementsGoogStringTypedString = true; - - -/** - * Returns this TrustedResourceUrl's value as a string. - * - * IMPORTANT: In code where it is security relevant that an object's type is - * indeed {@code TrustedResourceUrl}, use - * {@code goog.html.TrustedResourceUrl.unwrap} instead of this method. If in - * doubt, assume that it's security relevant. In particular, note that - * goog.html functions which return a goog.html type do not guarantee that - * the returned instance is of the right type. For example: - * - * <pre> - * var fakeSafeHtml = new String('fake'); - * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype; - * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml); - * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by - * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml instanceof - * // goog.html.SafeHtml. - * </pre> - * - * @see goog.html.TrustedResourceUrl#unwrap - * @override - */ -goog.html.TrustedResourceUrl.prototype.getTypedStringValue = function() { - return this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_; -}; - - -/** - * @override - * @const - */ -goog.html.TrustedResourceUrl.prototype.implementsGoogI18nBidiDirectionalString = - true; - - -/** - * Returns this URLs directionality, which is always {@code LTR}. - * @override - */ -goog.html.TrustedResourceUrl.prototype.getDirection = function() { - return goog.i18n.bidi.Dir.LTR; -}; - - -if (goog.DEBUG) { - /** - * Returns a debug string-representation of this value. - * - * To obtain the actual string value wrapped in a TrustedResourceUrl, use - * {@code goog.html.TrustedResourceUrl.unwrap}. - * - * @see goog.html.TrustedResourceUrl#unwrap - * @override - */ - goog.html.TrustedResourceUrl.prototype.toString = function() { - return 'TrustedResourceUrl{' + - this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ + '}'; - }; -} - - -/** - * Performs a runtime check that the provided object is indeed a - * TrustedResourceUrl object, and returns its value. - * - * @param {!goog.html.TrustedResourceUrl} trustedResourceUrl The object to - * extract from. - * @return {string} The trustedResourceUrl object's contained string, unless - * the run-time type check fails. In that case, {@code unwrap} returns an - * innocuous string, or, if assertions are enabled, throws - * {@code goog.asserts.AssertionError}. - */ -goog.html.TrustedResourceUrl.unwrap = function(trustedResourceUrl) { - // Perform additional Run-time type-checking to ensure that - // trustedResourceUrl is indeed an instance of the expected type. This - // provides some additional protection against security bugs due to - // application code that disables type checks. - // Specifically, the following checks are performed: - // 1. The object is an instance of the expected type. - // 2. The object is not an instance of a subclass. - // 3. The object carries a type marker for the expected type. "Faking" an - // object requires a reference to the type marker, which has names intended - // to stand out in code reviews. - if (trustedResourceUrl instanceof goog.html.TrustedResourceUrl && - trustedResourceUrl.constructor === goog.html.TrustedResourceUrl && - trustedResourceUrl - .TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ === - goog.html.TrustedResourceUrl - .TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) { - return trustedResourceUrl - .privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_; - } else { - goog.asserts.fail('expected object of type TrustedResourceUrl, got \'' + - trustedResourceUrl + '\' of type ' + goog.typeOf(trustedResourceUrl)); - return 'type_error:TrustedResourceUrl'; - } -}; - - -/** - * Creates a TrustedResourceUrl from a format string and arguments. - * - * The arguments for interpolation into the format string map labels to values. - * Values of type `goog.string.Const` are interpolated without modifcation. - * Values of other types are cast to string and encoded with - * encodeURIComponent. - * - * `%{<label>}` markers are used in the format string to indicate locations - * to be interpolated with the valued mapped to the given label. `<label>` - * must contain only alphanumeric and `_` characters. - * - * The format string must start with one of the following: - * - `https://<origin>/` - * - `//<origin>/` - * - `/<pathStart>` - * - `about:blank` - * - * `<origin>` must contain only alphanumeric or any of the following: `-.:[]`. - * `<pathStart>` is any character except `/` and `\`. - * - * Example usage: - * - * var url = goog.html.TrustedResourceUrl.format(goog.string.Const.from( - * 'https://www.google.com/search?q=%{query}), {'query': searchTerm}); - * - * var url = goog.html.TrustedResourceUrl.format(goog.string.Const.from( - * '//www.youtube.com/v/%{videoId}?hl=en&fs=1%{autoplay}'), { - * 'videoId': videoId, - * 'autoplay': opt_autoplay ? - * goog.string.Const.from('&autoplay=1') : goog.string.Const.EMPTY - * }); - * - * While this function can be used to create a TrustedResourceUrl from only - * constants, fromConstant() and fromConstants() are generally preferable for - * that purpose. - * - * @param {!goog.string.Const} format The format string. - * @param {!Object<string, (string|number|!goog.string.Const)>} args Mapping - * of labels to values to be interpolated into the format string. - * goog.string.Const values are interpolated without encoding. - * @return {!goog.html.TrustedResourceUrl} - * @throws {!Error} On an invalid format string or if a label used in the - * the format string is not present in args. - */ -goog.html.TrustedResourceUrl.format = function(format, args) { - var result = goog.html.TrustedResourceUrl.format_(format, args); - return goog.html.TrustedResourceUrl - .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(result); -}; - - -/** - * String version of TrustedResourceUrl.format. - * @param {!goog.string.Const} format - * @param {!Object<string, (string|number|!goog.string.Const)>} args - * @return {string} - * @throws {!Error} - * @private - */ -goog.html.TrustedResourceUrl.format_ = function(format, args) { - var formatStr = goog.string.Const.unwrap(format); - if (!goog.html.TrustedResourceUrl.BASE_URL_.test(formatStr)) { - throw new Error('Invalid TrustedResourceUrl format: ' + formatStr); - } - return formatStr.replace( - goog.html.TrustedResourceUrl.FORMAT_MARKER_, function(match, id) { - if (!Object.prototype.hasOwnProperty.call(args, id)) { - throw new Error( - 'Found marker, "' + id + '", in format string, "' + formatStr + - '", but no valid label mapping found ' + - 'in args: ' + JSON.stringify(args)); - } - var arg = args[id]; - if (arg instanceof goog.string.Const) { - return goog.string.Const.unwrap(arg); - } else { - return encodeURIComponent(String(arg)); - } - }); -}; - - -/** - * @private @const {!RegExp} - */ -goog.html.TrustedResourceUrl.FORMAT_MARKER_ = /%{(\w+)}/g; - - -/** - * The URL must be absolute, scheme-relative or path-absolute. So it must - * start with: - * - https:// followed by allowed origin characters. - * - // followed by allowed origin characters. - * - / not followed by / or \. There will only be an absolute path. - * - * Based on - * https://url.spec.whatwg.org/commit-snapshots/56b74ce7cca8883eab62e9a12666e2fac665d03d/#url-parsing - * an initial / which is not followed by another / or \ will end up in the "path - * state" and from there it can only go to "fragment state" and "query state". - * - * We don't enforce a well-formed domain name. So '.' or '1.2' are valid. - * That's ok because the origin comes from a compile-time constant. - * - * A regular expression is used instead of goog.uri for several reasons: - * - Strictness. E.g. we don't want any userinfo component and we don't - * want '/./, nor \' in the first path component. - * - Small trusted base. goog.uri is generic and might need to change, - * reasoning about all the ways it can parse a URL now and in the future - * is error-prone. - * - Code size. We expect many calls to .format(), many of which might - * not be using goog.uri. - * - Simplicity. Using goog.uri would likely not result in simpler nor shorter - * code. - * @private @const {!RegExp} - */ -goog.html.TrustedResourceUrl.BASE_URL_ = - /^(?:https:)?\/\/[0-9a-z.:[\]-]+\/|^\/[^\/\\]|^about:blank(#|$)/i; - - -/** - * Formats the URL same as TrustedResourceUrl.format and then adds extra URL - * parameters. - * - * Example usage: - * - * // Creates '//www.youtube.com/v/abc?autoplay=1' for videoId='abc' and - * // opt_autoplay=1. Creates '//www.youtube.com/v/abc' for videoId='abc' - * // and opt_autoplay=undefined. - * var url = goog.html.TrustedResourceUrl.formatWithParams( - * goog.string.Const.from('//www.youtube.com/v/%{videoId}'), - * {'videoId': videoId}, - * {'autoplay': opt_autoplay}); - * - * @param {!goog.string.Const} format The format string. - * @param {!Object<string, (string|number|!goog.string.Const)>} args Mapping - * of labels to values to be interpolated into the format string. - * goog.string.Const values are interpolated without encoding. - * @param {!Object<string, *>} params Parameters to add to URL. Parameters with - * value {@code null} or {@code undefined} are skipped. Both keys and values - * are encoded. If the value is an array then the same parameter is added - * for every element in the array. Note that JavaScript doesn't guarantee - * the order of values in an object which might result in non-deterministic - * order of the parameters. However, browsers currently preserve the order. - * @return {!goog.html.TrustedResourceUrl} - * @throws {!Error} On an invalid format string or if a label used in the - * the format string is not present in args. - */ -goog.html.TrustedResourceUrl.formatWithParams = function(format, args, params) { - var url = goog.html.TrustedResourceUrl.format_(format, args); - var separator = /\?/.test(url) ? '&' : '?'; - for (var key in params) { - var values = goog.isArray(params[key]) ? params[key] : [params[key]]; - for (var i = 0; i < values.length; i++) { - if (values[i] == null) { - continue; - } - url += separator + encodeURIComponent(key) + '=' + - encodeURIComponent(String(values[i])); - separator = '&'; - } - } - return goog.html.TrustedResourceUrl - .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(url); -}; - - -/** - * Creates a TrustedResourceUrl object from a compile-time constant string. - * - * Compile-time constant strings are inherently program-controlled and hence - * trusted. - * - * @param {!goog.string.Const} url A compile-time-constant string from which to - * create a TrustedResourceUrl. - * @return {!goog.html.TrustedResourceUrl} A TrustedResourceUrl object - * initialized to {@code url}. - */ -goog.html.TrustedResourceUrl.fromConstant = function(url) { - return goog.html.TrustedResourceUrl - .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse( - goog.string.Const.unwrap(url)); -}; - - -/** - * Creates a TrustedResourceUrl object from a compile-time constant strings. - * - * Compile-time constant strings are inherently program-controlled and hence - * trusted. - * - * @param {!Array<!goog.string.Const>} parts Compile-time-constant strings from - * which to create a TrustedResourceUrl. - * @return {!goog.html.TrustedResourceUrl} A TrustedResourceUrl object - * initialized to concatenation of {@code parts}. - */ -goog.html.TrustedResourceUrl.fromConstants = function(parts) { - var unwrapped = ''; - for (var i = 0; i < parts.length; i++) { - unwrapped += goog.string.Const.unwrap(parts[i]); - } - return goog.html.TrustedResourceUrl - .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(unwrapped); -}; - - -/** - * Type marker for the TrustedResourceUrl type, used to implement additional - * run-time type checking. - * @const {!Object} - * @private - */ -goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}; - - -/** - * Package-internal utility method to create TrustedResourceUrl instances. - * - * @param {string} url The string to initialize the TrustedResourceUrl object - * with. - * @return {!goog.html.TrustedResourceUrl} The initialized TrustedResourceUrl - * object. - * @package - */ -goog.html.TrustedResourceUrl - .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse = function(url) { - var trustedResourceUrl = new goog.html.TrustedResourceUrl(); - trustedResourceUrl.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ = - url; - return trustedResourceUrl; -};
diff --git a/third_party/ink/closure/html/uncheckedconversions.js b/third_party/ink/closure/html/uncheckedconversions.js deleted file mode 100644 index e75dfa2..0000000 --- a/third_party/ink/closure/html/uncheckedconversions.js +++ /dev/null
@@ -1,254 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Unchecked conversions to create values of goog.html types from - * plain strings. Use of these functions could potentially result in instances - * of goog.html types that violate their type contracts, and hence result in - * security vulnerabilties. - * - * Therefore, all uses of the methods herein must be carefully security - * reviewed. Avoid use of the methods in this file whenever possible; instead - * prefer to create instances of goog.html types using inherently safe builders - * or template systems. - * - * MOE:begin_intracomment_strip - * See http://go/safehtml-unchecked for guidelines on using these functions. - * MOE:end_intracomment_strip - * - * MOE:begin_intracomment_strip - * MAINTAINERS: Use of these functions is detected with a Tricorder analyzer. - * If adding functions here also add them to analyzer's list at - * j/c/g/devtools/staticanalysis/pipeline/analyzers/shared/SafeHtmlAnalyzers.java. - * MOE:end_intracomment_strip - * - * @visibility {//javascript/closure/html:approved_for_unchecked_conversion} - * @visibility {//javascript/closure/bin/sizetests:__pkg__} - */ - - -goog.provide('goog.html.uncheckedconversions'); - -goog.require('goog.asserts'); -goog.require('goog.html.SafeHtml'); -goog.require('goog.html.SafeScript'); -goog.require('goog.html.SafeStyle'); -goog.require('goog.html.SafeStyleSheet'); -goog.require('goog.html.SafeUrl'); -goog.require('goog.html.TrustedResourceUrl'); -goog.require('goog.string'); -goog.require('goog.string.Const'); - - -/** - * Performs an "unchecked conversion" to SafeHtml from a plain string that is - * known to satisfy the SafeHtml type contract. - * - * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure - * that the value of {@code html} satisfies the SafeHtml type contract in all - * possible program states. - * - * MOE:begin_intracomment_strip - * See http://go/safehtml-unchecked for guidelines on using these functions. - * MOE:end_intracomment_strip - * - * @param {!goog.string.Const} justification A constant string explaining why - * this use of this method is safe. May include a security review ticket - * number. - * @param {string} html A string that is claimed to adhere to the SafeHtml - * contract. - * @param {?goog.i18n.bidi.Dir=} opt_dir The optional directionality of the - * SafeHtml to be constructed. A null or undefined value signifies an - * unknown directionality. - * @return {!goog.html.SafeHtml} The value of html, wrapped in a SafeHtml - * object. - */ -goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract = - function(justification, html, opt_dir) { - // unwrap() called inside an assert so that justification can be optimized - // away in production code. - goog.asserts.assertString( - goog.string.Const.unwrap(justification), 'must provide justification'); - goog.asserts.assert( - !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)), - 'must provide non-empty justification'); - return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( - html, opt_dir || null); -}; - - -/** - * Performs an "unchecked conversion" to SafeScript from a plain string that is - * known to satisfy the SafeScript type contract. - * - * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure - * that the value of {@code script} satisfies the SafeScript type contract in - * all possible program states. - * - * MOE:begin_intracomment_strip - * See http://go/safehtml-unchecked for guidelines on using these functions. - * MOE:end_intracomment_strip - * - * @param {!goog.string.Const} justification A constant string explaining why - * this use of this method is safe. May include a security review ticket - * number. - * @param {string} script The string to wrap as a SafeScript. - * @return {!goog.html.SafeScript} The value of {@code script}, wrapped in a - * SafeScript object. - */ -goog.html.uncheckedconversions.safeScriptFromStringKnownToSatisfyTypeContract = - function(justification, script) { - // unwrap() called inside an assert so that justification can be optimized - // away in production code. - goog.asserts.assertString( - goog.string.Const.unwrap(justification), 'must provide justification'); - goog.asserts.assert( - !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)), - 'must provide non-empty justification'); - return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse( - script); -}; - - -/** - * Performs an "unchecked conversion" to SafeStyle from a plain string that is - * known to satisfy the SafeStyle type contract. - * - * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure - * that the value of {@code style} satisfies the SafeStyle type contract in all - * possible program states. - * - * MOE:begin_intracomment_strip - * See http://go/safehtml-unchecked for guidelines on using these functions. - * MOE:end_intracomment_strip - * - * @param {!goog.string.Const} justification A constant string explaining why - * this use of this method is safe. May include a security review ticket - * number. - * @param {string} style The string to wrap as a SafeStyle. - * @return {!goog.html.SafeStyle} The value of {@code style}, wrapped in a - * SafeStyle object. - */ -goog.html.uncheckedconversions.safeStyleFromStringKnownToSatisfyTypeContract = - function(justification, style) { - // unwrap() called inside an assert so that justification can be optimized - // away in production code. - goog.asserts.assertString( - goog.string.Const.unwrap(justification), 'must provide justification'); - goog.asserts.assert( - !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)), - 'must provide non-empty justification'); - return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse( - style); -}; - - -/** - * Performs an "unchecked conversion" to SafeStyleSheet from a plain string - * that is known to satisfy the SafeStyleSheet type contract. - * - * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure - * that the value of {@code styleSheet} satisfies the SafeStyleSheet type - * contract in all possible program states. - * - * MOE:begin_intracomment_strip - * See http://go/safehtml-unchecked for guidelines on using these functions. - * MOE:end_intracomment_strip - * - * @param {!goog.string.Const} justification A constant string explaining why - * this use of this method is safe. May include a security review ticket - * number. - * @param {string} styleSheet The string to wrap as a SafeStyleSheet. - * @return {!goog.html.SafeStyleSheet} The value of {@code styleSheet}, wrapped - * in a SafeStyleSheet object. - */ -goog.html.uncheckedconversions - .safeStyleSheetFromStringKnownToSatisfyTypeContract = function( - justification, styleSheet) { - // unwrap() called inside an assert so that justification can be optimized - // away in production code. - goog.asserts.assertString( - goog.string.Const.unwrap(justification), 'must provide justification'); - goog.asserts.assert( - !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)), - 'must provide non-empty justification'); - return goog.html.SafeStyleSheet - .createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheet); -}; - - -/** - * Performs an "unchecked conversion" to SafeUrl from a plain string that is - * known to satisfy the SafeUrl type contract. - * - * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure - * that the value of {@code url} satisfies the SafeUrl type contract in all - * possible program states. - * - * MOE:begin_intracomment_strip - * See http://go/safehtml-unchecked for guidelines on using these functions. - * MOE:end_intracomment_strip - * - * @param {!goog.string.Const} justification A constant string explaining why - * this use of this method is safe. May include a security review ticket - * number. - * @param {string} url The string to wrap as a SafeUrl. - * @return {!goog.html.SafeUrl} The value of {@code url}, wrapped in a SafeUrl - * object. - */ -goog.html.uncheckedconversions.safeUrlFromStringKnownToSatisfyTypeContract = - function(justification, url) { - // unwrap() called inside an assert so that justification can be optimized - // away in production code. - goog.asserts.assertString( - goog.string.Const.unwrap(justification), 'must provide justification'); - goog.asserts.assert( - !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)), - 'must provide non-empty justification'); - return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url); -}; - - -/** - * Performs an "unchecked conversion" to TrustedResourceUrl from a plain string - * that is known to satisfy the TrustedResourceUrl type contract. - * - * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure - * that the value of {@code url} satisfies the TrustedResourceUrl type contract - * in all possible program states. - * - * MOE:begin_intracomment_strip - * See http://go/safehtml-unchecked for guidelines on using these functions. - * MOE:end_intracomment_strip - * - * @param {!goog.string.Const} justification A constant string explaining why - * this use of this method is safe. May include a security review ticket - * number. - * @param {string} url The string to wrap as a TrustedResourceUrl. - * @return {!goog.html.TrustedResourceUrl} The value of {@code url}, wrapped in - * a TrustedResourceUrl object. - */ -goog.html.uncheckedconversions - .trustedResourceUrlFromStringKnownToSatisfyTypeContract = function( - justification, url) { - // unwrap() called inside an assert so that justification can be optimized - // away in production code. - goog.asserts.assertString( - goog.string.Const.unwrap(justification), 'must provide justification'); - goog.asserts.assert( - !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)), - 'must provide non-empty justification'); - return goog.html.TrustedResourceUrl - .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(url); -};
diff --git a/third_party/ink/closure/i18n/bidi.js b/third_party/ink/closure/i18n/bidi.js deleted file mode 100644 index fcf1120..0000000 --- a/third_party/ink/closure/i18n/bidi.js +++ /dev/null
@@ -1,878 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utility functions for supporting Bidi issues. - * @author shanjian@google.com (Shanjian Li) - * @author dougfelt@google.com (Doug Felt) - */ - - -/** - * Namespace for bidi supporting functions. - */ -goog.provide('goog.i18n.bidi'); -goog.provide('goog.i18n.bidi.Dir'); -goog.provide('goog.i18n.bidi.DirectionalString'); -goog.provide('goog.i18n.bidi.Format'); - - -/** - * @define {boolean} FORCE_RTL forces the {@link goog.i18n.bidi.IS_RTL} constant - * to say that the current locale is a RTL locale. This should only be used - * if you want to override the default behavior for deciding whether the - * current locale is RTL or not. - * - * {@see goog.i18n.bidi.IS_RTL} - */ -goog.define('goog.i18n.bidi.FORCE_RTL', false); - - -/** - * Constant that defines whether or not the current locale is a RTL locale. - * If {@link goog.i18n.bidi.FORCE_RTL} is not true, this constant will default - * to check that {@link goog.LOCALE} is one of a few major RTL locales. - * - * <p>This is designed to be a maximally efficient compile-time constant. For - * example, for the default goog.LOCALE, compiling - * "if (goog.i18n.bidi.IS_RTL) alert('rtl') else {}" should produce no code. It - * is this design consideration that limits the implementation to only - * supporting a few major RTL locales, as opposed to the broader repertoire of - * something like goog.i18n.bidi.isRtlLanguage. - * - * <p>Since this constant refers to the directionality of the locale, it is up - * to the caller to determine if this constant should also be used for the - * direction of the UI. - * - * {@see goog.LOCALE} - * - * @type {boolean} - * - * TODO(aharon): write a test that checks that this is a compile-time constant. - */ -goog.i18n.bidi.IS_RTL = goog.i18n.bidi.FORCE_RTL || - ((goog.LOCALE.substring(0, 2).toLowerCase() == 'ar' || - goog.LOCALE.substring(0, 2).toLowerCase() == 'fa' || - goog.LOCALE.substring(0, 2).toLowerCase() == 'he' || - goog.LOCALE.substring(0, 2).toLowerCase() == 'iw' || - goog.LOCALE.substring(0, 2).toLowerCase() == 'ps' || - goog.LOCALE.substring(0, 2).toLowerCase() == 'sd' || - goog.LOCALE.substring(0, 2).toLowerCase() == 'ug' || - goog.LOCALE.substring(0, 2).toLowerCase() == 'ur' || - goog.LOCALE.substring(0, 2).toLowerCase() == 'yi') && - (goog.LOCALE.length == 2 || goog.LOCALE.substring(2, 3) == '-' || - goog.LOCALE.substring(2, 3) == '_')) || - (goog.LOCALE.length >= 3 && - goog.LOCALE.substring(0, 3).toLowerCase() == 'ckb' && - (goog.LOCALE.length == 3 || goog.LOCALE.substring(3, 4) == '-' || - goog.LOCALE.substring(3, 4) == '_')); - - -/** - * Unicode formatting characters and directionality string constants. - * @enum {string} - */ -goog.i18n.bidi.Format = { - /** Unicode "Left-To-Right Embedding" (LRE) character. */ - LRE: '\u202A', - /** Unicode "Right-To-Left Embedding" (RLE) character. */ - RLE: '\u202B', - /** Unicode "Pop Directional Formatting" (PDF) character. */ - PDF: '\u202C', - /** Unicode "Left-To-Right Mark" (LRM) character. */ - LRM: '\u200E', - /** Unicode "Right-To-Left Mark" (RLM) character. */ - RLM: '\u200F' -}; - - -/** - * Directionality enum. - * @enum {number} - */ -goog.i18n.bidi.Dir = { - /** - * Left-to-right. - */ - LTR: 1, - - /** - * Right-to-left. - */ - RTL: -1, - - /** - * Neither left-to-right nor right-to-left. - */ - NEUTRAL: 0 -}; - - -/** - * 'right' string constant. - * @type {string} - */ -goog.i18n.bidi.RIGHT = 'right'; - - -/** - * 'left' string constant. - * @type {string} - */ -goog.i18n.bidi.LEFT = 'left'; - - -/** - * 'left' if locale is RTL, 'right' if not. - * @type {string} - */ -goog.i18n.bidi.I18N_RIGHT = - goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.LEFT : goog.i18n.bidi.RIGHT; - - -/** - * 'right' if locale is RTL, 'left' if not. - * @type {string} - */ -goog.i18n.bidi.I18N_LEFT = - goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.RIGHT : goog.i18n.bidi.LEFT; - - -/** - * Convert a directionality given in various formats to a goog.i18n.bidi.Dir - * constant. Useful for interaction with different standards of directionality - * representation. - * - * @param {goog.i18n.bidi.Dir|number|boolean|null} givenDir Directionality given - * in one of the following formats: - * 1. A goog.i18n.bidi.Dir constant. - * 2. A number (positive = LTR, negative = RTL, 0 = neutral). - * 3. A boolean (true = RTL, false = LTR). - * 4. A null for unknown directionality. - * @param {boolean=} opt_noNeutral Whether a givenDir of zero or - * goog.i18n.bidi.Dir.NEUTRAL should be treated as null, i.e. unknown, in - * order to preserve legacy behavior. - * @return {?goog.i18n.bidi.Dir} A goog.i18n.bidi.Dir constant matching the - * given directionality. If given null, returns null (i.e. unknown). - */ -goog.i18n.bidi.toDir = function(givenDir, opt_noNeutral) { - if (typeof givenDir == 'number') { - // This includes the non-null goog.i18n.bidi.Dir case. - return givenDir > 0 ? goog.i18n.bidi.Dir.LTR : givenDir < 0 ? - goog.i18n.bidi.Dir.RTL : - opt_noNeutral ? null : goog.i18n.bidi.Dir.NEUTRAL; - } else if (givenDir == null) { - return null; - } else { - // Must be typeof givenDir == 'boolean'. - return givenDir ? goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR; - } -}; - - -/** - * A practical pattern to identify strong LTR characters. This pattern is not - * theoretically correct according to the Unicode standard. It is simplified for - * performance and small code size. - * @type {string} - * @private - */ -goog.i18n.bidi.ltrChars_ = - 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF' + - '\u200E\u2C00-\uFB1C\uFE00-\uFE6F\uFEFD-\uFFFF'; - - -/** - * A practical pattern to identify strong RTL character. This pattern is not - * theoretically correct according to the Unicode standard. It is simplified - * for performance and small code size. - * @type {string} - * @private - */ -goog.i18n.bidi.rtlChars_ = - '\u0591-\u06EF\u06FA-\u07FF\u200F\uFB1D-\uFDFF\uFE70-\uFEFC'; - - -/** - * Simplified regular expression for an HTML tag (opening or closing) or an HTML - * escape. We might want to skip over such expressions when estimating the text - * directionality. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.htmlSkipReg_ = /<[^>]*>|&[^;]+;/g; - - -/** - * Returns the input text with spaces instead of HTML tags or HTML escapes, if - * opt_isStripNeeded is true. Else returns the input as is. - * Useful for text directionality estimation. - * Note: the function should not be used in other contexts; it is not 100% - * correct, but rather a good-enough implementation for directionality - * estimation purposes. - * @param {string} str The given string. - * @param {boolean=} opt_isStripNeeded Whether to perform the stripping. - * Default: false (to retain consistency with calling functions). - * @return {string} The given string cleaned of HTML tags / escapes. - * @private - */ -goog.i18n.bidi.stripHtmlIfNeeded_ = function(str, opt_isStripNeeded) { - return opt_isStripNeeded ? str.replace(goog.i18n.bidi.htmlSkipReg_, '') : str; -}; - - -/** - * Regular expression to check for RTL characters. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.rtlCharReg_ = new RegExp('[' + goog.i18n.bidi.rtlChars_ + ']'); - - -/** - * Regular expression to check for LTR characters. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.ltrCharReg_ = new RegExp('[' + goog.i18n.bidi.ltrChars_ + ']'); - - -/** - * Test whether the given string has any RTL characters in it. - * @param {string} str The given string that need to be tested. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {boolean} Whether the string contains RTL characters. - */ -goog.i18n.bidi.hasAnyRtl = function(str, opt_isHtml) { - return goog.i18n.bidi.rtlCharReg_.test( - goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml)); -}; - - -/** - * Test whether the given string has any RTL characters in it. - * @param {string} str The given string that need to be tested. - * @return {boolean} Whether the string contains RTL characters. - * @deprecated Use hasAnyRtl. - */ -goog.i18n.bidi.hasRtlChar = goog.i18n.bidi.hasAnyRtl; - - -/** - * Test whether the given string has any LTR characters in it. - * @param {string} str The given string that need to be tested. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {boolean} Whether the string contains LTR characters. - */ -goog.i18n.bidi.hasAnyLtr = function(str, opt_isHtml) { - return goog.i18n.bidi.ltrCharReg_.test( - goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml)); -}; - - -/** - * Regular expression pattern to check if the first character in the string - * is LTR. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.ltrRe_ = new RegExp('^[' + goog.i18n.bidi.ltrChars_ + ']'); - - -/** - * Regular expression pattern to check if the first character in the string - * is RTL. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.rtlRe_ = new RegExp('^[' + goog.i18n.bidi.rtlChars_ + ']'); - - -/** - * Check if the first character in the string is RTL or not. - * @param {string} str The given string that need to be tested. - * @return {boolean} Whether the first character in str is an RTL char. - */ -goog.i18n.bidi.isRtlChar = function(str) { - return goog.i18n.bidi.rtlRe_.test(str); -}; - - -/** - * Check if the first character in the string is LTR or not. - * @param {string} str The given string that need to be tested. - * @return {boolean} Whether the first character in str is an LTR char. - */ -goog.i18n.bidi.isLtrChar = function(str) { - return goog.i18n.bidi.ltrRe_.test(str); -}; - - -/** - * Check if the first character in the string is neutral or not. - * @param {string} str The given string that need to be tested. - * @return {boolean} Whether the first character in str is a neutral char. - */ -goog.i18n.bidi.isNeutralChar = function(str) { - return !goog.i18n.bidi.isLtrChar(str) && !goog.i18n.bidi.isRtlChar(str); -}; - - -/** - * Regular expressions to check if a piece of text is of LTR directionality - * on first character with strong directionality. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.ltrDirCheckRe_ = new RegExp( - '^[^' + goog.i18n.bidi.rtlChars_ + ']*[' + goog.i18n.bidi.ltrChars_ + ']'); - - -/** - * Regular expressions to check if a piece of text is of RTL directionality - * on first character with strong directionality. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.rtlDirCheckRe_ = new RegExp( - '^[^' + goog.i18n.bidi.ltrChars_ + ']*[' + goog.i18n.bidi.rtlChars_ + ']'); - - -/** - * Check whether the first strongly directional character (if any) is RTL. - * @param {string} str String being checked. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {boolean} Whether RTL directionality is detected using the first - * strongly-directional character method. - */ -goog.i18n.bidi.startsWithRtl = function(str, opt_isHtml) { - return goog.i18n.bidi.rtlDirCheckRe_.test( - goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml)); -}; - - -/** - * Check whether the first strongly directional character (if any) is RTL. - * @param {string} str String being checked. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {boolean} Whether RTL directionality is detected using the first - * strongly-directional character method. - * @deprecated Use startsWithRtl. - */ -goog.i18n.bidi.isRtlText = goog.i18n.bidi.startsWithRtl; - - -/** - * Check whether the first strongly directional character (if any) is LTR. - * @param {string} str String being checked. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {boolean} Whether LTR directionality is detected using the first - * strongly-directional character method. - */ -goog.i18n.bidi.startsWithLtr = function(str, opt_isHtml) { - return goog.i18n.bidi.ltrDirCheckRe_.test( - goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml)); -}; - - -/** - * Check whether the first strongly directional character (if any) is LTR. - * @param {string} str String being checked. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {boolean} Whether LTR directionality is detected using the first - * strongly-directional character method. - * @deprecated Use startsWithLtr. - */ -goog.i18n.bidi.isLtrText = goog.i18n.bidi.startsWithLtr; - - -/** - * Regular expression to check if a string looks like something that must - * always be LTR even in RTL text, e.g. a URL. When estimating the - * directionality of text containing these, we treat these as weakly LTR, - * like numbers. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.isRequiredLtrRe_ = /^http:\/\/.*/; - - -/** - * Check whether the input string either contains no strongly directional - * characters or looks like a url. - * @param {string} str String being checked. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {boolean} Whether neutral directionality is detected. - */ -goog.i18n.bidi.isNeutralText = function(str, opt_isHtml) { - str = goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml); - return goog.i18n.bidi.isRequiredLtrRe_.test(str) || - !goog.i18n.bidi.hasAnyLtr(str) && !goog.i18n.bidi.hasAnyRtl(str); -}; - - -/** - * Regular expressions to check if the last strongly-directional character in a - * piece of text is LTR. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.ltrExitDirCheckRe_ = new RegExp( - '[' + goog.i18n.bidi.ltrChars_ + '][^' + goog.i18n.bidi.rtlChars_ + ']*$'); - - -/** - * Regular expressions to check if the last strongly-directional character in a - * piece of text is RTL. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.rtlExitDirCheckRe_ = new RegExp( - '[' + goog.i18n.bidi.rtlChars_ + '][^' + goog.i18n.bidi.ltrChars_ + ']*$'); - - -/** - * Check if the exit directionality a piece of text is LTR, i.e. if the last - * strongly-directional character in the string is LTR. - * @param {string} str String being checked. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {boolean} Whether LTR exit directionality was detected. - */ -goog.i18n.bidi.endsWithLtr = function(str, opt_isHtml) { - return goog.i18n.bidi.ltrExitDirCheckRe_.test( - goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml)); -}; - - -/** - * Check if the exit directionality a piece of text is LTR, i.e. if the last - * strongly-directional character in the string is LTR. - * @param {string} str String being checked. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {boolean} Whether LTR exit directionality was detected. - * @deprecated Use endsWithLtr. - */ -goog.i18n.bidi.isLtrExitText = goog.i18n.bidi.endsWithLtr; - - -/** - * Check if the exit directionality a piece of text is RTL, i.e. if the last - * strongly-directional character in the string is RTL. - * @param {string} str String being checked. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {boolean} Whether RTL exit directionality was detected. - */ -goog.i18n.bidi.endsWithRtl = function(str, opt_isHtml) { - return goog.i18n.bidi.rtlExitDirCheckRe_.test( - goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml)); -}; - - -/** - * Check if the exit directionality a piece of text is RTL, i.e. if the last - * strongly-directional character in the string is RTL. - * @param {string} str String being checked. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {boolean} Whether RTL exit directionality was detected. - * @deprecated Use endsWithRtl. - */ -goog.i18n.bidi.isRtlExitText = goog.i18n.bidi.endsWithRtl; - - -/** - * A regular expression for matching right-to-left language codes. - * See {@link #isRtlLanguage} for the design. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.rtlLocalesRe_ = new RegExp( - '^(ar|ckb|dv|he|iw|fa|nqo|ps|sd|ug|ur|yi|' + - '.*[-_](Arab|Hebr|Thaa|Nkoo|Tfng))' + - '(?!.*[-_](Latn|Cyrl)($|-|_))($|-|_)', - 'i'); - - -/** - * Check if a BCP 47 / III language code indicates an RTL language, i.e. either: - * - a language code explicitly specifying one of the right-to-left scripts, - * e.g. "az-Arab", or<p> - * - a language code specifying one of the languages normally written in a - * right-to-left script, e.g. "fa" (Farsi), except ones explicitly specifying - * Latin or Cyrillic script (which are the usual LTR alternatives).<p> - * The list of right-to-left scripts appears in the 100-199 range in - * http://www.unicode.org/iso15924/iso15924-num.html, of which Arabic and - * Hebrew are by far the most widely used. We also recognize Thaana, N'Ko, and - * Tifinagh, which also have significant modern usage. The rest (Syriac, - * Samaritan, Mandaic, etc.) seem to have extremely limited or no modern usage - * and are not recognized to save on code size. - * The languages usually written in a right-to-left script are taken as those - * with Suppress-Script: Hebr|Arab|Thaa|Nkoo|Tfng in - * http://www.iana.org/assignments/language-subtag-registry, - * as well as Central (or Sorani) Kurdish (ckb), Sindhi (sd) and Uyghur (ug). - * Other subtags of the language code, e.g. regions like EG (Egypt), are - * ignored. - * @param {string} lang BCP 47 (a.k.a III) language code. - * @return {boolean} Whether the language code is an RTL language. - */ -goog.i18n.bidi.isRtlLanguage = function(lang) { - return goog.i18n.bidi.rtlLocalesRe_.test(lang); -}; - - -/** - * Regular expression for bracket guard replacement in text. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.bracketGuardTextRe_ = - /(\(.*?\)+)|(\[.*?\]+)|(\{.*?\}+)|(<.*?>+)/g; - - -/** - * Apply bracket guard using LRM and RLM. This is to address the problem of - * messy bracket display frequently happens in RTL layout. - * This function works for plain text, not for HTML. In HTML, the opening - * bracket might be in a different context than the closing bracket (such as - * an attribute value). - * @param {string} s The string that need to be processed. - * @param {boolean=} opt_isRtlContext specifies default direction (usually - * direction of the UI). - * @return {string} The processed string, with all bracket guarded. - */ -goog.i18n.bidi.guardBracketInText = function(s, opt_isRtlContext) { - var useRtl = opt_isRtlContext === undefined ? goog.i18n.bidi.hasAnyRtl(s) : - opt_isRtlContext; - var mark = useRtl ? goog.i18n.bidi.Format.RLM : goog.i18n.bidi.Format.LRM; - return s.replace(goog.i18n.bidi.bracketGuardTextRe_, mark + '$&' + mark); -}; - - -/** - * Enforce the html snippet in RTL directionality regardless overall context. - * If the html piece was enclosed by tag, dir will be applied to existing - * tag, otherwise a span tag will be added as wrapper. For this reason, if - * html snippet start with with tag, this tag must enclose the whole piece. If - * the tag already has a dir specified, this new one will override existing - * one in behavior (tested on FF and IE). - * @param {string} html The string that need to be processed. - * @return {string} The processed string, with directionality enforced to RTL. - */ -goog.i18n.bidi.enforceRtlInHtml = function(html) { - if (html.charAt(0) == '<') { - return html.replace(/<\w+/, '$& dir=rtl'); - } - // '\n' is important for FF so that it won't incorrectly merge span groups - return '\n<span dir=rtl>' + html + '</span>'; -}; - - -/** - * Enforce RTL on both end of the given text piece using unicode BiDi formatting - * characters RLE and PDF. - * @param {string} text The piece of text that need to be wrapped. - * @return {string} The wrapped string after process. - */ -goog.i18n.bidi.enforceRtlInText = function(text) { - return goog.i18n.bidi.Format.RLE + text + goog.i18n.bidi.Format.PDF; -}; - - -/** - * Enforce the html snippet in RTL directionality regardless overall context. - * If the html piece was enclosed by tag, dir will be applied to existing - * tag, otherwise a span tag will be added as wrapper. For this reason, if - * html snippet start with with tag, this tag must enclose the whole piece. If - * the tag already has a dir specified, this new one will override existing - * one in behavior (tested on FF and IE). - * @param {string} html The string that need to be processed. - * @return {string} The processed string, with directionality enforced to RTL. - */ -goog.i18n.bidi.enforceLtrInHtml = function(html) { - if (html.charAt(0) == '<') { - return html.replace(/<\w+/, '$& dir=ltr'); - } - // '\n' is important for FF so that it won't incorrectly merge span groups - return '\n<span dir=ltr>' + html + '</span>'; -}; - - -/** - * Enforce LTR on both end of the given text piece using unicode BiDi formatting - * characters LRE and PDF. - * @param {string} text The piece of text that need to be wrapped. - * @return {string} The wrapped string after process. - */ -goog.i18n.bidi.enforceLtrInText = function(text) { - return goog.i18n.bidi.Format.LRE + text + goog.i18n.bidi.Format.PDF; -}; - - -/** - * Regular expression to find dimensions such as "padding: .3 0.4ex 5px 6;" - * @type {RegExp} - * @private - */ -goog.i18n.bidi.dimensionsRe_ = - /:\s*([.\d][.\w]*)\s+([.\d][.\w]*)\s+([.\d][.\w]*)\s+([.\d][.\w]*)/g; - - -/** - * Regular expression for left. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.leftRe_ = /left/gi; - - -/** - * Regular expression for right. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.rightRe_ = /right/gi; - - -/** - * Placeholder regular expression for swapping. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.tempRe_ = /%%%%/g; - - -/** - * Swap location parameters and 'left'/'right' in CSS specification. The - * processed string will be suited for RTL layout. Though this function can - * cover most cases, there are always exceptions. It is suggested to put - * those exceptions in separate group of CSS string. - * @param {string} cssStr CSS spefication string. - * @return {string} Processed CSS specification string. - */ -goog.i18n.bidi.mirrorCSS = function(cssStr) { - return cssStr - . - // reverse dimensions - replace(goog.i18n.bidi.dimensionsRe_, ':$1 $4 $3 $2') - .replace(goog.i18n.bidi.leftRe_, '%%%%') - . // swap left and right - replace(goog.i18n.bidi.rightRe_, goog.i18n.bidi.LEFT) - .replace(goog.i18n.bidi.tempRe_, goog.i18n.bidi.RIGHT); -}; - - -/** - * Regular expression for hebrew double quote substitution, finding quote - * directly after hebrew characters. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.doubleQuoteSubstituteRe_ = /([\u0591-\u05f2])"/g; - - -/** - * Regular expression for hebrew single quote substitution, finding quote - * directly after hebrew characters. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.singleQuoteSubstituteRe_ = /([\u0591-\u05f2])'/g; - - -/** - * Replace the double and single quote directly after a Hebrew character with - * GERESH and GERSHAYIM. In such case, most likely that's user intention. - * @param {string} str String that need to be processed. - * @return {string} Processed string with double/single quote replaced. - */ -goog.i18n.bidi.normalizeHebrewQuote = function(str) { - return str.replace(goog.i18n.bidi.doubleQuoteSubstituteRe_, '$1\u05f4') - .replace(goog.i18n.bidi.singleQuoteSubstituteRe_, '$1\u05f3'); -}; - - -/** - * Regular expression to split a string into "words" for directionality - * estimation based on relative word counts. - * @type {RegExp} - * @private - */ -goog.i18n.bidi.wordSeparatorRe_ = /\s+/; - - -/** - * Regular expression to check if a string contains any numerals. Used to - * differentiate between completely neutral strings and those containing - * numbers, which are weakly LTR. - * - * Native Arabic digits (\u0660 - \u0669) are not included because although they - * do flow left-to-right inside a number, this is the case even if the overall - * directionality is RTL, and a mathematical expression using these digits is - * supposed to flow right-to-left overall, including unary plus and minus - * appearing to the right of a number, and this does depend on the overall - * directionality being RTL. The digits used in Farsi (\u06F0 - \u06F9), on the - * other hand, are included, since Farsi math (including unary plus and minus) - * does flow left-to-right. - * - * @type {RegExp} - * @private - */ -goog.i18n.bidi.hasNumeralsRe_ = /[\d\u06f0-\u06f9]/; - - -/** - * This constant controls threshold of RTL directionality. - * @type {number} - * @private - */ -goog.i18n.bidi.rtlDetectionThreshold_ = 0.40; - - -/** - * Estimates the directionality of a string based on relative word counts. - * If the number of RTL words is above a certain percentage of the total number - * of strongly directional words, returns RTL. - * Otherwise, if any words are strongly or weakly LTR, returns LTR. - * Otherwise, returns UNKNOWN, which is used to mean "neutral". - * Numbers are counted as weakly LTR. - * @param {string} str The string to be checked. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {goog.i18n.bidi.Dir} Estimated overall directionality of {@code str}. - */ -goog.i18n.bidi.estimateDirection = function(str, opt_isHtml) { - var rtlCount = 0; - var totalCount = 0; - var hasWeaklyLtr = false; - var tokens = goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml) - .split(goog.i18n.bidi.wordSeparatorRe_); - for (var i = 0; i < tokens.length; i++) { - var token = tokens[i]; - if (goog.i18n.bidi.startsWithRtl(token)) { - rtlCount++; - totalCount++; - } else if (goog.i18n.bidi.isRequiredLtrRe_.test(token)) { - hasWeaklyLtr = true; - } else if (goog.i18n.bidi.hasAnyLtr(token)) { - totalCount++; - } else if (goog.i18n.bidi.hasNumeralsRe_.test(token)) { - hasWeaklyLtr = true; - } - } - - return totalCount == 0 ? - (hasWeaklyLtr ? goog.i18n.bidi.Dir.LTR : goog.i18n.bidi.Dir.NEUTRAL) : - (rtlCount / totalCount > goog.i18n.bidi.rtlDetectionThreshold_ ? - goog.i18n.bidi.Dir.RTL : - goog.i18n.bidi.Dir.LTR); -}; - - -/** - * Check the directionality of a piece of text, return true if the piece of - * text should be laid out in RTL direction. - * @param {string} str The piece of text that need to be detected. - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. - * Default: false. - * @return {boolean} Whether this piece of text should be laid out in RTL. - */ -goog.i18n.bidi.detectRtlDirectionality = function(str, opt_isHtml) { - return goog.i18n.bidi.estimateDirection(str, opt_isHtml) == - goog.i18n.bidi.Dir.RTL; -}; - - -/** - * Sets text input element's directionality and text alignment based on a - * given directionality. Does nothing if the given directionality is unknown or - * neutral. - * @param {Element} element Input field element to set directionality to. - * @param {goog.i18n.bidi.Dir|number|boolean|null} dir Desired directionality, - * given in one of the following formats: - * 1. A goog.i18n.bidi.Dir constant. - * 2. A number (positive = LRT, negative = RTL, 0 = neutral). - * 3. A boolean (true = RTL, false = LTR). - * 4. A null for unknown directionality. - */ -goog.i18n.bidi.setElementDirAndAlign = function(element, dir) { - if (element) { - dir = goog.i18n.bidi.toDir(dir); - if (dir) { - element.style.textAlign = dir == goog.i18n.bidi.Dir.RTL ? - goog.i18n.bidi.RIGHT : - goog.i18n.bidi.LEFT; - element.dir = dir == goog.i18n.bidi.Dir.RTL ? 'rtl' : 'ltr'; - } - } -}; - - -/** - * Sets element dir based on estimated directionality of the given text. - * @param {!Element} element - * @param {string} text - */ -goog.i18n.bidi.setElementDirByTextDirectionality = function(element, text) { - switch (goog.i18n.bidi.estimateDirection(text)) { - case (goog.i18n.bidi.Dir.LTR): - element.dir = 'ltr'; - break; - case (goog.i18n.bidi.Dir.RTL): - element.dir = 'rtl'; - break; - default: - // Default for no direction, inherit from document. - element.removeAttribute('dir'); - } -}; - - - -/** - * Strings that have an (optional) known direction. - * - * Implementations of this interface are string-like objects that carry an - * attached direction, if known. - * @interface - */ -goog.i18n.bidi.DirectionalString = function() {}; - - -/** - * Interface marker of the DirectionalString interface. - * - * This property can be used to determine at runtime whether or not an object - * implements this interface. All implementations of this interface set this - * property to {@code true}. - * @type {boolean} - */ -goog.i18n.bidi.DirectionalString.prototype - .implementsGoogI18nBidiDirectionalString; - - -/** - * Retrieves this object's known direction (if any). - * @return {?goog.i18n.bidi.Dir} The known direction. Null if unknown. - */ -goog.i18n.bidi.DirectionalString.prototype.getDirection;
diff --git a/third_party/ink/closure/i18n/bidiformatter.js b/third_party/ink/closure/i18n/bidiformatter.js deleted file mode 100644 index 19bb2dd..0000000 --- a/third_party/ink/closure/i18n/bidiformatter.js +++ /dev/null
@@ -1,556 +0,0 @@ -// Copyright 2009 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utility for formatting text for display in a potentially - * opposite-directionality context without garbling. - * Mostly a port of http://go/formatter.cc. - * @author tomerigo@google.com (Tomer Greenberg) - */ - - -goog.provide('goog.i18n.BidiFormatter'); - -goog.require('goog.html.SafeHtml'); -goog.require('goog.i18n.bidi'); -goog.require('goog.i18n.bidi.Dir'); -goog.require('goog.i18n.bidi.Format'); - - - -/** - * Utility class for formatting text for display in a potentially - * opposite-directionality context without garbling. Provides the following - * functionality: - * - * 1. BiDi Wrapping - * When text in one language is mixed into a document in another, opposite- - * directionality language, e.g. when an English business name is embedded in a - * Hebrew web page, both the inserted string and the text following it may be - * displayed incorrectly unless the inserted string is explicitly separated - * from the surrounding text in a "wrapper" that declares its directionality at - * the start and then resets it back at the end. This wrapping can be done in - * HTML mark-up (e.g. a 'span dir="rtl"' tag) or - only in contexts where - * mark-up can not be used - in Unicode BiDi formatting codes (LRE|RLE and PDF). - * Providing such wrapping services is the basic purpose of the BiDi formatter. - * - * 2. Directionality estimation - * How does one know whether a string about to be inserted into surrounding - * text has the same directionality? Well, in many cases, one knows that this - * must be the case when writing the code doing the insertion, e.g. when a - * localized message is inserted into a localized page. In such cases there is - * no need to involve the BiDi formatter at all. In the remaining cases, e.g. - * when the string is user-entered or comes from a database, the language of - * the string (and thus its directionality) is not known a priori, and must be - * estimated at run-time. The BiDi formatter does this automatically. - * - * 3. Escaping - * When wrapping plain text - i.e. text that is not already HTML or HTML- - * escaped - in HTML mark-up, the text must first be HTML-escaped to prevent XSS - * attacks and other nasty business. This of course is always true, but the - * escaping can not be done after the string has already been wrapped in - * mark-up, so the BiDi formatter also serves as a last chance and includes - * escaping services. - * - * Thus, in a single call, the formatter will escape the input string as - * specified, determine its directionality, and wrap it as necessary. It is - * then up to the caller to insert the return value in the output. - * - * See http://wiki/Main/TemplatesAndBiDi for more information. - * - * @param {goog.i18n.bidi.Dir|number|boolean|null} contextDir The context - * directionality, in one of the following formats: - * 1. A goog.i18n.bidi.Dir constant. NEUTRAL is treated the same as null, - * i.e. unknown, for backward compatibility with legacy calls. - * 2. A number (positive = LTR, negative = RTL, 0 = unknown). - * 3. A boolean (true = RTL, false = LTR). - * 4. A null for unknown directionality. - * @param {boolean=} opt_alwaysSpan Whether {@link #spanWrap} should always - * use a 'span' tag, even when the input directionality is neutral or - * matches the context, so that the DOM structure of the output does not - * depend on the combination of directionalities. Default: false. - * @constructor - * @final - */ -goog.i18n.BidiFormatter = function(contextDir, opt_alwaysSpan) { - /** - * The overall directionality of the context in which the formatter is being - * used. - * @type {?goog.i18n.bidi.Dir} - * @private - */ - this.contextDir_ = goog.i18n.bidi.toDir(contextDir, true /* opt_noNeutral */); - - /** - * Whether {@link #spanWrap} and similar methods should always use the same - * span structure, regardless of the combination of directionalities, for a - * stable DOM structure. - * @type {boolean} - * @private - */ - this.alwaysSpan_ = !!opt_alwaysSpan; -}; - - -/** - * @return {?goog.i18n.bidi.Dir} The context directionality. - */ -goog.i18n.BidiFormatter.prototype.getContextDir = function() { - return this.contextDir_; -}; - - -/** - * @return {boolean} Whether alwaysSpan is set. - */ -goog.i18n.BidiFormatter.prototype.getAlwaysSpan = function() { - return this.alwaysSpan_; -}; - - -/** - * @param {goog.i18n.bidi.Dir|number|boolean|null} contextDir The context - * directionality, in one of the following formats: - * 1. A goog.i18n.bidi.Dir constant. NEUTRAL is treated the same as null, - * i.e. unknown. - * 2. A number (positive = LTR, negative = RTL, 0 = unknown). - * 3. A boolean (true = RTL, false = LTR). - * 4. A null for unknown directionality. - */ -goog.i18n.BidiFormatter.prototype.setContextDir = function(contextDir) { - this.contextDir_ = goog.i18n.bidi.toDir(contextDir, true /* opt_noNeutral */); -}; - - -/** - * @param {boolean} alwaysSpan Whether {@link #spanWrap} should always use a - * 'span' tag, even when the input directionality is neutral or matches the - * context, so that the DOM structure of the output does not depend on the - * combination of directionalities. - */ -goog.i18n.BidiFormatter.prototype.setAlwaysSpan = function(alwaysSpan) { - this.alwaysSpan_ = alwaysSpan; -}; - - -/** - * Returns the directionality of input argument {@code str}. - * Identical to {@link goog.i18n.bidi.estimateDirection}. - * - * @param {string} str The input text. - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped. - * Default: false. - * @return {goog.i18n.bidi.Dir} Estimated overall directionality of {@code str}. - */ -goog.i18n.BidiFormatter.prototype.estimateDirection = - goog.i18n.bidi.estimateDirection; - - -/** - * Returns true if two given directionalities are opposite. - * Note: the implementation is based on the numeric values of the Dir enum. - * - * @param {?goog.i18n.bidi.Dir} dir1 1st directionality. - * @param {?goog.i18n.bidi.Dir} dir2 2nd directionality. - * @return {boolean} Whether the directionalities are opposite. - * @private - */ -goog.i18n.BidiFormatter.prototype.areDirectionalitiesOpposite_ = function( - dir1, dir2) { - return Number(dir1) * Number(dir2) < 0; -}; - - -/** - * Returns a unicode BiDi mark matching the context directionality (LRM or - * RLM) if {@code opt_dirReset}, and if either the directionality or the exit - * directionality of {@code str} is opposite to the context directionality. - * Otherwise returns the empty string. - * - * @param {string} str The input text. - * @param {goog.i18n.bidi.Dir} dir {@code str}'s overall directionality. - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped. - * Default: false. - * @param {boolean=} opt_dirReset Whether to perform the reset. Default: false. - * @return {string} A unicode BiDi mark or the empty string. - * @private - */ -goog.i18n.BidiFormatter.prototype.dirResetIfNeeded_ = function( - str, dir, opt_isHtml, opt_dirReset) { - // endsWithRtl and endsWithLtr are called only if needed (short-circuit). - if (opt_dirReset && - (this.areDirectionalitiesOpposite_(dir, this.contextDir_) || - (this.contextDir_ == goog.i18n.bidi.Dir.LTR && - goog.i18n.bidi.endsWithRtl(str, opt_isHtml)) || - (this.contextDir_ == goog.i18n.bidi.Dir.RTL && - goog.i18n.bidi.endsWithLtr(str, opt_isHtml)))) { - return this.contextDir_ == goog.i18n.bidi.Dir.LTR ? - goog.i18n.bidi.Format.LRM : - goog.i18n.bidi.Format.RLM; - } else { - return ''; - } -}; - - -/** - * Returns "rtl" if {@code str}'s estimated directionality is RTL, and "ltr" if - * it is LTR. In case it's NEUTRAL, returns "rtl" if the context directionality - * is RTL, and "ltr" otherwise. - * Needed for GXP, which can't handle dirAttr. - * Example use case: - * <td expr:dir='bidiFormatter.dirAttrValue(foo)'> - * <gxp:eval expr='foo'> - * </td> - * - * @param {string} str Text whose directionality is to be estimated. - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped. - * Default: false. - * @return {string} "rtl" or "ltr", according to the logic described above. - */ -goog.i18n.BidiFormatter.prototype.dirAttrValue = function(str, opt_isHtml) { - return this.knownDirAttrValue(this.estimateDirection(str, opt_isHtml)); -}; - - -/** - * Returns "rtl" if the given directionality is RTL, and "ltr" if it is LTR. In - * case it's NEUTRAL, returns "rtl" if the context directionality is RTL, and - * "ltr" otherwise. - * - * @param {goog.i18n.bidi.Dir} dir A directionality. - * @return {string} "rtl" or "ltr", according to the logic described above. - */ -goog.i18n.BidiFormatter.prototype.knownDirAttrValue = function(dir) { - var resolvedDir = dir == goog.i18n.bidi.Dir.NEUTRAL ? this.contextDir_ : dir; - return resolvedDir == goog.i18n.bidi.Dir.RTL ? 'rtl' : 'ltr'; -}; - - -/** - * Returns 'dir="ltr"' or 'dir="rtl"', depending on {@code str}'s estimated - * directionality, if it is not the same as the context directionality. - * Otherwise, returns the empty string. - * - * @param {string} str Text whose directionality is to be estimated. - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped. - * Default: false. - * @return {string} 'dir="rtl"' for RTL text in non-RTL context; 'dir="ltr"' for - * LTR text in non-LTR context; else, the empty string. - */ -goog.i18n.BidiFormatter.prototype.dirAttr = function(str, opt_isHtml) { - return this.knownDirAttr(this.estimateDirection(str, opt_isHtml)); -}; - - -/** - * Returns 'dir="ltr"' or 'dir="rtl"', depending on the given directionality, if - * it is not the same as the context directionality. Otherwise, returns the - * empty string. - * - * @param {goog.i18n.bidi.Dir} dir A directionality. - * @return {string} 'dir="rtl"' for RTL text in non-RTL context; 'dir="ltr"' for - * LTR text in non-LTR context; else, the empty string. - */ -goog.i18n.BidiFormatter.prototype.knownDirAttr = function(dir) { - if (dir != this.contextDir_) { - return dir == goog.i18n.bidi.Dir.RTL ? - 'dir="rtl"' : - dir == goog.i18n.bidi.Dir.LTR ? 'dir="ltr"' : ''; - } - return ''; -}; - - -/** - * Formats a string of unknown directionality for use in HTML output of the - * context directionality, so an opposite-directionality string is neither - * garbled nor garbles what follows it. - * The algorithm: estimates the directionality of input argument {@code html}. - * In case its directionality doesn't match the context directionality, wraps it - * with a 'span' tag and adds a "dir" attribute (either 'dir="rtl"' or - * 'dir="ltr"'). If setAlwaysSpan(true) was used, the input is always wrapped - * with 'span', skipping just the dir attribute when it's not needed. - * - * If {@code opt_dirReset}, and if the overall directionality or the exit - * directionality of {@code str} are opposite to the context directionality, a - * trailing unicode BiDi mark matching the context directionality is appened - * (LRM or RLM). - * - * @param {!goog.html.SafeHtml} html The input HTML. - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark - * matching the context directionality, when needed, to prevent the possible - * garbling of whatever may follow {@code html}. Default: true. - * @return {!goog.html.SafeHtml} Input text after applying the processing. - */ -goog.i18n.BidiFormatter.prototype.spanWrapSafeHtml = function( - html, opt_dirReset) { - return this.spanWrapSafeHtmlWithKnownDir(null, html, opt_dirReset); -}; - - -/** - * Formats a string of given directionality for use in HTML output of the - * context directionality, so an opposite-directionality string is neither - * garbled nor garbles what follows it. - * The algorithm: If {@code dir} doesn't match the context directionality, wraps - * {@code html} with a 'span' tag and adds a "dir" attribute (either 'dir="rtl"' - * or 'dir="ltr"'). If setAlwaysSpan(true) was used, the input is always wrapped - * with 'span', skipping just the dir attribute when it's not needed. - * - * If {@code opt_dirReset}, and if {@code dir} or the exit directionality of - * {@code html} are opposite to the context directionality, a trailing unicode - * BiDi mark matching the context directionality is appened (LRM or RLM). - * - * @param {?goog.i18n.bidi.Dir} dir {@code html}'s overall directionality, or - * null if unknown and needs to be estimated. - * @param {!goog.html.SafeHtml} html The input HTML. - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark - * matching the context directionality, when needed, to prevent the possible - * garbling of whatever may follow {@code html}. Default: true. - * @return {!goog.html.SafeHtml} Input text after applying the processing. - */ -goog.i18n.BidiFormatter.prototype.spanWrapSafeHtmlWithKnownDir = function( - dir, html, opt_dirReset) { - if (dir == null) { - dir = this.estimateDirection(goog.html.SafeHtml.unwrap(html), true); - } - return this.spanWrapWithKnownDir_(dir, html, opt_dirReset); -}; - - -/** - * The internal implementation of spanWrapSafeHtmlWithKnownDir for non-null dir, - * to help the compiler optimize. - * - * @param {goog.i18n.bidi.Dir} dir {@code str}'s overall directionality. - * @param {!goog.html.SafeHtml} html The input HTML. - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark - * matching the context directionality, when needed, to prevent the possible - * garbling of whatever may follow {@code str}. Default: true. - * @return {!goog.html.SafeHtml} Input text after applying the above processing. - * @private - */ -goog.i18n.BidiFormatter.prototype.spanWrapWithKnownDir_ = function( - dir, html, opt_dirReset) { - opt_dirReset = opt_dirReset || (opt_dirReset == undefined); - - var result; - // Whether to add the "dir" attribute. - var dirCondition = - dir != goog.i18n.bidi.Dir.NEUTRAL && dir != this.contextDir_; - if (this.alwaysSpan_ || dirCondition) { // Wrap is needed - var dirAttribute; - if (dirCondition) { - dirAttribute = dir == goog.i18n.bidi.Dir.RTL ? 'rtl' : 'ltr'; - } - result = goog.html.SafeHtml.create('span', {'dir': dirAttribute}, html); - } else { - result = html; - } - var str = goog.html.SafeHtml.unwrap(html); - result = goog.html.SafeHtml.concatWithDir( - goog.i18n.bidi.Dir.NEUTRAL, result, - this.dirResetIfNeeded_(str, dir, true, opt_dirReset)); - return result; -}; - - -/** - * Formats a string of unknown directionality for use in plain-text output of - * the context directionality, so an opposite-directionality string is neither - * garbled nor garbles what follows it. - * As opposed to {@link #spanWrap}, this makes use of unicode BiDi formatting - * characters. In HTML, its *only* valid use is inside of elements that do not - * allow mark-up, e.g. an 'option' tag. - * The algorithm: estimates the directionality of input argument {@code str}. - * In case it doesn't match the context directionality, wraps it with Unicode - * BiDi formatting characters: RLE{@code str}PDF for RTL text, and - * LRE{@code str}PDF for LTR text. - * - * If {@code opt_dirReset}, and if the overall directionality or the exit - * directionality of {@code str} are opposite to the context directionality, a - * trailing unicode BiDi mark matching the context directionality is appended - * (LRM or RLM). - * - * Does *not* do HTML-escaping regardless of the value of {@code opt_isHtml}. - * The return value can be HTML-escaped as necessary. - * - * @param {string} str The input text. - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped. - * Default: false. - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark - * matching the context directionality, when needed, to prevent the possible - * garbling of whatever may follow {@code str}. Default: true. - * @return {string} Input text after applying the above processing. - */ -goog.i18n.BidiFormatter.prototype.unicodeWrap = function( - str, opt_isHtml, opt_dirReset) { - return this.unicodeWrapWithKnownDir(null, str, opt_isHtml, opt_dirReset); -}; - - -/** - * Formats a string of given directionality for use in plain-text output of the - * context directionality, so an opposite-directionality string is neither - * garbled nor garbles what follows it. - * As opposed to {@link #spanWrapWithKnownDir}, makes use of unicode BiDi - * formatting characters. In HTML, its *only* valid use is inside of elements - * that do not allow mark-up, e.g. an 'option' tag. - * The algorithm: If {@code dir} doesn't match the context directionality, wraps - * {@code str} with Unicode BiDi formatting characters: RLE{@code str}PDF for - * RTL text, and LRE{@code str}PDF for LTR text. - * - * If {@code opt_dirReset}, and if the overall directionality or the exit - * directionality of {@code str} are opposite to the context directionality, a - * trailing unicode BiDi mark matching the context directionality is appended - * (LRM or RLM). - * - * Does *not* do HTML-escaping regardless of the value of {@code opt_isHtml}. - * The return value can be HTML-escaped as necessary. - * - * @param {?goog.i18n.bidi.Dir} dir {@code str}'s overall directionality, or - * null if unknown and needs to be estimated. - * @param {string} str The input text. - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped. - * Default: false. - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark - * matching the context directionality, when needed, to prevent the possible - * garbling of whatever may follow {@code str}. Default: true. - * @return {string} Input text after applying the above processing. - */ -goog.i18n.BidiFormatter.prototype.unicodeWrapWithKnownDir = function( - dir, str, opt_isHtml, opt_dirReset) { - if (dir == null) { - dir = this.estimateDirection(str, opt_isHtml); - } - return this.unicodeWrapWithKnownDir_(dir, str, opt_isHtml, opt_dirReset); -}; - - -/** - * The internal implementation of unicodeWrapWithKnownDir for non-null dir, to - * help the compiler optimize. - * - * @param {goog.i18n.bidi.Dir} dir {@code str}'s overall directionality. - * @param {string} str The input text. - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped. - * Default: false. - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark - * matching the context directionality, when needed, to prevent the possible - * garbling of whatever may follow {@code str}. Default: true. - * @return {string} Input text after applying the above processing. - * @private - */ -goog.i18n.BidiFormatter.prototype.unicodeWrapWithKnownDir_ = function( - dir, str, opt_isHtml, opt_dirReset) { - opt_dirReset = opt_dirReset || (opt_dirReset == undefined); - var result = []; - if (dir != goog.i18n.bidi.Dir.NEUTRAL && dir != this.contextDir_) { - result.push( - dir == goog.i18n.bidi.Dir.RTL ? goog.i18n.bidi.Format.RLE : - goog.i18n.bidi.Format.LRE); - result.push(str); - result.push(goog.i18n.bidi.Format.PDF); - } else { - result.push(str); - } - - result.push(this.dirResetIfNeeded_(str, dir, opt_isHtml, opt_dirReset)); - return result.join(''); -}; - - -/** - * Returns a Unicode BiDi mark matching the context directionality (LRM or RLM) - * if the directionality or the exit directionality of {@code str} are opposite - * to the context directionality. Otherwise returns the empty string. - * - * @param {string} str The input text. - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped. - * Default: false. - * @return {string} A Unicode bidi mark matching the global directionality or - * the empty string. - */ -goog.i18n.BidiFormatter.prototype.markAfter = function(str, opt_isHtml) { - return this.markAfterKnownDir(null, str, opt_isHtml); -}; - - -/** - * Returns a Unicode BiDi mark matching the context directionality (LRM or RLM) - * if the given directionality or the exit directionality of {@code str} are - * opposite to the context directionality. Otherwise returns the empty string. - * - * @param {?goog.i18n.bidi.Dir} dir {@code str}'s overall directionality, or - * null if unknown and needs to be estimated. - * @param {string} str The input text. - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped. - * Default: false. - * @return {string} A Unicode bidi mark matching the global directionality or - * the empty string. - */ -goog.i18n.BidiFormatter.prototype.markAfterKnownDir = function( - dir, str, opt_isHtml) { - if (dir == null) { - dir = this.estimateDirection(str, opt_isHtml); - } - return this.dirResetIfNeeded_(str, dir, opt_isHtml, true); -}; - - -/** - * Returns the Unicode BiDi mark matching the context directionality (LRM for - * LTR context directionality, RLM for RTL context directionality), or the - * empty string for neutral / unknown context directionality. - * - * @return {string} LRM for LTR context directionality and RLM for RTL context - * directionality. - */ -goog.i18n.BidiFormatter.prototype.mark = function() { - switch (this.contextDir_) { - case (goog.i18n.bidi.Dir.LTR): - return goog.i18n.bidi.Format.LRM; - case (goog.i18n.bidi.Dir.RTL): - return goog.i18n.bidi.Format.RLM; - default: - return ''; - } -}; - - -/** - * Returns 'right' for RTL context directionality. Otherwise (LTR or neutral / - * unknown context directionality) returns 'left'. - * - * @return {string} 'right' for RTL context directionality and 'left' for other - * context directionality. - */ -goog.i18n.BidiFormatter.prototype.startEdge = function() { - return this.contextDir_ == goog.i18n.bidi.Dir.RTL ? goog.i18n.bidi.RIGHT : - goog.i18n.bidi.LEFT; -}; - - -/** - * Returns 'left' for RTL context directionality. Otherwise (LTR or neutral / - * unknown context directionality) returns 'right'. - * - * @return {string} 'left' for RTL context directionality and 'right' for other - * context directionality. - */ -goog.i18n.BidiFormatter.prototype.endEdge = function() { - return this.contextDir_ == goog.i18n.bidi.Dir.RTL ? goog.i18n.bidi.LEFT : - goog.i18n.bidi.RIGHT; -};
diff --git a/third_party/ink/closure/i18n/graphemebreak.js b/third_party/ink/closure/i18n/graphemebreak.js deleted file mode 100644 index ba85f94..0000000 --- a/third_party/ink/closure/i18n/graphemebreak.js +++ /dev/null
@@ -1,451 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Detect Grapheme Cluster Break in a pair of codepoints. Follows - * Unicode 10 UAX#29. Tailoring for Virama × Indic Letters is used. - * - * Reference: http://unicode.org/reports/tr29 - * - * @author cibu@google.com (Cibu Johny) - * @author fabalbon@google.com (Felipe Balbontin) - */ - -goog.provide('goog.i18n.GraphemeBreak'); - -goog.require('goog.asserts'); -goog.require('goog.i18n.uChar'); -goog.require('goog.structs.InversionMap'); - -/** - * Enum for all Grapheme Cluster Break properties. - * These enums directly corresponds to Grapheme_Cluster_Break property values - * mentioned in http://unicode.org/reports/tr29 table 2. VIRAMA and - * INDIC_LETTER are for the Virama × Base tailoring mentioned in the notes. - * - * @protected @enum {number} - */ -goog.i18n.GraphemeBreak.property = { - OTHER: 0, - CONTROL: 1, - EXTEND: 2, - PREPEND: 3, - SPACING_MARK: 4, - INDIC_LETTER: 5, - VIRAMA: 6, - L: 7, - V: 8, - T: 9, - LV: 10, - LVT: 11, - CR: 12, - LF: 13, - REGIONAL_INDICATOR: 14, - ZWJ: 15, - E_BASE: 16, - GLUE_AFTER_ZWJ: 17, - E_MODIFIER: 18, - E_BASE_GAZ: 19 -}; - - -/** - * Grapheme Cluster Break property values for all codepoints as inversion map. - * Constructed lazily. - * - * @private {?goog.structs.InversionMap} - */ -goog.i18n.GraphemeBreak.inversions_ = null; - - -/** - * Indicates if a and b form a grapheme cluster. - * - * This implements the rules in: - * http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules - * - * @param {number|string} a Code point or string with the first side of - * grapheme cluster. - * @param {number|string} b Code point or string with the second side of - * grapheme cluster. - * @param {boolean} extended If true, indicates extended grapheme cluster; - * If false, indicates legacy cluster. - * @return {boolean} True if a & b do not form a cluster; False otherwise. - * @private - */ -goog.i18n.GraphemeBreak.applyBreakRules_ = function(a, b, extended) { - var prop = goog.i18n.GraphemeBreak.property; - - var aCode = goog.isString(a) ? - goog.i18n.GraphemeBreak.getCodePoint_(a, a.length - 1) : - a; - var bCode = - goog.isString(b) ? goog.i18n.GraphemeBreak.getCodePoint_(b, 0) : b; - - var aProp = goog.i18n.GraphemeBreak.getBreakProp_(aCode); - var bProp = goog.i18n.GraphemeBreak.getBreakProp_(bCode); - - var isString = goog.isString(a); - - // GB3. - if (aProp === prop.CR && bProp === prop.LF) { - return false; - } - - // GB4. - if (aProp === prop.CONTROL || aProp === prop.CR || aProp === prop.LF) { - return true; - } - - // GB5. - if (bProp === prop.CONTROL || bProp === prop.CR || bProp === prop.LF) { - return true; - } - - // GB6. - if (aProp === prop.L && - (bProp === prop.L || bProp === prop.V || bProp === prop.LV || - bProp === prop.LVT)) { - return false; - } - - // GB7. - if ((aProp === prop.LV || aProp === prop.V) && - (bProp === prop.V || bProp === prop.T)) { - return false; - } - - // GB8. - if ((aProp === prop.LVT || aProp === prop.T) && bProp === prop.T) { - return false; - } - - // GB9. - if (bProp === prop.EXTEND || bProp === prop.ZWJ || bProp === prop.VIRAMA) { - return false; - } - - // GB9a, GB9b. - if (extended && (aProp === prop.PREPEND || bProp === prop.SPACING_MARK)) { - return false; - } - - // Tailorings for basic aksara support. - if (extended && aProp === prop.VIRAMA && bProp === prop.INDIC_LETTER) { - return false; - } - - var aStr, index, codePoint, codePointProp; - - // GB10. - if (isString) { - if (bProp === prop.E_MODIFIER) { - // If using new API, consume the string's code points starting from the - // end and test the left side of: (E_Base | EBG) Extend* × E_Modifier. - aStr = /** @type {string} */ (a); - index = aStr.length - 1; - codePoint = aCode; - codePointProp = aProp; - while (index > 0 && codePointProp === prop.EXTEND) { - index -= goog.i18n.uChar.charCount(codePoint); - codePoint = goog.i18n.GraphemeBreak.getCodePoint_(aStr, index); - codePointProp = goog.i18n.GraphemeBreak.getBreakProp_(codePoint); - } - if (codePointProp === prop.E_BASE || codePointProp === prop.E_BASE_GAZ) { - return false; - } - } - } else { - // If using legacy API, return best effort by testing: - // (E_Base | EBG) × E_Modifier. - if ((aProp === prop.E_BASE || aProp === prop.E_BASE_GAZ) && - bProp === prop.E_MODIFIER) { - return false; - } - } - - // GB11. - if (aProp === prop.ZWJ && - (bProp === prop.GLUE_AFTER_ZWJ || bProp === prop.E_BASE_GAZ)) { - return false; - } - - // GB12, GB13. - if (isString) { - if (bProp === prop.REGIONAL_INDICATOR) { - // If using new API, consume the string's code points starting from the - // end and test the left side of these rules: - // - sot (RI RI)* RI × RI - // - [^RI] (RI RI)* RI × RI. - var numberOfRi = 0; - aStr = /** @type {string} */ (a); - index = aStr.length - 1; - codePoint = aCode; - codePointProp = aProp; - while (index > 0 && codePointProp === prop.REGIONAL_INDICATOR) { - numberOfRi++; - index -= goog.i18n.uChar.charCount(codePoint); - codePoint = goog.i18n.GraphemeBreak.getCodePoint_(aStr, index); - codePointProp = goog.i18n.GraphemeBreak.getBreakProp_(codePoint); - } - if (codePointProp === prop.REGIONAL_INDICATOR) { - numberOfRi++; - } - if (numberOfRi % 2 === 1) { - return false; - } - } - } else { - // If using legacy API, return best effort by testing: RI × RI. - if (aProp === prop.REGIONAL_INDICATOR && - bProp === prop.REGIONAL_INDICATOR) { - return false; - } - } - - // GB999. - return true; -}; - - -/** - * Method to return property enum value of the code point. If it is Hangul LV or - * LVT, then it is computed; for the rest it is picked from the inversion map. - * - * @param {number} codePoint The code point value of the character. - * @return {number} Property enum value of code point. - * @private - */ -goog.i18n.GraphemeBreak.getBreakProp_ = function(codePoint) { - if (0xAC00 <= codePoint && codePoint <= 0xD7A3) { - var prop = goog.i18n.GraphemeBreak.property; - if (codePoint % 0x1C === 0x10) { - return prop.LV; - } - return prop.LVT; - } else { - if (!goog.i18n.GraphemeBreak.inversions_) { - goog.i18n.GraphemeBreak.inversions_ = new goog.structs.InversionMap( - [ - 0, 10, 1, 2, 1, 18, 95, 33, 13, 1, - 594, 112, 275, 7, 263, 45, 1, 1, 1, 2, - 1, 2, 1, 1, 56, 6, 10, 11, 1, 1, - 46, 21, 16, 1, 101, 7, 1, 1, 6, 2, - 2, 1, 4, 33, 1, 1, 1, 30, 27, 91, - 11, 58, 9, 34, 4, 1, 9, 1, 3, 1, - 5, 43, 3, 120, 14, 1, 32, 1, 17, 37, - 1, 1, 1, 1, 3, 8, 4, 1, 2, 1, - 7, 8, 2, 2, 21, 7, 1, 1, 2, 17, - 39, 1, 1, 1, 2, 6, 6, 1, 9, 5, - 4, 2, 2, 12, 2, 15, 2, 1, 17, 39, - 2, 3, 12, 4, 8, 6, 17, 2, 3, 14, - 1, 17, 39, 1, 1, 3, 8, 4, 1, 20, - 2, 29, 1, 2, 17, 39, 1, 1, 2, 1, - 6, 6, 9, 6, 4, 2, 2, 13, 1, 16, - 1, 18, 41, 1, 1, 1, 12, 1, 9, 1, - 40, 1, 3, 17, 31, 1, 5, 4, 3, 5, - 7, 8, 3, 2, 8, 2, 29, 1, 2, 17, - 39, 1, 1, 1, 1, 2, 1, 3, 1, 5, - 1, 8, 9, 1, 3, 2, 29, 1, 2, 17, - 38, 3, 1, 2, 5, 7, 1, 1, 8, 1, - 10, 2, 30, 2, 22, 48, 5, 1, 2, 6, - 7, 1, 18, 2, 13, 46, 2, 1, 1, 1, - 6, 1, 12, 8, 50, 46, 2, 1, 1, 1, - 9, 11, 6, 14, 2, 58, 2, 27, 1, 1, - 1, 1, 1, 4, 2, 49, 14, 1, 4, 1, - 1, 2, 5, 48, 9, 1, 57, 33, 12, 4, - 1, 6, 1, 2, 2, 2, 1, 16, 2, 4, - 2, 2, 4, 3, 1, 3, 2, 7, 3, 4, - 13, 1, 1, 1, 2, 6, 1, 1, 14, 1, - 98, 96, 72, 88, 349, 3, 931, 15, 2, 1, - 14, 15, 2, 1, 14, 15, 2, 15, 15, 14, - 35, 17, 2, 1, 7, 8, 1, 2, 9, 1, - 1, 9, 1, 45, 3, 1, 118, 2, 34, 1, - 87, 28, 3, 3, 4, 2, 9, 1, 6, 3, - 20, 19, 29, 44, 84, 23, 2, 2, 1, 4, - 45, 6, 2, 1, 1, 1, 8, 1, 1, 1, - 2, 8, 6, 13, 48, 84, 1, 14, 33, 1, - 1, 5, 1, 1, 5, 1, 1, 1, 7, 31, - 9, 12, 2, 1, 7, 23, 1, 4, 2, 2, - 2, 2, 2, 11, 3, 2, 36, 2, 1, 1, - 2, 3, 1, 1, 3, 2, 12, 36, 8, 8, - 2, 2, 21, 3, 128, 3, 1, 13, 1, 7, - 4, 1, 4, 2, 1, 3, 2, 198, 64, 523, - 1, 1, 1, 2, 24, 7, 49, 16, 96, 33, - 1324, 1, 34, 1, 1, 1, 82, 2, 98, 1, - 14, 1, 1, 4, 86, 1, 1418, 3, 141, 1, - 96, 32, 554, 6, 105, 2, 30164, 4, 1, 10, - 32, 2, 80, 2, 272, 1, 3, 1, 4, 1, - 23, 2, 2, 1, 24, 30, 4, 4, 3, 8, - 1, 1, 13, 2, 16, 34, 16, 1, 1, 26, - 18, 24, 24, 4, 8, 2, 23, 11, 1, 1, - 12, 32, 3, 1, 5, 3, 3, 36, 1, 2, - 4, 2, 1, 3, 1, 36, 1, 32, 35, 6, - 2, 2, 2, 2, 12, 1, 8, 1, 1, 18, - 16, 1, 3, 6, 1, 1, 1, 3, 48, 1, - 1, 3, 2, 2, 5, 2, 1, 1, 32, 9, - 1, 2, 2, 5, 1, 1, 201, 14, 2, 1, - 1, 9, 8, 2, 1, 2, 1, 2, 1, 1, - 1, 18, 11184, 27, 49, 1028, 1024, 6942, 1, 737, - 16, 16, 16, 207, 1, 158, 2, 89, 3, 513, - 1, 226, 1, 149, 5, 1670, 15, 40, 7, 1, - 165, 2, 1305, 1, 1, 1, 53, 14, 1, 56, - 1, 2, 1, 45, 3, 4, 2, 1, 1, 2, - 1, 66, 3, 36, 5, 1, 6, 2, 62, 1, - 12, 2, 1, 48, 3, 9, 1, 1, 1, 2, - 6, 3, 95, 3, 3, 2, 1, 1, 2, 6, - 1, 160, 1, 3, 7, 1, 21, 2, 2, 56, - 1, 1, 1, 1, 1, 12, 1, 9, 1, 10, - 4, 15, 192, 3, 8, 2, 1, 2, 1, 1, - 105, 1, 2, 6, 1, 1, 2, 1, 1, 2, - 1, 1, 1, 235, 1, 2, 6, 4, 2, 1, - 1, 1, 27, 2, 82, 3, 8, 2, 1, 1, - 1, 1, 106, 1, 1, 1, 2, 6, 1, 1, - 101, 3, 2, 4, 1, 4, 1, 1283, 1, 14, - 1, 1, 82, 23, 1, 7, 1, 2, 1, 2, - 20025, 5, 59, 7, 1050, 62, 4, 19722, 2, 1, - 4, 5313, 1, 1, 3, 3, 1, 5, 8, 8, - 2, 7, 30, 4, 148, 3, 1979, 55, 4, 50, - 8, 1, 14, 1, 22, 1424, 2213, 7, 109, 7, - 2203, 26, 264, 1, 53, 1, 52, 1, 17, 1, - 13, 1, 16, 1, 3, 1, 25, 3, 2, 1, - 2, 3, 30, 1, 1, 1, 13, 5, 66, 2, - 2, 11, 21, 4, 4, 1, 1, 9, 3, 1, - 4, 3, 1, 3, 3, 1, 30, 1, 16, 2, - 106, 1, 4, 1, 71, 2, 4, 1, 21, 1, - 4, 2, 81, 1, 92, 3, 3, 5, 48, 1, - 17, 1, 16, 1, 16, 3, 9, 1, 11, 1, - 587, 5, 1, 1, 7, 1, 9, 10, 3, 2, - 788162, 31 - ], - [ - 1, 13, 1, 12, 1, 0, 1, 0, 1, 0, 2, 0, 2, 0, 2, 0, 2, 0, - 2, 0, 2, 0, 2, 0, 3, 0, 2, 0, 1, 0, 2, 0, 2, 0, 2, 3, - 0, 2, 0, 2, 0, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, - 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 3, 2, 4, 0, 5, 2, 4, 2, - 0, 4, 2, 4, 6, 4, 0, 2, 5, 0, 2, 0, 5, 0, 2, 4, 0, 5, - 2, 0, 2, 4, 2, 4, 6, 0, 2, 5, 0, 2, 0, 5, 0, 2, 4, 0, - 5, 2, 4, 2, 6, 2, 5, 0, 2, 0, 2, 4, 0, 5, 2, 0, 4, 2, - 4, 6, 0, 2, 0, 2, 4, 0, 5, 2, 0, 2, 4, 2, 4, 6, 2, 5, - 0, 2, 0, 5, 0, 2, 0, 5, 2, 4, 2, 4, 6, 0, 2, 0, 2, 4, - 0, 5, 0, 5, 0, 2, 4, 2, 6, 2, 5, 0, 2, 0, 2, 4, 0, 5, - 2, 0, 4, 2, 4, 2, 4, 2, 4, 2, 6, 2, 5, 0, 2, 0, 2, 4, - 0, 5, 0, 2, 4, 2, 4, 6, 3, 0, 2, 0, 2, 0, 4, 0, 5, 6, - 2, 4, 2, 4, 2, 0, 4, 0, 5, 0, 2, 0, 4, 2, 6, 0, 2, 0, - 5, 0, 2, 0, 4, 2, 0, 2, 0, 5, 0, 2, 0, 2, 0, 2, 0, 2, - 0, 4, 5, 2, 4, 2, 6, 0, 2, 0, 2, 0, 2, 0, 5, 0, 2, 4, - 2, 0, 6, 4, 2, 5, 0, 5, 0, 4, 2, 5, 2, 5, 0, 5, 0, 5, - 2, 5, 2, 0, 4, 2, 0, 2, 5, 0, 2, 0, 7, 8, 9, 0, 2, 0, - 5, 2, 6, 0, 5, 2, 6, 0, 5, 2, 0, 5, 2, 5, 0, 2, 4, 2, - 4, 2, 4, 2, 6, 2, 0, 2, 0, 2, 1, 0, 2, 0, 2, 0, 5, 0, - 2, 4, 2, 4, 2, 4, 2, 0, 5, 0, 5, 0, 5, 2, 4, 2, 0, 5, - 0, 5, 4, 2, 4, 2, 6, 0, 2, 0, 2, 4, 2, 0, 2, 4, 0, 5, - 2, 4, 2, 4, 2, 4, 2, 4, 6, 5, 0, 2, 0, 2, 4, 0, 5, 4, - 2, 4, 2, 6, 2, 5, 0, 5, 0, 5, 0, 2, 4, 2, 4, 2, 4, 2, - 6, 0, 5, 4, 2, 4, 2, 0, 5, 0, 2, 0, 2, 4, 2, 0, 2, 0, - 4, 2, 0, 2, 0, 2, 0, 1, 2, 15, 1, 0, 1, 0, 1, 0, 2, 0, - 16, 0, 17, 0, 17, 0, 17, 0, 16, 0, 17, 0, 16, 0, 17, 0, 2, 0, - 6, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, - 6, 5, 2, 5, 4, 2, 4, 0, 5, 0, 5, 0, 5, 0, 5, 0, 4, 0, - 5, 4, 6, 2, 0, 2, 0, 5, 0, 2, 0, 5, 2, 4, 6, 0, 7, 2, - 4, 0, 5, 0, 5, 2, 4, 2, 4, 2, 4, 6, 0, 2, 0, 5, 2, 4, - 2, 4, 2, 0, 2, 0, 2, 4, 0, 5, 0, 5, 0, 5, 0, 2, 0, 5, - 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 5, 4, 2, 4, 0, 4, 6, 0, - 5, 0, 5, 0, 5, 0, 4, 2, 4, 2, 4, 0, 4, 6, 0, 11, 8, 9, - 0, 2, 0, 2, 0, 2, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 2, - 0, 2, 0, 2, 0, 2, 6, 0, 2, 0, 4, 2, 4, 0, 2, 6, 0, 6, - 2, 4, 0, 4, 2, 4, 6, 2, 0, 3, 0, 2, 0, 2, 4, 2, 6, 0, - 2, 0, 2, 4, 0, 4, 2, 4, 6, 0, 3, 0, 2, 0, 4, 2, 4, 2, - 6, 2, 0, 2, 0, 2, 4, 2, 6, 0, 2, 4, 0, 2, 0, 2, 4, 2, - 4, 6, 0, 2, 0, 4, 2, 0, 4, 2, 4, 6, 2, 4, 2, 0, 2, 4, - 2, 4, 2, 4, 2, 4, 2, 4, 6, 2, 0, 2, 4, 2, 4, 2, 4, 6, - 2, 0, 2, 0, 4, 2, 4, 2, 4, 6, 2, 0, 2, 4, 2, 4, 2, 6, - 2, 0, 2, 4, 2, 4, 2, 6, 0, 4, 2, 4, 6, 0, 2, 4, 2, 4, - 2, 4, 2, 0, 2, 0, 2, 0, 4, 2, 0, 2, 0, 1, 0, 2, 4, 2, - 0, 4, 2, 1, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, - 2, 0, 2, 0, 2, 0, 2, 0, 14, 0, 17, 0, 17, 0, 17, 0, 16, 0, - 17, 0, 17, 0, 17, 0, 16, 0, 16, 0, 16, 0, 17, 0, 17, 0, 18, 0, - 16, 0, 16, 0, 19, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 17, 0, - 16, 0, 17, 0, 17, 0, 17, 0, 16, 0, 16, 0, 16, 0, 16, 0, 17, 0, - 16, 0, 16, 0, 17, 0, 17, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, - 16, 0, 16, 0, 16, 0, 16, 0, 1, 2 - ], - true); - } - return /** @type {number} */ ( - goog.i18n.GraphemeBreak.inversions_.at(codePoint)); - } -}; - -/** - * Extracts a code point from a string at the specified index. - * - * @param {string} str - * @param {number} index - * @return {number} Extracted code point. - * @private - */ -goog.i18n.GraphemeBreak.getCodePoint_ = function(str, index) { - var codePoint = goog.i18n.uChar.getCodePointAround(str, index); - return (codePoint < 0) ? -codePoint : codePoint; -}; - -/** - * Indicates if there is a grapheme cluster boundary between a and b. - * - * Legacy function. Does not cover cases where a sequence of code points is - * required in order to decide if there is a grapheme cluster boundary, such as - * emoji modifier sequences and emoji flag sequences. To cover all cases please - * use {@code hasGraphemeBreakStrings}. - * - * There are two kinds of grapheme clusters: 1) Legacy 2) Extended. This method - * is to check for both using a boolean flag to switch between them. If no flag - * is provided rules for the extended clusters will be used by default. - * - * @param {number} a The code point value of the first character. - * @param {number} b The code point value of the second character. - * @param {boolean=} opt_extended If true, indicates extended grapheme cluster; - * If false, indicates legacy cluster. Default value is true. - * @return {boolean} True if there is a grapheme cluster boundary between - * a and b; False otherwise. - */ -goog.i18n.GraphemeBreak.hasGraphemeBreak = function(a, b, opt_extended) { - return goog.i18n.GraphemeBreak.applyBreakRules_(a, b, opt_extended !== false); -}; - -/** - * Indicates if there is a grapheme cluster boundary between a and b. - * - * There are two kinds of grapheme clusters: 1) Legacy 2) Extended. This method - * is to check for both using a boolean flag to switch between them. If no flag - * is provided rules for the extended clusters will be used by default. - * - * @param {string} a String with the first sequence of characters. - * @param {string} b String with the second sequence of characters. - * @param {boolean=} opt_extended If true, indicates extended grapheme cluster; - * If false, indicates legacy cluster. Default value is true. - * @return {boolean} True if there is a grapheme cluster boundary between - * a and b; False otherwise. - */ -goog.i18n.GraphemeBreak.hasGraphemeBreakStrings = function(a, b, opt_extended) { - goog.asserts.assert(goog.isDef(a), 'First string should be defined.'); - goog.asserts.assert(goog.isDef(b), 'Second string should be defined.'); - - // Break if any of the strings is empty. - if (a.length === 0 || b.length === 0) { - return true; - } - - return goog.i18n.GraphemeBreak.applyBreakRules_(a, b, opt_extended !== false); -};
diff --git a/third_party/ink/closure/i18n/uchar.js b/third_party/ink/closure/i18n/uchar.js deleted file mode 100644 index 6c22c40..0000000 --- a/third_party/ink/closure/i18n/uchar.js +++ /dev/null
@@ -1,294 +0,0 @@ -// Copyright 2009 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Collection of utility functions for Unicode character. - * - * @author cibu@google.com (Cibu Johny) - * @author burakov@google.com (Danny Burakov) - */ - -goog.provide('goog.i18n.uChar'); - - -// Constants for handling Unicode supplementary characters (surrogate pairs). - - -/** - * The minimum value for Supplementary code points. - * @type {number} - * @private - */ -goog.i18n.uChar.SUPPLEMENTARY_CODE_POINT_MIN_VALUE_ = 0x10000; - - -/** - * The highest Unicode code point value (scalar value) according to the Unicode - * Standard. - * @type {number} - * @private - */ -goog.i18n.uChar.CODE_POINT_MAX_VALUE_ = 0x10FFFF; - - -/** - * Lead surrogate minimum value. - * @type {number} - * @private - */ -goog.i18n.uChar.LEAD_SURROGATE_MIN_VALUE_ = 0xD800; - - -/** - * Lead surrogate maximum value. - * @type {number} - * @private - */ -goog.i18n.uChar.LEAD_SURROGATE_MAX_VALUE_ = 0xDBFF; - - -/** - * Trail surrogate minimum value. - * @type {number} - * @private - */ -goog.i18n.uChar.TRAIL_SURROGATE_MIN_VALUE_ = 0xDC00; - - -/** - * Trail surrogate maximum value. - * @type {number} - * @private - */ -goog.i18n.uChar.TRAIL_SURROGATE_MAX_VALUE_ = 0xDFFF; - - -/** - * The number of least significant bits of a supplementary code point that in - * UTF-16 become the least significant bits of the trail surrogate. The rest of - * the in-use bits of the supplementary code point become the least significant - * bits of the lead surrogate. - * @type {number} - * @private - */ -goog.i18n.uChar.TRAIL_SURROGATE_BIT_COUNT_ = 10; - - -/** - * Gets the U+ notation string of a Unicode character. Ex: 'U+0041' for 'A'. - * @param {string} ch The given character. - * @return {string} The U+ notation of the given character. - */ -goog.i18n.uChar.toHexString = function(ch) { - var chCode = goog.i18n.uChar.toCharCode(ch); - var chCodeStr = 'U+' + - goog.i18n.uChar.padString_(chCode.toString(16).toUpperCase(), 4, '0'); - - return chCodeStr; -}; - - -/** - * Gets a string padded with given character to get given size. - * @param {string} str The given string to be padded. - * @param {number} length The target size of the string. - * @param {string} ch The character to be padded with. - * @return {string} The padded string. - * @private - */ -goog.i18n.uChar.padString_ = function(str, length, ch) { - while (str.length < length) { - str = ch + str; - } - return str; -}; - - -/** - * Gets Unicode value of the given character. - * @param {string} ch The given character, which in the case of a supplementary - * character is actually a surrogate pair. The remainder of the string is - * ignored. - * @return {number} The Unicode value of the character. - */ -goog.i18n.uChar.toCharCode = function(ch) { - return goog.i18n.uChar.getCodePointAround(ch, 0); -}; - - -/** - * Gets a character from the given Unicode value. If the given code point is not - * a valid Unicode code point, null is returned. - * @param {number} code The Unicode value of the character. - * @return {?string} The character corresponding to the given Unicode value. - */ -goog.i18n.uChar.fromCharCode = function(code) { - if (!goog.isDefAndNotNull(code) || - !(code >= 0 && code <= goog.i18n.uChar.CODE_POINT_MAX_VALUE_)) { - return null; - } - if (goog.i18n.uChar.isSupplementaryCodePoint(code)) { - // First, we split the code point into the trail surrogate part (the - // TRAIL_SURROGATE_BIT_COUNT_ least significant bits) and the lead surrogate - // part (the rest of the bits, shifted down; note that for now this includes - // the supplementary offset, also shifted down, to be subtracted off below). - var leadBits = code >> goog.i18n.uChar.TRAIL_SURROGATE_BIT_COUNT_; - var trailBits = code & - // A bit-mask to get the TRAIL_SURROGATE_BIT_COUNT_ (i.e. 10) least - // significant bits. 1 << 10 = 0x0400. 0x0400 - 1 = 0x03FF. - ((1 << goog.i18n.uChar.TRAIL_SURROGATE_BIT_COUNT_) - 1); - - // Now we calculate the code point of each surrogate by adding each offset - // to the corresponding base code point. - var leadCodePoint = leadBits + - (goog.i18n.uChar.LEAD_SURROGATE_MIN_VALUE_ - - // Subtract off the supplementary offset, which had been shifted down - // with the rest of leadBits. We do this here instead of before the - // shift in order to save a separate subtraction step. - (goog.i18n.uChar.SUPPLEMENTARY_CODE_POINT_MIN_VALUE_ >> - goog.i18n.uChar.TRAIL_SURROGATE_BIT_COUNT_)); - var trailCodePoint = trailBits + goog.i18n.uChar.TRAIL_SURROGATE_MIN_VALUE_; - - // Convert the code points into a 2-character long string. - return String.fromCharCode(leadCodePoint) + - String.fromCharCode(trailCodePoint); - } - return String.fromCharCode(code); -}; - - -/** - * Returns the Unicode code point at the specified index. - * - * If the char value specified at the given index is in the leading-surrogate - * range, and the following index is less than the length of {@code string}, and - * the char value at the following index is in the trailing-surrogate range, - * then the supplementary code point corresponding to this surrogate pair is - * returned. - * - * If the char value specified at the given index is in the trailing-surrogate - * range, and the preceding index is not before the start of {@code string}, and - * the char value at the preceding index is in the leading-surrogate range, then - * the negated supplementary code point corresponding to this surrogate pair is - * returned. - * - * The negation allows the caller to differentiate between the case where the - * given index is at the leading surrogate and the one where it is at the - * trailing surrogate, and thus deduce where the next character starts and - * preceding character ends. - * - * Otherwise, the char value at the given index is returned. Thus, a leading - * surrogate is returned when it is not followed by a trailing surrogate, and a - * trailing surrogate is returned when it is not preceded by a leading - * surrogate. - * - * @param {string} string The string. - * @param {number} index The index from which the code point is to be retrieved. - * @return {number} The code point at the given index. If the given index is - * that of the start (i.e. lead surrogate) of a surrogate pair, returns the code - * point encoded by the pair. If the given index is that of the end (i.e. trail - * surrogate) of a surrogate pair, returns the negated code pointed encoded by - * the pair. - */ -goog.i18n.uChar.getCodePointAround = function(string, index) { - var charCode = string.charCodeAt(index); - if (goog.i18n.uChar.isLeadSurrogateCodePoint(charCode) && - index + 1 < string.length) { - var trail = string.charCodeAt(index + 1); - if (goog.i18n.uChar.isTrailSurrogateCodePoint(trail)) { - // Part of a surrogate pair. - return /** @type {number} */ ( - goog.i18n.uChar.buildSupplementaryCodePoint(charCode, trail)); - } - } else if (goog.i18n.uChar.isTrailSurrogateCodePoint(charCode) && index > 0) { - var lead = string.charCodeAt(index - 1); - if (goog.i18n.uChar.isLeadSurrogateCodePoint(lead)) { - // Part of a surrogate pair. - return /** @type {number} */ ( - -goog.i18n.uChar.buildSupplementaryCodePoint(lead, charCode)); - } - } - return charCode; -}; - - -/** - * Determines the length of the string needed to represent the specified - * Unicode code point. - * @param {number} codePoint - * @return {number} 2 if codePoint is a supplementary character, 1 otherwise. - */ -goog.i18n.uChar.charCount = function(codePoint) { - return goog.i18n.uChar.isSupplementaryCodePoint(codePoint) ? 2 : 1; -}; - - -/** - * Determines whether the specified Unicode code point is in the supplementary - * Unicode characters range. - * @param {number} codePoint - * @return {boolean} Whether then given code point is a supplementary character. - */ -goog.i18n.uChar.isSupplementaryCodePoint = function(codePoint) { - return codePoint >= goog.i18n.uChar.SUPPLEMENTARY_CODE_POINT_MIN_VALUE_ && - codePoint <= goog.i18n.uChar.CODE_POINT_MAX_VALUE_; -}; - - -/** - * Gets whether the given code point is a leading surrogate character. - * @param {number} codePoint - * @return {boolean} Whether the given code point is a leading surrogate - * character. - */ -goog.i18n.uChar.isLeadSurrogateCodePoint = function(codePoint) { - return codePoint >= goog.i18n.uChar.LEAD_SURROGATE_MIN_VALUE_ && - codePoint <= goog.i18n.uChar.LEAD_SURROGATE_MAX_VALUE_; -}; - - -/** - * Gets whether the given code point is a trailing surrogate character. - * @param {number} codePoint - * @return {boolean} Whether the given code point is a trailing surrogate - * character. - */ -goog.i18n.uChar.isTrailSurrogateCodePoint = function(codePoint) { - return codePoint >= goog.i18n.uChar.TRAIL_SURROGATE_MIN_VALUE_ && - codePoint <= goog.i18n.uChar.TRAIL_SURROGATE_MAX_VALUE_; -}; - - -/** - * Composes a supplementary Unicode code point from the given UTF-16 surrogate - * pair. If leadSurrogate isn't a leading surrogate code point or trailSurrogate - * isn't a trailing surrogate code point, null is returned. - * @param {number} lead The leading surrogate code point. - * @param {number} trail The trailing surrogate code point. - * @return {?number} The supplementary Unicode code point obtained by decoding - * the given UTF-16 surrogate pair. - */ -goog.i18n.uChar.buildSupplementaryCodePoint = function(lead, trail) { - if (goog.i18n.uChar.isLeadSurrogateCodePoint(lead) && - goog.i18n.uChar.isTrailSurrogateCodePoint(trail)) { - var shiftedLeadOffset = - (lead << goog.i18n.uChar.TRAIL_SURROGATE_BIT_COUNT_) - - (goog.i18n.uChar.LEAD_SURROGATE_MIN_VALUE_ - << goog.i18n.uChar.TRAIL_SURROGATE_BIT_COUNT_); - var trailOffset = trail - goog.i18n.uChar.TRAIL_SURROGATE_MIN_VALUE_ + - goog.i18n.uChar.SUPPLEMENTARY_CODE_POINT_MIN_VALUE_; - return shiftedLeadOffset + trailOffset; - } - return null; -};
diff --git a/third_party/ink/closure/iter/iter.js b/third_party/ink/closure/iter/iter.js deleted file mode 100644 index 534d24ad..0000000 --- a/third_party/ink/closure/iter/iter.js +++ /dev/null
@@ -1,1284 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Python style iteration utilities. - * @author arv@google.com (Erik Arvidsson) - */ - - -goog.provide('goog.iter'); -goog.provide('goog.iter.Iterable'); -goog.provide('goog.iter.Iterator'); -goog.provide('goog.iter.StopIteration'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.functions'); -goog.require('goog.math'); - - -/** - * @typedef {goog.iter.Iterator|{length:number}|{__iterator__}} - */ -goog.iter.Iterable; - - -/** - * Singleton Error object that is used to terminate iterations. - * @const {!Error} - */ -goog.iter.StopIteration = ('StopIteration' in goog.global) ? - // For script engines that support legacy iterators. - goog.global['StopIteration'] : - {message: 'StopIteration', stack: ''}; - - - -/** - * Class/interface for iterators. An iterator needs to implement a {@code next} - * method and it needs to throw a {@code goog.iter.StopIteration} when the - * iteration passes beyond the end. Iterators have no {@code hasNext} method. - * It is recommended to always use the helper functions to iterate over the - * iterator or in case you are only targeting JavaScript 1.7 for in loops. - * @constructor - * @template VALUE - */ -goog.iter.Iterator = function() {}; - - -/** - * Returns the next value of the iteration. This will throw the object - * {@see goog.iter#StopIteration} when the iteration passes the end. - * @return {VALUE} Any object or value. - */ -goog.iter.Iterator.prototype.next = function() { - throw goog.iter.StopIteration; -}; - - -/** - * Returns the {@code Iterator} object itself. This is used to implement - * the iterator protocol in JavaScript 1.7 - * @param {boolean=} opt_keys Whether to return the keys or values. Default is - * to only return the values. This is being used by the for-in loop (true) - * and the for-each-in loop (false). Even though the param gives a hint - * about what the iterator will return there is no guarantee that it will - * return the keys when true is passed. - * @return {!goog.iter.Iterator<VALUE>} The object itself. - */ -goog.iter.Iterator.prototype.__iterator__ = function(opt_keys) { - return this; -}; - - -/** - * Returns an iterator that knows how to iterate over the values in the object. - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable If the - * object is an iterator it will be returned as is. If the object has an - * {@code __iterator__} method that will be called to get the value - * iterator. If the object is an array-like object we create an iterator - * for that. - * @return {!goog.iter.Iterator<VALUE>} An iterator that knows how to iterate - * over the values in {@code iterable}. - * @template VALUE - */ -goog.iter.toIterator = function(iterable) { - if (iterable instanceof goog.iter.Iterator) { - return iterable; - } - if (typeof iterable.__iterator__ == 'function') { - return iterable.__iterator__(false); - } - if (goog.isArrayLike(iterable)) { - var i = 0; - var newIter = new goog.iter.Iterator; - newIter.next = function() { - while (true) { - if (i >= iterable.length) { - throw goog.iter.StopIteration; - } - // Don't include deleted elements. - if (!(i in iterable)) { - i++; - continue; - } - return iterable[i++]; - } - }; - return newIter; - } - - - // TODO(arv): Should we fall back on goog.structs.getValues()? - throw new Error('Not implemented'); -}; - - -/** - * Calls a function for each element in the iterator with the element of the - * iterator passed as argument. - * - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator - * to iterate over. If the iterable is an object {@code toIterator} will be - * called on it. - * @param {function(this:THIS,VALUE,?,!goog.iter.Iterator<VALUE>)} f - * The function to call for every element. This function takes 3 arguments - * (the element, undefined, and the iterator) and the return value is - * irrelevant. The reason for passing undefined as the second argument is - * so that the same function can be used in {@see goog.array#forEach} as - * well as others. The third parameter is of type "number" for - * arraylike objects, undefined, otherwise. - * @param {THIS=} opt_obj The object to be used as the value of 'this' within - * {@code f}. - * @template THIS, VALUE - */ -goog.iter.forEach = function(iterable, f, opt_obj) { - if (goog.isArrayLike(iterable)) { - - try { - // NOTES: this passes the index number to the second parameter - // of the callback contrary to the documentation above. - goog.array.forEach( - /** @type {IArrayLike<?>} */ (iterable), f, opt_obj); - } catch (ex) { - if (ex !== goog.iter.StopIteration) { - throw ex; - } - } - } else { - iterable = goog.iter.toIterator(iterable); - - try { - while (true) { - f.call(opt_obj, iterable.next(), undefined, iterable); - } - } catch (ex) { - if (ex !== goog.iter.StopIteration) { - throw ex; - } - } - } -}; - - -/** - * Calls a function for every element in the iterator, and if the function - * returns true adds the element to a new iterator. - * - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator - * to iterate over. - * @param { - * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f - * The function to call for every element. This function takes 3 arguments - * (the element, undefined, and the iterator) and should return a boolean. - * If the return value is true the element will be included in the returned - * iterator. If it is false the element is not included. - * @param {THIS=} opt_obj The object to be used as the value of 'this' within - * {@code f}. - * @return {!goog.iter.Iterator<VALUE>} A new iterator in which only elements - * that passed the test are present. - * @template THIS, VALUE - */ -goog.iter.filter = function(iterable, f, opt_obj) { - var iterator = goog.iter.toIterator(iterable); - var newIter = new goog.iter.Iterator; - newIter.next = function() { - while (true) { - var val = iterator.next(); - if (f.call(opt_obj, val, undefined, iterator)) { - return val; - } - } - }; - return newIter; -}; - - -/** - * Calls a function for every element in the iterator, and if the function - * returns false adds the element to a new iterator. - * - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator - * to iterate over. - * @param { - * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f - * The function to call for every element. This function takes 3 arguments - * (the element, undefined, and the iterator) and should return a boolean. - * If the return value is false the element will be included in the returned - * iterator. If it is true the element is not included. - * @param {THIS=} opt_obj The object to be used as the value of 'this' within - * {@code f}. - * @return {!goog.iter.Iterator<VALUE>} A new iterator in which only elements - * that did not pass the test are present. - * @template THIS, VALUE - */ -goog.iter.filterFalse = function(iterable, f, opt_obj) { - return goog.iter.filter(iterable, goog.functions.not(f), opt_obj); -}; - - -/** - * Creates a new iterator that returns the values in a range. This function - * can take 1, 2 or 3 arguments: - * <pre> - * range(5) same as range(0, 5, 1) - * range(2, 5) same as range(2, 5, 1) - * </pre> - * - * @param {number} startOrStop The stop value if only one argument is provided. - * The start value if 2 or more arguments are provided. If only one - * argument is used the start value is 0. - * @param {number=} opt_stop The stop value. If left out then the first - * argument is used as the stop value. - * @param {number=} opt_step The number to increment with between each call to - * next. This can be negative. - * @return {!goog.iter.Iterator<number>} A new iterator that returns the values - * in the range. - */ -goog.iter.range = function(startOrStop, opt_stop, opt_step) { - var start = 0; - var stop = startOrStop; - var step = opt_step || 1; - if (arguments.length > 1) { - start = startOrStop; - stop = opt_stop; - } - if (step == 0) { - throw new Error('Range step argument must not be zero'); - } - - var newIter = new goog.iter.Iterator; - newIter.next = function() { - if (step > 0 && start >= stop || step < 0 && start <= stop) { - throw goog.iter.StopIteration; - } - var rv = start; - start += step; - return rv; - }; - return newIter; -}; - - -/** - * Joins the values in a iterator with a delimiter. - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator - * to get the values from. - * @param {string} deliminator The text to put between the values. - * @return {string} The joined value string. - * @template VALUE - */ -goog.iter.join = function(iterable, deliminator) { - return goog.iter.toArray(iterable).join(deliminator); -}; - - -/** - * For every element in the iterator call a function and return a new iterator - * with that value. - * - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterator to iterate over. - * @param { - * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):RESULT} f - * The function to call for every element. This function takes 3 arguments - * (the element, undefined, and the iterator) and should return a new value. - * @param {THIS=} opt_obj The object to be used as the value of 'this' within - * {@code f}. - * @return {!goog.iter.Iterator<RESULT>} A new iterator that returns the - * results of applying the function to each element in the original - * iterator. - * @template THIS, VALUE, RESULT - */ -goog.iter.map = function(iterable, f, opt_obj) { - var iterator = goog.iter.toIterator(iterable); - var newIter = new goog.iter.Iterator; - newIter.next = function() { - var val = iterator.next(); - return f.call(opt_obj, val, undefined, iterator); - }; - return newIter; -}; - - -/** - * Passes every element of an iterator into a function and accumulates the - * result. - * - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator - * to iterate over. - * @param {function(this:THIS,VALUE,VALUE):VALUE} f The function to call for - * every element. This function takes 2 arguments (the function's previous - * result or the initial value, and the value of the current element). - * function(previousValue, currentElement) : newValue. - * @param {VALUE} val The initial value to pass into the function on the first - * call. - * @param {THIS=} opt_obj The object to be used as the value of 'this' within - * f. - * @return {VALUE} Result of evaluating f repeatedly across the values of - * the iterator. - * @template THIS, VALUE - */ -goog.iter.reduce = function(iterable, f, val, opt_obj) { - var rval = val; - goog.iter.forEach( - iterable, function(val) { rval = f.call(opt_obj, rval, val); }); - return rval; -}; - - -/** - * Goes through the values in the iterator. Calls f for each of these, and if - * any of them returns true, this returns true (without checking the rest). If - * all return false this will return false. - * - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator - * object. - * @param { - * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f - * The function to call for every value. This function takes 3 arguments - * (the value, undefined, and the iterator) and should return a boolean. - * @param {THIS=} opt_obj The object to be used as the value of 'this' within - * {@code f}. - * @return {boolean} true if any value passes the test. - * @template THIS, VALUE - */ -goog.iter.some = function(iterable, f, opt_obj) { - iterable = goog.iter.toIterator(iterable); - - try { - while (true) { - if (f.call(opt_obj, iterable.next(), undefined, iterable)) { - return true; - } - } - } catch (ex) { - if (ex !== goog.iter.StopIteration) { - throw ex; - } - } - return false; -}; - - -/** - * Goes through the values in the iterator. Calls f for each of these and if any - * of them returns false this returns false (without checking the rest). If all - * return true this will return true. - * - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator - * object. - * @param { - * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f - * The function to call for every value. This function takes 3 arguments - * (the value, undefined, and the iterator) and should return a boolean. - * @param {THIS=} opt_obj The object to be used as the value of 'this' within - * {@code f}. - * @return {boolean} true if every value passes the test. - * @template THIS, VALUE - */ -goog.iter.every = function(iterable, f, opt_obj) { - iterable = goog.iter.toIterator(iterable); - - try { - while (true) { - if (!f.call(opt_obj, iterable.next(), undefined, iterable)) { - return false; - } - } - } catch (ex) { - if (ex !== goog.iter.StopIteration) { - throw ex; - } - } - return true; -}; - - -/** - * Takes zero or more iterables and returns one iterator that will iterate over - * them in the order chained. - * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any - * number of iterable objects. - * @return {!goog.iter.Iterator<VALUE>} Returns a new iterator that will - * iterate over all the given iterables' contents. - * @template VALUE - */ -goog.iter.chain = function(var_args) { - return goog.iter.chainFromIterable(arguments); -}; - - -/** - * Takes a single iterable containing zero or more iterables and returns one - * iterator that will iterate over each one in the order given. - * @see https://goo.gl/5NRp5d - * @param {goog.iter.Iterable} iterable The iterable of iterables to chain. - * @return {!goog.iter.Iterator<VALUE>} Returns a new iterator that will - * iterate over all the contents of the iterables contained within - * {@code iterable}. - * @template VALUE - */ -goog.iter.chainFromIterable = function(iterable) { - var iterator = goog.iter.toIterator(iterable); - var iter = new goog.iter.Iterator(); - var current = null; - - iter.next = function() { - while (true) { - if (current == null) { - var it = iterator.next(); - current = goog.iter.toIterator(it); - } - try { - return current.next(); - } catch (ex) { - if (ex !== goog.iter.StopIteration) { - throw ex; - } - current = null; - } - } - }; - - return iter; -}; - - -/** - * Builds a new iterator that iterates over the original, but skips elements as - * long as a supplied function returns true. - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator - * object. - * @param { - * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f - * The function to call for every value. This function takes 3 arguments - * (the value, undefined, and the iterator) and should return a boolean. - * @param {THIS=} opt_obj The object to be used as the value of 'this' within - * {@code f}. - * @return {!goog.iter.Iterator<VALUE>} A new iterator that drops elements from - * the original iterator as long as {@code f} is true. - * @template THIS, VALUE - */ -goog.iter.dropWhile = function(iterable, f, opt_obj) { - var iterator = goog.iter.toIterator(iterable); - var newIter = new goog.iter.Iterator; - var dropping = true; - newIter.next = function() { - while (true) { - var val = iterator.next(); - if (dropping && f.call(opt_obj, val, undefined, iterator)) { - continue; - } else { - dropping = false; - } - return val; - } - }; - return newIter; -}; - - -/** - * Builds a new iterator that iterates over the original, but only as long as a - * supplied function returns true. - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator - * object. - * @param { - * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f - * The function to call for every value. This function takes 3 arguments - * (the value, undefined, and the iterator) and should return a boolean. - * @param {THIS=} opt_obj This is used as the 'this' object in f when called. - * @return {!goog.iter.Iterator<VALUE>} A new iterator that keeps elements in - * the original iterator as long as the function is true. - * @template THIS, VALUE - */ -goog.iter.takeWhile = function(iterable, f, opt_obj) { - var iterator = goog.iter.toIterator(iterable); - var iter = new goog.iter.Iterator(); - iter.next = function() { - var val = iterator.next(); - if (f.call(opt_obj, val, undefined, iterator)) { - return val; - } - throw goog.iter.StopIteration; - }; - return iter; -}; - - -/** - * Converts the iterator to an array - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator - * to convert to an array. - * @return {!Array<VALUE>} An array of the elements the iterator iterates over. - * @template VALUE - */ -goog.iter.toArray = function(iterable) { - // Fast path for array-like. - if (goog.isArrayLike(iterable)) { - return goog.array.toArray(/** @type {!IArrayLike<?>} */ (iterable)); - } - iterable = goog.iter.toIterator(iterable); - var array = []; - goog.iter.forEach(iterable, function(val) { array.push(val); }); - return array; -}; - - -/** - * Iterates over two iterables and returns true if they contain the same - * sequence of elements and have the same length. - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable1 The first - * iterable object. - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable2 The second - * iterable object. - * @param {function(VALUE,VALUE):boolean=} opt_equalsFn Optional comparison - * function. - * Should take two arguments to compare, and return true if the arguments - * are equal. Defaults to {@link goog.array.defaultCompareEquality} which - * compares the elements using the built-in '===' operator. - * @return {boolean} true if the iterables contain the same sequence of elements - * and have the same length. - * @template VALUE - */ -goog.iter.equals = function(iterable1, iterable2, opt_equalsFn) { - var fillValue = {}; - var pairs = goog.iter.zipLongest(fillValue, iterable1, iterable2); - var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality; - return goog.iter.every( - pairs, function(pair) { return equalsFn(pair[0], pair[1]); }); -}; - - -/** - * Advances the iterator to the next position, returning the given default value - * instead of throwing an exception if the iterator has no more entries. - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterable - * object. - * @param {VALUE} defaultValue The value to return if the iterator is empty. - * @return {VALUE} The next item in the iteration, or defaultValue if the - * iterator was empty. - * @template VALUE - */ -goog.iter.nextOrValue = function(iterable, defaultValue) { - try { - return goog.iter.toIterator(iterable).next(); - } catch (e) { - if (e != goog.iter.StopIteration) { - throw e; - } - return defaultValue; - } -}; - - -/** - * Cartesian product of zero or more sets. Gives an iterator that gives every - * combination of one element chosen from each set. For example, - * ([1, 2], [3, 4]) gives ([1, 3], [1, 4], [2, 3], [2, 4]). - * @see http://docs.python.org/library/itertools.html#itertools.product - * @param {...!IArrayLike<VALUE>} var_args Zero or more sets, as - * arrays. - * @return {!goog.iter.Iterator<!Array<VALUE>>} An iterator that gives each - * n-tuple (as an array). - * @template VALUE - */ -goog.iter.product = function(var_args) { - var someArrayEmpty = - goog.array.some(arguments, function(arr) { return !arr.length; }); - - // An empty set in a cartesian product gives an empty set. - if (someArrayEmpty || !arguments.length) { - return new goog.iter.Iterator(); - } - - var iter = new goog.iter.Iterator(); - var arrays = arguments; - - // The first indices are [0, 0, ...] - var indicies = goog.array.repeat(0, arrays.length); - - iter.next = function() { - - if (indicies) { - var retVal = goog.array.map(indicies, function(valueIndex, arrayIndex) { - return arrays[arrayIndex][valueIndex]; - }); - - // Generate the next-largest indices for the next call. - // Increase the rightmost index. If it goes over, increase the next - // rightmost (like carry-over addition). - for (var i = indicies.length - 1; i >= 0; i--) { - // Assertion prevents compiler warning below. - goog.asserts.assert(indicies); - if (indicies[i] < arrays[i].length - 1) { - indicies[i]++; - break; - } - - // We're at the last indices (the last element of every array), so - // the iteration is over on the next call. - if (i == 0) { - indicies = null; - break; - } - // Reset the index in this column and loop back to increment the - // next one. - indicies[i] = 0; - } - return retVal; - } - - throw goog.iter.StopIteration; - }; - - return iter; -}; - - -/** - * Create an iterator to cycle over the iterable's elements indefinitely. - * For example, ([1, 2, 3]) would return : 1, 2, 3, 1, 2, 3, ... - * @see: http://docs.python.org/library/itertools.html#itertools.cycle. - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterable object. - * @return {!goog.iter.Iterator<VALUE>} An iterator that iterates indefinitely - * over the values in {@code iterable}. - * @template VALUE - */ -goog.iter.cycle = function(iterable) { - var baseIterator = goog.iter.toIterator(iterable); - - // We maintain a cache to store the iterable elements as we iterate - // over them. The cache is used to return elements once we have - // iterated over the iterable once. - var cache = []; - var cacheIndex = 0; - - var iter = new goog.iter.Iterator(); - - // This flag is set after the iterable is iterated over once - var useCache = false; - - iter.next = function() { - var returnElement = null; - - // Pull elements off the original iterator if not using cache - if (!useCache) { - try { - // Return the element from the iterable - returnElement = baseIterator.next(); - cache.push(returnElement); - return returnElement; - } catch (e) { - // If an exception other than StopIteration is thrown - // or if there are no elements to iterate over (the iterable was empty) - // throw an exception - if (e != goog.iter.StopIteration || goog.array.isEmpty(cache)) { - throw e; - } - // set useCache to true after we know that a 'StopIteration' exception - // was thrown and the cache is not empty (to handle the 'empty iterable' - // use case) - useCache = true; - } - } - - returnElement = cache[cacheIndex]; - cacheIndex = (cacheIndex + 1) % cache.length; - - return returnElement; - }; - - return iter; -}; - - -/** - * Creates an iterator that counts indefinitely from a starting value. - * @see http://docs.python.org/2/library/itertools.html#itertools.count - * @param {number=} opt_start The starting value. Default is 0. - * @param {number=} opt_step The number to increment with between each call to - * next. Negative and floating point numbers are allowed. Default is 1. - * @return {!goog.iter.Iterator<number>} A new iterator that returns the values - * in the series. - */ -goog.iter.count = function(opt_start, opt_step) { - var counter = opt_start || 0; - var step = goog.isDef(opt_step) ? opt_step : 1; - var iter = new goog.iter.Iterator(); - - iter.next = function() { - var returnValue = counter; - counter += step; - return returnValue; - }; - - return iter; -}; - - -/** - * Creates an iterator that returns the same object or value repeatedly. - * @param {VALUE} value Any object or value to repeat. - * @return {!goog.iter.Iterator<VALUE>} A new iterator that returns the - * repeated value. - * @template VALUE - */ -goog.iter.repeat = function(value) { - var iter = new goog.iter.Iterator(); - - iter.next = goog.functions.constant(value); - - return iter; -}; - - -/** - * Creates an iterator that returns running totals from the numbers in - * {@code iterable}. For example, the array {@code [1, 2, 3, 4, 5]} yields - * {@code 1 -> 3 -> 6 -> 10 -> 15}. - * @see http://docs.python.org/3.2/library/itertools.html#itertools.accumulate - * @param {!goog.iter.Iterable} iterable The iterable of numbers to - * accumulate. - * @return {!goog.iter.Iterator<number>} A new iterator that returns the - * numbers in the series. - */ -goog.iter.accumulate = function(iterable) { - var iterator = goog.iter.toIterator(iterable); - var total = 0; - var iter = new goog.iter.Iterator(); - - iter.next = function() { - total += iterator.next(); - return total; - }; - - return iter; -}; - - -/** - * Creates an iterator that returns arrays containing the ith elements from the - * provided iterables. The returned arrays will be the same size as the number - * of iterables given in {@code var_args}. Once the shortest iterable is - * exhausted, subsequent calls to {@code next()} will throw - * {@code goog.iter.StopIteration}. - * @see http://docs.python.org/2/library/itertools.html#itertools.izip - * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any - * number of iterable objects. - * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator that returns - * arrays of elements from the provided iterables. - * @template VALUE - */ -goog.iter.zip = function(var_args) { - var args = arguments; - var iter = new goog.iter.Iterator(); - - if (args.length > 0) { - var iterators = goog.array.map(args, goog.iter.toIterator); - iter.next = function() { - var arr = goog.array.map(iterators, function(it) { return it.next(); }); - return arr; - }; - } - - return iter; -}; - - -/** - * Creates an iterator that returns arrays containing the ith elements from the - * provided iterables. The returned arrays will be the same size as the number - * of iterables given in {@code var_args}. Shorter iterables will be extended - * with {@code fillValue}. Once the longest iterable is exhausted, subsequent - * calls to {@code next()} will throw {@code goog.iter.StopIteration}. - * @see http://docs.python.org/2/library/itertools.html#itertools.izip_longest - * @param {VALUE} fillValue The object or value used to fill shorter iterables. - * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any - * number of iterable objects. - * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator that returns - * arrays of elements from the provided iterables. - * @template VALUE - */ -goog.iter.zipLongest = function(fillValue, var_args) { - var args = goog.array.slice(arguments, 1); - var iter = new goog.iter.Iterator(); - - if (args.length > 0) { - var iterators = goog.array.map(args, goog.iter.toIterator); - - iter.next = function() { - var iteratorsHaveValues = false; // false when all iterators are empty. - var arr = goog.array.map(iterators, function(it) { - var returnValue; - try { - returnValue = it.next(); - // Iterator had a value, so we've not exhausted the iterators. - // Set flag accordingly. - iteratorsHaveValues = true; - } catch (ex) { - if (ex !== goog.iter.StopIteration) { - throw ex; - } - returnValue = fillValue; - } - return returnValue; - }); - - if (!iteratorsHaveValues) { - throw goog.iter.StopIteration; - } - return arr; - }; - } - - return iter; -}; - - -/** - * Creates an iterator that filters {@code iterable} based on a series of - * {@code selectors}. On each call to {@code next()}, one item is taken from - * both the {@code iterable} and {@code selectors} iterators. If the item from - * {@code selectors} evaluates to true, the item from {@code iterable} is given. - * Otherwise, it is skipped. Once either {@code iterable} or {@code selectors} - * is exhausted, subsequent calls to {@code next()} will throw - * {@code goog.iter.StopIteration}. - * @see http://docs.python.org/2/library/itertools.html#itertools.compress - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterable to filter. - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} selectors An - * iterable of items to be evaluated in a boolean context to determine if - * the corresponding element in {@code iterable} should be included in the - * result. - * @return {!goog.iter.Iterator<VALUE>} A new iterator that returns the - * filtered values. - * @template VALUE - */ -goog.iter.compress = function(iterable, selectors) { - var selectorIterator = goog.iter.toIterator(selectors); - - return goog.iter.filter( - iterable, function() { return !!selectorIterator.next(); }); -}; - - - -/** - * Implements the {@code goog.iter.groupBy} iterator. - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterable to group. - * @param {function(VALUE): KEY=} opt_keyFunc Optional function for - * determining the key value for each group in the {@code iterable}. Default - * is the identity function. - * @constructor - * @extends {goog.iter.Iterator<!Array<?>>} - * @template KEY, VALUE - * @private - */ -goog.iter.GroupByIterator_ = function(iterable, opt_keyFunc) { - - /** - * The iterable to group, coerced to an iterator. - * @type {!goog.iter.Iterator} - */ - this.iterator = goog.iter.toIterator(iterable); - - /** - * A function for determining the key value for each element in the iterable. - * If no function is provided, the identity function is used and returns the - * element unchanged. - * @type {function(VALUE): KEY} - */ - this.keyFunc = opt_keyFunc || goog.functions.identity; - - /** - * The target key for determining the start of a group. - * @type {KEY} - */ - this.targetKey; - - /** - * The current key visited during iteration. - * @type {KEY} - */ - this.currentKey; - - /** - * The current value being added to the group. - * @type {VALUE} - */ - this.currentValue; -}; -goog.inherits(goog.iter.GroupByIterator_, goog.iter.Iterator); - - -/** @override */ -goog.iter.GroupByIterator_.prototype.next = function() { - while (this.currentKey == this.targetKey) { - this.currentValue = this.iterator.next(); // Exits on StopIteration - this.currentKey = this.keyFunc(this.currentValue); - } - this.targetKey = this.currentKey; - return [this.currentKey, this.groupItems_(this.targetKey)]; -}; - - -/** - * Performs the grouping of objects using the given key. - * @param {KEY} targetKey The target key object for the group. - * @return {!Array<VALUE>} An array of grouped objects. - * @private - */ -goog.iter.GroupByIterator_.prototype.groupItems_ = function(targetKey) { - var arr = []; - while (this.currentKey == targetKey) { - arr.push(this.currentValue); - try { - this.currentValue = this.iterator.next(); - } catch (ex) { - if (ex !== goog.iter.StopIteration) { - throw ex; - } - break; - } - this.currentKey = this.keyFunc(this.currentValue); - } - return arr; -}; - - -/** - * Creates an iterator that returns arrays containing elements from the - * {@code iterable} grouped by a key value. For iterables with repeated - * elements (i.e. sorted according to a particular key function), this function - * has a {@code uniq}-like effect. For example, grouping the array: - * {@code [A, B, B, C, C, A]} produces - * {@code [A, [A]], [B, [B, B]], [C, [C, C]], [A, [A]]}. - * @see http://docs.python.org/2/library/itertools.html#itertools.groupby - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterable to group. - * @param {function(VALUE): KEY=} opt_keyFunc Optional function for - * determining the key value for each group in the {@code iterable}. Default - * is the identity function. - * @return {!goog.iter.Iterator<!Array<?>>} A new iterator that returns - * arrays of consecutive key and groups. - * @template KEY, VALUE - */ -goog.iter.groupBy = function(iterable, opt_keyFunc) { - return new goog.iter.GroupByIterator_(iterable, opt_keyFunc); -}; - - -/** - * Gives an iterator that gives the result of calling the given function - * <code>f</code> with the arguments taken from the next element from - * <code>iterable</code> (the elements are expected to also be iterables). - * - * Similar to {@see goog.iter#map} but allows the function to accept multiple - * arguments from the iterable. - * - * @param {!goog.iter.Iterable} iterable The iterable of - * iterables to iterate over. - * @param {function(this:THIS,...*):RESULT} f The function to call for every - * element. This function takes N+2 arguments, where N represents the - * number of items from the next element of the iterable. The two - * additional arguments passed to the function are undefined and the - * iterator itself. The function should return a new value. - * @param {THIS=} opt_obj The object to be used as the value of 'this' within - * {@code f}. - * @return {!goog.iter.Iterator<RESULT>} A new iterator that returns the - * results of applying the function to each element in the original - * iterator. - * @template THIS, RESULT - */ -goog.iter.starMap = function(iterable, f, opt_obj) { - var iterator = goog.iter.toIterator(iterable); - var iter = new goog.iter.Iterator(); - - iter.next = function() { - var args = goog.iter.toArray(iterator.next()); - return f.apply(opt_obj, goog.array.concat(args, undefined, iterator)); - }; - - return iter; -}; - - -/** - * Returns an array of iterators each of which can iterate over the values in - * {@code iterable} without advancing the others. - * @see http://docs.python.org/2/library/itertools.html#itertools.tee - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterable to tee. - * @param {number=} opt_num The number of iterators to create. Default is 2. - * @return {!Array<goog.iter.Iterator<VALUE>>} An array of iterators. - * @template VALUE - */ -goog.iter.tee = function(iterable, opt_num) { - var iterator = goog.iter.toIterator(iterable); - var num = goog.isNumber(opt_num) ? opt_num : 2; - var buffers = - goog.array.map(goog.array.range(num), function() { return []; }); - - var addNextIteratorValueToBuffers = function() { - var val = iterator.next(); - goog.array.forEach(buffers, function(buffer) { buffer.push(val); }); - }; - - var createIterator = function(buffer) { - // Each tee'd iterator has an associated buffer (initially empty). When a - // tee'd iterator's buffer is empty, it calls - // addNextIteratorValueToBuffers(), adding the next value to all tee'd - // iterators' buffers, and then returns that value. This allows each - // iterator to be advanced independently. - var iter = new goog.iter.Iterator(); - - iter.next = function() { - if (goog.array.isEmpty(buffer)) { - addNextIteratorValueToBuffers(); - } - goog.asserts.assert(!goog.array.isEmpty(buffer)); - return buffer.shift(); - }; - - return iter; - }; - - return goog.array.map(buffers, createIterator); -}; - - -/** - * Creates an iterator that returns arrays containing a count and an element - * obtained from the given {@code iterable}. - * @see http://docs.python.org/2/library/functions.html#enumerate - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterable to enumerate. - * @param {number=} opt_start Optional starting value. Default is 0. - * @return {!goog.iter.Iterator<!Array<?>>} A new iterator containing - * count/item pairs. - * @template VALUE - */ -goog.iter.enumerate = function(iterable, opt_start) { - return goog.iter.zip(goog.iter.count(opt_start), iterable); -}; - - -/** - * Creates an iterator that returns the first {@code limitSize} elements from an - * iterable. If this number is greater than the number of elements in the - * iterable, all the elements are returned. - * @see http://goo.gl/V0sihp Inspired by the limit iterator in Guava. - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterable to limit. - * @param {number} limitSize The maximum number of elements to return. - * @return {!goog.iter.Iterator<VALUE>} A new iterator containing - * {@code limitSize} elements. - * @template VALUE - */ -goog.iter.limit = function(iterable, limitSize) { - goog.asserts.assert(goog.math.isInt(limitSize) && limitSize >= 0); - - var iterator = goog.iter.toIterator(iterable); - - var iter = new goog.iter.Iterator(); - var remaining = limitSize; - - iter.next = function() { - if (remaining-- > 0) { - return iterator.next(); - } - throw goog.iter.StopIteration; - }; - - return iter; -}; - - -/** - * Creates an iterator that is advanced {@code count} steps ahead. Consumed - * values are silently discarded. If {@code count} is greater than the number - * of elements in {@code iterable}, an empty iterator is returned. Subsequent - * calls to {@code next()} will throw {@code goog.iter.StopIteration}. - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterable to consume. - * @param {number} count The number of elements to consume from the iterator. - * @return {!goog.iter.Iterator<VALUE>} An iterator advanced zero or more steps - * ahead. - * @template VALUE - */ -goog.iter.consume = function(iterable, count) { - goog.asserts.assert(goog.math.isInt(count) && count >= 0); - - var iterator = goog.iter.toIterator(iterable); - - while (count-- > 0) { - goog.iter.nextOrValue(iterator, null); - } - - return iterator; -}; - - -/** - * Creates an iterator that returns a range of elements from an iterable. - * Similar to {@see goog.array#slice} but does not support negative indexes. - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterable to slice. - * @param {number} start The index of the first element to return. - * @param {number=} opt_end The index after the last element to return. If - * defined, must be greater than or equal to {@code start}. - * @return {!goog.iter.Iterator<VALUE>} A new iterator containing a slice of - * the original. - * @template VALUE - */ -goog.iter.slice = function(iterable, start, opt_end) { - goog.asserts.assert(goog.math.isInt(start) && start >= 0); - - var iterator = goog.iter.consume(iterable, start); - - if (goog.isNumber(opt_end)) { - goog.asserts.assert(goog.math.isInt(opt_end) && opt_end >= start); - iterator = goog.iter.limit(iterator, opt_end - start /* limitSize */); - } - - return iterator; -}; - - -/** - * Checks an array for duplicate elements. - * @param {?IArrayLike<VALUE>} arr The array to check for - * duplicates. - * @return {boolean} True, if the array contains duplicates, false otherwise. - * @private - * @template VALUE - */ -// TODO(dlindquist): Consider moving this into goog.array as a public function. -goog.iter.hasDuplicates_ = function(arr) { - var deduped = []; - goog.array.removeDuplicates(arr, deduped); - return arr.length != deduped.length; -}; - - -/** - * Creates an iterator that returns permutations of elements in - * {@code iterable}. - * - * Permutations are obtained by taking the Cartesian product of - * {@code opt_length} iterables and filtering out those with repeated - * elements. For example, the permutations of {@code [1,2,3]} are - * {@code [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]}. - * @see http://docs.python.org/2/library/itertools.html#itertools.permutations - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterable from which to generate permutations. - * @param {number=} opt_length Length of each permutation. If omitted, defaults - * to the length of {@code iterable}. - * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing the - * permutations of {@code iterable}. - * @template VALUE - */ -goog.iter.permutations = function(iterable, opt_length) { - var elements = goog.iter.toArray(iterable); - var length = goog.isNumber(opt_length) ? opt_length : elements.length; - - var sets = goog.array.repeat(elements, length); - var product = goog.iter.product.apply(undefined, sets); - - return goog.iter.filter( - product, function(arr) { return !goog.iter.hasDuplicates_(arr); }); -}; - - -/** - * Creates an iterator that returns combinations of elements from - * {@code iterable}. - * - * Combinations are obtained by taking the {@see goog.iter#permutations} of - * {@code iterable} and filtering those whose elements appear in the order they - * are encountered in {@code iterable}. For example, the 3-length combinations - * of {@code [0,1,2,3]} are {@code [[0,1,2], [0,1,3], [0,2,3], [1,2,3]]}. - * @see http://docs.python.org/2/library/itertools.html#itertools.combinations - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterable from which to generate combinations. - * @param {number} length The length of each combination. - * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing - * combinations from the {@code iterable}. - * @template VALUE - */ -goog.iter.combinations = function(iterable, length) { - var elements = goog.iter.toArray(iterable); - var indexes = goog.iter.range(elements.length); - var indexIterator = goog.iter.permutations(indexes, length); - // sortedIndexIterator will now give arrays of with the given length that - // indicate what indexes into "elements" should be returned on each iteration. - var sortedIndexIterator = goog.iter.filter( - indexIterator, function(arr) { return goog.array.isSorted(arr); }); - - var iter = new goog.iter.Iterator(); - - function getIndexFromElements(index) { return elements[index]; } - - iter.next = function() { - return goog.array.map(sortedIndexIterator.next(), getIndexFromElements); - }; - - return iter; -}; - - -/** - * Creates an iterator that returns combinations of elements from - * {@code iterable}, with repeated elements possible. - * - * Combinations are obtained by taking the Cartesian product of {@code length} - * iterables and filtering those whose elements appear in the order they are - * encountered in {@code iterable}. For example, the 2-length combinations of - * {@code [1,2,3]} are {@code [[1,1], [1,2], [1,3], [2,2], [2,3], [3,3]]}. - * @see https://goo.gl/C0yXe4 - * @see https://goo.gl/djOCsk - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The - * iterable to combine. - * @param {number} length The length of each combination. - * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing - * combinations from the {@code iterable}. - * @template VALUE - */ -goog.iter.combinationsWithReplacement = function(iterable, length) { - var elements = goog.iter.toArray(iterable); - var indexes = goog.array.range(elements.length); - var sets = goog.array.repeat(indexes, length); - var indexIterator = goog.iter.product.apply(undefined, sets); - // sortedIndexIterator will now give arrays of with the given length that - // indicate what indexes into "elements" should be returned on each iteration. - var sortedIndexIterator = goog.iter.filter( - indexIterator, function(arr) { return goog.array.isSorted(arr); }); - - var iter = new goog.iter.Iterator(); - - function getIndexFromElements(index) { return elements[index]; } - - iter.next = function() { - return goog.array.map( - /** @type {!Array<number>} */ - (sortedIndexIterator.next()), getIndexFromElements); - }; - - return iter; -};
diff --git a/third_party/ink/closure/labs/useragent/browser.js b/third_party/ink/closure/labs/useragent/browser.js deleted file mode 100644 index 78578e4..0000000 --- a/third_party/ink/closure/labs/useragent/browser.js +++ /dev/null
@@ -1,339 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Closure user agent detection (Browser). - * @see <a href="http://www.useragentstring.com/">User agent strings</a> - * For more information on rendering engine, platform, or device see the other - * sub-namespaces in goog.labs.userAgent, goog.labs.userAgent.platform, - * goog.labs.userAgent.device respectively.) - * - * @author vbhasin@google.com (Vipul Bhasin) - * @author martone@google.com (Andy Martone) - */ - -goog.provide('goog.labs.userAgent.browser'); - -goog.require('goog.array'); -goog.require('goog.labs.userAgent.util'); -goog.require('goog.object'); -goog.require('goog.string'); - - -// TODO(nnaze): Refactor to remove excessive exclusion logic in matching -// functions. - - -/** - * @return {boolean} Whether the user's browser is Opera. Note: Chromium - * based Opera (Opera 15+) is detected as Chrome to avoid unnecessary - * special casing. - * @private - */ -goog.labs.userAgent.browser.matchOpera_ = function() { - return goog.labs.userAgent.util.matchUserAgent('Opera'); -}; - - -/** - * @return {boolean} Whether the user's browser is IE. - * @private - */ -goog.labs.userAgent.browser.matchIE_ = function() { - return goog.labs.userAgent.util.matchUserAgent('Trident') || - goog.labs.userAgent.util.matchUserAgent('MSIE'); -}; - - -/** - * @return {boolean} Whether the user's browser is Edge. - * @private - */ -goog.labs.userAgent.browser.matchEdge_ = function() { - return goog.labs.userAgent.util.matchUserAgent('Edge'); -}; - - -/** - * @return {boolean} Whether the user's browser is Firefox. - * @private - */ -goog.labs.userAgent.browser.matchFirefox_ = function() { - return goog.labs.userAgent.util.matchUserAgent('Firefox'); -}; - - -/** - * @return {boolean} Whether the user's browser is Safari. - * @private - */ -goog.labs.userAgent.browser.matchSafari_ = function() { - return goog.labs.userAgent.util.matchUserAgent('Safari') && - !(goog.labs.userAgent.browser.matchChrome_() || - goog.labs.userAgent.browser.matchCoast_() || - goog.labs.userAgent.browser.matchOpera_() || - goog.labs.userAgent.browser.matchEdge_() || - goog.labs.userAgent.browser.isSilk() || - goog.labs.userAgent.util.matchUserAgent('Android')); -}; - - -/** - * @return {boolean} Whether the user's browser is Coast (Opera's Webkit-based - * iOS browser). - * @private - */ -goog.labs.userAgent.browser.matchCoast_ = function() { - return goog.labs.userAgent.util.matchUserAgent('Coast'); -}; - - -/** - * @return {boolean} Whether the user's browser is iOS Webview. - * @private - */ -goog.labs.userAgent.browser.matchIosWebview_ = function() { - // iOS Webview does not show up as Chrome or Safari. Also check for Opera's - // WebKit-based iOS browser, Coast. - return (goog.labs.userAgent.util.matchUserAgent('iPad') || - goog.labs.userAgent.util.matchUserAgent('iPhone')) && - !goog.labs.userAgent.browser.matchSafari_() && - !goog.labs.userAgent.browser.matchChrome_() && - !goog.labs.userAgent.browser.matchCoast_() && - goog.labs.userAgent.util.matchUserAgent('AppleWebKit'); -}; - - -/** - * @return {boolean} Whether the user's browser is Chrome. - * @private - */ -goog.labs.userAgent.browser.matchChrome_ = function() { - return (goog.labs.userAgent.util.matchUserAgent('Chrome') || - goog.labs.userAgent.util.matchUserAgent('CriOS')) && - !goog.labs.userAgent.browser.matchEdge_(); -}; - - -/** - * @return {boolean} Whether the user's browser is the Android browser. - * @private - */ -goog.labs.userAgent.browser.matchAndroidBrowser_ = function() { - // Android can appear in the user agent string for Chrome on Android. - // This is not the Android standalone browser if it does. - return goog.labs.userAgent.util.matchUserAgent('Android') && - !(goog.labs.userAgent.browser.isChrome() || - goog.labs.userAgent.browser.isFirefox() || - goog.labs.userAgent.browser.isOpera() || - goog.labs.userAgent.browser.isSilk()); -}; - - -/** - * @return {boolean} Whether the user's browser is Opera. - */ -goog.labs.userAgent.browser.isOpera = goog.labs.userAgent.browser.matchOpera_; - - -/** - * @return {boolean} Whether the user's browser is IE. - */ -goog.labs.userAgent.browser.isIE = goog.labs.userAgent.browser.matchIE_; - - -/** - * @return {boolean} Whether the user's browser is Edge. - */ -goog.labs.userAgent.browser.isEdge = goog.labs.userAgent.browser.matchEdge_; - - -/** - * @return {boolean} Whether the user's browser is Firefox. - */ -goog.labs.userAgent.browser.isFirefox = - goog.labs.userAgent.browser.matchFirefox_; - - -/** - * @return {boolean} Whether the user's browser is Safari. - */ -goog.labs.userAgent.browser.isSafari = goog.labs.userAgent.browser.matchSafari_; - - -/** - * @return {boolean} Whether the user's browser is Coast (Opera's Webkit-based - * iOS browser). - */ -goog.labs.userAgent.browser.isCoast = goog.labs.userAgent.browser.matchCoast_; - - -/** - * @return {boolean} Whether the user's browser is iOS Webview. - */ -goog.labs.userAgent.browser.isIosWebview = - goog.labs.userAgent.browser.matchIosWebview_; - - -/** - * @return {boolean} Whether the user's browser is Chrome. - */ -goog.labs.userAgent.browser.isChrome = goog.labs.userAgent.browser.matchChrome_; - - -/** - * @return {boolean} Whether the user's browser is the Android browser. - */ -goog.labs.userAgent.browser.isAndroidBrowser = - goog.labs.userAgent.browser.matchAndroidBrowser_; - - -/** - * For more information, see: - * http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html - * @return {boolean} Whether the user's browser is Silk. - */ -goog.labs.userAgent.browser.isSilk = function() { - return goog.labs.userAgent.util.matchUserAgent('Silk'); -}; - - -/** - * @return {string} The browser version or empty string if version cannot be - * determined. Note that for Internet Explorer, this returns the version of - * the browser, not the version of the rendering engine. (IE 8 in - * compatibility mode will return 8.0 rather than 7.0. To determine the - * rendering engine version, look at document.documentMode instead. See - * http://msdn.microsoft.com/en-us/library/cc196988(v=vs.85).aspx for more - * details.) - */ -goog.labs.userAgent.browser.getVersion = function() { - var userAgentString = goog.labs.userAgent.util.getUserAgent(); - // Special case IE since IE's version is inside the parenthesis and - // without the '/'. - if (goog.labs.userAgent.browser.isIE()) { - return goog.labs.userAgent.browser.getIEVersion_(userAgentString); - } - - var versionTuples = - goog.labs.userAgent.util.extractVersionTuples(userAgentString); - - // Construct a map for easy lookup. - var versionMap = {}; - goog.array.forEach(versionTuples, function(tuple) { - // Note that the tuple is of length three, but we only care about the - // first two. - var key = tuple[0]; - var value = tuple[1]; - versionMap[key] = value; - }); - - var versionMapHasKey = goog.partial(goog.object.containsKey, versionMap); - - // Gives the value with the first key it finds, otherwise empty string. - function lookUpValueWithKeys(keys) { - var key = goog.array.find(keys, versionMapHasKey); - return versionMap[key] || ''; - } - - // Check Opera before Chrome since Opera 15+ has "Chrome" in the string. - // See - // http://my.opera.com/ODIN/blog/2013/07/15/opera-user-agent-strings-opera-15-and-beyond - if (goog.labs.userAgent.browser.isOpera()) { - // Opera 10 has Version/10.0 but Opera/9.8, so look for "Version" first. - // Opera uses 'OPR' for more recent UAs. - return lookUpValueWithKeys(['Version', 'Opera']); - } - - // Check Edge before Chrome since it has Chrome in the string. - if (goog.labs.userAgent.browser.isEdge()) { - return lookUpValueWithKeys(['Edge']); - } - - if (goog.labs.userAgent.browser.isChrome()) { - return lookUpValueWithKeys(['Chrome', 'CriOS']); - } - - // Usually products browser versions are in the third tuple after "Mozilla" - // and the engine. - var tuple = versionTuples[2]; - return tuple && tuple[1] || ''; -}; - - -/** - * @param {string|number} version The version to check. - * @return {boolean} Whether the browser version is higher or the same as the - * given version. - */ -goog.labs.userAgent.browser.isVersionOrHigher = function(version) { - return goog.string.compareVersions( - goog.labs.userAgent.browser.getVersion(), version) >= 0; -}; - - -/** - * Determines IE version. More information: - * http://msdn.microsoft.com/en-us/library/ie/bg182625(v=vs.85).aspx#uaString - * http://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx - * http://blogs.msdn.com/b/ie/archive/2010/03/23/introducing-ie9-s-user-agent-string.aspx - * http://blogs.msdn.com/b/ie/archive/2009/01/09/the-internet-explorer-8-user-agent-string-updated-edition.aspx - * - * @param {string} userAgent the User-Agent. - * @return {string} - * @private - */ -goog.labs.userAgent.browser.getIEVersion_ = function(userAgent) { - // IE11 may identify itself as MSIE 9.0 or MSIE 10.0 due to an IE 11 upgrade - // bug. Example UA: - // Mozilla/5.0 (MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) - // like Gecko. - // See http://www.whatismybrowser.com/developers/unknown-user-agent-fragments. - var rv = /rv: *([\d\.]*)/.exec(userAgent); - if (rv && rv[1]) { - return rv[1]; - } - - var version = ''; - var msie = /MSIE +([\d\.]+)/.exec(userAgent); - if (msie && msie[1]) { - // IE in compatibility mode usually identifies itself as MSIE 7.0; in this - // case, use the Trident version to determine the version of IE. For more - // details, see the links above. - var tridentVersion = /Trident\/(\d.\d)/.exec(userAgent); - if (msie[1] == '7.0') { - if (tridentVersion && tridentVersion[1]) { - switch (tridentVersion[1]) { - case '4.0': - version = '8.0'; - break; - case '5.0': - version = '9.0'; - break; - case '6.0': - version = '10.0'; - break; - case '7.0': - version = '11.0'; - break; - } - } else { - version = '7.0'; - } - } else { - version = msie[1]; - } - } - return version; -};
diff --git a/third_party/ink/closure/labs/useragent/engine.js b/third_party/ink/closure/labs/useragent/engine.js deleted file mode 100644 index 4de0ff33..0000000 --- a/third_party/ink/closure/labs/useragent/engine.js +++ /dev/null
@@ -1,157 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Closure user agent detection. - * @see http://en.wikipedia.org/wiki/User_agent - * For more information on browser brand, platform, or device see the other - * sub-namespaces in goog.labs.userAgent (browser, platform, and device). - * - * @author vbhasin@google.com (Vipul Bhasin) - */ - -goog.provide('goog.labs.userAgent.engine'); - -goog.require('goog.array'); -goog.require('goog.labs.userAgent.util'); -goog.require('goog.string'); - - -/** - * @return {boolean} Whether the rendering engine is Presto. - */ -goog.labs.userAgent.engine.isPresto = function() { - return goog.labs.userAgent.util.matchUserAgent('Presto'); -}; - - -/** - * @return {boolean} Whether the rendering engine is Trident. - */ -goog.labs.userAgent.engine.isTrident = function() { - // IE only started including the Trident token in IE8. - return goog.labs.userAgent.util.matchUserAgent('Trident') || - goog.labs.userAgent.util.matchUserAgent('MSIE'); -}; - - -/** - * @return {boolean} Whether the rendering engine is Edge. - */ -goog.labs.userAgent.engine.isEdge = function() { - return goog.labs.userAgent.util.matchUserAgent('Edge'); -}; - - -/** - * @return {boolean} Whether the rendering engine is WebKit. - */ -goog.labs.userAgent.engine.isWebKit = function() { - return goog.labs.userAgent.util.matchUserAgentIgnoreCase('WebKit') && - !goog.labs.userAgent.engine.isEdge(); -}; - - -/** - * @return {boolean} Whether the rendering engine is Gecko. - */ -goog.labs.userAgent.engine.isGecko = function() { - return goog.labs.userAgent.util.matchUserAgent('Gecko') && - !goog.labs.userAgent.engine.isWebKit() && - !goog.labs.userAgent.engine.isTrident() && - !goog.labs.userAgent.engine.isEdge(); -}; - - -/** - * @return {string} The rendering engine's version or empty string if version - * can't be determined. - */ -goog.labs.userAgent.engine.getVersion = function() { - var userAgentString = goog.labs.userAgent.util.getUserAgent(); - if (userAgentString) { - var tuples = goog.labs.userAgent.util.extractVersionTuples(userAgentString); - - var engineTuple = goog.labs.userAgent.engine.getEngineTuple_(tuples); - if (engineTuple) { - // In Gecko, the version string is either in the browser info or the - // Firefox version. See Gecko user agent string reference: - // http://goo.gl/mULqa - if (engineTuple[0] == 'Gecko') { - return goog.labs.userAgent.engine.getVersionForKey_(tuples, 'Firefox'); - } - - return engineTuple[1]; - } - - // MSIE has only one version identifier, and the Trident version is - // specified in the parenthetical. IE Edge is covered in the engine tuple - // detection. - var browserTuple = tuples[0]; - var info; - if (browserTuple && (info = browserTuple[2])) { - var match = /Trident\/([^\s;]+)/.exec(info); - if (match) { - return match[1]; - } - } - } - return ''; -}; - - -/** - * @param {!Array<!Array<string>>} tuples Extracted version tuples. - * @return {!Array<string>|undefined} The engine tuple or undefined if not - * found. - * @private - */ -goog.labs.userAgent.engine.getEngineTuple_ = function(tuples) { - if (!goog.labs.userAgent.engine.isEdge()) { - return tuples[1]; - } - for (var i = 0; i < tuples.length; i++) { - var tuple = tuples[i]; - if (tuple[0] == 'Edge') { - return tuple; - } - } -}; - - -/** - * @param {string|number} version The version to check. - * @return {boolean} Whether the rendering engine version is higher or the same - * as the given version. - */ -goog.labs.userAgent.engine.isVersionOrHigher = function(version) { - return goog.string.compareVersions( - goog.labs.userAgent.engine.getVersion(), version) >= 0; -}; - - -/** - * @param {!Array<!Array<string>>} tuples Version tuples. - * @param {string} key The key to look for. - * @return {string} The version string of the given key, if present. - * Otherwise, the empty string. - * @private - */ -goog.labs.userAgent.engine.getVersionForKey_ = function(tuples, key) { - // TODO(nnaze): Move to util if useful elsewhere. - - var pair = goog.array.find(tuples, function(pair) { return key == pair[0]; }); - - return pair && pair[1] || ''; -};
diff --git a/third_party/ink/closure/labs/useragent/platform.js b/third_party/ink/closure/labs/useragent/platform.js deleted file mode 100644 index d5c3537..0000000 --- a/third_party/ink/closure/labs/useragent/platform.js +++ /dev/null
@@ -1,161 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Closure user agent platform detection. - * @see <a href="http://www.useragentstring.com/">User agent strings</a> - * For more information on browser brand, rendering engine, or device see the - * other sub-namespaces in goog.labs.userAgent (browser, engine, and device - * respectively). - * - * @author vbhasin@google.com (Vipul Bhasin) - */ - -goog.provide('goog.labs.userAgent.platform'); - -goog.require('goog.labs.userAgent.util'); -goog.require('goog.string'); - - -/** - * @return {boolean} Whether the platform is Android. - */ -goog.labs.userAgent.platform.isAndroid = function() { - return goog.labs.userAgent.util.matchUserAgent('Android'); -}; - - -/** - * @return {boolean} Whether the platform is iPod. - */ -goog.labs.userAgent.platform.isIpod = function() { - return goog.labs.userAgent.util.matchUserAgent('iPod'); -}; - - -/** - * @return {boolean} Whether the platform is iPhone. - */ -goog.labs.userAgent.platform.isIphone = function() { - return goog.labs.userAgent.util.matchUserAgent('iPhone') && - !goog.labs.userAgent.util.matchUserAgent('iPod') && - !goog.labs.userAgent.util.matchUserAgent('iPad'); -}; - - -/** - * @return {boolean} Whether the platform is iPad. - */ -goog.labs.userAgent.platform.isIpad = function() { - return goog.labs.userAgent.util.matchUserAgent('iPad'); -}; - - -/** - * @return {boolean} Whether the platform is iOS. - */ -goog.labs.userAgent.platform.isIos = function() { - return goog.labs.userAgent.platform.isIphone() || - goog.labs.userAgent.platform.isIpad() || - goog.labs.userAgent.platform.isIpod(); -}; - - -/** - * @return {boolean} Whether the platform is Mac. - */ -goog.labs.userAgent.platform.isMacintosh = function() { - return goog.labs.userAgent.util.matchUserAgent('Macintosh'); -}; - - -/** - * Note: ChromeOS is not considered to be Linux as it does not report itself - * as Linux in the user agent string. - * @return {boolean} Whether the platform is Linux. - */ -goog.labs.userAgent.platform.isLinux = function() { - return goog.labs.userAgent.util.matchUserAgent('Linux'); -}; - - -/** - * @return {boolean} Whether the platform is Windows. - */ -goog.labs.userAgent.platform.isWindows = function() { - return goog.labs.userAgent.util.matchUserAgent('Windows'); -}; - - -/** - * @return {boolean} Whether the platform is ChromeOS. - */ -goog.labs.userAgent.platform.isChromeOS = function() { - return goog.labs.userAgent.util.matchUserAgent('CrOS'); -}; - - -/** - * The version of the platform. We only determine the version for Windows, - * Mac, and Chrome OS. It doesn't make much sense on Linux. For Windows, we only - * look at the NT version. Non-NT-based versions (e.g. 95, 98, etc.) are given - * version 0.0. - * - * @return {string} The platform version or empty string if version cannot be - * determined. - */ -goog.labs.userAgent.platform.getVersion = function() { - var userAgentString = goog.labs.userAgent.util.getUserAgent(); - var version = '', re; - if (goog.labs.userAgent.platform.isWindows()) { - re = /Windows (?:NT|Phone) ([0-9.]+)/; - var match = re.exec(userAgentString); - if (match) { - version = match[1]; - } else { - version = '0.0'; - } - } else if (goog.labs.userAgent.platform.isIos()) { - re = /(?:iPhone|iPod|iPad|CPU)\s+OS\s+(\S+)/; - var match = re.exec(userAgentString); - // Report the version as x.y.z and not x_y_z - version = match && match[1].replace(/_/g, '.'); - } else if (goog.labs.userAgent.platform.isMacintosh()) { - re = /Mac OS X ([0-9_.]+)/; - var match = re.exec(userAgentString); - // Note: some old versions of Camino do not report an OSX version. - // Default to 10. - version = match ? match[1].replace(/_/g, '.') : '10'; - } else if (goog.labs.userAgent.platform.isAndroid()) { - re = /Android\s+([^\);]+)(\)|;)/; - var match = re.exec(userAgentString); - version = match && match[1]; - } else if (goog.labs.userAgent.platform.isChromeOS()) { - re = /(?:CrOS\s+(?:i686|x86_64)\s+([0-9.]+))/; - var match = re.exec(userAgentString); - version = match && match[1]; - } - return version || ''; -}; - - -/** - * @param {string|number} version The version to check. - * @return {boolean} Whether the browser version is higher or the same as the - * given version. - */ -goog.labs.userAgent.platform.isVersionOrHigher = function(version) { - return goog.string.compareVersions( - goog.labs.userAgent.platform.getVersion(), version) >= 0; -};
diff --git a/third_party/ink/closure/labs/useragent/util.js b/third_party/ink/closure/labs/useragent/util.js deleted file mode 100644 index a57e5d8d..0000000 --- a/third_party/ink/closure/labs/useragent/util.js +++ /dev/null
@@ -1,157 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities used by goog.labs.userAgent tools. These functions - * should not be used outside of goog.labs.userAgent.*. - * - * MOE:begin_intracomment_strip - * @visibility {//javascript/abc/libs/objects3d:__subpackages__} - * @visibility {//javascript/closure/bin/sizetests:__pkg__} - * @visibility {//javascript/closure/dom:__subpackages__} - * @visibility {//javascript/closure/style:__pkg__} - * @visibility {//javascript/closure/testing:__pkg__} - * @visibility {//javascript/closure/useragent:__subpackages__} - * @visibility {//testing/puppet/modules:__pkg__} - * @visibility {:util_legacy_users} - * MOE:end_intracomment_strip - * - * @author nnaze@google.com (Nathan Naze) - */ - -goog.provide('goog.labs.userAgent.util'); - -goog.require('goog.string'); - - -/** - * Gets the native userAgent string from navigator if it exists. - * If navigator or navigator.userAgent string is missing, returns an empty - * string. - * @return {string} - * @private - */ -goog.labs.userAgent.util.getNativeUserAgentString_ = function() { - var navigator = goog.labs.userAgent.util.getNavigator_(); - if (navigator) { - var userAgent = navigator.userAgent; - if (userAgent) { - return userAgent; - } - } - return ''; -}; - - -/** - * Getter for the native navigator. - * This is a separate function so it can be stubbed out in testing. - * @return {Navigator} - * @private - */ -goog.labs.userAgent.util.getNavigator_ = function() { - return goog.global.navigator; -}; - - -/** - * A possible override for applications which wish to not check - * navigator.userAgent but use a specified value for detection instead. - * @private {string} - */ -goog.labs.userAgent.util.userAgent_ = - goog.labs.userAgent.util.getNativeUserAgentString_(); - - -/** - * Applications may override browser detection on the built in - * navigator.userAgent object by setting this string. Set to null to use the - * browser object instead. - * @param {?string=} opt_userAgent The User-Agent override. - */ -goog.labs.userAgent.util.setUserAgent = function(opt_userAgent) { - goog.labs.userAgent.util.userAgent_ = - opt_userAgent || goog.labs.userAgent.util.getNativeUserAgentString_(); -}; - - -/** - * @return {string} The user agent string. - */ -goog.labs.userAgent.util.getUserAgent = function() { - return goog.labs.userAgent.util.userAgent_; -}; - - -/** - * @param {string} str - * @return {boolean} Whether the user agent contains the given string. - */ -goog.labs.userAgent.util.matchUserAgent = function(str) { - var userAgent = goog.labs.userAgent.util.getUserAgent(); - return goog.string.contains(userAgent, str); -}; - - -/** - * @param {string} str - * @return {boolean} Whether the user agent contains the given string, ignoring - * case. - */ -goog.labs.userAgent.util.matchUserAgentIgnoreCase = function(str) { - var userAgent = goog.labs.userAgent.util.getUserAgent(); - return goog.string.caseInsensitiveContains(userAgent, str); -}; - - -/** - * Parses the user agent into tuples for each section. - * @param {string} userAgent - * @return {!Array<!Array<string>>} Tuples of key, version, and the contents - * of the parenthetical. - */ -goog.labs.userAgent.util.extractVersionTuples = function(userAgent) { - // Matches each section of a user agent string. - // Example UA: - // Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us) - // AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405 - // This has three version tuples: Mozilla, AppleWebKit, and Mobile. - - var versionRegExp = new RegExp( - // Key. Note that a key may have a space. - // (i.e. 'Mobile Safari' in 'Mobile Safari/5.0') - '(\\w[\\w ]+)' + - - '/' + // slash - '([^\\s]+)' + // version (i.e. '5.0b') - '\\s*' + // whitespace - '(?:\\((.*?)\\))?', // parenthetical info. parentheses not matched. - 'g'); - - var data = []; - var match; - - // Iterate and collect the version tuples. Each iteration will be the - // next regex match. - while (match = versionRegExp.exec(userAgent)) { - data.push([ - match[1], // key - match[2], // value - // || undefined as this is not undefined in IE7 and IE8 - match[3] || undefined // info - ]); - } - - return data; -};
diff --git a/third_party/ink/closure/math/box.js b/third_party/ink/closure/math/box.js deleted file mode 100644 index 108e6f7..0000000 --- a/third_party/ink/closure/math/box.js +++ /dev/null
@@ -1,403 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A utility class for representing a numeric box. - * @author pupius@google.com (Daniel Pupius) - */ - - -goog.provide('goog.math.Box'); - -goog.require('goog.asserts'); -goog.require('goog.math.Coordinate'); - - - -/** - * Class for representing a box. A box is specified as a top, right, bottom, - * and left. A box is useful for representing margins and padding. - * - * This class assumes 'screen coordinates': larger Y coordinates are further - * from the top of the screen. - * - * @param {number} top Top. - * @param {number} right Right. - * @param {number} bottom Bottom. - * @param {number} left Left. - * @struct - * @constructor - */ -goog.math.Box = function(top, right, bottom, left) { - /** - * Top - * @type {number} - */ - this.top = top; - - /** - * Right - * @type {number} - */ - this.right = right; - - /** - * Bottom - * @type {number} - */ - this.bottom = bottom; - - /** - * Left - * @type {number} - */ - this.left = left; -}; - - -/** - * Creates a Box by bounding a collection of goog.math.Coordinate objects - * @param {...goog.math.Coordinate} var_args Coordinates to be included inside - * the box. - * @return {!goog.math.Box} A Box containing all the specified Coordinates. - */ -goog.math.Box.boundingBox = function(var_args) { - var box = new goog.math.Box( - arguments[0].y, arguments[0].x, arguments[0].y, arguments[0].x); - for (var i = 1; i < arguments.length; i++) { - box.expandToIncludeCoordinate(arguments[i]); - } - return box; -}; - - -/** - * @return {number} width The width of this Box. - */ -goog.math.Box.prototype.getWidth = function() { - return this.right - this.left; -}; - - -/** - * @return {number} height The height of this Box. - */ -goog.math.Box.prototype.getHeight = function() { - return this.bottom - this.top; -}; - - -/** - * Creates a copy of the box with the same dimensions. - * @return {!goog.math.Box} A clone of this Box. - */ -goog.math.Box.prototype.clone = function() { - return new goog.math.Box(this.top, this.right, this.bottom, this.left); -}; - - -if (goog.DEBUG) { - /** - * Returns a nice string representing the box. - * @return {string} In the form (50t, 73r, 24b, 13l). - * @override - */ - goog.math.Box.prototype.toString = function() { - return '(' + this.top + 't, ' + this.right + 'r, ' + this.bottom + 'b, ' + - this.left + 'l)'; - }; -} - - -/** - * Returns whether the box contains a coordinate or another box. - * - * @param {goog.math.Coordinate|goog.math.Box} other A Coordinate or a Box. - * @return {boolean} Whether the box contains the coordinate or other box. - */ -goog.math.Box.prototype.contains = function(other) { - return goog.math.Box.contains(this, other); -}; - - -/** - * Expands box with the given margins. - * - * @param {number|goog.math.Box} top Top margin or box with all margins. - * @param {number=} opt_right Right margin. - * @param {number=} opt_bottom Bottom margin. - * @param {number=} opt_left Left margin. - * @return {!goog.math.Box} A reference to this Box. - */ -goog.math.Box.prototype.expand = function( - top, opt_right, opt_bottom, opt_left) { - if (goog.isObject(top)) { - this.top -= top.top; - this.right += top.right; - this.bottom += top.bottom; - this.left -= top.left; - } else { - this.top -= /** @type {number} */ (top); - this.right += Number(opt_right); - this.bottom += Number(opt_bottom); - this.left -= Number(opt_left); - } - - return this; -}; - - -/** - * Expand this box to include another box. - * NOTE(bcornell): This is used in code that needs to be very fast, please don't - * add functionality to this function at the expense of speed (variable - * arguments, accepting multiple argument types, etc). - * @param {goog.math.Box} box The box to include in this one. - */ -goog.math.Box.prototype.expandToInclude = function(box) { - this.left = Math.min(this.left, box.left); - this.top = Math.min(this.top, box.top); - this.right = Math.max(this.right, box.right); - this.bottom = Math.max(this.bottom, box.bottom); -}; - - -/** - * Expand this box to include the coordinate. - * @param {!goog.math.Coordinate} coord The coordinate to be included - * inside the box. - */ -goog.math.Box.prototype.expandToIncludeCoordinate = function(coord) { - this.top = Math.min(this.top, coord.y); - this.right = Math.max(this.right, coord.x); - this.bottom = Math.max(this.bottom, coord.y); - this.left = Math.min(this.left, coord.x); -}; - - -/** - * Compares boxes for equality. - * @param {goog.math.Box} a A Box. - * @param {goog.math.Box} b A Box. - * @return {boolean} True iff the boxes are equal, or if both are null. - */ -goog.math.Box.equals = function(a, b) { - if (a == b) { - return true; - } - if (!a || !b) { - return false; - } - return a.top == b.top && a.right == b.right && a.bottom == b.bottom && - a.left == b.left; -}; - - -/** - * Returns whether a box contains a coordinate or another box. - * - * @param {goog.math.Box} box A Box. - * @param {goog.math.Coordinate|goog.math.Box} other A Coordinate or a Box. - * @return {boolean} Whether the box contains the coordinate or other box. - */ -goog.math.Box.contains = function(box, other) { - if (!box || !other) { - return false; - } - - if (other instanceof goog.math.Box) { - return other.left >= box.left && other.right <= box.right && - other.top >= box.top && other.bottom <= box.bottom; - } - - // other is a Coordinate. - return other.x >= box.left && other.x <= box.right && other.y >= box.top && - other.y <= box.bottom; -}; - - -/** - * Returns the relative x position of a coordinate compared to a box. Returns - * zero if the coordinate is inside the box. - * - * @param {goog.math.Box} box A Box. - * @param {goog.math.Coordinate} coord A Coordinate. - * @return {number} The x position of {@code coord} relative to the nearest - * side of {@code box}, or zero if {@code coord} is inside {@code box}. - */ -goog.math.Box.relativePositionX = function(box, coord) { - if (coord.x < box.left) { - return coord.x - box.left; - } else if (coord.x > box.right) { - return coord.x - box.right; - } - return 0; -}; - - -/** - * Returns the relative y position of a coordinate compared to a box. Returns - * zero if the coordinate is inside the box. - * - * @param {goog.math.Box} box A Box. - * @param {goog.math.Coordinate} coord A Coordinate. - * @return {number} The y position of {@code coord} relative to the nearest - * side of {@code box}, or zero if {@code coord} is inside {@code box}. - */ -goog.math.Box.relativePositionY = function(box, coord) { - if (coord.y < box.top) { - return coord.y - box.top; - } else if (coord.y > box.bottom) { - return coord.y - box.bottom; - } - return 0; -}; - - -/** - * Returns the distance between a coordinate and the nearest corner/side of a - * box. Returns zero if the coordinate is inside the box. - * - * @param {goog.math.Box} box A Box. - * @param {goog.math.Coordinate} coord A Coordinate. - * @return {number} The distance between {@code coord} and the nearest - * corner/side of {@code box}, or zero if {@code coord} is inside - * {@code box}. - */ -goog.math.Box.distance = function(box, coord) { - var x = goog.math.Box.relativePositionX(box, coord); - var y = goog.math.Box.relativePositionY(box, coord); - return Math.sqrt(x * x + y * y); -}; - - -/** - * Returns whether two boxes intersect. - * - * @param {goog.math.Box} a A Box. - * @param {goog.math.Box} b A second Box. - * @return {boolean} Whether the boxes intersect. - */ -goog.math.Box.intersects = function(a, b) { - return ( - a.left <= b.right && b.left <= a.right && a.top <= b.bottom && - b.top <= a.bottom); -}; - - -/** - * Returns whether two boxes would intersect with additional padding. - * - * @param {goog.math.Box} a A Box. - * @param {goog.math.Box} b A second Box. - * @param {number} padding The additional padding. - * @return {boolean} Whether the boxes intersect. - */ -goog.math.Box.intersectsWithPadding = function(a, b, padding) { - return ( - a.left <= b.right + padding && b.left <= a.right + padding && - a.top <= b.bottom + padding && b.top <= a.bottom + padding); -}; - - -/** - * Rounds the fields to the next larger integer values. - * - * @return {!goog.math.Box} This box with ceil'd fields. - */ -goog.math.Box.prototype.ceil = function() { - this.top = Math.ceil(this.top); - this.right = Math.ceil(this.right); - this.bottom = Math.ceil(this.bottom); - this.left = Math.ceil(this.left); - return this; -}; - - -/** - * Rounds the fields to the next smaller integer values. - * - * @return {!goog.math.Box} This box with floored fields. - */ -goog.math.Box.prototype.floor = function() { - this.top = Math.floor(this.top); - this.right = Math.floor(this.right); - this.bottom = Math.floor(this.bottom); - this.left = Math.floor(this.left); - return this; -}; - - -/** - * Rounds the fields to nearest integer values. - * - * @return {!goog.math.Box} This box with rounded fields. - */ -goog.math.Box.prototype.round = function() { - this.top = Math.round(this.top); - this.right = Math.round(this.right); - this.bottom = Math.round(this.bottom); - this.left = Math.round(this.left); - return this; -}; - - -/** - * Translates this box by the given offsets. If a {@code goog.math.Coordinate} - * is given, then the left and right values are translated by the coordinate's - * x value and the top and bottom values are translated by the coordinate's y - * value. Otherwise, {@code tx} and {@code opt_ty} are used to translate the x - * and y dimension values. - * - * @param {number|goog.math.Coordinate} tx The value to translate the x - * dimension values by or the the coordinate to translate this box by. - * @param {number=} opt_ty The value to translate y dimension values by. - * @return {!goog.math.Box} This box after translating. - */ -goog.math.Box.prototype.translate = function(tx, opt_ty) { - if (tx instanceof goog.math.Coordinate) { - this.left += tx.x; - this.right += tx.x; - this.top += tx.y; - this.bottom += tx.y; - } else { - goog.asserts.assertNumber(tx); - this.left += tx; - this.right += tx; - if (goog.isNumber(opt_ty)) { - this.top += opt_ty; - this.bottom += opt_ty; - } - } - return this; -}; - - -/** - * Scales this coordinate by the given scale factors. The x and y dimension - * values are scaled by {@code sx} and {@code opt_sy} respectively. - * If {@code opt_sy} is not given, then {@code sx} is used for both x and y. - * - * @param {number} sx The scale factor to use for the x dimension. - * @param {number=} opt_sy The scale factor to use for the y dimension. - * @return {!goog.math.Box} This box after scaling. - */ -goog.math.Box.prototype.scale = function(sx, opt_sy) { - var sy = goog.isNumber(opt_sy) ? opt_sy : sx; - this.left *= sx; - this.right *= sx; - this.top *= sy; - this.bottom *= sy; - return this; -};
diff --git a/third_party/ink/closure/math/coordinate.js b/third_party/ink/closure/math/coordinate.js deleted file mode 100644 index 6966451d..0000000 --- a/third_party/ink/closure/math/coordinate.js +++ /dev/null
@@ -1,280 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A utility class for representing two-dimensional positions. - * @author pupius@google.com (Daniel Pupius) - */ - - -goog.provide('goog.math.Coordinate'); - -goog.require('goog.math'); - - - -/** - * Class for representing coordinates and positions. - * @param {number=} opt_x Left, defaults to 0. - * @param {number=} opt_y Top, defaults to 0. - * @struct - * @constructor - */ -goog.math.Coordinate = function(opt_x, opt_y) { - /** - * X-value - * @type {number} - */ - this.x = goog.isDef(opt_x) ? opt_x : 0; - - /** - * Y-value - * @type {number} - */ - this.y = goog.isDef(opt_y) ? opt_y : 0; -}; - - -/** - * Returns a new copy of the coordinate. - * @return {!goog.math.Coordinate} A clone of this coordinate. - */ -goog.math.Coordinate.prototype.clone = function() { - return new goog.math.Coordinate(this.x, this.y); -}; - - -if (goog.DEBUG) { - /** - * Returns a nice string representing the coordinate. - * @return {string} In the form (50, 73). - * @override - */ - goog.math.Coordinate.prototype.toString = function() { - return '(' + this.x + ', ' + this.y + ')'; - }; -} - - -/** - * Returns whether the specified value is equal to this coordinate. - * @param {*} other Some other value. - * @return {boolean} Whether the specified value is equal to this coordinate. - */ -goog.math.Coordinate.prototype.equals = function(other) { - return other instanceof goog.math.Coordinate && - goog.math.Coordinate.equals(this, other); -}; - - -/** - * Compares coordinates for equality. - * @param {goog.math.Coordinate} a A Coordinate. - * @param {goog.math.Coordinate} b A Coordinate. - * @return {boolean} True iff the coordinates are equal, or if both are null. - */ -goog.math.Coordinate.equals = function(a, b) { - if (a == b) { - return true; - } - if (!a || !b) { - return false; - } - return a.x == b.x && a.y == b.y; -}; - - -/** - * Returns the distance between two coordinates. - * @param {!goog.math.Coordinate} a A Coordinate. - * @param {!goog.math.Coordinate} b A Coordinate. - * @return {number} The distance between {@code a} and {@code b}. - */ -goog.math.Coordinate.distance = function(a, b) { - var dx = a.x - b.x; - var dy = a.y - b.y; - return Math.sqrt(dx * dx + dy * dy); -}; - - -/** - * Returns the magnitude of a coordinate. - * @param {!goog.math.Coordinate} a A Coordinate. - * @return {number} The distance between the origin and {@code a}. - */ -goog.math.Coordinate.magnitude = function(a) { - return Math.sqrt(a.x * a.x + a.y * a.y); -}; - - -/** - * Returns the angle from the origin to a coordinate. - * @param {!goog.math.Coordinate} a A Coordinate. - * @return {number} The angle, in degrees, clockwise from the positive X - * axis to {@code a}. - */ -goog.math.Coordinate.azimuth = function(a) { - return goog.math.angle(0, 0, a.x, a.y); -}; - - -/** - * Returns the squared distance between two coordinates. Squared distances can - * be used for comparisons when the actual value is not required. - * - * Performance note: eliminating the square root is an optimization often used - * in lower-level languages, but the speed difference is not nearly as - * pronounced in JavaScript (only a few percent.) - * - * @param {!goog.math.Coordinate} a A Coordinate. - * @param {!goog.math.Coordinate} b A Coordinate. - * @return {number} The squared distance between {@code a} and {@code b}. - */ -goog.math.Coordinate.squaredDistance = function(a, b) { - var dx = a.x - b.x; - var dy = a.y - b.y; - return dx * dx + dy * dy; -}; - - -/** - * Returns the difference between two coordinates as a new - * goog.math.Coordinate. - * @param {!goog.math.Coordinate} a A Coordinate. - * @param {!goog.math.Coordinate} b A Coordinate. - * @return {!goog.math.Coordinate} A Coordinate representing the difference - * between {@code a} and {@code b}. - */ -goog.math.Coordinate.difference = function(a, b) { - return new goog.math.Coordinate(a.x - b.x, a.y - b.y); -}; - - -/** - * Returns the sum of two coordinates as a new goog.math.Coordinate. - * @param {!goog.math.Coordinate} a A Coordinate. - * @param {!goog.math.Coordinate} b A Coordinate. - * @return {!goog.math.Coordinate} A Coordinate representing the sum of the two - * coordinates. - */ -goog.math.Coordinate.sum = function(a, b) { - return new goog.math.Coordinate(a.x + b.x, a.y + b.y); -}; - - -/** - * Rounds the x and y fields to the next larger integer values. - * @return {!goog.math.Coordinate} This coordinate with ceil'd fields. - */ -goog.math.Coordinate.prototype.ceil = function() { - this.x = Math.ceil(this.x); - this.y = Math.ceil(this.y); - return this; -}; - - -/** - * Rounds the x and y fields to the next smaller integer values. - * @return {!goog.math.Coordinate} This coordinate with floored fields. - */ -goog.math.Coordinate.prototype.floor = function() { - this.x = Math.floor(this.x); - this.y = Math.floor(this.y); - return this; -}; - - -/** - * Rounds the x and y fields to the nearest integer values. - * @return {!goog.math.Coordinate} This coordinate with rounded fields. - */ -goog.math.Coordinate.prototype.round = function() { - this.x = Math.round(this.x); - this.y = Math.round(this.y); - return this; -}; - - -/** - * Translates this box by the given offsets. If a {@code goog.math.Coordinate} - * is given, then the x and y values are translated by the coordinate's x and y. - * Otherwise, x and y are translated by {@code tx} and {@code opt_ty} - * respectively. - * @param {number|goog.math.Coordinate} tx The value to translate x by or the - * the coordinate to translate this coordinate by. - * @param {number=} opt_ty The value to translate y by. - * @return {!goog.math.Coordinate} This coordinate after translating. - */ -goog.math.Coordinate.prototype.translate = function(tx, opt_ty) { - if (tx instanceof goog.math.Coordinate) { - this.x += tx.x; - this.y += tx.y; - } else { - this.x += Number(tx); - if (goog.isNumber(opt_ty)) { - this.y += opt_ty; - } - } - return this; -}; - - -/** - * Scales this coordinate by the given scale factors. The x and y values are - * scaled by {@code sx} and {@code opt_sy} respectively. If {@code opt_sy} - * is not given, then {@code sx} is used for both x and y. - * @param {number} sx The scale factor to use for the x dimension. - * @param {number=} opt_sy The scale factor to use for the y dimension. - * @return {!goog.math.Coordinate} This coordinate after scaling. - */ -goog.math.Coordinate.prototype.scale = function(sx, opt_sy) { - var sy = goog.isNumber(opt_sy) ? opt_sy : sx; - this.x *= sx; - this.y *= sy; - return this; -}; - - -/** - * Rotates this coordinate clockwise about the origin (or, optionally, the given - * center) by the given angle, in radians. - * @param {number} radians The angle by which to rotate this coordinate - * clockwise about the given center, in radians. - * @param {!goog.math.Coordinate=} opt_center The center of rotation. Defaults - * to (0, 0) if not given. - */ -goog.math.Coordinate.prototype.rotateRadians = function(radians, opt_center) { - var center = opt_center || new goog.math.Coordinate(0, 0); - - var x = this.x; - var y = this.y; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - - this.x = (x - center.x) * cos - (y - center.y) * sin + center.x; - this.y = (x - center.x) * sin + (y - center.y) * cos + center.y; -}; - - -/** - * Rotates this coordinate clockwise about the origin (or, optionally, the given - * center) by the given angle, in degrees. - * @param {number} degrees The angle by which to rotate this coordinate - * clockwise about the given center, in degrees. - * @param {!goog.math.Coordinate=} opt_center The center of rotation. Defaults - * to (0, 0) if not given. - */ -goog.math.Coordinate.prototype.rotateDegrees = function(degrees, opt_center) { - this.rotateRadians(goog.math.toRadians(degrees), opt_center); -};
diff --git a/third_party/ink/closure/math/irect.js b/third_party/ink/closure/math/irect.js deleted file mode 100644 index db7cee1..0000000 --- a/third_party/ink/closure/math/irect.js +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2016 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A record declaration to allow ClientRect and other rectangle - * like objects to be used with goog.math.Rect. - */ - -goog.provide('goog.math.IRect'); - - -/** - * Record for representing rectangular regions, allows compatibility between - * things like ClientRect and goog.math.Rect. - * - * @record - */ -goog.math.IRect = function() {}; - - -/** @type {number} */ -goog.math.IRect.prototype.left; - - -/** @type {number} */ -goog.math.IRect.prototype.top; - - -/** @type {number} */ -goog.math.IRect.prototype.width; - - -/** @type {number} */ -goog.math.IRect.prototype.height;
diff --git a/third_party/ink/closure/math/long.js b/third_party/ink/closure/math/long.js deleted file mode 100644 index 60ddef0..0000000 --- a/third_party/ink/closure/math/long.js +++ /dev/null
@@ -1,966 +0,0 @@ -// Copyright 2009 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Defines a Long class for representing a 64-bit two's-complement - * integer value, which faithfully simulates the behavior of a Java "long". This - * implementation is derived from LongLib in GWT. - * - * @author kevinz@google.com (Kevin Zatloukal) - */ - -goog.provide('goog.math.Long'); - -goog.require('goog.asserts'); -goog.require('goog.reflect'); - - - -/** - * Constructs a 64-bit two's-complement integer, given its low and high 32-bit - * values as *signed* integers. See the from* functions below for more - * convenient ways of constructing Longs. - * - * The internal representation of a long is the two given signed, 32-bit values. - * We use 32-bit pieces because these are the size of integers on which - * Javascript performs bit-operations. For operations like addition and - * multiplication, we split each number into 16-bit pieces, which can easily be - * multiplied within Javascript's floating-point representation without overflow - * or change in sign. - * - * In the algorithms below, we frequently reduce the negative case to the - * positive case by negating the input(s) and then post-processing the result. - * Note that we must ALWAYS check specially whether those values are MIN_VALUE - * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as - * a positive number, it overflows back into a negative). Not handling this - * case would often result in infinite recursion. - * - * @param {number} low The low (signed) 32 bits of the long. - * @param {number} high The high (signed) 32 bits of the long. - * @struct - * @constructor - * @final - */ -goog.math.Long = function(low, high) { - /** - * @type {number} - * @private - */ - this.low_ = low | 0; // force into 32 signed bits. - - /** - * @type {number} - * @private - */ - this.high_ = high | 0; // force into 32 signed bits. -}; - - -// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the -// from* methods on which they depend. - - -/** - * A cache of the Long representations of small integer values. - * @type {!Object<number, !goog.math.Long>} - * @private - */ -goog.math.Long.IntCache_ = {}; - - -/** - * A cache of the Long representations of common values. - * @type {!Object<goog.math.Long.ValueCacheId_, !goog.math.Long>} - * @private - */ -goog.math.Long.valueCache_ = {}; - -/** - * Returns a cached long number representing the given (32-bit) integer value. - * @param {number} value The 32-bit integer in question. - * @return {!goog.math.Long} The corresponding Long value. - * @private - */ -goog.math.Long.getCachedIntValue_ = function(value) { - return goog.reflect.cache(goog.math.Long.IntCache_, value, function(val) { - return new goog.math.Long(val, val < 0 ? -1 : 0); - }); -}; - -/** - * The array of maximum values of a Long in string representation for a given - * radix between 2 and 36, inclusive. - * @private @const {!Array<string>} - */ -goog.math.Long.MAX_VALUE_FOR_RADIX_ = [ - '', '', // unused - '111111111111111111111111111111111111111111111111111111111111111', - // base 2 - '2021110011022210012102010021220101220221', // base 3 - '13333333333333333333333333333333', // base 4 - '1104332401304422434310311212', // base 5 - '1540241003031030222122211', // base 6 - '22341010611245052052300', // base 7 - '777777777777777777777', // base 8 - '67404283172107811827', // base 9 - '9223372036854775807', // base 10 - '1728002635214590697', // base 11 - '41a792678515120367', // base 12 - '10b269549075433c37', // base 13 - '4340724c6c71dc7a7', // base 14 - '160e2ad3246366807', // base 15 - '7fffffffffffffff', // base 16 - '33d3d8307b214008', // base 17 - '16agh595df825fa7', // base 18 - 'ba643dci0ffeehh', // base 19 - '5cbfjia3fh26ja7', // base 20 - '2heiciiie82dh97', // base 21 - '1adaibb21dckfa7', // base 22 - 'i6k448cf4192c2', // base 23 - 'acd772jnc9l0l7', // base 24 - '64ie1focnn5g77', // base 25 - '3igoecjbmca687', // base 26 - '27c48l5b37oaop', // base 27 - '1bk39f3ah3dmq7', // base 28 - 'q1se8f0m04isb', // base 29 - 'hajppbc1fc207', // base 30 - 'bm03i95hia437', // base 31 - '7vvvvvvvvvvvv', // base 32 - '5hg4ck9jd4u37', // base 33 - '3tdtk1v8j6tpp', // base 34 - '2pijmikexrxp7', // base 35 - '1y2p0ij32e8e7' // base 36 -]; - - -/** - * The array of minimum values of a Long in string representation for a given - * radix between 2 and 36, inclusive. - * @private @const {!Array<string>} - */ -goog.math.Long.MIN_VALUE_FOR_RADIX_ = [ - '', '', // unused - '-1000000000000000000000000000000000000000000000000000000000000000', - // base 2 - '-2021110011022210012102010021220101220222', // base 3 - '-20000000000000000000000000000000', // base 4 - '-1104332401304422434310311213', // base 5 - '-1540241003031030222122212', // base 6 - '-22341010611245052052301', // base 7 - '-1000000000000000000000', // base 8 - '-67404283172107811828', // base 9 - '-9223372036854775808', // base 10 - '-1728002635214590698', // base 11 - '-41a792678515120368', // base 12 - '-10b269549075433c38', // base 13 - '-4340724c6c71dc7a8', // base 14 - '-160e2ad3246366808', // base 15 - '-8000000000000000', // base 16 - '-33d3d8307b214009', // base 17 - '-16agh595df825fa8', // base 18 - '-ba643dci0ffeehi', // base 19 - '-5cbfjia3fh26ja8', // base 20 - '-2heiciiie82dh98', // base 21 - '-1adaibb21dckfa8', // base 22 - '-i6k448cf4192c3', // base 23 - '-acd772jnc9l0l8', // base 24 - '-64ie1focnn5g78', // base 25 - '-3igoecjbmca688', // base 26 - '-27c48l5b37oaoq', // base 27 - '-1bk39f3ah3dmq8', // base 28 - '-q1se8f0m04isc', // base 29 - '-hajppbc1fc208', // base 30 - '-bm03i95hia438', // base 31 - '-8000000000000', // base 32 - '-5hg4ck9jd4u38', // base 33 - '-3tdtk1v8j6tpq', // base 34 - '-2pijmikexrxp8', // base 35 - '-1y2p0ij32e8e8' // base 36 -]; - - -/** - * Returns a Long representing the given (32-bit) integer value. - * @param {number} value The 32-bit integer in question. - * @return {!goog.math.Long} The corresponding Long value. - */ -goog.math.Long.fromInt = function(value) { - var intValue = value | 0; - goog.asserts.assert(value === intValue, 'value should be a 32-bit integer'); - - if (-128 <= intValue && intValue < 128) { - return goog.math.Long.getCachedIntValue_(intValue); - } else { - return new goog.math.Long(intValue, intValue < 0 ? -1 : 0); - } -}; - - -/** - * Returns a Long representing the given value. - * NaN will be returned as zero. Infinity is converted to max value and - * -Infinity to min value. - * @param {number} value The number in question. - * @return {!goog.math.Long} The corresponding Long value. - */ -goog.math.Long.fromNumber = function(value) { - if (isNaN(value)) { - return goog.math.Long.getZero(); - } else if (value <= -goog.math.Long.TWO_PWR_63_DBL_) { - return goog.math.Long.getMinValue(); - } else if (value + 1 >= goog.math.Long.TWO_PWR_63_DBL_) { - return goog.math.Long.getMaxValue(); - } else if (value < 0) { - return goog.math.Long.fromNumber(-value).negate(); - } else { - return new goog.math.Long( - (value % goog.math.Long.TWO_PWR_32_DBL_) | 0, - (value / goog.math.Long.TWO_PWR_32_DBL_) | 0); - } -}; - - -/** - * Returns a Long representing the 64-bit integer that comes by concatenating - * the given high and low bits. Each is assumed to use 32 bits. - * @param {number} lowBits The low 32-bits. - * @param {number} highBits The high 32-bits. - * @return {!goog.math.Long} The corresponding Long value. - */ -goog.math.Long.fromBits = function(lowBits, highBits) { - return new goog.math.Long(lowBits, highBits); -}; - - -/** - * Returns a Long representation of the given string, written using the given - * radix. - * @param {string} str The textual representation of the Long. - * @param {number=} opt_radix The radix in which the text is written. - * @return {!goog.math.Long} The corresponding Long value. - */ -goog.math.Long.fromString = function(str, opt_radix) { - if (str.length == 0) { - throw new Error('number format error: empty string'); - } - - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw new Error('radix out of range: ' + radix); - } - - if (str.charAt(0) == '-') { - return goog.math.Long.fromString(str.substring(1), radix).negate(); - } else if (str.indexOf('-') >= 0) { - throw new Error('number format error: interior "-" character: ' + str); - } - - // Do several (8) digits each time through the loop, so as to - // minimize the calls to the very expensive emulated div. - var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 8)); - - var result = goog.math.Long.getZero(); - for (var i = 0; i < str.length; i += 8) { - var size = Math.min(8, str.length - i); - var value = parseInt(str.substring(i, i + size), radix); - if (size < 8) { - var power = goog.math.Long.fromNumber(Math.pow(radix, size)); - result = result.multiply(power).add(goog.math.Long.fromNumber(value)); - } else { - result = result.multiply(radixToPower); - result = result.add(goog.math.Long.fromNumber(value)); - } - } - return result; -}; - -/** - * Returns the boolean value of whether the input string is within a Long's - * range. Assumes an input string containing only numeric characters with an - * optional preceding '-'. - * @param {string} str The textual representation of the Long. - * @param {number=} opt_radix The radix in which the text is written. - * @return {boolean} Whether the string is within the range of a Long. - */ -goog.math.Long.isStringInRange = function(str, opt_radix) { - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw new Error('radix out of range: ' + radix); - } - - var extremeValue = (str.charAt(0) == '-') ? - goog.math.Long.MIN_VALUE_FOR_RADIX_[radix] : - goog.math.Long.MAX_VALUE_FOR_RADIX_[radix]; - - if (str.length < extremeValue.length) { - return true; - } else if (str.length == extremeValue.length && str <= extremeValue) { - return true; - } else { - return false; - } -}; - -// NOTE: the compiler should inline these constant values below and then remove -// these variables, so there should be no runtime penalty for these. - - -/** - * Number used repeated below in calculations. This must appear before the - * first call to any from* function below. - * @type {number} - * @private - */ -goog.math.Long.TWO_PWR_16_DBL_ = 1 << 16; - - -/** - * @type {number} - * @private - */ -goog.math.Long.TWO_PWR_32_DBL_ = - goog.math.Long.TWO_PWR_16_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; - - -/** - * @type {number} - * @private - */ -goog.math.Long.TWO_PWR_64_DBL_ = - goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_32_DBL_; - - -/** - * @type {number} - * @private - */ -goog.math.Long.TWO_PWR_63_DBL_ = goog.math.Long.TWO_PWR_64_DBL_ / 2; - - -/** - * @return {!goog.math.Long} - * @public - */ -goog.math.Long.getZero = function() { - return goog.math.Long.getCachedIntValue_(0); -}; - - -/** - * @return {!goog.math.Long} - * @public - */ -goog.math.Long.getOne = function() { - return goog.math.Long.getCachedIntValue_(1); -}; - - -/** - * @return {!goog.math.Long} - * @public - */ -goog.math.Long.getNegOne = function() { - return goog.math.Long.getCachedIntValue_(-1); -}; - - -/** - * @return {!goog.math.Long} - * @public - */ -goog.math.Long.getMaxValue = function() { - return goog.reflect.cache( - goog.math.Long.valueCache_, goog.math.Long.ValueCacheId_.MAX_VALUE, - function() { - return goog.math.Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); - }); -}; - - -/** - * @return {!goog.math.Long} - * @public - */ -goog.math.Long.getMinValue = function() { - return goog.reflect.cache( - goog.math.Long.valueCache_, goog.math.Long.ValueCacheId_.MIN_VALUE, - function() { return goog.math.Long.fromBits(0, 0x80000000 | 0); }); -}; - - -/** - * @return {!goog.math.Long} - * @public - */ -goog.math.Long.getTwoPwr24 = function() { - return goog.reflect.cache( - goog.math.Long.valueCache_, goog.math.Long.ValueCacheId_.TWO_PWR_24, - function() { return goog.math.Long.fromInt(1 << 24); }); -}; - - -/** @return {number} The value, assuming it is a 32-bit integer. */ -goog.math.Long.prototype.toInt = function() { - return this.low_; -}; - - -/** @return {number} The closest floating-point representation to this value. */ -goog.math.Long.prototype.toNumber = function() { - return this.high_ * goog.math.Long.TWO_PWR_32_DBL_ + - this.getLowBitsUnsigned(); -}; - - -/** - * @param {number=} opt_radix The radix in which the text should be written. - * @return {string} The textual representation of this value. - * @override - */ -goog.math.Long.prototype.toString = function(opt_radix) { - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw new Error('radix out of range: ' + radix); - } - - if (this.isZero()) { - return '0'; - } - - if (this.isNegative()) { - if (this.equals(goog.math.Long.getMinValue())) { - // We need to change the Long value before it can be negated, so we remove - // the bottom-most digit in this base and then recurse to do the rest. - var radixLong = goog.math.Long.fromNumber(radix); - var div = this.div(radixLong); - var rem = div.multiply(radixLong).subtract(this); - return div.toString(radix) + rem.toInt().toString(radix); - } else { - return '-' + this.negate().toString(radix); - } - } - - // Do several (6) digits each time through the loop, so as to - // minimize the calls to the very expensive emulated div. - var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 6)); - - var rem = this; - var result = ''; - while (true) { - var remDiv = rem.div(radixToPower); - // The right shifting fixes negative values in the case when - // intval >= 2^31; for more details see - // https://github.com/google/closure-library/pull/498 - var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt() >>> 0; - var digits = intval.toString(radix); - - rem = remDiv; - if (rem.isZero()) { - return digits + result; - } else { - while (digits.length < 6) { - digits = '0' + digits; - } - result = '' + digits + result; - } - } -}; - - -/** @return {number} The high 32-bits as a signed value. */ -goog.math.Long.prototype.getHighBits = function() { - return this.high_; -}; - - -/** @return {number} The low 32-bits as a signed value. */ -goog.math.Long.prototype.getLowBits = function() { - return this.low_; -}; - - -/** @return {number} The low 32-bits as an unsigned value. */ -goog.math.Long.prototype.getLowBitsUnsigned = function() { - return (this.low_ >= 0) ? this.low_ : - goog.math.Long.TWO_PWR_32_DBL_ + this.low_; -}; - - -/** - * @return {number} Returns the number of bits needed to represent the absolute - * value of this Long. - */ -goog.math.Long.prototype.getNumBitsAbs = function() { - if (this.isNegative()) { - if (this.equals(goog.math.Long.getMinValue())) { - return 64; - } else { - return this.negate().getNumBitsAbs(); - } - } else { - var val = this.high_ != 0 ? this.high_ : this.low_; - for (var bit = 31; bit > 0; bit--) { - if ((val & (1 << bit)) != 0) { - break; - } - } - return this.high_ != 0 ? bit + 33 : bit + 1; - } -}; - - -/** @return {boolean} Whether this value is zero. */ -goog.math.Long.prototype.isZero = function() { - return this.high_ == 0 && this.low_ == 0; -}; - - -/** @return {boolean} Whether this value is negative. */ -goog.math.Long.prototype.isNegative = function() { - return this.high_ < 0; -}; - - -/** @return {boolean} Whether this value is odd. */ -goog.math.Long.prototype.isOdd = function() { - return (this.low_ & 1) == 1; -}; - - -/** - * @param {goog.math.Long} other Long to compare against. - * @return {boolean} Whether this Long equals the other. - */ -goog.math.Long.prototype.equals = function(other) { - return (this.high_ == other.high_) && (this.low_ == other.low_); -}; - - -/** - * @param {goog.math.Long} other Long to compare against. - * @return {boolean} Whether this Long does not equal the other. - */ -goog.math.Long.prototype.notEquals = function(other) { - return (this.high_ != other.high_) || (this.low_ != other.low_); -}; - - -/** - * @param {goog.math.Long} other Long to compare against. - * @return {boolean} Whether this Long is less than the other. - */ -goog.math.Long.prototype.lessThan = function(other) { - return this.compare(other) < 0; -}; - - -/** - * @param {goog.math.Long} other Long to compare against. - * @return {boolean} Whether this Long is less than or equal to the other. - */ -goog.math.Long.prototype.lessThanOrEqual = function(other) { - return this.compare(other) <= 0; -}; - - -/** - * @param {goog.math.Long} other Long to compare against. - * @return {boolean} Whether this Long is greater than the other. - */ -goog.math.Long.prototype.greaterThan = function(other) { - return this.compare(other) > 0; -}; - - -/** - * @param {goog.math.Long} other Long to compare against. - * @return {boolean} Whether this Long is greater than or equal to the other. - */ -goog.math.Long.prototype.greaterThanOrEqual = function(other) { - return this.compare(other) >= 0; -}; - - -/** - * Compares this Long with the given one. - * @param {goog.math.Long} other Long to compare against. - * @return {number} 0 if they are the same, 1 if the this is greater, and -1 - * if the given one is greater. - */ -goog.math.Long.prototype.compare = function(other) { - if (this.equals(other)) { - return 0; - } - - var thisNeg = this.isNegative(); - var otherNeg = other.isNegative(); - if (thisNeg && !otherNeg) { - return -1; - } - if (!thisNeg && otherNeg) { - return 1; - } - - // at this point, the signs are the same, so subtraction will not overflow - if (this.subtract(other).isNegative()) { - return -1; - } else { - return 1; - } -}; - - -/** @return {!goog.math.Long} The negation of this value. */ -goog.math.Long.prototype.negate = function() { - if (this.equals(goog.math.Long.getMinValue())) { - return goog.math.Long.getMinValue(); - } else { - return this.not().add(goog.math.Long.getOne()); - } -}; - - -/** - * Returns the sum of this and the given Long. - * @param {goog.math.Long} other Long to add to this one. - * @return {!goog.math.Long} The sum of this and the given Long. - */ -goog.math.Long.prototype.add = function(other) { - // Divide each number into 4 chunks of 16 bits, and then sum the chunks. - - var a48 = this.high_ >>> 16; - var a32 = this.high_ & 0xFFFF; - var a16 = this.low_ >>> 16; - var a00 = this.low_ & 0xFFFF; - - var b48 = other.high_ >>> 16; - var b32 = other.high_ & 0xFFFF; - var b16 = other.low_ >>> 16; - var b00 = other.low_ & 0xFFFF; - - var c48 = 0, c32 = 0, c16 = 0, c00 = 0; - c00 += a00 + b00; - c16 += c00 >>> 16; - c00 &= 0xFFFF; - c16 += a16 + b16; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c32 += a32 + b32; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c48 += a48 + b48; - c48 &= 0xFFFF; - return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); -}; - - -/** - * Returns the difference of this and the given Long. - * @param {goog.math.Long} other Long to subtract from this. - * @return {!goog.math.Long} The difference of this and the given Long. - */ -goog.math.Long.prototype.subtract = function(other) { - return this.add(other.negate()); -}; - - -/** - * Returns the product of this and the given long. - * @param {goog.math.Long} other Long to multiply with this. - * @return {!goog.math.Long} The product of this and the other. - */ -goog.math.Long.prototype.multiply = function(other) { - if (this.isZero()) { - return goog.math.Long.getZero(); - } else if (other.isZero()) { - return goog.math.Long.getZero(); - } - - if (this.equals(goog.math.Long.getMinValue())) { - return other.isOdd() ? goog.math.Long.getMinValue() : - goog.math.Long.getZero(); - } else if (other.equals(goog.math.Long.getMinValue())) { - return this.isOdd() ? goog.math.Long.getMinValue() : - goog.math.Long.getZero(); - } - - if (this.isNegative()) { - if (other.isNegative()) { - return this.negate().multiply(other.negate()); - } else { - return this.negate().multiply(other).negate(); - } - } else if (other.isNegative()) { - return this.multiply(other.negate()).negate(); - } - - // If both longs are small, use float multiplication - if (this.lessThan(goog.math.Long.getTwoPwr24()) && - other.lessThan(goog.math.Long.getTwoPwr24())) { - return goog.math.Long.fromNumber(this.toNumber() * other.toNumber()); - } - - // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. - // We can skip products that would overflow. - - var a48 = this.high_ >>> 16; - var a32 = this.high_ & 0xFFFF; - var a16 = this.low_ >>> 16; - var a00 = this.low_ & 0xFFFF; - - var b48 = other.high_ >>> 16; - var b32 = other.high_ & 0xFFFF; - var b16 = other.low_ >>> 16; - var b00 = other.low_ & 0xFFFF; - - var c48 = 0, c32 = 0, c16 = 0, c00 = 0; - c00 += a00 * b00; - c16 += c00 >>> 16; - c00 &= 0xFFFF; - c16 += a16 * b00; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c16 += a00 * b16; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c32 += a32 * b00; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c32 += a16 * b16; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c32 += a00 * b32; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; - c48 &= 0xFFFF; - return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); -}; - - -/** - * Returns this Long divided by the given one. - * @param {goog.math.Long} other Long by which to divide. - * @return {!goog.math.Long} This Long divided by the given one. - */ -goog.math.Long.prototype.div = function(other) { - if (other.isZero()) { - throw new Error('division by zero'); - } else if (this.isZero()) { - return goog.math.Long.getZero(); - } - - if (this.equals(goog.math.Long.getMinValue())) { - if (other.equals(goog.math.Long.getOne()) || - other.equals(goog.math.Long.getNegOne())) { - return goog.math.Long.getMinValue(); // recall -MIN_VALUE == MIN_VALUE - } else if (other.equals(goog.math.Long.getMinValue())) { - return goog.math.Long.getOne(); - } else { - // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. - var halfThis = this.shiftRight(1); - var approx = halfThis.div(other).shiftLeft(1); - if (approx.equals(goog.math.Long.getZero())) { - return other.isNegative() ? goog.math.Long.getOne() : - goog.math.Long.getNegOne(); - } else { - var rem = this.subtract(other.multiply(approx)); - var result = approx.add(rem.div(other)); - return result; - } - } - } else if (other.equals(goog.math.Long.getMinValue())) { - return goog.math.Long.getZero(); - } - - if (this.isNegative()) { - if (other.isNegative()) { - return this.negate().div(other.negate()); - } else { - return this.negate().div(other).negate(); - } - } else if (other.isNegative()) { - return this.div(other.negate()).negate(); - } - - // Repeat the following until the remainder is less than other: find a - // floating-point that approximates remainder / other *from below*, add this - // into the result, and subtract it from the remainder. It is critical that - // the approximate value is less than or equal to the real value so that the - // remainder never becomes negative. - var res = goog.math.Long.getZero(); - var rem = this; - while (rem.greaterThanOrEqual(other)) { - // Approximate the result of division. This may be a little greater or - // smaller than the actual value. - var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); - - // We will tweak the approximate result by changing it in the 48-th digit or - // the smallest non-fractional digit, whichever is larger. - var log2 = Math.ceil(Math.log(approx) / Math.LN2); - var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); - - // Decrease the approximation until it is smaller than the remainder. Note - // that if it is too large, the product overflows and is negative. - var approxRes = goog.math.Long.fromNumber(approx); - var approxRem = approxRes.multiply(other); - while (approxRem.isNegative() || approxRem.greaterThan(rem)) { - approx -= delta; - approxRes = goog.math.Long.fromNumber(approx); - approxRem = approxRes.multiply(other); - } - - // We know the answer can't be zero... and actually, zero would cause - // infinite recursion since we would make no progress. - if (approxRes.isZero()) { - approxRes = goog.math.Long.getOne(); - } - - res = res.add(approxRes); - rem = rem.subtract(approxRem); - } - return res; -}; - - -/** - * Returns this Long modulo the given one. - * @param {goog.math.Long} other Long by which to mod. - * @return {!goog.math.Long} This Long modulo the given one. - */ -goog.math.Long.prototype.modulo = function(other) { - return this.subtract(this.div(other).multiply(other)); -}; - - -/** @return {!goog.math.Long} The bitwise-NOT of this value. */ -goog.math.Long.prototype.not = function() { - return goog.math.Long.fromBits(~this.low_, ~this.high_); -}; - - -/** - * Returns the bitwise-AND of this Long and the given one. - * @param {goog.math.Long} other The Long with which to AND. - * @return {!goog.math.Long} The bitwise-AND of this and the other. - */ -goog.math.Long.prototype.and = function(other) { - return goog.math.Long.fromBits( - this.low_ & other.low_, this.high_ & other.high_); -}; - - -/** - * Returns the bitwise-OR of this Long and the given one. - * @param {goog.math.Long} other The Long with which to OR. - * @return {!goog.math.Long} The bitwise-OR of this and the other. - */ -goog.math.Long.prototype.or = function(other) { - return goog.math.Long.fromBits( - this.low_ | other.low_, this.high_ | other.high_); -}; - - -/** - * Returns the bitwise-XOR of this Long and the given one. - * @param {goog.math.Long} other The Long with which to XOR. - * @return {!goog.math.Long} The bitwise-XOR of this and the other. - */ -goog.math.Long.prototype.xor = function(other) { - return goog.math.Long.fromBits( - this.low_ ^ other.low_, this.high_ ^ other.high_); -}; - - -/** - * Returns this Long with bits shifted to the left by the given amount. - * @param {number} numBits The number of bits by which to shift. - * @return {!goog.math.Long} This shifted to the left by the given amount. - */ -goog.math.Long.prototype.shiftLeft = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var low = this.low_; - if (numBits < 32) { - var high = this.high_; - return goog.math.Long.fromBits( - low << numBits, (high << numBits) | (low >>> (32 - numBits))); - } else { - return goog.math.Long.fromBits(0, low << (numBits - 32)); - } - } -}; - - -/** - * Returns this Long with bits shifted to the right by the given amount. - * The new leading bits match the current sign bit. - * @param {number} numBits The number of bits by which to shift. - * @return {!goog.math.Long} This shifted to the right by the given amount. - */ -goog.math.Long.prototype.shiftRight = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var high = this.high_; - if (numBits < 32) { - var low = this.low_; - return goog.math.Long.fromBits( - (low >>> numBits) | (high << (32 - numBits)), high >> numBits); - } else { - return goog.math.Long.fromBits( - high >> (numBits - 32), high >= 0 ? 0 : -1); - } - } -}; - - -/** - * Returns this Long with bits shifted to the right by the given amount, with - * zeros placed into the new leading bits. - * @param {number} numBits The number of bits by which to shift. - * @return {!goog.math.Long} This shifted to the right by the given amount, with - * zeros placed into the new leading bits. - */ -goog.math.Long.prototype.shiftRightUnsigned = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var high = this.high_; - if (numBits < 32) { - var low = this.low_; - return goog.math.Long.fromBits( - (low >>> numBits) | (high << (32 - numBits)), high >>> numBits); - } else if (numBits == 32) { - return goog.math.Long.fromBits(high, 0); - } else { - return goog.math.Long.fromBits(high >>> (numBits - 32), 0); - } - } -}; - - -/** - * @enum {number} Ids of commonly requested Long instances. - * @private - */ -goog.math.Long.ValueCacheId_ = { - MAX_VALUE: 1, - MIN_VALUE: 2, - TWO_PWR_24: 6 -};
diff --git a/third_party/ink/closure/math/math.js b/third_party/ink/closure/math/math.js deleted file mode 100644 index a251005b..0000000 --- a/third_party/ink/closure/math/math.js +++ /dev/null
@@ -1,449 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Additional mathematical functions. - * @author pupius@google.com (Daniel Pupius) - */ - -goog.provide('goog.math'); - -goog.require('goog.array'); -goog.require('goog.asserts'); - - -/** - * Returns a random integer greater than or equal to 0 and less than {@code a}. - * @param {number} a The upper bound for the random integer (exclusive). - * @return {number} A random integer N such that 0 <= N < a. - */ -goog.math.randomInt = function(a) { - return Math.floor(Math.random() * a); -}; - - -/** - * Returns a random number greater than or equal to {@code a} and less than - * {@code b}. - * @param {number} a The lower bound for the random number (inclusive). - * @param {number} b The upper bound for the random number (exclusive). - * @return {number} A random number N such that a <= N < b. - */ -goog.math.uniformRandom = function(a, b) { - return a + Math.random() * (b - a); -}; - - -/** - * Takes a number and clamps it to within the provided bounds. - * @param {number} value The input number. - * @param {number} min The minimum value to return. - * @param {number} max The maximum value to return. - * @return {number} The input number if it is within bounds, or the nearest - * number within the bounds. - */ -goog.math.clamp = function(value, min, max) { - return Math.min(Math.max(value, min), max); -}; - - -/** - * The % operator in JavaScript returns the remainder of a / b, but differs from - * some other languages in that the result will have the same sign as the - * dividend. For example, -1 % 8 == -1, whereas in some other languages - * (such as Python) the result would be 7. This function emulates the more - * correct modulo behavior, which is useful for certain applications such as - * calculating an offset index in a circular list. - * - * @param {number} a The dividend. - * @param {number} b The divisor. - * @return {number} a % b where the result is between 0 and b (either 0 <= x < b - * or b < x <= 0, depending on the sign of b). - */ -goog.math.modulo = function(a, b) { - var r = a % b; - // If r and b differ in sign, add b to wrap the result to the correct sign. - return (r * b < 0) ? r + b : r; -}; - - -/** - * Performs linear interpolation between values a and b. Returns the value - * between a and b proportional to x (when x is between 0 and 1. When x is - * outside this range, the return value is a linear extrapolation). - * @param {number} a A number. - * @param {number} b A number. - * @param {number} x The proportion between a and b. - * @return {number} The interpolated value between a and b. - */ -goog.math.lerp = function(a, b, x) { - return a + x * (b - a); -}; - - -/** - * Tests whether the two values are equal to each other, within a certain - * tolerance to adjust for floating point errors. - * @param {number} a A number. - * @param {number} b A number. - * @param {number=} opt_tolerance Optional tolerance range. Defaults - * to 0.000001. If specified, should be greater than 0. - * @return {boolean} Whether {@code a} and {@code b} are nearly equal. - */ -goog.math.nearlyEquals = function(a, b, opt_tolerance) { - return Math.abs(a - b) <= (opt_tolerance || 0.000001); -}; - - -// TODO(jrajeshwar): Rename to normalizeAngle, retaining old name as deprecated -// alias. -/** - * Normalizes an angle to be in range [0-360). Angles outside this range will - * be normalized to be the equivalent angle with that range. - * @param {number} angle Angle in degrees. - * @return {number} Standardized angle. - */ -goog.math.standardAngle = function(angle) { - return goog.math.modulo(angle, 360); -}; - - -/** - * Normalizes an angle to be in range [0-2*PI). Angles outside this range will - * be normalized to be the equivalent angle with that range. - * @param {number} angle Angle in radians. - * @return {number} Standardized angle. - */ -goog.math.standardAngleInRadians = function(angle) { - return goog.math.modulo(angle, 2 * Math.PI); -}; - - -/** - * Converts degrees to radians. - * @param {number} angleDegrees Angle in degrees. - * @return {number} Angle in radians. - */ -goog.math.toRadians = function(angleDegrees) { - return angleDegrees * Math.PI / 180; -}; - - -/** - * Converts radians to degrees. - * @param {number} angleRadians Angle in radians. - * @return {number} Angle in degrees. - */ -goog.math.toDegrees = function(angleRadians) { - return angleRadians * 180 / Math.PI; -}; - - -/** - * For a given angle and radius, finds the X portion of the offset. - * @param {number} degrees Angle in degrees (zero points in +X direction). - * @param {number} radius Radius. - * @return {number} The x-distance for the angle and radius. - */ -goog.math.angleDx = function(degrees, radius) { - return radius * Math.cos(goog.math.toRadians(degrees)); -}; - - -/** - * For a given angle and radius, finds the Y portion of the offset. - * @param {number} degrees Angle in degrees (zero points in +X direction). - * @param {number} radius Radius. - * @return {number} The y-distance for the angle and radius. - */ -goog.math.angleDy = function(degrees, radius) { - return radius * Math.sin(goog.math.toRadians(degrees)); -}; - - -/** - * Computes the angle between two points (x1,y1) and (x2,y2). - * Angle zero points in the +X direction, 90 degrees points in the +Y - * direction (down) and from there we grow clockwise towards 360 degrees. - * @param {number} x1 x of first point. - * @param {number} y1 y of first point. - * @param {number} x2 x of second point. - * @param {number} y2 y of second point. - * @return {number} Standardized angle in degrees of the vector from - * x1,y1 to x2,y2. - */ -goog.math.angle = function(x1, y1, x2, y2) { - return goog.math.standardAngle( - goog.math.toDegrees(Math.atan2(y2 - y1, x2 - x1))); -}; - - -/** - * Computes the difference between startAngle and endAngle (angles in degrees). - * @param {number} startAngle Start angle in degrees. - * @param {number} endAngle End angle in degrees. - * @return {number} The number of degrees that when added to - * startAngle will result in endAngle. Positive numbers mean that the - * direction is clockwise. Negative numbers indicate a counter-clockwise - * direction. - * The shortest route (clockwise vs counter-clockwise) between the angles - * is used. - * When the difference is 180 degrees, the function returns 180 (not -180) - * angleDifference(30, 40) is 10, and angleDifference(40, 30) is -10. - * angleDifference(350, 10) is 20, and angleDifference(10, 350) is -20. - */ -goog.math.angleDifference = function(startAngle, endAngle) { - var d = - goog.math.standardAngle(endAngle) - goog.math.standardAngle(startAngle); - if (d > 180) { - d = d - 360; - } else if (d <= -180) { - d = 360 + d; - } - return d; -}; - - -/** - * Returns the sign of a number as per the "sign" or "signum" function. - * @param {number} x The number to take the sign of. - * @return {number} -1 when negative, 1 when positive, 0 when 0. Preserves - * signed zeros and NaN. - */ -goog.math.sign = function(x) { - if (x > 0) { - return 1; - } - if (x < 0) { - return -1; - } - return x; // Preserves signed zeros and NaN. -}; - - -/** - * JavaScript implementation of Longest Common Subsequence problem. - * http://en.wikipedia.org/wiki/Longest_common_subsequence - * - * Returns the longest possible array that is subarray of both of given arrays. - * - * @param {IArrayLike<S>} array1 First array of objects. - * @param {IArrayLike<T>} array2 Second array of objects. - * @param {Function=} opt_compareFn Function that acts as a custom comparator - * for the array ojects. Function should return true if objects are equal, - * otherwise false. - * @param {Function=} opt_collectorFn Function used to decide what to return - * as a result subsequence. It accepts 2 arguments: index of common element - * in the first array and index in the second. The default function returns - * element from the first array. - * @return {!Array<S|T>} A list of objects that are common to both arrays - * such that there is no common subsequence with size greater than the - * length of the list. - * @template S,T - */ -goog.math.longestCommonSubsequence = function( - array1, array2, opt_compareFn, opt_collectorFn) { - - var compare = opt_compareFn || function(a, b) { return a == b; }; - - var collect = opt_collectorFn || function(i1, i2) { return array1[i1]; }; - - var length1 = array1.length; - var length2 = array2.length; - - var arr = []; - for (var i = 0; i < length1 + 1; i++) { - arr[i] = []; - arr[i][0] = 0; - } - - for (var j = 0; j < length2 + 1; j++) { - arr[0][j] = 0; - } - - for (i = 1; i <= length1; i++) { - for (j = 1; j <= length2; j++) { - if (compare(array1[i - 1], array2[j - 1])) { - arr[i][j] = arr[i - 1][j - 1] + 1; - } else { - arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]); - } - } - } - - // Backtracking - var result = []; - var i = length1, j = length2; - while (i > 0 && j > 0) { - if (compare(array1[i - 1], array2[j - 1])) { - result.unshift(collect(i - 1, j - 1)); - i--; - j--; - } else { - if (arr[i - 1][j] > arr[i][j - 1]) { - i--; - } else { - j--; - } - } - } - - return result; -}; - - -/** - * Returns the sum of the arguments. - * @param {...number} var_args Numbers to add. - * @return {number} The sum of the arguments (0 if no arguments were provided, - * {@code NaN} if any of the arguments is not a valid number). - */ -goog.math.sum = function(var_args) { - return /** @type {number} */ ( - goog.array.reduce( - arguments, function(sum, value) { return sum + value; }, 0)); -}; - - -/** - * Returns the arithmetic mean of the arguments. - * @param {...number} var_args Numbers to average. - * @return {number} The average of the arguments ({@code NaN} if no arguments - * were provided or any of the arguments is not a valid number). - */ -goog.math.average = function(var_args) { - return goog.math.sum.apply(null, arguments) / arguments.length; -}; - - -/** - * Returns the unbiased sample variance of the arguments. For a definition, - * see e.g. http://en.wikipedia.org/wiki/Variance - * @param {...number} var_args Number samples to analyze. - * @return {number} The unbiased sample variance of the arguments (0 if fewer - * than two samples were provided, or {@code NaN} if any of the samples is - * not a valid number). - */ -goog.math.sampleVariance = function(var_args) { - var sampleSize = arguments.length; - if (sampleSize < 2) { - return 0; - } - - var mean = goog.math.average.apply(null, arguments); - var variance = - goog.math.sum.apply(null, goog.array.map(arguments, function(val) { - return Math.pow(val - mean, 2); - })) / (sampleSize - 1); - - return variance; -}; - - -/** - * Returns the sample standard deviation of the arguments. For a definition of - * sample standard deviation, see e.g. - * http://en.wikipedia.org/wiki/Standard_deviation - * @param {...number} var_args Number samples to analyze. - * @return {number} The sample standard deviation of the arguments (0 if fewer - * than two samples were provided, or {@code NaN} if any of the samples is - * not a valid number). - */ -goog.math.standardDeviation = function(var_args) { - return Math.sqrt(goog.math.sampleVariance.apply(null, arguments)); -}; - - -/** - * Returns whether the supplied number represents an integer, i.e. that is has - * no fractional component. No range-checking is performed on the number. - * @param {number} num The number to test. - * @return {boolean} Whether {@code num} is an integer. - */ -goog.math.isInt = function(num) { - return isFinite(num) && num % 1 == 0; -}; - - -/** - * Returns whether the supplied number is finite and not NaN. - * @param {number} num The number to test. - * @return {boolean} Whether {@code num} is a finite number. - * @deprecated Use {@link isFinite} instead. - */ -goog.math.isFiniteNumber = function(num) { - return isFinite(num); -}; - - -/** - * @param {number} num The number to test. - * @return {boolean} Whether it is negative zero. - */ -goog.math.isNegativeZero = function(num) { - return num == 0 && 1 / num < 0; -}; - - -/** - * Returns the precise value of floor(log10(num)). - * Simpler implementations didn't work because of floating point rounding - * errors. For example - * <ul> - * <li>Math.floor(Math.log(num) / Math.LN10) is off by one for num == 1e+3. - * <li>Math.floor(Math.log(num) * Math.LOG10E) is off by one for num == 1e+15. - * <li>Math.floor(Math.log10(num)) is off by one for num == 1e+15 - 1. - * </ul> - * @param {number} num A floating point number. - * @return {number} Its logarithm to base 10 rounded down to the nearest - * integer if num > 0. -Infinity if num == 0. NaN if num < 0. - */ -goog.math.log10Floor = function(num) { - if (num > 0) { - var x = Math.round(Math.log(num) * Math.LOG10E); - return x - (parseFloat('1e' + x) > num ? 1 : 0); - } - return num == 0 ? -Infinity : NaN; -}; - - -/** - * A tweaked variant of {@code Math.floor} which tolerates if the passed number - * is infinitesimally smaller than the closest integer. It often happens with - * the results of floating point calculations because of the finite precision - * of the intermediate results. For example {@code Math.floor(Math.log(1000) / - * Math.LN10) == 2}, not 3 as one would expect. - * @param {number} num A number. - * @param {number=} opt_epsilon An infinitesimally small positive number, the - * rounding error to tolerate. - * @return {number} The largest integer less than or equal to {@code num}. - */ -goog.math.safeFloor = function(num, opt_epsilon) { - goog.asserts.assert(!goog.isDef(opt_epsilon) || opt_epsilon > 0); - return Math.floor(num + (opt_epsilon || 2e-15)); -}; - - -/** - * A tweaked variant of {@code Math.ceil}. See {@code goog.math.safeFloor} for - * details. - * @param {number} num A number. - * @param {number=} opt_epsilon An infinitesimally small positive number, the - * rounding error to tolerate. - * @return {number} The smallest integer greater than or equal to {@code num}. - */ -goog.math.safeCeil = function(num, opt_epsilon) { - goog.asserts.assert(!goog.isDef(opt_epsilon) || opt_epsilon > 0); - return Math.ceil(num - (opt_epsilon || 2e-15)); -};
diff --git a/third_party/ink/closure/math/rect.js b/third_party/ink/closure/math/rect.js deleted file mode 100644 index 28bf840..0000000 --- a/third_party/ink/closure/math/rect.js +++ /dev/null
@@ -1,478 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A utility class for representing rectangles. Some of these - * functions should be migrated over to non-nullable params. - * @author pupius@google.com (Daniel Pupius) - */ - -goog.provide('goog.math.Rect'); - -goog.require('goog.asserts'); -goog.require('goog.math.Box'); -goog.require('goog.math.Coordinate'); -goog.require('goog.math.IRect'); -goog.require('goog.math.Size'); - - - -/** - * Class for representing rectangular regions. - * @param {number} x Left. - * @param {number} y Top. - * @param {number} w Width. - * @param {number} h Height. - * @struct - * @constructor - * @implements {goog.math.IRect} - */ -goog.math.Rect = function(x, y, w, h) { - /** @type {number} */ - this.left = x; - - /** @type {number} */ - this.top = y; - - /** @type {number} */ - this.width = w; - - /** @type {number} */ - this.height = h; -}; - - -/** - * @return {!goog.math.Rect} A new copy of this Rectangle. - */ -goog.math.Rect.prototype.clone = function() { - return new goog.math.Rect(this.left, this.top, this.width, this.height); -}; - - -/** - * Returns a new Box object with the same position and dimensions as this - * rectangle. - * @return {!goog.math.Box} A new Box representation of this Rectangle. - */ -goog.math.Rect.prototype.toBox = function() { - var right = this.left + this.width; - var bottom = this.top + this.height; - return new goog.math.Box(this.top, right, bottom, this.left); -}; - - -/** - * Creates a new Rect object with the position and size given. - * @param {!goog.math.Coordinate} position The top-left coordinate of the Rect - * @param {!goog.math.Size} size The size of the Rect - * @return {!goog.math.Rect} A new Rect initialized with the given position and - * size. - */ -goog.math.Rect.createFromPositionAndSize = function(position, size) { - return new goog.math.Rect(position.x, position.y, size.width, size.height); -}; - - -/** - * Creates a new Rect object with the same position and dimensions as a given - * Box. Note that this is only the inverse of toBox if left/top are defined. - * @param {goog.math.Box} box A box. - * @return {!goog.math.Rect} A new Rect initialized with the box's position - * and size. - */ -goog.math.Rect.createFromBox = function(box) { - return new goog.math.Rect( - box.left, box.top, box.right - box.left, box.bottom - box.top); -}; - - -if (goog.DEBUG) { - /** - * Returns a nice string representing size and dimensions of rectangle. - * @return {string} In the form (50, 73 - 75w x 25h). - * @override - */ - goog.math.Rect.prototype.toString = function() { - return '(' + this.left + ', ' + this.top + ' - ' + this.width + 'w x ' + - this.height + 'h)'; - }; -} - - -/** - * Compares rectangles for equality. - * @param {goog.math.IRect} a A Rectangle. - * @param {goog.math.IRect} b A Rectangle. - * @return {boolean} True iff the rectangles have the same left, top, width, - * and height, or if both are null. - */ -goog.math.Rect.equals = function(a, b) { - if (a == b) { - return true; - } - if (!a || !b) { - return false; - } - return a.left == b.left && a.width == b.width && a.top == b.top && - a.height == b.height; -}; - - -/** - * Computes the intersection of this rectangle and the rectangle parameter. If - * there is no intersection, returns false and leaves this rectangle as is. - * @param {goog.math.IRect} rect A Rectangle. - * @return {boolean} True iff this rectangle intersects with the parameter. - */ -goog.math.Rect.prototype.intersection = function(rect) { - var x0 = Math.max(this.left, rect.left); - var x1 = Math.min(this.left + this.width, rect.left + rect.width); - - if (x0 <= x1) { - var y0 = Math.max(this.top, rect.top); - var y1 = Math.min(this.top + this.height, rect.top + rect.height); - - if (y0 <= y1) { - this.left = x0; - this.top = y0; - this.width = x1 - x0; - this.height = y1 - y0; - - return true; - } - } - return false; -}; - - -/** - * Returns the intersection of two rectangles. Two rectangles intersect if they - * touch at all, for example, two zero width and height rectangles would - * intersect if they had the same top and left. - * @param {goog.math.IRect} a A Rectangle. - * @param {goog.math.IRect} b A Rectangle. - * @return {goog.math.Rect} A new intersection rect (even if width and height - * are 0), or null if there is no intersection. - */ -goog.math.Rect.intersection = function(a, b) { - // There is no nice way to do intersection via a clone, because any such - // clone might be unnecessary if this function returns null. So, we duplicate - // code from above. - - var x0 = Math.max(a.left, b.left); - var x1 = Math.min(a.left + a.width, b.left + b.width); - - if (x0 <= x1) { - var y0 = Math.max(a.top, b.top); - var y1 = Math.min(a.top + a.height, b.top + b.height); - - if (y0 <= y1) { - return new goog.math.Rect(x0, y0, x1 - x0, y1 - y0); - } - } - return null; -}; - - -/** - * Returns whether two rectangles intersect. Two rectangles intersect if they - * touch at all, for example, two zero width and height rectangles would - * intersect if they had the same top and left. - * @param {goog.math.IRect} a A Rectangle. - * @param {goog.math.IRect} b A Rectangle. - * @return {boolean} Whether a and b intersect. - */ -goog.math.Rect.intersects = function(a, b) { - return ( - a.left <= b.left + b.width && b.left <= a.left + a.width && - a.top <= b.top + b.height && b.top <= a.top + a.height); -}; - - -/** - * Returns whether a rectangle intersects this rectangle. - * @param {goog.math.IRect} rect A rectangle. - * @return {boolean} Whether rect intersects this rectangle. - */ -goog.math.Rect.prototype.intersects = function(rect) { - return goog.math.Rect.intersects(this, rect); -}; - - -/** - * Computes the difference regions between two rectangles. The return value is - * an array of 0 to 4 rectangles defining the remaining regions of the first - * rectangle after the second has been subtracted. - * @param {goog.math.Rect} a A Rectangle. - * @param {goog.math.IRect} b A Rectangle. - * @return {!Array<!goog.math.Rect>} An array with 0 to 4 rectangles which - * together define the difference area of rectangle a minus rectangle b. - */ -goog.math.Rect.difference = function(a, b) { - var intersection = goog.math.Rect.intersection(a, b); - if (!intersection || !intersection.height || !intersection.width) { - return [a.clone()]; - } - - var result = []; - - var top = a.top; - var height = a.height; - - var ar = a.left + a.width; - var ab = a.top + a.height; - - var br = b.left + b.width; - var bb = b.top + b.height; - - // Subtract off any area on top where A extends past B - if (b.top > a.top) { - result.push(new goog.math.Rect(a.left, a.top, a.width, b.top - a.top)); - top = b.top; - // If we're moving the top down, we also need to subtract the height diff. - height -= b.top - a.top; - } - // Subtract off any area on bottom where A extends past B - if (bb < ab) { - result.push(new goog.math.Rect(a.left, bb, a.width, ab - bb)); - height = bb - top; - } - // Subtract any area on left where A extends past B - if (b.left > a.left) { - result.push(new goog.math.Rect(a.left, top, b.left - a.left, height)); - } - // Subtract any area on right where A extends past B - if (br < ar) { - result.push(new goog.math.Rect(br, top, ar - br, height)); - } - - return result; -}; - - -/** - * Computes the difference regions between this rectangle and {@code rect}. The - * return value is an array of 0 to 4 rectangles defining the remaining regions - * of this rectangle after the other has been subtracted. - * @param {goog.math.IRect} rect A Rectangle. - * @return {!Array<!goog.math.Rect>} An array with 0 to 4 rectangles which - * together define the difference area of rectangle a minus rectangle b. - */ -goog.math.Rect.prototype.difference = function(rect) { - return goog.math.Rect.difference(this, rect); -}; - - -/** - * Expand this rectangle to also include the area of the given rectangle. - * @param {goog.math.IRect} rect The other rectangle. - */ -goog.math.Rect.prototype.boundingRect = function(rect) { - // We compute right and bottom before we change left and top below. - var right = Math.max(this.left + this.width, rect.left + rect.width); - var bottom = Math.max(this.top + this.height, rect.top + rect.height); - - this.left = Math.min(this.left, rect.left); - this.top = Math.min(this.top, rect.top); - - this.width = right - this.left; - this.height = bottom - this.top; -}; - - -/** - * Returns a new rectangle which completely contains both input rectangles. - * @param {goog.math.IRect} a A rectangle. - * @param {goog.math.IRect} b A rectangle. - * @return {goog.math.Rect} A new bounding rect, or null if either rect is - * null. - */ -goog.math.Rect.boundingRect = function(a, b) { - if (!a || !b) { - return null; - } - - var newRect = new goog.math.Rect(a.left, a.top, a.width, a.height); - newRect.boundingRect(b); - - return newRect; -}; - - -/** - * Tests whether this rectangle entirely contains another rectangle or - * coordinate. - * - * @param {goog.math.IRect|goog.math.Coordinate} another The rectangle or - * coordinate to test for containment. - * @return {boolean} Whether this rectangle contains given rectangle or - * coordinate. - */ -goog.math.Rect.prototype.contains = function(another) { - if (another instanceof goog.math.Coordinate) { - return another.x >= this.left && another.x <= this.left + this.width && - another.y >= this.top && another.y <= this.top + this.height; - } else { // (another instanceof goog.math.IRect) - return this.left <= another.left && - this.left + this.width >= another.left + another.width && - this.top <= another.top && - this.top + this.height >= another.top + another.height; - } -}; - - -/** - * @param {!goog.math.Coordinate} point A coordinate. - * @return {number} The squared distance between the point and the closest - * point inside the rectangle. Returns 0 if the point is inside the - * rectangle. - */ -goog.math.Rect.prototype.squaredDistance = function(point) { - var dx = point.x < this.left ? - this.left - point.x : - Math.max(point.x - (this.left + this.width), 0); - var dy = point.y < this.top ? this.top - point.y : - Math.max(point.y - (this.top + this.height), 0); - return dx * dx + dy * dy; -}; - - -/** - * @param {!goog.math.Coordinate} point A coordinate. - * @return {number} The distance between the point and the closest point - * inside the rectangle. Returns 0 if the point is inside the rectangle. - */ -goog.math.Rect.prototype.distance = function(point) { - return Math.sqrt(this.squaredDistance(point)); -}; - - -/** - * @return {!goog.math.Size} The size of this rectangle. - */ -goog.math.Rect.prototype.getSize = function() { - return new goog.math.Size(this.width, this.height); -}; - - -/** - * @return {!goog.math.Coordinate} A new coordinate for the top-left corner of - * the rectangle. - */ -goog.math.Rect.prototype.getTopLeft = function() { - return new goog.math.Coordinate(this.left, this.top); -}; - - -/** - * @return {!goog.math.Coordinate} A new coordinate for the center of the - * rectangle. - */ -goog.math.Rect.prototype.getCenter = function() { - return new goog.math.Coordinate( - this.left + this.width / 2, this.top + this.height / 2); -}; - - -/** - * @return {!goog.math.Coordinate} A new coordinate for the bottom-right corner - * of the rectangle. - */ -goog.math.Rect.prototype.getBottomRight = function() { - return new goog.math.Coordinate( - this.left + this.width, this.top + this.height); -}; - - -/** - * Rounds the fields to the next larger integer values. - * @return {!goog.math.Rect} This rectangle with ceil'd fields. - */ -goog.math.Rect.prototype.ceil = function() { - this.left = Math.ceil(this.left); - this.top = Math.ceil(this.top); - this.width = Math.ceil(this.width); - this.height = Math.ceil(this.height); - return this; -}; - - -/** - * Rounds the fields to the next smaller integer values. - * @return {!goog.math.Rect} This rectangle with floored fields. - */ -goog.math.Rect.prototype.floor = function() { - this.left = Math.floor(this.left); - this.top = Math.floor(this.top); - this.width = Math.floor(this.width); - this.height = Math.floor(this.height); - return this; -}; - - -/** - * Rounds the fields to nearest integer values. - * @return {!goog.math.Rect} This rectangle with rounded fields. - */ -goog.math.Rect.prototype.round = function() { - this.left = Math.round(this.left); - this.top = Math.round(this.top); - this.width = Math.round(this.width); - this.height = Math.round(this.height); - return this; -}; - - -/** - * Translates this rectangle by the given offsets. If a - * {@code goog.math.Coordinate} is given, then the left and top values are - * translated by the coordinate's x and y values. Otherwise, top and left are - * translated by {@code tx} and {@code opt_ty} respectively. - * @param {number|goog.math.Coordinate} tx The value to translate left by or the - * the coordinate to translate this rect by. - * @param {number=} opt_ty The value to translate top by. - * @return {!goog.math.Rect} This rectangle after translating. - */ -goog.math.Rect.prototype.translate = function(tx, opt_ty) { - if (tx instanceof goog.math.Coordinate) { - this.left += tx.x; - this.top += tx.y; - } else { - this.left += goog.asserts.assertNumber(tx); - if (goog.isNumber(opt_ty)) { - this.top += opt_ty; - } - } - return this; -}; - - -/** - * Scales this rectangle by the given scale factors. The left and width values - * are scaled by {@code sx} and the top and height values are scaled by - * {@code opt_sy}. If {@code opt_sy} is not given, then all fields are scaled - * by {@code sx}. - * @param {number} sx The scale factor to use for the x dimension. - * @param {number=} opt_sy The scale factor to use for the y dimension. - * @return {!goog.math.Rect} This rectangle after scaling. - */ -goog.math.Rect.prototype.scale = function(sx, opt_sy) { - var sy = goog.isNumber(opt_sy) ? opt_sy : sx; - this.left *= sx; - this.width *= sx; - this.top *= sy; - this.height *= sy; - return this; -};
diff --git a/third_party/ink/closure/math/size.js b/third_party/ink/closure/math/size.js deleted file mode 100644 index b539d0c..0000000 --- a/third_party/ink/closure/math/size.js +++ /dev/null
@@ -1,228 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A utility class for representing two-dimensional sizes. - * @author pupius@google.com (Dan Pupius) - * @author brenneman@google.com (Shawn Brenneman) - */ - - -goog.provide('goog.math.Size'); - - - -/** - * Class for representing sizes consisting of a width and height. Undefined - * width and height support is deprecated and results in compiler warning. - * @param {number} width Width. - * @param {number} height Height. - * @struct - * @constructor - */ -goog.math.Size = function(width, height) { - /** - * Width - * @type {number} - */ - this.width = width; - - /** - * Height - * @type {number} - */ - this.height = height; -}; - - -/** - * Compares sizes for equality. - * @param {goog.math.Size} a A Size. - * @param {goog.math.Size} b A Size. - * @return {boolean} True iff the sizes have equal widths and equal - * heights, or if both are null. - */ -goog.math.Size.equals = function(a, b) { - if (a == b) { - return true; - } - if (!a || !b) { - return false; - } - return a.width == b.width && a.height == b.height; -}; - - -/** - * @return {!goog.math.Size} A new copy of the Size. - */ -goog.math.Size.prototype.clone = function() { - return new goog.math.Size(this.width, this.height); -}; - - -if (goog.DEBUG) { - /** - * Returns a nice string representing size. - * @return {string} In the form (50 x 73). - * @override - */ - goog.math.Size.prototype.toString = function() { - return '(' + this.width + ' x ' + this.height + ')'; - }; -} - - -/** - * @return {number} The longer of the two dimensions in the size. - */ -goog.math.Size.prototype.getLongest = function() { - return Math.max(this.width, this.height); -}; - - -/** - * @return {number} The shorter of the two dimensions in the size. - */ -goog.math.Size.prototype.getShortest = function() { - return Math.min(this.width, this.height); -}; - - -/** - * @return {number} The area of the size (width * height). - */ -goog.math.Size.prototype.area = function() { - return this.width * this.height; -}; - - -/** - * @return {number} The perimeter of the size (width + height) * 2. - */ -goog.math.Size.prototype.perimeter = function() { - return (this.width + this.height) * 2; -}; - - -/** - * @return {number} The ratio of the size's width to its height. - */ -goog.math.Size.prototype.aspectRatio = function() { - return this.width / this.height; -}; - - -/** - * @return {boolean} True if the size has zero area, false if both dimensions - * are non-zero numbers. - */ -goog.math.Size.prototype.isEmpty = function() { - return !this.area(); -}; - - -/** - * Clamps the width and height parameters upward to integer values. - * @return {!goog.math.Size} This size with ceil'd components. - */ -goog.math.Size.prototype.ceil = function() { - this.width = Math.ceil(this.width); - this.height = Math.ceil(this.height); - return this; -}; - - -/** - * @param {!goog.math.Size} target The target size. - * @return {boolean} True if this Size is the same size or smaller than the - * target size in both dimensions. - */ -goog.math.Size.prototype.fitsInside = function(target) { - return this.width <= target.width && this.height <= target.height; -}; - - -/** - * Clamps the width and height parameters downward to integer values. - * @return {!goog.math.Size} This size with floored components. - */ -goog.math.Size.prototype.floor = function() { - this.width = Math.floor(this.width); - this.height = Math.floor(this.height); - return this; -}; - - -/** - * Rounds the width and height parameters to integer values. - * @return {!goog.math.Size} This size with rounded components. - */ -goog.math.Size.prototype.round = function() { - this.width = Math.round(this.width); - this.height = Math.round(this.height); - return this; -}; - - -/** - * Scales this size by the given scale factors. The width and height are scaled - * by {@code sx} and {@code opt_sy} respectively. If {@code opt_sy} is not - * given, then {@code sx} is used for both the width and height. - * @param {number} sx The scale factor to use for the width. - * @param {number=} opt_sy The scale factor to use for the height. - * @return {!goog.math.Size} This Size object after scaling. - */ -goog.math.Size.prototype.scale = function(sx, opt_sy) { - var sy = goog.isNumber(opt_sy) ? opt_sy : sx; - this.width *= sx; - this.height *= sy; - return this; -}; - - -/** - * Uniformly scales the size to perfectly cover the dimensions of a given size. - * If the size is already larger than the target, it will be scaled down to the - * minimum size at which it still covers the entire target. The original aspect - * ratio will be preserved. - * - * This function assumes that both Sizes contain strictly positive dimensions. - * @param {!goog.math.Size} target The target size. - * @return {!goog.math.Size} This Size object, after optional scaling. - */ -goog.math.Size.prototype.scaleToCover = function(target) { - var s = this.aspectRatio() <= target.aspectRatio() ? - target.width / this.width : - target.height / this.height; - - return this.scale(s); -}; - - -/** - * Uniformly scales the size to fit inside the dimensions of a given size. The - * original aspect ratio will be preserved. - * - * This function assumes that both Sizes contain strictly positive dimensions. - * @param {!goog.math.Size} target The target size. - * @return {!goog.math.Size} This Size object, after optional scaling. - */ -goog.math.Size.prototype.scaleToFit = function(target) { - var s = this.aspectRatio() > target.aspectRatio() ? - target.width / this.width : - target.height / this.height; - - return this.scale(s); -};
diff --git a/third_party/ink/closure/object/object.js b/third_party/ink/closure/object/object.js deleted file mode 100644 index 286d24e..0000000 --- a/third_party/ink/closure/object/object.js +++ /dev/null
@@ -1,751 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for manipulating objects/maps/hashes. - * @author pupius@google.com (Daniel Pupius) - * @author arv@google.com (Erik Arvidsson) - * @author pallosp@google.com (Peter Pallos) - */ - -goog.provide('goog.object'); - - -/** - * Whether two values are not observably distinguishable. This - * correctly detects that 0 is not the same as -0 and two NaNs are - * practically equivalent. - * - * The implementation is as suggested by harmony:egal proposal. - * - * @param {*} v The first value to compare. - * @param {*} v2 The second value to compare. - * @return {boolean} Whether two values are not observably distinguishable. - * @see http://wiki.ecmascript.org/doku.php?id=harmony:egal - */ -goog.object.is = function(v, v2) { - if (v === v2) { - // 0 === -0, but they are not identical. - // We need the cast because the compiler requires that v2 is a - // number (although 1/v2 works with non-number). We cast to ? to - // stop the compiler from type-checking this statement. - return v !== 0 || 1 / v === 1 / /** @type {?} */ (v2); - } - - // NaN is non-reflexive: NaN !== NaN, although they are identical. - return v !== v && v2 !== v2; -}; - - -/** - * Calls a function for each element in an object/map/hash. - * - * @param {Object<K,V>} obj The object over which to iterate. - * @param {function(this:T,V,?,Object<K,V>):?} f The function to call - * for every element. This function takes 3 arguments (the value, the - * key and the object) and the return value is ignored. - * @param {T=} opt_obj This is used as the 'this' object within f. - * @template T,K,V - */ -goog.object.forEach = function(obj, f, opt_obj) { - for (var key in obj) { - f.call(/** @type {?} */ (opt_obj), obj[key], key, obj); - } -}; - - -/** - * Calls a function for each element in an object/map/hash. If that call returns - * true, adds the element to a new object. - * - * @param {Object<K,V>} obj The object over which to iterate. - * @param {function(this:T,V,?,Object<K,V>):boolean} f The function to call - * for every element. This - * function takes 3 arguments (the value, the key and the object) - * and should return a boolean. If the return value is true the - * element is added to the result object. If it is false the - * element is not included. - * @param {T=} opt_obj This is used as the 'this' object within f. - * @return {!Object<K,V>} a new object in which only elements that passed the - * test are present. - * @template T,K,V - */ -goog.object.filter = function(obj, f, opt_obj) { - var res = {}; - for (var key in obj) { - if (f.call(/** @type {?} */ (opt_obj), obj[key], key, obj)) { - res[key] = obj[key]; - } - } - return res; -}; - - -/** - * For every element in an object/map/hash calls a function and inserts the - * result into a new object. - * - * @param {Object<K,V>} obj The object over which to iterate. - * @param {function(this:T,V,?,Object<K,V>):R} f The function to call - * for every element. This function - * takes 3 arguments (the value, the key and the object) - * and should return something. The result will be inserted - * into a new object. - * @param {T=} opt_obj This is used as the 'this' object within f. - * @return {!Object<K,R>} a new object with the results from f. - * @template T,K,V,R - */ -goog.object.map = function(obj, f, opt_obj) { - var res = {}; - for (var key in obj) { - res[key] = f.call(/** @type {?} */ (opt_obj), obj[key], key, obj); - } - return res; -}; - - -/** - * Calls a function for each element in an object/map/hash. If any - * call returns true, returns true (without checking the rest). If - * all calls return false, returns false. - * - * @param {Object<K,V>} obj The object to check. - * @param {function(this:T,V,?,Object<K,V>):boolean} f The function to - * call for every element. This function - * takes 3 arguments (the value, the key and the object) and should - * return a boolean. - * @param {T=} opt_obj This is used as the 'this' object within f. - * @return {boolean} true if any element passes the test. - * @template T,K,V - */ -goog.object.some = function(obj, f, opt_obj) { - for (var key in obj) { - if (f.call(/** @type {?} */ (opt_obj), obj[key], key, obj)) { - return true; - } - } - return false; -}; - - -/** - * Calls a function for each element in an object/map/hash. If - * all calls return true, returns true. If any call returns false, returns - * false at this point and does not continue to check the remaining elements. - * - * @param {Object<K,V>} obj The object to check. - * @param {?function(this:T,V,?,Object<K,V>):boolean} f The function to - * call for every element. This function - * takes 3 arguments (the value, the key and the object) and should - * return a boolean. - * @param {T=} opt_obj This is used as the 'this' object within f. - * @return {boolean} false if any element fails the test. - * @template T,K,V - */ -goog.object.every = function(obj, f, opt_obj) { - for (var key in obj) { - if (!f.call(/** @type {?} */ (opt_obj), obj[key], key, obj)) { - return false; - } - } - return true; -}; - - -/** - * Returns the number of key-value pairs in the object map. - * - * @param {Object} obj The object for which to get the number of key-value - * pairs. - * @return {number} The number of key-value pairs in the object map. - */ -goog.object.getCount = function(obj) { - var rv = 0; - for (var key in obj) { - rv++; - } - return rv; -}; - - -/** - * Returns one key from the object map, if any exists. - * For map literals the returned key will be the first one in most of the - * browsers (a know exception is Konqueror). - * - * @param {Object} obj The object to pick a key from. - * @return {string|undefined} The key or undefined if the object is empty. - */ -goog.object.getAnyKey = function(obj) { - for (var key in obj) { - return key; - } -}; - - -/** - * Returns one value from the object map, if any exists. - * For map literals the returned value will be the first one in most of the - * browsers (a know exception is Konqueror). - * - * @param {Object<K,V>} obj The object to pick a value from. - * @return {V|undefined} The value or undefined if the object is empty. - * @template K,V - */ -goog.object.getAnyValue = function(obj) { - for (var key in obj) { - return obj[key]; - } -}; - - -/** - * Whether the object/hash/map contains the given object as a value. - * An alias for goog.object.containsValue(obj, val). - * - * @param {Object<K,V>} obj The object in which to look for val. - * @param {V} val The object for which to check. - * @return {boolean} true if val is present. - * @template K,V - */ -goog.object.contains = function(obj, val) { - return goog.object.containsValue(obj, val); -}; - - -/** - * Returns the values of the object/map/hash. - * - * @param {Object<K,V>} obj The object from which to get the values. - * @return {!Array<V>} The values in the object/map/hash. - * @template K,V - */ -goog.object.getValues = function(obj) { - var res = []; - var i = 0; - for (var key in obj) { - res[i++] = obj[key]; - } - return res; -}; - - -/** - * Returns the keys of the object/map/hash. - * - * @param {Object} obj The object from which to get the keys. - * @return {!Array<string>} Array of property keys. - */ -goog.object.getKeys = function(obj) { - var res = []; - var i = 0; - for (var key in obj) { - res[i++] = key; - } - return res; -}; - - -/** - * Get a value from an object multiple levels deep. This is useful for - * pulling values from deeply nested objects, such as JSON responses. - * Example usage: getValueByKeys(jsonObj, 'foo', 'entries', 3) - * - * @param {!Object} obj An object to get the value from. Can be array-like. - * @param {...(string|number|!IArrayLike<number|string>)} - * var_args A number of keys - * (as strings, or numbers, for array-like objects). Can also be - * specified as a single array of keys. - * @return {*} The resulting value. If, at any point, the value for a key - * in the current object is null or undefined, returns undefined. - */ -goog.object.getValueByKeys = function(obj, var_args) { - var isArrayLike = goog.isArrayLike(var_args); - var keys = isArrayLike ? var_args : arguments; - - // Start with the 2nd parameter for the variable parameters syntax. - for (var i = isArrayLike ? 0 : 1; i < keys.length; i++) { - if (obj == null) return undefined; - obj = obj[keys[i]]; - } - - return obj; -}; - - -/** - * Whether the object/map/hash contains the given key. - * - * @param {Object} obj The object in which to look for key. - * @param {?} key The key for which to check. - * @return {boolean} true If the map contains the key. - */ -goog.object.containsKey = function(obj, key) { - return obj !== null && key in obj; -}; - - -/** - * Whether the object/map/hash contains the given value. This is O(n). - * - * @param {Object<K,V>} obj The object in which to look for val. - * @param {V} val The value for which to check. - * @return {boolean} true If the map contains the value. - * @template K,V - */ -goog.object.containsValue = function(obj, val) { - for (var key in obj) { - if (obj[key] == val) { - return true; - } - } - return false; -}; - - -/** - * Searches an object for an element that satisfies the given condition and - * returns its key. - * @param {Object<K,V>} obj The object to search in. - * @param {function(this:T,V,string,Object<K,V>):boolean} f The - * function to call for every element. Takes 3 arguments (the value, - * the key and the object) and should return a boolean. - * @param {T=} opt_this An optional "this" context for the function. - * @return {string|undefined} The key of an element for which the function - * returns true or undefined if no such element is found. - * @template T,K,V - */ -goog.object.findKey = function(obj, f, opt_this) { - for (var key in obj) { - if (f.call(/** @type {?} */ (opt_this), obj[key], key, obj)) { - return key; - } - } - return undefined; -}; - - -/** - * Searches an object for an element that satisfies the given condition and - * returns its value. - * @param {Object<K,V>} obj The object to search in. - * @param {function(this:T,V,string,Object<K,V>):boolean} f The function - * to call for every element. Takes 3 arguments (the value, the key - * and the object) and should return a boolean. - * @param {T=} opt_this An optional "this" context for the function. - * @return {V} The value of an element for which the function returns true or - * undefined if no such element is found. - * @template T,K,V - */ -goog.object.findValue = function(obj, f, opt_this) { - var key = goog.object.findKey(obj, f, opt_this); - return key && obj[key]; -}; - - -/** - * Whether the object/map/hash is empty. - * - * @param {Object} obj The object to test. - * @return {boolean} true if obj is empty. - */ -goog.object.isEmpty = function(obj) { - for (var key in obj) { - return false; - } - return true; -}; - - -/** - * Removes all key value pairs from the object/map/hash. - * - * @param {Object} obj The object to clear. - */ -goog.object.clear = function(obj) { - for (var i in obj) { - delete obj[i]; - } -}; - - -/** - * Removes a key-value pair based on the key. - * - * @param {Object} obj The object from which to remove the key. - * @param {?} key The key to remove. - * @return {boolean} Whether an element was removed. - */ -goog.object.remove = function(obj, key) { - var rv; - if (rv = key in /** @type {!Object} */ (obj)) { - delete obj[key]; - } - return rv; -}; - - -/** - * Adds a key-value pair to the object. Throws an exception if the key is - * already in use. Use set if you want to change an existing pair. - * - * @param {Object<K,V>} obj The object to which to add the key-value pair. - * @param {string} key The key to add. - * @param {V} val The value to add. - * @template K,V - */ -goog.object.add = function(obj, key, val) { - if (obj !== null && key in obj) { - throw new Error('The object already contains the key "' + key + '"'); - } - goog.object.set(obj, key, val); -}; - - -/** - * Returns the value for the given key. - * - * @param {Object<K,V>} obj The object from which to get the value. - * @param {string} key The key for which to get the value. - * @param {R=} opt_val The value to return if no item is found for the given - * key (default is undefined). - * @return {V|R|undefined} The value for the given key. - * @template K,V,R - */ -goog.object.get = function(obj, key, opt_val) { - if (obj !== null && key in obj) { - return obj[key]; - } - return opt_val; -}; - - -/** - * Adds a key-value pair to the object/map/hash. - * - * @param {Object<K,V>} obj The object to which to add the key-value pair. - * @param {string} key The key to add. - * @param {V} value The value to add. - * @template K,V - */ -goog.object.set = function(obj, key, value) { - obj[key] = value; -}; - - -/** - * Adds a key-value pair to the object/map/hash if it doesn't exist yet. - * - * @param {Object<K,V>} obj The object to which to add the key-value pair. - * @param {string} key The key to add. - * @param {V} value The value to add if the key wasn't present. - * @return {V} The value of the entry at the end of the function. - * @template K,V - */ -goog.object.setIfUndefined = function(obj, key, value) { - return key in /** @type {!Object} */ (obj) ? obj[key] : (obj[key] = value); -}; - - -/** - * Sets a key and value to an object if the key is not set. The value will be - * the return value of the given function. If the key already exists, the - * object will not be changed and the function will not be called (the function - * will be lazily evaluated -- only called if necessary). - * - * This function is particularly useful for use with a map used a as a cache. - * - * @param {!Object<K,V>} obj The object to which to add the key-value pair. - * @param {string} key The key to add. - * @param {function():V} f The value to add if the key wasn't present. - * @return {V} The value of the entry at the end of the function. - * @template K,V - */ -goog.object.setWithReturnValueIfNotSet = function(obj, key, f) { - if (key in obj) { - return obj[key]; - } - - var val = f(); - obj[key] = val; - return val; -}; - - -/** - * Compares two objects for equality using === on the values. - * - * @param {!Object<K,V>} a - * @param {!Object<K,V>} b - * @return {boolean} - * @template K,V - */ -goog.object.equals = function(a, b) { - for (var k in a) { - if (!(k in b) || a[k] !== b[k]) { - return false; - } - } - for (var k in b) { - if (!(k in a)) { - return false; - } - } - return true; -}; - - -/** - * Returns a shallow clone of the object. - * - * @param {Object<K,V>} obj Object to clone. - * @return {!Object<K,V>} Clone of the input object. - * @template K,V - */ -goog.object.clone = function(obj) { - // We cannot use the prototype trick because a lot of methods depend on where - // the actual key is set. - - var res = {}; - for (var key in obj) { - res[key] = obj[key]; - } - return res; - // We could also use goog.mixin but I wanted this to be independent from that. -}; - - -/** - * Clones a value. The input may be an Object, Array, or basic type. Objects and - * arrays will be cloned recursively. - * - * WARNINGS: - * <code>goog.object.unsafeClone</code> does not detect reference loops. Objects - * that refer to themselves will cause infinite recursion. - * - * <code>goog.object.unsafeClone</code> is unaware of unique identifiers, and - * copies UIDs created by <code>getUid</code> into cloned results. - * - * @param {T} obj The value to clone. - * @return {T} A clone of the input value. - * @template T - */ -goog.object.unsafeClone = function(obj) { - var type = goog.typeOf(obj); - if (type == 'object' || type == 'array') { - if (goog.isFunction(obj.clone)) { - return obj.clone(); - } - var clone = type == 'array' ? [] : {}; - for (var key in obj) { - clone[key] = goog.object.unsafeClone(obj[key]); - } - return clone; - } - - return obj; -}; - - -/** - * Returns a new object in which all the keys and values are interchanged - * (keys become values and values become keys). If multiple keys map to the - * same value, the chosen transposed value is implementation-dependent. - * - * @param {Object} obj The object to transpose. - * @return {!Object} The transposed object. - */ -goog.object.transpose = function(obj) { - var transposed = {}; - for (var key in obj) { - transposed[obj[key]] = key; - } - return transposed; -}; - - -/** - * The names of the fields that are defined on Object.prototype. - * @type {Array<string>} - * @private - */ -goog.object.PROTOTYPE_FIELDS_ = [ - 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', - 'toLocaleString', 'toString', 'valueOf' -]; - - -/** - * Extends an object with another object. - * This operates 'in-place'; it does not create a new Object. - * - * Example: - * var o = {}; - * goog.object.extend(o, {a: 0, b: 1}); - * o; // {a: 0, b: 1} - * goog.object.extend(o, {b: 2, c: 3}); - * o; // {a: 0, b: 2, c: 3} - * - * @param {Object} target The object to modify. Existing properties will be - * overwritten if they are also present in one of the objects in - * {@code var_args}. - * @param {...Object} var_args The objects from which values will be copied. - */ -goog.object.extend = function(target, var_args) { - var key, source; - for (var i = 1; i < arguments.length; i++) { - source = arguments[i]; - for (key in source) { - target[key] = source[key]; - } - - // For IE the for-in-loop does not contain any properties that are not - // enumerable on the prototype object (for example isPrototypeOf from - // Object.prototype) and it will also not include 'replace' on objects that - // extend String and change 'replace' (not that it is common for anyone to - // extend anything except Object). - - for (var j = 0; j < goog.object.PROTOTYPE_FIELDS_.length; j++) { - key = goog.object.PROTOTYPE_FIELDS_[j]; - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - } -}; - - -/** - * Creates a new object built from the key-value pairs provided as arguments. - * @param {...*} var_args If only one argument is provided and it is an array - * then this is used as the arguments, otherwise even arguments are used as - * the property names and odd arguments are used as the property values. - * @return {!Object} The new object. - * @throws {Error} If there are uneven number of arguments or there is only one - * non array argument. - */ -goog.object.create = function(var_args) { - var argLength = arguments.length; - if (argLength == 1 && goog.isArray(arguments[0])) { - return goog.object.create.apply(null, arguments[0]); - } - - if (argLength % 2) { - throw new Error('Uneven number of arguments'); - } - - var rv = {}; - for (var i = 0; i < argLength; i += 2) { - rv[arguments[i]] = arguments[i + 1]; - } - return rv; -}; - - -/** - * Creates a new object where the property names come from the arguments but - * the value is always set to true - * @param {...*} var_args If only one argument is provided and it is an array - * then this is used as the arguments, otherwise the arguments are used - * as the property names. - * @return {!Object} The new object. - */ -goog.object.createSet = function(var_args) { - var argLength = arguments.length; - if (argLength == 1 && goog.isArray(arguments[0])) { - return goog.object.createSet.apply(null, arguments[0]); - } - - var rv = {}; - for (var i = 0; i < argLength; i++) { - rv[arguments[i]] = true; - } - return rv; -}; - - -/** - * Creates an immutable view of the underlying object, if the browser - * supports immutable objects. - * - * In default mode, writes to this view will fail silently. In strict mode, - * they will throw an error. - * - * @param {!Object<K,V>} obj An object. - * @return {!Object<K,V>} An immutable view of that object, or the - * original object if this browser does not support immutables. - * @template K,V - */ -goog.object.createImmutableView = function(obj) { - var result = obj; - if (Object.isFrozen && !Object.isFrozen(obj)) { - result = Object.create(obj); - Object.freeze(result); - } - return result; -}; - - -/** - * @param {!Object} obj An object. - * @return {boolean} Whether this is an immutable view of the object. - */ -goog.object.isImmutableView = function(obj) { - return !!Object.isFrozen && Object.isFrozen(obj); -}; - - -/** - * Get all properties names on a given Object regardless of enumerability. - * - * <p> If the browser does not support {@code Object.getOwnPropertyNames} nor - * {@code Object.getPrototypeOf} then this is equivalent to using {@code - * goog.object.getKeys} - * - * @param {?Object} obj The object to get the properties of. - * @param {boolean=} opt_includeObjectPrototype Whether properties defined on - * {@code Object.prototype} should be included in the result. - * @param {boolean=} opt_includeFunctionPrototype Whether properties defined on - * {@code Function.prototype} should be included in the result. - * @return {!Array<string>} - * @public - */ -goog.object.getAllPropertyNames = function( - obj, opt_includeObjectPrototype, opt_includeFunctionPrototype) { - if (!obj) { - return []; - } - - // Naively use a for..in loop to get the property names if the browser doesn't - // support any other APIs for getting it. - if (!Object.getOwnPropertyNames || !Object.getPrototypeOf) { - return goog.object.getKeys(obj); - } - - var visitedSet = {}; - - // Traverse the prototype chain and add all properties to the visited set. - var proto = obj; - while (proto && - (proto !== Object.prototype || !!opt_includeObjectPrototype) && - (proto !== Function.prototype || !!opt_includeFunctionPrototype)) { - var names = Object.getOwnPropertyNames(proto); - for (var i = 0; i < names.length; i++) { - visitedSet[names[i]] = true; - } - proto = Object.getPrototypeOf(proto); - } - - return goog.object.getKeys(visitedSet); -};
diff --git a/third_party/ink/closure/proto2/descriptor.js b/third_party/ink/closure/proto2/descriptor.js deleted file mode 100644 index 4abc3a35..0000000 --- a/third_party/ink/closure/proto2/descriptor.js +++ /dev/null
@@ -1,202 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Protocol Buffer (Message) Descriptor class. - * @author jschorr@google.com (Joseph Schorr) - */ - -goog.provide('goog.proto2.Descriptor'); -goog.provide('goog.proto2.Metadata'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.object'); -goog.require('goog.string'); - - -/** - * @typedef {{name: (string|undefined), - * fullName: (string|undefined), - * containingType: (goog.proto2.Message|undefined)}} - */ -goog.proto2.Metadata; - - - -/** - * A class which describes a Protocol Buffer 2 Message. - * - * @param {function(new:goog.proto2.Message)} messageType Constructor for - * the message class that this descriptor describes. - * @param {!goog.proto2.Metadata} metadata The metadata about the message that - * will be used to construct this descriptor. - * @param {Array<!goog.proto2.FieldDescriptor>} fields The fields of the - * message described by this descriptor. - * - * @constructor - * @final - */ -goog.proto2.Descriptor = function(messageType, metadata, fields) { - - /** - * @type {function(new:goog.proto2.Message)} - * @private - */ - this.messageType_ = messageType; - - /** - * @type {?string} - * @private - */ - this.name_ = metadata.name || null; - - /** - * @type {?string} - * @private - */ - this.fullName_ = metadata.fullName || null; - - /** - * @type {goog.proto2.Message|undefined} - * @private - */ - this.containingType_ = metadata.containingType; - - /** - * The fields of the message described by this descriptor. - * @type {!Object<number, !goog.proto2.FieldDescriptor>} - * @private - */ - this.fields_ = {}; - - for (var i = 0; i < fields.length; i++) { - var field = fields[i]; - this.fields_[field.getTag()] = field; - } -}; - - -/** - * Returns the name of the message, if any. - * - * @return {?string} The name. - */ -goog.proto2.Descriptor.prototype.getName = function() { - return this.name_; -}; - - -/** - * Returns the full name of the message, if any. - * - * @return {?string} The name. - */ -goog.proto2.Descriptor.prototype.getFullName = function() { - return this.fullName_; -}; - - -/** - * Returns the descriptor of the containing message type or null if none. - * - * @return {goog.proto2.Descriptor} The descriptor. - */ -goog.proto2.Descriptor.prototype.getContainingType = function() { - if (!this.containingType_) { - return null; - } - - return this.containingType_.getDescriptor(); -}; - - -/** - * Returns the fields in the message described by this descriptor ordered by - * tag. - * - * @return {!Array<!goog.proto2.FieldDescriptor>} The array of field - * descriptors. - */ -goog.proto2.Descriptor.prototype.getFields = function() { - /** - * @param {!goog.proto2.FieldDescriptor} fieldA First field. - * @param {!goog.proto2.FieldDescriptor} fieldB Second field. - * @return {number} Negative if fieldA's tag number is smaller, positive - * if greater, zero if the same. - */ - function tagComparator(fieldA, fieldB) { - return fieldA.getTag() - fieldB.getTag(); - } - - var fields = goog.object.getValues(this.fields_); - goog.array.sort(fields, tagComparator); - - return fields; -}; - - -/** - * Returns the fields in the message as a key/value map, where the key is - * the tag number of the field. DO NOT MODIFY THE RETURNED OBJECT. We return - * the actual, internal, fields map for performance reasons, and changing the - * map can result in undefined behavior of this library. - * - * @return {!Object<number, !goog.proto2.FieldDescriptor>} The field map. - */ -goog.proto2.Descriptor.prototype.getFieldsMap = function() { - return this.fields_; -}; - - -/** - * Returns the field matching the given name, if any. Note that - * this method searches over the *original* name of the field, - * not the camelCase version. - * - * @param {string} name The field name for which to search. - * - * @return {goog.proto2.FieldDescriptor} The field found, if any. - */ -goog.proto2.Descriptor.prototype.findFieldByName = function(name) { - var valueFound = goog.object.findValue( - this.fields_, - function(field, key, obj) { return field.getName() == name; }); - - return /** @type {goog.proto2.FieldDescriptor} */ (valueFound) || null; -}; - - -/** - * Returns the field matching the given tag number, if any. - * - * @param {number|string} tag The field tag number for which to search. - * - * @return {goog.proto2.FieldDescriptor} The field found, if any. - */ -goog.proto2.Descriptor.prototype.findFieldByTag = function(tag) { - goog.asserts.assert(goog.string.isNumeric(tag)); - return this.fields_[parseInt(tag, 10)] || null; -}; - - -/** - * Creates an instance of the message type that this descriptor - * describes. - * - * @return {!goog.proto2.Message} The instance of the message. - */ -goog.proto2.Descriptor.prototype.createMessageInstance = function() { - return new this.messageType_; -};
diff --git a/third_party/ink/closure/proto2/fielddescriptor.js b/third_party/ink/closure/proto2/fielddescriptor.js deleted file mode 100644 index 7fbef98..0000000 --- a/third_party/ink/closure/proto2/fielddescriptor.js +++ /dev/null
@@ -1,313 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Protocol Buffer Field Descriptor class. - * @author jschorr@google.com (Joseph Schorr) - */ - -goog.provide('goog.proto2.FieldDescriptor'); - -goog.require('goog.asserts'); -goog.require('goog.string'); - - - -/** - * A class which describes a field in a Protocol Buffer 2 Message. - * - * @param {function(new:goog.proto2.Message)} messageType Constructor for the - * message class to which the field described by this class belongs. - * @param {number|string} tag The field's tag index. - * @param {Object} metadata The metadata about this field that will be used - * to construct this descriptor. - * - * @constructor - * @final - */ -goog.proto2.FieldDescriptor = function(messageType, tag, metadata) { - /** - * The message type that contains the field that this - * descriptor describes. - * @private {function(new:goog.proto2.Message)} - */ - this.parent_ = messageType; - - // Ensure that the tag is numeric. - goog.asserts.assert(goog.string.isNumeric(tag)); - - /** - * The field's tag number. - * @private {number} - */ - this.tag_ = /** @type {number} */ (tag); - - /** - * The field's name. - * @private {string} - */ - this.name_ = metadata.name; - - /** @type {goog.proto2.FieldDescriptor.FieldType} */ - metadata.fieldType; - - /** @type {*} */ - metadata.repeated; - - /** @type {*} */ - metadata.required; - - /** @type {*} */ - metadata.packed; - - /** - * If true, this field is a packed field. - * @private {boolean} - */ - this.isPacked_ = !!metadata.packed; - - /** - * If true, this field is a repeating field. - * @private {boolean} - */ - this.isRepeated_ = !!metadata.repeated; - - /** - * If true, this field is required. - * @private {boolean} - */ - this.isRequired_ = !!metadata.required; - - /** - * The field type of this field. - * @private {goog.proto2.FieldDescriptor.FieldType} - */ - this.fieldType_ = metadata.fieldType; - - /** - * If this field is a primitive: The native (ECMAScript) type of this field. - * If an enumeration: The enumeration object. - * If a message or group field: The Message function. - * @private {Function} - */ - this.nativeType_ = metadata.type; - - /** - * Is it permissible on deserialization to convert between numbers and - * well-formed strings? Is true for 64-bit integral field types and float and - * double types, false for all other field types. - * @private {boolean} - */ - this.deserializationConversionPermitted_ = false; - - switch (this.fieldType_) { - case goog.proto2.FieldDescriptor.FieldType.INT64: - case goog.proto2.FieldDescriptor.FieldType.UINT64: - case goog.proto2.FieldDescriptor.FieldType.FIXED64: - case goog.proto2.FieldDescriptor.FieldType.SFIXED64: - case goog.proto2.FieldDescriptor.FieldType.SINT64: - case goog.proto2.FieldDescriptor.FieldType.FLOAT: - case goog.proto2.FieldDescriptor.FieldType.DOUBLE: - this.deserializationConversionPermitted_ = true; - break; - } - - /** - * The default value of this field, if different from the default, default - * value. - * @private {*} - */ - this.defaultValue_ = metadata.defaultValue; -}; - - -/** - * An enumeration defining the possible field types. - * Should be a mirror of that defined in descriptor.h. - * - * @enum {number} - */ -goog.proto2.FieldDescriptor.FieldType = { - DOUBLE: 1, - FLOAT: 2, - INT64: 3, - UINT64: 4, - INT32: 5, - FIXED64: 6, - FIXED32: 7, - BOOL: 8, - STRING: 9, - GROUP: 10, - MESSAGE: 11, - BYTES: 12, - UINT32: 13, - ENUM: 14, - SFIXED32: 15, - SFIXED64: 16, - SINT32: 17, - SINT64: 18 -}; - - -/** - * Returns the tag of the field that this descriptor represents. - * - * @return {number} The tag number. - */ -goog.proto2.FieldDescriptor.prototype.getTag = function() { - return this.tag_; -}; - - -/** - * Returns the descriptor describing the message that defined this field. - * @return {!goog.proto2.Descriptor} The descriptor. - */ -goog.proto2.FieldDescriptor.prototype.getContainingType = function() { - // Generated JS proto_library messages have getDescriptor() method which can - // be called with or without an instance. - return this.parent_.prototype.getDescriptor(); -}; - - -/** - * Returns the name of the field that this descriptor represents. - * @return {string} The name. - */ -goog.proto2.FieldDescriptor.prototype.getName = function() { - return this.name_; -}; - - -/** - * Returns the default value of this field. - * @return {*} The default value. - */ -goog.proto2.FieldDescriptor.prototype.getDefaultValue = function() { - if (this.defaultValue_ === undefined) { - // Set the default value based on a new instance of the native type. - // This will be (0, false, "") for (number, boolean, string) and will - // be a new instance of a group/message if the field is a message type. - var nativeType = this.nativeType_; - if (nativeType === Boolean) { - this.defaultValue_ = false; - } else if (nativeType === Number) { - this.defaultValue_ = 0; - } else if (nativeType === String) { - if (this.deserializationConversionPermitted_) { - // This field is a 64 bit integer represented as a string. - this.defaultValue_ = '0'; - } else { - this.defaultValue_ = ''; - } - } else { - return new nativeType; - } - } - - return this.defaultValue_; -}; - - -/** - * Returns the field type of the field described by this descriptor. - * @return {goog.proto2.FieldDescriptor.FieldType} The field type. - */ -goog.proto2.FieldDescriptor.prototype.getFieldType = function() { - return this.fieldType_; -}; - - -/** - * Returns the native (i.e. ECMAScript) type of the field described by this - * descriptor. - * - * @return {Object} The native type. - */ -goog.proto2.FieldDescriptor.prototype.getNativeType = function() { - return this.nativeType_; -}; - - -/** - * Returns true if simple conversions between numbers and strings are permitted - * during deserialization for this field. - * - * @return {boolean} Whether conversion is permitted. - */ -goog.proto2.FieldDescriptor.prototype.deserializationConversionPermitted = - function() { - return this.deserializationConversionPermitted_; -}; - - -/** - * Returns the descriptor of the message type of this field. Only valid - * for fields of type GROUP and MESSAGE. - * - * @return {!goog.proto2.Descriptor} The message descriptor. - */ -goog.proto2.FieldDescriptor.prototype.getFieldMessageType = function() { - // Generated JS proto_library messages have getDescriptor() method which can - // be called with or without an instance. - var messageClass = - /** @type {function(new:goog.proto2.Message)} */ (this.nativeType_); - return messageClass.prototype.getDescriptor(); -}; - - -/** - * @return {boolean} True if the field stores composite data or repeated - * composite data (message or group). - */ -goog.proto2.FieldDescriptor.prototype.isCompositeType = function() { - return this.fieldType_ == goog.proto2.FieldDescriptor.FieldType.MESSAGE || - this.fieldType_ == goog.proto2.FieldDescriptor.FieldType.GROUP; -}; - - -/** - * Returns whether the field described by this descriptor is packed. - * @return {boolean} Whether the field is packed. - */ -goog.proto2.FieldDescriptor.prototype.isPacked = function() { - return this.isPacked_; -}; - - -/** - * Returns whether the field described by this descriptor is repeating. - * @return {boolean} Whether the field is repeated. - */ -goog.proto2.FieldDescriptor.prototype.isRepeated = function() { - return this.isRepeated_; -}; - - -/** - * Returns whether the field described by this descriptor is required. - * @return {boolean} Whether the field is required. - */ -goog.proto2.FieldDescriptor.prototype.isRequired = function() { - return this.isRequired_; -}; - - -/** - * Returns whether the field described by this descriptor is optional. - * @return {boolean} Whether the field is optional. - */ -goog.proto2.FieldDescriptor.prototype.isOptional = function() { - return !this.isRepeated_ && !this.isRequired_; -};
diff --git a/third_party/ink/closure/proto2/message.js b/third_party/ink/closure/proto2/message.js deleted file mode 100644 index 0315680..0000000 --- a/third_party/ink/closure/proto2/message.js +++ /dev/null
@@ -1,733 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Protocol Buffer Message base class. - * @author jschorr@google.com (Joseph Schorr) - * @author pallosp@google.com (Peter Pallos) - * @suppress {unusedPrivateMembers} For descriptor_ declaration. - */ - -goog.provide('goog.proto2.Message'); - -goog.require('goog.asserts'); -goog.require('goog.proto2.Descriptor'); -goog.require('goog.proto2.FieldDescriptor'); - -goog.forwardDeclare('goog.proto2.LazyDeserializer'); // circular reference - - - -/** - * Abstract base class for all Protocol Buffer 2 messages. It will be - * subclassed in the code generated by the Protocol Compiler. Any other - * subclasses are prohibited. - * @constructor - */ -goog.proto2.Message = function() { - /** - * Stores the field values in this message. Keyed by the tag of the fields. - * @type {!Object} - * @private - */ - this.values_ = {}; - - /** - * Stores the field information (i.e. metadata) about this message. - * @type {Object<number, !goog.proto2.FieldDescriptor>} - * @private - */ - this.fields_ = this.getDescriptor().getFieldsMap(); - - /** - * The lazy deserializer for this message instance, if any. - * @type {goog.proto2.LazyDeserializer} - * @private - */ - this.lazyDeserializer_ = null; - - /** - * A map of those fields deserialized, from tag number to their deserialized - * value. - * @type {Object} - * @private - */ - this.deserializedFields_ = null; -}; - - -/** - * An enumeration defining the possible field types. - * Should be a mirror of that defined in descriptor.h. - * - * TODO(sra): Remove this alias. The code generator generates code that - * references this enum, so it needs to exist until the code generator is - * changed. The enum was moved to from Message to FieldDescriptor to avoid a - * dependency cycle. - * - * Use goog.proto2.FieldDescriptor.FieldType instead. - * - * @enum {number} - */ -goog.proto2.Message.FieldType = { - DOUBLE: 1, - FLOAT: 2, - INT64: 3, - UINT64: 4, - INT32: 5, - FIXED64: 6, - FIXED32: 7, - BOOL: 8, - STRING: 9, - GROUP: 10, - MESSAGE: 11, - BYTES: 12, - UINT32: 13, - ENUM: 14, - SFIXED32: 15, - SFIXED64: 16, - SINT32: 17, - SINT64: 18 -}; - - -/** - * All instances of goog.proto2.Message should have a static descriptor_ - * property. The Descriptor will be deserialized lazily in the getDescriptor() - * method. - * - * This declaration is just here for documentation purposes. - * goog.proto2.Message does not have its own descriptor. - * - * @type {undefined} - * @private - */ -goog.proto2.Message.descriptor_; - - -/** - * Initializes the message with a lazy deserializer and its associated data. - * This method should be called by internal methods ONLY. - * - * @param {goog.proto2.LazyDeserializer} deserializer The lazy deserializer to - * use to decode the data on the fly. - * - * @param {?} data The data to decode/deserialize. - */ -goog.proto2.Message.prototype.initializeForLazyDeserializer = function( - deserializer, data) { - - this.lazyDeserializer_ = deserializer; - this.values_ = data; - this.deserializedFields_ = {}; -}; - - -/** - * Sets the value of an unknown field, by tag. - * - * @param {number} tag The tag of an unknown field (must be >= 1). - * @param {*} value The value for that unknown field. - */ -goog.proto2.Message.prototype.setUnknown = function(tag, value) { - goog.asserts.assert( - !this.fields_[tag], 'Field is not unknown in this message'); - goog.asserts.assert( - tag >= 1, 'Tag ' + tag + ' has value "' + value + '" in descriptor ' + - this.getDescriptor().getName()); - - goog.asserts.assert(value !== null, 'Value cannot be null'); - - this.values_[tag] = value; - if (this.deserializedFields_) { - delete this.deserializedFields_[tag]; - } -}; - - -/** - * Iterates over all the unknown fields in the message. - * - * @param {function(this:T, number, *)} callback A callback method - * which gets invoked for each unknown field. - * @param {T=} opt_scope The scope under which to execute the callback. - * If not given, the current message will be used. - * @template T - */ -goog.proto2.Message.prototype.forEachUnknown = function(callback, opt_scope) { - var scope = opt_scope || this; - for (var key in this.values_) { - var keyNum = Number(key); - if (!this.fields_[keyNum]) { - callback.call(scope, keyNum, this.values_[key]); - } - } -}; - - -/** - * Returns the descriptor which describes the current message. - * - * This only works if we assume people never subclass protobufs. - * - * @return {!goog.proto2.Descriptor} The descriptor. - */ -goog.proto2.Message.prototype.getDescriptor = goog.abstractMethod; - - -/** - * Returns whether there is a value stored at the field specified by the - * given field descriptor. - * - * @param {goog.proto2.FieldDescriptor} field The field for which to check - * if there is a value. - * - * @return {boolean} True if a value was found. - */ -goog.proto2.Message.prototype.has = function(field) { - goog.asserts.assert( - field.getContainingType() == this.getDescriptor(), - 'The current message does not contain the given field'); - - return this.has$Value(field.getTag()); -}; - - -/** - * Returns the array of values found for the given repeated field. - * - * @param {goog.proto2.FieldDescriptor} field The field for which to - * return the values. - * - * @return {!Array<?>} The values found. - */ -goog.proto2.Message.prototype.arrayOf = function(field) { - goog.asserts.assert( - field.getContainingType() == this.getDescriptor(), - 'The current message does not contain the given field'); - - return this.array$Values(field.getTag()); -}; - - -/** - * Returns the number of values stored in the given field. - * - * @param {goog.proto2.FieldDescriptor} field The field for which to count - * the number of values. - * - * @return {number} The count of the values in the given field. - */ -goog.proto2.Message.prototype.countOf = function(field) { - goog.asserts.assert( - field.getContainingType() == this.getDescriptor(), - 'The current message does not contain the given field'); - - return this.count$Values(field.getTag()); -}; - - -/** - * Returns the value stored at the field specified by the - * given field descriptor. - * - * @param {goog.proto2.FieldDescriptor} field The field for which to get the - * value. - * @param {number=} opt_index If the field is repeated, the index to use when - * looking up the value. - * - * @return {?} The value found or null if none. - */ -goog.proto2.Message.prototype.get = function(field, opt_index) { - goog.asserts.assert( - field.getContainingType() == this.getDescriptor(), - 'The current message does not contain the given field'); - - return this.get$Value(field.getTag(), opt_index); -}; - - -/** - * Returns the value stored at the field specified by the - * given field descriptor or the default value if none exists. - * - * @param {goog.proto2.FieldDescriptor} field The field for which to get the - * value. - * @param {number=} opt_index If the field is repeated, the index to use when - * looking up the value. - * - * @return {?} The value found or the default if none. - */ -goog.proto2.Message.prototype.getOrDefault = function(field, opt_index) { - goog.asserts.assert( - field.getContainingType() == this.getDescriptor(), - 'The current message does not contain the given field'); - - return this.get$ValueOrDefault(field.getTag(), opt_index); -}; - - -/** - * Stores the given value to the field specified by the - * given field descriptor. Note that the field must not be repeated. - * - * @param {goog.proto2.FieldDescriptor} field The field for which to set - * the value. - * @param {*} value The new value for the field. - */ -goog.proto2.Message.prototype.set = function(field, value) { - goog.asserts.assert( - field.getContainingType() == this.getDescriptor(), - 'The current message does not contain the given field'); - - this.set$Value(field.getTag(), value); -}; - - -/** - * Adds the given value to the field specified by the - * given field descriptor. Note that the field must be repeated. - * - * @param {goog.proto2.FieldDescriptor} field The field in which to add the - * the value. - * @param {*} value The new value to add to the field. - */ -goog.proto2.Message.prototype.add = function(field, value) { - goog.asserts.assert( - field.getContainingType() == this.getDescriptor(), - 'The current message does not contain the given field'); - - this.add$Value(field.getTag(), value); -}; - - -/** - * Clears the field specified. - * - * @param {goog.proto2.FieldDescriptor} field The field to clear. - */ -goog.proto2.Message.prototype.clear = function(field) { - goog.asserts.assert( - field.getContainingType() == this.getDescriptor(), - 'The current message does not contain the given field'); - - this.clear$Field(field.getTag()); -}; - - -/** - * Compares this message with another one ignoring the unknown fields. - * @param {?} other The other message. - * @return {boolean} Whether they are equal. Returns false if the {@code other} - * argument is a different type of message or not a message. - */ -goog.proto2.Message.prototype.equals = function(other) { - if (!other || this.constructor != other.constructor) { - return false; - } - - var fields = this.getDescriptor().getFields(); - for (var i = 0; i < fields.length; i++) { - var field = fields[i]; - var tag = field.getTag(); - if (this.has$Value(tag) != other.has$Value(tag)) { - return false; - } - - if (this.has$Value(tag)) { - var isComposite = field.isCompositeType(); - - var fieldsEqual = function(value1, value2) { - return isComposite ? value1.equals(value2) : value1 == value2; - }; - - var thisValue = this.getValueForTag_(tag); - var otherValue = other.getValueForTag_(tag); - - if (field.isRepeated()) { - // In this case thisValue and otherValue are arrays. - if (thisValue.length != otherValue.length) { - return false; - } - for (var j = 0; j < thisValue.length; j++) { - if (!fieldsEqual(thisValue[j], otherValue[j])) { - return false; - } - } - } else if (!fieldsEqual(thisValue, otherValue)) { - return false; - } - } - } - - return true; -}; - - -/** - * Recursively copies the known fields from the given message to this message. - * Removes the fields which are not present in the source message. - * @param {!goog.proto2.Message} message The source message. - */ -goog.proto2.Message.prototype.copyFrom = function(message) { - goog.asserts.assert( - this.constructor == message.constructor, - 'The source message must have the same type.'); - - if (this != message) { - this.values_ = {}; - if (this.deserializedFields_) { - this.deserializedFields_ = {}; - } - this.mergeFrom(message); - } -}; - - -/** - * Merges the given message into this message. - * - * Singular fields will be overwritten, except for embedded messages which will - * be merged. Repeated fields will be concatenated. - * @param {!goog.proto2.Message} message The source message. - */ -goog.proto2.Message.prototype.mergeFrom = function(message) { - goog.asserts.assert( - this.constructor == message.constructor, - 'The source message must have the same type.'); - var fields = this.getDescriptor().getFields(); - - for (var i = 0; i < fields.length; i++) { - var field = fields[i]; - var tag = field.getTag(); - if (message.has$Value(tag)) { - if (this.deserializedFields_) { - delete this.deserializedFields_[field.getTag()]; - } - - var isComposite = field.isCompositeType(); - if (field.isRepeated()) { - var values = message.array$Values(tag); - for (var j = 0; j < values.length; j++) { - this.add$Value(tag, isComposite ? values[j].clone() : values[j]); - } - } else { - var value = message.getValueForTag_(tag); - if (isComposite) { - var child = this.getValueForTag_(tag); - if (child) { - child.mergeFrom(value); - } else { - this.set$Value(tag, value.clone()); - } - } else { - this.set$Value(tag, value); - } - } - } - } -}; - - -/** - * @return {!goog.proto2.Message} Recursive clone of the message only including - * the known fields. - */ -goog.proto2.Message.prototype.clone = function() { - /** @type {!goog.proto2.Message} */ - var clone = new this.constructor; - clone.copyFrom(this); - return clone; -}; - - -/** - * Fills in the protocol buffer with default values. Any fields that are - * already set will not be overridden. - * @param {boolean} simpleFieldsToo If true, all fields will be initialized; - * if false, only the nested messages and groups. - */ -goog.proto2.Message.prototype.initDefaults = function(simpleFieldsToo) { - var fields = this.getDescriptor().getFields(); - for (var i = 0; i < fields.length; i++) { - var field = fields[i]; - var tag = field.getTag(); - var isComposite = field.isCompositeType(); - - // Initialize missing fields. - if (!this.has$Value(tag) && !field.isRepeated()) { - if (isComposite) { - this.values_[tag] = new /** @type {Function} */ (field.getNativeType()); - } else if (simpleFieldsToo) { - this.values_[tag] = field.getDefaultValue(); - } - } - - // Fill in the existing composite fields recursively. - if (isComposite) { - if (field.isRepeated()) { - var values = this.array$Values(tag); - for (var j = 0; j < values.length; j++) { - values[j].initDefaults(simpleFieldsToo); - } - } else { - this.get$Value(tag).initDefaults(simpleFieldsToo); - } - } - } -}; - - -/** - * Returns the whether or not the field indicated by the given tag - * has a value. - * - * GENERATED CODE USE ONLY. Basis of the has{Field} methods. - * - * @param {number} tag The tag. - * - * @return {boolean} Whether the message has a value for the field. - */ -goog.proto2.Message.prototype.has$Value = function(tag) { - return this.values_[tag] != null; -}; - - -/** - * Returns the value for the given tag number. If a lazy deserializer is - * instantiated, lazily deserializes the field if required before returning the - * value. - * - * @param {number} tag The tag number. - * @return {?} The corresponding value, if any. - * @private - */ -goog.proto2.Message.prototype.getValueForTag_ = function(tag) { - // Retrieve the current value, which may still be serialized. - var value = this.values_[tag]; - if (!goog.isDefAndNotNull(value)) { - return null; - } - - // If we have a lazy deserializer, then ensure that the field is - // properly deserialized. - if (this.lazyDeserializer_) { - // If the tag is not deserialized, then we must do so now. Deserialize - // the field's value via the deserializer. - if (!(tag in /** @type {!Object} */ (this.deserializedFields_))) { - var deserializedValue = this.lazyDeserializer_.deserializeField( - this, this.fields_[tag], value); - this.deserializedFields_[tag] = deserializedValue; - return deserializedValue; - } - - return this.deserializedFields_[tag]; - } - - // Otherwise, just return the value. - return value; -}; - - -/** - * Gets the value at the field indicated by the given tag. - * - * GENERATED CODE USE ONLY. Basis of the get{Field} methods. - * - * @param {number} tag The field's tag index. - * @param {number=} opt_index If the field is a repeated field, the index - * at which to get the value. - * - * @return {?} The value found or null for none. - * @protected - */ -goog.proto2.Message.prototype.get$Value = function(tag, opt_index) { - var value = this.getValueForTag_(tag); - - if (this.fields_[tag].isRepeated()) { - var index = opt_index || 0; - goog.asserts.assert( - index >= 0 && index < value.length, - 'Given index %s is out of bounds. Repeated field length: %s', index, - value.length); - return value[index]; - } - - return value; -}; - - -/** - * Gets the value at the field indicated by the given tag or the default value - * if none. - * - * GENERATED CODE USE ONLY. Basis of the get{Field} methods. - * - * @param {number} tag The field's tag index. - * @param {number=} opt_index If the field is a repeated field, the index - * at which to get the value. - * - * @return {?} The value found or the default value if none set. - * @protected - */ -goog.proto2.Message.prototype.get$ValueOrDefault = function(tag, opt_index) { - if (!this.has$Value(tag)) { - // Return the default value. - var field = this.fields_[tag]; - return field.getDefaultValue(); - } - - return this.get$Value(tag, opt_index); -}; - - -/** - * Gets the values at the field indicated by the given tag. - * - * GENERATED CODE USE ONLY. Basis of the {field}Array methods. - * - * @param {number} tag The field's tag index. - * - * @return {!Array<?>} The values found. If none, returns an empty array. - * @protected - */ -goog.proto2.Message.prototype.array$Values = function(tag) { - var value = this.getValueForTag_(tag); - return value || []; -}; - - -/** - * Returns the number of values stored in the field by the given tag. - * - * GENERATED CODE USE ONLY. Basis of the {field}Count methods. - * - * @param {number} tag The tag. - * - * @return {number} The number of values. - * @protected - */ -goog.proto2.Message.prototype.count$Values = function(tag) { - var field = this.fields_[tag]; - if (field.isRepeated()) { - return this.has$Value(tag) ? this.values_[tag].length : 0; - } else { - return this.has$Value(tag) ? 1 : 0; - } -}; - - -/** - * Sets the value of the *non-repeating* field indicated by the given tag. - * - * GENERATED CODE USE ONLY. Basis of the set{Field} methods. - * - * @param {number} tag The field's tag index. - * @param {*} value The field's value. - * @protected - */ -goog.proto2.Message.prototype.set$Value = function(tag, value) { - if (goog.asserts.ENABLE_ASSERTS) { - var field = this.fields_[tag]; - this.checkFieldType_(field, value); - } - - this.values_[tag] = value; - if (this.deserializedFields_) { - this.deserializedFields_[tag] = value; - } -}; - - -/** - * Adds the value to the *repeating* field indicated by the given tag. - * - * GENERATED CODE USE ONLY. Basis of the add{Field} methods. - * - * @param {number} tag The field's tag index. - * @param {*} value The value to add. - * @protected - */ -goog.proto2.Message.prototype.add$Value = function(tag, value) { - if (goog.asserts.ENABLE_ASSERTS) { - var field = this.fields_[tag]; - this.checkFieldType_(field, value); - } - - if (!this.values_[tag]) { - this.values_[tag] = []; - } - - this.values_[tag].push(value); - if (this.deserializedFields_) { - delete this.deserializedFields_[tag]; - } -}; - - -/** - * Ensures that the value being assigned to the given field - * is valid. - * - * @param {!goog.proto2.FieldDescriptor} field The field being assigned. - * @param {*} value The value being assigned. - * @private - */ -goog.proto2.Message.prototype.checkFieldType_ = function(field, value) { - if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.ENUM) { - goog.asserts.assertNumber(value); - } else { - goog.asserts.assert(Object(value).constructor == field.getNativeType()); - } -}; - - -/** - * Clears the field specified by tag. - * - * GENERATED CODE USE ONLY. Basis of the clear{Field} methods. - * - * @param {number} tag The tag of the field to clear. - * @protected - */ -goog.proto2.Message.prototype.clear$Field = function(tag) { - delete this.values_[tag]; - if (this.deserializedFields_) { - delete this.deserializedFields_[tag]; - } -}; - - -/** - * Creates the metadata descriptor representing the definition of this message. - * - * @param {function(new:goog.proto2.Message)} messageType Constructor for the - * message type to which this metadata applies. - * @param {!Object} metadataObj The object containing the metadata. - * @return {!goog.proto2.Descriptor} The new descriptor. - */ -goog.proto2.Message.createDescriptor = function(messageType, metadataObj) { - var fields = []; - var descriptorInfo = metadataObj[0]; - - for (var key in metadataObj) { - if (key != 0) { - // Create the field descriptor. - fields.push( - new goog.proto2.FieldDescriptor(messageType, key, metadataObj[key])); - } - } - - return new goog.proto2.Descriptor(messageType, descriptorInfo, fields); -};
diff --git a/third_party/ink/closure/proto2/objectserializer.js b/third_party/ink/closure/proto2/objectserializer.js deleted file mode 100644 index 95fa5d3f..0000000 --- a/third_party/ink/closure/proto2/objectserializer.js +++ /dev/null
@@ -1,202 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Protocol Buffer 2 Serializer which serializes messages - * into anonymous, simplified JSON objects. - * - * @author jschorr@google.com (Joseph Schorr) - */ - -goog.provide('goog.proto2.ObjectSerializer'); - -goog.require('goog.asserts'); -goog.require('goog.proto2.FieldDescriptor'); -goog.require('goog.proto2.Serializer'); -goog.require('goog.string'); - - - -/** - * ObjectSerializer, a serializer which turns Messages into simplified - * ECMAScript objects. - * - * @param {goog.proto2.ObjectSerializer.KeyOption=} opt_keyOption If specified, - * which key option to use when serializing/deserializing. - * @param {boolean=} opt_serializeBooleanAsNumber If specified and true, the - * serializer will convert boolean values to 0/1 representation. - * @constructor - * @extends {goog.proto2.Serializer} - */ -goog.proto2.ObjectSerializer = function( - opt_keyOption, opt_serializeBooleanAsNumber) { - this.keyOption_ = opt_keyOption; - this.serializeBooleanAsNumber_ = opt_serializeBooleanAsNumber; -}; -goog.inherits(goog.proto2.ObjectSerializer, goog.proto2.Serializer); - - -/** - * An enumeration of the options for how to emit the keys in - * the generated simplified object. - * - * @enum {number} - */ -goog.proto2.ObjectSerializer.KeyOption = { - /** - * Use the tag of the field as the key (default) - */ - TAG: 0, - - /** - * Use the name of the field as the key. Unknown fields - * will still use their tags as keys. - */ - NAME: 1 -}; - - -/** - * Serializes a message to an object. - * - * @param {goog.proto2.Message} message The message to be serialized. - * @return {!Object} The serialized form of the message. - * @override - */ -goog.proto2.ObjectSerializer.prototype.serialize = function(message) { - var descriptor = message.getDescriptor(); - var fields = descriptor.getFields(); - - var objectValue = {}; - - // Add the defined fields, recursively. - for (var i = 0; i < fields.length; i++) { - var field = fields[i]; - - var key = this.keyOption_ == goog.proto2.ObjectSerializer.KeyOption.NAME ? - field.getName() : - field.getTag(); - - - if (message.has(field)) { - if (field.isRepeated()) { - var array = []; - objectValue[key] = array; - - for (var j = 0; j < message.countOf(field); j++) { - array.push(this.getSerializedValue(field, message.get(field, j))); - } - - } else { - objectValue[key] = this.getSerializedValue(field, message.get(field)); - } - } - } - - // Add the unknown fields, if any. - message.forEachUnknown(function(tag, value) { objectValue[tag] = value; }); - - return objectValue; -}; - - -/** @override */ -goog.proto2.ObjectSerializer.prototype.getSerializedValue = function( - field, value) { - - // Handle the case where a boolean should be serialized as 0/1. - // Some deserialization libraries, such as GWT, can use this notation. - if (this.serializeBooleanAsNumber_ && - field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.BOOL && - goog.isBoolean(value)) { - return value ? 1 : 0; - } - - return goog.proto2.ObjectSerializer.base( - this, 'getSerializedValue', field, value); -}; - - -/** @override */ -goog.proto2.ObjectSerializer.prototype.getDeserializedValue = function( - field, value) { - - // Gracefully handle the case where a boolean is represented by 0/1. - // Some serialization libraries, such as GWT, can use this notation. - if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.BOOL && - goog.isNumber(value)) { - return Boolean(value); - } - - return goog.proto2.ObjectSerializer.base( - this, 'getDeserializedValue', field, value); -}; - - -/** - * Deserializes a message from an object and places the - * data in the message. - * - * @param {goog.proto2.Message} message The message in which to - * place the information. - * @param {*} data The data of the message. - * @override - */ -goog.proto2.ObjectSerializer.prototype.deserializeTo = function(message, data) { - var descriptor = message.getDescriptor(); - - for (var key in data) { - var field; - var value = data[key]; - - var isNumeric = goog.string.isNumeric(key); - - if (isNumeric) { - field = descriptor.findFieldByTag(key); - } else { - // We must be in Key == NAME mode to lookup by name. - goog.asserts.assert( - this.keyOption_ == goog.proto2.ObjectSerializer.KeyOption.NAME, - 'Key mode ' + this.keyOption_ + 'for key ' + key + ' is not ' + - goog.proto2.ObjectSerializer.KeyOption.NAME); - - field = descriptor.findFieldByName(key); - } - - if (field) { - if (field.isRepeated()) { - goog.asserts.assert( - goog.isArray(value), - 'Value for repeated field ' + field + ' must be an array.'); - - for (var j = 0; j < value.length; j++) { - message.add(field, this.getDeserializedValue(field, value[j])); - } - } else { - goog.asserts.assert( - !goog.isArray(value), - 'Value for non-repeated field ' + field + ' must not be an array.'); - message.set(field, this.getDeserializedValue(field, value)); - } - } else { - if (isNumeric) { - // We have an unknown field. - message.setUnknown(Number(key), value); - } else { - // Named fields must be present. - goog.asserts.fail('Failed to find field: ' + key); - } - } - } -};
diff --git a/third_party/ink/closure/proto2/serializer.js b/third_party/ink/closure/proto2/serializer.js deleted file mode 100644 index eb976d74..0000000 --- a/third_party/ink/closure/proto2/serializer.js +++ /dev/null
@@ -1,198 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Base class for all Protocol Buffer 2 serializers. - * @author jschorr@google.com (Joseph Schorr) - */ - -goog.provide('goog.proto2.Serializer'); - -goog.require('goog.asserts'); -goog.require('goog.proto2.FieldDescriptor'); -goog.require('goog.proto2.Message'); - - - -/** - * Abstract base class for PB2 serializers. A serializer is a class which - * implements the serialization and deserialization of a Protocol Buffer Message - * to/from a specific format. - * - * @constructor - */ -goog.proto2.Serializer = function() {}; - - -/** - * @define {boolean} Whether to decode and convert symbolic enum values to - * actual enum values or leave them as strings. - */ -goog.define('goog.proto2.Serializer.DECODE_SYMBOLIC_ENUMS', false); - - -/** - * Serializes a message to the expected format. - * - * @param {goog.proto2.Message} message The message to be serialized. - * - * @return {*} The serialized form of the message. - */ -goog.proto2.Serializer.prototype.serialize = goog.abstractMethod; - - -/** - * Returns the serialized form of the given value for the given field if the - * field is a Message or Group and returns the value unchanged otherwise, except - * for Infinity, -Infinity and NaN numerical values which are converted to - * string representation. - * - * @param {goog.proto2.FieldDescriptor} field The field from which this - * value came. - * - * @param {*} value The value of the field. - * - * @return {*} The value. - * @protected - */ -goog.proto2.Serializer.prototype.getSerializedValue = function(field, value) { - if (field.isCompositeType()) { - return this.serialize(/** @type {goog.proto2.Message} */ (value)); - } else if (goog.isNumber(value) && !isFinite(value)) { - return value.toString(); - } else { - return value; - } -}; - - -/** - * Deserializes a message from the expected format. - * - * @param {goog.proto2.Descriptor} descriptor The descriptor of the message - * to be created. - * @param {*} data The data of the message. - * - * @return {!goog.proto2.Message} The message created. - */ -goog.proto2.Serializer.prototype.deserialize = function(descriptor, data) { - var message = descriptor.createMessageInstance(); - this.deserializeTo(message, data); - goog.asserts.assert(message instanceof goog.proto2.Message); - return message; -}; - - -/** - * Deserializes a message from the expected format and places the - * data in the message. - * - * @param {goog.proto2.Message} message The message in which to - * place the information. - * @param {*} data The data of the message. - */ -goog.proto2.Serializer.prototype.deserializeTo = goog.abstractMethod; - - -/** - * Returns the deserialized form of the given value for the given field if the - * field is a Message or Group and returns the value, converted or unchanged, - * for primitive field types otherwise. - * - * @param {goog.proto2.FieldDescriptor} field The field from which this - * value came. - * - * @param {*} value The value of the field. - * - * @return {*} The value. - * @protected - */ -goog.proto2.Serializer.prototype.getDeserializedValue = function(field, value) { - // Composite types are deserialized recursively. - if (field.isCompositeType()) { - if (value instanceof goog.proto2.Message) { - return value; - } - - return this.deserialize(field.getFieldMessageType(), value); - } - - // Decode enum values. - if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.ENUM) { - // If it's a string, get enum value by name. - // NB: In order this feature to work, property renaming should be turned off - // for the respective enums. - if (goog.proto2.Serializer.DECODE_SYMBOLIC_ENUMS && goog.isString(value)) { - // enumType is a regular Javascript enum as defined in field's metadata. - var enumType = field.getNativeType(); - if (enumType.hasOwnProperty(value)) { - return enumType[value]; - } - } - - // If it's a string containing a positive integer, this looks like a viable - // enum int value. Return as numeric. - if (goog.isString(value) && - goog.proto2.Serializer.INTEGER_REGEX.test(value)) { - var numeric = Number(value); - if (numeric > 0) { - return numeric; - } - } - - // Return unknown values as is for backward compatibility. - return value; - } - - // Return the raw value if the field does not allow the JSON input to be - // converted. - if (!field.deserializationConversionPermitted()) { - return value; - } - - // Convert to native type of field. Return the converted value or fall - // through to return the raw value. The JSON encoding of int64 value 123 - // might be either the number 123 or the string "123". The field native type - // could be either Number or String (depending on field options in the .proto - // file). All four combinations should work correctly. - var nativeType = field.getNativeType(); - if (nativeType === String) { - // JSON numbers can be converted to strings. - if (goog.isNumber(value)) { - return String(value); - } - } else if (nativeType === Number) { - // JSON strings are sometimes used for large integer numeric values, as well - // as Infinity, -Infinity and NaN. - if (goog.isString(value)) { - // Handle +/- Infinity and NaN values. - if (value === 'Infinity' || value === '-Infinity' || value === 'NaN') { - return Number(value); - } - - // Validate the string. If the string is not an integral number, we would - // rather have an assertion or error in the caller than a mysterious NaN - // value. - if (goog.proto2.Serializer.INTEGER_REGEX.test(value)) { - return Number(value); - } - } - } - - return value; -}; - - -/** @const {!RegExp} */ -goog.proto2.Serializer.INTEGER_REGEX = /^-?[0-9]+$/;
diff --git a/third_party/ink/closure/reflect/reflect.js b/third_party/ink/closure/reflect/reflect.js deleted file mode 100644 index b846fba6..0000000 --- a/third_party/ink/closure/reflect/reflect.js +++ /dev/null
@@ -1,139 +0,0 @@ -// Copyright 2009 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Useful compiler idioms. - * - * @author mgoodman@google.com (Mark Goodman) - * @author johnlenz@google.com (John Lenz) - */ - -goog.provide('goog.reflect'); - - -/** - * Syntax for object literal casts. - * @see http://go/jscompiler-renaming - * @see https://goo.gl/CRs09P - * - * Use this if you have an object literal whose keys need to have the same names - * as the properties of some class even after they are renamed by the compiler. - * - * @param {!Function} type Type to cast to. - * @param {Object} object Object literal to cast. - * @return {Object} The object literal. - */ -goog.reflect.object = function(type, object) { - return object; -}; - -/** - * Syntax for renaming property strings. - * @see http://go/jscompiler-renaming - * @see https://goo.gl/CRs09P - * - * Use this if you have an need to access a property as a string, but want - * to also have the property renamed by the compiler. In contrast to - * goog.reflect.object, this method takes an instance of an object. - * - * Properties must be simple names (not qualified names). - * - * @param {string} prop Name of the property - * @param {!Object} object Instance of the object whose type will be used - * for renaming - * @return {string} The renamed property. - */ -goog.reflect.objectProperty = function(prop, object) { - return prop; -}; - -/** - * To assert to the compiler that an operation is needed when it would - * otherwise be stripped. For example: - * <code> - * // Force a layout - * goog.reflect.sinkValue(dialog.offsetHeight); - * </code> - * @param {T} x - * @return {T} - * @template T - */ -goog.reflect.sinkValue = function(x) { - goog.reflect.sinkValue[' '](x); - return x; -}; - - -/** - * The compiler should optimize this function away iff no one ever uses - * goog.reflect.sinkValue. - */ -goog.reflect.sinkValue[' '] = goog.nullFunction; - - -/** - * Check if a property can be accessed without throwing an exception. - * @param {Object} obj The owner of the property. - * @param {string} prop The property name. - * @return {boolean} Whether the property is accessible. Will also return true - * if obj is null. - */ -goog.reflect.canAccessProperty = function(obj, prop) { - - try { - goog.reflect.sinkValue(obj[prop]); - return true; - } catch (e) { - } - return false; -}; - - -/** - * Retrieves a value from a cache given a key. The compiler provides special - * consideration for this call such that it is generally considered side-effect - * free. However, if the {@code opt_keyFn} or {@code valueFn} have side-effects - * then the entire call is considered to have side-effects. - * - * Conventionally storing the value on the cache would be considered a - * side-effect and preclude unused calls from being pruned, ie. even if - * the value was never used, it would still always be stored in the cache. - * - * Providing a side-effect free {@code valueFn} and {@code opt_keyFn} - * allows unused calls to {@code goog.reflect.cache} to be pruned. - * - * @param {!Object<K, V>} cacheObj The object that contains the cached values. - * @param {?} key The key to lookup in the cache. If it is not string or number - * then a {@code opt_keyFn} should be provided. The key is also used as the - * parameter to the {@code valueFn}. - * @param {function(?):V} valueFn The value provider to use to calculate the - * value to store in the cache. This function should be side-effect free - * to take advantage of the optimization. - * @param {function(?):K=} opt_keyFn The key provider to determine the cache - * map key. This should be used if the given key is not a string or number. - * If not provided then the given key is used. This function should be - * side-effect free to take advantage of the optimization. - * @return {V} The cached or calculated value. - * @template K - * @template V - */ -goog.reflect.cache = function(cacheObj, key, valueFn, opt_keyFn) { - var storedKey = opt_keyFn ? opt_keyFn(key) : key; - - if (Object.prototype.hasOwnProperty.call(cacheObj, storedKey)) { - return cacheObj[storedKey]; - } - - return (cacheObj[storedKey] = valueFn(key)); -};
diff --git a/third_party/ink/closure/soy/data.js b/third_party/ink/closure/soy/data.js deleted file mode 100644 index 24e3307..0000000 --- a/third_party/ink/closure/soy/data.js +++ /dev/null
@@ -1,525 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Soy data primitives. - * - * The goal is to encompass data types used by Soy, especially to mark content - * as known to be "safe". - * - * @author gboyer@google.com (Garrett Boyer) - */ - -goog.provide('goog.soy.data.SanitizedContent'); -goog.provide('goog.soy.data.SanitizedContentKind'); -goog.provide('goog.soy.data.SanitizedCss'); -goog.provide('goog.soy.data.SanitizedHtml'); -goog.provide('goog.soy.data.SanitizedHtmlAttribute'); -goog.provide('goog.soy.data.SanitizedJs'); -goog.provide('goog.soy.data.SanitizedStyle'); -goog.provide('goog.soy.data.SanitizedTrustedResourceUri'); -goog.provide('goog.soy.data.SanitizedUri'); -goog.provide('goog.soy.data.UnsanitizedText'); - -goog.require('goog.Uri'); -goog.require('goog.asserts'); -goog.require('goog.html.SafeHtml'); -goog.require('goog.html.SafeScript'); -goog.require('goog.html.SafeStyle'); -goog.require('goog.html.SafeStyleSheet'); -goog.require('goog.html.SafeUrl'); -goog.require('goog.html.TrustedResourceUrl'); -goog.require('goog.html.uncheckedconversions'); -goog.require('goog.i18n.bidi.Dir'); -goog.require('goog.string.Const'); - - -/** - * A type of textual content. - * - * This is an enum of type Object so that these values are unforgeable. - * - * @enum {!Object} - */ -goog.soy.data.SanitizedContentKind = { - - /** - * A snippet of HTML that does not start or end inside a tag, comment, entity, - * or DOCTYPE; and that does not contain any executable code - * (JS, {@code <object>}s, etc.) from a different trust domain. - */ - HTML: goog.DEBUG ? {sanitizedContentKindHtml: true} : {}, - - /** - * Executable Javascript code or expression, safe for insertion in a - * script-tag or event handler context, known to be free of any - * attacker-controlled scripts. This can either be side-effect-free - * Javascript (such as JSON) or Javascript that's entirely under Google's - * control. - */ - JS: goog.DEBUG ? {sanitizedContentJsChars: true} : {}, - - /** A properly encoded portion of a URI. */ - URI: goog.DEBUG ? {sanitizedContentUri: true} : {}, - - /** A resource URI not under attacker control. */ - TRUSTED_RESOURCE_URI: - goog.DEBUG ? {sanitizedContentTrustedResourceUri: true} : {}, - - /** - * Repeated attribute names and values. For example, - * {@code dir="ltr" foo="bar" onclick="trustedFunction()" checked}. - */ - ATTRIBUTES: goog.DEBUG ? {sanitizedContentHtmlAttribute: true} : {}, - - // TODO: Consider separating rules, declarations, and values into - // separate types, but for simplicity, we'll treat explicitly blessed - // SanitizedContent as allowed in all of these contexts. - /** - * A CSS3 declaration, property, value or group of semicolon separated - * declarations. - */ - STYLE: goog.DEBUG ? {sanitizedContentStyle: true} : {}, - - /** A CSS3 style sheet (list of rules). */ - CSS: goog.DEBUG ? {sanitizedContentCss: true} : {}, - - /** - * Unsanitized plain-text content. - * - * This is effectively the "null" entry of this enum, and is sometimes used - * to explicitly mark content that should never be used unescaped. Since any - * string is safe to use as text, being of ContentKind.TEXT makes no - * guarantees about its safety in any other context such as HTML. - */ - TEXT: goog.DEBUG ? {sanitizedContentKindText: true} : {} -}; - - - -/** - * A string-like object that carries a content-type and a content direction. - * - * IMPORTANT! Do not create these directly, nor instantiate the subclasses. - * Instead, use a trusted, centrally reviewed library as endorsed by your team - * to generate these objects. Otherwise, you risk accidentally creating - * SanitizedContent that is attacker-controlled and gets evaluated unescaped in - * templates. - * - * @constructor - */ -goog.soy.data.SanitizedContent = function() { - throw new Error('Do not instantiate directly'); -}; - - -/** - * The context in which this content is safe from XSS attacks. - * @type {goog.soy.data.SanitizedContentKind} - */ -goog.soy.data.SanitizedContent.prototype.contentKind; - - -/** - * The content's direction; null if unknown and thus to be estimated when - * necessary. - * @type {?goog.i18n.bidi.Dir} - */ -goog.soy.data.SanitizedContent.prototype.contentDir = null; - - -/** - * The already-safe content. - * @protected {string} - */ -goog.soy.data.SanitizedContent.prototype.content; - - -/** - * Gets the already-safe content. - * @return {string} - */ -goog.soy.data.SanitizedContent.prototype.getContent = function() { - return this.content; -}; - - -/** @override */ -goog.soy.data.SanitizedContent.prototype.toString = function() { - return this.content; -}; - - -/** - * Converts sanitized content of kind TEXT or HTML into SafeHtml. HTML content - * is converted without modification, while text content is HTML-escaped. - * @return {!goog.html.SafeHtml} - * @throws {Error} when the content kind is not TEXT or HTML. - */ -goog.soy.data.SanitizedContent.prototype.toSafeHtml = function() { - if (this.contentKind === goog.soy.data.SanitizedContentKind.TEXT) { - return goog.html.SafeHtml.htmlEscape(this.toString()); - } - if (this.contentKind !== goog.soy.data.SanitizedContentKind.HTML) { - throw new Error('Sanitized content was not of kind TEXT or HTML.'); - } - return goog.html.uncheckedconversions - .safeHtmlFromStringKnownToSatisfyTypeContract( - goog.string.Const.from( - 'Soy SanitizedContent of kind HTML produces ' + - 'SafeHtml-contract-compliant value.'), - this.toString(), this.contentDir); -}; - - -/** - * Converts sanitized content of kind URI into SafeUrl without modification. - * @return {!goog.html.SafeUrl} - * @throws {Error} when the content kind is not URI. - */ -goog.soy.data.SanitizedContent.prototype.toSafeUrl = function() { - if (this.contentKind !== goog.soy.data.SanitizedContentKind.URI) { - throw new Error('Sanitized content was not of kind URI.'); - } - return goog.html.uncheckedconversions - .safeUrlFromStringKnownToSatisfyTypeContract( - goog.string.Const.from( - 'Soy SanitizedContent of kind URI produces ' + - 'SafeHtml-contract-compliant value.'), - this.toString()); -}; - - -/** - * Unsanitized plain text string. - * - * While all strings are effectively safe to use as a plain text, there are no - * guarantees about safety in any other context such as HTML. This is - * sometimes used to mark that should never be used unescaped. - * - * @param {*} content Plain text with no guarantees. - * @param {?goog.i18n.bidi.Dir=} opt_contentDir The content direction; null if - * unknown and thus to be estimated when necessary. Default: null. - * @extends {goog.soy.data.SanitizedContent} - * @constructor - */ -goog.soy.data.UnsanitizedText = function(content, opt_contentDir) { - // Not calling the superclass constructor which just throws an exception. - - /** @override */ - this.content = String(content); - this.contentDir = opt_contentDir != null ? opt_contentDir : null; -}; -goog.inherits(goog.soy.data.UnsanitizedText, goog.soy.data.SanitizedContent); - - -/** @override */ -goog.soy.data.UnsanitizedText.prototype.contentKind = - goog.soy.data.SanitizedContentKind.TEXT; - - - -/** - * Content of type {@link goog.soy.data.SanitizedContentKind.HTML}. - * - * The content is a string of HTML that can safely be embedded in a PCDATA - * context in your app. If you would be surprised to find that an HTML - * sanitizer produced {@code s} (e.g. it runs code or fetches bad URLs) and - * you wouldn't write a template that produces {@code s} on security or privacy - * grounds, then don't pass {@code s} here. The default content direction is - * unknown, i.e. to be estimated when necessary. - * - * @extends {goog.soy.data.SanitizedContent} - * @constructor - */ -goog.soy.data.SanitizedHtml = function() { - goog.soy.data.SanitizedHtml.base(this, 'constructor'); -}; -goog.inherits(goog.soy.data.SanitizedHtml, goog.soy.data.SanitizedContent); - -/** @override */ -goog.soy.data.SanitizedHtml.prototype.contentKind = - goog.soy.data.SanitizedContentKind.HTML; - -/** - * Checks if the value could be used as the Soy type {html}. - * @param {*} value - * @return {boolean} - */ -goog.soy.data.SanitizedHtml.isCompatibleWith = function(value) { - return goog.isString(value) || - value instanceof goog.soy.data.SanitizedHtml || - value instanceof goog.soy.data.UnsanitizedText || - value instanceof goog.html.SafeHtml; -}; - - - -/** - * Content of type {@link goog.soy.data.SanitizedContentKind.JS}. - * - * The content is JavaScript source that when evaluated does not execute any - * attacker-controlled scripts. The content direction is LTR. - * - * @extends {goog.soy.data.SanitizedContent} - * @constructor - */ -goog.soy.data.SanitizedJs = function() { - goog.soy.data.SanitizedJs.base(this, 'constructor'); -}; -goog.inherits(goog.soy.data.SanitizedJs, goog.soy.data.SanitizedContent); - -/** @override */ -goog.soy.data.SanitizedJs.prototype.contentKind = - goog.soy.data.SanitizedContentKind.JS; - -/** @override */ -goog.soy.data.SanitizedJs.prototype.contentDir = goog.i18n.bidi.Dir.LTR; - -/** - * Checks if the value could be used as the Soy type {js}. - * @param {*} value - * @return {boolean} - */ -goog.soy.data.SanitizedJs.isCompatibleWith = function(value) { - return goog.isString(value) || - value instanceof goog.soy.data.SanitizedJs || - value instanceof goog.soy.data.UnsanitizedText || - value instanceof goog.html.SafeScript; -}; - - - -/** - * Content of type {@link goog.soy.data.SanitizedContentKind.URI}. - * - * The content is a URI chunk that the caller knows is safe to emit in a - * template. The content direction is LTR. - * - * @extends {goog.soy.data.SanitizedContent} - * @constructor - */ -goog.soy.data.SanitizedUri = function() { - goog.soy.data.SanitizedUri.base(this, 'constructor'); -}; -goog.inherits(goog.soy.data.SanitizedUri, goog.soy.data.SanitizedContent); - -/** @override */ -goog.soy.data.SanitizedUri.prototype.contentKind = - goog.soy.data.SanitizedContentKind.URI; - -/** @override */ -goog.soy.data.SanitizedUri.prototype.contentDir = goog.i18n.bidi.Dir.LTR; - -/** - * Checks if the value could be used as the Soy type {uri}. - * @param {*} value - * @return {boolean} - */ -goog.soy.data.SanitizedUri.isCompatibleWith = function(value) { - return goog.isString(value) || - value instanceof goog.soy.data.SanitizedUri || - value instanceof goog.soy.data.UnsanitizedText || - value instanceof goog.html.SafeUrl || - value instanceof goog.html.TrustedResourceUrl || - value instanceof goog.Uri; -}; - - - -/** - * Content of type - * {@link goog.soy.data.SanitizedContentKind.TRUSTED_RESOURCE_URI}. - * - * The content is a TrustedResourceUri chunk that is not under attacker control. - * The content direction is LTR. - * - * @extends {goog.soy.data.SanitizedContent} - * @constructor - */ -goog.soy.data.SanitizedTrustedResourceUri = function() { - goog.soy.data.SanitizedTrustedResourceUri.base(this, 'constructor'); -}; -goog.inherits( - goog.soy.data.SanitizedTrustedResourceUri, goog.soy.data.SanitizedContent); - -/** @override */ -goog.soy.data.SanitizedTrustedResourceUri.prototype.contentKind = - goog.soy.data.SanitizedContentKind.TRUSTED_RESOURCE_URI; - -/** @override */ -goog.soy.data.SanitizedTrustedResourceUri.prototype.contentDir = - goog.i18n.bidi.Dir.LTR; - -/** - * Converts sanitized content into TrustedResourceUrl without modification. - * @return {!goog.html.TrustedResourceUrl} - */ -goog.soy.data.SanitizedTrustedResourceUri.prototype.toTrustedResourceUrl = - function() { - return goog.html.uncheckedconversions - .trustedResourceUrlFromStringKnownToSatisfyTypeContract( - goog.string.Const.from( - 'Soy SanitizedContent of kind TRUSTED_RESOURCE_URI produces ' + - 'TrustedResourceUrl-contract-compliant value.'), - this.toString()); -}; - -/** - * Checks if the value could be used as the Soy type {trusted_resource_uri}. - * @param {*} value - * @return {boolean} - */ -goog.soy.data.SanitizedTrustedResourceUri.isCompatibleWith = function(value) { - return goog.isString(value) || - value instanceof goog.soy.data.SanitizedTrustedResourceUri || - value instanceof goog.soy.data.UnsanitizedText || - value instanceof goog.html.TrustedResourceUrl; -}; - - - -/** - * Content of type {@link goog.soy.data.SanitizedContentKind.ATTRIBUTES}. - * - * The content should be safely embeddable within an open tag, such as a - * key="value" pair. The content direction is LTR. - * - * @extends {goog.soy.data.SanitizedContent} - * @constructor - */ -goog.soy.data.SanitizedHtmlAttribute = function() { - goog.soy.data.SanitizedHtmlAttribute.base(this, 'constructor'); -}; -goog.inherits( - goog.soy.data.SanitizedHtmlAttribute, goog.soy.data.SanitizedContent); - -/** @override */ -goog.soy.data.SanitizedHtmlAttribute.prototype.contentKind = - goog.soy.data.SanitizedContentKind.ATTRIBUTES; - -/** @override */ -goog.soy.data.SanitizedHtmlAttribute.prototype.contentDir = - goog.i18n.bidi.Dir.LTR; - -/** - * Checks if the value could be used as the Soy type {attribute}. - * @param {*} value - * @return {boolean} - */ -goog.soy.data.SanitizedHtmlAttribute.isCompatibleWith = function(value) { - return goog.isString(value) || - value instanceof goog.soy.data.SanitizedHtmlAttribute || - value instanceof goog.soy.data.UnsanitizedText; -}; - - - -/** - * Content of type {@link goog.soy.data.SanitizedContentKind.STYLE}. - * - * The content is non-attacker-exploitable CSS, such as {@code color:#c3d9ff}. - * The content direction is LTR. - * - * @extends {goog.soy.data.SanitizedContent} - * @constructor - */ -goog.soy.data.SanitizedStyle = function() { - goog.soy.data.SanitizedStyle.base(this, 'constructor'); -}; -goog.inherits(goog.soy.data.SanitizedStyle, goog.soy.data.SanitizedContent); - - -/** @override */ -goog.soy.data.SanitizedStyle.prototype.contentKind = - goog.soy.data.SanitizedContentKind.STYLE; - - -/** @override */ -goog.soy.data.SanitizedStyle.prototype.contentDir = goog.i18n.bidi.Dir.LTR; - - -/** - * Checks if the value could be used as the Soy type {css}. - * @param {*} value - * @return {boolean} - */ -goog.soy.data.SanitizedStyle.isCompatibleWith = function(value) { - return goog.isString(value) || - value instanceof goog.soy.data.SanitizedStyle || - value instanceof goog.soy.data.UnsanitizedText || - value instanceof goog.html.SafeStyle; -}; - - - -/** - * Content of type {@link goog.soy.data.SanitizedContentKind.CSS}. - * - * The content is non-attacker-exploitable CSS, such as {@code @import url(x)}. - * The content direction is LTR. - * - * @extends {goog.soy.data.SanitizedContent} - * @constructor - */ -goog.soy.data.SanitizedCss = function() { - goog.soy.data.SanitizedCss.base(this, 'constructor'); -}; -goog.inherits(goog.soy.data.SanitizedCss, goog.soy.data.SanitizedContent); - - -/** @override */ -goog.soy.data.SanitizedCss.prototype.contentKind = - goog.soy.data.SanitizedContentKind.CSS; - - -/** @override */ -goog.soy.data.SanitizedCss.prototype.contentDir = goog.i18n.bidi.Dir.LTR; - - -/** - * Checks if the value could be used as the Soy type {css}. - * @param {*} value - * @return {boolean} - */ -goog.soy.data.SanitizedCss.isCompatibleWith = function(value) { - return goog.isString(value) || - value instanceof goog.soy.data.SanitizedCss || - value instanceof goog.soy.data.UnsanitizedText || - value instanceof goog.html.SafeStyle || // TODO(jakubvrana): Delete. - value instanceof goog.html.SafeStyleSheet; -}; - - -/** - * Converts SanitizedCss into SafeStyleSheet. - * Note: SanitizedCss in Soy represents both SafeStyle and SafeStyleSheet in - * Closure. It's about to be split so that SanitizedCss represents only - * SafeStyleSheet. - * @return {!goog.html.SafeStyleSheet} - */ -goog.soy.data.SanitizedCss.prototype.toSafeStyleSheet = function() { - var value = this.toString(); - // TODO(jakubvrana): Remove this check when there's a separate type for style - // declaration. - goog.asserts.assert( - /[@{]|^\s*$/.test(value), - 'value doesn\'t look like style sheet: ' + value); - return goog.html.uncheckedconversions - .safeStyleSheetFromStringKnownToSatisfyTypeContract( - goog.string.Const.from( - 'Soy SanitizedCss produces SafeStyleSheet-contract-compliant ' + - 'value.'), - value); -};
diff --git a/third_party/ink/closure/soy/soy.js b/third_party/ink/closure/soy/soy.js deleted file mode 100644 index e10dd5d..0000000 --- a/third_party/ink/closure/soy/soy.js +++ /dev/null
@@ -1,298 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Provides utility methods to render soy template. - * @author kai@google.com (Kai Huang) - * @author ptucker@google.com (Philip Tucker) - * @author chrishenry@google.com (Chris Henry) - */ - -goog.provide('goog.soy'); - -goog.require('goog.asserts'); -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TagName'); -goog.require('goog.html.legacyconversions'); -goog.require('goog.soy.data.SanitizedContent'); -goog.require('goog.soy.data.SanitizedContentKind'); -goog.require('goog.string'); - - -/** - * @define {boolean} Whether to require all Soy templates to be "strict html". - * Soy templates that use strict autoescaping forbid noAutoescape along with - * many dangerous directives, and return a runtime type SanitizedContent that - * marks them as safe. - * - * If this flag is enabled, Soy templates will fail to render if a template - * returns plain text -- indicating it is a non-strict template. - */ -goog.define('goog.soy.REQUIRE_STRICT_AUTOESCAPE', false); - - -/** - * Type definition for strict Soy templates. Very useful when passing a template - * as an argument. - * @typedef {function(?, null=, ?Object<string, *>=): - * !goog.soy.data.SanitizedContent} - */ -goog.soy.StrictTemplate; - - -/** - * Type definition for strict Soy HTML templates. Very useful when passing - * a template as an argument. - * @typedef {function(?, null=, ?Object<string, *>=): - * !goog.soy.data.SanitizedHtml} - */ -goog.soy.StrictHtmlTemplate; - - -/** - * Sets the processed template as the innerHTML of an element. It is recommended - * to use this helper function instead of directly setting innerHTML in your - * hand-written code, so that it will be easier to audit the code for cross-site - * scripting vulnerabilities. - * - * @param {?Element} element The element whose content we are rendering into. - * @param {!goog.soy.data.SanitizedContent} templateResult The processed - * template of kind HTML or TEXT (which will be escaped). - * @template ARG_TYPES - */ -goog.soy.renderHtml = function(element, templateResult) { - element.innerHTML = goog.soy.ensureTemplateOutputHtml_(templateResult); -}; - - -/** - * Renders a Soy template and then set the output string as - * the innerHTML of an element. It is recommended to use this helper function - * instead of directly setting innerHTML in your hand-written code, so that it - * will be easier to audit the code for cross-site scripting vulnerabilities. - * - * @param {Element} element The element whose content we are rendering into. - * @param {?function(ARG_TYPES, Object<string, *>=):*| - * ?function(ARG_TYPES, null=, Object<string, *>=):*} template - * The Soy template defining the element's content. - * @param {ARG_TYPES=} opt_templateData The data for the template. - * @param {Object=} opt_injectedData The injected data for the template. - * @template ARG_TYPES - */ -goog.soy.renderElement = function( - element, template, opt_templateData, opt_injectedData) { - // Soy template parameter is only nullable for historical reasons. - goog.asserts.assert(template, 'Soy template may not be null.'); - element.innerHTML = goog.soy.ensureTemplateOutputHtml_( - template( - opt_templateData || goog.soy.defaultTemplateData_, undefined, - opt_injectedData)); -}; - - -/** - * Renders a Soy template into a single node or a document - * fragment. If the rendered HTML string represents a single node, then that - * node is returned (note that this is *not* a fragment, despite them name of - * the method). Otherwise a document fragment is returned containing the - * rendered nodes. - * - * @param {?function(ARG_TYPES, Object<string, *>=):*| - * ?function(ARG_TYPES, null=, Object<string, *>=):*} template - * The Soy template defining the element's content. - * @param {ARG_TYPES=} opt_templateData The data for the template. - * @param {Object=} opt_injectedData The injected data for the template. - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper used to - * create DOM nodes; defaults to {@code goog.dom.getDomHelper}. - * @return {!Node} The resulting node or document fragment. - * @template ARG_TYPES - */ -goog.soy.renderAsFragment = function( - template, opt_templateData, opt_injectedData, opt_domHelper) { - // Soy template parameter is only nullable for historical reasons. - goog.asserts.assert(template, 'Soy template may not be null.'); - var dom = opt_domHelper || goog.dom.getDomHelper(); - var output = template( - opt_templateData || goog.soy.defaultTemplateData_, undefined, - opt_injectedData); - var html = goog.soy.ensureTemplateOutputHtml_(output); - goog.soy.assertFirstTagValid_(html); - var safeHtml = output instanceof goog.soy.data.SanitizedContent ? - output.toSafeHtml() : - goog.html.legacyconversions.safeHtmlFromString(html); - return dom.safeHtmlToNode(safeHtml); -}; - - -/** - * Renders a Soy template into a single node. If the rendered - * HTML string represents a single node, then that node is returned. Otherwise, - * a DIV element is returned containing the rendered nodes. - * - * @param {?function(ARG_TYPES, Object<string, *>=):*| - * ?function(ARG_TYPES, null=, Object<string, *>=):*} template - * The Soy template defining the element's content. - * @param {ARG_TYPES=} opt_templateData The data for the template. - * @param {Object=} opt_injectedData The injected data for the template. - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper used to - * create DOM nodes; defaults to {@code goog.dom.getDomHelper}. - * @return {!Element} Rendered template contents, wrapped in a parent DIV - * element if necessary. - * @template ARG_TYPES - */ -goog.soy.renderAsElement = function( - template, opt_templateData, opt_injectedData, opt_domHelper) { - // Soy template parameter is only nullable for historical reasons. - goog.asserts.assert(template, 'Soy template may not be null.'); - return goog.soy.convertToElement_( - template( - opt_templateData || goog.soy.defaultTemplateData_, undefined, - opt_injectedData), - opt_domHelper); -}; - - -/** - * Converts a processed Soy template into a single node. If the rendered - * HTML string represents a single node, then that node is returned. Otherwise, - * a DIV element is returned containing the rendered nodes. - * - * @param {!goog.soy.data.SanitizedContent} templateResult The processed - * template of kind HTML or TEXT (which will be escaped). - * @param {?goog.dom.DomHelper=} opt_domHelper The DOM helper used to - * create DOM nodes; defaults to {@code goog.dom.getDomHelper}. - * @return {!Element} Rendered template contents, wrapped in a parent DIV - * element if necessary. - */ -goog.soy.convertToElement = function(templateResult, opt_domHelper) { - return goog.soy.convertToElement_(templateResult, opt_domHelper); -}; - - -/** - * Non-strict version of {@code goog.soy.convertToElement}. - * - * @param {*} templateResult The processed template. - * @param {?goog.dom.DomHelper=} opt_domHelper The DOM helper used to - * create DOM nodes; defaults to {@code goog.dom.getDomHelper}. - * @return {!Element} Rendered template contents, wrapped in a parent DIV - * element if necessary. - * @private - */ -goog.soy.convertToElement_ = function(templateResult, opt_domHelper) { - var dom = opt_domHelper || goog.dom.getDomHelper(); - var wrapper = dom.createElement(goog.dom.TagName.DIV); - var html = goog.soy.ensureTemplateOutputHtml_(templateResult); - goog.soy.assertFirstTagValid_(html); - wrapper.innerHTML = html; - - // If the template renders as a single element, return it. - if (wrapper.childNodes.length == 1) { - var firstChild = wrapper.firstChild; - if (firstChild.nodeType == goog.dom.NodeType.ELEMENT) { - return /** @type {!Element} */ (firstChild); - } - } - - // Otherwise, return the wrapper DIV. - return wrapper; -}; - - -/** - * Ensures the result is "safe" to insert as HTML. - * - * Note if the template has non-strict autoescape, the guarantees here are very - * weak. It is recommended applications switch to requiring strict - * autoescaping over time by tweaking goog.soy.REQUIRE_STRICT_AUTOESCAPE. - * - * In the case the argument is a SanitizedContent object, it either must - * already be of kind HTML, or if it is kind="text", the output will be HTML - * escaped. - * - * @param {*} templateResult The template result. - * @return {string} The assumed-safe HTML output string. - * @private - */ -goog.soy.ensureTemplateOutputHtml_ = function(templateResult) { - // Allow strings as long as strict autoescaping is not mandated. Note we - // allow everything that isn't an object, because some non-escaping templates - // end up returning non-strings if their only print statement is a - // non-escaped argument, plus some unit tests spoof templates. - // TODO(gboyer): Track down and fix these cases. - if (!goog.soy.REQUIRE_STRICT_AUTOESCAPE && !goog.isObject(templateResult)) { - return String(templateResult); - } - - // Allow SanitizedContent of kind HTML. - if (templateResult instanceof goog.soy.data.SanitizedContent) { - templateResult = - /** @type {!goog.soy.data.SanitizedContent} */ (templateResult); - var ContentKind = goog.soy.data.SanitizedContentKind; - if (templateResult.contentKind === ContentKind.HTML) { - return goog.asserts.assertString(templateResult.getContent()); - } - if (templateResult.contentKind === ContentKind.TEXT) { - // Allow text to be rendered, as long as we escape it. Other content - // kinds will fail, since we don't know what to do with them. - // TODO(gboyer): Perhaps also include URI in this case. - return goog.string.htmlEscape(templateResult.getContent()); - } - } - - goog.asserts.fail( - 'Soy template output is unsafe for use as HTML: ' + templateResult); - - // In production, return a safe string, rather than failing hard. - return 'zSoyz'; -}; - - -/** - * Checks that the rendered HTML does not start with an invalid tag that would - * likely cause unexpected output from renderAsElement or renderAsFragment. - * See {@link http://www.w3.org/TR/html5/semantics.html#semantics} for reference - * as to which HTML elements can be parents of each other. - * @param {string} html The output of a template. - * @private - */ -goog.soy.assertFirstTagValid_ = function(html) { - if (goog.asserts.ENABLE_ASSERTS) { - var matches = html.match(goog.soy.INVALID_TAG_TO_RENDER_); - goog.asserts.assert( - !matches, 'This template starts with a %s, which ' + - 'cannot be a child of a <div>, as required by soy internals. ' + - 'Consider using goog.soy.renderElement instead.\nTemplate output: %s', - matches && matches[0], html); - } -}; - - -/** - * A pattern to find templates that cannot be rendered by renderAsElement or - * renderAsFragment, as these elements cannot exist as the child of a <div>. - * @type {!RegExp} - * @private - */ -goog.soy.INVALID_TAG_TO_RENDER_ = - /^<(body|caption|col|colgroup|head|html|tr|td|th|tbody|thead|tfoot)>/i; - - -/** - * Immutable object that is passed into templates that are rendered - * without any data. - * @private @const - */ -goog.soy.defaultTemplateData_ = {};
diff --git a/third_party/ink/closure/string/const.js b/third_party/ink/closure/string/const.js deleted file mode 100644 index 30bfc4e..0000000 --- a/third_party/ink/closure/string/const.js +++ /dev/null
@@ -1,186 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.string.Const'); - -goog.require('goog.asserts'); -goog.require('goog.string.TypedString'); - - - -/** - * Wrapper for compile-time-constant strings. - * - * Const is a wrapper for strings that can only be created from program - * constants (i.e., string literals). This property relies on a custom Closure - * compiler check that {@code goog.string.Const.from} is only invoked on - * compile-time-constant expressions. - * - * Const is useful in APIs whose correct and secure use requires that certain - * arguments are not attacker controlled: Compile-time constants are inherently - * under the control of the application and not under control of external - * attackers, and hence are safe to use in such contexts. - * - * Instances of this type must be created via its factory method - * {@code goog.string.Const.from} and not by invoking its constructor. The - * constructor intentionally takes no parameters and the type is immutable; - * hence only a default instance corresponding to the empty string can be - * obtained via constructor invocation. - * - * @see goog.string.Const#from - * @constructor - * @final - * @struct - * @implements {goog.string.TypedString} - */ -goog.string.Const = function() { - /** - * The wrapped value of this Const object. The field has a purposely ugly - * name to make (non-compiled) code that attempts to directly access this - * field stand out. - * @private {string} - */ - this.stringConstValueWithSecurityContract__googStringSecurityPrivate_ = ''; - - /** - * A type marker used to implement additional run-time type checking. - * @see goog.string.Const#unwrap - * @const {!Object} - * @private - */ - this.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_ = - goog.string.Const.TYPE_MARKER_; -}; - - -/** - * @override - * @const - */ -goog.string.Const.prototype.implementsGoogStringTypedString = true; - - -/** - * Returns this Const's value a string. - * - * IMPORTANT: In code where it is security-relevant that an object's type is - * indeed {@code goog.string.Const}, use {@code goog.string.Const.unwrap} - * instead of this method. - * - * @see goog.string.Const#unwrap - * @override - */ -goog.string.Const.prototype.getTypedStringValue = function() { - return this.stringConstValueWithSecurityContract__googStringSecurityPrivate_; -}; - - -/** - * Returns a debug-string representation of this value. - * - * To obtain the actual string value wrapped inside an object of this type, - * use {@code goog.string.Const.unwrap}. - * - * @see goog.string.Const#unwrap - * @override - */ -goog.string.Const.prototype.toString = function() { - return 'Const{' + - this.stringConstValueWithSecurityContract__googStringSecurityPrivate_ + - '}'; -}; - - -/** - * Performs a runtime check that the provided object is indeed an instance - * of {@code goog.string.Const}, and returns its value. - * @param {!goog.string.Const} stringConst The object to extract from. - * @return {string} The Const object's contained string, unless the run-time - * type check fails. In that case, {@code unwrap} returns an innocuous - * string, or, if assertions are enabled, throws - * {@code goog.asserts.AssertionError}. - */ -goog.string.Const.unwrap = function(stringConst) { - // Perform additional run-time type-checking to ensure that stringConst is - // indeed an instance of the expected type. This provides some additional - // protection against security bugs due to application code that disables type - // checks. - if (stringConst instanceof goog.string.Const && - stringConst.constructor === goog.string.Const && - stringConst.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_ === - goog.string.Const.TYPE_MARKER_) { - return stringConst - .stringConstValueWithSecurityContract__googStringSecurityPrivate_; - } else { - goog.asserts.fail( - 'expected object of type Const, got \'' + stringConst + '\''); - return 'type_error:Const'; - } -}; - - -/** - * Creates a Const object from a compile-time constant string. - * - * It is illegal to invoke this function on an expression whose - * compile-time-contant value cannot be determined by the Closure compiler. - * - * Correct invocations include, - * <pre> - * var s = goog.string.Const.from('hello'); - * var t = goog.string.Const.from('hello' + 'world'); - * </pre> - * - * In contrast, the following are illegal: - * <pre> - * var s = goog.string.Const.from(getHello()); - * var t = goog.string.Const.from('hello' + world); - * </pre> - * - * @param {string} s A constant string from which to create a Const. - * @return {!goog.string.Const} A Const object initialized to stringConst. - */ -goog.string.Const.from = function(s) { - return goog.string.Const.create__googStringSecurityPrivate_(s); -}; - - -/** - * Type marker for the Const type, used to implement additional run-time - * type checking. - * @const {!Object} - * @private - */ -goog.string.Const.TYPE_MARKER_ = {}; - - -/** - * Utility method to create Const instances. - * @param {string} s The string to initialize the Const object with. - * @return {!goog.string.Const} The initialized Const object. - * @private - */ -goog.string.Const.create__googStringSecurityPrivate_ = function(s) { - var stringConst = new goog.string.Const(); - stringConst.stringConstValueWithSecurityContract__googStringSecurityPrivate_ = - s; - return stringConst; -}; - - -/** - * A Const instance wrapping the empty string. - * @const {!goog.string.Const} - */ -goog.string.Const.EMPTY = goog.string.Const.from('');
diff --git a/third_party/ink/closure/string/string.js b/third_party/ink/closure/string/string.js deleted file mode 100644 index 8e8c1c4f..0000000 --- a/third_party/ink/closure/string/string.js +++ /dev/null
@@ -1,1642 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for string manipulation. - * @author pupius@google.com (Daniel Pupius) - * @author arv@google.com (Erik Arvidsson) - */ - - -/** - * Namespace for string utilities - */ -goog.provide('goog.string'); -goog.provide('goog.string.Unicode'); - - -/** - * @define {boolean} Enables HTML escaping of lowercase letter "e" which helps - * with detection of double-escaping as this letter is frequently used. - */ -goog.define('goog.string.DETECT_DOUBLE_ESCAPING', false); - - -/** - * @define {boolean} Whether to force non-dom html unescaping. - */ -goog.define('goog.string.FORCE_NON_DOM_HTML_UNESCAPING', false); - - -/** - * Common Unicode string characters. - * @enum {string} - */ -goog.string.Unicode = { - NBSP: '\xa0' -}; - - -/** - * Fast prefix-checker. - * @param {string} str The string to check. - * @param {string} prefix A string to look for at the start of {@code str}. - * @return {boolean} True if {@code str} begins with {@code prefix}. - */ -goog.string.startsWith = function(str, prefix) { - return str.lastIndexOf(prefix, 0) == 0; -}; - - -/** - * Fast suffix-checker. - * @param {string} str The string to check. - * @param {string} suffix A string to look for at the end of {@code str}. - * @return {boolean} True if {@code str} ends with {@code suffix}. - */ -goog.string.endsWith = function(str, suffix) { - var l = str.length - suffix.length; - return l >= 0 && str.indexOf(suffix, l) == l; -}; - - -/** - * Case-insensitive prefix-checker. - * @param {string} str The string to check. - * @param {string} prefix A string to look for at the end of {@code str}. - * @return {boolean} True if {@code str} begins with {@code prefix} (ignoring - * case). - */ -goog.string.caseInsensitiveStartsWith = function(str, prefix) { - return goog.string.caseInsensitiveCompare( - prefix, str.substr(0, prefix.length)) == 0; -}; - - -/** - * Case-insensitive suffix-checker. - * @param {string} str The string to check. - * @param {string} suffix A string to look for at the end of {@code str}. - * @return {boolean} True if {@code str} ends with {@code suffix} (ignoring - * case). - */ -goog.string.caseInsensitiveEndsWith = function(str, suffix) { - return ( - goog.string.caseInsensitiveCompare( - suffix, str.substr(str.length - suffix.length, suffix.length)) == 0); -}; - - -/** - * Case-insensitive equality checker. - * @param {string} str1 First string to check. - * @param {string} str2 Second string to check. - * @return {boolean} True if {@code str1} and {@code str2} are the same string, - * ignoring case. - */ -goog.string.caseInsensitiveEquals = function(str1, str2) { - return str1.toLowerCase() == str2.toLowerCase(); -}; - - -/** - * Does simple python-style string substitution. - * subs("foo%s hot%s", "bar", "dog") becomes "foobar hotdog". - * @param {string} str The string containing the pattern. - * @param {...*} var_args The items to substitute into the pattern. - * @return {string} A copy of {@code str} in which each occurrence of - * {@code %s} has been replaced an argument from {@code var_args}. - */ -goog.string.subs = function(str, var_args) { - var splitParts = str.split('%s'); - var returnString = ''; - - var subsArguments = Array.prototype.slice.call(arguments, 1); - while (subsArguments.length && - // Replace up to the last split part. We are inserting in the - // positions between split parts. - splitParts.length > 1) { - returnString += splitParts.shift() + subsArguments.shift(); - } - - return returnString + splitParts.join('%s'); // Join unused '%s' -}; - - -/** - * Converts multiple whitespace chars (spaces, non-breaking-spaces, new lines - * and tabs) to a single space, and strips leading and trailing whitespace. - * @param {string} str Input string. - * @return {string} A copy of {@code str} with collapsed whitespace. - */ -goog.string.collapseWhitespace = function(str) { - // Since IE doesn't include non-breaking-space (0xa0) in their \s character - // class (as required by section 7.2 of the ECMAScript spec), we explicitly - // include it in the regexp to enforce consistent cross-browser behavior. - return str.replace(/[\s\xa0]+/g, ' ').replace(/^\s+|\s+$/g, ''); -}; - - -/** - * Checks if a string is empty or contains only whitespaces. - * @param {string} str The string to check. - * @return {boolean} Whether {@code str} is empty or whitespace only. - */ -goog.string.isEmptyOrWhitespace = function(str) { - // testing length == 0 first is actually slower in all browsers (about the - // same in Opera). - // Since IE doesn't include non-breaking-space (0xa0) in their \s character - // class (as required by section 7.2 of the ECMAScript spec), we explicitly - // include it in the regexp to enforce consistent cross-browser behavior. - return /^[\s\xa0]*$/.test(str); -}; - - -/** - * Checks if a string is empty. - * @param {string} str The string to check. - * @return {boolean} Whether {@code str} is empty. - */ -goog.string.isEmptyString = function(str) { - return str.length == 0; -}; - - -/** - * Checks if a string is empty or contains only whitespaces. - * - * @param {string} str The string to check. - * @return {boolean} Whether {@code str} is empty or whitespace only. - * @deprecated Use goog.string.isEmptyOrWhitespace instead. - */ -goog.string.isEmpty = goog.string.isEmptyOrWhitespace; - - -/** - * Checks if a string is null, undefined, empty or contains only whitespaces. - * @param {*} str The string to check. - * @return {boolean} Whether {@code str} is null, undefined, empty, or - * whitespace only. - * @deprecated Use goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str)) - * instead. - */ -goog.string.isEmptyOrWhitespaceSafe = function(str) { - return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str)); -}; - - -/** - * Checks if a string is null, undefined, empty or contains only whitespaces. - * - * @param {*} str The string to check. - * @return {boolean} Whether {@code str} is null, undefined, empty, or - * whitespace only. - * @deprecated Use goog.string.isEmptyOrWhitespace instead. - */ -goog.string.isEmptySafe = goog.string.isEmptyOrWhitespaceSafe; - - -/** - * Checks if a string is all breaking whitespace. - * @param {string} str The string to check. - * @return {boolean} Whether the string is all breaking whitespace. - */ -goog.string.isBreakingWhitespace = function(str) { - return !/[^\t\n\r ]/.test(str); -}; - - -/** - * Checks if a string contains all letters. - * @param {string} str string to check. - * @return {boolean} True if {@code str} consists entirely of letters. - */ -goog.string.isAlpha = function(str) { - return !/[^a-zA-Z]/.test(str); -}; - - -/** - * Checks if a string contains only numbers. - * @param {*} str string to check. If not a string, it will be - * casted to one. - * @return {boolean} True if {@code str} is numeric. - */ -goog.string.isNumeric = function(str) { - return !/[^0-9]/.test(str); -}; - - -/** - * Checks if a string contains only numbers or letters. - * @param {string} str string to check. - * @return {boolean} True if {@code str} is alphanumeric. - */ -goog.string.isAlphaNumeric = function(str) { - return !/[^a-zA-Z0-9]/.test(str); -}; - - -/** - * Checks if a character is a space character. - * @param {string} ch Character to check. - * @return {boolean} True if {@code ch} is a space. - */ -goog.string.isSpace = function(ch) { - return ch == ' '; -}; - - -/** - * Checks if a character is a valid unicode character. - * @param {string} ch Character to check. - * @return {boolean} True if {@code ch} is a valid unicode character. - */ -goog.string.isUnicodeChar = function(ch) { - return ch.length == 1 && ch >= ' ' && ch <= '~' || - ch >= '\u0080' && ch <= '\uFFFD'; -}; - - -/** - * Takes a string and replaces newlines with a space. Multiple lines are - * replaced with a single space. - * @param {string} str The string from which to strip newlines. - * @return {string} A copy of {@code str} stripped of newlines. - */ -goog.string.stripNewlines = function(str) { - return str.replace(/(\r\n|\r|\n)+/g, ' '); -}; - - -/** - * Replaces Windows and Mac new lines with unix style: \r or \r\n with \n. - * @param {string} str The string to in which to canonicalize newlines. - * @return {string} {@code str} A copy of {@code} with canonicalized newlines. - */ -goog.string.canonicalizeNewlines = function(str) { - return str.replace(/(\r\n|\r|\n)/g, '\n'); -}; - - -/** - * Normalizes whitespace in a string, replacing all whitespace chars with - * a space. - * @param {string} str The string in which to normalize whitespace. - * @return {string} A copy of {@code str} with all whitespace normalized. - */ -goog.string.normalizeWhitespace = function(str) { - return str.replace(/\xa0|\s/g, ' '); -}; - - -/** - * Normalizes spaces in a string, replacing all consecutive spaces and tabs - * with a single space. Replaces non-breaking space with a space. - * @param {string} str The string in which to normalize spaces. - * @return {string} A copy of {@code str} with all consecutive spaces and tabs - * replaced with a single space. - */ -goog.string.normalizeSpaces = function(str) { - return str.replace(/\xa0|[ \t]+/g, ' '); -}; - - -/** - * Removes the breaking spaces from the left and right of the string and - * collapses the sequences of breaking spaces in the middle into single spaces. - * The original and the result strings render the same way in HTML. - * @param {string} str A string in which to collapse spaces. - * @return {string} Copy of the string with normalized breaking spaces. - */ -goog.string.collapseBreakingSpaces = function(str) { - return str.replace(/[\t\r\n ]+/g, ' ') - .replace(/^[\t\r\n ]+|[\t\r\n ]+$/g, ''); -}; - - -/** - * Trims white spaces to the left and right of a string. - * @param {string} str The string to trim. - * @return {string} A trimmed copy of {@code str}. - */ -goog.string.trim = - (goog.TRUSTED_SITE && String.prototype.trim) ? function(str) { - return str.trim(); - } : function(str) { - // Since IE doesn't include non-breaking-space (0xa0) in their \s - // character class (as required by section 7.2 of the ECMAScript spec), - // we explicitly include it in the regexp to enforce consistent - // cross-browser behavior. - return str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''); - }; - - -/** - * Trims whitespaces at the left end of a string. - * @param {string} str The string to left trim. - * @return {string} A trimmed copy of {@code str}. - */ -goog.string.trimLeft = function(str) { - // Since IE doesn't include non-breaking-space (0xa0) in their \s character - // class (as required by section 7.2 of the ECMAScript spec), we explicitly - // include it in the regexp to enforce consistent cross-browser behavior. - return str.replace(/^[\s\xa0]+/, ''); -}; - - -/** - * Trims whitespaces at the right end of a string. - * @param {string} str The string to right trim. - * @return {string} A trimmed copy of {@code str}. - */ -goog.string.trimRight = function(str) { - // Since IE doesn't include non-breaking-space (0xa0) in their \s character - // class (as required by section 7.2 of the ECMAScript spec), we explicitly - // include it in the regexp to enforce consistent cross-browser behavior. - return str.replace(/[\s\xa0]+$/, ''); -}; - - -/** - * A string comparator that ignores case. - * -1 = str1 less than str2 - * 0 = str1 equals str2 - * 1 = str1 greater than str2 - * - * @param {string} str1 The string to compare. - * @param {string} str2 The string to compare {@code str1} to. - * @return {number} The comparator result, as described above. - */ -goog.string.caseInsensitiveCompare = function(str1, str2) { - var test1 = String(str1).toLowerCase(); - var test2 = String(str2).toLowerCase(); - - if (test1 < test2) { - return -1; - } else if (test1 == test2) { - return 0; - } else { - return 1; - } -}; - - -/** - * Compares two strings interpreting their numeric substrings as numbers. - * - * @param {string} str1 First string. - * @param {string} str2 Second string. - * @param {!RegExp} tokenizerRegExp Splits a string into substrings of - * non-negative integers, non-numeric characters and optionally fractional - * numbers starting with a decimal point. - * @return {number} Negative if str1 < str2, 0 is str1 == str2, positive if - * str1 > str2. - * @private - */ -goog.string.numberAwareCompare_ = function(str1, str2, tokenizerRegExp) { - if (str1 == str2) { - return 0; - } - if (!str1) { - return -1; - } - if (!str2) { - return 1; - } - - // Using match to split the entire string ahead of time turns out to be faster - // for most inputs than using RegExp.exec or iterating over each character. - var tokens1 = str1.toLowerCase().match(tokenizerRegExp); - var tokens2 = str2.toLowerCase().match(tokenizerRegExp); - - var count = Math.min(tokens1.length, tokens2.length); - - for (var i = 0; i < count; i++) { - var a = tokens1[i]; - var b = tokens2[i]; - - // Compare pairs of tokens, returning if one token sorts before the other. - if (a != b) { - // Only if both tokens are integers is a special comparison required. - // Decimal numbers are sorted as strings (e.g., '.09' < '.1'). - var num1 = parseInt(a, 10); - if (!isNaN(num1)) { - var num2 = parseInt(b, 10); - if (!isNaN(num2) && num1 - num2) { - return num1 - num2; - } - } - return a < b ? -1 : 1; - } - } - - // If one string is a substring of the other, the shorter string sorts first. - if (tokens1.length != tokens2.length) { - return tokens1.length - tokens2.length; - } - - // The two strings must be equivalent except for case (perfect equality is - // tested at the head of the function.) Revert to default ASCII string - // comparison to stabilize the sort. - return str1 < str2 ? -1 : 1; -}; - - -/** - * String comparison function that handles non-negative integer numbers in a - * way humans might expect. Using this function, the string 'File 2.jpg' sorts - * before 'File 10.jpg', and 'Version 1.9' before 'Version 1.10'. The comparison - * is mostly case-insensitive, though strings that are identical except for case - * are sorted with the upper-case strings before lower-case. - * - * This comparison function is up to 50x slower than either the default or the - * case-insensitive compare. It should not be used in time-critical code, but - * should be fast enough to sort several hundred short strings (like filenames) - * with a reasonable delay. - * - * @param {string} str1 The string to compare in a numerically sensitive way. - * @param {string} str2 The string to compare {@code str1} to. - * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than - * 0 if str1 > str2. - */ -goog.string.intAwareCompare = function(str1, str2) { - return goog.string.numberAwareCompare_(str1, str2, /\d+|\D+/g); -}; - - -/** - * String comparison function that handles non-negative integer and fractional - * numbers in a way humans might expect. Using this function, the string - * 'File 2.jpg' sorts before 'File 10.jpg', and '3.14' before '3.2'. Equivalent - * to {@link goog.string.intAwareCompare} apart from the way how it interprets - * dots. - * - * @param {string} str1 The string to compare in a numerically sensitive way. - * @param {string} str2 The string to compare {@code str1} to. - * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than - * 0 if str1 > str2. - */ -goog.string.floatAwareCompare = function(str1, str2) { - return goog.string.numberAwareCompare_(str1, str2, /\d+|\.\d+|\D+/g); -}; - - -/** - * Alias for {@link goog.string.floatAwareCompare}. - * - * @param {string} str1 - * @param {string} str2 - * @return {number} - */ -goog.string.numerateCompare = goog.string.floatAwareCompare; - - -/** - * URL-encodes a string - * @param {*} str The string to url-encode. - * @return {string} An encoded copy of {@code str} that is safe for urls. - * Note that '#', ':', and other characters used to delimit portions - * of URLs *will* be encoded. - */ -goog.string.urlEncode = function(str) { - return encodeURIComponent(String(str)); -}; - - -/** - * URL-decodes the string. We need to specially handle '+'s because - * the javascript library doesn't convert them to spaces. - * @param {string} str The string to url decode. - * @return {string} The decoded {@code str}. - */ -goog.string.urlDecode = function(str) { - return decodeURIComponent(str.replace(/\+/g, ' ')); -}; - - -/** - * Converts \n to <br>s or <br />s. - * @param {string} str The string in which to convert newlines. - * @param {boolean=} opt_xml Whether to use XML compatible tags. - * @return {string} A copy of {@code str} with converted newlines. - */ -goog.string.newLineToBr = function(str, opt_xml) { - return str.replace(/(\r\n|\r|\n)/g, opt_xml ? '<br />' : '<br>'); -}; - - -/** - * Escapes double quote '"' and single quote '\'' characters in addition to - * '&', '<', and '>' so that a string can be included in an HTML tag attribute - * value within double or single quotes. - * - * It should be noted that > doesn't need to be escaped for the HTML or XML to - * be valid, but it has been decided to escape it for consistency with other - * implementations. - * - * With goog.string.DETECT_DOUBLE_ESCAPING, this function escapes also the - * lowercase letter "e". - * - * NOTE(pupius): - * HtmlEscape is often called during the generation of large blocks of HTML. - * Using statics for the regular expressions and strings is an optimization - * that can more than half the amount of time IE spends in this function for - * large apps, since strings and regexes both contribute to GC allocations. - * - * Testing for the presence of a character before escaping increases the number - * of function calls, but actually provides a speed increase for the average - * case -- since the average case often doesn't require the escaping of all 4 - * characters and indexOf() is much cheaper than replace(). - * The worst case does suffer slightly from the additional calls, therefore the - * opt_isLikelyToContainHtmlChars option has been included for situations - * where all 4 HTML entities are very likely to be present and need escaping. - * - * Some benchmarks (times tended to fluctuate +-0.05ms): - * FireFox IE6 - * (no chars / average (mix of cases) / all 4 chars) - * no checks 0.13 / 0.22 / 0.22 0.23 / 0.53 / 0.80 - * indexOf 0.08 / 0.17 / 0.26 0.22 / 0.54 / 0.84 - * indexOf + re test 0.07 / 0.17 / 0.28 0.19 / 0.50 / 0.85 - * - * An additional advantage of checking if replace actually needs to be called - * is a reduction in the number of object allocations, so as the size of the - * application grows the difference between the various methods would increase. - * - * @param {string} str string to be escaped. - * @param {boolean=} opt_isLikelyToContainHtmlChars Don't perform a check to see - * if the character needs replacing - use this option if you expect each of - * the characters to appear often. Leave false if you expect few html - * characters to occur in your strings, such as if you are escaping HTML. - * @return {string} An escaped copy of {@code str}. - */ -goog.string.htmlEscape = function(str, opt_isLikelyToContainHtmlChars) { - - if (opt_isLikelyToContainHtmlChars) { - str = str.replace(goog.string.AMP_RE_, '&') - .replace(goog.string.LT_RE_, '<') - .replace(goog.string.GT_RE_, '>') - .replace(goog.string.QUOT_RE_, '"') - .replace(goog.string.SINGLE_QUOTE_RE_, ''') - .replace(goog.string.NULL_RE_, '�'); - if (goog.string.DETECT_DOUBLE_ESCAPING) { - str = str.replace(goog.string.E_RE_, 'e'); - } - return str; - - } else { - // quick test helps in the case when there are no chars to replace, in - // worst case this makes barely a difference to the time taken - if (!goog.string.ALL_RE_.test(str)) return str; - - // str.indexOf is faster than regex.test in this case - if (str.indexOf('&') != -1) { - str = str.replace(goog.string.AMP_RE_, '&'); - } - if (str.indexOf('<') != -1) { - str = str.replace(goog.string.LT_RE_, '<'); - } - if (str.indexOf('>') != -1) { - str = str.replace(goog.string.GT_RE_, '>'); - } - if (str.indexOf('"') != -1) { - str = str.replace(goog.string.QUOT_RE_, '"'); - } - if (str.indexOf('\'') != -1) { - str = str.replace(goog.string.SINGLE_QUOTE_RE_, '''); - } - if (str.indexOf('\x00') != -1) { - str = str.replace(goog.string.NULL_RE_, '�'); - } - if (goog.string.DETECT_DOUBLE_ESCAPING && str.indexOf('e') != -1) { - str = str.replace(goog.string.E_RE_, 'e'); - } - return str; - } -}; - - -/** - * Regular expression that matches an ampersand, for use in escaping. - * @const {!RegExp} - * @private - */ -goog.string.AMP_RE_ = /&/g; - - -/** - * Regular expression that matches a less than sign, for use in escaping. - * @const {!RegExp} - * @private - */ -goog.string.LT_RE_ = /</g; - - -/** - * Regular expression that matches a greater than sign, for use in escaping. - * @const {!RegExp} - * @private - */ -goog.string.GT_RE_ = />/g; - - -/** - * Regular expression that matches a double quote, for use in escaping. - * @const {!RegExp} - * @private - */ -goog.string.QUOT_RE_ = /"/g; - - -/** - * Regular expression that matches a single quote, for use in escaping. - * @const {!RegExp} - * @private - */ -goog.string.SINGLE_QUOTE_RE_ = /'/g; - - -/** - * Regular expression that matches null character, for use in escaping. - * @const {!RegExp} - * @private - */ -goog.string.NULL_RE_ = /\x00/g; - - -/** - * Regular expression that matches a lowercase letter "e", for use in escaping. - * @const {!RegExp} - * @private - */ -goog.string.E_RE_ = /e/g; - - -/** - * Regular expression that matches any character that needs to be escaped. - * @const {!RegExp} - * @private - */ -goog.string.ALL_RE_ = - (goog.string.DETECT_DOUBLE_ESCAPING ? /[\x00&<>"'e]/ : /[\x00&<>"']/); - - -/** - * Unescapes an HTML string. - * - * @param {string} str The string to unescape. - * @return {string} An unescaped copy of {@code str}. - */ -goog.string.unescapeEntities = function(str) { - if (goog.string.contains(str, '&')) { - // We are careful not to use a DOM if we do not have one or we explicitly - // requested non-DOM html unescaping. - if (!goog.string.FORCE_NON_DOM_HTML_UNESCAPING && - 'document' in goog.global) { - return goog.string.unescapeEntitiesUsingDom_(str); - } else { - // Fall back on pure XML entities - return goog.string.unescapePureXmlEntities_(str); - } - } - return str; -}; - - -/** - * Unescapes a HTML string using the provided document. - * - * @param {string} str The string to unescape. - * @param {!Document} document A document to use in escaping the string. - * @return {string} An unescaped copy of {@code str}. - */ -goog.string.unescapeEntitiesWithDocument = function(str, document) { - if (goog.string.contains(str, '&')) { - return goog.string.unescapeEntitiesUsingDom_(str, document); - } - return str; -}; - - -/** - * Unescapes an HTML string using a DOM to resolve non-XML, non-numeric - * entities. This function is XSS-safe and whitespace-preserving. - * @private - * @param {string} str The string to unescape. - * @param {Document=} opt_document An optional document to use for creating - * elements. If this is not specified then the default window.document - * will be used. - * @return {string} The unescaped {@code str} string. - */ -goog.string.unescapeEntitiesUsingDom_ = function(str, opt_document) { - /** @type {!Object<string, string>} */ - var seen = {'&': '&', '<': '<', '>': '>', '"': '"'}; - var div; - if (opt_document) { - div = opt_document.createElement('div'); - } else { - div = goog.global.document.createElement('div'); - } - // Match as many valid entity characters as possible. If the actual entity - // happens to be shorter, it will still work as innerHTML will return the - // trailing characters unchanged. Since the entity characters do not include - // open angle bracket, there is no chance of XSS from the innerHTML use. - // Since no whitespace is passed to innerHTML, whitespace is preserved. - return str.replace(goog.string.HTML_ENTITY_PATTERN_, function(s, entity) { - // Check for cached entity. - var value = seen[s]; - if (value) { - return value; - } - // Check for numeric entity. - if (entity.charAt(0) == '#') { - // Prefix with 0 so that hex entities (e.g. ) parse as hex numbers. - var n = Number('0' + entity.substr(1)); - if (!isNaN(n)) { - value = String.fromCharCode(n); - } - } - // Fall back to innerHTML otherwise. - if (!value) { - // Append a non-entity character to avoid a bug in Webkit that parses - // an invalid entity at the end of innerHTML text as the empty string. - div.innerHTML = s + ' '; - // Then remove the trailing character from the result. - value = div.firstChild.nodeValue.slice(0, -1); - } - // Cache and return. - return seen[s] = value; - }); -}; - - -/** - * Unescapes XML entities. - * @private - * @param {string} str The string to unescape. - * @return {string} An unescaped copy of {@code str}. - */ -goog.string.unescapePureXmlEntities_ = function(str) { - return str.replace(/&([^;]+);/g, function(s, entity) { - switch (entity) { - case 'amp': - return '&'; - case 'lt': - return '<'; - case 'gt': - return '>'; - case 'quot': - return '"'; - default: - if (entity.charAt(0) == '#') { - // Prefix with 0 so that hex entities (e.g. ) parse as hex. - var n = Number('0' + entity.substr(1)); - if (!isNaN(n)) { - return String.fromCharCode(n); - } - } - // For invalid entities we just return the entity - return s; - } - }); -}; - - -/** - * Regular expression that matches an HTML entity. - * See also HTML5: Tokenization / Tokenizing character references. - * @private - * @type {!RegExp} - */ -goog.string.HTML_ENTITY_PATTERN_ = /&([^;\s<&]+);?/g; - - -/** - * Do escaping of whitespace to preserve spatial formatting. We use character - * entity #160 to make it safer for xml. - * @param {string} str The string in which to escape whitespace. - * @param {boolean=} opt_xml Whether to use XML compatible tags. - * @return {string} An escaped copy of {@code str}. - */ -goog.string.whitespaceEscape = function(str, opt_xml) { - // This doesn't use goog.string.preserveSpaces for backwards compatibility. - return goog.string.newLineToBr(str.replace(/ /g, '  '), opt_xml); -}; - - -/** - * Preserve spaces that would be otherwise collapsed in HTML by replacing them - * with non-breaking space Unicode characters. - * @param {string} str The string in which to preserve whitespace. - * @return {string} A copy of {@code str} with preserved whitespace. - */ -goog.string.preserveSpaces = function(str) { - return str.replace(/(^|[\n ]) /g, '$1' + goog.string.Unicode.NBSP); -}; - - -/** - * Strip quote characters around a string. The second argument is a string of - * characters to treat as quotes. This can be a single character or a string of - * multiple character and in that case each of those are treated as possible - * quote characters. For example: - * - * <pre> - * goog.string.stripQuotes('"abc"', '"`') --> 'abc' - * goog.string.stripQuotes('`abc`', '"`') --> 'abc' - * </pre> - * - * @param {string} str The string to strip. - * @param {string} quoteChars The quote characters to strip. - * @return {string} A copy of {@code str} without the quotes. - */ -goog.string.stripQuotes = function(str, quoteChars) { - var length = quoteChars.length; - for (var i = 0; i < length; i++) { - var quoteChar = length == 1 ? quoteChars : quoteChars.charAt(i); - if (str.charAt(0) == quoteChar && str.charAt(str.length - 1) == quoteChar) { - return str.substring(1, str.length - 1); - } - } - return str; -}; - - -/** - * Truncates a string to a certain length and adds '...' if necessary. The - * length also accounts for the ellipsis, so a maximum length of 10 and a string - * 'Hello World!' produces 'Hello W...'. - * @param {string} str The string to truncate. - * @param {number} chars Max number of characters. - * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped - * characters from being cut off in the middle. - * @return {string} The truncated {@code str} string. - */ -goog.string.truncate = function(str, chars, opt_protectEscapedCharacters) { - if (opt_protectEscapedCharacters) { - str = goog.string.unescapeEntities(str); - } - - if (str.length > chars) { - str = str.substring(0, chars - 3) + '...'; - } - - if (opt_protectEscapedCharacters) { - str = goog.string.htmlEscape(str); - } - - return str; -}; - - -/** - * Truncate a string in the middle, adding "..." if necessary, - * and favoring the beginning of the string. - * @param {string} str The string to truncate the middle of. - * @param {number} chars Max number of characters. - * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped - * characters from being cutoff in the middle. - * @param {number=} opt_trailingChars Optional number of trailing characters to - * leave at the end of the string, instead of truncating as close to the - * middle as possible. - * @return {string} A truncated copy of {@code str}. - */ -goog.string.truncateMiddle = function( - str, chars, opt_protectEscapedCharacters, opt_trailingChars) { - if (opt_protectEscapedCharacters) { - str = goog.string.unescapeEntities(str); - } - - if (opt_trailingChars && str.length > chars) { - if (opt_trailingChars > chars) { - opt_trailingChars = chars; - } - var endPoint = str.length - opt_trailingChars; - var startPoint = chars - opt_trailingChars; - str = str.substring(0, startPoint) + '...' + str.substring(endPoint); - } else if (str.length > chars) { - // Favor the beginning of the string: - var half = Math.floor(chars / 2); - var endPos = str.length - half; - half += chars % 2; - str = str.substring(0, half) + '...' + str.substring(endPos); - } - - if (opt_protectEscapedCharacters) { - str = goog.string.htmlEscape(str); - } - - return str; -}; - - -/** - * Special chars that need to be escaped for goog.string.quote. - * @private {!Object<string, string>} - */ -goog.string.specialEscapeChars_ = { - '\0': '\\0', - '\b': '\\b', - '\f': '\\f', - '\n': '\\n', - '\r': '\\r', - '\t': '\\t', - '\x0B': '\\x0B', // '\v' is not supported in JScript - '"': '\\"', - '\\': '\\\\', - // To support the use case of embedding quoted strings inside of script - // tags, we have to make sure HTML comments and opening/closing script tags do - // not appear in the resulting string. The specific strings that must be - // escaped are documented at: - // http://www.w3.org/TR/html51/semantics.html#restrictions-for-contents-of-script-elements - '<': '\x3c' -}; - - -/** - * Character mappings used internally for goog.string.escapeChar. - * @private {!Object<string, string>} - */ -goog.string.jsEscapeCache_ = { - '\'': '\\\'' -}; - - -/** - * Encloses a string in double quotes and escapes characters so that the - * string is a valid JS string. The resulting string is safe to embed in - * `<script>` tags as "<" is escaped. - * @param {string} s The string to quote. - * @return {string} A copy of {@code s} surrounded by double quotes. - */ -goog.string.quote = function(s) { - s = String(s); - var sb = ['"']; - for (var i = 0; i < s.length; i++) { - var ch = s.charAt(i); - var cc = ch.charCodeAt(0); - sb[i + 1] = goog.string.specialEscapeChars_[ch] || - ((cc > 31 && cc < 127) ? ch : goog.string.escapeChar(ch)); - } - sb.push('"'); - return sb.join(''); -}; - - -/** - * Takes a string and returns the escaped string for that input string. - * @param {string} str The string to escape. - * @return {string} An escaped string representing {@code str}. - */ -goog.string.escapeString = function(str) { - var sb = []; - for (var i = 0; i < str.length; i++) { - sb[i] = goog.string.escapeChar(str.charAt(i)); - } - return sb.join(''); -}; - - -/** - * Takes a character and returns the escaped string for that character. For - * example escapeChar(String.fromCharCode(15)) -> "\\x0E". - * @param {string} c The character to escape. - * @return {string} An escaped string representing {@code c}. - */ -goog.string.escapeChar = function(c) { - if (c in goog.string.jsEscapeCache_) { - return goog.string.jsEscapeCache_[c]; - } - - if (c in goog.string.specialEscapeChars_) { - return goog.string.jsEscapeCache_[c] = goog.string.specialEscapeChars_[c]; - } - - var rv = c; - var cc = c.charCodeAt(0); - if (cc > 31 && cc < 127) { - rv = c; - } else { - // tab is 9 but handled above - if (cc < 256) { - rv = '\\x'; - if (cc < 16 || cc > 256) { - rv += '0'; - } - } else { - rv = '\\u'; - if (cc < 4096) { // \u1000 - rv += '0'; - } - } - rv += cc.toString(16).toUpperCase(); - } - - return goog.string.jsEscapeCache_[c] = rv; -}; - - -/** - * Determines whether a string contains a substring. - * @param {string} str The string to search. - * @param {string} subString The substring to search for. - * @return {boolean} Whether {@code str} contains {@code subString}. - */ -goog.string.contains = function(str, subString) { - return str.indexOf(subString) != -1; -}; - - -/** - * Determines whether a string contains a substring, ignoring case. - * @param {string} str The string to search. - * @param {string} subString The substring to search for. - * @return {boolean} Whether {@code str} contains {@code subString}. - */ -goog.string.caseInsensitiveContains = function(str, subString) { - return goog.string.contains(str.toLowerCase(), subString.toLowerCase()); -}; - - -/** - * Returns the non-overlapping occurrences of ss in s. - * If either s or ss evalutes to false, then returns zero. - * @param {string} s The string to look in. - * @param {string} ss The string to look for. - * @return {number} Number of occurrences of ss in s. - */ -goog.string.countOf = function(s, ss) { - return s && ss ? s.split(ss).length - 1 : 0; -}; - - -/** - * Removes a substring of a specified length at a specific - * index in a string. - * @param {string} s The base string from which to remove. - * @param {number} index The index at which to remove the substring. - * @param {number} stringLength The length of the substring to remove. - * @return {string} A copy of {@code s} with the substring removed or the full - * string if nothing is removed or the input is invalid. - */ -goog.string.removeAt = function(s, index, stringLength) { - var resultStr = s; - // If the index is greater or equal to 0 then remove substring - if (index >= 0 && index < s.length && stringLength > 0) { - resultStr = s.substr(0, index) + - s.substr(index + stringLength, s.length - index - stringLength); - } - return resultStr; -}; - - -/** - * Removes the first occurrence of a substring from a string. - * @param {string} str The base string from which to remove. - * @param {string} substr The string to remove. - * @return {string} A copy of {@code str} with {@code substr} removed or the - * full string if nothing is removed. - */ -goog.string.remove = function(str, substr) { - return str.replace(substr, ''); -}; - - -/** - * Removes all occurrences of a substring from a string. - * @param {string} s The base string from which to remove. - * @param {string} ss The string to remove. - * @return {string} A copy of {@code s} with {@code ss} removed or the full - * string if nothing is removed. - */ -goog.string.removeAll = function(s, ss) { - var re = new RegExp(goog.string.regExpEscape(ss), 'g'); - return s.replace(re, ''); -}; - - -/** - * Replaces all occurrences of a substring of a string with a new substring. - * @param {string} s The base string from which to remove. - * @param {string} ss The string to replace. - * @param {string} replacement The replacement string. - * @return {string} A copy of {@code s} with {@code ss} replaced by - * {@code replacement} or the original string if nothing is replaced. - */ -goog.string.replaceAll = function(s, ss, replacement) { - var re = new RegExp(goog.string.regExpEscape(ss), 'g'); - return s.replace(re, replacement.replace(/\$/g, '$$$$')); -}; - - -/** - * Escapes characters in the string that are not safe to use in a RegExp. - * @param {*} s The string to escape. If not a string, it will be casted - * to one. - * @return {string} A RegExp safe, escaped copy of {@code s}. - */ -goog.string.regExpEscape = function(s) { - return String(s) - .replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1') - .replace(/\x08/g, '\\x08'); -}; - - -/** - * Repeats a string n times. - * @param {string} string The string to repeat. - * @param {number} length The number of times to repeat. - * @return {string} A string containing {@code length} repetitions of - * {@code string}. - */ -goog.string.repeat = (String.prototype.repeat) ? function(string, length) { - // The native method is over 100 times faster than the alternative. - return string.repeat(length); -} : function(string, length) { - return new Array(length + 1).join(string); -}; - - -/** - * Pads number to given length and optionally rounds it to a given precision. - * For example: - * <pre>padNumber(1.25, 2, 3) -> '01.250' - * padNumber(1.25, 2) -> '01.25' - * padNumber(1.25, 2, 1) -> '01.3' - * padNumber(1.25, 0) -> '1.25'</pre> - * - * @param {number} num The number to pad. - * @param {number} length The desired length. - * @param {number=} opt_precision The desired precision. - * @return {string} {@code num} as a string with the given options. - */ -goog.string.padNumber = function(num, length, opt_precision) { - var s = goog.isDef(opt_precision) ? num.toFixed(opt_precision) : String(num); - var index = s.indexOf('.'); - if (index == -1) { - index = s.length; - } - return goog.string.repeat('0', Math.max(0, length - index)) + s; -}; - - -/** - * Returns a string representation of the given object, with - * null and undefined being returned as the empty string. - * - * @param {*} obj The object to convert. - * @return {string} A string representation of the {@code obj}. - */ -goog.string.makeSafe = function(obj) { - return obj == null ? '' : String(obj); -}; - - -/** - * Concatenates string expressions. This is useful - * since some browsers are very inefficient when it comes to using plus to - * concat strings. Be careful when using null and undefined here since - * these will not be included in the result. If you need to represent these - * be sure to cast the argument to a String first. - * For example: - * <pre>buildString('a', 'b', 'c', 'd') -> 'abcd' - * buildString(null, undefined) -> '' - * </pre> - * @param {...*} var_args A list of strings to concatenate. If not a string, - * it will be casted to one. - * @return {string} The concatenation of {@code var_args}. - */ -goog.string.buildString = function(var_args) { - return Array.prototype.join.call(arguments, ''); -}; - - -/** - * Returns a string with at least 64-bits of randomness. - * - * Doesn't trust Javascript's random function entirely. Uses a combination of - * random and current timestamp, and then encodes the string in base-36 to - * make it shorter. - * - * @return {string} A random string, e.g. sn1s7vb4gcic. - */ -goog.string.getRandomString = function() { - var x = 2147483648; - return Math.floor(Math.random() * x).toString(36) + - Math.abs(Math.floor(Math.random() * x) ^ goog.now()).toString(36); -}; - - -/** - * Compares two version numbers. - * - * @param {string|number} version1 Version of first item. - * @param {string|number} version2 Version of second item. - * - * @return {number} 1 if {@code version1} is higher. - * 0 if arguments are equal. - * -1 if {@code version2} is higher. - */ -goog.string.compareVersions = function(version1, version2) { - var order = 0; - // Trim leading and trailing whitespace and split the versions into - // subversions. - var v1Subs = goog.string.trim(String(version1)).split('.'); - var v2Subs = goog.string.trim(String(version2)).split('.'); - var subCount = Math.max(v1Subs.length, v2Subs.length); - - // Iterate over the subversions, as long as they appear to be equivalent. - for (var subIdx = 0; order == 0 && subIdx < subCount; subIdx++) { - var v1Sub = v1Subs[subIdx] || ''; - var v2Sub = v2Subs[subIdx] || ''; - - do { - // Split the subversions into pairs of numbers and qualifiers (like 'b'). - // Two different RegExp objects are use to make it clear the code - // is side-effect free - var v1Comp = /(\d*)(\D*)(.*)/.exec(v1Sub) || ['', '', '', '']; - var v2Comp = /(\d*)(\D*)(.*)/.exec(v2Sub) || ['', '', '', '']; - // Break if there are no more matches. - if (v1Comp[0].length == 0 && v2Comp[0].length == 0) { - break; - } - - // Parse the numeric part of the subversion. A missing number is - // equivalent to 0. - var v1CompNum = v1Comp[1].length == 0 ? 0 : parseInt(v1Comp[1], 10); - var v2CompNum = v2Comp[1].length == 0 ? 0 : parseInt(v2Comp[1], 10); - - // Compare the subversion components. The number has the highest - // precedence. Next, if the numbers are equal, a subversion without any - // qualifier is always higher than a subversion with any qualifier. Next, - // the qualifiers are compared as strings. - order = goog.string.compareElements_(v1CompNum, v2CompNum) || - goog.string.compareElements_( - v1Comp[2].length == 0, v2Comp[2].length == 0) || - goog.string.compareElements_(v1Comp[2], v2Comp[2]); - // Stop as soon as an inequality is discovered. - - v1Sub = v1Comp[3]; - v2Sub = v2Comp[3]; - } while (order == 0); - } - - return order; -}; - - -/** - * Compares elements of a version number. - * - * @param {string|number|boolean} left An element from a version number. - * @param {string|number|boolean} right An element from a version number. - * - * @return {number} 1 if {@code left} is higher. - * 0 if arguments are equal. - * -1 if {@code right} is higher. - * @private - */ -goog.string.compareElements_ = function(left, right) { - if (left < right) { - return -1; - } else if (left > right) { - return 1; - } - return 0; -}; - - -/** - * String hash function similar to java.lang.String.hashCode(). - * The hash code for a string is computed as - * s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1], - * where s[i] is the ith character of the string and n is the length of - * the string. We mod the result to make it between 0 (inclusive) and 2^32 - * (exclusive). - * @param {string} str A string. - * @return {number} Hash value for {@code str}, between 0 (inclusive) and 2^32 - * (exclusive). The empty string returns 0. - */ -goog.string.hashCode = function(str) { - var result = 0; - for (var i = 0; i < str.length; ++i) { - // Normalize to 4 byte range, 0 ... 2^32. - result = (31 * result + str.charCodeAt(i)) >>> 0; - } - return result; -}; - - -/** - * The most recent unique ID. |0 is equivalent to Math.floor in this case. - * @type {number} - * @private - */ -goog.string.uniqueStringCounter_ = Math.random() * 0x80000000 | 0; - - -/** - * Generates and returns a string which is unique in the current document. - * This is useful, for example, to create unique IDs for DOM elements. - * @return {string} A unique id. - */ -goog.string.createUniqueString = function() { - return 'goog_' + goog.string.uniqueStringCounter_++; -}; - - -/** - * Converts the supplied string to a number, which may be Infinity or NaN. - * This function strips whitespace: (toNumber(' 123') === 123) - * This function accepts scientific notation: (toNumber('1e1') === 10) - * - * This is better than Javascript's built-in conversions because, sadly: - * (Number(' ') === 0) and (parseFloat('123a') === 123) - * - * @param {string} str The string to convert. - * @return {number} The number the supplied string represents, or NaN. - */ -goog.string.toNumber = function(str) { - var num = Number(str); - if (num == 0 && goog.string.isEmptyOrWhitespace(str)) { - return NaN; - } - return num; -}; - - -/** - * Returns whether the given string is lower camel case (e.g. "isFooBar"). - * - * Note that this assumes the string is entirely letters. - * @see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms - * - * @param {string} str String to test. - * @return {boolean} Whether the string is lower camel case. - */ -goog.string.isLowerCamelCase = function(str) { - return /^[a-z]+([A-Z][a-z]*)*$/.test(str); -}; - - -/** - * Returns whether the given string is upper camel case (e.g. "FooBarBaz"). - * - * Note that this assumes the string is entirely letters. - * @see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms - * - * @param {string} str String to test. - * @return {boolean} Whether the string is upper camel case. - */ -goog.string.isUpperCamelCase = function(str) { - return /^([A-Z][a-z]*)+$/.test(str); -}; - - -/** - * Converts a string from selector-case to camelCase (e.g. from - * "multi-part-string" to "multiPartString"), useful for converting - * CSS selectors and HTML dataset keys to their equivalent JS properties. - * @param {string} str The string in selector-case form. - * @return {string} The string in camelCase form. - */ -goog.string.toCamelCase = function(str) { - return String(str).replace( - /\-([a-z])/g, function(all, match) { return match.toUpperCase(); }); -}; - - -/** - * Converts a string from camelCase to selector-case (e.g. from - * "multiPartString" to "multi-part-string"), useful for converting JS - * style and dataset properties to equivalent CSS selectors and HTML keys. - * @param {string} str The string in camelCase form. - * @return {string} The string in selector-case form. - */ -goog.string.toSelectorCase = function(str) { - return String(str).replace(/([A-Z])/g, '-$1').toLowerCase(); -}; - - -/** - * Converts a string into TitleCase. First character of the string is always - * capitalized in addition to the first letter of every subsequent word. - * Words are delimited by one or more whitespaces by default. Custom delimiters - * can optionally be specified to replace the default, which doesn't preserve - * whitespace delimiters and instead must be explicitly included if needed. - * - * Default delimiter => " ": - * goog.string.toTitleCase('oneTwoThree') => 'OneTwoThree' - * goog.string.toTitleCase('one two three') => 'One Two Three' - * goog.string.toTitleCase(' one two ') => ' One Two ' - * goog.string.toTitleCase('one_two_three') => 'One_two_three' - * goog.string.toTitleCase('one-two-three') => 'One-two-three' - * - * Custom delimiter => "_-.": - * goog.string.toTitleCase('oneTwoThree', '_-.') => 'OneTwoThree' - * goog.string.toTitleCase('one two three', '_-.') => 'One two three' - * goog.string.toTitleCase(' one two ', '_-.') => ' one two ' - * goog.string.toTitleCase('one_two_three', '_-.') => 'One_Two_Three' - * goog.string.toTitleCase('one-two-three', '_-.') => 'One-Two-Three' - * goog.string.toTitleCase('one...two...three', '_-.') => 'One...Two...Three' - * goog.string.toTitleCase('one. two. three', '_-.') => 'One. two. three' - * goog.string.toTitleCase('one-two.three', '_-.') => 'One-Two.Three' - * - * @param {string} str String value in camelCase form. - * @param {string=} opt_delimiters Custom delimiter character set used to - * distinguish words in the string value. Each character represents a - * single delimiter. When provided, default whitespace delimiter is - * overridden and must be explicitly included if needed. - * @return {string} String value in TitleCase form. - */ -goog.string.toTitleCase = function(str, opt_delimiters) { - var delimiters = goog.isString(opt_delimiters) ? - goog.string.regExpEscape(opt_delimiters) : - '\\s'; - - // For IE8, we need to prevent using an empty character set. Otherwise, - // incorrect matching will occur. - delimiters = delimiters ? '|[' + delimiters + ']+' : ''; - - var regexp = new RegExp('(^' + delimiters + ')([a-z])', 'g'); - return str.replace( - regexp, function(all, p1, p2) { return p1 + p2.toUpperCase(); }); -}; - - -/** - * Capitalizes a string, i.e. converts the first letter to uppercase - * and all other letters to lowercase, e.g.: - * - * goog.string.capitalize('one') => 'One' - * goog.string.capitalize('ONE') => 'One' - * goog.string.capitalize('one two') => 'One two' - * - * Note that this function does not trim initial whitespace. - * - * @param {string} str String value to capitalize. - * @return {string} String value with first letter in uppercase. - */ -goog.string.capitalize = function(str) { - return String(str.charAt(0)).toUpperCase() + - String(str.substr(1)).toLowerCase(); -}; - - -/** - * Parse a string in decimal or hexidecimal ('0xFFFF') form. - * - * To parse a particular radix, please use parseInt(string, radix) directly. See - * https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseInt - * - * This is a wrapper for the built-in parseInt function that will only parse - * numbers as base 10 or base 16. Some JS implementations assume strings - * starting with "0" are intended to be octal. ES3 allowed but discouraged - * this behavior. ES5 forbids it. This function emulates the ES5 behavior. - * - * For more information, see Mozilla JS Reference: http://goo.gl/8RiFj - * - * @param {string|number|null|undefined} value The value to be parsed. - * @return {number} The number, parsed. If the string failed to parse, this - * will be NaN. - */ -goog.string.parseInt = function(value) { - // Force finite numbers to strings. - if (isFinite(value)) { - value = String(value); - } - - if (goog.isString(value)) { - // If the string starts with '0x' or '-0x', parse as hex. - return /^\s*-?0x/i.test(value) ? parseInt(value, 16) : parseInt(value, 10); - } - - return NaN; -}; - - -/** - * Splits a string on a separator a limited number of times. - * - * This implementation is more similar to Python or Java, where the limit - * parameter specifies the maximum number of splits rather than truncating - * the number of results. - * - * See http://docs.python.org/2/library/stdtypes.html#str.split - * See JavaDoc: http://goo.gl/F2AsY - * See Mozilla reference: http://goo.gl/dZdZs - * - * @param {string} str String to split. - * @param {string} separator The separator. - * @param {number} limit The limit to the number of splits. The resulting array - * will have a maximum length of limit+1. Negative numbers are the same - * as zero. - * @return {!Array<string>} The string, split. - */ -goog.string.splitLimit = function(str, separator, limit) { - var parts = str.split(separator); - var returnVal = []; - - // Only continue doing this while we haven't hit the limit and we have - // parts left. - while (limit > 0 && parts.length) { - returnVal.push(parts.shift()); - limit--; - } - - // If there are remaining parts, append them to the end. - if (parts.length) { - returnVal.push(parts.join(separator)); - } - - return returnVal; -}; - - -/** - * Finds the characters to the right of the last instance of any separator - * - * This function is similar to goog.string.path.baseName, except it can take a - * list of characters to split the string on. It will return the rightmost - * grouping of characters to the right of any separator as a left-to-right - * oriented string. - * - * @see goog.string.path.baseName - * @param {string} str The string - * @param {string|!Array<string>} separators A list of separator characters - * @return {string} The last part of the string with respect to the separators - */ -goog.string.lastComponent = function(str, separators) { - if (!separators) { - return str; - } else if (typeof separators == 'string') { - separators = [separators]; - } - - var lastSeparatorIndex = -1; - for (var i = 0; i < separators.length; i++) { - if (separators[i] == '') { - continue; - } - var currentSeparatorIndex = str.lastIndexOf(separators[i]); - if (currentSeparatorIndex > lastSeparatorIndex) { - lastSeparatorIndex = currentSeparatorIndex; - } - } - if (lastSeparatorIndex == -1) { - return str; - } - return str.slice(lastSeparatorIndex + 1); -}; - - -/** - * Computes the Levenshtein edit distance between two strings. - * @param {string} a - * @param {string} b - * @return {number} The edit distance between the two strings. - */ -goog.string.editDistance = function(a, b) { - var v0 = []; - var v1 = []; - - if (a == b) { - return 0; - } - - if (!a.length || !b.length) { - return Math.max(a.length, b.length); - } - - for (var i = 0; i < b.length + 1; i++) { - v0[i] = i; - } - - for (var i = 0; i < a.length; i++) { - v1[0] = i + 1; - - for (var j = 0; j < b.length; j++) { - var cost = Number(a[i] != b[j]); - // Cost for the substring is the minimum of adding one character, removing - // one character, or a swap. - v1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost); - } - - for (var j = 0; j < v0.length; j++) { - v0[j] = v1[j]; - } - } - - return v1[b.length]; -};
diff --git a/third_party/ink/closure/string/typedstring.js b/third_party/ink/closure/string/typedstring.js deleted file mode 100644 index d0d7bd9..0000000 --- a/third_party/ink/closure/string/typedstring.js +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.string.TypedString'); - - - -/** - * Wrapper for strings that conform to a data type or language. - * - * Implementations of this interface are wrappers for strings, and typically - * associate a type contract with the wrapped string. Concrete implementations - * of this interface may choose to implement additional run-time type checking, - * see for example {@code goog.html.SafeHtml}. If available, client code that - * needs to ensure type membership of an object should use the type's function - * to assert type membership, such as {@code goog.html.SafeHtml.unwrap}. - * @interface - */ -goog.string.TypedString = function() {}; - - -/** - * Interface marker of the TypedString interface. - * - * This property can be used to determine at runtime whether or not an object - * implements this interface. All implementations of this interface set this - * property to {@code true}. - * @type {boolean} - */ -goog.string.TypedString.prototype.implementsGoogStringTypedString; - - -/** - * Retrieves this wrapped string's value. - * @return {string} The wrapped string's value. - */ -goog.string.TypedString.prototype.getTypedStringValue;
diff --git a/third_party/ink/closure/structs/collection.js b/third_party/ink/closure/structs/collection.js deleted file mode 100644 index 267862c..0000000 --- a/third_party/ink/closure/structs/collection.js +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Defines the collection interface. - * - * @author nnaze@google.com (Nathan Naze) - */ - -goog.provide('goog.structs.Collection'); - - - -/** - * An interface for a collection of values. - * @interface - * @template T - */ -goog.structs.Collection = function() {}; - - -/** - * @param {T} value Value to add to the collection. - */ -goog.structs.Collection.prototype.add; - - -/** - * @param {T} value Value to remove from the collection. - */ -goog.structs.Collection.prototype.remove; - - -/** - * @param {T} value Value to find in the collection. - * @return {boolean} Whether the collection contains the specified value. - */ -goog.structs.Collection.prototype.contains; - - -/** - * @return {number} The number of values stored in the collection. - */ -goog.structs.Collection.prototype.getCount;
diff --git a/third_party/ink/closure/structs/inversionmap.js b/third_party/ink/closure/structs/inversionmap.js deleted file mode 100644 index 009c02aa..0000000 --- a/third_party/ink/closure/structs/inversionmap.js +++ /dev/null
@@ -1,158 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Provides inversion and inversion map functionality for storing - * integer ranges and corresponding values. - * - * @author cibu@google.com (Cibu Johny) - * @author markdavis@google.com (Mark Davis) - */ - -goog.provide('goog.structs.InversionMap'); - -goog.require('goog.array'); -goog.require('goog.asserts'); - - - -/** - * Maps ranges to values. - * @param {Array<number>} rangeArray An array of monotonically - * increasing integer values, with at least one instance. - * @param {Array<T>} valueArray An array of corresponding values. - * Length must be the same as rangeArray. - * @param {boolean=} opt_delta If true, saves only delta from previous value. - * @constructor - * @template T - */ -goog.structs.InversionMap = function(rangeArray, valueArray, opt_delta) { - /** - * @protected {Array<number>} - */ - this.rangeArray = null; - - goog.asserts.assert( - rangeArray.length == valueArray.length, - 'rangeArray and valueArray must have the same length.'); - this.storeInversion_(rangeArray, opt_delta); - - /** @protected {Array<T>} */ - this.values = valueArray; -}; - - -/** - * Stores the integers as ranges (half-open). - * If delta is true, the integers are delta from the previous value and - * will be restored to the absolute value. - * When used as a set, even indices are IN, and odd are OUT. - * @param {Array<number>} rangeArray An array of monotonically - * increasing integer values, with at least one instance. - * @param {boolean=} opt_delta If true, saves only delta from previous value. - * @private - */ -goog.structs.InversionMap.prototype.storeInversion_ = function( - rangeArray, opt_delta) { - this.rangeArray = rangeArray; - - for (var i = 1; i < rangeArray.length; i++) { - if (rangeArray[i] == null) { - rangeArray[i] = rangeArray[i - 1] + 1; - } else if (opt_delta) { - rangeArray[i] += rangeArray[i - 1]; - } - } -}; - - -/** - * Splices a range -> value map into this inversion map. - * @param {Array<number>} rangeArray An array of monotonically - * increasing integer values, with at least one instance. - * @param {Array<T>} valueArray An array of corresponding values. - * Length must be the same as rangeArray. - * @param {boolean=} opt_delta If true, saves only delta from previous value. - */ -goog.structs.InversionMap.prototype.spliceInversion = function( - rangeArray, valueArray, opt_delta) { - // By building another inversion map, we build the arrays that we need - // to splice in. - var otherMap = - new goog.structs.InversionMap(rangeArray, valueArray, opt_delta); - - // Figure out where to splice those arrays. - var startRange = otherMap.rangeArray[0]; - var endRange = - /** @type {number} */ (goog.array.peek(otherMap.rangeArray)); - var startSplice = this.getLeast(startRange); - var endSplice = this.getLeast(endRange); - - // The inversion map works by storing the start points of ranges... - if (startRange != this.rangeArray[startSplice]) { - // ...if we're splicing in a start point that isn't already here, - // then we need to insert it after the insertion point. - startSplice++; - } // otherwise we overwrite the insertion point. - - this.rangeArray = this.rangeArray.slice(0, startSplice) - .concat(otherMap.rangeArray) - .concat(this.rangeArray.slice(endSplice + 1)); - this.values = this.values.slice(0, startSplice) - .concat(otherMap.values) - .concat(this.values.slice(endSplice + 1)); -}; - - -/** - * Gets the value corresponding to a number from the inversion map. - * @param {number} intKey The number for which value needs to be retrieved - * from inversion map. - * @return {T|null} Value retrieved from inversion map; null if not found. - */ -goog.structs.InversionMap.prototype.at = function(intKey) { - var index = this.getLeast(intKey); - if (index < 0) { - return null; - } - return this.values[index]; -}; - - -/** - * Gets the largest index such that rangeArray[index] <= intKey from the - * inversion map. - * @param {number} intKey The probe for which rangeArray is searched. - * @return {number} Largest index such that rangeArray[index] <= intKey. - * @protected - */ -goog.structs.InversionMap.prototype.getLeast = function(intKey) { - var arr = this.rangeArray; - var low = 0; - var high = arr.length; - while (high - low > 8) { - var mid = (high + low) >> 1; - if (arr[mid] <= intKey) { - low = mid; - } else { - high = mid; - } - } - for (; low < high; ++low) { - if (intKey < arr[low]) { - break; - } - } - return low - 1; -};
diff --git a/third_party/ink/closure/structs/map.js b/third_party/ink/closure/structs/map.js deleted file mode 100644 index ccc8184..0000000 --- a/third_party/ink/closure/structs/map.js +++ /dev/null
@@ -1,485 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Datastructure: Hash Map. - * - * @author arv@google.com (Erik Arvidsson) - * @author jonp@google.com (Jon Perlow) Optimized for IE6 - * - * This file contains an implementation of a Map structure. It implements a lot - * of the methods used in goog.structs so those functions work on hashes. This - * is best suited for complex key types. For simple keys such as numbers and - * strings consider using the lighter-weight utilities in goog.object. - * MOE:begin_intracomment_strip - * - * NOTE(flan): Internally, key types are NOT actually cast to - * strings. Some people actually rely on this behavior even though it - * is incorrect. For more information, see http://b/5622311. - * - * NOTE(flan): Erik Corry (erikcorry) from the V8 team went over this - * class with me to help look for simplifications and - * optimizations. In the end, he didn't come up with very much. Erik - * explained that "for (k in o)" is not optimized in Crankshaft - * because it needs to look up properties in the whole prototype - * chain. It also needs to return the keys in order. Thus keeping an - * array of keys is actually much more efficient. - * - * Likewise, one option to iterate safely with "for (k in o)" is to - * prefix the keys with some character, like ':'. This can create a - * lot of strings that didn't exist before. In Closure Labs, - * goog.labs.structs.Map uses extra arrays to store non-safe keys and - * values. - * - * Thus, there are not a lot of reasonable simplifications that can be - * done here without impacting performance. - * - * TODO(chrishenry): Create some performance benchmarks for common - * operations. - * MOE:end_intracomment_strip - */ - - -goog.provide('goog.structs.Map'); - -goog.require('goog.iter.Iterator'); -goog.require('goog.iter.StopIteration'); -goog.require('goog.object'); - - - -/** - * Class for Hash Map datastructure. - * @param {*=} opt_map Map or Object to initialize the map with. - * @param {...*} var_args If 2 or more arguments are present then they - * will be used as key-value pairs. - * @constructor - * @template K, V - * @deprecated This type is misleading: use ES6 Map instead. - */ -goog.structs.Map = function(opt_map, var_args) { - - /** - * Underlying JS object used to implement the map. - * @private {!Object} - */ - this.map_ = {}; - - /** - * An array of keys. This is necessary for two reasons: - * 1. Iterating the keys using for (var key in this.map_) allocates an - * object for every key in IE which is really bad for IE6 GC perf. - * 2. Without a side data structure, we would need to escape all the keys - * as that would be the only way we could tell during iteration if the - * key was an internal key or a property of the object. - * - * This array can contain deleted keys so it's necessary to check the map - * as well to see if the key is still in the map (this doesn't require a - * memory allocation in IE). - * @private {!Array<string>} - */ - this.keys_ = []; - - /** - * The number of key value pairs in the map. - * @private {number} - */ - this.count_ = 0; - - /** - * Version used to detect changes while iterating. - * @private {number} - */ - this.version_ = 0; - - var argLength = arguments.length; - - if (argLength > 1) { - if (argLength % 2) { - throw new Error('Uneven number of arguments'); - } - for (var i = 0; i < argLength; i += 2) { - this.set(arguments[i], arguments[i + 1]); - } - } else if (opt_map) { - this.addAll(/** @type {Object} */ (opt_map)); - } -}; - - -/** - * @return {number} The number of key-value pairs in the map. - */ -goog.structs.Map.prototype.getCount = function() { - return this.count_; -}; - - -/** - * Returns the values of the map. - * @return {!Array<V>} The values in the map. - */ -goog.structs.Map.prototype.getValues = function() { - this.cleanupKeysArray_(); - - var rv = []; - for (var i = 0; i < this.keys_.length; i++) { - var key = this.keys_[i]; - rv.push(this.map_[key]); - } - return rv; -}; - - -/** - * Returns the keys of the map. - * @return {!Array<string>} Array of string values. - */ -goog.structs.Map.prototype.getKeys = function() { - this.cleanupKeysArray_(); - return /** @type {!Array<string>} */ (this.keys_.concat()); -}; - - -/** - * Whether the map contains the given key. - * @param {*} key The key to check for. - * @return {boolean} Whether the map contains the key. - */ -goog.structs.Map.prototype.containsKey = function(key) { - return goog.structs.Map.hasKey_(this.map_, key); -}; - - -/** - * Whether the map contains the given value. This is O(n). - * @param {V} val The value to check for. - * @return {boolean} Whether the map contains the value. - */ -goog.structs.Map.prototype.containsValue = function(val) { - for (var i = 0; i < this.keys_.length; i++) { - var key = this.keys_[i]; - if (goog.structs.Map.hasKey_(this.map_, key) && this.map_[key] == val) { - return true; - } - } - return false; -}; - - -/** - * Whether this map is equal to the argument map. - * @param {goog.structs.Map} otherMap The map against which to test equality. - * @param {function(V, V): boolean=} opt_equalityFn Optional equality function - * to test equality of values. If not specified, this will test whether - * the values contained in each map are identical objects. - * @return {boolean} Whether the maps are equal. - */ -goog.structs.Map.prototype.equals = function(otherMap, opt_equalityFn) { - if (this === otherMap) { - return true; - } - - if (this.count_ != otherMap.getCount()) { - return false; - } - - var equalityFn = opt_equalityFn || goog.structs.Map.defaultEquals; - - this.cleanupKeysArray_(); - for (var key, i = 0; key = this.keys_[i]; i++) { - if (!equalityFn(this.get(key), otherMap.get(key))) { - return false; - } - } - - return true; -}; - - -/** - * Default equality test for values. - * @param {*} a The first value. - * @param {*} b The second value. - * @return {boolean} Whether a and b reference the same object. - */ -goog.structs.Map.defaultEquals = function(a, b) { - return a === b; -}; - - -/** - * @return {boolean} Whether the map is empty. - */ -goog.structs.Map.prototype.isEmpty = function() { - return this.count_ == 0; -}; - - -/** - * Removes all key-value pairs from the map. - */ -goog.structs.Map.prototype.clear = function() { - this.map_ = {}; - this.keys_.length = 0; - this.count_ = 0; - this.version_ = 0; -}; - - -/** - * Removes a key-value pair based on the key. This is O(logN) amortized due to - * updating the keys array whenever the count becomes half the size of the keys - * in the keys array. - * @param {*} key The key to remove. - * @return {boolean} Whether object was removed. - */ -goog.structs.Map.prototype.remove = function(key) { - if (goog.structs.Map.hasKey_(this.map_, key)) { - delete this.map_[key]; - this.count_--; - this.version_++; - - // clean up the keys array if the threshold is hit - if (this.keys_.length > 2 * this.count_) { - this.cleanupKeysArray_(); - } - - return true; - } - return false; -}; - - -/** - * Cleans up the temp keys array by removing entries that are no longer in the - * map. - * @private - */ -goog.structs.Map.prototype.cleanupKeysArray_ = function() { - if (this.count_ != this.keys_.length) { - // First remove keys that are no longer in the map. - var srcIndex = 0; - var destIndex = 0; - while (srcIndex < this.keys_.length) { - var key = this.keys_[srcIndex]; - if (goog.structs.Map.hasKey_(this.map_, key)) { - this.keys_[destIndex++] = key; - } - srcIndex++; - } - this.keys_.length = destIndex; - } - - if (this.count_ != this.keys_.length) { - // If the count still isn't correct, that means we have duplicates. This can - // happen when the same key is added and removed multiple times. Now we have - // to allocate one extra Object to remove the duplicates. This could have - // been done in the first pass, but in the common case, we can avoid - // allocating an extra object by only doing this when necessary. - var seen = {}; - var srcIndex = 0; - var destIndex = 0; - while (srcIndex < this.keys_.length) { - var key = this.keys_[srcIndex]; - if (!(goog.structs.Map.hasKey_(seen, key))) { - this.keys_[destIndex++] = key; - seen[key] = 1; - } - srcIndex++; - } - this.keys_.length = destIndex; - } -}; - - -/** - * Returns the value for the given key. If the key is not found and the default - * value is not given this will return {@code undefined}. - * @param {*} key The key to get the value for. - * @param {DEFAULT=} opt_val The value to return if no item is found for the - * given key, defaults to undefined. - * @return {V|DEFAULT} The value for the given key. - * @template DEFAULT - */ -goog.structs.Map.prototype.get = function(key, opt_val) { - if (goog.structs.Map.hasKey_(this.map_, key)) { - return this.map_[key]; - } - return opt_val; -}; - - -/** - * Adds a key-value pair to the map. - * @param {*} key The key. - * @param {V} value The value to add. - * @return {*} Some subclasses return a value. - */ -goog.structs.Map.prototype.set = function(key, value) { - if (!(goog.structs.Map.hasKey_(this.map_, key))) { - this.count_++; - // TODO(johnlenz): This class lies, it claims to return an array of string - // keys, but instead returns the original object used. - this.keys_.push(/** @type {?} */ (key)); - // Only change the version if we add a new key. - this.version_++; - } - this.map_[key] = value; -}; - - -/** - * Adds multiple key-value pairs from another goog.structs.Map or Object. - * @param {Object} map Object containing the data to add. - */ -goog.structs.Map.prototype.addAll = function(map) { - var keys, values; - if (map instanceof goog.structs.Map) { - keys = map.getKeys(); - values = map.getValues(); - } else { - keys = goog.object.getKeys(map); - values = goog.object.getValues(map); - } - // we could use goog.array.forEach here but I don't want to introduce that - // dependency just for this. - for (var i = 0; i < keys.length; i++) { - this.set(keys[i], values[i]); - } -}; - - -/** - * Calls the given function on each entry in the map. - * @param {function(this:T, V, K, goog.structs.Map<K,V>)} f - * @param {T=} opt_obj The value of "this" inside f. - * @template T - */ -goog.structs.Map.prototype.forEach = function(f, opt_obj) { - var keys = this.getKeys(); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - var value = this.get(key); - f.call(opt_obj, value, key, this); - } -}; - - -/** - * Clones a map and returns a new map. - * @return {!goog.structs.Map} A new map with the same key-value pairs. - */ -goog.structs.Map.prototype.clone = function() { - return new goog.structs.Map(this); -}; - - -/** - * Returns a new map in which all the keys and values are interchanged - * (keys become values and values become keys). If multiple keys map to the - * same value, the chosen transposed value is implementation-dependent. - * - * It acts very similarly to {goog.object.transpose(Object)}. - * - * @return {!goog.structs.Map} The transposed map. - */ -goog.structs.Map.prototype.transpose = function() { - var transposed = new goog.structs.Map(); - for (var i = 0; i < this.keys_.length; i++) { - var key = this.keys_[i]; - var value = this.map_[key]; - transposed.set(value, key); - } - - return transposed; -}; - - -/** - * @return {!Object} Object representation of the map. - */ -goog.structs.Map.prototype.toObject = function() { - this.cleanupKeysArray_(); - var obj = {}; - for (var i = 0; i < this.keys_.length; i++) { - var key = this.keys_[i]; - obj[key] = this.map_[key]; - } - return obj; -}; - - -/** - * Returns an iterator that iterates over the keys in the map. Removal of keys - * while iterating might have undesired side effects. - * @return {!goog.iter.Iterator} An iterator over the keys in the map. - */ -goog.structs.Map.prototype.getKeyIterator = function() { - return this.__iterator__(true); -}; - - -/** - * Returns an iterator that iterates over the values in the map. Removal of - * keys while iterating might have undesired side effects. - * @return {!goog.iter.Iterator} An iterator over the values in the map. - */ -goog.structs.Map.prototype.getValueIterator = function() { - return this.__iterator__(false); -}; - - -/** - * Returns an iterator that iterates over the values or the keys in the map. - * This throws an exception if the map was mutated since the iterator was - * created. - * @param {boolean=} opt_keys True to iterate over the keys. False to iterate - * over the values. The default value is false. - * @return {!goog.iter.Iterator} An iterator over the values or keys in the map. - */ -goog.structs.Map.prototype.__iterator__ = function(opt_keys) { - // Clean up keys to minimize the risk of iterating over dead keys. - this.cleanupKeysArray_(); - - var i = 0; - var version = this.version_; - var selfObj = this; - - var newIter = new goog.iter.Iterator; - newIter.next = function() { - if (version != selfObj.version_) { - throw new Error('The map has changed since the iterator was created'); - } - if (i >= selfObj.keys_.length) { - throw goog.iter.StopIteration; - } - var key = selfObj.keys_[i++]; - return opt_keys ? key : selfObj.map_[key]; - }; - return newIter; -}; - - -/** - * Safe way to test for hasOwnProperty. It even allows testing for - * 'hasOwnProperty'. - * @param {Object} obj The object to test for presence of the given key. - * @param {*} key The key to check for. - * @return {boolean} Whether the object has the key. - * @private - */ -goog.structs.Map.hasKey_ = function(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -};
diff --git a/third_party/ink/closure/structs/set.js b/third_party/ink/closure/structs/set.js deleted file mode 100644 index e8470ab..0000000 --- a/third_party/ink/closure/structs/set.js +++ /dev/null
@@ -1,280 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Datastructure: Set. - * - * @author arv@google.com (Erik Arvidsson) - * @author pallosp@google.com (Peter Pallos) - * - * This class implements a set data structure. Adding and removing is O(1). It - * supports both object and primitive values. Be careful because you can add - * both 1 and new Number(1), because these are not the same. You can even add - * multiple new Number(1) because these are not equal. - */ - - -goog.provide('goog.structs.Set'); - -goog.require('goog.structs'); -goog.require('goog.structs.Collection'); -goog.require('goog.structs.Map'); - - - -/** - * A set that can contain both primitives and objects. Adding and removing - * elements is O(1). Primitives are treated as identical if they have the same - * type and convert to the same string. Objects are treated as identical only - * if they are references to the same object. WARNING: A goog.structs.Set can - * contain both 1 and (new Number(1)), because they are not the same. WARNING: - * Adding (new Number(1)) twice will yield two distinct elements, because they - * are two different objects. WARNING: Any object that is added to a - * goog.structs.Set will be modified! Because goog.getUid() is used to - * identify objects, every object in the set will be mutated. - * @param {Array<T>|Object<?,T>=} opt_values Initial values to start with. - * @constructor - * @implements {goog.structs.Collection<T>} - * @final - * @template T - * @deprecated This type is misleading: use ES6 Set instead. - */ -goog.structs.Set = function(opt_values) { - this.map_ = new goog.structs.Map; - if (opt_values) { - this.addAll(opt_values); - } -}; - - -/** - * Obtains a unique key for an element of the set. Primitives will yield the - * same key if they have the same type and convert to the same string. Object - * references will yield the same key only if they refer to the same object. - * @param {*} val Object or primitive value to get a key for. - * @return {string} A unique key for this value/object. - * @private - */ -goog.structs.Set.getKey_ = function(val) { - var type = typeof val; - if (type == 'object' && val || type == 'function') { - return 'o' + goog.getUid(/** @type {Object} */ (val)); - } else { - return type.substr(0, 1) + val; - } -}; - - -/** - * @return {number} The number of elements in the set. - * @override - */ -goog.structs.Set.prototype.getCount = function() { - return this.map_.getCount(); -}; - - -/** - * Add a primitive or an object to the set. - * @param {T} element The primitive or object to add. - * @override - */ -goog.structs.Set.prototype.add = function(element) { - this.map_.set(goog.structs.Set.getKey_(element), element); -}; - - -/** - * Adds all the values in the given collection to this set. - * @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection - * containing the elements to add. - */ -goog.structs.Set.prototype.addAll = function(col) { - var values = goog.structs.getValues(col); - var l = values.length; - for (var i = 0; i < l; i++) { - this.add(values[i]); - } -}; - - -/** - * Removes all values in the given collection from this set. - * @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection - * containing the elements to remove. - */ -goog.structs.Set.prototype.removeAll = function(col) { - var values = goog.structs.getValues(col); - var l = values.length; - for (var i = 0; i < l; i++) { - this.remove(values[i]); - } -}; - - -/** - * Removes the given element from this set. - * @param {T} element The primitive or object to remove. - * @return {boolean} Whether the element was found and removed. - * @override - */ -goog.structs.Set.prototype.remove = function(element) { - return this.map_.remove(goog.structs.Set.getKey_(element)); -}; - - -/** - * Removes all elements from this set. - */ -goog.structs.Set.prototype.clear = function() { - this.map_.clear(); -}; - - -/** - * Tests whether this set is empty. - * @return {boolean} True if there are no elements in this set. - */ -goog.structs.Set.prototype.isEmpty = function() { - return this.map_.isEmpty(); -}; - - -/** - * Tests whether this set contains the given element. - * @param {T} element The primitive or object to test for. - * @return {boolean} True if this set contains the given element. - * @override - */ -goog.structs.Set.prototype.contains = function(element) { - return this.map_.containsKey(goog.structs.Set.getKey_(element)); -}; - - -/** - * Tests whether this set contains all the values in a given collection. - * Repeated elements in the collection are ignored, e.g. (new - * goog.structs.Set([1, 2])).containsAll([1, 1]) is True. - * @param {goog.structs.Collection<T>|Object} col A collection-like object. - * @return {boolean} True if the set contains all elements. - */ -goog.structs.Set.prototype.containsAll = function(col) { - return goog.structs.every(col, this.contains, this); -}; - - -/** - * Finds all values that are present in both this set and the given collection. - * @param {Array<S>|Object<?,S>} col A collection. - * @return {!goog.structs.Set<T|S>} A new set containing all the values - * (primitives or objects) present in both this set and the given - * collection. - * @template S - */ -goog.structs.Set.prototype.intersection = function(col) { - var result = new goog.structs.Set(); - - var values = goog.structs.getValues(col); - for (var i = 0; i < values.length; i++) { - var value = values[i]; - if (this.contains(value)) { - result.add(value); - } - } - - return result; -}; - - -/** - * Finds all values that are present in this set and not in the given - * collection. - * @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection. - * @return {!goog.structs.Set} A new set containing all the values - * (primitives or objects) present in this set but not in the given - * collection. - */ -goog.structs.Set.prototype.difference = function(col) { - var result = this.clone(); - result.removeAll(col); - return result; -}; - - -/** - * Returns an array containing all the elements in this set. - * @return {!Array<T>} An array containing all the elements in this set. - */ -goog.structs.Set.prototype.getValues = function() { - return this.map_.getValues(); -}; - - -/** - * Creates a shallow clone of this set. - * @return {!goog.structs.Set<T>} A new set containing all the same elements as - * this set. - */ -goog.structs.Set.prototype.clone = function() { - return new goog.structs.Set(this); -}; - - -/** - * Tests whether the given collection consists of the same elements as this set, - * regardless of order, without repetition. Primitives are treated as equal if - * they have the same type and convert to the same string; objects are treated - * as equal if they are references to the same object. This operation is O(n). - * @param {goog.structs.Collection<T>|Object} col A collection. - * @return {boolean} True if the given collection consists of the same elements - * as this set, regardless of order, without repetition. - */ -goog.structs.Set.prototype.equals = function(col) { - return this.getCount() == goog.structs.getCount(col) && this.isSubsetOf(col); -}; - - -/** - * Tests whether the given collection contains all the elements in this set. - * Primitives are treated as equal if they have the same type and convert to the - * same string; objects are treated as equal if they are references to the same - * object. This operation is O(n). - * @param {goog.structs.Collection<T>|Object} col A collection. - * @return {boolean} True if this set is a subset of the given collection. - */ -goog.structs.Set.prototype.isSubsetOf = function(col) { - var colCount = goog.structs.getCount(col); - if (this.getCount() > colCount) { - return false; - } - // TODO(pallosp) Find the minimal collection size where the conversion makes - // the contains() method faster. - if (!(col instanceof goog.structs.Set) && colCount > 5) { - // Convert to a goog.structs.Set so that goog.structs.contains runs in - // O(1) time instead of O(n) time. - col = new goog.structs.Set(col); - } - return goog.structs.every( - this, function(value) { return goog.structs.contains(col, value); }); -}; - - -/** - * Returns an iterator that iterates over the elements in this set. - * @param {boolean=} opt_keys This argument is ignored. - * @return {!goog.iter.Iterator} An iterator over the elements in this set. - */ -goog.structs.Set.prototype.__iterator__ = function(opt_keys) { - return this.map_.__iterator__(false); -};
diff --git a/third_party/ink/closure/structs/structs.js b/third_party/ink/closure/structs/structs.js deleted file mode 100644 index 684ddfe4..0000000 --- a/third_party/ink/closure/structs/structs.js +++ /dev/null
@@ -1,354 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Generics method for collection-like classes and objects. - * - * @author arv@google.com (Erik Arvidsson) - * - * This file contains functions to work with collections. It supports using - * Map, Set, Array and Object and other classes that implement collection-like - * methods. - */ - - -goog.provide('goog.structs'); - -goog.require('goog.array'); -goog.require('goog.object'); - - -// We treat an object as a dictionary if it has getKeys or it is an object that -// isn't arrayLike. - - -/** - * Returns the number of values in the collection-like object. - * @param {Object} col The collection-like object. - * @return {number} The number of values in the collection-like object. - */ -goog.structs.getCount = function(col) { - if (col.getCount && typeof col.getCount == 'function') { - return col.getCount(); - } - if (goog.isArrayLike(col) || goog.isString(col)) { - return col.length; - } - return goog.object.getCount(col); -}; - - -/** - * Returns the values of the collection-like object. - * @param {Object} col The collection-like object. - * @return {!Array<?>} The values in the collection-like object. - */ -goog.structs.getValues = function(col) { - if (col.getValues && typeof col.getValues == 'function') { - return col.getValues(); - } - if (goog.isString(col)) { - return col.split(''); - } - if (goog.isArrayLike(col)) { - var rv = []; - var l = col.length; - for (var i = 0; i < l; i++) { - rv.push(col[i]); - } - return rv; - } - return goog.object.getValues(col); -}; - - -/** - * Returns the keys of the collection. Some collections have no notion of - * keys/indexes and this function will return undefined in those cases. - * @param {Object} col The collection-like object. - * @return {!Array|undefined} The keys in the collection. - */ -goog.structs.getKeys = function(col) { - if (col.getKeys && typeof col.getKeys == 'function') { - return col.getKeys(); - } - // if we have getValues but no getKeys we know this is a key-less collection - if (col.getValues && typeof col.getValues == 'function') { - return undefined; - } - if (goog.isArrayLike(col) || goog.isString(col)) { - var rv = []; - var l = col.length; - for (var i = 0; i < l; i++) { - rv.push(i); - } - return rv; - } - - return goog.object.getKeys(col); -}; - - -/** - * Whether the collection contains the given value. This is O(n) and uses - * equals (==) to test the existence. - * @param {Object} col The collection-like object. - * @param {*} val The value to check for. - * @return {boolean} True if the map contains the value. - */ -goog.structs.contains = function(col, val) { - if (col.contains && typeof col.contains == 'function') { - return col.contains(val); - } - if (col.containsValue && typeof col.containsValue == 'function') { - return col.containsValue(val); - } - if (goog.isArrayLike(col) || goog.isString(col)) { - return goog.array.contains(/** @type {!Array<?>} */ (col), val); - } - return goog.object.containsValue(col, val); -}; - - -/** - * Whether the collection is empty. - * @param {Object} col The collection-like object. - * @return {boolean} True if empty. - */ -goog.structs.isEmpty = function(col) { - if (col.isEmpty && typeof col.isEmpty == 'function') { - return col.isEmpty(); - } - - // We do not use goog.string.isEmptyOrWhitespace because here we treat the - // string as - // collection and as such even whitespace matters - - if (goog.isArrayLike(col) || goog.isString(col)) { - return goog.array.isEmpty(/** @type {!Array<?>} */ (col)); - } - return goog.object.isEmpty(col); -}; - - -/** - * Removes all the elements from the collection. - * @param {Object} col The collection-like object. - */ -goog.structs.clear = function(col) { - // NOTE(arv): This should not contain strings because strings are immutable - if (col.clear && typeof col.clear == 'function') { - col.clear(); - } else if (goog.isArrayLike(col)) { - goog.array.clear(/** @type {IArrayLike<?>} */ (col)); - } else { - goog.object.clear(col); - } -}; - - -/** - * Calls a function for each value in a collection. The function takes - * three arguments; the value, the key and the collection. - * - * @param {S} col The collection-like object. - * @param {function(this:T,?,?,S):?} f The function to call for every value. - * This function takes - * 3 arguments (the value, the key or undefined if the collection has no - * notion of keys, and the collection) and the return value is irrelevant. - * @param {T=} opt_obj The object to be used as the value of 'this' - * within {@code f}. - * @template T,S - * @deprecated Use a more specific method, e.g. goog.array.forEach, - * goog.object.forEach, or for-of. - */ -goog.structs.forEach = function(col, f, opt_obj) { - if (col.forEach && typeof col.forEach == 'function') { - col.forEach(f, opt_obj); - } else if (goog.isArrayLike(col) || goog.isString(col)) { - goog.array.forEach(/** @type {!Array<?>} */ (col), f, opt_obj); - } else { - var keys = goog.structs.getKeys(col); - var values = goog.structs.getValues(col); - var l = values.length; - for (var i = 0; i < l; i++) { - f.call(/** @type {?} */ (opt_obj), values[i], keys && keys[i], col); - } - } -}; - - -/** - * Calls a function for every value in the collection. When a call returns true, - * adds the value to a new collection (Array is returned by default). - * - * @param {S} col The collection-like object. - * @param {function(this:T,?,?,S):boolean} f The function to call for every - * value. This function takes - * 3 arguments (the value, the key or undefined if the collection has no - * notion of keys, and the collection) and should return a Boolean. If the - * return value is true the value is added to the result collection. If it - * is false the value is not included. - * @param {T=} opt_obj The object to be used as the value of 'this' - * within {@code f}. - * @return {!Object|!Array<?>} A new collection where the passed values are - * present. If col is a key-less collection an array is returned. If col - * has keys and values a plain old JS object is returned. - * @template T,S - */ -goog.structs.filter = function(col, f, opt_obj) { - if (typeof col.filter == 'function') { - return col.filter(f, opt_obj); - } - if (goog.isArrayLike(col) || goog.isString(col)) { - return goog.array.filter(/** @type {!Array<?>} */ (col), f, opt_obj); - } - - var rv; - var keys = goog.structs.getKeys(col); - var values = goog.structs.getValues(col); - var l = values.length; - if (keys) { - rv = {}; - for (var i = 0; i < l; i++) { - if (f.call(/** @type {?} */ (opt_obj), values[i], keys[i], col)) { - rv[keys[i]] = values[i]; - } - } - } else { - // We should not use goog.array.filter here since we want to make sure that - // the index is undefined as well as make sure that col is passed to the - // function. - rv = []; - for (var i = 0; i < l; i++) { - if (f.call(opt_obj, values[i], undefined, col)) { - rv.push(values[i]); - } - } - } - return rv; -}; - - -/** - * Calls a function for every value in the collection and adds the result into a - * new collection (defaults to creating a new Array). - * - * @param {S} col The collection-like object. - * @param {function(this:T,?,?,S):V} f The function to call for every value. - * This function takes 3 arguments (the value, the key or undefined if the - * collection has no notion of keys, and the collection) and should return - * something. The result will be used as the value in the new collection. - * @param {T=} opt_obj The object to be used as the value of 'this' - * within {@code f}. - * @return {!Object<V>|!Array<V>} A new collection with the new values. If - * col is a key-less collection an array is returned. If col has keys and - * values a plain old JS object is returned. - * @template T,S,V - */ -goog.structs.map = function(col, f, opt_obj) { - if (typeof col.map == 'function') { - return col.map(f, opt_obj); - } - if (goog.isArrayLike(col) || goog.isString(col)) { - return goog.array.map(/** @type {!Array<?>} */ (col), f, opt_obj); - } - - var rv; - var keys = goog.structs.getKeys(col); - var values = goog.structs.getValues(col); - var l = values.length; - if (keys) { - rv = {}; - for (var i = 0; i < l; i++) { - rv[keys[i]] = f.call(/** @type {?} */ (opt_obj), values[i], keys[i], col); - } - } else { - // We should not use goog.array.map here since we want to make sure that - // the index is undefined as well as make sure that col is passed to the - // function. - rv = []; - for (var i = 0; i < l; i++) { - rv[i] = f.call(/** @type {?} */ (opt_obj), values[i], undefined, col); - } - } - return rv; -}; - - -/** - * Calls f for each value in a collection. If any call returns true this returns - * true (without checking the rest). If all returns false this returns false. - * - * @param {S} col The collection-like object. - * @param {function(this:T,?,?,S):boolean} f The function to call for every - * value. This function takes 3 arguments (the value, the key or undefined - * if the collection has no notion of keys, and the collection) and should - * return a boolean. - * @param {T=} opt_obj The object to be used as the value of 'this' - * within {@code f}. - * @return {boolean} True if any value passes the test. - * @template T,S - */ -goog.structs.some = function(col, f, opt_obj) { - if (typeof col.some == 'function') { - return col.some(f, opt_obj); - } - if (goog.isArrayLike(col) || goog.isString(col)) { - return goog.array.some(/** @type {!Array<?>} */ (col), f, opt_obj); - } - var keys = goog.structs.getKeys(col); - var values = goog.structs.getValues(col); - var l = values.length; - for (var i = 0; i < l; i++) { - if (f.call(/** @type {?} */ (opt_obj), values[i], keys && keys[i], col)) { - return true; - } - } - return false; -}; - - -/** - * Calls f for each value in a collection. If all calls return true this return - * true this returns true. If any returns false this returns false at this point - * and does not continue to check the remaining values. - * - * @param {S} col The collection-like object. - * @param {function(this:T,?,?,S):boolean} f The function to call for every - * value. This function takes 3 arguments (the value, the key or - * undefined if the collection has no notion of keys, and the collection) - * and should return a boolean. - * @param {T=} opt_obj The object to be used as the value of 'this' - * within {@code f}. - * @return {boolean} True if all key-value pairs pass the test. - * @template T,S - */ -goog.structs.every = function(col, f, opt_obj) { - if (typeof col.every == 'function') { - return col.every(f, opt_obj); - } - if (goog.isArrayLike(col) || goog.isString(col)) { - return goog.array.every(/** @type {!Array<?>} */ (col), f, opt_obj); - } - var keys = goog.structs.getKeys(col); - var values = goog.structs.getValues(col); - var l = values.length; - for (var i = 0; i < l; i++) { - if (!f.call(/** @type {?} */ (opt_obj), values[i], keys && keys[i], col)) { - return false; - } - } - return true; -};
diff --git a/third_party/ink/closure/style/style.js b/third_party/ink/closure/style/style.js deleted file mode 100644 index ff44b099..0000000 --- a/third_party/ink/closure/style/style.js +++ /dev/null
@@ -1,2046 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for element styles. - * - * @author pupius@google.com (Daniel Pupius) - * @author arv@google.com (Erik Arvidsson) - * @author eae@google.com (Emil A Eklund) - * @author pallosp@google.com (Peter Pallos) - * @see ../demos/inline_block_quirks.html - * @see ../demos/inline_block_standards.html - * @see ../demos/style_viewport.html - */ - -goog.provide('goog.style'); - - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.vendor'); -goog.require('goog.html.SafeStyleSheet'); -goog.require('goog.math.Box'); -goog.require('goog.math.Coordinate'); -goog.require('goog.math.Rect'); -goog.require('goog.math.Size'); -goog.require('goog.object'); -goog.require('goog.reflect'); -goog.require('goog.string'); -goog.require('goog.userAgent'); - -goog.forwardDeclare('goog.events.Event'); - - -/** - * Sets a style value on an element. - * - * This function is not indended to patch issues in the browser's style - * handling, but to allow easy programmatic access to setting dash-separated - * style properties. An example is setting a batch of properties from a data - * object without overwriting old styles. When possible, use native APIs: - * elem.style.propertyKey = 'value' or (if obliterating old styles is fine) - * elem.style.cssText = 'property1: value1; property2: value2'. - * - * @param {Element} element The element to change. - * @param {string|Object} style If a string, a style name. If an object, a hash - * of style names to style values. - * @param {string|number|boolean=} opt_value If style was a string, then this - * should be the value. - */ -goog.style.setStyle = function(element, style, opt_value) { - if (goog.isString(style)) { - goog.style.setStyle_(element, opt_value, style); - } else { - for (var key in style) { - goog.style.setStyle_(element, style[key], key); - } - } -}; - - -/** - * Sets a style value on an element, with parameters swapped to work with - * {@code goog.object.forEach()}. Prepends a vendor-specific prefix when - * necessary. - * @param {Element} element The element to change. - * @param {string|number|boolean|undefined} value Style value. - * @param {string} style Style name. - * @private - */ -goog.style.setStyle_ = function(element, value, style) { - var propertyName = goog.style.getVendorJsStyleName_(element, style); - - if (propertyName) { - // TODO(johnlenz): coerce to string? - element.style[propertyName] = /** @type {?} */ (value); - } -}; - - -/** - * Style name cache that stores previous property name lookups. - * - * This is used by setStyle to speed up property lookups, entries look like: - * { StyleName: ActualPropertyName } - * - * @private {!Object<string, string>} - */ -goog.style.styleNameCache_ = {}; - - -/** - * Returns the style property name in camel-case. If it does not exist and a - * vendor-specific version of the property does exist, then return the vendor- - * specific property name instead. - * @param {Element} element The element to change. - * @param {string} style Style name. - * @return {string} Vendor-specific style. - * @private - */ -goog.style.getVendorJsStyleName_ = function(element, style) { - var propertyName = goog.style.styleNameCache_[style]; - if (!propertyName) { - var camelStyle = goog.string.toCamelCase(style); - propertyName = camelStyle; - - if (element.style[camelStyle] === undefined) { - var prefixedStyle = goog.dom.vendor.getVendorJsPrefix() + - goog.string.toTitleCase(camelStyle); - - if (element.style[prefixedStyle] !== undefined) { - propertyName = prefixedStyle; - } - } - goog.style.styleNameCache_[style] = propertyName; - } - - return propertyName; -}; - - -/** - * Returns the style property name in CSS notation. If it does not exist and a - * vendor-specific version of the property does exist, then return the vendor- - * specific property name instead. - * @param {Element} element The element to change. - * @param {string} style Style name. - * @return {string} Vendor-specific style. - * @private - */ -goog.style.getVendorStyleName_ = function(element, style) { - var camelStyle = goog.string.toCamelCase(style); - - if (element.style[camelStyle] === undefined) { - var prefixedStyle = goog.dom.vendor.getVendorJsPrefix() + - goog.string.toTitleCase(camelStyle); - - if (element.style[prefixedStyle] !== undefined) { - return goog.dom.vendor.getVendorPrefix() + '-' + style; - } - } - - return style; -}; - - -/** - * Retrieves an explicitly-set style value of a node. This returns '' if there - * isn't a style attribute on the element or if this style property has not been - * explicitly set in script. - * - * @param {Element} element Element to get style of. - * @param {string} property Property to get, css-style (if you have a camel-case - * property, use element.style[style]). - * @return {string} Style value. - */ -goog.style.getStyle = function(element, property) { - // element.style is '' for well-known properties which are unset. - // For for browser specific styles as 'filter' is undefined - // so we need to return '' explicitly to make it consistent across - // browsers. - var styleValue = element.style[goog.string.toCamelCase(property)]; - - // Using typeof here because of a bug in Safari 5.1, where this value - // was undefined, but === undefined returned false. - if (typeof(styleValue) !== 'undefined') { - return styleValue; - } - - return element.style[goog.style.getVendorJsStyleName_(element, property)] || - ''; -}; - - -/** - * Retrieves a computed style value of a node. It returns empty string if the - * value cannot be computed (which will be the case in Internet Explorer) or - * "none" if the property requested is an SVG one and it has not been - * explicitly set (firefox and webkit). - * - * @param {Element} element Element to get style of. - * @param {string} property Property to get (camel-case). - * @return {string} Style value. - */ -goog.style.getComputedStyle = function(element, property) { - var doc = goog.dom.getOwnerDocument(element); - if (doc.defaultView && doc.defaultView.getComputedStyle) { - var styles = doc.defaultView.getComputedStyle(element, null); - if (styles) { - // element.style[..] is undefined for browser specific styles - // as 'filter'. - return styles[property] || styles.getPropertyValue(property) || ''; - } - } - - return ''; -}; - - -/** - * Gets the cascaded style value of a node, or null if the value cannot be - * computed (only Internet Explorer can do this). - * - * @param {Element} element Element to get style of. - * @param {string} style Property to get (camel-case). - * @return {string} Style value. - */ -goog.style.getCascadedStyle = function(element, style) { - // TODO(nicksantos): This should be documented to return null. #fixTypes - return /** @type {string} */ ( - element.currentStyle ? element.currentStyle[style] : null); -}; - - -/** - * Cross-browser pseudo get computed style. It returns the computed style where - * available. If not available it tries the cascaded style value (IE - * currentStyle) and in worst case the inline style value. It shouldn't be - * called directly, see http://wiki/Main/ComputedStyleVsCascadedStyle for - * discussion. - * - * @param {Element} element Element to get style of. - * @param {string} style Property to get (must be camelCase, not css-style.). - * @return {string} Style value. - * @private - */ -goog.style.getStyle_ = function(element, style) { - return goog.style.getComputedStyle(element, style) || - goog.style.getCascadedStyle(element, style) || - (element.style && element.style[style]); -}; - - -/** - * Retrieves the computed value of the box-sizing CSS attribute. - * Browser support: http://caniuse.com/css3-boxsizing. - * @param {!Element} element The element whose box-sizing to get. - * @return {?string} 'content-box', 'border-box' or 'padding-box'. null if - * box-sizing is not supported (IE7 and below). - */ -goog.style.getComputedBoxSizing = function(element) { - return goog.style.getStyle_(element, 'boxSizing') || - goog.style.getStyle_(element, 'MozBoxSizing') || - goog.style.getStyle_(element, 'WebkitBoxSizing') || null; -}; - - -/** - * Retrieves the computed value of the position CSS attribute. - * @param {Element} element The element to get the position of. - * @return {string} Position value. - */ -goog.style.getComputedPosition = function(element) { - return goog.style.getStyle_(element, 'position'); -}; - - -/** - * Retrieves the computed background color string for a given element. The - * string returned is suitable for assigning to another element's - * background-color, but is not guaranteed to be in any particular string - * format. Accessing the color in a numeric form may not be possible in all - * browsers or with all input. - * - * If the background color for the element is defined as a hexadecimal value, - * the resulting string can be parsed by goog.color.parse in all supported - * browsers. - * - * Whether named colors like "red" or "lightblue" get translated into a - * format which can be parsed is browser dependent. Calling this function on - * transparent elements will return "transparent" in most browsers or - * "rgba(0, 0, 0, 0)" in WebKit. - * @param {Element} element The element to get the background color of. - * @return {string} The computed string value of the background color. - */ -goog.style.getBackgroundColor = function(element) { - return goog.style.getStyle_(element, 'backgroundColor'); -}; - - -/** - * Retrieves the computed value of the overflow-x CSS attribute. - * @param {Element} element The element to get the overflow-x of. - * @return {string} The computed string value of the overflow-x attribute. - */ -goog.style.getComputedOverflowX = function(element) { - return goog.style.getStyle_(element, 'overflowX'); -}; - - -/** - * Retrieves the computed value of the overflow-y CSS attribute. - * @param {Element} element The element to get the overflow-y of. - * @return {string} The computed string value of the overflow-y attribute. - */ -goog.style.getComputedOverflowY = function(element) { - return goog.style.getStyle_(element, 'overflowY'); -}; - - -/** - * Retrieves the computed value of the z-index CSS attribute. - * @param {Element} element The element to get the z-index of. - * @return {string|number} The computed value of the z-index attribute. - */ -goog.style.getComputedZIndex = function(element) { - return goog.style.getStyle_(element, 'zIndex'); -}; - - -/** - * Retrieves the computed value of the text-align CSS attribute. - * @param {Element} element The element to get the text-align of. - * @return {string} The computed string value of the text-align attribute. - */ -goog.style.getComputedTextAlign = function(element) { - return goog.style.getStyle_(element, 'textAlign'); -}; - - -/** - * Retrieves the computed value of the cursor CSS attribute. - * @param {Element} element The element to get the cursor of. - * @return {string} The computed string value of the cursor attribute. - */ -goog.style.getComputedCursor = function(element) { - return goog.style.getStyle_(element, 'cursor'); -}; - - -/** - * Retrieves the computed value of the CSS transform attribute. - * @param {Element} element The element to get the transform of. - * @return {string} The computed string representation of the transform matrix. - */ -goog.style.getComputedTransform = function(element) { - var property = goog.style.getVendorStyleName_(element, 'transform'); - return goog.style.getStyle_(element, property) || - goog.style.getStyle_(element, 'transform'); -}; - - -/** - * Sets the top/left values of an element. If no unit is specified in the - * argument then it will add px. The second argument is required if the first - * argument is a string or number and is ignored if the first argument - * is a coordinate. - * @param {Element} el Element to move. - * @param {string|number|goog.math.Coordinate} arg1 Left position or coordinate. - * @param {string|number=} opt_arg2 Top position. - */ -goog.style.setPosition = function(el, arg1, opt_arg2) { - var x, y; - - if (arg1 instanceof goog.math.Coordinate) { - x = arg1.x; - y = arg1.y; - } else { - x = arg1; - y = opt_arg2; - } - - el.style.left = goog.style.getPixelStyleValue_( - /** @type {number|string} */ (x), false); - el.style.top = goog.style.getPixelStyleValue_( - /** @type {number|string} */ (y), false); -}; - - -/** - * Gets the offsetLeft and offsetTop properties of an element and returns them - * in a Coordinate object - * @param {Element} element Element. - * @return {!goog.math.Coordinate} The position. - */ -goog.style.getPosition = function(element) { - return new goog.math.Coordinate( - /** @type {!HTMLElement} */ (element).offsetLeft, - /** @type {!HTMLElement} */ (element).offsetTop); -}; - - -/** - * Returns the viewport element for a particular document - * @param {Node=} opt_node DOM node (Document is OK) to get the viewport element - * of. - * @return {Element} document.documentElement or document.body. - */ -goog.style.getClientViewportElement = function(opt_node) { - var doc; - if (opt_node) { - doc = goog.dom.getOwnerDocument(opt_node); - } else { - doc = goog.dom.getDocument(); - } - - // In old IE versions the document.body represented the viewport - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9) && - !goog.dom.getDomHelper(doc).isCss1CompatMode()) { - return doc.body; - } - return doc.documentElement; -}; - - -/** - * Calculates the viewport coordinates relative to the page/document - * containing the node. The viewport may be the browser viewport for - * non-iframe document, or the iframe container for iframe'd document. - * @param {!Document} doc The document to use as the reference point. - * @return {!goog.math.Coordinate} The page offset of the viewport. - */ -goog.style.getViewportPageOffset = function(doc) { - var body = doc.body; - var documentElement = doc.documentElement; - var scrollLeft = body.scrollLeft || documentElement.scrollLeft; - var scrollTop = body.scrollTop || documentElement.scrollTop; - return new goog.math.Coordinate(scrollLeft, scrollTop); -}; - - -/** - * Gets the client rectangle of the DOM element. - * - * getBoundingClientRect is part of a new CSS object model draft (with a - * long-time presence in IE), replacing the error-prone parent offset - * computation and the now-deprecated Gecko getBoxObjectFor. - * - * This utility patches common browser bugs in getBoundingClientRect. It - * will fail if getBoundingClientRect is unsupported. - * - * If the element is not in the DOM, the result is undefined, and an error may - * be thrown depending on user agent. - * - * @param {!Element} el The element whose bounding rectangle is being queried. - * @return {Object} A native bounding rectangle with numerical left, top, - * right, and bottom. Reported by Firefox to be of object type ClientRect. - * @private - */ -goog.style.getBoundingClientRect_ = function(el) { - var rect; - try { - rect = el.getBoundingClientRect(); - } catch (e) { - // In IE < 9, calling getBoundingClientRect on an orphan element raises an - // "Unspecified Error". All other browsers return zeros. - return {'left': 0, 'top': 0, 'right': 0, 'bottom': 0}; - } - - // Patch the result in IE only, so that this function can be inlined if - // compiled for non-IE. - if (goog.userAgent.IE && el.ownerDocument.body) { - // In IE, most of the time, 2 extra pixels are added to the top and left - // due to the implicit 2-pixel inset border. In IE6/7 quirks mode and - // IE6 standards mode, this border can be overridden by setting the - // document element's border to zero -- thus, we cannot rely on the - // offset always being 2 pixels. - - // In quirks mode, the offset can be determined by querying the body's - // clientLeft/clientTop, but in standards mode, it is found by querying - // the document element's clientLeft/clientTop. Since we already called - // getBoundingClientRect we have already forced a reflow, so it is not - // too expensive just to query them all. - - // See: http://msdn.microsoft.com/en-us/library/ms536433(VS.85).aspx - var doc = el.ownerDocument; - rect.left -= doc.documentElement.clientLeft + doc.body.clientLeft; - rect.top -= doc.documentElement.clientTop + doc.body.clientTop; - } - return rect; -}; - - -/** - * Returns the first parent that could affect the position of a given element. - * @param {Element} element The element to get the offset parent for. - * @return {Element} The first offset parent or null if one cannot be found. - */ -goog.style.getOffsetParent = function(element) { - // element.offsetParent does the right thing in IE7 and below. In other - // browsers it only includes elements with position absolute, relative or - // fixed, not elements with overflow set to auto or scroll. - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(8)) { - goog.asserts.assert(element && 'offsetParent' in element); - return element.offsetParent; - } - - var doc = goog.dom.getOwnerDocument(element); - var positionStyle = goog.style.getStyle_(element, 'position'); - var skipStatic = positionStyle == 'fixed' || positionStyle == 'absolute'; - for (var parent = element.parentNode; parent && parent != doc; - parent = parent.parentNode) { - // Skip shadowDOM roots. - if (parent.nodeType == goog.dom.NodeType.DOCUMENT_FRAGMENT && parent.host) { - parent = parent.host; - } - positionStyle = - goog.style.getStyle_(/** @type {!Element} */ (parent), 'position'); - skipStatic = skipStatic && positionStyle == 'static' && - parent != doc.documentElement && parent != doc.body; - if (!skipStatic && - (parent.scrollWidth > parent.clientWidth || - parent.scrollHeight > parent.clientHeight || - positionStyle == 'fixed' || positionStyle == 'absolute' || - positionStyle == 'relative')) { - return /** @type {!Element} */ (parent); - } - } - return null; -}; - - -/** - * Calculates and returns the visible rectangle for a given element. Returns a - * box describing the visible portion of the nearest scrollable offset ancestor. - * Coordinates are given relative to the document. - * - * @param {Element} element Element to get the visible rect for. - * @return {goog.math.Box} Bounding elementBox describing the visible rect or - * null if scrollable ancestor isn't inside the visible viewport. - */ -goog.style.getVisibleRectForElement = function(element) { - var visibleRect = new goog.math.Box(0, Infinity, Infinity, 0); - var dom = goog.dom.getDomHelper(element); - var body = dom.getDocument().body; - var documentElement = dom.getDocument().documentElement; - var scrollEl = dom.getDocumentScrollElement(); - - // Determine the size of the visible rect by climbing the dom accounting for - // all scrollable containers. - for (var el = element; el = goog.style.getOffsetParent(el);) { - // clientWidth is zero for inline block elements in IE. - // on WEBKIT, body element can have clientHeight = 0 and scrollHeight > 0 - if ((!goog.userAgent.IE || el.clientWidth != 0) && - (!goog.userAgent.WEBKIT || el.clientHeight != 0 || el != body) && - // body may have overflow set on it, yet we still get the entire - // viewport. In some browsers, el.offsetParent may be - // document.documentElement, so check for that too. - (el != body && el != documentElement && - goog.style.getStyle_(el, 'overflow') != 'visible')) { - var pos = goog.style.getPageOffset(el); - var client = goog.style.getClientLeftTop(el); - pos.x += client.x; - pos.y += client.y; - - visibleRect.top = Math.max(visibleRect.top, pos.y); - visibleRect.right = Math.min(visibleRect.right, pos.x + el.clientWidth); - visibleRect.bottom = - Math.min(visibleRect.bottom, pos.y + el.clientHeight); - visibleRect.left = Math.max(visibleRect.left, pos.x); - } - } - - // Clip by window's viewport. - var scrollX = scrollEl.scrollLeft, scrollY = scrollEl.scrollTop; - visibleRect.left = Math.max(visibleRect.left, scrollX); - visibleRect.top = Math.max(visibleRect.top, scrollY); - var winSize = dom.getViewportSize(); - visibleRect.right = Math.min(visibleRect.right, scrollX + winSize.width); - visibleRect.bottom = Math.min(visibleRect.bottom, scrollY + winSize.height); - return visibleRect.top >= 0 && visibleRect.left >= 0 && - visibleRect.bottom > visibleRect.top && - visibleRect.right > visibleRect.left ? - visibleRect : - null; -}; - - -/** - * Calculate the scroll position of {@code container} with the minimum amount so - * that the content and the borders of the given {@code element} become visible. - * If the element is bigger than the container, its top left corner will be - * aligned as close to the container's top left corner as possible. - * - * @param {Element} element The element to make visible. - * @param {Element=} opt_container The container to scroll. If not set, then the - * document scroll element will be used. - * @param {boolean=} opt_center Whether to center the element in the container. - * Defaults to false. - * @return {!goog.math.Coordinate} The new scroll position of the container, - * in form of goog.math.Coordinate(scrollLeft, scrollTop). - */ -goog.style.getContainerOffsetToScrollInto = function( - element, opt_container, opt_center) { - var container = opt_container || goog.dom.getDocumentScrollElement(); - // Absolute position of the element's border's top left corner. - var elementPos = goog.style.getPageOffset(element); - // Absolute position of the container's border's top left corner. - var containerPos = goog.style.getPageOffset(container); - var containerBorder = goog.style.getBorderBox(container); - if (container == goog.dom.getDocumentScrollElement()) { - // The element position is calculated based on the page offset, and the - // document scroll element holds the scroll position within the page. We can - // use the scroll position to calculate the relative position from the - // element. - var relX = elementPos.x - container.scrollLeft; - var relY = elementPos.y - container.scrollTop; - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) { - // In older versions of IE getPageOffset(element) does not include the - // container border so it has to be added to accommodate. - relX += containerBorder.left; - relY += containerBorder.top; - } - } else { - // Relative pos. of the element's border box to the container's content box. - var relX = elementPos.x - containerPos.x - containerBorder.left; - var relY = elementPos.y - containerPos.y - containerBorder.top; - } - // How much the element can move in the container, i.e. the difference between - // the element's bottom-right-most and top-left-most position where it's - // fully visible. - var elementSize = goog.style.getSizeWithDisplay_(element); - var spaceX = container.clientWidth - elementSize.width; - var spaceY = container.clientHeight - elementSize.height; - var scrollLeft = container.scrollLeft; - var scrollTop = container.scrollTop; - if (opt_center) { - // All browsers round non-integer scroll positions down. - scrollLeft += relX - spaceX / 2; - scrollTop += relY - spaceY / 2; - } else { - // This formula was designed to give the correct scroll values in the - // following cases: - // - element is higher than container (spaceY < 0) => scroll down by relY - // - element is not higher that container (spaceY >= 0): - // - it is above container (relY < 0) => scroll up by abs(relY) - // - it is below container (relY > spaceY) => scroll down by relY - spaceY - // - it is in the container => don't scroll - scrollLeft += Math.min(relX, Math.max(relX - spaceX, 0)); - scrollTop += Math.min(relY, Math.max(relY - spaceY, 0)); - } - return new goog.math.Coordinate(scrollLeft, scrollTop); -}; - - -/** - * Changes the scroll position of {@code container} with the minimum amount so - * that the content and the borders of the given {@code element} become visible. - * If the element is bigger than the container, its top left corner will be - * aligned as close to the container's top left corner as possible. - * - * @param {Element} element The element to make visible. - * @param {Element=} opt_container The container to scroll. If not set, then the - * document scroll element will be used. - * @param {boolean=} opt_center Whether to center the element in the container. - * Defaults to false. - */ -goog.style.scrollIntoContainerView = function( - element, opt_container, opt_center) { - var container = opt_container || goog.dom.getDocumentScrollElement(); - var offset = - goog.style.getContainerOffsetToScrollInto(element, container, opt_center); - container.scrollLeft = offset.x; - container.scrollTop = offset.y; -}; - - -/** - * Returns clientLeft (width of the left border and, if the directionality is - * right to left, the vertical scrollbar) and clientTop as a coordinate object. - * - * @param {Element} el Element to get clientLeft for. - * @return {!goog.math.Coordinate} Client left and top. - */ -goog.style.getClientLeftTop = function(el) { - return new goog.math.Coordinate(el.clientLeft, el.clientTop); -}; - - -/** - * Returns a Coordinate object relative to the top-left of the HTML document. - * Implemented as a single function to save having to do two recursive loops in - * opera and safari just to get both coordinates. If you just want one value do - * use goog.style.getPageOffsetLeft() and goog.style.getPageOffsetTop(), but - * note if you call both those methods the tree will be analysed twice. - * - * @param {Element} el Element to get the page offset for. - * @return {!goog.math.Coordinate} The page offset. - */ -goog.style.getPageOffset = function(el) { - var doc = goog.dom.getOwnerDocument(el); - // TODO(gboyer): Update the jsdoc in a way that doesn't break the universe. - goog.asserts.assertObject(el, 'Parameter is required'); - - // NOTE(arv): If element is hidden (display none or disconnected or any the - // ancestors are hidden) we get (0,0) by default but we still do the - // accumulation of scroll position. - - // TODO(arv): Should we check if the node is disconnected and in that case - // return (0,0)? - - var pos = new goog.math.Coordinate(0, 0); - var viewportElement = goog.style.getClientViewportElement(doc); - if (el == viewportElement) { - // viewport is always at 0,0 as that defined the coordinate system for this - // function - this avoids special case checks in the code below - return pos; - } - - var box = goog.style.getBoundingClientRect_(el); - // Must add the scroll coordinates in to get the absolute page offset - // of element since getBoundingClientRect returns relative coordinates to - // the viewport. - var scrollCoord = goog.dom.getDomHelper(doc).getDocumentScroll(); - pos.x = box.left + scrollCoord.x; - pos.y = box.top + scrollCoord.y; - - return pos; -}; - - -/** - * Returns the left coordinate of an element relative to the HTML document - * @param {Element} el Elements. - * @return {number} The left coordinate. - */ -goog.style.getPageOffsetLeft = function(el) { - return goog.style.getPageOffset(el).x; -}; - - -/** - * Returns the top coordinate of an element relative to the HTML document - * @param {Element} el Elements. - * @return {number} The top coordinate. - */ -goog.style.getPageOffsetTop = function(el) { - return goog.style.getPageOffset(el).y; -}; - - -/** - * Returns a Coordinate object relative to the top-left of an HTML document - * in an ancestor frame of this element. Used for measuring the position of - * an element inside a frame relative to a containing frame. - * - * @param {Element} el Element to get the page offset for. - * @param {Window} relativeWin The window to measure relative to. If relativeWin - * is not in the ancestor frame chain of the element, we measure relative to - * the top-most window. - * @return {!goog.math.Coordinate} The page offset. - */ -goog.style.getFramedPageOffset = function(el, relativeWin) { - var position = new goog.math.Coordinate(0, 0); - - // Iterate up the ancestor frame chain, keeping track of the current window - // and the current element in that window. - var currentWin = goog.dom.getWindow(goog.dom.getOwnerDocument(el)); - - // MS Edge throws when accessing "parent" if el's containing iframe has been - // deleted. - if (!goog.reflect.canAccessProperty(currentWin, 'parent')) { - return position; - } - - var currentEl = el; - do { - // if we're at the top window, we want to get the page offset. - // if we're at an inner frame, we only want to get the window position - // so that we can determine the actual page offset in the context of - // the outer window. - var offset = currentWin == relativeWin ? - goog.style.getPageOffset(currentEl) : - goog.style.getClientPositionForElement_(goog.asserts.assert(currentEl)); - - position.x += offset.x; - position.y += offset.y; - } while (currentWin && currentWin != relativeWin && - currentWin != currentWin.parent && - (currentEl = currentWin.frameElement) && - (currentWin = currentWin.parent)); - - return position; -}; - - -/** - * Translates the specified rect relative to origBase page, for newBase page. - * If origBase and newBase are the same, this function does nothing. - * - * @param {goog.math.Rect} rect The source rectangle relative to origBase page, - * and it will have the translated result. - * @param {goog.dom.DomHelper} origBase The DomHelper for the input rectangle. - * @param {goog.dom.DomHelper} newBase The DomHelper for the resultant - * coordinate. This must be a DOM for an ancestor frame of origBase - * or the same as origBase. - */ -goog.style.translateRectForAnotherFrame = function(rect, origBase, newBase) { - if (origBase.getDocument() != newBase.getDocument()) { - var body = origBase.getDocument().body; - var pos = goog.style.getFramedPageOffset(body, newBase.getWindow()); - - // Adjust Body's margin. - pos = goog.math.Coordinate.difference(pos, goog.style.getPageOffset(body)); - - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9) && - !origBase.isCss1CompatMode()) { - pos = goog.math.Coordinate.difference(pos, origBase.getDocumentScroll()); - } - - rect.left += pos.x; - rect.top += pos.y; - } -}; - - -/** - * Returns the position of an element relative to another element in the - * document. A relative to B - * @param {Element|Event|goog.events.Event} a Element or mouse event whose - * position we're calculating. - * @param {Element|Event|goog.events.Event} b Element or mouse event position - * is relative to. - * @return {!goog.math.Coordinate} The relative position. - */ -goog.style.getRelativePosition = function(a, b) { - var ap = goog.style.getClientPosition(a); - var bp = goog.style.getClientPosition(b); - return new goog.math.Coordinate(ap.x - bp.x, ap.y - bp.y); -}; - - -/** - * Returns the position of the event or the element's border box relative to - * the client viewport. - * @param {!Element} el Element whose position to get. - * @return {!goog.math.Coordinate} The position. - * @private - */ -goog.style.getClientPositionForElement_ = function(el) { - var box = goog.style.getBoundingClientRect_(el); - return new goog.math.Coordinate(box.left, box.top); -}; - - -/** - * Returns the position of the event or the element's border box relative to - * the client viewport. If an event is passed, and if this event is a "touch" - * event, then the position of the first changedTouches will be returned. - * @param {Element|Event|goog.events.Event} el Element or a mouse / touch event. - * @return {!goog.math.Coordinate} The position. - */ -goog.style.getClientPosition = function(el) { - goog.asserts.assert(el); - if (el.nodeType == goog.dom.NodeType.ELEMENT) { - return goog.style.getClientPositionForElement_( - /** @type {!Element} */ (el)); - } else { - var targetEvent = el.changedTouches ? el.changedTouches[0] : el; - return new goog.math.Coordinate(targetEvent.clientX, targetEvent.clientY); - } -}; - - -/** - * Moves an element to the given coordinates relative to the client viewport. - * @param {Element} el Absolutely positioned element to set page offset for. - * It must be in the document. - * @param {number|goog.math.Coordinate} x Left position of the element's margin - * box or a coordinate object. - * @param {number=} opt_y Top position of the element's margin box. - */ -goog.style.setPageOffset = function(el, x, opt_y) { - // Get current pageoffset - var cur = goog.style.getPageOffset(el); - - if (x instanceof goog.math.Coordinate) { - opt_y = x.y; - x = x.x; - } - - // NOTE(arv): We cannot allow strings for x and y. We could but that would - // require us to manually transform between different units - - // Work out deltas - var dx = goog.asserts.assertNumber(x) - cur.x; - var dy = Number(opt_y) - cur.y; - - // Set position to current left/top + delta - goog.style.setPosition( - el, /** @type {!HTMLElement} */ (el).offsetLeft + dx, - /** @type {!HTMLElement} */ (el).offsetTop + dy); -}; - - -/** - * Sets the width/height values of an element. If an argument is numeric, - * or a goog.math.Size is passed, it is assumed to be pixels and will add - * 'px' after converting it to an integer in string form. (This just sets the - * CSS width and height properties so it might set content-box or border-box - * size depending on the box model the browser is using.) - * - * @param {Element} element Element to set the size of. - * @param {string|number|goog.math.Size} w Width of the element, or a - * size object. - * @param {string|number=} opt_h Height of the element. Required if w is not a - * size object. - */ -goog.style.setSize = function(element, w, opt_h) { - var h; - if (w instanceof goog.math.Size) { - h = w.height; - w = w.width; - } else { - if (opt_h == undefined) { - throw new Error('missing height argument'); - } - h = opt_h; - } - - goog.style.setWidth(element, /** @type {string|number} */ (w)); - goog.style.setHeight(element, h); -}; - - -/** - * Helper function to create a string to be set into a pixel-value style - * property of an element. Can round to the nearest integer value. - * - * @param {string|number} value The style value to be used. If a number, - * 'px' will be appended, otherwise the value will be applied directly. - * @param {boolean} round Whether to round the nearest integer (if property - * is a number). - * @return {string} The string value for the property. - * @private - */ -goog.style.getPixelStyleValue_ = function(value, round) { - if (typeof value == 'number') { - value = (round ? Math.round(value) : value) + 'px'; - } - - return value; -}; - - -/** - * Set the height of an element. Sets the element's style property. - * @param {Element} element Element to set the height of. - * @param {string|number} height The height value to set. If a number, 'px' - * will be appended, otherwise the value will be applied directly. - */ -goog.style.setHeight = function(element, height) { - element.style.height = goog.style.getPixelStyleValue_(height, true); -}; - - -/** - * Set the width of an element. Sets the element's style property. - * @param {Element} element Element to set the width of. - * @param {string|number} width The width value to set. If a number, 'px' - * will be appended, otherwise the value will be applied directly. - */ -goog.style.setWidth = function(element, width) { - element.style.width = goog.style.getPixelStyleValue_(width, true); -}; - - -/** - * Gets the height and width of an element, even if its display is none. - * - * Specifically, this returns the height and width of the border box, - * irrespective of the box model in effect. - * - * Note that this function does not take CSS transforms into account. Please see - * {@code goog.style.getTransformedSize}. - * @param {Element} element Element to get size of. - * @return {!goog.math.Size} Object with width/height properties. - */ -goog.style.getSize = function(element) { - return goog.style.evaluateWithTemporaryDisplay_( - goog.style.getSizeWithDisplay_, /** @type {!Element} */ (element)); -}; - - -/** - * Call {@code fn} on {@code element} such that {@code element}'s dimensions are - * accurate when it's passed to {@code fn}. - * @param {function(!Element): T} fn Function to call with {@code element} as - * an argument after temporarily changing {@code element}'s display such - * that its dimensions are accurate. - * @param {!Element} element Element (which may have display none) to use as - * argument to {@code fn}. - * @return {T} Value returned by calling {@code fn} with {@code element}. - * @template T - * @private - */ -goog.style.evaluateWithTemporaryDisplay_ = function(fn, element) { - if (goog.style.getStyle_(element, 'display') != 'none') { - return fn(element); - } - - var style = element.style; - var originalDisplay = style.display; - var originalVisibility = style.visibility; - var originalPosition = style.position; - - style.visibility = 'hidden'; - style.position = 'absolute'; - style.display = 'inline'; - - var retVal = fn(element); - - style.display = originalDisplay; - style.position = originalPosition; - style.visibility = originalVisibility; - - return retVal; -}; - - -/** - * Gets the height and width of an element when the display is not none. - * @param {Element} element Element to get size of. - * @return {!goog.math.Size} Object with width/height properties. - * @private - */ -goog.style.getSizeWithDisplay_ = function(element) { - var offsetWidth = /** @type {!HTMLElement} */ (element).offsetWidth; - var offsetHeight = /** @type {!HTMLElement} */ (element).offsetHeight; - var webkitOffsetsZero = - goog.userAgent.WEBKIT && !offsetWidth && !offsetHeight; - if ((!goog.isDef(offsetWidth) || webkitOffsetsZero) && - element.getBoundingClientRect) { - // Fall back to calling getBoundingClientRect when offsetWidth or - // offsetHeight are not defined, or when they are zero in WebKit browsers. - // This makes sure that we return for the correct size for SVG elements, but - // will still return 0 on Webkit prior to 534.8, see - // http://trac.webkit.org/changeset/67252. - var clientRect = goog.style.getBoundingClientRect_(element); - return new goog.math.Size( - clientRect.right - clientRect.left, clientRect.bottom - clientRect.top); - } - return new goog.math.Size(offsetWidth, offsetHeight); -}; - - -/** - * Gets the height and width of an element, post transform, even if its display - * is none. - * - * This is like {@code goog.style.getSize}, except: - * <ol> - * <li>Takes webkitTransforms such as rotate and scale into account. - * <li>Will return null if {@code element} doesn't respond to - * {@code getBoundingClientRect}. - * <li>Currently doesn't make sense on non-WebKit browsers which don't support - * webkitTransforms. - * </ol> - * @param {!Element} element Element to get size of. - * @return {goog.math.Size} Object with width/height properties. - */ -goog.style.getTransformedSize = function(element) { - if (!element.getBoundingClientRect) { - return null; - } - - var clientRect = goog.style.evaluateWithTemporaryDisplay_( - goog.style.getBoundingClientRect_, element); - return new goog.math.Size( - clientRect.right - clientRect.left, clientRect.bottom - clientRect.top); -}; - - -/** - * Returns a bounding rectangle for a given element in page space. - * @param {Element} element Element to get bounds of. Must not be display none. - * @return {!goog.math.Rect} Bounding rectangle for the element. - */ -goog.style.getBounds = function(element) { - var o = goog.style.getPageOffset(element); - var s = goog.style.getSize(element); - return new goog.math.Rect(o.x, o.y, s.width, s.height); -}; - - -/** - * Converts a CSS selector in the form style-property to styleProperty. - * @param {*} selector CSS Selector. - * @return {string} Camel case selector. - * @deprecated Use goog.string.toCamelCase instead. - */ -goog.style.toCamelCase = function(selector) { - return goog.string.toCamelCase(String(selector)); -}; - - -/** - * Converts a CSS selector in the form styleProperty to style-property. - * @param {string} selector Camel case selector. - * @return {string} Selector cased. - * @deprecated Use goog.string.toSelectorCase instead. - */ -goog.style.toSelectorCase = function(selector) { - return goog.string.toSelectorCase(selector); -}; - - -/** - * Gets the opacity of a node (x-browser). This gets the inline style opacity - * of the node, and does not take into account the cascaded or the computed - * style for this node. - * @param {Element} el Element whose opacity has to be found. - * @return {number|string} Opacity between 0 and 1 or an empty string {@code ''} - * if the opacity is not set. - */ -goog.style.getOpacity = function(el) { - goog.asserts.assert(el); - var style = el.style; - var result = ''; - if ('opacity' in style) { - result = style.opacity; - } else if ('MozOpacity' in style) { - result = style.MozOpacity; - } else if ('filter' in style) { - var match = style.filter.match(/alpha\(opacity=([\d.]+)\)/); - if (match) { - result = String(match[1] / 100); - } - } - return result == '' ? result : Number(result); -}; - - -/** - * Sets the opacity of a node (x-browser). - * @param {Element} el Elements whose opacity has to be set. - * @param {number|string} alpha Opacity between 0 and 1 or an empty string - * {@code ''} to clear the opacity. - */ -goog.style.setOpacity = function(el, alpha) { - goog.asserts.assert(el); - var style = el.style; - if ('opacity' in style) { - style.opacity = alpha; - } else if ('MozOpacity' in style) { - style.MozOpacity = alpha; - } else if ('filter' in style) { - // TODO(arv): Overwriting the filter might have undesired side effects. - if (alpha === '') { - style.filter = ''; - } else { - style.filter = 'alpha(opacity=' + (Number(alpha) * 100) + ')'; - } - } -}; - - -/** - * Sets the background of an element to a transparent image in a browser- - * independent manner. - * - * This function does not support repeating backgrounds or alternate background - * positions to match the behavior of Internet Explorer. It also does not - * support sizingMethods other than crop since they cannot be replicated in - * browsers other than Internet Explorer. - * - * @param {Element} el The element to set background on. - * @param {string} src The image source URL. - */ -goog.style.setTransparentBackgroundImage = function(el, src) { - var style = el.style; - // It is safe to use the style.filter in IE only. In Safari 'filter' is in - // style object but access to style.filter causes it to throw an exception. - // Note: IE8 supports images with an alpha channel. - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) { - // See TODO in setOpacity. - style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(' + - 'src="' + src + '", sizingMethod="crop")'; - } else { - // Set style properties individually instead of using background shorthand - // to prevent overwriting a pre-existing background color. - style.backgroundImage = 'url(' + src + ')'; - style.backgroundPosition = 'top left'; - style.backgroundRepeat = 'no-repeat'; - } -}; - - -/** - * Clears the background image of an element in a browser independent manner. - * @param {Element} el The element to clear background image for. - */ -goog.style.clearTransparentBackgroundImage = function(el) { - var style = el.style; - if ('filter' in style) { - // See TODO in setOpacity. - style.filter = ''; - } else { - // Set style properties individually instead of using background shorthand - // to prevent overwriting a pre-existing background color. - style.backgroundImage = 'none'; - } -}; - - -/** - * Shows or hides an element from the page. Hiding the element is done by - * setting the display property to "none", removing the element from the - * rendering hierarchy so it takes up no space. To show the element, the default - * inherited display property is restored (defined either in stylesheets or by - * the browser's default style rules.) - * - * Caveat 1: if the inherited display property for the element is set to "none" - * by the stylesheets, that is the property that will be restored by a call to - * showElement(), effectively toggling the display between "none" and "none". - * - * Caveat 2: if the element display style is set inline (by setting either - * element.style.display or a style attribute in the HTML), a call to - * showElement will clear that setting and defer to the inherited style in the - * stylesheet. - * @param {Element} el Element to show or hide. - * @param {*} display True to render the element in its default style, - * false to disable rendering the element. - * @deprecated Use goog.style.setElementShown instead. - */ -goog.style.showElement = function(el, display) { - goog.style.setElementShown(el, display); -}; - - -/** - * Shows or hides an element from the page. Hiding the element is done by - * setting the display property to "none", removing the element from the - * rendering hierarchy so it takes up no space. To show the element, the default - * inherited display property is restored (defined either in stylesheets or by - * the browser's default style rules). - * - * Caveat 1: if the inherited display property for the element is set to "none" - * by the stylesheets, that is the property that will be restored by a call to - * setElementShown(), effectively toggling the display between "none" and - * "none". - * - * Caveat 2: if the element display style is set inline (by setting either - * element.style.display or a style attribute in the HTML), a call to - * setElementShown will clear that setting and defer to the inherited style in - * the stylesheet. - * @param {Element} el Element to show or hide. - * @param {*} isShown True to render the element in its default style, - * false to disable rendering the element. - */ -goog.style.setElementShown = function(el, isShown) { - el.style.display = isShown ? '' : 'none'; -}; - - -/** - * Test whether the given element has been shown or hidden via a call to - * {@link #setElementShown}. - * - * Note this is strictly a companion method for a call - * to {@link #setElementShown} and the same caveats apply; in particular, this - * method does not guarantee that the return value will be consistent with - * whether or not the element is actually visible. - * - * @param {Element} el The element to test. - * @return {boolean} Whether the element has been shown. - * @see #setElementShown - */ -goog.style.isElementShown = function(el) { - return el.style.display != 'none'; -}; - - -/** - * Installs the style sheet into the window that contains opt_node. If - * opt_node is null, the main window is used. - * @param {!goog.html.SafeStyleSheet} safeStyleSheet The style sheet to install. - * @param {?Node=} opt_node Node whose parent document should have the - * styles installed. - * @return {!HTMLStyleElement|!StyleSheet} In IE<11, a StyleSheet object with no - * owning <style> tag (this is how IE creates style sheets). In every other - * browser, a <style> element with an attached style. This doesn't return a - * StyleSheet object so that setSafeStyleSheet can replace it (otherwise, if - * you pass a StyleSheet to setSafeStyleSheet, it will make a new StyleSheet - * and leave the original StyleSheet orphaned). - */ -goog.style.installSafeStyleSheet = function(safeStyleSheet, opt_node) { - var dh = goog.dom.getDomHelper(opt_node); - - // IE < 11 requires createStyleSheet. Note that doc.createStyleSheet will be - // undefined as of IE 11. - var doc = dh.getDocument(); - if (goog.userAgent.IE && doc.createStyleSheet) { - var styleSheet = doc.createStyleSheet(); - goog.style.setSafeStyleSheet(styleSheet, safeStyleSheet); - return styleSheet; - } else { - var head = dh.getElementsByTagNameAndClass(goog.dom.TagName.HEAD)[0]; - - // In opera documents are not guaranteed to have a head element, thus we - // have to make sure one exists before using it. - if (!head) { - var body = dh.getElementsByTagNameAndClass(goog.dom.TagName.BODY)[0]; - head = dh.createDom(goog.dom.TagName.HEAD); - body.parentNode.insertBefore(head, body); - } - var el = dh.createDom(goog.dom.TagName.STYLE); - // NOTE(vkarun): Setting styles after the style element has been appended - // to the head results in a nasty Webkit bug in certain scenarios. Please - // refer to https://bugs.webkit.org/show_bug.cgi?id=26307 for additional - // details. - goog.style.setSafeStyleSheet(el, safeStyleSheet); - dh.appendChild(head, el); - return el; - } -}; - - -/** - * Removes the styles added by {@link #installStyles}. - * @param {!HTMLStyleElement|!StyleSheet} styleSheet The value returned by - * {@link #installStyles}. - */ -goog.style.uninstallStyles = function(styleSheet) { - var node = styleSheet.ownerNode || styleSheet.owningElement || - /** @type {Element} */ (styleSheet); - goog.dom.removeNode(node); -}; - - -/** - * Sets the content of a style element. The style element can be any valid - * style element. This element will have its content completely replaced by - * the safeStyleSheet. - * @param {!HTMLStyleElement|!StyleSheet} element A <style> element, as returned - * by installStyles (or a Stylesheet in IE<11). - * @param {!goog.html.SafeStyleSheet} safeStyleSheet The new content of the - * stylesheet. - */ -goog.style.setSafeStyleSheet = function(element, safeStyleSheet) { - var stylesString = goog.html.SafeStyleSheet.unwrap(safeStyleSheet); - if (goog.userAgent.IE && goog.isDef(element.cssText)) { - // Adding the selectors individually caused the browser to hang if the - // selector was invalid or there were CSS comments. Setting the cssText of - // the style node works fine and ignores CSS that IE doesn't understand. - // However IE >= 11 doesn't support cssText any more, so we make sure that - // cssText is a defined property and otherwise fall back to innerHTML. - element.cssText = stylesString; - } else { - // Setting textContent doesn't work in Safari, see b/29340337. - element.innerHTML = stylesString; - } -}; - - -/** - * Sets 'white-space: pre-wrap' for a node (x-browser). - * - * There are as many ways of specifying pre-wrap as there are browsers. - * - * CSS3/IE8: white-space: pre-wrap; - * Mozilla: white-space: -moz-pre-wrap; - * Opera: white-space: -o-pre-wrap; - * IE6/7: white-space: pre; word-wrap: break-word; - * - * @param {Element} el Element to enable pre-wrap for. - */ -goog.style.setPreWrap = function(el) { - var style = el.style; - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) { - style.whiteSpace = 'pre'; - style.wordWrap = 'break-word'; - } else if (goog.userAgent.GECKO) { - style.whiteSpace = '-moz-pre-wrap'; - } else { - style.whiteSpace = 'pre-wrap'; - } -}; - - -/** - * Sets 'display: inline-block' for an element (cross-browser). - * @param {Element} el Element to which the inline-block display style is to be - * applied. - * @see ../demos/inline_block_quirks.html - * @see ../demos/inline_block_standards.html - */ -goog.style.setInlineBlock = function(el) { - var style = el.style; - // Without position:relative, weirdness ensues. Just accept it and move on. - style.position = 'relative'; - - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) { - // IE8 supports inline-block so fall through to the else - // Zoom:1 forces hasLayout, display:inline gives inline behavior. - style.zoom = '1'; - style.display = 'inline'; - } else { - // Opera, Webkit, and Safari seem to do OK with the standard inline-block - // style. - style.display = 'inline-block'; - } -}; - - -/** - * Returns true if the element is using right to left (rtl) direction. - * @param {Element} el The element to test. - * @return {boolean} True for right to left, false for left to right. - */ -goog.style.isRightToLeft = function(el) { - return 'rtl' == goog.style.getStyle_(el, 'direction'); -}; - - -/** - * The CSS style property corresponding to an element being - * unselectable on the current browser platform (null if none). - * Opera and IE instead use a DOM attribute 'unselectable'. MS Edge uses - * the Webkit prefix. - * @type {?string} - * @private - */ -goog.style.unselectableStyle_ = goog.userAgent.GECKO ? - 'MozUserSelect' : - goog.userAgent.WEBKIT || goog.userAgent.EDGE ? 'WebkitUserSelect' : null; - - -/** - * Returns true if the element is set to be unselectable, false otherwise. - * Note that on some platforms (e.g. Mozilla), even if an element isn't set - * to be unselectable, it will behave as such if any of its ancestors is - * unselectable. - * @param {Element} el Element to check. - * @return {boolean} Whether the element is set to be unselectable. - */ -goog.style.isUnselectable = function(el) { - if (goog.style.unselectableStyle_) { - return el.style[goog.style.unselectableStyle_].toLowerCase() == 'none'; - } else if (goog.userAgent.IE || goog.userAgent.OPERA) { - return el.getAttribute('unselectable') == 'on'; - } - return false; -}; - - -/** - * Makes the element and its descendants selectable or unselectable. Note - * that on some platforms (e.g. Mozilla), even if an element isn't set to - * be unselectable, it will behave as such if any of its ancestors is - * unselectable. - * @param {Element} el The element to alter. - * @param {boolean} unselectable Whether the element and its descendants - * should be made unselectable. - * @param {boolean=} opt_noRecurse Whether to only alter the element's own - * selectable state, and leave its descendants alone; defaults to false. - */ -goog.style.setUnselectable = function(el, unselectable, opt_noRecurse) { - // TODO(attila): Do we need all of TR_DomUtil.makeUnselectable() in Closure? - var descendants = !opt_noRecurse ? el.getElementsByTagName('*') : null; - var name = goog.style.unselectableStyle_; - if (name) { - // Add/remove the appropriate CSS style to/from the element and its - // descendants. - var value = unselectable ? 'none' : ''; - // MathML elements do not have a style property. Verify before setting. - if (el.style) { - el.style[name] = value; - } - if (descendants) { - for (var i = 0, descendant; descendant = descendants[i]; i++) { - if (descendant.style) { - descendant.style[name] = value; - } - } - } - } else if (goog.userAgent.IE || goog.userAgent.OPERA) { - // Toggle the 'unselectable' attribute on the element and its descendants. - var value = unselectable ? 'on' : ''; - el.setAttribute('unselectable', value); - if (descendants) { - for (var i = 0, descendant; descendant = descendants[i]; i++) { - descendant.setAttribute('unselectable', value); - } - } - } -}; - - -/** - * Gets the border box size for an element. - * @param {Element} element The element to get the size for. - * @return {!goog.math.Size} The border box size. - */ -goog.style.getBorderBoxSize = function(element) { - return new goog.math.Size( - /** @type {!HTMLElement} */ (element).offsetWidth, - /** @type {!HTMLElement} */ (element).offsetHeight); -}; - - -/** - * Sets the border box size of an element. This is potentially expensive in IE - * if the document is CSS1Compat mode - * @param {Element} element The element to set the size on. - * @param {goog.math.Size} size The new size. - */ -goog.style.setBorderBoxSize = function(element, size) { - var doc = goog.dom.getOwnerDocument(element); - var isCss1CompatMode = goog.dom.getDomHelper(doc).isCss1CompatMode(); - - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('10') && - (!isCss1CompatMode || !goog.userAgent.isVersionOrHigher('8'))) { - var style = element.style; - if (isCss1CompatMode) { - var paddingBox = goog.style.getPaddingBox(element); - var borderBox = goog.style.getBorderBox(element); - style.pixelWidth = size.width - borderBox.left - paddingBox.left - - paddingBox.right - borderBox.right; - style.pixelHeight = size.height - borderBox.top - paddingBox.top - - paddingBox.bottom - borderBox.bottom; - } else { - style.pixelWidth = size.width; - style.pixelHeight = size.height; - } - } else { - goog.style.setBoxSizingSize_(element, size, 'border-box'); - } -}; - - -/** - * Gets the content box size for an element. This is potentially expensive in - * all browsers. - * @param {Element} element The element to get the size for. - * @return {!goog.math.Size} The content box size. - */ -goog.style.getContentBoxSize = function(element) { - var doc = goog.dom.getOwnerDocument(element); - var ieCurrentStyle = goog.userAgent.IE && element.currentStyle; - if (ieCurrentStyle && goog.dom.getDomHelper(doc).isCss1CompatMode() && - ieCurrentStyle.width != 'auto' && ieCurrentStyle.height != 'auto' && - !ieCurrentStyle.boxSizing) { - // If IE in CSS1Compat mode than just use the width and height. - // If we have a boxSizing then fall back on measuring the borders etc. - var width = goog.style.getIePixelValue_( - element, /** @type {string} */ (ieCurrentStyle.width), 'width', - 'pixelWidth'); - var height = goog.style.getIePixelValue_( - element, /** @type {string} */ (ieCurrentStyle.height), 'height', - 'pixelHeight'); - return new goog.math.Size(width, height); - } else { - var borderBoxSize = goog.style.getBorderBoxSize(element); - var paddingBox = goog.style.getPaddingBox(element); - var borderBox = goog.style.getBorderBox(element); - return new goog.math.Size( - borderBoxSize.width - borderBox.left - paddingBox.left - - paddingBox.right - borderBox.right, - borderBoxSize.height - borderBox.top - paddingBox.top - - paddingBox.bottom - borderBox.bottom); - } -}; - - -/** - * Sets the content box size of an element. This is potentially expensive in IE - * if the document is BackCompat mode. - * @param {Element} element The element to set the size on. - * @param {goog.math.Size} size The new size. - */ -goog.style.setContentBoxSize = function(element, size) { - var doc = goog.dom.getOwnerDocument(element); - var isCss1CompatMode = goog.dom.getDomHelper(doc).isCss1CompatMode(); - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('10') && - (!isCss1CompatMode || !goog.userAgent.isVersionOrHigher('8'))) { - var style = element.style; - if (isCss1CompatMode) { - style.pixelWidth = size.width; - style.pixelHeight = size.height; - } else { - var paddingBox = goog.style.getPaddingBox(element); - var borderBox = goog.style.getBorderBox(element); - style.pixelWidth = size.width + borderBox.left + paddingBox.left + - paddingBox.right + borderBox.right; - style.pixelHeight = size.height + borderBox.top + paddingBox.top + - paddingBox.bottom + borderBox.bottom; - } - } else { - goog.style.setBoxSizingSize_(element, size, 'content-box'); - } -}; - - -/** - * Helper function that sets the box sizing as well as the width and height - * @param {Element} element The element to set the size on. - * @param {goog.math.Size} size The new size to set. - * @param {string} boxSizing The box-sizing value. - * @private - */ -goog.style.setBoxSizingSize_ = function(element, size, boxSizing) { - var style = element.style; - if (goog.userAgent.GECKO) { - style.MozBoxSizing = boxSizing; - } else if (goog.userAgent.WEBKIT) { - style.WebkitBoxSizing = boxSizing; - } else { - // Includes IE8 and Opera 9.50+ - style.boxSizing = boxSizing; - } - - // Setting this to a negative value will throw an exception on IE - // (and doesn't do anything different than setting it to 0). - style.width = Math.max(size.width, 0) + 'px'; - style.height = Math.max(size.height, 0) + 'px'; -}; - - -/** - * IE specific function that converts a non pixel unit to pixels. - * @param {Element} element The element to convert the value for. - * @param {string} value The current value as a string. The value must not be - * ''. - * @param {string} name The CSS property name to use for the converstion. This - * should be 'left', 'top', 'width' or 'height'. - * @param {string} pixelName The CSS pixel property name to use to get the - * value in pixels. - * @return {number} The value in pixels. - * @private - */ -goog.style.getIePixelValue_ = function(element, value, name, pixelName) { - // Try if we already have a pixel value. IE does not do half pixels so we - // only check if it matches a number followed by 'px'. - if (/^\d+px?$/.test(value)) { - return parseInt(value, 10); - } else { - var oldStyleValue = element.style[name]; - var oldRuntimeValue = element.runtimeStyle[name]; - // set runtime style to prevent changes - element.runtimeStyle[name] = element.currentStyle[name]; - element.style[name] = value; - var pixelValue = element.style[pixelName]; - // restore - element.style[name] = oldStyleValue; - element.runtimeStyle[name] = oldRuntimeValue; - return +pixelValue; - } -}; - - -/** - * Helper function for getting the pixel padding or margin for IE. - * @param {Element} element The element to get the padding for. - * @param {string} propName The property name. - * @return {number} The pixel padding. - * @private - */ -goog.style.getIePixelDistance_ = function(element, propName) { - var value = goog.style.getCascadedStyle(element, propName); - return value ? - goog.style.getIePixelValue_(element, value, 'left', 'pixelLeft') : - 0; -}; - - -/** - * Gets the computed paddings or margins (on all sides) in pixels. - * @param {Element} element The element to get the padding for. - * @param {string} stylePrefix Pass 'padding' to retrieve the padding box, - * or 'margin' to retrieve the margin box. - * @return {!goog.math.Box} The computed paddings or margins. - * @private - */ -goog.style.getBox_ = function(element, stylePrefix) { - if (goog.userAgent.IE) { - var left = goog.style.getIePixelDistance_(element, stylePrefix + 'Left'); - var right = goog.style.getIePixelDistance_(element, stylePrefix + 'Right'); - var top = goog.style.getIePixelDistance_(element, stylePrefix + 'Top'); - var bottom = - goog.style.getIePixelDistance_(element, stylePrefix + 'Bottom'); - return new goog.math.Box(top, right, bottom, left); - } else { - // On non-IE browsers, getComputedStyle is always non-null. - var left = goog.style.getComputedStyle(element, stylePrefix + 'Left'); - var right = goog.style.getComputedStyle(element, stylePrefix + 'Right'); - var top = goog.style.getComputedStyle(element, stylePrefix + 'Top'); - var bottom = goog.style.getComputedStyle(element, stylePrefix + 'Bottom'); - - // NOTE(arv): Gecko can return floating point numbers for the computed - // style values. - return new goog.math.Box( - parseFloat(top), parseFloat(right), parseFloat(bottom), - parseFloat(left)); - } -}; - - -/** - * Gets the computed paddings (on all sides) in pixels. - * @param {Element} element The element to get the padding for. - * @return {!goog.math.Box} The computed paddings. - */ -goog.style.getPaddingBox = function(element) { - return goog.style.getBox_(element, 'padding'); -}; - - -/** - * Gets the computed margins (on all sides) in pixels. - * @param {Element} element The element to get the margins for. - * @return {!goog.math.Box} The computed margins. - */ -goog.style.getMarginBox = function(element) { - return goog.style.getBox_(element, 'margin'); -}; - - -/** - * A map used to map the border width keywords to a pixel width. - * @type {!Object} - * @private - */ -goog.style.ieBorderWidthKeywords_ = { - 'thin': 2, - 'medium': 4, - 'thick': 6 -}; - - -/** - * Helper function for IE to get the pixel border. - * @param {Element} element The element to get the pixel border for. - * @param {string} prop The part of the property name. - * @return {number} The value in pixels. - * @private - */ -goog.style.getIePixelBorder_ = function(element, prop) { - if (goog.style.getCascadedStyle(element, prop + 'Style') == 'none') { - return 0; - } - var width = goog.style.getCascadedStyle(element, prop + 'Width'); - if (width in goog.style.ieBorderWidthKeywords_) { - return goog.style.ieBorderWidthKeywords_[width]; - } - return goog.style.getIePixelValue_(element, width, 'left', 'pixelLeft'); -}; - - -/** - * Gets the computed border widths (on all sides) in pixels - * @param {Element} element The element to get the border widths for. - * @return {!goog.math.Box} The computed border widths. - */ -goog.style.getBorderBox = function(element) { - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) { - var left = goog.style.getIePixelBorder_(element, 'borderLeft'); - var right = goog.style.getIePixelBorder_(element, 'borderRight'); - var top = goog.style.getIePixelBorder_(element, 'borderTop'); - var bottom = goog.style.getIePixelBorder_(element, 'borderBottom'); - return new goog.math.Box(top, right, bottom, left); - } else { - // On non-IE browsers, getComputedStyle is always non-null. - var left = goog.style.getComputedStyle(element, 'borderLeftWidth'); - var right = goog.style.getComputedStyle(element, 'borderRightWidth'); - var top = goog.style.getComputedStyle(element, 'borderTopWidth'); - var bottom = goog.style.getComputedStyle(element, 'borderBottomWidth'); - - return new goog.math.Box( - parseFloat(top), parseFloat(right), parseFloat(bottom), - parseFloat(left)); - } -}; - - -/** - * Returns the font face applied to a given node. Opera and IE should return - * the font actually displayed. Firefox returns the author's most-preferred - * font (whether the browser is capable of displaying it or not.) - * @param {Element} el The element whose font family is returned. - * @return {string} The font family applied to el. - */ -goog.style.getFontFamily = function(el) { - var doc = goog.dom.getOwnerDocument(el); - var font = ''; - // The moveToElementText method from the TextRange only works if the element - // is attached to the owner document. - if (doc.body.createTextRange && goog.dom.contains(doc, el)) { - var range = doc.body.createTextRange(); - range.moveToElementText(el); - - try { - font = range.queryCommandValue('FontName'); - } catch (e) { - // This is a workaround for a awkward exception. - // On some IE, there is an exception coming from it. - // The error description from this exception is: - // This window has already been registered as a drop target - // This is bogus description, likely due to a bug in ie. - font = ''; - } - } - if (!font) { - // Note if for some reason IE can't derive FontName with a TextRange, we - // fallback to using currentStyle - font = goog.style.getStyle_(el, 'fontFamily'); - } - - // Firefox returns the applied font-family string (author's list of - // preferred fonts.) We want to return the most-preferred font, in lieu of - // the *actually* applied font. - var fontsArray = font.split(','); - if (fontsArray.length > 1) font = fontsArray[0]; - - // Sanitize for x-browser consistency: - // Strip quotes because browsers aren't consistent with how they're - // applied; Opera always encloses, Firefox sometimes, and IE never. - return goog.string.stripQuotes(font, '"\''); -}; - - -/** - * Regular expression used for getLengthUnits. - * @type {RegExp} - * @private - */ -goog.style.lengthUnitRegex_ = /[^\d]+$/; - - -/** - * Returns the units used for a CSS length measurement. - * @param {string} value A CSS length quantity. - * @return {?string} The units of measurement. - */ -goog.style.getLengthUnits = function(value) { - var units = value.match(goog.style.lengthUnitRegex_); - return units && units[0] || null; -}; - - -/** - * Map of absolute CSS length units - * @type {!Object} - * @private - */ -goog.style.ABSOLUTE_CSS_LENGTH_UNITS_ = { - 'cm': 1, - 'in': 1, - 'mm': 1, - 'pc': 1, - 'pt': 1 -}; - - -/** - * Map of relative CSS length units that can be accurately converted to px - * font-size values using getIePixelValue_. Only units that are defined in - * relation to a font size are convertible (%, small, etc. are not). - * @type {!Object} - * @private - */ -goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_ = { - 'em': 1, - 'ex': 1 -}; - - -/** - * Returns the font size, in pixels, of text in an element. - * @param {Element} el The element whose font size is returned. - * @return {number} The font size (in pixels). - */ -goog.style.getFontSize = function(el) { - var fontSize = goog.style.getStyle_(el, 'fontSize'); - var sizeUnits = goog.style.getLengthUnits(fontSize); - if (fontSize && 'px' == sizeUnits) { - // NOTE(nathanl): This could be parseFloat instead, but IE doesn't return - // decimal fractions in getStyle_ and Firefox reports the fractions, but - // ignores them when rendering. Interestingly enough, when we force the - // issue and size something to e.g., 50% of 25px, the browsers round in - // opposite directions with Firefox reporting 12px and IE 13px. I punt. - return parseInt(fontSize, 10); - } - - // In IE, we can convert absolute length units to a px value using - // goog.style.getIePixelValue_. Units defined in relation to a font size - // (em, ex) are applied relative to the element's parentNode and can also - // be converted. - if (goog.userAgent.IE) { - if (String(sizeUnits) in goog.style.ABSOLUTE_CSS_LENGTH_UNITS_) { - return goog.style.getIePixelValue_(el, fontSize, 'left', 'pixelLeft'); - } else if ( - el.parentNode && el.parentNode.nodeType == goog.dom.NodeType.ELEMENT && - String(sizeUnits) in goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_) { - // Check the parent size - if it is the same it means the relative size - // value is inherited and we therefore don't want to count it twice. If - // it is different, this element either has explicit style or has a CSS - // rule applying to it. - var parentElement = /** @type {!Element} */ (el.parentNode); - var parentSize = goog.style.getStyle_(parentElement, 'fontSize'); - return goog.style.getIePixelValue_( - parentElement, fontSize == parentSize ? '1em' : fontSize, 'left', - 'pixelLeft'); - } - } - - // Sometimes we can't cleanly find the font size (some units relative to a - // node's parent's font size are difficult: %, smaller et al), so we create - // an invisible, absolutely-positioned span sized to be the height of an 'M' - // rendered in its parent's (i.e., our target element's) font size. This is - // the definition of CSS's font size attribute. - var sizeElement = goog.dom.createDom(goog.dom.TagName.SPAN, { - 'style': 'visibility:hidden;position:absolute;' + - 'line-height:0;padding:0;margin:0;border:0;height:1em;' - }); - goog.dom.appendChild(el, sizeElement); - fontSize = sizeElement.offsetHeight; - goog.dom.removeNode(sizeElement); - - return fontSize; -}; - - -/** - * Parses a style attribute value. Converts CSS property names to camel case. - * @param {string} value The style attribute value. - * @return {!Object} Map of CSS properties to string values. - */ -goog.style.parseStyleAttribute = function(value) { - var result = {}; - goog.array.forEach(value.split(/\s*;\s*/), function(pair) { - var keyValue = pair.match(/\s*([\w-]+)\s*\:(.+)/); - if (keyValue) { - var styleName = keyValue[1]; - var styleValue = goog.string.trim(keyValue[2]); - result[goog.string.toCamelCase(styleName.toLowerCase())] = styleValue; - } - }); - return result; -}; - - -/** - * Reverse of parseStyleAttribute; that is, takes a style object and returns the - * corresponding attribute value. Converts camel case property names to proper - * CSS selector names. - * @param {Object} obj Map of CSS properties to values. - * @return {string} The style attribute value. - */ -goog.style.toStyleAttribute = function(obj) { - var buffer = []; - goog.object.forEach(obj, function(value, key) { - buffer.push(goog.string.toSelectorCase(key), ':', value, ';'); - }); - return buffer.join(''); -}; - - -/** - * Sets CSS float property on an element. - * @param {Element} el The element to set float property on. - * @param {string} value The value of float CSS property to set on this element. - */ -goog.style.setFloat = function(el, value) { - el.style[goog.userAgent.IE ? 'styleFloat' : 'cssFloat'] = value; -}; - - -/** - * Gets value of explicitly-set float CSS property on an element. - * @param {Element} el The element to get float property of. - * @return {string} The value of explicitly-set float CSS property on this - * element. - */ -goog.style.getFloat = function(el) { - return el.style[goog.userAgent.IE ? 'styleFloat' : 'cssFloat'] || ''; -}; - - -/** - * Returns the scroll bar width (represents the width of both horizontal - * and vertical scroll). - * - * @param {string=} opt_className An optional class name (or names) to apply - * to the invisible div created to measure the scrollbar. This is necessary - * if some scrollbars are styled differently than others. - * @return {number} The scroll bar width in px. - */ -goog.style.getScrollbarWidth = function(opt_className) { - // Add two hidden divs. The child div is larger than the parent and - // forces scrollbars to appear on it. - // Using overflow:scroll does not work consistently with scrollbars that - // are styled with ::-webkit-scrollbar. - var outerDiv = goog.dom.createElement(goog.dom.TagName.DIV); - if (opt_className) { - outerDiv.className = opt_className; - } - outerDiv.style.cssText = 'overflow:auto;' + - 'position:absolute;top:0;width:100px;height:100px'; - var innerDiv = goog.dom.createElement(goog.dom.TagName.DIV); - goog.style.setSize(innerDiv, '200px', '200px'); - outerDiv.appendChild(innerDiv); - goog.dom.appendChild(goog.dom.getDocument().body, outerDiv); - var width = outerDiv.offsetWidth - outerDiv.clientWidth; - goog.dom.removeNode(outerDiv); - return width; -}; - - -/** - * Regular expression to extract x and y translation components from a CSS - * transform Matrix representation. - * - * @type {!RegExp} - * @const - * @private - */ -goog.style.MATRIX_TRANSLATION_REGEX_ = new RegExp( - 'matrix\\([0-9\\.\\-]+, [0-9\\.\\-]+, ' + - '[0-9\\.\\-]+, [0-9\\.\\-]+, ' + - '([0-9\\.\\-]+)p?x?, ([0-9\\.\\-]+)p?x?\\)'); - - -/** - * Returns the x,y translation component of any CSS transforms applied to the - * element, in pixels. - * - * @param {!Element} element The element to get the translation of. - * @return {!goog.math.Coordinate} The CSS translation of the element in px. - */ -goog.style.getCssTranslation = function(element) { - var transform = goog.style.getComputedTransform(element); - if (!transform) { - return new goog.math.Coordinate(0, 0); - } - var matches = transform.match(goog.style.MATRIX_TRANSLATION_REGEX_); - if (!matches) { - return new goog.math.Coordinate(0, 0); - } - return new goog.math.Coordinate( - parseFloat(matches[1]), parseFloat(matches[2])); -};
diff --git a/third_party/ink/closure/ui/component.js b/third_party/ink/closure/ui/component.js deleted file mode 100644 index f4f7737a..0000000 --- a/third_party/ink/closure/ui/component.js +++ /dev/null
@@ -1,1305 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Abstract class for all UI components. This defines the standard - * design pattern that all UI components should follow. - * - * @author pupius@google.com (Daniel Pupius) - * @author ssaviano@google.com (Steven Saviano) - * @author baker@google.com (Greg Baker) - * @author attila@google.com (Attila Bodis) - * @see ../demos/samplecomponent.html - * @see http://code.google.com/p/closure-library/wiki/IntroToComponents - */ - -goog.provide('goog.ui.Component'); -goog.provide('goog.ui.Component.Error'); -goog.provide('goog.ui.Component.EventType'); -goog.provide('goog.ui.Component.State'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TagName'); -goog.require('goog.events.EventHandler'); -goog.require('goog.events.EventTarget'); -goog.require('goog.object'); -goog.require('goog.style'); -goog.require('goog.ui.IdGenerator'); - - - -/** - * Default implementation of UI component. - * - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper. - * @constructor - * @extends {goog.events.EventTarget} - * @suppress {underscore} - */ -goog.ui.Component = function(opt_domHelper) { - goog.events.EventTarget.call(this); - /** - * DomHelper used to interact with the document, allowing components to be - * created in a different window. - * @protected {!goog.dom.DomHelper} - * @suppress {underscore|visibility} - */ - this.dom_ = opt_domHelper || goog.dom.getDomHelper(); - - /** - * Whether the component is rendered right-to-left. Right-to-left is set - * lazily when {@link #isRightToLeft} is called the first time, unless it has - * been set by calling {@link #setRightToLeft} explicitly. - * @private {?boolean} - */ - this.rightToLeft_ = goog.ui.Component.defaultRightToLeft_; - - /** - * Unique ID of the component, lazily initialized in {@link - * goog.ui.Component#getId} if needed. This property is strictly private and - * must not be accessed directly outside of this class! - * @private {?string} - */ - this.id_ = null; - - /** - * Whether the component is in the document. - * @private {boolean} - */ - this.inDocument_ = false; - - // TODO(attila): Stop referring to this private field in subclasses. - /** - * The DOM element for the component. - * @private {Element} - */ - this.element_ = null; - - /** - * Event handler. - * TODO(pallosp): rename it to handler_ after all component subclasses in - * inside Google have been cleaned up. - * Code search: http://go/component_code_search - * @private {goog.events.EventHandler|undefined} - */ - this.googUiComponentHandler_ = void 0; - - /** - * Arbitrary data object associated with the component. Such as meta-data. - * @private {*} - */ - this.model_ = null; - - /** - * Parent component to which events will be propagated. This property is - * strictly private and must not be accessed directly outside of this class! - * @private {goog.ui.Component?} - */ - this.parent_ = null; - - /** - * Array of child components. Lazily initialized on first use. Must be kept - * in sync with {@code childIndex_}. This property is strictly private and - * must not be accessed directly outside of this class! - * @private {Array<goog.ui.Component>?} - */ - this.children_ = null; - - /** - * Map of child component IDs to child components. Used for constant-time - * random access to child components by ID. Lazily initialized on first use. - * Must be kept in sync with {@code children_}. This property is strictly - * private and must not be accessed directly outside of this class! - * - * We use a plain Object, not a {@link goog.structs.Map}, for simplicity. - * This means components can't have children with IDs such as 'constructor' or - * 'valueOf', but this shouldn't really be an issue in practice, and if it is, - * we can always fix it later without changing the API. - * - * @private {Object} - */ - this.childIndex_ = null; - - /** - * Flag used to keep track of whether a component decorated an already - * existing element or whether it created the DOM itself. - * - * If an element is decorated, dispose will leave the node in the document. - * It is up to the app to remove the node. - * - * If an element was rendered, dispose will remove the node automatically. - * - * @private {boolean} - */ - this.wasDecorated_ = false; -}; -goog.inherits(goog.ui.Component, goog.events.EventTarget); - - -/** - * @define {boolean} Whether to support calling decorate with an element that is - * not yet in the document. If true, we check if the element is in the - * document, and avoid calling enterDocument if it isn't. If false, we - * maintain legacy behavior (always call enterDocument from decorate). - */ -goog.define('goog.ui.Component.ALLOW_DETACHED_DECORATION', false); - - -/** - * Generator for unique IDs. - * @type {goog.ui.IdGenerator} - * @private - */ -goog.ui.Component.prototype.idGenerator_ = goog.ui.IdGenerator.getInstance(); - - -// TODO(gboyer): See if we can remove this and just check goog.i18n.bidi.IS_RTL. -/** - * @define {number} Defines the default BIDI directionality. - * 0: Unknown. - * 1: Left-to-right. - * -1: Right-to-left. - */ -goog.define('goog.ui.Component.DEFAULT_BIDI_DIR', 0); - - -/** - * The default right to left value. - * @type {?boolean} - * @private - */ -goog.ui.Component.defaultRightToLeft_ = - (goog.ui.Component.DEFAULT_BIDI_DIR == 1) ? - false : - (goog.ui.Component.DEFAULT_BIDI_DIR == -1) ? true : null; - - -/** - * Common events fired by components so that event propagation is useful. Not - * all components are expected to dispatch or listen for all event types. - * Events dispatched before a state transition should be cancelable to prevent - * the corresponding state change. - * @enum {string} - */ -goog.ui.Component.EventType = { - /** Dispatched before the component becomes visible. */ - BEFORE_SHOW: 'beforeshow', - - /** - * Dispatched after the component becomes visible. - * NOTE(bloom): For goog.ui.Container, this actually fires before containers - * are shown. Use goog.ui.Container.EventType.AFTER_SHOW if you want an event - * that fires after a goog.ui.Container is shown. - */ - SHOW: 'show', - - /** Dispatched before the component becomes hidden. */ - HIDE: 'hide', - - /** Dispatched before the component becomes disabled. */ - DISABLE: 'disable', - - /** Dispatched before the component becomes enabled. */ - ENABLE: 'enable', - - /** Dispatched before the component becomes highlighted. */ - HIGHLIGHT: 'highlight', - - /** Dispatched before the component becomes un-highlighted. */ - UNHIGHLIGHT: 'unhighlight', - - /** Dispatched before the component becomes activated. */ - ACTIVATE: 'activate', - - /** Dispatched before the component becomes deactivated. */ - DEACTIVATE: 'deactivate', - - /** Dispatched before the component becomes selected. */ - SELECT: 'select', - - /** Dispatched before the component becomes un-selected. */ - UNSELECT: 'unselect', - - /** Dispatched before a component becomes checked. */ - CHECK: 'check', - - /** Dispatched before a component becomes un-checked. */ - UNCHECK: 'uncheck', - - /** Dispatched before a component becomes focused. */ - FOCUS: 'focus', - - /** Dispatched before a component becomes blurred. */ - BLUR: 'blur', - - /** Dispatched before a component is opened (expanded). */ - OPEN: 'open', - - /** Dispatched before a component is closed (collapsed). */ - CLOSE: 'close', - - /** Dispatched after a component is moused over. */ - ENTER: 'enter', - - /** Dispatched after a component is moused out of. */ - LEAVE: 'leave', - - /** Dispatched after the user activates the component. */ - ACTION: 'action', - - /** Dispatched after the external-facing state of a component is changed. */ - CHANGE: 'change' -}; - - -/** - * Errors thrown by the component. - * @enum {string} - */ -goog.ui.Component.Error = { - /** - * Error when a method is not supported. - */ - NOT_SUPPORTED: 'Method not supported', - - /** - * Error when the given element can not be decorated. - */ - DECORATE_INVALID: 'Invalid element to decorate', - - /** - * Error when the component is already rendered and another render attempt is - * made. - */ - ALREADY_RENDERED: 'Component already rendered', - - /** - * Error when an attempt is made to set the parent of a component in a way - * that would result in an inconsistent object graph. - */ - PARENT_UNABLE_TO_BE_SET: 'Unable to set parent component', - - /** - * Error when an attempt is made to add a child component at an out-of-bounds - * index. We don't support sparse child arrays. - */ - CHILD_INDEX_OUT_OF_BOUNDS: 'Child component index out of bounds', - - /** - * Error when an attempt is made to remove a child component from a component - * other than its parent. - */ - NOT_OUR_CHILD: 'Child is not in parent component', - - /** - * Error when an operation requiring DOM interaction is made when the - * component is not in the document - */ - NOT_IN_DOCUMENT: 'Operation not supported while component is not in document', - - /** - * Error when an invalid component state is encountered. - */ - STATE_INVALID: 'Invalid component state' -}; - - -/** - * Common component states. Components may have distinct appearance depending - * on what state(s) apply to them. Not all components are expected to support - * all states. - * @enum {number} - */ -goog.ui.Component.State = { - /** - * Union of all supported component states. - */ - ALL: 0xFF, - - /** - * Component is disabled. - * @see goog.ui.Component.EventType.DISABLE - * @see goog.ui.Component.EventType.ENABLE - */ - DISABLED: 0x01, - - /** - * Component is highlighted. - * @see goog.ui.Component.EventType.HIGHLIGHT - * @see goog.ui.Component.EventType.UNHIGHLIGHT - */ - HOVER: 0x02, - - /** - * Component is active (or "pressed"). - * @see goog.ui.Component.EventType.ACTIVATE - * @see goog.ui.Component.EventType.DEACTIVATE - */ - ACTIVE: 0x04, - - /** - * Component is selected. - * @see goog.ui.Component.EventType.SELECT - * @see goog.ui.Component.EventType.UNSELECT - */ - SELECTED: 0x08, - - /** - * Component is checked. - * @see goog.ui.Component.EventType.CHECK - * @see goog.ui.Component.EventType.UNCHECK - */ - CHECKED: 0x10, - - /** - * Component has focus. - * @see goog.ui.Component.EventType.FOCUS - * @see goog.ui.Component.EventType.BLUR - */ - FOCUSED: 0x20, - - /** - * Component is opened (expanded). Applies to tree nodes, menu buttons, - * submenus, zippys (zippies?), etc. - * @see goog.ui.Component.EventType.OPEN - * @see goog.ui.Component.EventType.CLOSE - */ - OPENED: 0x40 -}; - - -/** - * Static helper method; returns the type of event components are expected to - * dispatch when transitioning to or from the given state. - * @param {goog.ui.Component.State} state State to/from which the component - * is transitioning. - * @param {boolean} isEntering Whether the component is entering or leaving the - * state. - * @return {goog.ui.Component.EventType} Event type to dispatch. - */ -goog.ui.Component.getStateTransitionEvent = function(state, isEntering) { - switch (state) { - case goog.ui.Component.State.DISABLED: - return isEntering ? goog.ui.Component.EventType.DISABLE : - goog.ui.Component.EventType.ENABLE; - case goog.ui.Component.State.HOVER: - return isEntering ? goog.ui.Component.EventType.HIGHLIGHT : - goog.ui.Component.EventType.UNHIGHLIGHT; - case goog.ui.Component.State.ACTIVE: - return isEntering ? goog.ui.Component.EventType.ACTIVATE : - goog.ui.Component.EventType.DEACTIVATE; - case goog.ui.Component.State.SELECTED: - return isEntering ? goog.ui.Component.EventType.SELECT : - goog.ui.Component.EventType.UNSELECT; - case goog.ui.Component.State.CHECKED: - return isEntering ? goog.ui.Component.EventType.CHECK : - goog.ui.Component.EventType.UNCHECK; - case goog.ui.Component.State.FOCUSED: - return isEntering ? goog.ui.Component.EventType.FOCUS : - goog.ui.Component.EventType.BLUR; - case goog.ui.Component.State.OPENED: - return isEntering ? goog.ui.Component.EventType.OPEN : - goog.ui.Component.EventType.CLOSE; - default: - // Fall through. - } - - // Invalid state. - throw new Error(goog.ui.Component.Error.STATE_INVALID); -}; - - -/** - * Set the default right-to-left value. This causes all component's created from - * this point forward to have the given value. This is useful for cases where - * a given page is always in one directionality, avoiding unnecessary - * right to left determinations. - * @param {?boolean} rightToLeft Whether the components should be rendered - * right-to-left. Null iff components should determine their directionality. - */ -goog.ui.Component.setDefaultRightToLeft = function(rightToLeft) { - goog.ui.Component.defaultRightToLeft_ = rightToLeft; -}; - - -/** - * Gets the unique ID for the instance of this component. If the instance - * doesn't already have an ID, generates one on the fly. - * @return {string} Unique component ID. - */ -goog.ui.Component.prototype.getId = function() { - return this.id_ || (this.id_ = this.idGenerator_.getNextUniqueId()); -}; - - -/** - * Assigns an ID to this component instance. It is the caller's responsibility - * to guarantee that the ID is unique. If the component is a child of a parent - * component, then the parent component's child index is updated to reflect the - * new ID; this may throw an error if the parent already has a child with an ID - * that conflicts with the new ID. - * @param {string} id Unique component ID. - */ -goog.ui.Component.prototype.setId = function(id) { - if (this.parent_ && this.parent_.childIndex_) { - // Update the parent's child index. - goog.object.remove(this.parent_.childIndex_, this.id_); - goog.object.add(this.parent_.childIndex_, id, this); - } - - // Update the component ID. - this.id_ = id; -}; - - -/** - * Gets the component's element. - * @return {Element} The element for the component. - */ -goog.ui.Component.prototype.getElement = function() { - return this.element_; -}; - - -/** - * Gets the component's element. This differs from getElement in that - * it assumes that the element exists (i.e. the component has been - * rendered/decorated) and will cause an assertion error otherwise (if - * assertion is enabled). - * @return {!Element} The element for the component. - */ -goog.ui.Component.prototype.getElementStrict = function() { - var el = this.element_; - goog.asserts.assert( - el, 'Can not call getElementStrict before rendering/decorating.'); - return el; -}; - - -/** - * Sets the component's root element to the given element. Considered - * protected and final. - * - * This should generally only be called during createDom. Setting the element - * does not actually change which element is rendered, only the element that is - * associated with this UI component. - * - * This should only be used by subclasses and its associated renderers. - * - * @param {Element} element Root element for the component. - */ -goog.ui.Component.prototype.setElementInternal = function(element) { - this.element_ = element; -}; - - -/** - * Returns an array of all the elements in this component's DOM with the - * provided className. - * @param {string} className The name of the class to look for. - * @return {!IArrayLike<!Element>} The items found with the class name provided. - */ -goog.ui.Component.prototype.getElementsByClass = function(className) { - return this.element_ ? - this.dom_.getElementsByClass(className, this.element_) : - []; -}; - - -/** - * Returns the first element in this component's DOM with the provided - * className. - * @param {string} className The name of the class to look for. - * @return {Element} The first item with the class name provided. - */ -goog.ui.Component.prototype.getElementByClass = function(className) { - return this.element_ ? this.dom_.getElementByClass(className, this.element_) : - null; -}; - - -/** - * Similar to {@code getElementByClass} except that it expects the - * element to be present in the dom thus returning a required value. Otherwise, - * will assert. - * @param {string} className The name of the class to look for. - * @return {!Element} The first item with the class name provided. - */ -goog.ui.Component.prototype.getRequiredElementByClass = function(className) { - var el = this.getElementByClass(className); - goog.asserts.assert( - el, 'Expected element in component with class: %s', className); - return el; -}; - - -/** - * Returns the event handler for this component, lazily created the first time - * this method is called. - * @return {!goog.events.EventHandler<T>} Event handler for this component. - * @protected - * @this {T} - * @template T - */ -goog.ui.Component.prototype.getHandler = function() { - // TODO(17988911): templated "this" values currently result in "this" being - // "unknown" in the body of the function. - var self = /** @type {goog.ui.Component} */ (this); - if (!self.googUiComponentHandler_) { - self.googUiComponentHandler_ = new goog.events.EventHandler(self); - } - return self.googUiComponentHandler_; -}; - - -/** - * Sets the parent of this component to use for event bubbling. Throws an error - * if the component already has a parent or if an attempt is made to add a - * component to itself as a child. Callers must use {@code removeChild} - * or {@code removeChildAt} to remove components from their containers before - * calling this method. - * @see goog.ui.Component#removeChild - * @see goog.ui.Component#removeChildAt - * @param {goog.ui.Component} parent The parent component. - */ -goog.ui.Component.prototype.setParent = function(parent) { - if (this == parent) { - // Attempting to add a child to itself is an error. - throw new Error(goog.ui.Component.Error.PARENT_UNABLE_TO_BE_SET); - } - - if (parent && this.parent_ && this.id_ && this.parent_.getChild(this.id_) && - this.parent_ != parent) { - // This component is already the child of some parent, so it should be - // removed using removeChild/removeChildAt first. - throw new Error(goog.ui.Component.Error.PARENT_UNABLE_TO_BE_SET); - } - - this.parent_ = parent; - goog.ui.Component.superClass_.setParentEventTarget.call(this, parent); -}; - - -/** - * Returns the component's parent, if any. - * @return {goog.ui.Component?} The parent component. - */ -goog.ui.Component.prototype.getParent = function() { - return this.parent_; -}; - - -/** - * Overrides {@link goog.events.EventTarget#setParentEventTarget} to throw an - * error if the parent component is set, and the argument is not the parent. - * @override - */ -goog.ui.Component.prototype.setParentEventTarget = function(parent) { - if (this.parent_ && this.parent_ != parent) { - throw new Error(goog.ui.Component.Error.NOT_SUPPORTED); - } - goog.ui.Component.superClass_.setParentEventTarget.call(this, parent); -}; - - -/** - * Returns the dom helper that is being used on this component. - * @return {!goog.dom.DomHelper} The dom helper used on this component. - */ -goog.ui.Component.prototype.getDomHelper = function() { - return this.dom_; -}; - - -/** - * Determines whether the component has been added to the document. - * @return {boolean} TRUE if rendered. Otherwise, FALSE. - */ -goog.ui.Component.prototype.isInDocument = function() { - return this.inDocument_; -}; - - -/** - * Creates the initial DOM representation for the component. The default - * implementation is to set this.element_ = div. - */ -goog.ui.Component.prototype.createDom = function() { - this.element_ = this.dom_.createElement(goog.dom.TagName.DIV); -}; - - -/** - * Renders the component. If a parent element is supplied, the component's - * element will be appended to it. If there is no optional parent element and - * the element doesn't have a parentNode then it will be appended to the - * document body. - * - * If this component has a parent component, and the parent component is - * not in the document already, then this will not call {@code enterDocument} - * on this component. - * - * Throws an Error if the component is already rendered. - * - * @param {Element=} opt_parentElement Optional parent element to render the - * component into. - */ -goog.ui.Component.prototype.render = function(opt_parentElement) { - this.render_(opt_parentElement); -}; - - -/** - * Renders the component before another element. The other element should be in - * the document already. - * - * Throws an Error if the component is already rendered. - * - * @param {Node} sibling Node to render the component before. - */ -goog.ui.Component.prototype.renderBefore = function(sibling) { - this.render_(/** @type {Element} */ (sibling.parentNode), sibling); -}; - - -/** - * Renders the component. If a parent element is supplied, the component's - * element will be appended to it. If there is no optional parent element and - * the element doesn't have a parentNode then it will be appended to the - * document body. - * - * If this component has a parent component, and the parent component is - * not in the document already, then this will not call {@code enterDocument} - * on this component. - * - * Throws an Error if the component is already rendered. - * - * @param {Element=} opt_parentElement Optional parent element to render the - * component into. - * @param {Node=} opt_beforeNode Node before which the component is to - * be rendered. If left out the node is appended to the parent element. - * @private - */ -goog.ui.Component.prototype.render_ = function( - opt_parentElement, opt_beforeNode) { - if (this.inDocument_) { - throw new Error(goog.ui.Component.Error.ALREADY_RENDERED); - } - - if (!this.element_) { - this.createDom(); - } - - if (opt_parentElement) { - opt_parentElement.insertBefore(this.element_, opt_beforeNode || null); - } else { - this.dom_.getDocument().body.appendChild(this.element_); - } - - // If this component has a parent component that isn't in the document yet, - // we don't call enterDocument() here. Instead, when the parent component - // enters the document, the enterDocument() call will propagate to its - // children, including this one. If the component doesn't have a parent - // or if the parent is already in the document, we call enterDocument(). - if (!this.parent_ || this.parent_.isInDocument()) { - this.enterDocument(); - } -}; - - -/** - * Decorates the element for the UI component. If the element is in the - * document, the enterDocument method will be called. - * - * If goog.ui.Component.ALLOW_DETACHED_DECORATION is false, the caller must - * pass an element that is in the document. - * - * @param {Element} element Element to decorate. - */ -goog.ui.Component.prototype.decorate = function(element) { - if (this.inDocument_) { - throw new Error(goog.ui.Component.Error.ALREADY_RENDERED); - } else if (element && this.canDecorate(element)) { - this.wasDecorated_ = true; - - // Set the DOM helper of the component to match the decorated element. - var doc = goog.dom.getOwnerDocument(element); - if (!this.dom_ || this.dom_.getDocument() != doc) { - this.dom_ = goog.dom.getDomHelper(element); - } - - // Call specific component decorate logic. - this.decorateInternal(element); - - // If supporting detached decoration, check that element is in doc. - if (!goog.ui.Component.ALLOW_DETACHED_DECORATION || - goog.dom.contains(doc, element)) { - this.enterDocument(); - } - } else { - throw new Error(goog.ui.Component.Error.DECORATE_INVALID); - } -}; - - -/** - * Determines if a given element can be decorated by this type of component. - * This method should be overridden by inheriting objects. - * @param {Element} element Element to decorate. - * @return {boolean} True if the element can be decorated, false otherwise. - */ -goog.ui.Component.prototype.canDecorate = function(element) { - return true; -}; - - -/** - * @return {boolean} Whether the component was decorated. - */ -goog.ui.Component.prototype.wasDecorated = function() { - return this.wasDecorated_; -}; - - -/** - * Actually decorates the element. Should be overridden by inheriting objects. - * This method can assume there are checks to ensure the component has not - * already been rendered have occurred and that enter document will be called - * afterwards. This method is considered protected. - * @param {Element} element Element to decorate. - * @protected - */ -goog.ui.Component.prototype.decorateInternal = function(element) { - this.element_ = element; -}; - - -/** - * Called when the component's element is known to be in the document. Anything - * using document.getElementById etc. should be done at this stage. - * - * If the component contains child components, this call is propagated to its - * children. - */ -goog.ui.Component.prototype.enterDocument = function() { - this.inDocument_ = true; - - // Propagate enterDocument to child components that have a DOM, if any. - // If a child was decorated before entering the document (permitted when - // goog.ui.Component.ALLOW_DETACHED_DECORATION is true), its enterDocument - // will be called here. - this.forEachChild(function(child) { - if (!child.isInDocument() && child.getElement()) { - child.enterDocument(); - } - }); -}; - - -/** - * Called by dispose to clean up the elements and listeners created by a - * component, or by a parent component/application who has removed the - * component from the document but wants to reuse it later. - * - * If the component contains child components, this call is propagated to its - * children. - * - * It should be possible for the component to be rendered again once this method - * has been called. - */ -goog.ui.Component.prototype.exitDocument = function() { - // Propagate exitDocument to child components that have been rendered, if any. - this.forEachChild(function(child) { - if (child.isInDocument()) { - child.exitDocument(); - } - }); - - if (this.googUiComponentHandler_) { - this.googUiComponentHandler_.removeAll(); - } - - this.inDocument_ = false; -}; - - -/** - * Disposes of the component. Calls {@code exitDocument}, which is expected to - * remove event handlers and clean up the component. Propagates the call to - * the component's children, if any. Removes the component's DOM from the - * document unless it was decorated. - * @override - * @protected - */ -goog.ui.Component.prototype.disposeInternal = function() { - if (this.inDocument_) { - this.exitDocument(); - } - - if (this.googUiComponentHandler_) { - this.googUiComponentHandler_.dispose(); - delete this.googUiComponentHandler_; - } - - // Disposes of the component's children, if any. - this.forEachChild(function(child) { child.dispose(); }); - - // Detach the component's element from the DOM, unless it was decorated. - if (!this.wasDecorated_ && this.element_) { - goog.dom.removeNode(this.element_); - } - - this.children_ = null; - this.childIndex_ = null; - this.element_ = null; - this.model_ = null; - this.parent_ = null; - - goog.ui.Component.superClass_.disposeInternal.call(this); -}; - - -/** - * Helper function for subclasses that gets a unique id for a given fragment, - * this can be used by components to generate unique string ids for DOM - * elements. - * @param {string} idFragment A partial id. - * @return {string} Unique element id. - */ -goog.ui.Component.prototype.makeId = function(idFragment) { - return this.getId() + '.' + idFragment; -}; - - -/** - * Makes a collection of ids. This is a convenience method for makeId. The - * object's values are the id fragments and the new values are the generated - * ids. The key will remain the same. - * @param {Object} object The object that will be used to create the ids. - * @return {!Object<string, string>} An object of id keys to generated ids. - */ -goog.ui.Component.prototype.makeIds = function(object) { - var ids = {}; - for (var key in object) { - ids[key] = this.makeId(object[key]); - } - return ids; -}; - - -/** - * Returns the model associated with the UI component. - * @return {*} The model. - */ -goog.ui.Component.prototype.getModel = function() { - return this.model_; -}; - - -/** - * Sets the model associated with the UI component. - * @param {*} obj The model. - */ -goog.ui.Component.prototype.setModel = function(obj) { - this.model_ = obj; -}; - - -/** - * Helper function for returning the fragment portion of an id generated using - * makeId(). - * @param {string} id Id generated with makeId(). - * @return {string} Fragment. - */ -goog.ui.Component.prototype.getFragmentFromId = function(id) { - return id.substring(this.getId().length + 1); -}; - - -/** - * Helper function for returning an element in the document with a unique id - * generated using makeId(). - * @param {string} idFragment The partial id. - * @return {Element} The element with the unique id, or null if it cannot be - * found. - */ -goog.ui.Component.prototype.getElementByFragment = function(idFragment) { - if (!this.inDocument_) { - throw new Error(goog.ui.Component.Error.NOT_IN_DOCUMENT); - } - return this.dom_.getElement(this.makeId(idFragment)); -}; - - -/** - * Adds the specified component as the last child of this component. See - * {@link goog.ui.Component#addChildAt} for detailed semantics. - * - * @see goog.ui.Component#addChildAt - * @param {goog.ui.Component} child The new child component. - * @param {boolean=} opt_render If true, the child component will be rendered - * into the parent. - */ -goog.ui.Component.prototype.addChild = function(child, opt_render) { - // TODO(gboyer): addChildAt(child, this.getChildCount(), false) will - // reposition any already-rendered child to the end. Instead, perhaps - // addChild(child, false) should never reposition the child; instead, clients - // that need the repositioning will use addChildAt explicitly. Right now, - // clients can get around this by calling addChild before calling decorate. - this.addChildAt(child, this.getChildCount(), opt_render); -}; - - -/** - * Adds the specified component as a child of this component at the given - * 0-based index. - * - * Both {@code addChild} and {@code addChildAt} assume the following contract - * between parent and child components: - * <ul> - * <li>the child component's element must be a descendant of the parent - * component's element, and - * <li>the DOM state of the child component must be consistent with the DOM - * state of the parent component (see {@code isInDocument}) in the - * steady state -- the exception is to addChildAt(child, i, false) and - * then immediately decorate/render the child. - * </ul> - * - * In particular, {@code parent.addChild(child)} will throw an error if the - * child component is already in the document, but the parent isn't. - * - * Clients of this API may call {@code addChild} and {@code addChildAt} with - * {@code opt_render} set to true. If {@code opt_render} is true, calling these - * methods will automatically render the child component's element into the - * parent component's element. If the parent does not yet have an element, then - * {@code createDom} will automatically be invoked on the parent before - * rendering the child. - * - * Invoking {@code parent.addChild(child, true)} will throw an error if the - * child component is already in the document, regardless of the parent's DOM - * state. - * - * If {@code opt_render} is true and the parent component is not already - * in the document, {@code enterDocument} will not be called on this component - * at this point. - * - * Finally, this method also throws an error if the new child already has a - * different parent, or the given index is out of bounds. - * - * @see goog.ui.Component#addChild - * @param {goog.ui.Component} child The new child component. - * @param {number} index 0-based index at which the new child component is to be - * added; must be between 0 and the current child count (inclusive). - * @param {boolean=} opt_render If true, the child component will be rendered - * into the parent. - * @return {void} Nada. - */ -goog.ui.Component.prototype.addChildAt = function(child, index, opt_render) { - goog.asserts.assert(!!child, 'Provided element must not be null.'); - - if (child.inDocument_ && (opt_render || !this.inDocument_)) { - // Adding a child that's already in the document is an error, except if the - // parent is also in the document and opt_render is false (e.g. decorate()). - throw new Error(goog.ui.Component.Error.ALREADY_RENDERED); - } - - if (index < 0 || index > this.getChildCount()) { - // Allowing sparse child arrays would lead to strange behavior, so we don't. - throw new Error(goog.ui.Component.Error.CHILD_INDEX_OUT_OF_BOUNDS); - } - - // Create the index and the child array on first use. - if (!this.childIndex_ || !this.children_) { - this.childIndex_ = {}; - this.children_ = []; - } - - // Moving child within component, remove old reference. - if (child.getParent() == this) { - goog.object.set(this.childIndex_, child.getId(), child); - goog.array.remove(this.children_, child); - - // Add the child to this component. goog.object.add() throws an error if - // a child with the same ID already exists. - } else { - goog.object.add(this.childIndex_, child.getId(), child); - } - - // Set the parent of the child to this component. This throws an error if - // the child is already contained by another component. - child.setParent(this); - goog.array.insertAt(this.children_, child, index); - - if (child.inDocument_ && this.inDocument_ && child.getParent() == this) { - // Changing the position of an existing child, move the DOM node (if - // necessary). - var contentElement = this.getContentElement(); - var insertBeforeElement = contentElement.childNodes[index] || null; - if (insertBeforeElement != child.getElement()) { - contentElement.insertBefore(child.getElement(), insertBeforeElement); - } - } else if (opt_render) { - // If this (parent) component doesn't have a DOM yet, call createDom now - // to make sure we render the child component's element into the correct - // parent element (otherwise render_ with a null first argument would - // render the child into the document body, which is almost certainly not - // what we want). - if (!this.element_) { - this.createDom(); - } - // Render the child into the parent at the appropriate location. Note that - // getChildAt(index + 1) returns undefined if inserting at the end. - // TODO(attila): We should have a renderer with a renderChildAt API. - var sibling = this.getChildAt(index + 1); - // render_() calls enterDocument() if the parent is already in the document. - child.render_(this.getContentElement(), sibling ? sibling.element_ : null); - } else if ( - this.inDocument_ && !child.inDocument_ && child.element_ && - child.element_.parentNode && - // Under some circumstances, IE8 implicitly creates a Document Fragment - // for detached nodes, so ensure the parent is an Element as it should be. - child.element_.parentNode.nodeType == goog.dom.NodeType.ELEMENT) { - // We don't touch the DOM, but if the parent is in the document, and the - // child element is in the document but not marked as such, then we call - // enterDocument on the child. - // TODO(gboyer): It would be nice to move this condition entirely, but - // there's a large risk of breaking existing applications that manually - // append the child to the DOM and then call addChild. - child.enterDocument(); - } -}; - - -/** - * Returns the DOM element into which child components are to be rendered, - * or null if the component itself hasn't been rendered yet. This default - * implementation returns the component's root element. Subclasses with - * complex DOM structures must override this method. - * @return {Element} Element to contain child elements (null if none). - */ -goog.ui.Component.prototype.getContentElement = function() { - return this.element_; -}; - - -/** - * Returns true if the component is rendered right-to-left, false otherwise. - * The first time this function is invoked, the right-to-left rendering property - * is set if it has not been already. - * @return {boolean} Whether the control is rendered right-to-left. - */ -goog.ui.Component.prototype.isRightToLeft = function() { - if (this.rightToLeft_ == null) { - this.rightToLeft_ = goog.style.isRightToLeft( - this.inDocument_ ? this.element_ : this.dom_.getDocument().body); - } - return this.rightToLeft_; -}; - - -/** - * Set is right-to-left. This function should be used if the component needs - * to know the rendering direction during dom creation (i.e. before - * {@link #enterDocument} is called and is right-to-left is set). - * @param {boolean} rightToLeft Whether the component is rendered - * right-to-left. - */ -goog.ui.Component.prototype.setRightToLeft = function(rightToLeft) { - if (this.inDocument_) { - throw new Error(goog.ui.Component.Error.ALREADY_RENDERED); - } - this.rightToLeft_ = rightToLeft; -}; - - -/** - * Returns true if the component has children. - * @return {boolean} True if the component has children. - */ -goog.ui.Component.prototype.hasChildren = function() { - return !!this.children_ && this.children_.length != 0; -}; - - -/** - * Returns the number of children of this component. - * @return {number} The number of children. - */ -goog.ui.Component.prototype.getChildCount = function() { - return this.children_ ? this.children_.length : 0; -}; - - -/** - * Returns an array containing the IDs of the children of this component, or an - * empty array if the component has no children. - * @return {!Array<string>} Child component IDs. - */ -goog.ui.Component.prototype.getChildIds = function() { - var ids = []; - - // We don't use goog.object.getKeys(this.childIndex_) because we want to - // return the IDs in the correct order as determined by this.children_. - this.forEachChild(function(child) { - // addChild()/addChildAt() guarantee that the child array isn't sparse. - ids.push(child.getId()); - }); - - return ids; -}; - - -/** - * Returns the child with the given ID, or null if no such child exists. - * @param {string} id Child component ID. - * @return {goog.ui.Component?} The child with the given ID; null if none. - */ -goog.ui.Component.prototype.getChild = function(id) { - // Use childIndex_ for O(1) access by ID. - return (this.childIndex_ && id) ? - /** @type {goog.ui.Component} */ ( - goog.object.get(this.childIndex_, id)) || - null : - null; -}; - - -/** - * Returns the child at the given index, or null if the index is out of bounds. - * @param {number} index 0-based index. - * @return {goog.ui.Component?} The child at the given index; null if none. - */ -goog.ui.Component.prototype.getChildAt = function(index) { - // Use children_ for access by index. - return this.children_ ? this.children_[index] || null : null; -}; - - -/** - * Calls the given function on each of this component's children in order. If - * {@code opt_obj} is provided, it will be used as the 'this' object in the - * function when called. The function should take two arguments: the child - * component and its 0-based index. The return value is ignored. - * @param {function(this:T,?,number):?} f The function to call for every - * child component; should take 2 arguments (the child and its index). - * @param {T=} opt_obj Used as the 'this' object in f when called. - * @template T - */ -goog.ui.Component.prototype.forEachChild = function(f, opt_obj) { - if (this.children_) { - goog.array.forEach(this.children_, f, opt_obj); - } -}; - - -/** - * Returns the 0-based index of the given child component, or -1 if no such - * child is found. - * @param {goog.ui.Component?} child The child component. - * @return {number} 0-based index of the child component; -1 if not found. - */ -goog.ui.Component.prototype.indexOfChild = function(child) { - return (this.children_ && child) ? goog.array.indexOf(this.children_, child) : - -1; -}; - - -/** - * Removes the given child from this component, and returns it. Throws an error - * if the argument is invalid or if the specified child isn't found in the - * parent component. The argument can either be a string (interpreted as the - * ID of the child component to remove) or the child component itself. - * - * If {@code opt_unrender} is true, calls {@link goog.ui.component#exitDocument} - * on the removed child, and subsequently detaches the child's DOM from the - * document. Otherwise it is the caller's responsibility to clean up the child - * component's DOM. - * - * @see goog.ui.Component#removeChildAt - * @param {string|goog.ui.Component|null} child The ID of the child to remove, - * or the child component itself. - * @param {boolean=} opt_unrender If true, calls {@code exitDocument} on the - * removed child component, and detaches its DOM from the document. - * @return {goog.ui.Component} The removed component, if any. - */ -goog.ui.Component.prototype.removeChild = function(child, opt_unrender) { - if (child) { - // Normalize child to be the object and id to be the ID string. This also - // ensures that the child is really ours. - var id = goog.isString(child) ? child : child.getId(); - child = this.getChild(id); - - if (id && child) { - goog.object.remove(this.childIndex_, id); - goog.array.remove(this.children_, child); - - if (opt_unrender) { - // Remove the child component's DOM from the document. We have to call - // exitDocument first (see documentation). - child.exitDocument(); - if (child.element_) { - goog.dom.removeNode(child.element_); - } - } - - // Child's parent must be set to null after exitDocument is called - // so that the child can unlisten to its parent if required. - child.setParent(null); - } - } - - if (!child) { - throw new Error(goog.ui.Component.Error.NOT_OUR_CHILD); - } - - return /** @type {!goog.ui.Component} */ (child); -}; - - -/** - * Removes the child at the given index from this component, and returns it. - * Throws an error if the argument is out of bounds, or if the specified child - * isn't found in the parent. See {@link goog.ui.Component#removeChild} for - * detailed semantics. - * - * @see goog.ui.Component#removeChild - * @param {number} index 0-based index of the child to remove. - * @param {boolean=} opt_unrender If true, calls {@code exitDocument} on the - * removed child component, and detaches its DOM from the document. - * @return {goog.ui.Component} The removed component, if any. - */ -goog.ui.Component.prototype.removeChildAt = function(index, opt_unrender) { - // removeChild(null) will throw error. - return this.removeChild(this.getChildAt(index), opt_unrender); -}; - - -/** - * Removes every child component attached to this one and returns them. - * - * @see goog.ui.Component#removeChild - * @param {boolean=} opt_unrender If true, calls {@link #exitDocument} on the - * removed child components, and detaches their DOM from the document. - * @return {!Array<goog.ui.Component>} The removed components if any. - */ -goog.ui.Component.prototype.removeChildren = function(opt_unrender) { - var removedChildren = []; - while (this.hasChildren()) { - removedChildren.push(this.removeChildAt(0, opt_unrender)); - } - return removedChildren; -};
diff --git a/third_party/ink/closure/ui/idgenerator.js b/third_party/ink/closure/ui/idgenerator.js deleted file mode 100644 index 799dc2b..0000000 --- a/third_party/ink/closure/ui/idgenerator.js +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Generator for unique element IDs. - * - * @author jonp@google.com (Jon Perlow) - */ - -goog.provide('goog.ui.IdGenerator'); - - - -/** - * Creates a new id generator. - * @constructor - * @final - */ -goog.ui.IdGenerator = function() {}; -goog.addSingletonGetter(goog.ui.IdGenerator); - - -/** - * Next unique ID to use - * @type {number} - * @private - */ -goog.ui.IdGenerator.prototype.nextId_ = 0; - - -/** - * Gets the next unique ID. - * @return {string} The next unique identifier. - */ -goog.ui.IdGenerator.prototype.getNextUniqueId = function() { - return ':' + (this.nextId_++).toString(36); -};
diff --git a/third_party/ink/closure/uri/uri.js b/third_party/ink/closure/uri/uri.js deleted file mode 100644 index 33bb5ac..0000000 --- a/third_party/ink/closure/uri/uri.js +++ /dev/null
@@ -1,1550 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Class for parsing and formatting URIs. - * - * Use goog.Uri(string) to parse a URI string. Use goog.Uri.create(...) to - * create a new instance of the goog.Uri object from Uri parts. - * - * e.g: <code>var myUri = new goog.Uri(window.location);</code> - * - * Implements RFC 3986 for parsing/formatting URIs. - * http://www.ietf.org/rfc/rfc3986.txt - * - * Some changes have been made to the interface (more like .NETs), though the - * internal representation is now of un-encoded parts, this will change the - * behavior slightly. - * - * @author msamuel@google.com (Mike Samuel) - * @author pupius@google.com (Dan Pupius) - Ported to Closure - * @author jonp@google.com (Jon Perlow) - Optimized for IE6 - * @author micapolos@google.com (Michal Pociecha-Los) - Dot segments removal - */ - -goog.provide('goog.Uri'); -goog.provide('goog.Uri.QueryData'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.string'); -goog.require('goog.structs'); -goog.require('goog.structs.Map'); -goog.require('goog.uri.utils'); -goog.require('goog.uri.utils.ComponentIndex'); -goog.require('goog.uri.utils.StandardQueryParam'); - - - -/** - * This class contains setters and getters for the parts of the URI. - * The <code>getXyz</code>/<code>setXyz</code> methods return the decoded part - * -- so<code>goog.Uri.parse('/foo%20bar').getPath()</code> will return the - * decoded path, <code>/foo bar</code>. - * - * Reserved characters (see RFC 3986 section 2.2) can be present in - * their percent-encoded form in scheme, domain, and path URI components and - * will not be auto-decoded. For example: - * <code>goog.Uri.parse('rel%61tive/path%2fto/resource').getPath()</code> will - * return <code>relative/path%2fto/resource</code>. - * - * The constructor accepts an optional unparsed, raw URI string. The parser - * is relaxed, so special characters that aren't escaped but don't cause - * ambiguities will not cause parse failures. - * - * All setters return <code>this</code> and so may be chained, a la - * <code>goog.Uri.parse('/foo').setFragment('part').toString()</code>. - * - * @param {*=} opt_uri Optional string URI to parse - * (use goog.Uri.create() to create a URI from parts), or if - * a goog.Uri is passed, a clone is created. - * @param {boolean=} opt_ignoreCase If true, #getParameterValue will ignore - * the case of the parameter name. - * - * @throws URIError If opt_uri is provided and URI is malformed (that is, - * if decodeURIComponent fails on any of the URI components). - * @constructor - * @struct - */ -goog.Uri = function(opt_uri, opt_ignoreCase) { - /** - * Scheme such as "http". - * @private {string} - */ - this.scheme_ = ''; - - /** - * User credentials in the form "username:password". - * @private {string} - */ - this.userInfo_ = ''; - - /** - * Domain part, e.g. "www.google.com". - * @private {string} - */ - this.domain_ = ''; - - /** - * Port, e.g. 8080. - * @private {?number} - */ - this.port_ = null; - - /** - * Path, e.g. "/tests/img.png". - * @private {string} - */ - this.path_ = ''; - - /** - * The fragment without the #. - * @private {string} - */ - this.fragment_ = ''; - - /** - * Whether or not this Uri should be treated as Read Only. - * @private {boolean} - */ - this.isReadOnly_ = false; - - /** - * Whether or not to ignore case when comparing query params. - * @private {boolean} - */ - this.ignoreCase_ = false; - - /** - * Object representing query data. - * @private {!goog.Uri.QueryData} - */ - this.queryData_; - - // Parse in the uri string - var m; - if (opt_uri instanceof goog.Uri) { - this.ignoreCase_ = - goog.isDef(opt_ignoreCase) ? opt_ignoreCase : opt_uri.getIgnoreCase(); - this.setScheme(opt_uri.getScheme()); - this.setUserInfo(opt_uri.getUserInfo()); - this.setDomain(opt_uri.getDomain()); - this.setPort(opt_uri.getPort()); - this.setPath(opt_uri.getPath()); - this.setQueryData(opt_uri.getQueryData().clone()); - this.setFragment(opt_uri.getFragment()); - } else if (opt_uri && (m = goog.uri.utils.split(String(opt_uri)))) { - this.ignoreCase_ = !!opt_ignoreCase; - - // Set the parts -- decoding as we do so. - // COMPATIBILITY NOTE - In IE, unmatched fields may be empty strings, - // whereas in other browsers they will be undefined. - this.setScheme(m[goog.uri.utils.ComponentIndex.SCHEME] || '', true); - this.setUserInfo(m[goog.uri.utils.ComponentIndex.USER_INFO] || '', true); - this.setDomain(m[goog.uri.utils.ComponentIndex.DOMAIN] || '', true); - this.setPort(m[goog.uri.utils.ComponentIndex.PORT]); - this.setPath(m[goog.uri.utils.ComponentIndex.PATH] || '', true); - this.setQueryData(m[goog.uri.utils.ComponentIndex.QUERY_DATA] || '', true); - this.setFragment(m[goog.uri.utils.ComponentIndex.FRAGMENT] || '', true); - - } else { - this.ignoreCase_ = !!opt_ignoreCase; - this.queryData_ = new goog.Uri.QueryData(null, null, this.ignoreCase_); - } -}; - - -/** - * If true, we preserve the type of query parameters set programmatically. - * - * This means that if you set a parameter to a boolean, and then call - * getParameterValue, you will get a boolean back. - * - * If false, we will coerce parameters to strings, just as they would - * appear in real URIs. - * - * TODO(nicksantos): Remove this once people have time to fix all tests. - * - * @type {boolean} - */ -goog.Uri.preserveParameterTypesCompatibilityFlag = false; - - -/** - * Parameter name added to stop caching. - * @type {string} - */ -goog.Uri.RANDOM_PARAM = goog.uri.utils.StandardQueryParam.RANDOM; - - -/** - * @return {string} The string form of the url. - * @override - */ -goog.Uri.prototype.toString = function() { - var out = []; - - var scheme = this.getScheme(); - if (scheme) { - out.push( - goog.Uri.encodeSpecialChars_( - scheme, goog.Uri.reDisallowedInSchemeOrUserInfo_, true), - ':'); - } - - var domain = this.getDomain(); - if (domain || scheme == 'file') { - out.push('//'); - - var userInfo = this.getUserInfo(); - if (userInfo) { - out.push( - goog.Uri.encodeSpecialChars_( - userInfo, goog.Uri.reDisallowedInSchemeOrUserInfo_, true), - '@'); - } - - out.push(goog.Uri.removeDoubleEncoding_(goog.string.urlEncode(domain))); - - var port = this.getPort(); - if (port != null) { - out.push(':', String(port)); - } - } - - var path = this.getPath(); - if (path) { - if (this.hasDomain() && path.charAt(0) != '/') { - out.push('/'); - } - out.push( - goog.Uri.encodeSpecialChars_( - path, path.charAt(0) == '/' ? goog.Uri.reDisallowedInAbsolutePath_ : - goog.Uri.reDisallowedInRelativePath_, - true)); - } - - var query = this.getEncodedQuery(); - if (query) { - out.push('?', query); - } - - var fragment = this.getFragment(); - if (fragment) { - out.push( - '#', goog.Uri.encodeSpecialChars_( - fragment, goog.Uri.reDisallowedInFragment_)); - } - return out.join(''); -}; - - -/** - * Resolves the given relative URI (a goog.Uri object), using the URI - * represented by this instance as the base URI. - * - * There are several kinds of relative URIs:<br> - * 1. foo - replaces the last part of the path, the whole query and fragment<br> - * 2. /foo - replaces the the path, the query and fragment<br> - * 3. //foo - replaces everything from the domain on. foo is a domain name<br> - * 4. ?foo - replace the query and fragment<br> - * 5. #foo - replace the fragment only - * - * Additionally, if relative URI has a non-empty path, all ".." and "." - * segments will be resolved, as described in RFC 3986. - * - * @param {!goog.Uri} relativeUri The relative URI to resolve. - * @return {!goog.Uri} The resolved URI. - */ -goog.Uri.prototype.resolve = function(relativeUri) { - - var absoluteUri = this.clone(); - - // we satisfy these conditions by looking for the first part of relativeUri - // that is not blank and applying defaults to the rest - - var overridden = relativeUri.hasScheme(); - - if (overridden) { - absoluteUri.setScheme(relativeUri.getScheme()); - } else { - overridden = relativeUri.hasUserInfo(); - } - - if (overridden) { - absoluteUri.setUserInfo(relativeUri.getUserInfo()); - } else { - overridden = relativeUri.hasDomain(); - } - - if (overridden) { - absoluteUri.setDomain(relativeUri.getDomain()); - } else { - overridden = relativeUri.hasPort(); - } - - var path = relativeUri.getPath(); - if (overridden) { - absoluteUri.setPort(relativeUri.getPort()); - } else { - overridden = relativeUri.hasPath(); - if (overridden) { - // resolve path properly - if (path.charAt(0) != '/') { - // path is relative - if (this.hasDomain() && !this.hasPath()) { - // RFC 3986, section 5.2.3, case 1 - path = '/' + path; - } else { - // RFC 3986, section 5.2.3, case 2 - var lastSlashIndex = absoluteUri.getPath().lastIndexOf('/'); - if (lastSlashIndex != -1) { - path = absoluteUri.getPath().substr(0, lastSlashIndex + 1) + path; - } - } - } - path = goog.Uri.removeDotSegments(path); - } - } - - if (overridden) { - absoluteUri.setPath(path); - } else { - overridden = relativeUri.hasQuery(); - } - - if (overridden) { - absoluteUri.setQueryData(relativeUri.getQueryData().clone()); - } else { - overridden = relativeUri.hasFragment(); - } - - if (overridden) { - absoluteUri.setFragment(relativeUri.getFragment()); - } - - return absoluteUri; -}; - - -/** - * Clones the URI instance. - * @return {!goog.Uri} New instance of the URI object. - */ -goog.Uri.prototype.clone = function() { - return new goog.Uri(this); -}; - - -/** - * @return {string} The encoded scheme/protocol for the URI. - */ -goog.Uri.prototype.getScheme = function() { - return this.scheme_; -}; - - -/** - * Sets the scheme/protocol. - * @throws URIError If opt_decode is true and newScheme is malformed (that is, - * if decodeURIComponent fails). - * @param {string} newScheme New scheme value. - * @param {boolean=} opt_decode Optional param for whether to decode new value. - * @return {!goog.Uri} Reference to this URI object. - */ -goog.Uri.prototype.setScheme = function(newScheme, opt_decode) { - this.enforceReadOnly(); - this.scheme_ = - opt_decode ? goog.Uri.decodeOrEmpty_(newScheme, true) : newScheme; - - // remove an : at the end of the scheme so somebody can pass in - // window.location.protocol - if (this.scheme_) { - this.scheme_ = this.scheme_.replace(/:$/, ''); - } - return this; -}; - - -/** - * @return {boolean} Whether the scheme has been set. - */ -goog.Uri.prototype.hasScheme = function() { - return !!this.scheme_; -}; - - -/** - * @return {string} The decoded user info. - */ -goog.Uri.prototype.getUserInfo = function() { - return this.userInfo_; -}; - - -/** - * Sets the userInfo. - * @throws URIError If opt_decode is true and newUserInfo is malformed (that is, - * if decodeURIComponent fails). - * @param {string} newUserInfo New userInfo value. - * @param {boolean=} opt_decode Optional param for whether to decode new value. - * @return {!goog.Uri} Reference to this URI object. - */ -goog.Uri.prototype.setUserInfo = function(newUserInfo, opt_decode) { - this.enforceReadOnly(); - this.userInfo_ = - opt_decode ? goog.Uri.decodeOrEmpty_(newUserInfo) : newUserInfo; - return this; -}; - - -/** - * @return {boolean} Whether the user info has been set. - */ -goog.Uri.prototype.hasUserInfo = function() { - return !!this.userInfo_; -}; - - -/** - * @return {string} The decoded domain. - */ -goog.Uri.prototype.getDomain = function() { - return this.domain_; -}; - - -/** - * Sets the domain. - * @throws URIError If opt_decode is true and newDomain is malformed (that is, - * if decodeURIComponent fails). - * @param {string} newDomain New domain value. - * @param {boolean=} opt_decode Optional param for whether to decode new value. - * @return {!goog.Uri} Reference to this URI object. - */ -goog.Uri.prototype.setDomain = function(newDomain, opt_decode) { - this.enforceReadOnly(); - this.domain_ = - opt_decode ? goog.Uri.decodeOrEmpty_(newDomain, true) : newDomain; - return this; -}; - - -/** - * @return {boolean} Whether the domain has been set. - */ -goog.Uri.prototype.hasDomain = function() { - return !!this.domain_; -}; - - -/** - * @return {?number} The port number. - */ -goog.Uri.prototype.getPort = function() { - return this.port_; -}; - - -/** - * Sets the port number. - * @param {*} newPort Port number. Will be explicitly casted to a number. - * @return {!goog.Uri} Reference to this URI object. - */ -goog.Uri.prototype.setPort = function(newPort) { - this.enforceReadOnly(); - - if (newPort) { - newPort = Number(newPort); - if (isNaN(newPort) || newPort < 0) { - throw new Error('Bad port number ' + newPort); - } - this.port_ = newPort; - } else { - this.port_ = null; - } - - return this; -}; - - -/** - * @return {boolean} Whether the port has been set. - */ -goog.Uri.prototype.hasPort = function() { - return this.port_ != null; -}; - - -/** - * @return {string} The decoded path. - */ -goog.Uri.prototype.getPath = function() { - return this.path_; -}; - - -/** - * Sets the path. - * @throws URIError If opt_decode is true and newPath is malformed (that is, - * if decodeURIComponent fails). - * @param {string} newPath New path value. - * @param {boolean=} opt_decode Optional param for whether to decode new value. - * @return {!goog.Uri} Reference to this URI object. - */ -goog.Uri.prototype.setPath = function(newPath, opt_decode) { - this.enforceReadOnly(); - this.path_ = opt_decode ? goog.Uri.decodeOrEmpty_(newPath, true) : newPath; - return this; -}; - - -/** - * @return {boolean} Whether the path has been set. - */ -goog.Uri.prototype.hasPath = function() { - return !!this.path_; -}; - - -/** - * @return {boolean} Whether the query string has been set. - */ -goog.Uri.prototype.hasQuery = function() { - return this.queryData_.toString() !== ''; -}; - - -/** - * Sets the query data. - * @param {goog.Uri.QueryData|string|undefined} queryData QueryData object. - * @param {boolean=} opt_decode Optional param for whether to decode new value. - * Applies only if queryData is a string. - * @return {!goog.Uri} Reference to this URI object. - */ -goog.Uri.prototype.setQueryData = function(queryData, opt_decode) { - this.enforceReadOnly(); - - if (queryData instanceof goog.Uri.QueryData) { - this.queryData_ = queryData; - this.queryData_.setIgnoreCase(this.ignoreCase_); - } else { - if (!opt_decode) { - // QueryData accepts encoded query string, so encode it if - // opt_decode flag is not true. - queryData = goog.Uri.encodeSpecialChars_( - queryData, goog.Uri.reDisallowedInQuery_); - } - this.queryData_ = new goog.Uri.QueryData(queryData, null, this.ignoreCase_); - } - - return this; -}; - - -/** - * Sets the URI query. - * @param {string} newQuery New query value. - * @param {boolean=} opt_decode Optional param for whether to decode new value. - * @return {!goog.Uri} Reference to this URI object. - */ -goog.Uri.prototype.setQuery = function(newQuery, opt_decode) { - return this.setQueryData(newQuery, opt_decode); -}; - - -/** - * @return {string} The encoded URI query, not including the ?. - */ -goog.Uri.prototype.getEncodedQuery = function() { - return this.queryData_.toString(); -}; - - -/** - * @return {string} The decoded URI query, not including the ?. - */ -goog.Uri.prototype.getDecodedQuery = function() { - return this.queryData_.toDecodedString(); -}; - - -/** - * Returns the query data. - * @return {!goog.Uri.QueryData} QueryData object. - */ -goog.Uri.prototype.getQueryData = function() { - return this.queryData_; -}; - - -/** - * @return {string} The encoded URI query, not including the ?. - * - * Warning: This method, unlike other getter methods, returns encoded - * value, instead of decoded one. - */ -goog.Uri.prototype.getQuery = function() { - return this.getEncodedQuery(); -}; - - -/** - * Sets the value of the named query parameters, clearing previous values for - * that key. - * - * @param {string} key The parameter to set. - * @param {*} value The new value. - * @return {!goog.Uri} Reference to this URI object. - */ -goog.Uri.prototype.setParameterValue = function(key, value) { - this.enforceReadOnly(); - this.queryData_.set(key, value); - return this; -}; - - -/** - * Sets the values of the named query parameters, clearing previous values for - * that key. Not new values will currently be moved to the end of the query - * string. - * - * So, <code>goog.Uri.parse('foo?a=b&c=d&e=f').setParameterValues('c', ['new']) - * </code> yields <tt>foo?a=b&e=f&c=new</tt>.</p> - * - * @param {string} key The parameter to set. - * @param {*} values The new values. If values is a single - * string then it will be treated as the sole value. - * @return {!goog.Uri} Reference to this URI object. - */ -goog.Uri.prototype.setParameterValues = function(key, values) { - this.enforceReadOnly(); - - if (!goog.isArray(values)) { - values = [String(values)]; - } - - this.queryData_.setValues(key, values); - - return this; -}; - - -/** - * Returns the value<b>s</b> for a given cgi parameter as a list of decoded - * query parameter values. - * @param {string} name The parameter to get values for. - * @return {!Array<?>} The values for a given cgi parameter as a list of - * decoded query parameter values. - */ -goog.Uri.prototype.getParameterValues = function(name) { - return this.queryData_.getValues(name); -}; - - -/** - * Returns the first value for a given cgi parameter or undefined if the given - * parameter name does not appear in the query string. - * @param {string} paramName Unescaped parameter name. - * @return {string|undefined} The first value for a given cgi parameter or - * undefined if the given parameter name does not appear in the query - * string. - */ -goog.Uri.prototype.getParameterValue = function(paramName) { - // NOTE(nicksantos): This type-cast is a lie when - // preserveParameterTypesCompatibilityFlag is set to true. - // But this should only be set to true in tests. - return /** @type {string|undefined} */ (this.queryData_.get(paramName)); -}; - - -/** - * @return {string} The URI fragment, not including the #. - */ -goog.Uri.prototype.getFragment = function() { - return this.fragment_; -}; - - -/** - * Sets the URI fragment. - * @throws URIError If opt_decode is true and newFragment is malformed (that is, - * if decodeURIComponent fails). - * @param {string} newFragment New fragment value. - * @param {boolean=} opt_decode Optional param for whether to decode new value. - * @return {!goog.Uri} Reference to this URI object. - */ -goog.Uri.prototype.setFragment = function(newFragment, opt_decode) { - this.enforceReadOnly(); - this.fragment_ = - opt_decode ? goog.Uri.decodeOrEmpty_(newFragment) : newFragment; - return this; -}; - - -/** - * @return {boolean} Whether the URI has a fragment set. - */ -goog.Uri.prototype.hasFragment = function() { - return !!this.fragment_; -}; - - -/** - * Returns true if this has the same domain as that of uri2. - * @param {!goog.Uri} uri2 The URI object to compare to. - * @return {boolean} true if same domain; false otherwise. - */ -goog.Uri.prototype.hasSameDomainAs = function(uri2) { - return ((!this.hasDomain() && !uri2.hasDomain()) || - this.getDomain() == uri2.getDomain()) && - ((!this.hasPort() && !uri2.hasPort()) || - this.getPort() == uri2.getPort()); -}; - - -/** - * Adds a random parameter to the Uri. - * @return {!goog.Uri} Reference to this Uri object. - */ -goog.Uri.prototype.makeUnique = function() { - this.enforceReadOnly(); - this.setParameterValue(goog.Uri.RANDOM_PARAM, goog.string.getRandomString()); - - return this; -}; - - -/** - * Removes the named query parameter. - * - * @param {string} key The parameter to remove. - * @return {!goog.Uri} Reference to this URI object. - */ -goog.Uri.prototype.removeParameter = function(key) { - this.enforceReadOnly(); - this.queryData_.remove(key); - return this; -}; - - -/** - * Sets whether Uri is read only. If this goog.Uri is read-only, - * enforceReadOnly_ will be called at the start of any function that may modify - * this Uri. - * @param {boolean} isReadOnly whether this goog.Uri should be read only. - * @return {!goog.Uri} Reference to this Uri object. - */ -goog.Uri.prototype.setReadOnly = function(isReadOnly) { - this.isReadOnly_ = isReadOnly; - return this; -}; - - -/** - * @return {boolean} Whether the URI is read only. - */ -goog.Uri.prototype.isReadOnly = function() { - return this.isReadOnly_; -}; - - -/** - * Checks if this Uri has been marked as read only, and if so, throws an error. - * This should be called whenever any modifying function is called. - */ -goog.Uri.prototype.enforceReadOnly = function() { - if (this.isReadOnly_) { - throw new Error('Tried to modify a read-only Uri'); - } -}; - - -/** - * Sets whether to ignore case. - * NOTE: If there are already key/value pairs in the QueryData, and - * ignoreCase_ is set to false, the keys will all be lower-cased. - * @param {boolean} ignoreCase whether this goog.Uri should ignore case. - * @return {!goog.Uri} Reference to this Uri object. - */ -goog.Uri.prototype.setIgnoreCase = function(ignoreCase) { - this.ignoreCase_ = ignoreCase; - if (this.queryData_) { - this.queryData_.setIgnoreCase(ignoreCase); - } - return this; -}; - - -/** - * @return {boolean} Whether to ignore case. - */ -goog.Uri.prototype.getIgnoreCase = function() { - return this.ignoreCase_; -}; - - -//============================================================================== -// Static members -//============================================================================== - - -/** - * Creates a uri from the string form. Basically an alias of new goog.Uri(). - * If a Uri object is passed to parse then it will return a clone of the object. - * - * @throws URIError If parsing the URI is malformed. The passed URI components - * should all be parseable by decodeURIComponent. - * @param {*} uri Raw URI string or instance of Uri - * object. - * @param {boolean=} opt_ignoreCase Whether to ignore the case of parameter - * names in #getParameterValue. - * @return {!goog.Uri} The new URI object. - */ -goog.Uri.parse = function(uri, opt_ignoreCase) { - return uri instanceof goog.Uri ? uri.clone() : - new goog.Uri(uri, opt_ignoreCase); -}; - - -/** - * Creates a new goog.Uri object from unencoded parts. - * - * @param {?string=} opt_scheme Scheme/protocol or full URI to parse. - * @param {?string=} opt_userInfo username:password. - * @param {?string=} opt_domain www.google.com. - * @param {?number=} opt_port 9830. - * @param {?string=} opt_path /some/path/to/a/file.html. - * @param {string|goog.Uri.QueryData=} opt_query a=1&b=2. - * @param {?string=} opt_fragment The fragment without the #. - * @param {boolean=} opt_ignoreCase Whether to ignore parameter name case in - * #getParameterValue. - * - * @return {!goog.Uri} The new URI object. - */ -goog.Uri.create = function( - opt_scheme, opt_userInfo, opt_domain, opt_port, opt_path, opt_query, - opt_fragment, opt_ignoreCase) { - - var uri = new goog.Uri(null, opt_ignoreCase); - - // Only set the parts if they are defined and not empty strings. - opt_scheme && uri.setScheme(opt_scheme); - opt_userInfo && uri.setUserInfo(opt_userInfo); - opt_domain && uri.setDomain(opt_domain); - opt_port && uri.setPort(opt_port); - opt_path && uri.setPath(opt_path); - opt_query && uri.setQueryData(opt_query); - opt_fragment && uri.setFragment(opt_fragment); - - return uri; -}; - - -/** - * Resolves a relative Uri against a base Uri, accepting both strings and - * Uri objects. - * - * @param {*} base Base Uri. - * @param {*} rel Relative Uri. - * @return {!goog.Uri} Resolved uri. - */ -goog.Uri.resolve = function(base, rel) { - if (!(base instanceof goog.Uri)) { - base = goog.Uri.parse(base); - } - - if (!(rel instanceof goog.Uri)) { - rel = goog.Uri.parse(rel); - } - - return base.resolve(rel); -}; - - -/** - * Removes dot segments in given path component, as described in - * RFC 3986, section 5.2.4. - * - * @param {string} path A non-empty path component. - * @return {string} Path component with removed dot segments. - */ -goog.Uri.removeDotSegments = function(path) { - if (path == '..' || path == '.') { - return ''; - - } else if ( - !goog.string.contains(path, './') && !goog.string.contains(path, '/.')) { - // This optimization detects uris which do not contain dot-segments, - // and as a consequence do not require any processing. - return path; - - } else { - var leadingSlash = goog.string.startsWith(path, '/'); - var segments = path.split('/'); - var out = []; - - for (var pos = 0; pos < segments.length;) { - var segment = segments[pos++]; - - if (segment == '.') { - if (leadingSlash && pos == segments.length) { - out.push(''); - } - } else if (segment == '..') { - if (out.length > 1 || out.length == 1 && out[0] != '') { - out.pop(); - } - if (leadingSlash && pos == segments.length) { - out.push(''); - } - } else { - out.push(segment); - leadingSlash = true; - } - } - - return out.join('/'); - } -}; - - -/** - * Decodes a value or returns the empty string if it isn't defined or empty. - * @throws URIError If decodeURIComponent fails to decode val. - * @param {string|undefined} val Value to decode. - * @param {boolean=} opt_preserveReserved If true, restricted characters will - * not be decoded. - * @return {string} Decoded value. - * @private - */ -goog.Uri.decodeOrEmpty_ = function(val, opt_preserveReserved) { - // Don't use UrlDecode() here because val is not a query parameter. - if (!val) { - return ''; - } - - // decodeURI has the same output for '%2f' and '%252f'. We double encode %25 - // so that we can distinguish between the 2 inputs. This is later undone by - // removeDoubleEncoding_. - return opt_preserveReserved ? decodeURI(val.replace(/%25/g, '%2525')) : - decodeURIComponent(val); -}; - - -/** - * If unescapedPart is non null, then escapes any characters in it that aren't - * valid characters in a url and also escapes any special characters that - * appear in extra. - * - * @param {*} unescapedPart The string to encode. - * @param {RegExp} extra A character set of characters in [\01-\177]. - * @param {boolean=} opt_removeDoubleEncoding If true, remove double percent - * encoding. - * @return {?string} null iff unescapedPart == null. - * @private - */ -goog.Uri.encodeSpecialChars_ = function( - unescapedPart, extra, opt_removeDoubleEncoding) { - if (goog.isString(unescapedPart)) { - var encoded = encodeURI(unescapedPart).replace(extra, goog.Uri.encodeChar_); - if (opt_removeDoubleEncoding) { - // encodeURI double-escapes %XX sequences used to represent restricted - // characters in some URI components, remove the double escaping here. - encoded = goog.Uri.removeDoubleEncoding_(encoded); - } - return encoded; - } - return null; -}; - - -/** - * Converts a character in [\01-\177] to its unicode character equivalent. - * @param {string} ch One character string. - * @return {string} Encoded string. - * @private - */ -goog.Uri.encodeChar_ = function(ch) { - var n = ch.charCodeAt(0); - return '%' + ((n >> 4) & 0xf).toString(16) + (n & 0xf).toString(16); -}; - - -/** - * Removes double percent-encoding from a string. - * @param {string} doubleEncodedString String - * @return {string} String with double encoding removed. - * @private - */ -goog.Uri.removeDoubleEncoding_ = function(doubleEncodedString) { - return doubleEncodedString.replace(/%25([0-9a-fA-F]{2})/g, '%$1'); -}; - - -/** - * Regular expression for characters that are disallowed in the scheme or - * userInfo part of the URI. - * @type {RegExp} - * @private - */ -goog.Uri.reDisallowedInSchemeOrUserInfo_ = /[#\/\?@]/g; - - -/** - * Regular expression for characters that are disallowed in a relative path. - * Colon is included due to RFC 3986 3.3. - * @type {RegExp} - * @private - */ -goog.Uri.reDisallowedInRelativePath_ = /[\#\?:]/g; - - -/** - * Regular expression for characters that are disallowed in an absolute path. - * @type {RegExp} - * @private - */ -goog.Uri.reDisallowedInAbsolutePath_ = /[\#\?]/g; - - -/** - * Regular expression for characters that are disallowed in the query. - * @type {RegExp} - * @private - */ -goog.Uri.reDisallowedInQuery_ = /[\#\?@]/g; - - -/** - * Regular expression for characters that are disallowed in the fragment. - * @type {RegExp} - * @private - */ -goog.Uri.reDisallowedInFragment_ = /#/g; - - -/** - * Checks whether two URIs have the same domain. - * @param {string} uri1String First URI string. - * @param {string} uri2String Second URI string. - * @return {boolean} true if the two URIs have the same domain; false otherwise. - */ -goog.Uri.haveSameDomain = function(uri1String, uri2String) { - // Differs from goog.uri.utils.haveSameDomain, since this ignores scheme. - // TODO(gboyer): Have this just call goog.uri.util.haveSameDomain. - var pieces1 = goog.uri.utils.split(uri1String); - var pieces2 = goog.uri.utils.split(uri2String); - return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] == - pieces2[goog.uri.utils.ComponentIndex.DOMAIN] && - pieces1[goog.uri.utils.ComponentIndex.PORT] == - pieces2[goog.uri.utils.ComponentIndex.PORT]; -}; - - - -/** - * Class used to represent URI query parameters. It is essentially a hash of - * name-value pairs, though a name can be present more than once. - * - * Has the same interface as the collections in goog.structs. - * - * @param {?string=} opt_query Optional encoded query string to parse into - * the object. - * @param {goog.Uri=} opt_uri Optional uri object that should have its - * cache invalidated when this object updates. Deprecated -- this - * is no longer required. - * @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter - * name in #get. - * @constructor - * @struct - * @final - */ -goog.Uri.QueryData = function(opt_query, opt_uri, opt_ignoreCase) { - /** - * The map containing name/value or name/array-of-values pairs. - * May be null if it requires parsing from the query string. - * - * We need to use a Map because we cannot guarantee that the key names will - * not be problematic for IE. - * - * @private {goog.structs.Map<string, !Array<*>>} - */ - this.keyMap_ = null; - - /** - * The number of params, or null if it requires computing. - * @private {?number} - */ - this.count_ = null; - - /** - * Encoded query string, or null if it requires computing from the key map. - * @private {?string} - */ - this.encodedQuery_ = opt_query || null; - - /** - * If true, ignore the case of the parameter name in #get. - * @private {boolean} - */ - this.ignoreCase_ = !!opt_ignoreCase; -}; - - -/** - * If the underlying key map is not yet initialized, it parses the - * query string and fills the map with parsed data. - * @private - */ -goog.Uri.QueryData.prototype.ensureKeyMapInitialized_ = function() { - if (!this.keyMap_) { - this.keyMap_ = new goog.structs.Map(); - this.count_ = 0; - if (this.encodedQuery_) { - var self = this; - goog.uri.utils.parseQueryData(this.encodedQuery_, function(name, value) { - self.add(goog.string.urlDecode(name), value); - }); - } - } -}; - - -/** - * Creates a new query data instance from a map of names and values. - * - * @param {!goog.structs.Map<string, ?>|!Object} map Map of string parameter - * names to parameter value. If parameter value is an array, it is - * treated as if the key maps to each individual value in the - * array. - * @param {goog.Uri=} opt_uri URI object that should have its cache - * invalidated when this object updates. - * @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter - * name in #get. - * @return {!goog.Uri.QueryData} The populated query data instance. - */ -goog.Uri.QueryData.createFromMap = function(map, opt_uri, opt_ignoreCase) { - var keys = goog.structs.getKeys(map); - if (typeof keys == 'undefined') { - throw new Error('Keys are undefined'); - } - - var queryData = new goog.Uri.QueryData(null, null, opt_ignoreCase); - var values = goog.structs.getValues(map); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - var value = values[i]; - if (!goog.isArray(value)) { - queryData.add(key, value); - } else { - queryData.setValues(key, value); - } - } - return queryData; -}; - - -/** - * Creates a new query data instance from parallel arrays of parameter names - * and values. Allows for duplicate parameter names. Throws an error if the - * lengths of the arrays differ. - * - * @param {!Array<string>} keys Parameter names. - * @param {!Array<?>} values Parameter values. - * @param {goog.Uri=} opt_uri URI object that should have its cache - * invalidated when this object updates. - * @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter - * name in #get. - * @return {!goog.Uri.QueryData} The populated query data instance. - */ -goog.Uri.QueryData.createFromKeysValues = function( - keys, values, opt_uri, opt_ignoreCase) { - if (keys.length != values.length) { - throw new Error('Mismatched lengths for keys/values'); - } - var queryData = new goog.Uri.QueryData(null, null, opt_ignoreCase); - for (var i = 0; i < keys.length; i++) { - queryData.add(keys[i], values[i]); - } - return queryData; -}; - - -/** - * @return {?number} The number of parameters. - */ -goog.Uri.QueryData.prototype.getCount = function() { - this.ensureKeyMapInitialized_(); - return this.count_; -}; - - -/** - * Adds a key value pair. - * @param {string} key Name. - * @param {*} value Value. - * @return {!goog.Uri.QueryData} Instance of this object. - */ -goog.Uri.QueryData.prototype.add = function(key, value) { - this.ensureKeyMapInitialized_(); - this.invalidateCache_(); - - key = this.getKeyName_(key); - var values = this.keyMap_.get(key); - if (!values) { - this.keyMap_.set(key, (values = [])); - } - values.push(value); - this.count_ = goog.asserts.assertNumber(this.count_) + 1; - return this; -}; - - -/** - * Removes all the params with the given key. - * @param {string} key Name. - * @return {boolean} Whether any parameter was removed. - */ -goog.Uri.QueryData.prototype.remove = function(key) { - this.ensureKeyMapInitialized_(); - - key = this.getKeyName_(key); - if (this.keyMap_.containsKey(key)) { - this.invalidateCache_(); - - // Decrement parameter count. - this.count_ = - goog.asserts.assertNumber(this.count_) - this.keyMap_.get(key).length; - return this.keyMap_.remove(key); - } - return false; -}; - - -/** - * Clears the parameters. - */ -goog.Uri.QueryData.prototype.clear = function() { - this.invalidateCache_(); - this.keyMap_ = null; - this.count_ = 0; -}; - - -/** - * @return {boolean} Whether we have any parameters. - */ -goog.Uri.QueryData.prototype.isEmpty = function() { - this.ensureKeyMapInitialized_(); - return this.count_ == 0; -}; - - -/** - * Whether there is a parameter with the given name - * @param {string} key The parameter name to check for. - * @return {boolean} Whether there is a parameter with the given name. - */ -goog.Uri.QueryData.prototype.containsKey = function(key) { - this.ensureKeyMapInitialized_(); - key = this.getKeyName_(key); - return this.keyMap_.containsKey(key); -}; - - -/** - * Whether there is a parameter with the given value. - * @param {*} value The value to check for. - * @return {boolean} Whether there is a parameter with the given value. - */ -goog.Uri.QueryData.prototype.containsValue = function(value) { - // NOTE(arv): This solution goes through all the params even if it was the - // first param. We can get around this by not reusing code or by switching to - // iterators. - var vals = this.getValues(); - return goog.array.contains(vals, value); -}; - - -/** - * Runs a callback on every key-value pair in the map, including duplicate keys. - * This won't maintain original order when duplicate keys are interspersed (like - * getKeys() / getValues()). - * @param {function(this:SCOPE, ?, string, !goog.Uri.QueryData)} f - * @param {SCOPE=} opt_scope The value of "this" inside f. - * @template SCOPE - */ -goog.Uri.QueryData.prototype.forEach = function(f, opt_scope) { - this.ensureKeyMapInitialized_(); - this.keyMap_.forEach(function(values, key) { - goog.array.forEach(values, function(value) { - f.call(opt_scope, value, key, this); - }, this); - }, this); -}; - - -/** - * Returns all the keys of the parameters. If a key is used multiple times - * it will be included multiple times in the returned array - * @return {!Array<string>} All the keys of the parameters. - */ -goog.Uri.QueryData.prototype.getKeys = function() { - this.ensureKeyMapInitialized_(); - // We need to get the values to know how many keys to add. - var vals = this.keyMap_.getValues(); - var keys = this.keyMap_.getKeys(); - var rv = []; - for (var i = 0; i < keys.length; i++) { - var val = vals[i]; - for (var j = 0; j < val.length; j++) { - rv.push(keys[i]); - } - } - return rv; -}; - - -/** - * Returns all the values of the parameters with the given name. If the query - * data has no such key this will return an empty array. If no key is given - * all values wil be returned. - * @param {string=} opt_key The name of the parameter to get the values for. - * @return {!Array<?>} All the values of the parameters with the given name. - */ -goog.Uri.QueryData.prototype.getValues = function(opt_key) { - this.ensureKeyMapInitialized_(); - var rv = []; - if (goog.isString(opt_key)) { - if (this.containsKey(opt_key)) { - rv = goog.array.concat(rv, this.keyMap_.get(this.getKeyName_(opt_key))); - } - } else { - // Return all values. - var values = this.keyMap_.getValues(); - for (var i = 0; i < values.length; i++) { - rv = goog.array.concat(rv, values[i]); - } - } - return rv; -}; - - -/** - * Sets a key value pair and removes all other keys with the same value. - * - * @param {string} key Name. - * @param {*} value Value. - * @return {!goog.Uri.QueryData} Instance of this object. - */ -goog.Uri.QueryData.prototype.set = function(key, value) { - this.ensureKeyMapInitialized_(); - this.invalidateCache_(); - - // TODO(chrishenry): This could be better written as - // this.remove(key), this.add(key, value), but that would reorder - // the key (since the key is first removed and then added at the - // end) and we would have to fix unit tests that depend on key - // ordering. - key = this.getKeyName_(key); - if (this.containsKey(key)) { - this.count_ = - goog.asserts.assertNumber(this.count_) - this.keyMap_.get(key).length; - } - this.keyMap_.set(key, [value]); - this.count_ = goog.asserts.assertNumber(this.count_) + 1; - return this; -}; - - -/** - * Returns the first value associated with the key. If the query data has no - * such key this will return undefined or the optional default. - * @param {string} key The name of the parameter to get the value for. - * @param {*=} opt_default The default value to return if the query data - * has no such key. - * @return {*} The first string value associated with the key, or opt_default - * if there's no value. - */ -goog.Uri.QueryData.prototype.get = function(key, opt_default) { - var values = key ? this.getValues(key) : []; - if (goog.Uri.preserveParameterTypesCompatibilityFlag) { - return values.length > 0 ? values[0] : opt_default; - } else { - return values.length > 0 ? String(values[0]) : opt_default; - } -}; - - -/** - * Sets the values for a key. If the key already exists, this will - * override all of the existing values that correspond to the key. - * @param {string} key The key to set values for. - * @param {!Array<?>} values The values to set. - */ -goog.Uri.QueryData.prototype.setValues = function(key, values) { - this.remove(key); - - if (values.length > 0) { - this.invalidateCache_(); - this.keyMap_.set(this.getKeyName_(key), goog.array.clone(values)); - this.count_ = goog.asserts.assertNumber(this.count_) + values.length; - } -}; - - -/** - * @return {string} Encoded query string. - * @override - */ -goog.Uri.QueryData.prototype.toString = function() { - if (this.encodedQuery_) { - return this.encodedQuery_; - } - - if (!this.keyMap_) { - return ''; - } - - var sb = []; - - // In the past, we use this.getKeys() and this.getVals(), but that - // generates a lot of allocations as compared to simply iterating - // over the keys. - var keys = this.keyMap_.getKeys(); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - var encodedKey = goog.string.urlEncode(key); - var val = this.getValues(key); - for (var j = 0; j < val.length; j++) { - var param = encodedKey; - // Ensure that null and undefined are encoded into the url as - // literal strings. - if (val[j] !== '') { - param += '=' + goog.string.urlEncode(val[j]); - } - sb.push(param); - } - } - - return this.encodedQuery_ = sb.join('&'); -}; - - -/** - * @throws URIError If URI is malformed (that is, if decodeURIComponent fails on - * any of the URI components). - * @return {string} Decoded query string. - */ -goog.Uri.QueryData.prototype.toDecodedString = function() { - return goog.Uri.decodeOrEmpty_(this.toString()); -}; - - -/** - * Invalidate the cache. - * @private - */ -goog.Uri.QueryData.prototype.invalidateCache_ = function() { - this.encodedQuery_ = null; -}; - - -/** - * Removes all keys that are not in the provided list. (Modifies this object.) - * @param {Array<string>} keys The desired keys. - * @return {!goog.Uri.QueryData} a reference to this object. - */ -goog.Uri.QueryData.prototype.filterKeys = function(keys) { - this.ensureKeyMapInitialized_(); - this.keyMap_.forEach(function(value, key) { - if (!goog.array.contains(keys, key)) { - this.remove(key); - } - }, this); - return this; -}; - - -/** - * Clone the query data instance. - * @return {!goog.Uri.QueryData} New instance of the QueryData object. - */ -goog.Uri.QueryData.prototype.clone = function() { - var rv = new goog.Uri.QueryData(); - rv.encodedQuery_ = this.encodedQuery_; - if (this.keyMap_) { - rv.keyMap_ = this.keyMap_.clone(); - rv.count_ = this.count_; - } - return rv; -}; - - -/** - * Helper function to get the key name from a JavaScript object. Converts - * the object to a string, and to lower case if necessary. - * @private - * @param {*} arg The object to get a key name from. - * @return {string} valid key name which can be looked up in #keyMap_. - */ -goog.Uri.QueryData.prototype.getKeyName_ = function(arg) { - var keyName = String(arg); - if (this.ignoreCase_) { - keyName = keyName.toLowerCase(); - } - return keyName; -}; - - -/** - * Ignore case in parameter names. - * NOTE: If there are already key/value pairs in the QueryData, and - * ignoreCase_ is set to false, the keys will all be lower-cased. - * @param {boolean} ignoreCase whether this goog.Uri should ignore case. - */ -goog.Uri.QueryData.prototype.setIgnoreCase = function(ignoreCase) { - var resetKeys = ignoreCase && !this.ignoreCase_; - if (resetKeys) { - this.ensureKeyMapInitialized_(); - this.invalidateCache_(); - this.keyMap_.forEach(function(value, key) { - var lowerCase = key.toLowerCase(); - if (key != lowerCase) { - this.remove(key); - this.setValues(lowerCase, value); - } - }, this); - } - this.ignoreCase_ = ignoreCase; -}; - - -/** - * Extends a query data object with another query data or map like object. This - * operates 'in-place', it does not create a new QueryData object. - * - * @param {...(?goog.Uri.QueryData|?goog.structs.Map<?, ?>|?Object)} var_args - * The object from which key value pairs will be copied. - * @suppress {deprecated} Use deprecated goog.structs.forEach to allow different - * types of parameters. - */ -goog.Uri.QueryData.prototype.extend = function(var_args) { - for (var i = 0; i < arguments.length; i++) { - var data = arguments[i]; - goog.structs.forEach( - data, function(value, key) { this.add(key, value); }, this); - } -};
diff --git a/third_party/ink/closure/uri/utils.js b/third_party/ink/closure/uri/utils.js deleted file mode 100644 index 3b8917ae..0000000 --- a/third_party/ink/closure/uri/utils.js +++ /dev/null
@@ -1,1103 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Simple utilities for dealing with URI strings. - * - * This is intended to be a lightweight alternative to constructing goog.Uri - * objects. Whereas goog.Uri adds several kilobytes to the binary regardless - * of how much of its functionality you use, this is designed to be a set of - * mostly-independent utilities so that the compiler includes only what is - * necessary for the task. Estimated savings of porting is 5k pre-gzip and - * 1.5k post-gzip. To ensure the savings remain, future developers should - * avoid adding new functionality to existing functions, but instead create - * new ones and factor out shared code. - * - * Many of these utilities have limited functionality, tailored to common - * cases. The query parameter utilities assume that the parameter keys are - * already encoded, since most keys are compile-time alphanumeric strings. The - * query parameter mutation utilities also do not tolerate fragment identifiers. - * - * By design, these functions can be slower than goog.Uri equivalents. - * Repeated calls to some of functions may be quadratic in behavior for IE, - * although the effect is somewhat limited given the 2kb limit. - * - * One advantage of the limited functionality here is that this approach is - * less sensitive to differences in URI encodings than goog.Uri, since these - * functions operate on strings directly, rather than decoding them and - * then re-encoding. - * - * Uses features of RFC 3986 for parsing/formatting URIs: - * http://www.ietf.org/rfc/rfc3986.txt - * - * @author gboyer@google.com (Garrett Boyer) - The "lightened" design. - * @author msamuel@google.com (Mike Samuel) - Domain knowledge and regexes. - */ - -goog.provide('goog.uri.utils'); -goog.provide('goog.uri.utils.ComponentIndex'); -goog.provide('goog.uri.utils.QueryArray'); -goog.provide('goog.uri.utils.QueryValue'); -goog.provide('goog.uri.utils.StandardQueryParam'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.string'); - - -/** - * Character codes inlined to avoid object allocations due to charCode. - * @enum {number} - * @private - */ -goog.uri.utils.CharCode_ = { - AMPERSAND: 38, - EQUAL: 61, - HASH: 35, - QUESTION: 63 -}; - - -/** - * Builds a URI string from already-encoded parts. - * - * No encoding is performed. Any component may be omitted as either null or - * undefined. - * - * @param {?string=} opt_scheme The scheme such as 'http'. - * @param {?string=} opt_userInfo The user name before the '@'. - * @param {?string=} opt_domain The domain such as 'www.google.com', already - * URI-encoded. - * @param {(string|number|null)=} opt_port The port number. - * @param {?string=} opt_path The path, already URI-encoded. If it is not - * empty, it must begin with a slash. - * @param {?string=} opt_queryData The URI-encoded query data. - * @param {?string=} opt_fragment The URI-encoded fragment identifier. - * @return {string} The fully combined URI. - */ -goog.uri.utils.buildFromEncodedParts = function( - opt_scheme, opt_userInfo, opt_domain, opt_port, opt_path, opt_queryData, - opt_fragment) { - var out = ''; - - if (opt_scheme) { - out += opt_scheme + ':'; - } - - if (opt_domain) { - out += '//'; - - if (opt_userInfo) { - out += opt_userInfo + '@'; - } - - out += opt_domain; - - if (opt_port) { - out += ':' + opt_port; - } - } - - if (opt_path) { - out += opt_path; - } - - if (opt_queryData) { - out += '?' + opt_queryData; - } - - if (opt_fragment) { - out += '#' + opt_fragment; - } - - return out; -}; - - -/** - * A regular expression for breaking a URI into its component parts. - * - * {@link http://www.ietf.org/rfc/rfc3986.txt} says in Appendix B - * As the "first-match-wins" algorithm is identical to the "greedy" - * disambiguation method used by POSIX regular expressions, it is natural and - * commonplace to use a regular expression for parsing the potential five - * components of a URI reference. - * - * The following line is the regular expression for breaking-down a - * well-formed URI reference into its components. - * - * <pre> - * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? - * 12 3 4 5 6 7 8 9 - * </pre> - * - * The numbers in the second line above are only to assist readability; they - * indicate the reference points for each subexpression (i.e., each paired - * parenthesis). We refer to the value matched for subexpression <n> as $<n>. - * For example, matching the above expression to - * <pre> - * http://www.ics.uci.edu/pub/ietf/uri/#Related - * </pre> - * results in the following subexpression matches: - * <pre> - * $1 = http: - * $2 = http - * $3 = //www.ics.uci.edu - * $4 = www.ics.uci.edu - * $5 = /pub/ietf/uri/ - * $6 = <undefined> - * $7 = <undefined> - * $8 = #Related - * $9 = Related - * </pre> - * where <undefined> indicates that the component is not present, as is the - * case for the query component in the above example. Therefore, we can - * determine the value of the five components as - * <pre> - * scheme = $2 - * authority = $4 - * path = $5 - * query = $7 - * fragment = $9 - * </pre> - * - * The regular expression has been modified slightly to expose the - * userInfo, domain, and port separately from the authority. - * The modified version yields - * <pre> - * $1 = http scheme - * $2 = <undefined> userInfo -\ - * $3 = www.ics.uci.edu domain | authority - * $4 = <undefined> port -/ - * $5 = /pub/ietf/uri/ path - * $6 = <undefined> query without ? - * $7 = Related fragment without # - * </pre> - * @type {!RegExp} - * @private - */ -goog.uri.utils.splitRe_ = new RegExp( - '^' + - '(?:' + - '([^:/?#.]+)' + // scheme - ignore special characters - // used by other URL parts such as :, - // ?, /, #, and . - ':)?' + - '(?://' + - '(?:([^/?#]*)@)?' + // userInfo - '([^/#?]*?)' + // domain - '(?::([0-9]+))?' + // port - '(?=[/#?]|$)' + // authority-terminating character - ')?' + - '([^?#]+)?' + // path - '(?:\\?([^#]*))?' + // query - '(?:#([\\s\\S]*))?' + // fragment - '$'); - - -/** - * The index of each URI component in the return value of goog.uri.utils.split. - * @enum {number} - */ -goog.uri.utils.ComponentIndex = { - SCHEME: 1, - USER_INFO: 2, - DOMAIN: 3, - PORT: 4, - PATH: 5, - QUERY_DATA: 6, - FRAGMENT: 7 -}; - - -/** - * Splits a URI into its component parts. - * - * Each component can be accessed via the component indices; for example: - * <pre> - * goog.uri.utils.split(someStr)[goog.uri.utils.ComponentIndex.QUERY_DATA]; - * </pre> - * - * @param {string} uri The URI string to examine. - * @return {!Array<string|undefined>} Each component still URI-encoded. - * Each component that is present will contain the encoded value, whereas - * components that are not present will be undefined or empty, depending - * on the browser's regular expression implementation. Never null, since - * arbitrary strings may still look like path names. - */ -goog.uri.utils.split = function(uri) { - // See @return comment -- never null. - return /** @type {!Array<string|undefined>} */ ( - uri.match(goog.uri.utils.splitRe_)); -}; - - -/** - * @param {?string} uri A possibly null string. - * @param {boolean=} opt_preserveReserved If true, percent-encoding of RFC-3986 - * reserved characters will not be removed. - * @return {?string} The string URI-decoded, or null if uri is null. - * @private - */ -goog.uri.utils.decodeIfPossible_ = function(uri, opt_preserveReserved) { - if (!uri) { - return uri; - } - - return opt_preserveReserved ? decodeURI(uri) : decodeURIComponent(uri); -}; - - -/** - * Gets a URI component by index. - * - * It is preferred to use the getPathEncoded() variety of functions ahead, - * since they are more readable. - * - * @param {goog.uri.utils.ComponentIndex} componentIndex The component index. - * @param {string} uri The URI to examine. - * @return {?string} The still-encoded component, or null if the component - * is not present. - * @private - */ -goog.uri.utils.getComponentByIndex_ = function(componentIndex, uri) { - // Convert undefined, null, and empty string into null. - return goog.uri.utils.split(uri)[componentIndex] || null; -}; - - -/** - * @param {string} uri The URI to examine. - * @return {?string} The protocol or scheme, or null if none. Does not - * include trailing colons or slashes. - */ -goog.uri.utils.getScheme = function(uri) { - return goog.uri.utils.getComponentByIndex_( - goog.uri.utils.ComponentIndex.SCHEME, uri); -}; - - -/** - * Gets the effective scheme for the URL. If the URL is relative then the - * scheme is derived from the page's location. - * @param {string} uri The URI to examine. - * @return {string} The protocol or scheme, always lower case. - */ -goog.uri.utils.getEffectiveScheme = function(uri) { - var scheme = goog.uri.utils.getScheme(uri); - if (!scheme && goog.global.self && goog.global.self.location) { - var protocol = goog.global.self.location.protocol; - scheme = protocol.substr(0, protocol.length - 1); - } - // NOTE: When called from a web worker in Firefox 3.5, location maybe null. - // All other browsers with web workers support self.location from the worker. - return scheme ? scheme.toLowerCase() : ''; -}; - - -/** - * @param {string} uri The URI to examine. - * @return {?string} The user name still encoded, or null if none. - */ -goog.uri.utils.getUserInfoEncoded = function(uri) { - return goog.uri.utils.getComponentByIndex_( - goog.uri.utils.ComponentIndex.USER_INFO, uri); -}; - - -/** - * @param {string} uri The URI to examine. - * @return {?string} The decoded user info, or null if none. - */ -goog.uri.utils.getUserInfo = function(uri) { - return goog.uri.utils.decodeIfPossible_( - goog.uri.utils.getUserInfoEncoded(uri)); -}; - - -/** - * @param {string} uri The URI to examine. - * @return {?string} The domain name still encoded, or null if none. - */ -goog.uri.utils.getDomainEncoded = function(uri) { - return goog.uri.utils.getComponentByIndex_( - goog.uri.utils.ComponentIndex.DOMAIN, uri); -}; - - -/** - * @param {string} uri The URI to examine. - * @return {?string} The decoded domain, or null if none. - */ -goog.uri.utils.getDomain = function(uri) { - return goog.uri.utils.decodeIfPossible_( - goog.uri.utils.getDomainEncoded(uri), true /* opt_preserveReserved */); -}; - - -/** - * @param {string} uri The URI to examine. - * @return {?number} The port number, or null if none. - */ -goog.uri.utils.getPort = function(uri) { - // Coerce to a number. If the result of getComponentByIndex_ is null or - // non-numeric, the number coersion yields NaN. This will then return - // null for all non-numeric cases (though also zero, which isn't a relevant - // port number). - return Number( - goog.uri.utils.getComponentByIndex_( - goog.uri.utils.ComponentIndex.PORT, uri)) || - null; -}; - - -/** - * @param {string} uri The URI to examine. - * @return {?string} The path still encoded, or null if none. Includes the - * leading slash, if any. - */ -goog.uri.utils.getPathEncoded = function(uri) { - return goog.uri.utils.getComponentByIndex_( - goog.uri.utils.ComponentIndex.PATH, uri); -}; - - -/** - * @param {string} uri The URI to examine. - * @return {?string} The decoded path, or null if none. Includes the leading - * slash, if any. - */ -goog.uri.utils.getPath = function(uri) { - return goog.uri.utils.decodeIfPossible_( - goog.uri.utils.getPathEncoded(uri), true /* opt_preserveReserved */); -}; - - -/** - * @param {string} uri The URI to examine. - * @return {?string} The query data still encoded, or null if none. Does not - * include the question mark itself. - */ -goog.uri.utils.getQueryData = function(uri) { - return goog.uri.utils.getComponentByIndex_( - goog.uri.utils.ComponentIndex.QUERY_DATA, uri); -}; - - -/** - * @param {string} uri The URI to examine. - * @return {?string} The fragment identifier, or null if none. Does not - * include the hash mark itself. - */ -goog.uri.utils.getFragmentEncoded = function(uri) { - // The hash mark may not appear in any other part of the URL. - var hashIndex = uri.indexOf('#'); - return hashIndex < 0 ? null : uri.substr(hashIndex + 1); -}; - - -/** - * @param {string} uri The URI to examine. - * @param {?string} fragment The encoded fragment identifier, or null if none. - * Does not include the hash mark itself. - * @return {string} The URI with the fragment set. - */ -goog.uri.utils.setFragmentEncoded = function(uri, fragment) { - return goog.uri.utils.removeFragment(uri) + (fragment ? '#' + fragment : ''); -}; - - -/** - * @param {string} uri The URI to examine. - * @return {?string} The decoded fragment identifier, or null if none. Does - * not include the hash mark. - */ -goog.uri.utils.getFragment = function(uri) { - return goog.uri.utils.decodeIfPossible_( - goog.uri.utils.getFragmentEncoded(uri)); -}; - - -/** - * Extracts everything up to the port of the URI. - * @param {string} uri The URI string. - * @return {string} Everything up to and including the port. - */ -goog.uri.utils.getHost = function(uri) { - var pieces = goog.uri.utils.split(uri); - return goog.uri.utils.buildFromEncodedParts( - pieces[goog.uri.utils.ComponentIndex.SCHEME], - pieces[goog.uri.utils.ComponentIndex.USER_INFO], - pieces[goog.uri.utils.ComponentIndex.DOMAIN], - pieces[goog.uri.utils.ComponentIndex.PORT]); -}; - - -/** - * Returns the origin for a given URL. - * @param {string} uri The URI string. - * @return {string} Everything up to and including the port. - */ -goog.uri.utils.getOrigin = function(uri) { - var pieces = goog.uri.utils.split(uri); - return goog.uri.utils.buildFromEncodedParts( - pieces[goog.uri.utils.ComponentIndex.SCHEME], null /* opt_userInfo */, - pieces[goog.uri.utils.ComponentIndex.DOMAIN], - pieces[goog.uri.utils.ComponentIndex.PORT]); -}; - - -/** - * Extracts the path of the URL and everything after. - * @param {string} uri The URI string. - * @return {string} The URI, starting at the path and including the query - * parameters and fragment identifier. - */ -goog.uri.utils.getPathAndAfter = function(uri) { - var pieces = goog.uri.utils.split(uri); - return goog.uri.utils.buildFromEncodedParts( - null, null, null, null, pieces[goog.uri.utils.ComponentIndex.PATH], - pieces[goog.uri.utils.ComponentIndex.QUERY_DATA], - pieces[goog.uri.utils.ComponentIndex.FRAGMENT]); -}; - - -/** - * Gets the URI with the fragment identifier removed. - * @param {string} uri The URI to examine. - * @return {string} Everything preceding the hash mark. - */ -goog.uri.utils.removeFragment = function(uri) { - // The hash mark may not appear in any other part of the URL. - var hashIndex = uri.indexOf('#'); - return hashIndex < 0 ? uri : uri.substr(0, hashIndex); -}; - - -/** - * Ensures that two URI's have the exact same domain, scheme, and port. - * - * Unlike the version in goog.Uri, this checks protocol, and therefore is - * suitable for checking against the browser's same-origin policy. - * - * @param {string} uri1 The first URI. - * @param {string} uri2 The second URI. - * @return {boolean} Whether they have the same scheme, domain and port. - */ -goog.uri.utils.haveSameDomain = function(uri1, uri2) { - var pieces1 = goog.uri.utils.split(uri1); - var pieces2 = goog.uri.utils.split(uri2); - return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] == - pieces2[goog.uri.utils.ComponentIndex.DOMAIN] && - pieces1[goog.uri.utils.ComponentIndex.SCHEME] == - pieces2[goog.uri.utils.ComponentIndex.SCHEME] && - pieces1[goog.uri.utils.ComponentIndex.PORT] == - pieces2[goog.uri.utils.ComponentIndex.PORT]; -}; - - -/** - * Asserts that there are no fragment or query identifiers, only in uncompiled - * mode. - * @param {string} uri The URI to examine. - * @private - */ -goog.uri.utils.assertNoFragmentsOrQueries_ = function(uri) { - goog.asserts.assert( - uri.indexOf('#') < 0 && uri.indexOf('?') < 0, - 'goog.uri.utils: Fragment or query identifiers are not supported: [%s]', - uri); -}; - - -/** - * Supported query parameter values by the parameter serializing utilities. - * - * If a value is null or undefined, the key-value pair is skipped, as an easy - * way to omit parameters conditionally. Non-array parameters are converted - * to a string and URI encoded. Array values are expanded into multiple - * &key=value pairs, with each element stringized and URI-encoded. - * - * @typedef {*} - */ -goog.uri.utils.QueryValue; - - -/** - * An array representing a set of query parameters with alternating keys - * and values. - * - * Keys are assumed to be URI encoded already and live at even indices. See - * goog.uri.utils.QueryValue for details on how parameter values are encoded. - * - * Example: - * <pre> - * var data = [ - * // Simple param: ?name=BobBarker - * 'name', 'BobBarker', - * // Conditional param -- may be omitted entirely. - * 'specialDietaryNeeds', hasDietaryNeeds() ? getDietaryNeeds() : null, - * // Multi-valued param: &house=LosAngeles&house=NewYork&house=null - * 'house', ['LosAngeles', 'NewYork', null] - * ]; - * </pre> - * - * @typedef {!Array<string|goog.uri.utils.QueryValue>} - */ -goog.uri.utils.QueryArray; - - -/** - * Parses encoded query parameters and calls callback function for every - * parameter found in the string. - * - * Missing value of parameter (e.g. “…&key&…”) is treated as if the value was an - * empty string. Keys may be empty strings (e.g. “…&=value&…”) which also means - * that “…&=&…” and “…&&…” will result in an empty key and value. - * - * @param {string} encodedQuery Encoded query string excluding question mark at - * the beginning. - * @param {function(string, string)} callback Function called for every - * parameter found in query string. The first argument (name) will not be - * urldecoded (so the function is consistent with buildQueryData), but the - * second will. If the parameter has no value (i.e. “=” was not present) - * the second argument (value) will be an empty string. - */ -goog.uri.utils.parseQueryData = function(encodedQuery, callback) { - if (!encodedQuery) { - return; - } - var pairs = encodedQuery.split('&'); - for (var i = 0; i < pairs.length; i++) { - var indexOfEquals = pairs[i].indexOf('='); - var name = null; - var value = null; - if (indexOfEquals >= 0) { - name = pairs[i].substring(0, indexOfEquals); - value = pairs[i].substring(indexOfEquals + 1); - } else { - name = pairs[i]; - } - callback(name, value ? goog.string.urlDecode(value) : ''); - } -}; - - -/** - * Split the URI into 3 parts where the [1] is the queryData without a leading - * '?'. For example, the URI http://foo.com/bar?a=b#abc returns - * ['http://foo.com/bar','a=b','#abc']. - * @param {string} uri The URI to parse. - * @return {!Array<string>} An array representation of uri of length 3 where the - * middle value is the queryData without a leading '?'. - * @private - */ -goog.uri.utils.splitQueryData_ = function(uri) { - // Find the query data and and hash. - var hashIndex = uri.indexOf('#'); - if (hashIndex < 0) { - hashIndex = uri.length; - } - var questionIndex = uri.indexOf('?'); - var queryData; - if (questionIndex < 0 || questionIndex > hashIndex) { - questionIndex = hashIndex; - queryData = ''; - } else { - queryData = uri.substring(questionIndex + 1, hashIndex); - } - return [uri.substr(0, questionIndex), queryData, uri.substr(hashIndex)]; -}; - - -/** - * Join an array created by splitQueryData_ back into a URI. - * @param {!Array<string>} parts A URI in the form generated by splitQueryData_. - * @return {string} The joined URI. - * @private - */ -goog.uri.utils.joinQueryData_ = function(parts) { - return parts[0] + (parts[1] ? '?' + parts[1] : '') + parts[2]; -}; - - -/** - * @param {string} queryData - * @param {string} newData - * @return {string} - * @private - */ -goog.uri.utils.appendQueryData_ = function(queryData, newData) { - if (!newData) { - return queryData; - } - return queryData ? queryData + '&' + newData : newData; -}; - - -/** - * @param {string} uri - * @param {string} queryData - * @return {string} - * @private - */ -goog.uri.utils.appendQueryDataToUri_ = function(uri, queryData) { - if (!queryData) { - return uri; - } - var parts = goog.uri.utils.splitQueryData_(uri); - parts[1] = goog.uri.utils.appendQueryData_(parts[1], queryData); - return goog.uri.utils.joinQueryData_(parts); -}; - - -/** - * Appends key=value pairs to an array, supporting multi-valued objects. - * @param {*} key The key prefix. - * @param {goog.uri.utils.QueryValue} value The value to serialize. - * @param {!Array<string>} pairs The array to which the 'key=value' strings - * should be appended. - * @private - */ -goog.uri.utils.appendKeyValuePairs_ = function(key, value, pairs) { - goog.asserts.assertString(key); - if (goog.isArray(value)) { - // Convince the compiler it's an array. - goog.asserts.assertArray(value); - for (var j = 0; j < value.length; j++) { - // Convert to string explicitly, to short circuit the null and array - // logic in this function -- this ensures that null and undefined get - // written as literal 'null' and 'undefined', and arrays don't get - // expanded out but instead encoded in the default way. - goog.uri.utils.appendKeyValuePairs_(key, String(value[j]), pairs); - } - } else if (value != null) { - // Skip a top-level null or undefined entirely. - pairs.push( - key + - // Check for empty string. Zero gets encoded into the url as literal - // strings. For empty string, skip the equal sign, to be consistent - // with UriBuilder.java. - (value === '' ? '' : '=' + goog.string.urlEncode(value))); - } -}; - - -/** - * Builds a query data string from a sequence of alternating keys and values. - * Currently generates "&key&" for empty args. - * - * @param {!IArrayLike<string|goog.uri.utils.QueryValue>} keysAndValues - * Alternating keys and values. See the QueryArray typedef. - * @param {number=} opt_startIndex A start offset into the arary, defaults to 0. - * @return {string} The encoded query string, in the form 'a=1&b=2'. - */ -goog.uri.utils.buildQueryData = function(keysAndValues, opt_startIndex) { - goog.asserts.assert( - Math.max(keysAndValues.length - (opt_startIndex || 0), 0) % 2 == 0, - 'goog.uri.utils: Key/value lists must be even in length.'); - - var params = []; - for (var i = opt_startIndex || 0; i < keysAndValues.length; i += 2) { - var key = /** @type {string} */ (keysAndValues[i]); - goog.uri.utils.appendKeyValuePairs_(key, keysAndValues[i + 1], params); - } - return params.join('&'); -}; - - -/** - * Builds a query data string from a map. - * Currently generates "&key&" for empty args. - * - * @param {!Object<string, goog.uri.utils.QueryValue>} map An object where keys - * are URI-encoded parameter keys, and the values are arbitrary types - * or arrays. Keys with a null value are dropped. - * @return {string} The encoded query string, in the form 'a=1&b=2'. - */ -goog.uri.utils.buildQueryDataFromMap = function(map) { - var params = []; - for (var key in map) { - goog.uri.utils.appendKeyValuePairs_(key, map[key], params); - } - return params.join('&'); -}; - - -/** - * Appends URI parameters to an existing URI. - * - * The variable arguments may contain alternating keys and values. Keys are - * assumed to be already URI encoded. The values should not be URI-encoded, - * and will instead be encoded by this function. - * <pre> - * appendParams('http://www.foo.com?existing=true', - * 'key1', 'value1', - * 'key2', 'value?willBeEncoded', - * 'key3', ['valueA', 'valueB', 'valueC'], - * 'key4', null); - * result: 'http://www.foo.com?existing=true&' + - * 'key1=value1&' + - * 'key2=value%3FwillBeEncoded&' + - * 'key3=valueA&key3=valueB&key3=valueC' - * </pre> - * - * A single call to this function will not exhibit quadratic behavior in IE, - * whereas multiple repeated calls may, although the effect is limited by - * fact that URL's generally can't exceed 2kb. - * - * @param {string} uri The original URI, which may already have query data. - * @param {...(goog.uri.utils.QueryArray|goog.uri.utils.QueryValue)} - * var_args - * An array or argument list conforming to goog.uri.utils.QueryArray. - * @return {string} The URI with all query parameters added. - */ -goog.uri.utils.appendParams = function(uri, var_args) { - var queryData = arguments.length == 2 ? - goog.uri.utils.buildQueryData(arguments[1], 0) : - goog.uri.utils.buildQueryData(arguments, 1); - return goog.uri.utils.appendQueryDataToUri_(uri, queryData); -}; - - -/** - * Appends query parameters from a map. - * - * @param {string} uri The original URI, which may already have query data. - * @param {!Object<goog.uri.utils.QueryValue>} map An object where keys are - * URI-encoded parameter keys, and the values are arbitrary types or arrays. - * Keys with a null value are dropped. - * @return {string} The new parameters. - */ -goog.uri.utils.appendParamsFromMap = function(uri, map) { - var queryData = goog.uri.utils.buildQueryDataFromMap(map); - return goog.uri.utils.appendQueryDataToUri_(uri, queryData); -}; - - -/** - * Appends a single URI parameter. - * - * Repeated calls to this can exhibit quadratic behavior in IE6 due to the - * way string append works, though it should be limited given the 2kb limit. - * - * @param {string} uri The original URI, which may already have query data. - * @param {string} key The key, which must already be URI encoded. - * @param {*=} opt_value The value, which will be stringized and encoded - * (assumed not already to be encoded). If omitted, undefined, or null, the - * key will be added as a valueless parameter. - * @return {string} The URI with the query parameter added. - */ -goog.uri.utils.appendParam = function(uri, key, opt_value) { - var value = goog.isDefAndNotNull(opt_value) ? - '=' + goog.string.urlEncode(opt_value) : - ''; - return goog.uri.utils.appendQueryDataToUri_(uri, key + value); -}; - - -/** - * Finds the next instance of a query parameter with the specified name. - * - * Does not instantiate any objects. - * - * @param {string} uri The URI to search. May contain a fragment identifier - * if opt_hashIndex is specified. - * @param {number} startIndex The index to begin searching for the key at. A - * match may be found even if this is one character after the ampersand. - * @param {string} keyEncoded The URI-encoded key. - * @param {number} hashOrEndIndex Index to stop looking at. If a hash - * mark is present, it should be its index, otherwise it should be the - * length of the string. - * @return {number} The position of the first character in the key's name, - * immediately after either a question mark or a dot. - * @private - */ -goog.uri.utils.findParam_ = function( - uri, startIndex, keyEncoded, hashOrEndIndex) { - var index = startIndex; - var keyLength = keyEncoded.length; - - // Search for the key itself and post-filter for surronuding punctuation, - // rather than expensively building a regexp. - while ((index = uri.indexOf(keyEncoded, index)) >= 0 && - index < hashOrEndIndex) { - var precedingChar = uri.charCodeAt(index - 1); - // Ensure that the preceding character is '&' or '?'. - if (precedingChar == goog.uri.utils.CharCode_.AMPERSAND || - precedingChar == goog.uri.utils.CharCode_.QUESTION) { - // Ensure the following character is '&', '=', '#', or NaN - // (end of string). - var followingChar = uri.charCodeAt(index + keyLength); - if (!followingChar || followingChar == goog.uri.utils.CharCode_.EQUAL || - followingChar == goog.uri.utils.CharCode_.AMPERSAND || - followingChar == goog.uri.utils.CharCode_.HASH) { - return index; - } - } - index += keyLength + 1; - } - - return -1; -}; - - -/** - * Regular expression for finding a hash mark or end of string. - * @type {RegExp} - * @private - */ -goog.uri.utils.hashOrEndRe_ = /#|$/; - - -/** - * Determines if the URI contains a specific key. - * - * Performs no object instantiations. - * - * @param {string} uri The URI to process. May contain a fragment - * identifier. - * @param {string} keyEncoded The URI-encoded key. Case-sensitive. - * @return {boolean} Whether the key is present. - */ -goog.uri.utils.hasParam = function(uri, keyEncoded) { - return goog.uri.utils.findParam_( - uri, 0, keyEncoded, uri.search(goog.uri.utils.hashOrEndRe_)) >= 0; -}; - - -/** - * Gets the first value of a query parameter. - * @param {string} uri The URI to process. May contain a fragment. - * @param {string} keyEncoded The URI-encoded key. Case-sensitive. - * @return {?string} The first value of the parameter (URI-decoded), or null - * if the parameter is not found. - */ -goog.uri.utils.getParamValue = function(uri, keyEncoded) { - var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_); - var foundIndex = - goog.uri.utils.findParam_(uri, 0, keyEncoded, hashOrEndIndex); - - if (foundIndex < 0) { - return null; - } else { - var endPosition = uri.indexOf('&', foundIndex); - if (endPosition < 0 || endPosition > hashOrEndIndex) { - endPosition = hashOrEndIndex; - } - // Progress forth to the end of the "key=" or "key&" substring. - foundIndex += keyEncoded.length + 1; - // Use substr, because it (unlike substring) will return empty string - // if foundIndex > endPosition. - return goog.string.urlDecode( - uri.substr(foundIndex, endPosition - foundIndex)); - } -}; - - -/** - * Gets all values of a query parameter. - * @param {string} uri The URI to process. May contain a fragment. - * @param {string} keyEncoded The URI-encoded key. Case-sensitive. - * @return {!Array<string>} All URI-decoded values with the given key. - * If the key is not found, this will have length 0, but never be null. - */ -goog.uri.utils.getParamValues = function(uri, keyEncoded) { - var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_); - var position = 0; - var foundIndex; - var result = []; - - while ((foundIndex = goog.uri.utils.findParam_( - uri, position, keyEncoded, hashOrEndIndex)) >= 0) { - // Find where this parameter ends, either the '&' or the end of the - // query parameters. - position = uri.indexOf('&', foundIndex); - if (position < 0 || position > hashOrEndIndex) { - position = hashOrEndIndex; - } - - // Progress forth to the end of the "key=" or "key&" substring. - foundIndex += keyEncoded.length + 1; - // Use substr, because it (unlike substring) will return empty string - // if foundIndex > position. - result.push( - goog.string.urlDecode(uri.substr(foundIndex, position - foundIndex))); - } - - return result; -}; - - -/** - * Regexp to find trailing question marks and ampersands. - * @type {RegExp} - * @private - */ -goog.uri.utils.trailingQueryPunctuationRe_ = /[?&]($|#)/; - - -/** - * Removes all instances of a query parameter. - * @param {string} uri The URI to process. Must not contain a fragment. - * @param {string} keyEncoded The URI-encoded key. - * @return {string} The URI with all instances of the parameter removed. - */ -goog.uri.utils.removeParam = function(uri, keyEncoded) { - var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_); - var position = 0; - var foundIndex; - var buffer = []; - - // Look for a query parameter. - while ((foundIndex = goog.uri.utils.findParam_( - uri, position, keyEncoded, hashOrEndIndex)) >= 0) { - // Get the portion of the query string up to, but not including, the ? - // or & starting the parameter. - buffer.push(uri.substring(position, foundIndex)); - // Progress to immediately after the '&'. If not found, go to the end. - // Avoid including the hash mark. - position = Math.min( - (uri.indexOf('&', foundIndex) + 1) || hashOrEndIndex, hashOrEndIndex); - } - - // Append everything that is remaining. - buffer.push(uri.substr(position)); - - // Join the buffer, and remove trailing punctuation that remains. - return buffer.join('').replace( - goog.uri.utils.trailingQueryPunctuationRe_, '$1'); -}; - - -/** - * Replaces all existing definitions of a parameter with a single definition. - * - * Repeated calls to this can exhibit quadratic behavior due to the need to - * find existing instances and reconstruct the string, though it should be - * limited given the 2kb limit. Consider using appendParams or setParamsFromMap - * to update multiple parameters in bulk. - * - * @param {string} uri The original URI, which may already have query data. - * @param {string} keyEncoded The key, which must already be URI encoded. - * @param {*} value The value, which will be stringized and encoded (assumed - * not already to be encoded). - * @return {string} The URI with the query parameter added. - */ -goog.uri.utils.setParam = function(uri, keyEncoded, value) { - return goog.uri.utils.appendParam( - goog.uri.utils.removeParam(uri, keyEncoded), keyEncoded, value); -}; - - -/** - * Effeciently set or remove multiple query parameters in a URI. Order of - * unchanged parameters will not be modified, all updated parameters will be - * appended to the end of the query. Params with values of null or undefined are - * removed. - * - * @param {string} uri The URI to process. - * @param {!Object<string, goog.uri.utils.QueryValue>} params A list of - * parameters to update. If null or undefined, the param will be removed. - * @return {string} An updated URI where the query data has been updated with - * the params. - */ -goog.uri.utils.setParamsFromMap = function(uri, params) { - var parts = goog.uri.utils.splitQueryData_(uri); - var queryData = parts[1]; - var buffer = []; - if (queryData) { - goog.array.forEach(queryData.split('&'), function(pair) { - var indexOfEquals = pair.indexOf('='); - var name = indexOfEquals >= 0 ? pair.substr(0, indexOfEquals) : pair; - if (!params.hasOwnProperty(name)) { - buffer.push(pair); - } - }); - } - parts[1] = goog.uri.utils.appendQueryData_( - buffer.join('&'), goog.uri.utils.buildQueryDataFromMap(params)); - return goog.uri.utils.joinQueryData_(parts); -}; - - -/** - * Generates a URI path using a given URI and a path with checks to - * prevent consecutive "//". The baseUri passed in must not contain - * query or fragment identifiers. The path to append may not contain query or - * fragment identifiers. - * - * @param {string} baseUri URI to use as the base. - * @param {string} path Path to append. - * @return {string} Updated URI. - */ -goog.uri.utils.appendPath = function(baseUri, path) { - goog.uri.utils.assertNoFragmentsOrQueries_(baseUri); - - // Remove any trailing '/' - if (goog.string.endsWith(baseUri, '/')) { - baseUri = baseUri.substr(0, baseUri.length - 1); - } - // Remove any leading '/' - if (goog.string.startsWith(path, '/')) { - path = path.substr(1); - } - return goog.string.buildString(baseUri, '/', path); -}; - - -/** - * Replaces the path. - * @param {string} uri URI to use as the base. - * @param {string} path New path. - * @return {string} Updated URI. - */ -goog.uri.utils.setPath = function(uri, path) { - // Add any missing '/'. - if (!goog.string.startsWith(path, '/')) { - path = '/' + path; - } - var parts = goog.uri.utils.split(uri); - return goog.uri.utils.buildFromEncodedParts( - parts[goog.uri.utils.ComponentIndex.SCHEME], - parts[goog.uri.utils.ComponentIndex.USER_INFO], - parts[goog.uri.utils.ComponentIndex.DOMAIN], - parts[goog.uri.utils.ComponentIndex.PORT], path, - parts[goog.uri.utils.ComponentIndex.QUERY_DATA], - parts[goog.uri.utils.ComponentIndex.FRAGMENT]); -}; - - -/** - * Standard supported query parameters. - * @enum {string} - */ -goog.uri.utils.StandardQueryParam = { - - /** Unused parameter for unique-ifying. */ - RANDOM: 'zx' -}; - - -/** - * Sets the zx parameter of a URI to a random value. - * @param {string} uri Any URI. - * @return {string} That URI with the "zx" parameter added or replaced to - * contain a random string. - */ -goog.uri.utils.makeUnique = function(uri) { - return goog.uri.utils.setParam( - uri, goog.uri.utils.StandardQueryParam.RANDOM, - goog.string.getRandomString()); -};
diff --git a/third_party/ink/closure/useragent/product.js b/third_party/ink/closure/useragent/product.js deleted file mode 100644 index cc85e63..0000000 --- a/third_party/ink/closure/useragent/product.js +++ /dev/null
@@ -1,182 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Detects the specific browser and not just the rendering engine. - * - * @author andybons@google.com (Andrew Bonventre) - */ - -goog.provide('goog.userAgent.product'); - -goog.require('goog.labs.userAgent.browser'); -goog.require('goog.labs.userAgent.platform'); -goog.require('goog.userAgent'); - - -/** - * @define {boolean} Whether the code is running on the Firefox web browser. - */ -goog.define('goog.userAgent.product.ASSUME_FIREFOX', false); - - -/** - * @define {boolean} Whether we know at compile-time that the product is an - * iPhone. - */ -goog.define('goog.userAgent.product.ASSUME_IPHONE', false); - - -/** - * @define {boolean} Whether we know at compile-time that the product is an - * iPad. - */ -goog.define('goog.userAgent.product.ASSUME_IPAD', false); - - -/** - * @define {boolean} Whether we know at compile-time that the product is an - * AOSP browser or WebView inside a pre KitKat Android phone or tablet. - */ -goog.define('goog.userAgent.product.ASSUME_ANDROID', false); - - -/** - * @define {boolean} Whether the code is running on the Chrome web browser on - * any platform or AOSP browser or WebView in a KitKat+ Android phone or tablet. - */ -goog.define('goog.userAgent.product.ASSUME_CHROME', false); - - -/** - * @define {boolean} Whether the code is running on the Safari web browser. - */ -goog.define('goog.userAgent.product.ASSUME_SAFARI', false); - - -/** - * Whether we know the product type at compile-time. - * @type {boolean} - * @private - */ -goog.userAgent.product.PRODUCT_KNOWN_ = goog.userAgent.ASSUME_IE || - goog.userAgent.ASSUME_EDGE || goog.userAgent.ASSUME_OPERA || - goog.userAgent.product.ASSUME_FIREFOX || - goog.userAgent.product.ASSUME_IPHONE || - goog.userAgent.product.ASSUME_IPAD || - goog.userAgent.product.ASSUME_ANDROID || - goog.userAgent.product.ASSUME_CHROME || - goog.userAgent.product.ASSUME_SAFARI; - - -/** - * Whether the code is running on the Opera web browser. - * @type {boolean} - */ -goog.userAgent.product.OPERA = goog.userAgent.OPERA; - - -/** - * Whether the code is running on an IE web browser. - * @type {boolean} - */ -goog.userAgent.product.IE = goog.userAgent.IE; - - -/** - * Whether the code is running on an Edge web browser. - * @type {boolean} - */ -goog.userAgent.product.EDGE = goog.userAgent.EDGE; - - -/** - * Whether the code is running on the Firefox web browser. - * @type {boolean} - */ -goog.userAgent.product.FIREFOX = goog.userAgent.product.PRODUCT_KNOWN_ ? - goog.userAgent.product.ASSUME_FIREFOX : - goog.labs.userAgent.browser.isFirefox(); - - -/** - * Whether the user agent is an iPhone or iPod (as in iPod touch). - * @return {boolean} - * @private - */ -goog.userAgent.product.isIphoneOrIpod_ = function() { - return goog.labs.userAgent.platform.isIphone() || - goog.labs.userAgent.platform.isIpod(); -}; - - -/** - * Whether the code is running on an iPhone or iPod touch. - * - * iPod touch is considered an iPhone for legacy reasons. - * @type {boolean} - */ -goog.userAgent.product.IPHONE = goog.userAgent.product.PRODUCT_KNOWN_ ? - goog.userAgent.product.ASSUME_IPHONE : - goog.userAgent.product.isIphoneOrIpod_(); - - -/** - * Whether the code is running on an iPad. - * @type {boolean} - */ -goog.userAgent.product.IPAD = goog.userAgent.product.PRODUCT_KNOWN_ ? - goog.userAgent.product.ASSUME_IPAD : - goog.labs.userAgent.platform.isIpad(); - - -/** - * Whether the code is running on AOSP browser or WebView inside - * a pre KitKat Android phone or tablet. - * @type {boolean} - */ -goog.userAgent.product.ANDROID = goog.userAgent.product.PRODUCT_KNOWN_ ? - goog.userAgent.product.ASSUME_ANDROID : - goog.labs.userAgent.browser.isAndroidBrowser(); - - -/** - * Whether the code is running on the Chrome web browser on any platform - * or AOSP browser or WebView in a KitKat+ Android phone or tablet. - * @type {boolean} - */ -goog.userAgent.product.CHROME = goog.userAgent.product.PRODUCT_KNOWN_ ? - goog.userAgent.product.ASSUME_CHROME : - goog.labs.userAgent.browser.isChrome(); - - -/** - * @return {boolean} Whether the browser is Safari on desktop. - * @private - */ -goog.userAgent.product.isSafariDesktop_ = function() { - return goog.labs.userAgent.browser.isSafari() && - !goog.labs.userAgent.platform.isIos(); -}; - - -/** - * Whether the code is running on the desktop Safari web browser. - * Note: the legacy behavior here is only true for Safari not running - * on iOS. - * @type {boolean} - */ -goog.userAgent.product.SAFARI = goog.userAgent.product.PRODUCT_KNOWN_ ? - goog.userAgent.product.ASSUME_SAFARI : - goog.userAgent.product.isSafariDesktop_();
diff --git a/third_party/ink/closure/useragent/useragent.js b/third_party/ink/closure/useragent/useragent.js deleted file mode 100644 index 007d571..0000000 --- a/third_party/ink/closure/useragent/useragent.js +++ /dev/null
@@ -1,581 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Rendering engine detection. - * @see <a href="http://www.useragentstring.com/">User agent strings</a> - * For information on the browser brand (such as Safari versus Chrome), see - * goog.userAgent.product. - * @author pupius@google.com (Daniel Pupius) - * @author arv@google.com (Erik Arvidsson) - * @see ../demos/useragent.html - */ - -goog.provide('goog.userAgent'); - -goog.require('goog.labs.userAgent.browser'); -goog.require('goog.labs.userAgent.engine'); -goog.require('goog.labs.userAgent.platform'); -goog.require('goog.labs.userAgent.util'); -goog.require('goog.reflect'); -goog.require('goog.string'); - - -/** - * @define {boolean} Whether we know at compile-time that the browser is IE. - */ -goog.define('goog.userAgent.ASSUME_IE', false); - - -/** - * @define {boolean} Whether we know at compile-time that the browser is EDGE. - */ -goog.define('goog.userAgent.ASSUME_EDGE', false); - - -/** - * @define {boolean} Whether we know at compile-time that the browser is GECKO. - */ -goog.define('goog.userAgent.ASSUME_GECKO', false); - - -/** - * @define {boolean} Whether we know at compile-time that the browser is WEBKIT. - */ -goog.define('goog.userAgent.ASSUME_WEBKIT', false); - - -/** - * @define {boolean} Whether we know at compile-time that the browser is a - * mobile device running WebKit e.g. iPhone or Android. - */ -goog.define('goog.userAgent.ASSUME_MOBILE_WEBKIT', false); - - -/** - * @define {boolean} Whether we know at compile-time that the browser is OPERA. - */ -goog.define('goog.userAgent.ASSUME_OPERA', false); - - -/** - * @define {boolean} Whether the - * {@code goog.userAgent.isVersionOrHigher} - * function will return true for any version. - */ -goog.define('goog.userAgent.ASSUME_ANY_VERSION', false); - - -/** - * Whether we know the browser engine at compile-time. - * @type {boolean} - * @private - */ -goog.userAgent.BROWSER_KNOWN_ = goog.userAgent.ASSUME_IE || - goog.userAgent.ASSUME_EDGE || goog.userAgent.ASSUME_GECKO || - goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.ASSUME_WEBKIT || - goog.userAgent.ASSUME_OPERA; - - -/** - * Returns the userAgent string for the current browser. - * - * @return {string} The userAgent string. - */ -goog.userAgent.getUserAgentString = function() { - return goog.labs.userAgent.util.getUserAgent(); -}; - - -/** - * TODO(nnaze): Change type to "Navigator" and update compilation targets. - * @return {?Object} The native navigator object. - */ -goog.userAgent.getNavigator = function() { - // Need a local navigator reference instead of using the global one, - // to avoid the rare case where they reference different objects. - // (in a WorkerPool, for example). - return goog.global['navigator'] || null; -}; - - -/** - * Whether the user agent is Opera. - * @type {boolean} - */ -goog.userAgent.OPERA = goog.userAgent.BROWSER_KNOWN_ ? - goog.userAgent.ASSUME_OPERA : - goog.labs.userAgent.browser.isOpera(); - - -/** - * Whether the user agent is Internet Explorer. - * @type {boolean} - */ -goog.userAgent.IE = goog.userAgent.BROWSER_KNOWN_ ? - goog.userAgent.ASSUME_IE : - goog.labs.userAgent.browser.isIE(); - - -/** - * Whether the user agent is Microsoft Edge. - * @type {boolean} - */ -goog.userAgent.EDGE = goog.userAgent.BROWSER_KNOWN_ ? - goog.userAgent.ASSUME_EDGE : - goog.labs.userAgent.engine.isEdge(); - - -/** - * Whether the user agent is MS Internet Explorer or MS Edge. - * @type {boolean} - */ -goog.userAgent.EDGE_OR_IE = goog.userAgent.EDGE || goog.userAgent.IE; - - -/** - * Whether the user agent is Gecko. Gecko is the rendering engine used by - * Mozilla, Firefox, and others. - * @type {boolean} - */ -goog.userAgent.GECKO = goog.userAgent.BROWSER_KNOWN_ ? - goog.userAgent.ASSUME_GECKO : - goog.labs.userAgent.engine.isGecko(); - - -/** - * Whether the user agent is WebKit. WebKit is the rendering engine that - * Safari, Android and others use. - * @type {boolean} - */ -goog.userAgent.WEBKIT = goog.userAgent.BROWSER_KNOWN_ ? - goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_MOBILE_WEBKIT : - goog.labs.userAgent.engine.isWebKit(); - - -/** - * Whether the user agent is running on a mobile device. - * - * This is a separate function so that the logic can be tested. - * - * TODO(nnaze): Investigate swapping in goog.labs.userAgent.device.isMobile(). - * - * @return {boolean} Whether the user agent is running on a mobile device. - * @private - */ -goog.userAgent.isMobile_ = function() { - return goog.userAgent.WEBKIT && - goog.labs.userAgent.util.matchUserAgent('Mobile'); -}; - - -/** - * Whether the user agent is running on a mobile device. - * - * TODO(nnaze): Consider deprecating MOBILE when labs.userAgent - * is promoted as the gecko/webkit logic is likely inaccurate. - * - * @type {boolean} - */ -goog.userAgent.MOBILE = - goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.isMobile_(); - - -/** - * Used while transitioning code to use WEBKIT instead. - * @type {boolean} - * @deprecated Use {@link goog.userAgent.product.SAFARI} instead. - * TODO(nicksantos): Delete this from goog.userAgent. - */ -goog.userAgent.SAFARI = goog.userAgent.WEBKIT; - - -/** - * @return {string} the platform (operating system) the user agent is running - * on. Default to empty string because navigator.platform may not be defined - * (on Rhino, for example). - * @private - */ -goog.userAgent.determinePlatform_ = function() { - var navigator = goog.userAgent.getNavigator(); - return navigator && navigator.platform || ''; -}; - - -/** - * The platform (operating system) the user agent is running on. Default to - * empty string because navigator.platform may not be defined (on Rhino, for - * example). - * @type {string} - */ -goog.userAgent.PLATFORM = goog.userAgent.determinePlatform_(); - - -/** - * @define {boolean} Whether the user agent is running on a Macintosh operating - * system. - */ -goog.define('goog.userAgent.ASSUME_MAC', false); - - -/** - * @define {boolean} Whether the user agent is running on a Windows operating - * system. - */ -goog.define('goog.userAgent.ASSUME_WINDOWS', false); - - -/** - * @define {boolean} Whether the user agent is running on a Linux operating - * system. - */ -goog.define('goog.userAgent.ASSUME_LINUX', false); - - -/** - * @define {boolean} Whether the user agent is running on a X11 windowing - * system. - */ -goog.define('goog.userAgent.ASSUME_X11', false); - - -/** - * @define {boolean} Whether the user agent is running on Android. - */ -goog.define('goog.userAgent.ASSUME_ANDROID', false); - - -/** - * @define {boolean} Whether the user agent is running on an iPhone. - */ -goog.define('goog.userAgent.ASSUME_IPHONE', false); - - -/** - * @define {boolean} Whether the user agent is running on an iPad. - */ -goog.define('goog.userAgent.ASSUME_IPAD', false); - - -/** - * @define {boolean} Whether the user agent is running on an iPod. - */ -goog.define('goog.userAgent.ASSUME_IPOD', false); - - -/** - * @type {boolean} - * @private - */ -goog.userAgent.PLATFORM_KNOWN_ = goog.userAgent.ASSUME_MAC || - goog.userAgent.ASSUME_WINDOWS || goog.userAgent.ASSUME_LINUX || - goog.userAgent.ASSUME_X11 || goog.userAgent.ASSUME_ANDROID || - goog.userAgent.ASSUME_IPHONE || goog.userAgent.ASSUME_IPAD || - goog.userAgent.ASSUME_IPOD; - - -/** - * Whether the user agent is running on a Macintosh operating system. - * @type {boolean} - */ -goog.userAgent.MAC = goog.userAgent.PLATFORM_KNOWN_ ? - goog.userAgent.ASSUME_MAC : - goog.labs.userAgent.platform.isMacintosh(); - - -/** - * Whether the user agent is running on a Windows operating system. - * @type {boolean} - */ -goog.userAgent.WINDOWS = goog.userAgent.PLATFORM_KNOWN_ ? - goog.userAgent.ASSUME_WINDOWS : - goog.labs.userAgent.platform.isWindows(); - - -/** - * Whether the user agent is Linux per the legacy behavior of - * goog.userAgent.LINUX, which considered ChromeOS to also be - * Linux. - * @return {boolean} - * @private - */ -goog.userAgent.isLegacyLinux_ = function() { - return goog.labs.userAgent.platform.isLinux() || - goog.labs.userAgent.platform.isChromeOS(); -}; - - -/** - * Whether the user agent is running on a Linux operating system. - * - * Note that goog.userAgent.LINUX considers ChromeOS to be Linux, - * while goog.labs.userAgent.platform considers ChromeOS and - * Linux to be different OSes. - * - * @type {boolean} - */ -goog.userAgent.LINUX = goog.userAgent.PLATFORM_KNOWN_ ? - goog.userAgent.ASSUME_LINUX : - goog.userAgent.isLegacyLinux_(); - - -/** - * @return {boolean} Whether the user agent is an X11 windowing system. - * @private - */ -goog.userAgent.isX11_ = function() { - var navigator = goog.userAgent.getNavigator(); - return !!navigator && - goog.string.contains(navigator['appVersion'] || '', 'X11'); -}; - - -/** - * Whether the user agent is running on a X11 windowing system. - * @type {boolean} - */ -goog.userAgent.X11 = goog.userAgent.PLATFORM_KNOWN_ ? - goog.userAgent.ASSUME_X11 : - goog.userAgent.isX11_(); - - -/** - * Whether the user agent is running on Android. - * @type {boolean} - */ -goog.userAgent.ANDROID = goog.userAgent.PLATFORM_KNOWN_ ? - goog.userAgent.ASSUME_ANDROID : - goog.labs.userAgent.platform.isAndroid(); - - -/** - * Whether the user agent is running on an iPhone. - * @type {boolean} - */ -goog.userAgent.IPHONE = goog.userAgent.PLATFORM_KNOWN_ ? - goog.userAgent.ASSUME_IPHONE : - goog.labs.userAgent.platform.isIphone(); - - -/** - * Whether the user agent is running on an iPad. - * @type {boolean} - */ -goog.userAgent.IPAD = goog.userAgent.PLATFORM_KNOWN_ ? - goog.userAgent.ASSUME_IPAD : - goog.labs.userAgent.platform.isIpad(); - - -/** - * Whether the user agent is running on an iPod. - * @type {boolean} - */ -goog.userAgent.IPOD = goog.userAgent.PLATFORM_KNOWN_ ? - goog.userAgent.ASSUME_IPOD : - goog.labs.userAgent.platform.isIpod(); - - -/** - * Whether the user agent is running on iOS. - * @type {boolean} - */ -goog.userAgent.IOS = goog.userAgent.PLATFORM_KNOWN_ ? - (goog.userAgent.ASSUME_IPHONE || goog.userAgent.ASSUME_IPAD || - goog.userAgent.ASSUME_IPOD) : - goog.labs.userAgent.platform.isIos(); - -/** - * @return {string} The string that describes the version number of the user - * agent. - * @private - */ -goog.userAgent.determineVersion_ = function() { - // All browsers have different ways to detect the version and they all have - // different naming schemes. - // version is a string rather than a number because it may contain 'b', 'a', - // and so on. - var version = ''; - var arr = goog.userAgent.getVersionRegexResult_(); - if (arr) { - version = arr ? arr[1] : ''; - } - - if (goog.userAgent.IE) { - // IE9 can be in document mode 9 but be reporting an inconsistent user agent - // version. If it is identifying as a version lower than 9 we take the - // documentMode as the version instead. IE8 has similar behavior. - // It is recommended to set the X-UA-Compatible header to ensure that IE9 - // uses documentMode 9. - var docMode = goog.userAgent.getDocumentMode_(); - if (docMode != null && docMode > parseFloat(version)) { - return String(docMode); - } - } - - return version; -}; - - -/** - * @return {?Array|undefined} The version regex matches from parsing the user - * agent string. These regex statements must be executed inline so they can - * be compiled out by the closure compiler with the rest of the useragent - * detection logic when ASSUME_* is specified. - * @private - */ -goog.userAgent.getVersionRegexResult_ = function() { - var userAgent = goog.userAgent.getUserAgentString(); - if (goog.userAgent.GECKO) { - return /rv\:([^\);]+)(\)|;)/.exec(userAgent); - } - if (goog.userAgent.EDGE) { - return /Edge\/([\d\.]+)/.exec(userAgent); - } - if (goog.userAgent.IE) { - return /\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(userAgent); - } - if (goog.userAgent.WEBKIT) { - // WebKit/125.4 - return /WebKit\/(\S+)/.exec(userAgent); - } - if (goog.userAgent.OPERA) { - // If none of the above browsers were detected but the browser is Opera, the - // only string that is of interest is 'Version/<number>'. - return /(?:Version)[ \/]?(\S+)/.exec(userAgent); - } - return undefined; -}; - - -/** - * @return {number|undefined} Returns the document mode (for testing). - * @private - */ -goog.userAgent.getDocumentMode_ = function() { - // NOTE(pupius): goog.userAgent may be used in context where there is no DOM. - var doc = goog.global['document']; - return doc ? doc['documentMode'] : undefined; -}; - - -/** - * The version of the user agent. This is a string because it might contain - * 'b' (as in beta) as well as multiple dots. - * @type {string} - */ -goog.userAgent.VERSION = goog.userAgent.determineVersion_(); - - -/** - * Compares two version numbers. - * - * @param {string} v1 Version of first item. - * @param {string} v2 Version of second item. - * - * @return {number} 1 if first argument is higher - * 0 if arguments are equal - * -1 if second argument is higher. - * @deprecated Use goog.string.compareVersions. - */ -goog.userAgent.compare = function(v1, v2) { - return goog.string.compareVersions(v1, v2); -}; - - -/** - * Cache for {@link goog.userAgent.isVersionOrHigher}. - * Calls to compareVersions are surprisingly expensive and, as a browser's - * version number is unlikely to change during a session, we cache the results. - * @const - * @private - */ -goog.userAgent.isVersionOrHigherCache_ = {}; - - -/** - * Whether the user agent version is higher or the same as the given version. - * NOTE: When checking the version numbers for Firefox and Safari, be sure to - * use the engine's version, not the browser's version number. For example, - * Firefox 3.0 corresponds to Gecko 1.9 and Safari 3.0 to Webkit 522.11. - * Opera and Internet Explorer versions match the product release number.<br> - * @see <a href="http://en.wikipedia.org/wiki/Safari_version_history"> - * Webkit</a> - * @see <a href="http://en.wikipedia.org/wiki/Gecko_engine">Gecko</a> - * - * @param {string|number} version The version to check. - * @return {boolean} Whether the user agent version is higher or the same as - * the given version. - */ -goog.userAgent.isVersionOrHigher = function(version) { - return goog.userAgent.ASSUME_ANY_VERSION || - goog.reflect.cache( - goog.userAgent.isVersionOrHigherCache_, version, function() { - return goog.string.compareVersions( - goog.userAgent.VERSION, version) >= 0; - }); -}; - - -/** - * Deprecated alias to {@code goog.userAgent.isVersionOrHigher}. - * @param {string|number} version The version to check. - * @return {boolean} Whether the user agent version is higher or the same as - * the given version. - * @deprecated Use goog.userAgent.isVersionOrHigher(). - */ -goog.userAgent.isVersion = goog.userAgent.isVersionOrHigher; - - -/** - * Whether the IE effective document mode is higher or the same as the given - * document mode version. - * NOTE: Only for IE, return false for another browser. - * - * @param {number} documentMode The document mode version to check. - * @return {boolean} Whether the IE effective document mode is higher or the - * same as the given version. - */ -goog.userAgent.isDocumentModeOrHigher = function(documentMode) { - return Number(goog.userAgent.DOCUMENT_MODE) >= documentMode; -}; - - -/** - * Deprecated alias to {@code goog.userAgent.isDocumentModeOrHigher}. - * @param {number} version The version to check. - * @return {boolean} Whether the IE effective document mode is higher or the - * same as the given version. - * @deprecated Use goog.userAgent.isDocumentModeOrHigher(). - */ -goog.userAgent.isDocumentMode = goog.userAgent.isDocumentModeOrHigher; - - -/** - * For IE version < 7, documentMode is undefined, so attempt to use the - * CSS1Compat property to see if we are in standards mode. If we are in - * standards mode, treat the browser version as the document mode. Otherwise, - * IE is emulating version 5. - * @type {number|undefined} - * @const - */ -goog.userAgent.DOCUMENT_MODE = (function() { - var doc = goog.global['document']; - var mode = goog.userAgent.getDocumentMode_(); - if (!doc || !goog.userAgent.IE) { - return undefined; - } - return mode || (doc['compatMode'] == 'CSS1Compat' ? - parseInt(goog.userAgent.VERSION, 10) : - 5); -})();
diff --git a/third_party/ink/ink/web/js/canvas_manager/canvas_manager.js b/third_party/ink/ink/web/js/canvas_manager/canvas_manager.js deleted file mode 100644 index c4db2c8..0000000 --- a/third_party/ink/ink/web/js/canvas_manager/canvas_manager.js +++ /dev/null
@@ -1,598 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -goog.provide('ink.CanvasManager'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.html.SafeUrl'); -goog.require('goog.structs.Set'); -goog.require('goog.ui.Component'); -goog.require('ink.BrushModel'); -goog.require('ink.Color'); -goog.require('ink.ElementListener'); -goog.require('ink.SketchologyEngineWrapper'); -goog.require('ink.embed.events'); -goog.require('ink.util'); -goog.require('sketchology.proto.BackgroundImageInfo'); -goog.require('sketchology.proto.Border'); -goog.require('sketchology.proto.ImageExport'); -goog.require('sketchology.proto.Rect'); -goog.require('sketchology.proto.SetCallbackFlags'); - - - -/** - * The controller of the canvas used for drawing. - * - * @param {?string} engineUrl - * @param {ink.util.SEngineType} sengineType - * @struct - * @constructor - * @extends {goog.ui.Component} - * @implements {ink.ElementListener} - */ -ink.CanvasManager = function(engineUrl, sengineType) { - ink.CanvasManager.base(this, 'constructor'); - - /** @private {ink.BrushModel} */ - this.brushModel_ = null; - - /** @private {!ink.SketchologyEngineWrapper} */ - this.engine_ = new ink.SketchologyEngineWrapper( - engineUrl, this, goog.bind(this.onPngExportComplete_, this), sengineType); - this.addChild(this.engine_); - this.getHandler().listenOnce( - this.engine_, ink.SketchologyEngineWrapper.EventType.CANVAS_INITIALIZED, - goog.bind(function() { - this.brushUpdate_(); - this.setBorderImage_(); - this.dispatchEvent(ink.embed.events.EventType.CANVAS_INITIALIZED); - }, this)); - - // Redispatch CANVAS_FATAL_ERROR events as the top level FATAL_ERROR. - this.getHandler().listen( - this.engine_, ink.SketchologyEngineWrapper.EventType.CANVAS_FATAL_ERROR, - this.dispatchFatalError_); - - this.getHandler().listen( - this.engine_, ink.SketchologyEngineWrapper.EventType.PEN_MODE_ENABLED, - (ev) => { - this.dispatchEvent(new ink.embed.events.PenModeEnabled(ev.enabled)); - }); - - /** - * Known element UUIDs from bottom to top - * @private {Array.<string>} - */ - this.UUIDs_ = []; - - /** - * Set of UUIDs created by the engine but not yet acknowledged by Brix. - * @private {goog.structs.Set}} - */ - this.pendingUUIDs_ = new goog.structs.Set(); - - /** - * Next local ID to use for Brix element bundles missing IDs. - * @private {number} - */ - this.nextLocalId_ = 0; - - /** - * @const - * @type {string} - */ - this.FAKE_UUID = 'fake'; - - /** - * Background counter - * @type {number} - * @private - */ - this.bgCount_ = 0; - - /** @private {?function(!goog.html.SafeUrl)} */ - this.onPngExportCompleteCallback_ = null; - - /** @private {boolean} */ - this.exportAsBlob_ = false; -}; -goog.inherits(ink.CanvasManager, goog.ui.Component); - - -/** @const */ -ink.CanvasManager.BORDER_IMAGE = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEU' + - 'gAAAFgAAABYCAYAAABxlTA0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAm' + - 'pwYAAAAB3RJTUUH4AgPEBYrHoEFUgAAAw1JREFUeNrt3b9uE0EQBvBvZvd8LURUkVwEkEDAm' + - '9AgQYOQKHgZWloqUMoUaVJSpAivQBEhJGhSWiAlKXz7JwXey9nE9vrOgHT3fZKVFM5F/mUyN' + - '5tIY8F2EtG/yNYucnZ21keg/57d3V1RMvzdEJjABGYITGACM+1iNz5RxGGPzCIbnT+i3RA1A' + - 'jgFcADgR4zRDwTVABjHGF8AeJwOaDnYNgd29jGGED6JyMvxeDwZYvVOJpN3FxcXH0TkWfMov' + - 'Qpac6p39jgdMi4A7Ozs/HLOvQkhfEkurW9yDVh47+GcOxgybsre3t5P59y+937OqHUFhxAQQ' + - 'kBVVd85E/yOc+5bcuk0pqWLeO/hvQ+krV289x45yLqqPSRk5xym0yllZ5lOp6iqCiGEtW3C5' + - 'lZwzq/DUOK9h4jUwK3GtGYFz1oEZa97cA2crJaNapozoiVk5rqCm+2h898ihn487uKiWPMPy' + - '2arYG7G7TQHM91CYAITmCEwgQnMEJjABGYITGCGwAQmMENgAhOYITCBCUwCAhOYITCBCcwQm' + - 'MAEZghMYIbABCYwQ2ACE5ghMIEJzBCYwAyBCUxghsAEJjBDYAIzBP63wFkLcUX4lhAp3nu79' + - 'Qr23t8lbZ37WwNuLFx7fnJycnvossfHx7dijK+WGLWrYBFBjPHh5eXl/tHR0Z0h41ZV9T7G+' + - 'EREum/AThcREaiqqOpTAJ8PDw8/VlX11TnnhgArIrYsy3vn5+evy7J8NLNADrJd1xpUFcaY9' + - 'BBVfSAib2foAPq7GTAZGGNSkcFaC2stjDH161+BLGsrOAEXRYGyLOsNgKqK5hbovgIng/T6R' + - '6MRiqKogVtVcPqi5k+tKIo5XOfcYICNMbDWYjQaoSzLP4BXtYqVFayqiDHCWlsjJnDnXPYG0' + - 'j5UcCqy9LDWtq/gZcipHxVFMbfitec3uMX70FwP7nyTW2zyaSt236v3pipO7UJVs9pDVgU3p' + - '4n0jZqwQwBeHFlzYLPn4MXPb4Lt+5i2CJ1zgsuu4GUX2vBNk3qJnvX8jOdwv3h7O1wBYIqaD' + - '5lCtYoAAAAASUVORK5CYII='; - - -/** - * This color needs to match BORDER_IMAGE. - * @const - */ -ink.CanvasManager.OUT_OF_BOUNDS_COLOR = 0xe6e6e6ff; - - -/** @override */ -ink.CanvasManager.prototype.enterDocument = function() { - ink.CanvasManager.base(this, 'enterDocument'); - - this.engine_.render(this.getElement()); - - var handler = this.getHandler(); - goog.asserts.assert(handler); - - this.brushModel_ = ink.BrushModel.getInstance(this); - - handler.listen( - this.brushModel_, ink.BrushModel.EventType.CHANGE, this.brushUpdate_); -}; - -/** - * Sets or unsets readOnly on the engine. - * @param {boolean} readOnly - */ -ink.CanvasManager.prototype.setReadOnly = function(readOnly) { - this.engine_.setReadOnly(readOnly); -}; - - -/** - * Export the scene as a PNG from the engine. - * @param {number} maxWidth - * @param {boolean} drawBackground - * @param {function(!goog.html.SafeUrl)} callback - * @param {boolean=} opt_asBlob - */ -ink.CanvasManager.prototype.exportPng = function( - maxWidth, drawBackground, callback, opt_asBlob) { - this.onPngExportCompleteCallback_ = callback; - this.exportAsBlob_ = !!opt_asBlob; - var exportProto = new sketchology.proto.ImageExport(); - exportProto.setMaxDimensionPx(maxWidth); - exportProto.setShouldDrawBackground(drawBackground); - this.engine_.exportPng(exportProto); -}; - - -/** - * @private - * @param {number} width - * @param {number} height - * @param {Uint8ClampedArray} bytesArr - */ -ink.CanvasManager.prototype.onPngExportComplete_ = function( - width, height, bytesArr) { - if (this.onPngExportCompleteCallback_) { - try { - var imageData = new ImageData(bytesArr, width, height); - var scratchCanvas = - /** @type {!HTMLCanvasElement} */ (document.createElement('canvas')); - var scratchContext = - /** @type {!CanvasRenderingContext2D} */ ( - scratchCanvas.getContext('2d')); - scratchCanvas.width = width; - scratchCanvas.height = height; - scratchContext.putImageData(imageData, 0, 0); - } catch (ex) { - this.dispatchFatalError_(ex); - return; - } - if (this.exportAsBlob_) { - var cb = (blob) => { - this.onPngExportCompleteCallback_(goog.html.SafeUrl.fromBlob(blob)); - }; - - if (scratchCanvas['msToBlob']) { - scratchCanvas['msToBlob'](cb, 'image/png'); - } else { - scratchCanvas.toBlob(cb, 'image/png'); - } - } else { - this.onPngExportCompleteCallback_( - goog.html.SafeUrl.fromDataUrl(scratchCanvas.toDataURL())); - } - } -}; - - -/** - * Sets a background image, and sets the page bounds to match the image size. - * @param {Uint8ClampedArray} data The image data in RGBA 8888. - * @param {goog.math.Size} size The image dimensions. - */ -ink.CanvasManager.prototype.setBackgroundImage = function(data, size) { - this.setBackgroundImage_(data, size); -}; - - -/** - * Sets a background image and scales the image to match the existing page - * bounds. Will not display the background if no page bounds are set. - * @param {Uint8ClampedArray} data The image data in RGBA 8888. - * @param {goog.math.Size} size The image dimensions. - */ -ink.CanvasManager.prototype.setImageToUseForPageBackground = function( - data, size) { - this.setBackgroundImage_(data, size, {'bounds': 'none'}); -}; - - -/** - * @private - * @param {Uint8ClampedArray} data The image data in RGBA 8888. - * @param {goog.math.Size} size The image dimensions. - * @param {Object<string, *>=} opt_options - */ -ink.CanvasManager.prototype.setBackgroundImage_ = function( - data, size, opt_options) { - opt_options = opt_options || {}; - - var nextUri = 'sketchology://background_' + this.bgCount_; - this.bgCount_++; - - var bgImageProto = new sketchology.proto.BackgroundImageInfo(); - bgImageProto.setUri(nextUri); - if (opt_options['bounds'] != 'none') { - var optBounds = opt_options['bounds'] || - {'xlow': 0, 'ylow': 0, 'xhigh': size.width, 'yhigh': size.height}; - var bounds = new sketchology.proto.Rect(); - bounds.setXlow(optBounds['xlow']); - bounds.setYlow(optBounds['ylow']); - bounds.setXhigh(optBounds['xhigh']); - bounds.setYhigh(optBounds['yhigh']); - bgImageProto.setBounds(bounds); - } - this.engine_.setBackgroundImage(data, size, nextUri, bgImageProto); -}; - - -/** - * Set background color. - * @param {ink.Color} color - */ -ink.CanvasManager.prototype.setBackgroundColor = function(color) { - this.engine_.setBackgroundColor(color); -}; - - -/** @private */ -ink.CanvasManager.prototype.brushUpdate_ = function() { - goog.asserts.assert(this.brushModel_); - - var tool_type = this.brushModel_.getToolType(); - var brush_type = this.brushModel_.getBrushType(); - var strokeWidth = this.brushModel_.getStrokeWidth(); - - var colorString = this.brushModel_.getColor().substring(1); - var color = new ink.Color(parseInt(colorString, 16)); - // Using this alpha channel would make calligraphy or marker brushes - // translucent; highlighter, watercolor, and airbrush have hard-coded alpha - // values in the engine. - color.a = 0xFF; // Set alpha to opaque - - this.engine_.brushUpdate( - color.getRgbaUint32(), strokeWidth, tool_type, brush_type); -}; - - -/** - * Handles a new element created in the engine. - * @param {string} uuid - * @param {string} encodedElement - * @param {string} encodedTransform - * @override - */ -ink.CanvasManager.prototype.onElementCreated = function( - uuid, encodedElement, encodedTransform) { - this.pendingUUIDs_.add(uuid); - this.dispatchEvent(new ink.embed.events.ElementCreatedEvent( - uuid, encodedElement, encodedTransform)); -}; - - -/** - * Handles an element being transformed. - * @param {Array.<string>} uuids - * @param {Array.<string>} encodedTransforms - * @override - */ -ink.CanvasManager.prototype.onElementsMutated = function( - uuids, encodedTransforms) { - this.dispatchEvent( - new ink.embed.events.ElementsMutatedEvent(uuids, encodedTransforms)); -}; - - -/** - * Handles elements being removed. - * @param {Array.<string>} uuids - * @override - */ -ink.CanvasManager.prototype.onElementsRemoved = function(uuids) { - this.dispatchEvent(new ink.embed.events.ElementsRemovedEvent(uuids)); -}; - - -/** - * Handle an addElement request from Brix. If this is a remote add or an - * add-by-undo or redo, adds the element to the engine and the local list of - * elements (this.UUIDs_) at the specified index. If this is a local add - * originated by the engine, the element is already present in the engine and is - * simply removed from this.pendingUUIDs_. - * - * @param {!Object<string, string>} bundle - * @param {number} idx index to add the element at - * @param {boolean} isLocal - */ -ink.CanvasManager.prototype.addElement = function(bundle, idx, isLocal) { - if (!bundle['id']) { - bundle['id'] = 'local-' + this.nextLocalId_++; - } - - var uuid = bundle['id']; - goog.array.insertAt(this.UUIDs_, uuid, idx); - - // If the element originated in the engine, it should be present in the - // pending UUID set, so we just remove it from that set so that future adds by - // undo/redo will work as expected. - if (this.pendingUUIDs_.contains(uuid)) { - this.pendingUUIDs_.remove(uuid); - } else { - // If the element is a remote add or an add by undo or redo, it may not be - // the top element, in which case we add it below the element after it. - if (idx < this.UUIDs_.length - 1) { - this.engine_.addElementBelow(bundle, this.UUIDs_[idx + 1]); - } else { - this.engine_.addElement(bundle); - } - } - - // TODO(wfurr): Figure out how to have the engine wake itself up. - // See b/18830720. - this.engine_.poke(); -}; - - -/** - * Removes a number of elements. - * @param {number} idx index to start removing. - * @param {number} count number of items to remove. - */ -ink.CanvasManager.prototype.removeElements = function(idx, count) { - for (var i = 0; i < count; i++) { - var uuid = this.UUIDs_[idx]; - this.engine_.removeElement(uuid); - goog.array.removeAt(this.UUIDs_, idx); - } - - // TODO(wfurr): Figure out how to have the engine wake itself up. - // See b/18830720. - this.engine_.poke(); -}; - - -/** - * Resets the engine but does not dispatch any Brix related events. Used to - * clear the canvas to reuse it to display another drawing. - */ -ink.CanvasManager.prototype.resetCanvas = function() { - this.engine_.clear(); - this.engine_.setBackgroundColor(ink.Color.DEFAULT_BACKGROUND_COLOR); - this.pendingUUIDs_.clear(); - this.UUIDs_ = []; - this.engine_.poke(); -}; - - -/** - * Clears the canvas. - */ -ink.CanvasManager.prototype.clear = function() { - this.engine_.removeAll(); -}; - - -/** - * Sets element transforms. - * @param {Array.<string>} uuids - * @param {Array.<string>} encodedTransforms - */ -ink.CanvasManager.prototype.setElementTransforms = function( - uuids, encodedTransforms) { - this.engine_.setElementTransforms(uuids, encodedTransforms); -}; - - -/** - * Set callback flags - * @param {!sketchology.proto.SetCallbackFlags} setCallbackFlags - */ -ink.CanvasManager.prototype.setCallbackFlags = function(setCallbackFlags) { - this.engine_.setCallbackFlags(setCallbackFlags); -}; - - -/** - * Sets the size of the page. - * @param {number} left - * @param {number} top - * @param {number} right - * @param {number} bottom - */ -ink.CanvasManager.prototype.setPageBounds = function(left, top, right, bottom) { - this.engine_.setPageBounds(left, top, right, bottom); -}; - - -/** - * Deselects anything selected with the edit tool. - */ -ink.CanvasManager.prototype.deselectAll = function() { - this.engine_.deselectAll(); -}; - - -/** - * Sets the border image. - * @private - */ -ink.CanvasManager.prototype.setBorderImage_ = function() { - var self = this; - var uri = 'sketchology://border0'; - var borderImageProto = new sketchology.proto.Border(); - borderImageProto.setUri(uri); - borderImageProto.setScale(1); - - ink.util.getImageBytes(ink.CanvasManager.BORDER_IMAGE, function(data, size) { - self.engine_.setBorderImage( - data, size, uri, borderImageProto, - ink.CanvasManager.OUT_OF_BOUNDS_COLOR); - }); -}; - - -/** - * Dispatches a FATAL_ERROR event, and throws an Error if it isn't handled. - * @param {Error=} opt_cause - * @private - */ -ink.CanvasManager.prototype.dispatchFatalError_ = function(opt_cause) { - if (this.dispatchEvent(new ink.embed.events.FatalErrorEvent(opt_cause))) { - // Unless one of the listeners returns false or preventDefaults, throw an - // error to trigger default exception handlers on the page. - throw opt_cause || new Error('Unhandled fatal ink error'); - } -}; - - -/** - * Enable or disable an engine flag. - * @param {sketchology.proto.Flag} which - * @param {boolean} enable - */ -ink.CanvasManager.prototype.assignFlag = function(which, enable) { - this.engine_.assignFlag(which, enable); -}; - - -/** - * Simple undo. This only works if the SEngine was constructed with a - * SingleUserDocument with InMemoryStorage. - */ -ink.CanvasManager.prototype.undo = function() { - this.engine_.undo(); -}; - - -/** - * Simple redo. This only works if the SEngine was constructed with a - * SingleUserDocument with InMemoryStorage. - */ -ink.CanvasManager.prototype.redo = function() { - this.engine_.redo(); -}; - - -/** - * Returns the current snapshot. - * @param {function(!sketchology.proto.Snapshot)} callback - */ -ink.CanvasManager.prototype.getSnapshot = function(callback) { - this.engine_.getSnapshot(callback); -}; - - -/** - * Loads a document from a snapshot. - * - * @param {!sketchology.proto.Snapshot} snapshotProto - */ -ink.CanvasManager.prototype.loadFromSnapshot = function(snapshotProto) { - this.engine_.loadFromSnapshot(snapshotProto); -}; - - -/** - * Allows the user to execute arbitrary commands on the engine. - * @param {!sketchology.proto.Command} command - */ -ink.CanvasManager.prototype.handleCommand = function(command) { - this.engine_.handleCommand(command); -}; - - -/** - * Gets the raw engine object. Do not use this. - * @return {Object} - */ -ink.CanvasManager.prototype.getRawEngineObject = function() { - return this.engine_.getRawEngineObject(); -}; - - -/** - * Generates a snapshot based on a brix document. - * @param {!ink.util.RealtimeDocument} brixDoc - * @param {function(!sketchology.proto.Snapshot)} callback - */ -ink.CanvasManager.prototype.convertBrixDocumentToSnapshot = - function(brixDoc, callback) { - this.engine_.convertBrixDocumentToSnapshot(brixDoc, callback); -}; - - -/** - * @param {!sketchology.proto.Snapshot} snapshot - * @param {function(boolean)} callback - */ -ink.CanvasManager.prototype.snapshotHasPendingMutations = - function(snapshot, callback) { - this.engine_.snapshotHasPendingMutations(snapshot, callback); -}; - - -/** - * @param {!sketchology.proto.Snapshot} snapshot - * @param {function(sketchology.proto.MutationPacket)} callback - */ -ink.CanvasManager.prototype.extractMutationPacket = - function(snapshot, callback) { - this.engine_.extractMutationPacket(snapshot, callback); -}; - - -/** - * @param {!sketchology.proto.Snapshot} snapshot - * @param {function(sketchology.proto.Snapshot)} callback - */ -ink.CanvasManager.prototype.clearPendingMutations = - function(snapshot, callback) { - this.engine_.clearPendingMutations(snapshot, callback); -}; - - -/** - * Calls the given callback once all previous asynchronous engine operations - * have been applied. - * @param {!Function} callback - */ -ink.CanvasManager.prototype.flush = function(callback) { - this.engine_.flush(callback); -};
diff --git a/third_party/ink/ink/web/js/cursor_updater.js b/third_party/ink/ink/web/js/cursor_updater.js deleted file mode 100644 index 5f4803e..0000000 --- a/third_party/ink/ink/web/js/cursor_updater.js +++ /dev/null
@@ -1,124 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -goog.provide('ink.CursorUpdater'); - -goog.require('goog.ui.Component'); -goog.require('ink.BrushModel'); -goog.require('ink.Color'); -goog.require('ink.embed.events'); -goog.require('ink.util'); - - - -/** - * @constructor - * @extends {goog.ui.Component} - * @struct - */ -ink.CursorUpdater = function() { - ink.CursorUpdater.base(this, 'constructor'); - - /** @private {ink.BrushModel} */ - this.brushModel_ = null; -}; -goog.inherits(ink.CursorUpdater, goog.ui.Component); - - -/** @override */ -ink.CursorUpdater.prototype.enterDocument = function() { - ink.CursorUpdater.base(this, 'enterDocument'); - - this.brushModel_ = ink.BrushModel.getInstance(this); - - var handler = this.getHandler(); - - handler.listen(this.brushModel_, - ink.BrushModel.EventType.CHANGE, - this.updateCursor_); - - handler.listen(ink.util.getRootParentComponent(this), - ink.embed.events.EventType.DONE_LOADING, - this.handleDoneLoadingEvent_); -}; - - -/** - * @param {!ink.embed.events.DoneLoadingEvent} evt - * @private - */ -ink.CursorUpdater.prototype.handleDoneLoadingEvent_ = function(evt) { - if (evt.isReadOnly) { - // If we aren't editable, use a default cursor. - this.getElement().style.cursor = ''; - } else { - this.updateCursor_(); - } -}; - - -/** - * Updates the cursor icon for the drawable area based on the current selection. - * @private - */ -ink.CursorUpdater.prototype.updateCursor_ = function() { - var rgb = this.brushModel_.getActiveColorNumericRbg(); - var r = 8; - - var url = 'url(' + this.getCursorDataUrlImage(r, rgb) + ')'; - var target = r + ' ' + r; // target is center of cursor - var fallback = ', auto'; - var cursorStyle = url + target + fallback; - - this.getElement().style.cursor = cursorStyle; -}; - -/** - * @param {number} radius - * @param {number} rgb - * @return {string} A data url for a cursor with the provided radius and color. - */ -ink.CursorUpdater.prototype.getCursorDataUrlImage = function(radius, rgb) { - - // TODO(esrauch): We avoid initializing with a fixed brush width for normal - // rendering ahead of time since the android client has the same brush at a - // very large number of different radiuses. Since this is only used for - // cursors, we should really just precompute these as images offline and just - // splice in the colors. - var scratchCanvas = - /** @type {!HTMLCanvasElement} */ (document.createElement('canvas')); - - var context = - /** @type {!CanvasRenderingContext2D} */ (scratchCanvas.getContext('2d')); - - // Make the cursors opaque. - var color = new ink.Color(rgb | 0xFF000000); - - // Cap the minimum radius at 2. - radius = Math.max(radius, 2); - var diameter = Math.ceil(2 * radius); - scratchCanvas.width = diameter; - scratchCanvas.height = diameter; - - // If we have a dark color, use a white outline. For a light color, use a - // black outline. - // Compute the lightness value as defined by HSL. - var max = Math.max(color.r, color.g, color.b); - var min = Math.min(color.r, color.g, color.b); - var lightness = 0.5 * (max + min); - var outlineColor = lightness > 127 ? ink.Color.BLACK : ink.Color.WHITE; - - context.fillStyle = outlineColor.getRgbString(); - context.beginPath(); - context.arc(radius, radius, radius, 0, 2 * Math.PI); - context.closePath(); - context.fill(); - - context.fillStyle = color.getRgbString(); - context.beginPath(); - context.arc(radius, radius, radius - 1, 0, 2 * Math.PI); - context.closePath(); - context.fill(); - - return scratchCanvas.toDataURL(); -};
diff --git a/third_party/ink/ink/web/js/embed/embed.js b/third_party/ink/ink/web/js/embed/embed.js deleted file mode 100644 index 1c159444c..0000000 --- a/third_party/ink/ink/web/js/embed/embed.js +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -goog.provide('ink.embed.Config'); - -goog.require('goog.ui.Component'); -goog.require('ink.util'); -goog.require('protos.research.ink.InkEvent'); - - - -/** - * @constructor - * @struct - */ -ink.embed.Config = function() { - /** - * The parent element to render into (required). - * @type {?Element} - */ - this.parentEl = null; - - /** - * The parent component to set (optional); - * TODO(esrauch): This is only necessary because of the cross-package events - * that are currently going in both directions. Remove this from the config - * after this is cleaned up to avoid Whiteboard events being listened to - * directly in Embed code. - * @type {?goog.ui.Component} - */ - this.parentComponent = null; - - /** - * If true, allows ink to show its own error dialogs for certain cases. - * @type {boolean} - */ - this.allowDialogs = false; - - /** - * Path to NaCl binary. - * - * If you are using the Native Client build, you must specify the url for the - * Ink Native Client NMF file. - * - * @type {?string} - */ - this.nativeClientManifestUrl = null; - - /** - * The source of the embedder. - * - * From //logs/proto/research/ink/ink_event.proto - * - * @type {protos.research.ink.InkEvent.Host} - */ - this.logsHost = protos.research.ink.InkEvent.Host.UNKNOWN_HOST; - - /** - * The type of the document the SEngine should be constructed with. - * - * For Brix documents, this should be PASSTHROUGH_DOCUMENT. - * - * @type {ink.util.SEngineType} - */ - this.sengineType = - ink.util.SEngineType.PASSTHROUGH_DOCUMENT; -};
diff --git a/third_party/ink/ink/web/js/embed/embed_component.js b/third_party/ink/ink/web/js/embed/embed_component.js deleted file mode 100644 index 60206d9..0000000 --- a/third_party/ink/ink/web/js/embed/embed_component.js +++ /dev/null
@@ -1,417 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -/** - * @fileoverview The embeddable ink component. Generally should be constructed - * by using {@code ink.embed.Config.execute()}. - */ -goog.provide('ink.embed.EmbedComponent'); - -goog.require('goog.dom'); -goog.require('goog.events'); -goog.require('goog.events.Event'); -goog.require('goog.math.Size'); -goog.require('goog.soy'); -goog.require('goog.ui.Component'); -goog.require('ink.CanvasManager'); -goog.require('ink.Color'); -goog.require('ink.CursorUpdater'); -goog.require('ink.embed.Config'); -goog.require('ink.embed.events'); -goog.require('ink.soy.embedContent'); -goog.require('ink.util'); -goog.require('protos.research.ink.InkEvent'); -goog.require('sketchology.proto.SetCallbackFlags'); - - - -/** - * @param {!ink.embed.Config} config - * @param {!Function} callback - * @constructor - * @extends {goog.ui.Component} - * @struct - */ -ink.embed.EmbedComponent = function(config, callback) { - ink.embed.EmbedComponent.base(this, 'constructor'); - - /** @private {!ink.embed.Config} */ - this.config_ = config; - - /** @public {boolean} */ - this.allowDialogs = config.allowDialogs; - - /** @private {!ink.CursorUpdater} */ - this.cursorUpdater_ = new ink.CursorUpdater(); - this.addChild(this.cursorUpdater_); - - /** @private {!ink.CanvasManager} */ - this.canvasManager_ = - new ink.CanvasManager(config.nativeClientManifestUrl, config.sengineType); - this.addChild(this.canvasManager_); - - /** @private {!Function} */ - this.callback_ = callback; -}; -goog.inherits(ink.embed.EmbedComponent, goog.ui.Component); - - -//////////////////////////////////////////////////////////////// -// Public API for embedders. -//////////////////////////////////////////////////////////////// - - -/** - * @param {!ink.embed.Config} config - * @param {function(ink.embed.EmbedComponent)} callback Callback function that - * returns the component that is configured based on the settings in this - * Config. This component will raise the relevant ink.embed.Events and provides - * an interface to change the brush color, size, etc. Null is returned if the - * config is invalid. - */ -ink.embed.EmbedComponent.execute = function(config, callback) { - var embed = new ink.embed.EmbedComponent(config, callback); - embed.setParent(config.parentComponent); - embed.render(config.parentEl); -}; - - -/** Removes all elements from the drawing space. */ -ink.embed.EmbedComponent.prototype.clear = function() { - var e = new goog.events.Event(ink.embed.events.EventType.CLEAR_REQUESTED); - this.dispatchEvent(e); - if (!e.defaultPrevented) { - this.canvasManager_.clear(); - } -}; - - -/** Undoes the last modification to the document taken by the user. */ -ink.embed.EmbedComponent.prototype.undo = function() { - var e = new goog.events.Event(ink.embed.events.EventType.UNDO_REQUESTED); - this.dispatchEvent(e); - if (!e.defaultPrevented) { - this.canvasManager_.undo(); - } - var eventProto = ink.util.createDocumentEvent( - this.getLogsHost(), - protos.research.ink.InkEvent.DocumentEvent.DocumentEventType.UNDO); - var logEvent = new ink.embed.events.LogEvent(eventProto); - this.dispatchEvent(logEvent); -}; - - -/** Redoes the last undone action. */ -ink.embed.EmbedComponent.prototype.redo = function() { - var e = new goog.events.Event(ink.embed.events.EventType.REDO_REQUESTED); - this.dispatchEvent(e); - if (!e.defaultPrevented) { - this.canvasManager_.redo(); - } - var eventProto = ink.util.createDocumentEvent( - this.getLogsHost(), - protos.research.ink.InkEvent.DocumentEvent.DocumentEventType.REDO); - var logEvent = new ink.embed.events.LogEvent(eventProto); - this.dispatchEvent(logEvent); -}; - - -/** - * Adds a background image. Sets page bounds to match the given image. - * @param {string} imgSrc - * @param {Function=} opt_cb callback on image load complete - */ -ink.embed.EmbedComponent.prototype.setBackgroundImage = - function(imgSrc, opt_cb) { - ink.util.getImageBytes(imgSrc, - (data, size) => { - this.canvasManager_.setBackgroundImage(data, size); - if (opt_cb) opt_cb(); - }); -}; - - -/** - * Sets a background image to match the existing page bounds. Will not - * display if no page bounds are set. - * @param {string} imgSrc - * @param {Function=} opt_cb callback on image load complete - */ -ink.embed.EmbedComponent.prototype.setImageToUseForPageBackground = - function(imgSrc, opt_cb) { - ink.util.getImageBytes(imgSrc, - (data, size) => { - this.canvasManager_.setImageToUseForPageBackground(data, size); - if (opt_cb) opt_cb(); - }); -}; - - -/** - * Set background color. - * @param {ink.Color} color - */ -ink.embed.EmbedComponent.prototype.setBackgroundColor = function(color) { - this.canvasManager_.setBackgroundColor(color); -}; - - -/** - * Export the scene as a PNG from the engine. - * @param {number} maxWidth - * @param {boolean} drawBackground - * @param {function(!goog.html.SafeUrl)} callback - * @param {boolean=} opt_asBlob If true, returns a blob uri. - */ -ink.embed.EmbedComponent.prototype.exportPng = function( - maxWidth, drawBackground, callback, opt_asBlob) { - this.canvasManager_.exportPng(maxWidth, drawBackground, callback, opt_asBlob); -}; - - -/** - * Set callback flags, for whether to receive callbacks and what data to attach. - * @param {!sketchology.proto.SetCallbackFlags} setCallbackFlags - */ -ink.embed.EmbedComponent.prototype.setCallbackFlags = - function(setCallbackFlags) { - this.canvasManager_.setCallbackFlags(setCallbackFlags); -}; - - -/** - * Sets the size of the page. - * @param {number} left - * @param {number} top - * @param {number} right - * @param {number} bottom - */ -ink.embed.EmbedComponent.prototype.setPageBounds = - function(left, top, right, bottom) { - this.canvasManager_.setPageBounds(left, top, right, bottom); -}; - - -/** - * Deselects anything selected with the edit tool. - */ -ink.embed.EmbedComponent.prototype.deselectAll = function() { - this.canvasManager_.deselectAll(); -}; - - -//////////////////////////////////////////////////////////////// -// Internal code. -//////////////////////////////////////////////////////////////// - - -/** @override */ -ink.embed.EmbedComponent.prototype.createDom = function() { - this.setElementInternal(goog.soy.renderAsElement(ink.soy.embedContent)); -}; - - -/** @override */ -ink.embed.EmbedComponent.prototype.enterDocument = function() { - ink.embed.EmbedComponent.base(this, 'enterDocument'); - - var container = goog.dom.getElement('layer-container'); - - this.canvasManager_.render(container); - this.cursorUpdater_.decorate(container); - - this.getHandler().listen( - this.canvasManager_, ink.embed.events.EventType.CANVAS_INITIALIZED, - goog.bind(this.callback_, this, this)); -}; - - -/** - * Manually adds an element. - * @param {!sketchology.proto.Element} elem - * @param {number} idx index to add the element at - * @param {boolean} isLocal - */ -ink.embed.EmbedComponent.prototype.addElement = function(elem, idx, isLocal) { - this.canvasManager_.addElement(elem, idx, isLocal); -}; - - -/** - * Manually removes a number of elements. - * @param {number} idx index to start removing. - * @param {number} count number of items to remove. - */ -ink.embed.EmbedComponent.prototype.removeElements = function(idx, count) { - this.canvasManager_.removeElements(idx, count); -}; - - -/** - * Resets the canvas associated with the embed component. - * - * Note: Does not affect any attached Brix documents. - */ -ink.embed.EmbedComponent.prototype.resetCanvas = function() { - this.canvasManager_.resetCanvas(); -}; - - -/** - * Sets or unsets readOnly on the canvas. - * @param {boolean} readOnly - */ -ink.embed.EmbedComponent.prototype.setReadOnly = function(readOnly) { - this.canvasManager_.setReadOnly(readOnly); -}; - - -/** - * Sets element transforms. - * @param {Array.<string>} uuids - * @param {Array.<string>} encodedTransforms - */ -ink.embed.EmbedComponent.prototype.setElementTransforms = function( - uuids, encodedTransforms) { - this.canvasManager_.setElementTransforms(uuids, encodedTransforms); -}; - - -/** - * Returns true if the document is empty, false if it has content, and - * undefined if not a brix document. - * @param {Function} callback - */ -ink.embed.EmbedComponent.prototype.isEmpty = function(callback) { - var e = new ink.embed.events.EmptyStatusRequestedEvent(callback); - this.dispatchEvent(e); - if (!e.defaultPrevented) { - callback(undefined); - } -}; - - -/** - * Returns the current dimensions of the canvas element. - * @return {goog.math.Size} The width and height of the canvas. - */ -ink.embed.EmbedComponent.prototype.getCanvasDimensions = function() { - var element = - this.canvasManager_.getElementStrict().querySelector('canvas,embed'); - return new goog.math.Size(element.clientWidth, element.clientHeight); -}; - - -/** - * Returns the logs host id. - * @return {protos.research.ink.InkEvent.Host} - */ -ink.embed.EmbedComponent.prototype.getLogsHost = function() { - return this.config_.logsHost; -}; - - -/** - * Enable or disable an engine flag. - * @param {sketchology.proto.Flag} which - * @param {boolean} enable - */ -ink.embed.EmbedComponent.prototype.assignFlag = function(which, enable) { - this.canvasManager_.assignFlag(which, enable); -}; - - -/** - * Returns the current snapshot. Only works if sengineType is set to - * ink.util.SEngineType.IN_MEMORY. - * @param {function(!sketchology.proto.Snapshot)} callback - */ -ink.embed.EmbedComponent.prototype.getSnapshot = function(callback) { - if (this.config_.sengineType !== ink.util.SEngineType.IN_MEMORY) { - throw new Error(`Can't getSnapshot without sengineType IN_MEMORY.`); - } - this.canvasManager_.getSnapshot(callback); -}; - - -/** - * Loads a document from a snapshot. Only works if sengineType is set to - * ink.util.SEngineType.IN_MEMORY. - * - * @param {!sketchology.proto.Snapshot} snapshotProto - */ -ink.embed.EmbedComponent.prototype.loadFromSnapshot = function(snapshotProto) { - if (this.config_.sengineType !== ink.util.SEngineType.IN_MEMORY) { - throw new Error(`Can't loadFromSnapshot without sengineType IN_MEMORY.`); - } - this.canvasManager_.loadFromSnapshot(snapshotProto); -}; - - -/** - * Allows the user to execute arbitrary commands on the engine. - * @param {!sketchology.proto.Command} command - */ -ink.embed.EmbedComponent.prototype.handleCommand = function(command) { - this.canvasManager_.handleCommand(command); -}; - - -/** - * Gets the raw engine object. Do not use this. - * @return {Object} - */ -ink.embed.EmbedComponent.prototype.getRawEngineObject = function() { - return this.canvasManager_.getRawEngineObject(); -}; - - -/** - * Generates a snapshot based on a brix document. - * @param {!ink.util.RealtimeDocument} brixDoc - * @param {function(!sketchology.proto.Snapshot)} callback - */ -ink.embed.EmbedComponent.prototype.convertBrixDocumentToSnapshot = - function(brixDoc, callback) { - this.canvasManager_.convertBrixDocumentToSnapshot(brixDoc, callback); -}; - - -/** - * @param {!sketchology.proto.Snapshot} snapshot - * @param {function(boolean)} callback - */ -ink.embed.EmbedComponent.prototype.snapshotHasPendingMutations = - function(snapshot, callback) { - this.canvasManager_.snapshotHasPendingMutations(snapshot, callback); -}; - - -/** - * @param {!sketchology.proto.Snapshot} snapshot - * @param {function(sketchology.proto.MutationPacket)} callback - */ -ink.embed.EmbedComponent.prototype.extractMutationPacket = - function(snapshot, callback) { - this.canvasManager_.extractMutationPacket(snapshot, callback); -}; - - -/** - * @param {!sketchology.proto.Snapshot} snapshot - * @param {function(sketchology.proto.Snapshot)} callback - */ -ink.embed.EmbedComponent.prototype.clearPendingMutations = - function(snapshot, callback) { - this.canvasManager_.clearPendingMutations(snapshot, callback); -}; - - -/** - * Calls the given callback once all previous asynchronous engine operations - * have been applied. - * @param {!Function} callback - */ -ink.embed.EmbedComponent.prototype.flush = function(callback) { - this.canvasManager_.flush(callback); -};
diff --git a/third_party/ink/ink/web/js/embed/events.js b/third_party/ink/ink/web/js/embed/events.js deleted file mode 100644 index 2997c5e..0000000 --- a/third_party/ink/ink/web/js/embed/events.js +++ /dev/null
@@ -1,225 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -/** - * @fileoverview Events that embedders can listen to. Note: currently embedders - * are able to listen to other internal events, but only these events should be - * treated as a public API. - */ -goog.provide('ink.embed.events'); -goog.provide('ink.embed.events.DoneLoadingEvent'); -goog.provide('ink.embed.events.ElementCreatedEvent'); -goog.provide('ink.embed.events.ElementsMutatedEvent'); -goog.provide('ink.embed.events.ElementsRemovedEvent'); -goog.provide('ink.embed.events.EmptyStatusRequestedEvent'); -goog.provide('ink.embed.events.EventType'); -goog.provide('ink.embed.events.FatalErrorEvent'); -goog.provide('ink.embed.events.LogEvent'); - -goog.require('goog.events'); -goog.require('protos.research.ink.InkEvent'); - - -/** @enum {string} */ -ink.embed.events.EventType = { - // Dispatched when the space is ready to be drawn onto. - DONE_LOADING: goog.events.getUniqueId('done_loading'), - - // Dispatched when pen mode is enabled. - PEN_MODE_ENABLED: goog.events.getUniqueId('pen_mode_enabled'), - - // Dispatched when the GL canvas is initialized. - CANVAS_INITIALIZED: goog.events.getUniqueId('canvas_initialized'), - - // Dispatched when a new element has been created on the canvas. - ELEMENT_CREATED: goog.events.getUniqueId('element_created'), - - // Dispatched when an element is mutaed. - ELEMENTS_MUTATED: goog.events.getUniqueId('elements_mutated'), - - // Dispatched when elements are removed. - ELEMENTS_REMOVED: goog.events.getUniqueId('elements_removed'), - - // Dispatched when something wants to know if the document is empty. - EMPTY_STATUS_REQUESTED: goog.events.getUniqueId('empty_status_requested'), - - // Dispatched when something needs to be logged. - LOG: goog.events.getUniqueId('log'), - - // Dispatched to request an undo. - UNDO_REQUESTED: goog.events.getUniqueId('undo_requested'), - - // Dispatched to request a redo. - REDO_REQUESTED: goog.events.getUniqueId('redo_requested'), - - // Dispatched to request a clear. - CLEAR_REQUESTED: goog.events.getUniqueId('clear_requested'), - - // Dispatched when a fatal error occurs and the canvas is no longer valid. - // If this is not handled, an Error is thrown (or re-raised). The canvas - // should be discarded and a new one constructed. - FATAL_ERROR: goog.events.getUniqueId('fatal_error') -}; - - - -/** - * An event fired when the embed is ready to be drawn onto. - * - * @param {Object} brixDoc The brix realtime document associated with - * the document that has been loaded. - * @param {boolean} isReadOnly Whether the document is read only. - * - * @extends {goog.events.Event} - * @constructor - * @struct - */ -ink.embed.events.DoneLoadingEvent = function(brixDoc, isReadOnly) { - ink.embed.events.DoneLoadingEvent.base( - this, 'constructor', ink.embed.events.EventType.DONE_LOADING); - - /** @type {Object} */ - this.brixDoc = brixDoc; - - /** @type {boolean} */ - this.isReadOnly = isReadOnly; -}; -goog.inherits(ink.embed.events.DoneLoadingEvent, goog.events.Event); - - -/** - * An event fired when pen mode is enabled or disabled. - * - * @param {boolean} enabled - * - * @extends {goog.events.Event} - * @constructor - * @struct - */ -ink.embed.events.PenModeEnabled = function(enabled) { - ink.embed.events.PenModeEnabled.base(this, 'constructor', - ink.embed.events.EventType.PEN_MODE_ENABLED); - - /** @type {boolean} */ - this.enabled = enabled; -}; -goog.inherits(ink.embed.events.PenModeEnabled, goog.events.Event); - - -/** - * An event fired when a new element is created in the embed. - * - * @param {string} uuid - * @param {string} encodedElement - * @param {string} encodedTransform - * - * @extends {goog.events.Event} - * @constructor - * @struct - */ -ink.embed.events.ElementCreatedEvent = function(uuid, encodedElement, - encodedTransform) { - ink.embed.events.ElementCreatedEvent.base( - this, 'constructor', ink.embed.events.EventType.ELEMENT_CREATED); - - this.uuid = uuid; - this.encodedElement = encodedElement; - this.encodedTransform = encodedTransform; -}; -goog.inherits(ink.embed.events.ElementCreatedEvent, goog.events.Event); - - -/** - * An event fired when an element is mutated. - * - * @param {Array.<string>} uuids - * @param {Array.<string>} encodedTransforms - * - * @extends {goog.events.Event} - * @constructor - * @struct - */ -ink.embed.events.ElementsMutatedEvent = function(uuids, encodedTransforms) { - ink.embed.events.ElementsMutatedEvent.base( - this, 'constructor', ink.embed.events.EventType.ELEMENTS_MUTATED); - - this.uuids = uuids; - this.encodedTransforms = encodedTransforms; -}; -goog.inherits(ink.embed.events.ElementsMutatedEvent, goog.events.Event); - - -/** - * An event fired when elements are removed. - * - * @param {Array.<string>} uuids - * - * @extends {goog.events.Event} - * @constructor - * @struct - */ -ink.embed.events.ElementsRemovedEvent = function(uuids) { - ink.embed.events.ElementsRemovedEvent.base( - this, 'constructor', ink.embed.events.EventType.ELEMENTS_REMOVED); - - this.uuids = uuids; -}; -goog.inherits(ink.embed.events.ElementsRemovedEvent, goog.events.Event); - - -/** - * An event fired when something wants to know if the document is empty. - * - * @param {Function} callback - * - * @extends {goog.events.Event} - * @constructor - * @struct - */ -ink.embed.events.EmptyStatusRequestedEvent = function(callback) { - ink.embed.events.EmptyStatusRequestedEvent.base( - this, 'constructor', ink.embed.events.EventType.EMPTY_STATUS_REQUESTED); - - this.callback = callback; -}; -goog.inherits(ink.embed.events.EmptyStatusRequestedEvent, goog.events.Event); - - -/** - * An event fired when an event should be logged by the embedder. - * - * @param {protos.research.ink.InkEvent} proto The ink event proto. - * - * @extends {goog.events.Event} - * @constructor - * @struct - */ -ink.embed.events.LogEvent = function(proto) { - ink.embed.events.LogEvent.base( - this, 'constructor', ink.embed.events.EventType.LOG); - - this.proto = proto; -}; -goog.inherits(ink.embed.events.LogEvent, goog.events.Event); - - -/** - * An event fired when a fatal error has occured. - * - * If this error is not handled by the embedder, the component will throw an - * error. The embedder should discard this component and construct a new one. - * - * @param {Error=} opt_cause Optional cause of the fatal error - * - * @extends {goog.events.Event} - * @constructor - * @struct - */ -ink.embed.events.FatalErrorEvent = function(opt_cause) { - ink.embed.events.FatalErrorEvent.base( - this, 'constructor', ink.embed.events.EventType.FATAL_ERROR); - - /** @type {Error} */ - this.cause = opt_cause || null; -}; -goog.inherits(ink.embed.events.FatalErrorEvent, goog.events.Event);
diff --git a/third_party/ink/ink/web/js/main.soy.js b/third_party/ink/ink/web/js/main.soy.js deleted file mode 100644 index 3883d56..0000000 --- a/third_party/ink/ink/web/js/main.soy.js +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// This file was automatically generated from main.soy. -// Please don't edit this file by hand. - -/** - * @fileoverview Templates in namespace ink.soy. - * @public - */ - -goog.provide('ink.soy.embedContent'); - -goog.require('soy'); -goog.require('soydata.VERY_UNSAFE'); - - -/** - * @param {Object<string, *>=} opt_data - * @param {Object<string, *>=} opt_ijData - * @param {Object<string, *>=} opt_ijData_deprecated - * @return {!goog.soy.data.SanitizedHtml} - * @suppress {checkTypes} - */ -ink.soy.embedContent = function(opt_data, opt_ijData, opt_ijData_deprecated) { - opt_ijData = opt_ijData_deprecated || opt_ijData; - return soydata.VERY_UNSAFE.ordainSanitizedHtml(((goog.DEBUG && soy.$$debugSoyTemplateInfo) ? '<!--dta_of(ink.soy.embedContent, research/ink/web/js/main.soy, 7)-->' : '') + '<div id="canvas-parent"><style' + (opt_ijData && opt_ijData.csp_nonce ? ' nonce="' + soy.$$escapeHtmlAttribute(opt_ijData && opt_ijData.csp_nonce) + '"' : '') + '>\n #canvas-parent {\n height: 100%;\n position: relative;\n width: 100%;\n }\n #layer-container {\n height: 100%;\n position: relative;\n width: 100%;\n }\n #ink-engine {\n height: 100%;\n left: 0;\n position: absolute;\n top: 0;\n width: 100%;\n touch-action: none;\n }\n .above-ink-canvas {\n display: none;\n }\n </style><div class="above-ink-canvas"></div><div id="layer-container"></div><div class="below-ink-canvas"></div></div>' + ((goog.DEBUG && soy.$$debugSoyTemplateInfo) ? '<!--dta_cf(ink.soy.embedContent)-->' : '')); -}; -if (goog.DEBUG) { - ink.soy.embedContent.soyTemplateName = 'ink.soy.embedContent'; -}
diff --git a/third_party/ink/ink_event.pb.js b/third_party/ink/ink_event.pb.js deleted file mode 100644 index 26cd567..0000000 --- a/third_party/ink/ink_event.pb.js +++ /dev/null
@@ -1,2654 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Protocol Buffer 2 Copyright 2008 Google Inc. -// All other code copyright its respective owners. - -/** - * @fileoverview Generated Protocol Buffer code for file - * logs/proto/research/ink/ink_event.proto. - * Generated by //net/proto2/compiler/public:protocol_compiler. - * @suppress {messageConventions} - */ - -goog.provide('protos.research.ink.InkEvent'); -goog.provide('protos.research.ink.InkEvent.DocumentEvent'); -goog.provide('protos.research.ink.InkEvent.DocumentEvent.OpenedEvent'); -goog.provide('protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent'); -goog.provide('protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined'); -goog.provide('protos.research.ink.InkEvent.DocumentEvent.DocumentState'); -goog.provide('protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField'); -goog.provide('protos.research.ink.InkEvent.DocumentEvent.DocumentEventType'); -goog.provide('protos.research.ink.InkEvent.ToolbarEvent'); -goog.provide('protos.research.ink.InkEvent.ToolbarEvent.ToolEventType'); -goog.provide('protos.research.ink.InkEvent.ToolbarEvent.ToolType'); -goog.provide('protos.research.ink.InkEvent.ToolbarEvent.ExpandMethod'); -goog.provide('protos.research.ink.InkEvent.EngineEvent'); -goog.provide('protos.research.ink.InkEvent.EngineEvent.EngineEventType'); -goog.provide('protos.research.ink.InkEvent.GmsEvent'); -goog.provide('protos.research.ink.InkEvent.GmsEvent.GmsEventType'); -goog.provide('protos.research.ink.InkEvent.Host'); -goog.provide('protos.research.ink.InkEvent.EventType'); - -goog.require('goog.proto2.Message'); - - - -/** - * Message InkEvent. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -protos.research.ink.InkEvent = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(protos.research.ink.InkEvent, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -protos.research.ink.InkEvent.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!protos.research.ink.InkEvent} The cloned message. - * @override - */ -protos.research.ink.InkEvent.prototype.clone; - - -/** - * Gets the value of the host field. - * @return {?protos.research.ink.InkEvent.Host} The value. - */ -protos.research.ink.InkEvent.prototype.getHost = function() { - return /** @type {?protos.research.ink.InkEvent.Host} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the host field or the default value if not set. - * @return {!protos.research.ink.InkEvent.Host} The value. - */ -protos.research.ink.InkEvent.prototype.getHostOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.Host} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the host field. - * @param {!protos.research.ink.InkEvent.Host} value The value. - */ -protos.research.ink.InkEvent.prototype.setHost = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the host field has a value. - */ -protos.research.ink.InkEvent.prototype.hasHost = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the host field. - */ -protos.research.ink.InkEvent.prototype.hostCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the host field. - */ -protos.research.ink.InkEvent.prototype.clearHost = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the event_type field. - * @return {?protos.research.ink.InkEvent.EventType} The value. - */ -protos.research.ink.InkEvent.prototype.getEventType = function() { - return /** @type {?protos.research.ink.InkEvent.EventType} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the event_type field or the default value if not set. - * @return {!protos.research.ink.InkEvent.EventType} The value. - */ -protos.research.ink.InkEvent.prototype.getEventTypeOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.EventType} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the event_type field. - * @param {!protos.research.ink.InkEvent.EventType} value The value. - */ -protos.research.ink.InkEvent.prototype.setEventType = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the event_type field has a value. - */ -protos.research.ink.InkEvent.prototype.hasEventType = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the event_type field. - */ -protos.research.ink.InkEvent.prototype.eventTypeCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the event_type field. - */ -protos.research.ink.InkEvent.prototype.clearEventType = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the document_event field. - * @return {?protos.research.ink.InkEvent.DocumentEvent} The value. - */ -protos.research.ink.InkEvent.prototype.getDocumentEvent = function() { - return /** @type {?protos.research.ink.InkEvent.DocumentEvent} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the document_event field or the default value if not set. - * @return {!protos.research.ink.InkEvent.DocumentEvent} The value. - */ -protos.research.ink.InkEvent.prototype.getDocumentEventOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.DocumentEvent} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the document_event field. - * @param {!protos.research.ink.InkEvent.DocumentEvent} value The value. - */ -protos.research.ink.InkEvent.prototype.setDocumentEvent = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the document_event field has a value. - */ -protos.research.ink.InkEvent.prototype.hasDocumentEvent = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the document_event field. - */ -protos.research.ink.InkEvent.prototype.documentEventCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the document_event field. - */ -protos.research.ink.InkEvent.prototype.clearDocumentEvent = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the toolbar_event field. - * @return {?protos.research.ink.InkEvent.ToolbarEvent} The value. - */ -protos.research.ink.InkEvent.prototype.getToolbarEvent = function() { - return /** @type {?protos.research.ink.InkEvent.ToolbarEvent} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the toolbar_event field or the default value if not set. - * @return {!protos.research.ink.InkEvent.ToolbarEvent} The value. - */ -protos.research.ink.InkEvent.prototype.getToolbarEventOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.ToolbarEvent} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the toolbar_event field. - * @param {!protos.research.ink.InkEvent.ToolbarEvent} value The value. - */ -protos.research.ink.InkEvent.prototype.setToolbarEvent = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the toolbar_event field has a value. - */ -protos.research.ink.InkEvent.prototype.hasToolbarEvent = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the toolbar_event field. - */ -protos.research.ink.InkEvent.prototype.toolbarEventCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the toolbar_event field. - */ -protos.research.ink.InkEvent.prototype.clearToolbarEvent = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the engine_event field. - * @return {?protos.research.ink.InkEvent.EngineEvent} The value. - */ -protos.research.ink.InkEvent.prototype.getEngineEvent = function() { - return /** @type {?protos.research.ink.InkEvent.EngineEvent} */ (this.get$Value(5)); -}; - - -/** - * Gets the value of the engine_event field or the default value if not set. - * @return {!protos.research.ink.InkEvent.EngineEvent} The value. - */ -protos.research.ink.InkEvent.prototype.getEngineEventOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.EngineEvent} */ (this.get$ValueOrDefault(5)); -}; - - -/** - * Sets the value of the engine_event field. - * @param {!protos.research.ink.InkEvent.EngineEvent} value The value. - */ -protos.research.ink.InkEvent.prototype.setEngineEvent = function(value) { - this.set$Value(5, value); -}; - - -/** - * @return {boolean} Whether the engine_event field has a value. - */ -protos.research.ink.InkEvent.prototype.hasEngineEvent = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the engine_event field. - */ -protos.research.ink.InkEvent.prototype.engineEventCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the engine_event field. - */ -protos.research.ink.InkEvent.prototype.clearEngineEvent = function() { - this.clear$Field(5); -}; - - -/** - * Gets the value of the gms_event field. - * @return {?protos.research.ink.InkEvent.GmsEvent} The value. - */ -protos.research.ink.InkEvent.prototype.getGmsEvent = function() { - return /** @type {?protos.research.ink.InkEvent.GmsEvent} */ (this.get$Value(6)); -}; - - -/** - * Gets the value of the gms_event field or the default value if not set. - * @return {!protos.research.ink.InkEvent.GmsEvent} The value. - */ -protos.research.ink.InkEvent.prototype.getGmsEventOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.GmsEvent} */ (this.get$ValueOrDefault(6)); -}; - - -/** - * Sets the value of the gms_event field. - * @param {!protos.research.ink.InkEvent.GmsEvent} value The value. - */ -protos.research.ink.InkEvent.prototype.setGmsEvent = function(value) { - this.set$Value(6, value); -}; - - -/** - * @return {boolean} Whether the gms_event field has a value. - */ -protos.research.ink.InkEvent.prototype.hasGmsEvent = function() { - return this.has$Value(6); -}; - - -/** - * @return {number} The number of values in the gms_event field. - */ -protos.research.ink.InkEvent.prototype.gmsEventCount = function() { - return this.count$Values(6); -}; - - -/** - * Clears the values in the gms_event field. - */ -protos.research.ink.InkEvent.prototype.clearGmsEvent = function() { - this.clear$Field(6); -}; - - -/** - * Enumeration Host. - * @enum {number} - */ -protos.research.ink.InkEvent.Host = { - UNKNOWN_HOST: 0, - FISHFOOD: 1, - KEEP: 2, - CLASSROOM: 3, - FIREBALL: 4 -}; - - -/** - * Enumeration EventType. - * @enum {number} - */ -protos.research.ink.InkEvent.EventType = { - UNKNOWN_TYPE: 0, - DOCUMENT_EVENT: 1, - TOOLBAR_EVENT: 2, - ENGINE_EVENT: 3, - GMS_EVENT: 4 -}; - - - -/** - * Message DocumentEvent. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -protos.research.ink.InkEvent.DocumentEvent = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(protos.research.ink.InkEvent.DocumentEvent, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -protos.research.ink.InkEvent.DocumentEvent.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!protos.research.ink.InkEvent.DocumentEvent} The cloned message. - * @override - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.clone; - - -/** - * Gets the value of the event_type field. - * @return {?protos.research.ink.InkEvent.DocumentEvent.DocumentEventType} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getEventType = function() { - return /** @type {?protos.research.ink.InkEvent.DocumentEvent.DocumentEventType} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the event_type field or the default value if not set. - * @return {!protos.research.ink.InkEvent.DocumentEvent.DocumentEventType} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getEventTypeOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.DocumentEvent.DocumentEventType} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the event_type field. - * @param {!protos.research.ink.InkEvent.DocumentEvent.DocumentEventType} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.setEventType = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the event_type field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.hasEventType = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the event_type field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.eventTypeCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the event_type field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.clearEventType = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the opened_event field. - * @return {?protos.research.ink.InkEvent.DocumentEvent.OpenedEvent} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getOpenedEvent = function() { - return /** @type {?protos.research.ink.InkEvent.DocumentEvent.OpenedEvent} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the opened_event field or the default value if not set. - * @return {!protos.research.ink.InkEvent.DocumentEvent.OpenedEvent} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getOpenedEventOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.DocumentEvent.OpenedEvent} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the opened_event field. - * @param {!protos.research.ink.InkEvent.DocumentEvent.OpenedEvent} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.setOpenedEvent = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the opened_event field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.hasOpenedEvent = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the opened_event field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.openedEventCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the opened_event field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.clearOpenedEvent = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the open_cancelled_event field. - * @return {?protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getOpenCancelledEvent = function() { - return /** @type {?protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the open_cancelled_event field or the default value if not set. - * @return {!protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getOpenCancelledEventOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the open_cancelled_event field. - * @param {!protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.setOpenCancelledEvent = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the open_cancelled_event field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.hasOpenCancelledEvent = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the open_cancelled_event field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.openCancelledEventCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the open_cancelled_event field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.clearOpenCancelledEvent = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the error_code field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getErrorCode = function() { - return /** @type {?string} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the error_code field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getErrorCodeOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the error_code field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.setErrorCode = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the error_code field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.hasErrorCode = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the error_code field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.errorCodeCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the error_code field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.clearErrorCode = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the brix_error_code field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getBrixErrorCode = function() { - return /** @type {?string} */ (this.get$Value(5)); -}; - - -/** - * Gets the value of the brix_error_code field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getBrixErrorCodeOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(5)); -}; - - -/** - * Sets the value of the brix_error_code field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.setBrixErrorCode = function(value) { - this.set$Value(5, value); -}; - - -/** - * @return {boolean} Whether the brix_error_code field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.hasBrixErrorCode = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the brix_error_code field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.brixErrorCodeCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the brix_error_code field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.clearBrixErrorCode = function() { - this.clear$Field(5); -}; - - -/** - * Gets the value of the collaborator_joined_event field. - * @return {?protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getCollaboratorJoinedEvent = function() { - return /** @type {?protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined} */ (this.get$Value(6)); -}; - - -/** - * Gets the value of the collaborator_joined_event field or the default value if not set. - * @return {!protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getCollaboratorJoinedEventOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined} */ (this.get$ValueOrDefault(6)); -}; - - -/** - * Sets the value of the collaborator_joined_event field. - * @param {!protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.setCollaboratorJoinedEvent = function(value) { - this.set$Value(6, value); -}; - - -/** - * @return {boolean} Whether the collaborator_joined_event field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.hasCollaboratorJoinedEvent = function() { - return this.has$Value(6); -}; - - -/** - * @return {number} The number of values in the collaborator_joined_event field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.collaboratorJoinedEventCount = function() { - return this.count$Values(6); -}; - - -/** - * Clears the values in the collaborator_joined_event field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.clearCollaboratorJoinedEvent = function() { - this.clear$Field(6); -}; - - -/** - * Gets the value of the document_state field. - * @return {?protos.research.ink.InkEvent.DocumentEvent.DocumentState} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getDocumentState = function() { - return /** @type {?protos.research.ink.InkEvent.DocumentEvent.DocumentState} */ (this.get$Value(7)); -}; - - -/** - * Gets the value of the document_state field or the default value if not set. - * @return {!protos.research.ink.InkEvent.DocumentEvent.DocumentState} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getDocumentStateOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.DocumentEvent.DocumentState} */ (this.get$ValueOrDefault(7)); -}; - - -/** - * Sets the value of the document_state field. - * @param {!protos.research.ink.InkEvent.DocumentEvent.DocumentState} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.setDocumentState = function(value) { - this.set$Value(7, value); -}; - - -/** - * @return {boolean} Whether the document_state field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.hasDocumentState = function() { - return this.has$Value(7); -}; - - -/** - * @return {number} The number of values in the document_state field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.documentStateCount = function() { - return this.count$Values(7); -}; - - -/** - * Clears the values in the document_state field. - */ -protos.research.ink.InkEvent.DocumentEvent.prototype.clearDocumentState = function() { - this.clear$Field(7); -}; - - -/** - * Enumeration DocumentEventType. - * @enum {number} - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentEventType = { - UNKNOWN_DOCUMENT_EVENT: 0, - CREATED: 1, - OPENED: 2, - OPEN_FAILED: 3, - KICKED_USER_OUT: 4, - OPEN_CANCELLED: 5, - BRIX_DOCUMENT_CONNECT: 6, - UNDO: 7, - REDO: 8, - COLLABORATOR_JOINED: 9, - SEND: 10, - ABANDON: 11, - EXTERNAL_SHARE: 12 -}; - - - -/** - * Message OpenedEvent. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(protos.research.ink.InkEvent.DocumentEvent.OpenedEvent, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!protos.research.ink.InkEvent.DocumentEvent.OpenedEvent} The cloned message. - * @override - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.clone; - - -/** - * Gets the value of the millis_until_first_byte_loaded field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.getMillisUntilFirstByteLoaded = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the millis_until_first_byte_loaded field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.getMillisUntilFirstByteLoadedOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the millis_until_first_byte_loaded field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.setMillisUntilFirstByteLoaded = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the millis_until_first_byte_loaded field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.hasMillisUntilFirstByteLoaded = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the millis_until_first_byte_loaded field. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.millisUntilFirstByteLoadedCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the millis_until_first_byte_loaded field. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.clearMillisUntilFirstByteLoaded = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the millis_until_editable field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.getMillisUntilEditable = function() { - return /** @type {?string} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the millis_until_editable field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.getMillisUntilEditableOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the millis_until_editable field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.setMillisUntilEditable = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the millis_until_editable field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.hasMillisUntilEditable = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the millis_until_editable field. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.millisUntilEditableCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the millis_until_editable field. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.clearMillisUntilEditable = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the missing_document_bounds field. - * @return {?boolean} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.getMissingDocumentBounds = function() { - return /** @type {?boolean} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the missing_document_bounds field or the default value if not set. - * @return {boolean} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.getMissingDocumentBoundsOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the missing_document_bounds field. - * @param {boolean} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.setMissingDocumentBounds = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the missing_document_bounds field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.hasMissingDocumentBounds = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the missing_document_bounds field. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.missingDocumentBoundsCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the missing_document_bounds field. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.clearMissingDocumentBounds = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the was_opened_by_cosmoid field. - * @return {?boolean} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.getWasOpenedByCosmoid = function() { - return /** @type {?boolean} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the was_opened_by_cosmoid field or the default value if not set. - * @return {boolean} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.getWasOpenedByCosmoidOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the was_opened_by_cosmoid field. - * @param {boolean} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.setWasOpenedByCosmoid = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the was_opened_by_cosmoid field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.hasWasOpenedByCosmoid = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the was_opened_by_cosmoid field. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.wasOpenedByCosmoidCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the was_opened_by_cosmoid field. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.clearWasOpenedByCosmoid = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the active_users field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.getActiveUsers = function() { - return /** @type {?string} */ (this.get$Value(5)); -}; - - -/** - * Gets the value of the active_users field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.getActiveUsersOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(5)); -}; - - -/** - * Sets the value of the active_users field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.setActiveUsers = function(value) { - this.set$Value(5, value); -}; - - -/** - * @return {boolean} Whether the active_users field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.hasActiveUsers = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the active_users field. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.activeUsersCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the active_users field. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.clearActiveUsers = function() { - this.clear$Field(5); -}; - - - -/** - * Message OpenCancelledEvent. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent} The cloned message. - * @override - */ -protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.prototype.clone; - - -/** - * Gets the value of the time_until_cancelled field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.prototype.getTimeUntilCancelled = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the time_until_cancelled field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.prototype.getTimeUntilCancelledOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the time_until_cancelled field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.prototype.setTimeUntilCancelled = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the time_until_cancelled field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.prototype.hasTimeUntilCancelled = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the time_until_cancelled field. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.prototype.timeUntilCancelledCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the time_until_cancelled field. - */ -protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.prototype.clearTimeUntilCancelled = function() { - this.clear$Field(1); -}; - - - -/** - * Message CollaboratorJoined. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined} The cloned message. - * @override - */ -protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.prototype.clone; - - -/** - * Gets the value of the is_me field. - * @return {?boolean} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.prototype.getIsMe = function() { - return /** @type {?boolean} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the is_me field or the default value if not set. - * @return {boolean} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.prototype.getIsMeOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the is_me field. - * @param {boolean} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.prototype.setIsMe = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the is_me field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.prototype.hasIsMe = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the is_me field. - */ -protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.prototype.isMeCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the is_me field. - */ -protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.prototype.clearIsMe = function() { - this.clear$Field(1); -}; - - - -/** - * Message DocumentState. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(protos.research.ink.InkEvent.DocumentEvent.DocumentState, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!protos.research.ink.InkEvent.DocumentEvent.DocumentState} The cloned message. - * @override - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.clone; - - -/** - * Gets the value of the stroke_count field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.getStrokeCount = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the stroke_count field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.getStrokeCountOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the stroke_count field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.setStrokeCount = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the stroke_count field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.hasStrokeCount = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the stroke_count field. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.strokeCountCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the stroke_count field. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.clearStrokeCount = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the text_field field at the index given. - * @param {number} index The index to lookup. - * @return {?protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.getTextField = function(index) { - return /** @type {?protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField} */ (this.get$Value(2, index)); -}; - - -/** - * Gets the value of the text_field field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.getTextFieldOrDefault = function(index) { - return /** @type {!protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField} */ (this.get$ValueOrDefault(2, index)); -}; - - -/** - * Adds a value to the text_field field. - * @param {!protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField} value The value to add. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.addTextField = function(value) { - this.add$Value(2, value); -}; - - -/** - * Returns the array of values in the text_field field. - * @return {!Array<!protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField>} The values in the field. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.textFieldArray = function() { - return /** @type {!Array<!protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField>} */ (this.array$Values(2)); -}; - - -/** - * @return {boolean} Whether the text_field field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.hasTextField = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the text_field field. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.textFieldCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the text_field field. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.clearTextField = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the sticker_count field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.getStickerCount = function() { - return /** @type {?string} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the sticker_count field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.getStickerCountOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the sticker_count field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.setStickerCount = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the sticker_count field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.hasStickerCount = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the sticker_count field. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.stickerCountCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the sticker_count field. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.clearStickerCount = function() { - this.clear$Field(3); -}; - - - -/** - * Message TextField. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField} The cloned message. - * @override - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.clone; - - -/** - * Gets the value of the character_count field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.getCharacterCount = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the character_count field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.getCharacterCountOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the character_count field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.setCharacterCount = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the character_count field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.hasCharacterCount = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the character_count field. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.characterCountCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the character_count field. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.clearCharacterCount = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the line_count field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.getLineCount = function() { - return /** @type {?string} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the line_count field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.getLineCountOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the line_count field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.setLineCount = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the line_count field has a value. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.hasLineCount = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the line_count field. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.lineCountCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the line_count field. - */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.clearLineCount = function() { - this.clear$Field(2); -}; - - - -/** - * Message ToolbarEvent. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -protos.research.ink.InkEvent.ToolbarEvent = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(protos.research.ink.InkEvent.ToolbarEvent, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -protos.research.ink.InkEvent.ToolbarEvent.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!protos.research.ink.InkEvent.ToolbarEvent} The cloned message. - * @override - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.clone; - - -/** - * Gets the value of the tool_event_type field. - * @return {?protos.research.ink.InkEvent.ToolbarEvent.ToolEventType} The value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.getToolEventType = function() { - return /** @type {?protos.research.ink.InkEvent.ToolbarEvent.ToolEventType} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the tool_event_type field or the default value if not set. - * @return {!protos.research.ink.InkEvent.ToolbarEvent.ToolEventType} The value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.getToolEventTypeOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.ToolbarEvent.ToolEventType} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the tool_event_type field. - * @param {!protos.research.ink.InkEvent.ToolbarEvent.ToolEventType} value The value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.setToolEventType = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the tool_event_type field has a value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.hasToolEventType = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the tool_event_type field. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.toolEventTypeCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the tool_event_type field. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.clearToolEventType = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the tool_type field. - * @return {?protos.research.ink.InkEvent.ToolbarEvent.ToolType} The value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.getToolType = function() { - return /** @type {?protos.research.ink.InkEvent.ToolbarEvent.ToolType} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the tool_type field or the default value if not set. - * @return {!protos.research.ink.InkEvent.ToolbarEvent.ToolType} The value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.getToolTypeOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.ToolbarEvent.ToolType} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the tool_type field. - * @param {!protos.research.ink.InkEvent.ToolbarEvent.ToolType} value The value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.setToolType = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the tool_type field has a value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.hasToolType = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the tool_type field. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.toolTypeCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the tool_type field. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.clearToolType = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the expand_method field. - * @return {?protos.research.ink.InkEvent.ToolbarEvent.ExpandMethod} The value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.getExpandMethod = function() { - return /** @type {?protos.research.ink.InkEvent.ToolbarEvent.ExpandMethod} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the expand_method field or the default value if not set. - * @return {!protos.research.ink.InkEvent.ToolbarEvent.ExpandMethod} The value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.getExpandMethodOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.ToolbarEvent.ExpandMethod} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the expand_method field. - * @param {!protos.research.ink.InkEvent.ToolbarEvent.ExpandMethod} value The value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.setExpandMethod = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the expand_method field has a value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.hasExpandMethod = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the expand_method field. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.expandMethodCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the expand_method field. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.clearExpandMethod = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the color field. - * @return {?number} The value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.getColor = function() { - return /** @type {?number} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the color field or the default value if not set. - * @return {number} The value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.getColorOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the color field. - * @param {number} value The value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.setColor = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the color field has a value. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.hasColor = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the color field. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.colorCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the color field. - */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.clearColor = function() { - this.clear$Field(4); -}; - - -/** - * Enumeration ToolEventType. - * @enum {number} - */ -protos.research.ink.InkEvent.ToolbarEvent.ToolEventType = { - UNKNOWN_TOOL_EVENT: 0, - TOOLBAR_EXPANDED: 1, - TOOLBAR_EXTRA_COLORS_EXPANDED: 2, - TOOLBAR_CONTRACTED_BY_USER: 3, - TOOL_TYPE_CHANGED: 4, - TOOL_COLOR_SELECTED: 5, - TOOL_SIZE_SELECTED: 6, - CLEAR_CANVAS: 7, - SELECT_NONE: 8 -}; - - -/** - * Enumeration ToolType. - * @enum {number} - */ -protos.research.ink.InkEvent.ToolbarEvent.ToolType = { - UNKNOWN_TOOL_TYPE: 0, - EDIT_TOOL: 1, - CALLIGRAPHY: 2, - MARKER: 3, - HIGHLIGHTER: 4, - MAGIC_ERASER: 5 -}; - - -/** - * Enumeration ExpandMethod. - * @enum {number} - */ -protos.research.ink.InkEvent.ToolbarEvent.ExpandMethod = { - UNKNOWN_EXPAND_METHOD: 0, - SECOND_TAP: 1, - DRAG: 2, - EXPAND_BUTTON_TAP: 3 -}; - - - -/** - * Message EngineEvent. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -protos.research.ink.InkEvent.EngineEvent = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(protos.research.ink.InkEvent.EngineEvent, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -protos.research.ink.InkEvent.EngineEvent.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!protos.research.ink.InkEvent.EngineEvent} The cloned message. - * @override - */ -protos.research.ink.InkEvent.EngineEvent.prototype.clone; - - -/** - * Gets the value of the engine_event_type field. - * @return {?protos.research.ink.InkEvent.EngineEvent.EngineEventType} The value. - */ -protos.research.ink.InkEvent.EngineEvent.prototype.getEngineEventType = function() { - return /** @type {?protos.research.ink.InkEvent.EngineEvent.EngineEventType} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the engine_event_type field or the default value if not set. - * @return {!protos.research.ink.InkEvent.EngineEvent.EngineEventType} The value. - */ -protos.research.ink.InkEvent.EngineEvent.prototype.getEngineEventTypeOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.EngineEvent.EngineEventType} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the engine_event_type field. - * @param {!protos.research.ink.InkEvent.EngineEvent.EngineEventType} value The value. - */ -protos.research.ink.InkEvent.EngineEvent.prototype.setEngineEventType = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the engine_event_type field has a value. - */ -protos.research.ink.InkEvent.EngineEvent.prototype.hasEngineEventType = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the engine_event_type field. - */ -protos.research.ink.InkEvent.EngineEvent.prototype.engineEventTypeCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the engine_event_type field. - */ -protos.research.ink.InkEvent.EngineEvent.prototype.clearEngineEventType = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the error_code field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.EngineEvent.prototype.getErrorCode = function() { - return /** @type {?string} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the error_code field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.EngineEvent.prototype.getErrorCodeOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the error_code field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.EngineEvent.prototype.setErrorCode = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the error_code field has a value. - */ -protos.research.ink.InkEvent.EngineEvent.prototype.hasErrorCode = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the error_code field. - */ -protos.research.ink.InkEvent.EngineEvent.prototype.errorCodeCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the error_code field. - */ -protos.research.ink.InkEvent.EngineEvent.prototype.clearErrorCode = function() { - this.clear$Field(2); -}; - - -/** - * Enumeration EngineEventType. - * @enum {number} - */ -protos.research.ink.InkEvent.EngineEvent.EngineEventType = { - UNKNOWN_ENGINE_EVENT: 0, - LOST_GL_CONTEXT: 1, - RAISED_FATAL_EXCEPTION: 2 -}; - - - -/** - * Message GmsEvent. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -protos.research.ink.InkEvent.GmsEvent = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(protos.research.ink.InkEvent.GmsEvent, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -protos.research.ink.InkEvent.GmsEvent.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!protos.research.ink.InkEvent.GmsEvent} The cloned message. - * @override - */ -protos.research.ink.InkEvent.GmsEvent.prototype.clone; - - -/** - * Gets the value of the gms_event_type field. - * @return {?protos.research.ink.InkEvent.GmsEvent.GmsEventType} The value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.getGmsEventType = function() { - return /** @type {?protos.research.ink.InkEvent.GmsEvent.GmsEventType} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the gms_event_type field or the default value if not set. - * @return {!protos.research.ink.InkEvent.GmsEvent.GmsEventType} The value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.getGmsEventTypeOrDefault = function() { - return /** @type {!protos.research.ink.InkEvent.GmsEvent.GmsEventType} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the gms_event_type field. - * @param {!protos.research.ink.InkEvent.GmsEvent.GmsEventType} value The value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.setGmsEventType = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the gms_event_type field has a value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.hasGmsEventType = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the gms_event_type field. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.gmsEventTypeCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the gms_event_type field. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.clearGmsEventType = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the time_since_connect_start field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.getTimeSinceConnectStart = function() { - return /** @type {?string} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the time_since_connect_start field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.getTimeSinceConnectStartOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the time_since_connect_start field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.setTimeSinceConnectStart = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the time_since_connect_start field has a value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.hasTimeSinceConnectStart = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the time_since_connect_start field. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.timeSinceConnectStartCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the time_since_connect_start field. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.clearTimeSinceConnectStart = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the failure_has_resolution field. - * @return {?boolean} The value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.getFailureHasResolution = function() { - return /** @type {?boolean} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the failure_has_resolution field or the default value if not set. - * @return {boolean} The value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.getFailureHasResolutionOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the failure_has_resolution field. - * @param {boolean} value The value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.setFailureHasResolution = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the failure_has_resolution field has a value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.hasFailureHasResolution = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the failure_has_resolution field. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.failureHasResolutionCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the failure_has_resolution field. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.clearFailureHasResolution = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the gms_error_code field. - * @return {?string} The value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.getGmsErrorCode = function() { - return /** @type {?string} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the gms_error_code field or the default value if not set. - * @return {string} The value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.getGmsErrorCodeOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the gms_error_code field. - * @param {string} value The value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.setGmsErrorCode = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the gms_error_code field has a value. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.hasGmsErrorCode = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the gms_error_code field. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.gmsErrorCodeCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the gms_error_code field. - */ -protos.research.ink.InkEvent.GmsEvent.prototype.clearGmsErrorCode = function() { - this.clear$Field(4); -}; - - -/** - * Enumeration GmsEventType. - * @enum {number} - */ -protos.research.ink.InkEvent.GmsEvent.GmsEventType = { - CONNECT_SUCCESS: 0, - CONNECT_FAILED: 1, - STOPPED_WHEN_PENDING_CONNECT: 2 -}; - - -/** @override */ -protos.research.ink.InkEvent.prototype.getDescriptor = function() { - var descriptor = protos.research.ink.InkEvent.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'InkEvent', - fullName: 'logs.proto.research.ink.InkEvent' - }, - 1: { - name: 'host', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: protos.research.ink.InkEvent.Host.UNKNOWN_HOST, - type: protos.research.ink.InkEvent.Host - }, - 2: { - name: 'event_type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: protos.research.ink.InkEvent.EventType.UNKNOWN_TYPE, - type: protos.research.ink.InkEvent.EventType - }, - 3: { - name: 'document_event', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: protos.research.ink.InkEvent.DocumentEvent - }, - 4: { - name: 'toolbar_event', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: protos.research.ink.InkEvent.ToolbarEvent - }, - 5: { - name: 'engine_event', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: protos.research.ink.InkEvent.EngineEvent - }, - 6: { - name: 'gms_event', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: protos.research.ink.InkEvent.GmsEvent - } - }; - protos.research.ink.InkEvent.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - protos.research.ink.InkEvent, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -protos.research.ink.InkEvent.getDescriptor = - protos.research.ink.InkEvent.prototype.getDescriptor; - - -/** @override */ -protos.research.ink.InkEvent.DocumentEvent.prototype.getDescriptor = function() { - var descriptor = protos.research.ink.InkEvent.DocumentEvent.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'DocumentEvent', - containingType: protos.research.ink.InkEvent, - fullName: 'logs.proto.research.ink.InkEvent.DocumentEvent' - }, - 1: { - name: 'event_type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: protos.research.ink.InkEvent.DocumentEvent.DocumentEventType.UNKNOWN_DOCUMENT_EVENT, - type: protos.research.ink.InkEvent.DocumentEvent.DocumentEventType - }, - 2: { - name: 'opened_event', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: protos.research.ink.InkEvent.DocumentEvent.OpenedEvent - }, - 3: { - name: 'open_cancelled_event', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent - }, - 4: { - name: 'error_code', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - }, - 5: { - name: 'brix_error_code', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - }, - 6: { - name: 'collaborator_joined_event', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined - }, - 7: { - name: 'document_state', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: protos.research.ink.InkEvent.DocumentEvent.DocumentState - } - }; - protos.research.ink.InkEvent.DocumentEvent.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - protos.research.ink.InkEvent.DocumentEvent, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -protos.research.ink.InkEvent.DocumentEvent.getDescriptor = - protos.research.ink.InkEvent.DocumentEvent.prototype.getDescriptor; - - -/** @override */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.getDescriptor = function() { - var descriptor = protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'OpenedEvent', - containingType: protos.research.ink.InkEvent.DocumentEvent, - fullName: 'logs.proto.research.ink.InkEvent.DocumentEvent.OpenedEvent' - }, - 1: { - name: 'millis_until_first_byte_loaded', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - }, - 2: { - name: 'millis_until_editable', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - }, - 3: { - name: 'missing_document_bounds', - fieldType: goog.proto2.Message.FieldType.BOOL, - type: Boolean - }, - 4: { - name: 'was_opened_by_cosmoid', - fieldType: goog.proto2.Message.FieldType.BOOL, - type: Boolean - }, - 5: { - name: 'active_users', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - } - }; - protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - protos.research.ink.InkEvent.DocumentEvent.OpenedEvent, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.getDescriptor = - protos.research.ink.InkEvent.DocumentEvent.OpenedEvent.prototype.getDescriptor; - - -/** @override */ -protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.prototype.getDescriptor = function() { - var descriptor = protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'OpenCancelledEvent', - containingType: protos.research.ink.InkEvent.DocumentEvent, - fullName: 'logs.proto.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent' - }, - 1: { - name: 'time_until_cancelled', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - } - }; - protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.getDescriptor = - protos.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent.prototype.getDescriptor; - - -/** @override */ -protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.prototype.getDescriptor = function() { - var descriptor = protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'CollaboratorJoined', - containingType: protos.research.ink.InkEvent.DocumentEvent, - fullName: 'logs.proto.research.ink.InkEvent.DocumentEvent.CollaboratorJoined' - }, - 1: { - name: 'is_me', - fieldType: goog.proto2.Message.FieldType.BOOL, - type: Boolean - } - }; - protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.getDescriptor = - protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined.prototype.getDescriptor; - - -/** @override */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.getDescriptor = function() { - var descriptor = protos.research.ink.InkEvent.DocumentEvent.DocumentState.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'DocumentState', - containingType: protos.research.ink.InkEvent.DocumentEvent, - fullName: 'logs.proto.research.ink.InkEvent.DocumentEvent.DocumentState' - }, - 1: { - name: 'stroke_count', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - }, - 2: { - name: 'text_field', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField - }, - 3: { - name: 'sticker_count', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - } - }; - protos.research.ink.InkEvent.DocumentEvent.DocumentState.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - protos.research.ink.InkEvent.DocumentEvent.DocumentState, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.getDescriptor = - protos.research.ink.InkEvent.DocumentEvent.DocumentState.prototype.getDescriptor; - - -/** @override */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.getDescriptor = function() { - var descriptor = protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'TextField', - containingType: protos.research.ink.InkEvent.DocumentEvent.DocumentState, - fullName: 'logs.proto.research.ink.InkEvent.DocumentEvent.DocumentState.TextField' - }, - 1: { - name: 'character_count', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - }, - 2: { - name: 'line_count', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - } - }; - protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.getDescriptor = - protos.research.ink.InkEvent.DocumentEvent.DocumentState.TextField.prototype.getDescriptor; - - -/** @override */ -protos.research.ink.InkEvent.ToolbarEvent.prototype.getDescriptor = function() { - var descriptor = protos.research.ink.InkEvent.ToolbarEvent.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ToolbarEvent', - containingType: protos.research.ink.InkEvent, - fullName: 'logs.proto.research.ink.InkEvent.ToolbarEvent' - }, - 1: { - name: 'tool_event_type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: protos.research.ink.InkEvent.ToolbarEvent.ToolEventType.UNKNOWN_TOOL_EVENT, - type: protos.research.ink.InkEvent.ToolbarEvent.ToolEventType - }, - 2: { - name: 'tool_type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: protos.research.ink.InkEvent.ToolbarEvent.ToolType.UNKNOWN_TOOL_TYPE, - type: protos.research.ink.InkEvent.ToolbarEvent.ToolType - }, - 3: { - name: 'expand_method', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: protos.research.ink.InkEvent.ToolbarEvent.ExpandMethod.UNKNOWN_EXPAND_METHOD, - type: protos.research.ink.InkEvent.ToolbarEvent.ExpandMethod - }, - 4: { - name: 'color', - fieldType: goog.proto2.Message.FieldType.INT32, - type: Number - } - }; - protos.research.ink.InkEvent.ToolbarEvent.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - protos.research.ink.InkEvent.ToolbarEvent, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -protos.research.ink.InkEvent.ToolbarEvent.getDescriptor = - protos.research.ink.InkEvent.ToolbarEvent.prototype.getDescriptor; - - -/** @override */ -protos.research.ink.InkEvent.EngineEvent.prototype.getDescriptor = function() { - var descriptor = protos.research.ink.InkEvent.EngineEvent.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'EngineEvent', - containingType: protos.research.ink.InkEvent, - fullName: 'logs.proto.research.ink.InkEvent.EngineEvent' - }, - 1: { - name: 'engine_event_type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: protos.research.ink.InkEvent.EngineEvent.EngineEventType.UNKNOWN_ENGINE_EVENT, - type: protos.research.ink.InkEvent.EngineEvent.EngineEventType - }, - 2: { - name: 'error_code', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - } - }; - protos.research.ink.InkEvent.EngineEvent.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - protos.research.ink.InkEvent.EngineEvent, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -protos.research.ink.InkEvent.EngineEvent.getDescriptor = - protos.research.ink.InkEvent.EngineEvent.prototype.getDescriptor; - - -/** @override */ -protos.research.ink.InkEvent.GmsEvent.prototype.getDescriptor = function() { - var descriptor = protos.research.ink.InkEvent.GmsEvent.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'GmsEvent', - containingType: protos.research.ink.InkEvent, - fullName: 'logs.proto.research.ink.InkEvent.GmsEvent' - }, - 1: { - name: 'gms_event_type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: protos.research.ink.InkEvent.GmsEvent.GmsEventType.CONNECT_SUCCESS, - type: protos.research.ink.InkEvent.GmsEvent.GmsEventType - }, - 2: { - name: 'time_since_connect_start', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - }, - 3: { - name: 'failure_has_resolution', - fieldType: goog.proto2.Message.FieldType.BOOL, - type: Boolean - }, - 4: { - name: 'gms_error_code', - fieldType: goog.proto2.Message.FieldType.INT64, - type: String - } - }; - protos.research.ink.InkEvent.GmsEvent.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - protos.research.ink.InkEvent.GmsEvent, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -protos.research.ink.InkEvent.GmsEvent.getDescriptor = - protos.research.ink.InkEvent.GmsEvent.prototype.getDescriptor;
diff --git a/third_party/ink/ink_scripts.js b/third_party/ink/ink_scripts.js deleted file mode 100644 index b056e6d6..0000000 --- a/third_party/ink/ink_scripts.js +++ /dev/null
@@ -1,118 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// The include directives are put into Javascript-style comments to prevent -// parsing errors in non-flattened mode. The flattener still sees them. -// Note that this makes the flattener to comment out the first line of the -// included file but that's all right since any javascript file should start -// with a copyright comment anyway. - -// <include src="ink/web/js/main.soy.js"> -// <include src="ink/web/js/cursor_updater.js"> -// <include src="ink/web/js/canvas_manager/canvas_manager.js"> -// <include src="ink/web/js/embed/embed_component.js"> -// <include src="ink/web/js/embed/events.js"> -// <include src="ink/web/js/embed/embed.js"> -// <include src="template/soy/soyutils_usegoog.js"> -// <include src="ink_event.pb.js"> -// <include src="sketchology/public/nacl/embed.soy.js"> -// <include src="sketchology/public/nacl/sketchology_engine_wrapper.js"> -// <include src="sketchology/public/js/common/color.js"> -// <include src="sketchology/public/js/common/model.js"> -// <include src="sketchology/public/js/common/undo_state_change_event.js"> -// <include src="sketchology/public/js/common/proto_serializer.js"> -// <include src="sketchology/public/js/common/util.js"> -// <include src="sketchology/public/js/common/element_listener.js"> -// <include src="sketchology/public/js/common/brush_model.js"> -// <include src="sketchology/proto/rect_bounds.pb.js"> -// <include src="sketchology/proto/elements.pb.js"> -// <include src="sketchology/proto/animations.pb.js"> -// <include src="sketchology/proto/sengine.pb.js"> -// <include src="sketchology/proto/document.pb.js"> -// <include src="wireserializer.js"> -// <include src="closure/functions/functions.js"> -// <include src="closure/base.js"> -// <include src="closure/fs/url.js"> -// <include src="closure/uri/utils.js"> -// <include src="closure/uri/uri.js"> -// <include src="closure/style/style.js"> -// <include src="closure/crypt/crypt.js"> -// <include src="closure/crypt/base64.js"> -// <include src="closure/ui/component.js"> -// <include src="closure/ui/idgenerator.js"> -// <include src="closure/labs/useragent/platform.js"> -// <include src="closure/labs/useragent/browser.js"> -// <include src="closure/labs/useragent/util.js"> -// <include src="closure/labs/useragent/engine.js"> -// <include src="closure/string/const.js"> -// <include src="closure/string/string.js"> -// <include src="closure/string/typedstring.js"> -// <include src="closure/structs/set.js"> -// <include src="closure/structs/inversionmap.js"> -// <include src="closure/structs/collection.js"> -// <include src="closure/structs/structs.js"> -// <include src="closure/structs/map.js"> -// <include src="closure/proto2/serializer.js"> -// <include src="closure/proto2/objectserializer.js"> -// <include src="closure/proto2/message.js"> -// <include src="closure/proto2/fielddescriptor.js"> -// <include src="closure/proto2/descriptor.js"> -// <include src="closure/html/safehtml.js"> -// <include src="closure/html/safescript.js"> -// <include src="closure/html/safestyle.js"> -// <include src="closure/html/uncheckedconversions.js"> -// <include src="closure/html/safestylesheet.js"> -// <include src="closure/html/legacyconversions.js"> -// <include src="closure/html/trustedresourceurl.js"> -// <include src="closure/html/safeurl.js"> -// <include src="closure/math/long.js"> -// <include src="closure/math/irect.js"> -// <include src="closure/math/size.js"> -// <include src="closure/math/math.js"> -// <include src="closure/math/rect.js"> -// <include src="closure/math/coordinate.js"> -// <include src="closure/math/box.js"> -// <include src="closure/object/object.js"> -// <include src="closure/reflect/reflect.js"> -// <include src="closure/useragent/useragent.js"> -// <include src="closure/useragent/product.js"> -// <include src="closure/i18n/uchar.js"> -// <include src="closure/i18n/bidi.js"> -// <include src="closure/i18n/graphemebreak.js"> -// <include src="closure/i18n/bidiformatter.js"> -// <include src="closure/dom/tagname.js"> -// <include src="closure/dom/classlist.js"> -// <include src="closure/dom/asserts.js"> -// <include src="closure/dom/nodetype.js"> -// <include src="closure/dom/dom.js"> -// <include src="closure/dom/tags.js"> -// <include src="closure/dom/safe.js"> -// <include src="closure/dom/browserfeature.js"> -// <include src="closure/dom/htmlelement.js"> -// <include src="closure/dom/vendor.js"> -// <include src="closure/soy/soy.js"> -// <include src="closure/soy/data.js"> -// <include src="closure/format/format.js"> -// <include src="closure/asserts/asserts.js"> -// <include src="closure/array/array.js"> -// <include src="closure/iter/iter.js"> -// <include src="closure/events/eventid.js"> -// <include src="closure/events/event.js"> -// <include src="closure/events/listener.js"> -// <include src="closure/events/listenable.js"> -// <include src="closure/events/browserevent.js"> -// <include src="closure/events/events.js"> -// <include src="closure/events/browserfeature.js"> -// <include src="closure/events/eventtarget.js"> -// <include src="closure/events/eventhandler.js"> -// <include src="closure/events/listenermap.js"> -// <include src="closure/events/keycodes.js"> -// <include src="closure/events/wheelevent.js"> -// <include src="closure/events/eventtype.js"> -// <include src="closure/disposable/idisposable.js"> -// <include src="closure/disposable/disposable.js"> -// <include src="closure/debug/debug.js"> -// <include src="closure/debug/errorcontext.js"> -// <include src="closure/debug/entrypointregistry.js"> -// <include src="closure/debug/error.js">
diff --git a/third_party/ink/prebuilt/nacl/_platform_specific/arm/ink_arm.nexe b/third_party/ink/prebuilt/nacl/_platform_specific/arm/ink_arm.nexe deleted file mode 100644 index f4b52055..0000000 --- a/third_party/ink/prebuilt/nacl/_platform_specific/arm/ink_arm.nexe +++ /dev/null Binary files differ
diff --git a/third_party/ink/prebuilt/nacl/_platform_specific/x86-32/ink_x86_32.nexe b/third_party/ink/prebuilt/nacl/_platform_specific/x86-32/ink_x86_32.nexe deleted file mode 100644 index f4b63923..0000000 --- a/third_party/ink/prebuilt/nacl/_platform_specific/x86-32/ink_x86_32.nexe +++ /dev/null Binary files differ
diff --git a/third_party/ink/prebuilt/nacl/_platform_specific/x86-64/ink_x86_64.nexe b/third_party/ink/prebuilt/nacl/_platform_specific/x86-64/ink_x86_64.nexe deleted file mode 100644 index 74abf1ba..0000000 --- a/third_party/ink/prebuilt/nacl/_platform_specific/x86-64/ink_x86_64.nexe +++ /dev/null Binary files differ
diff --git a/third_party/ink/prebuilt/nacl/index.html b/third_party/ink/prebuilt/nacl/index.html deleted file mode 100644 index 42e5dc0..0000000 --- a/third_party/ink/prebuilt/nacl/index.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!DOCTYPE html> -<html> -<!-- -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. ---> - - <head> - <style type="text/css"> - body { margin: 0; } - #ink-canvas { - height: 600px; - width: 800px; - } - </style> - <link rel="icon" href="data:,"> <!-- Prevent favicon.ico requests --> - </head> - <body> - <h1>Ink demo — NaCl version</h1> - <div id="ink-canvas"></div> - <script src="ink_lib_binary.js"></script> - <script src="ink_demo.js"></script> - </body> -</html>
diff --git a/third_party/ink/prebuilt/nacl/ink.nmf b/third_party/ink/prebuilt/nacl/ink.nmf deleted file mode 100644 index b901943..0000000 --- a/third_party/ink/prebuilt/nacl/ink.nmf +++ /dev/null
@@ -1,14 +0,0 @@ -{ - "program": { - "arm": { - "url": "_platform_specific/arm/ink_arm.nexe" - }, - "x86-32": { - "url": "_platform_specific/x86-32/ink_x86_32.nexe" - }, - "x86-64": { - "url": "_platform_specific/x86-64/ink_x86_64.nexe" - } - }, - "files": {} -}
diff --git a/third_party/ink/prebuilt/nacl/ink_demo.js b/third_party/ink/prebuilt/nacl/ink_demo.js deleted file mode 100644 index b12ac89..0000000 --- a/third_party/ink/prebuilt/nacl/ink_demo.js +++ /dev/null
@@ -1,19 +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. - -(function() { - var config = new ink.embed.Config({ - parentEl: document.querySelector('#ink-canvas'), - nativeClientManifestUrl: 'ink.nmf', - sengineType: 'makeSEngineInMemory' - }); - ink.embed.EmbedComponent.execute(config, (embed) => { - // put the embed component on the window so it's easy to experiment in the console. - window.embed = embed; - - // change the brush color - var brushModel = ink.BrushModel.getInstance(embed); - brushModel.setColor('#FF00FF'); - }); -}());
diff --git a/third_party/ink/prebuilt/nacl/ink_lib_binary.js b/third_party/ink/prebuilt/nacl/ink_lib_binary.js deleted file mode 100644 index a806172..0000000 --- a/third_party/ink/prebuilt/nacl/ink_lib_binary.js +++ /dev/null
@@ -1,159 +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. -var g,aa="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)},ba="undefined"!=typeof window&&window===this?this:"undefined"!=typeof global&&null!=global?global:this,ca=function(a,b){if(b){var c=ba;a=a.split(".");for(var d=0;d<a.length-1;d++){var e=a[d];e in c||(c[e]={});c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&aa(c,a,{configurable:!0,writable:!0,value:b})}}; -ca("Array.prototype.find",function(a){return a?a:function(a,c){a:{var b=this;b instanceof String&&(b=String(b));for(var e=b.length,f=0;f<e;f++){var h=b[f];if(a.call(c,h,f,b)){a=h;break a}}a=void 0}return a}}); -var da=function(){da=function(){};ba.Symbol||(ba.Symbol=ea)},ea=function(){var a=0;return function(b){return"jscomp_symbol_"+(b||"")+a++}}(),ha=function(){da();var a=ba.Symbol.iterator;a||(a=ba.Symbol.iterator=ba.Symbol("iterator"));"function"!=typeof Array.prototype[a]&&aa(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return fa(this)}});ha=function(){}},fa=function(a){var b=0;return ia(function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}})},ia=function(a){ha();a={next:a}; -a[ba.Symbol.iterator]=function(){return this};return a},k=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};ca("Object.entries",function(a){return a?a:function(a){var b=[],d;for(d in a)k(a,d)&&b.push([d,a[d]]);return b}});var ja=function(a){ha();var b=a[Symbol.iterator];return b?b.call(a):fa(a)}; -ca("WeakMap",function(a){function b(a){k(a,d)||aa(a,d,{value:{}})}function c(a){var c=Object[a];c&&(Object[a]=function(a){b(a);return c(a)})}if(function(){if(!a||!Object.seal)return!1;try{var b=Object.seal({}),c=Object.seal({}),d=new a([[b,2],[c,3]]);if(2!=d.get(b)||3!=d.get(c))return!1;d.delete(b);d.set(c,4);return!d.has(b)&&4==d.get(c)}catch(y){return!1}}())return a;var d="$jscomp_hidden_"+Math.random();c("freeze");c("preventExtensions");c("seal");var e=0,f=function(a){this.a=(e+=Math.random()+ -1).toString();if(a){da();ha();a=ja(a);for(var b;!(b=a.next()).done;)b=b.value,this.set(b[0],b[1])}};f.prototype.set=function(a,c){b(a);if(!k(a,d))throw Error("WeakMap key fail: "+a);a[d][this.a]=c;return this};f.prototype.get=function(a){return k(a,d)?a[d][this.a]:void 0};f.prototype.has=function(a){return k(a,d)&&k(a[d],this.a)};f.prototype.delete=function(a){return k(a,d)&&k(a[d],this.a)?delete a[d][this.a]:!1};return f}); -ca("Map",function(a){if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var b=Object.seal({x:4}),c=new a(ja([[b,"s"]]));if("s"!=c.get(b)||1!=c.size||c.get({x:4})||c.set({x:4},"t")!=c||2!=c.size)return!1;var d=c.entries(),e=d.next();if(e.done||e.value[0]!=b||"s"!=e.value[1])return!1;e=d.next();return e.done||4!=e.value[0].x||"t"!=e.value[1]||!d.next().done?!1:!0}catch(J){return!1}}())return a;da();ha();var b=new WeakMap,c=function(a){this.f= -{};this.a=f();this.size=0;if(a){a=ja(a);for(var b;!(b=a.next()).done;)b=b.value,this.set(b[0],b[1])}};c.prototype.set=function(a,b){var c=d(this,a);c.list||(c.list=this.f[c.id]=[]);c.o?c.o.value=b:(c.o={next:this.a,D:this.a.D,head:this.a,key:a,value:b},c.list.push(c.o),this.a.D.next=c.o,this.a.D=c.o,this.size++);return this};c.prototype.delete=function(a){a=d(this,a);return a.o&&a.list?(a.list.splice(a.index,1),a.list.length||delete this.f[a.id],a.o.D.next=a.o.next,a.o.next.D=a.o.D,a.o.head=null, -this.size--,!0):!1};c.prototype.clear=function(){this.f={};this.a=this.a.D=f();this.size=0};c.prototype.has=function(a){return!!d(this,a).o};c.prototype.get=function(a){return(a=d(this,a).o)&&a.value};c.prototype.entries=function(){return e(this,function(a){return[a.key,a.value]})};c.prototype.keys=function(){return e(this,function(a){return a.key})};c.prototype.values=function(){return e(this,function(a){return a.value})};c.prototype.forEach=function(a,b){for(var c=this.entries(),d;!(d=c.next()).done;)d= -d.value,a.call(b,d[1],d[0],this)};c.prototype[Symbol.iterator]=c.prototype.entries;var d=function(a,c){var d=c&&typeof c;"object"==d||"function"==d?b.has(c)?d=b.get(c):(d=""+ ++h,b.set(c,d)):d="p_"+c;var e=a.f[d];if(e&&k(a.f,d))for(a=0;a<e.length;a++){var f=e[a];if(c!==c&&f.key!==f.key||c===f.key)return{id:d,list:e,index:a,o:f}}return{id:d,list:e,index:-1,o:void 0}},e=function(a,b){var c=a.a;return ia(function(){if(c){for(;c.head!=a.a;)c=c.D;for(;c.next!=c.head;)return c=c.next,{done:!1,value:b(c)}; -c=null}return{done:!0,value:void 0}})},f=function(){var a={};return a.D=a.next=a.head=a},h=0;return c}); -ca("Set",function(a){if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var b=Object.seal({x:4}),d=new a(ja([b]));if(!d.has(b)||1!=d.size||d.add(b)!=d||1!=d.size||d.add({x:4})!=d||2!=d.size)return!1;var e=d.entries(),f=e.next();if(f.done||f.value[0]!=b||f.value[1]!=b)return!1;f=e.next();return f.done||f.value[0]==b||4!=f.value[0].x||f.value[1]!=f.value[0]?!1:e.next().done}catch(h){return!1}}())return a;da();ha();var b=function(a){this.a=new Map; -if(a){a=ja(a);for(var b;!(b=a.next()).done;)this.add(b.value)}this.size=this.a.size};b.prototype.add=function(a){this.a.set(a,a);this.size=this.a.size;return this};b.prototype.delete=function(a){a=this.a.delete(a);this.size=this.a.size;return a};b.prototype.clear=function(){this.a.clear();this.size=0};b.prototype.has=function(a){return this.a.has(a)};b.prototype.entries=function(){return this.a.entries()};b.prototype.values=function(){return this.a.values()};b.prototype.keys=b.prototype.values;b.prototype[Symbol.iterator]= -b.prototype.values;b.prototype.forEach=function(a,b){var c=this;this.a.forEach(function(d){return a.call(b,d,d,c)})};return b}); -var l=this,m=function(a){return"string"==typeof a},ka=function(a,b){a=a.split(".");var c=l;a[0]in c||"undefined"==typeof c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)a.length||void 0===b?c[d]&&c[d]!==Object.prototype[d]?c=c[d]:c=c[d]={}:c[d]=b},la=function(){},n=function(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"== -c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null";else if("function"==b&&"undefined"==typeof a.call)return"object";return b},ma=function(a){return"array"==n(a)},na=function(a){var b=typeof a;return"object"==b&&null!=a||"function"==b}, -oa="closure_uid_"+(1E9*Math.random()>>>0),pa=0,qa=function(a,b,c){return a.call.apply(a.bind,arguments)},ra=function(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}return function(){return a.apply(b,arguments)}},sa=function(a,b,c){Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf("native code")?sa=qa:sa=ra;return sa.apply(null, -arguments)},q=function(a,b){function c(){}c.prototype=b.prototype;a.R=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.Fd=function(a,c,f){for(var d=Array(arguments.length-2),e=2;e<arguments.length;e++)d[e-2]=arguments[e];return b.prototype[c].apply(a,d)}};var ta=function(a){if(Error.captureStackTrace)Error.captureStackTrace(this,ta);else{var b=Error().stack;b&&(this.stack=b)}a&&(this.message=String(a))};q(ta,Error);ta.prototype.name="CustomError";var ua;var va=function(a,b){a=a.split("%s");for(var c="",d=a.length-1,e=0;e<d;e++)c+=a[e]+(e<b.length?b[e]:"%s");ta.call(this,c+a[d])};q(va,ta);va.prototype.name="AssertionError"; -var wa=function(a,b,c,d){var e="Assertion failed";if(c){e+=": "+c;var f=d}else a&&(e+=": "+a,f=b);throw new va(""+e,f||[]);},r=function(a,b,c){a||wa("",null,b,Array.prototype.slice.call(arguments,2));return a},xa=function(a,b){throw new va("Failure"+(a?": "+a:""),Array.prototype.slice.call(arguments,1));},ya=function(a,b,c){"number"==typeof a||wa("Expected number but got %s: %s.",[n(a),a],b,Array.prototype.slice.call(arguments,2))},za=function(a,b,c){m(a)||wa("Expected string but got %s: %s.",[n(a), -a],b,Array.prototype.slice.call(arguments,2));return a},Aa=function(a,b,c){na(a)||wa("Expected object but got %s: %s.",[n(a),a],b,Array.prototype.slice.call(arguments,2))};var Ba=Array.prototype.indexOf?function(a,b){r(null!=a.length);return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if(m(a))return m(b)&&1==b.length?a.indexOf(b,0):-1;for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1},Ca=Array.prototype.forEach?function(a,b,c){r(null!=a.length);Array.prototype.forEach.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=m(a)?a.split(""):a,f=0;f<d;f++)f in e&&b.call(c,e[f],f,a)},Da=Array.prototype.filter?function(a,b){r(null!=a.length);return Array.prototype.filter.call(a, -b,void 0)}:function(a,b){for(var c=a.length,d=[],e=0,f=m(a)?a.split(""):a,h=0;h<c;h++)if(h in f){var p=f[h];b.call(void 0,p,h,a)&&(d[e++]=p)}return d},Fa=function(a,b){b=Ba(a,b);var c;(c=0<=b)&&Ea(a,b);return c},Ea=function(a,b){r(null!=a.length);Array.prototype.splice.call(a,b,1)},Ga=function(a,b){for(var c=1;c<arguments.length;c++){var d=arguments[c],e=d,f=n(e);if("array"==f||"object"==f&&"number"==typeof e.length){e=a.length||0;f=d.length||0;a.length=e+f;for(var h=0;h<f;h++)a[e+h]=d[h]}else a.push(d)}}, -Ia=function(a,b,c,d){r(null!=a.length);Array.prototype.splice.apply(a,Ha(arguments,1))},Ha=function(a,b,c){r(null!=a.length);return 2>=arguments.length?Array.prototype.slice.call(a,b):Array.prototype.slice.call(a,b,c)},Ka=function(a,b){a.sort(b||Ja)},Ja=function(a,b){return a>b?1:a<b?-1:0};var La=String.prototype.trim?function(a){return a.trim()}:function(a){return/^[\s\xa0]*([\s\S]*?)[\s\xa0]*$/.exec(a)[1]},Ta=function(a){if(!Ma.test(a))return a;-1!=a.indexOf("&")&&(a=a.replace(Na,"&"));-1!=a.indexOf("<")&&(a=a.replace(Oa,"<"));-1!=a.indexOf(">")&&(a=a.replace(Pa,">"));-1!=a.indexOf('"')&&(a=a.replace(Qa,"""));-1!=a.indexOf("'")&&(a=a.replace(Ra,"'"));-1!=a.indexOf("\x00")&&(a=a.replace(Sa,"�"));return a},Na=/&/g,Oa=/</g,Pa=/>/g,Qa=/"/g,Ra=/'/g,Sa=/\x00/g,Ma= -/[\x00&<>"']/,Va=function(a,b){var c=0;a=La(String(a)).split(".");b=La(String(b)).split(".");for(var d=Math.max(a.length,b.length),e=0;0==c&&e<d;e++){var f=a[e]||"",h=b[e]||"";do{f=/(\d*)(\D*)(.*)/.exec(f)||["","","",""];h=/(\d*)(\D*)(.*)/.exec(h)||["","","",""];if(0==f[0].length&&0==h[0].length)break;c=Ua(0==f[1].length?0:parseInt(f[1],10),0==h[1].length?0:parseInt(h[1],10))||Ua(0==f[2].length,0==h[2].length)||Ua(f[2],h[2]);f=f[3];h=h[3]}while(0==c)}return c},Ua=function(a,b){return a<b?-1:a>b?1: -0};var Wa;a:{var Xa=l.navigator;if(Xa){var Ya=Xa.userAgent;if(Ya){Wa=Ya;break a}}Wa=""}var u=function(a){return-1!=Wa.indexOf(a)};var Za=function(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b},$a="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),ab=function(a,b){for(var c,d,e=1;e<arguments.length;e++){d=arguments[e];for(c in d)a[c]=d[c];for(var f=0;f<$a.length;f++)c=$a[f],Object.prototype.hasOwnProperty.call(d,c)&&(a[c]=d[c])}};var bb=function(){var a=Wa,b="";u("Windows")?(b=/Windows (?:NT|Phone) ([0-9.]+)/,b=(a=b.exec(a))?a[1]:"0.0"):u("iPhone")&&!u("iPod")&&!u("iPad")||u("iPad")||u("iPod")?(b=/(?:iPhone|iPod|iPad|CPU)\s+OS\s+(\S+)/,b=(a=b.exec(a))&&a[1].replace(/_/g,".")):u("Macintosh")?(b=/Mac OS X ([0-9_.]+)/,b=(a=b.exec(a))?a[1].replace(/_/g,"."):"10"):u("Android")?(b=/Android\s+([^\);]+)(\)|;)/,b=(a=b.exec(a))&&a[1]):u("CrOS")&&(b=/(?:CrOS\s+(?:i686|x86_64)\s+([0-9.]+))/,b=(a=b.exec(a))&&a[1]);return b||""};var cb=function(a){cb[" "](a);return a};cb[" "]=la;var db=function(a,b,c){return Object.prototype.hasOwnProperty.call(a,b)?a[b]:a[b]=c(b)};var eb=u("Opera"),fb=u("Trident")||u("MSIE"),gb=u("Edge"),hb=u("Gecko")&&!(-1!=Wa.toLowerCase().indexOf("webkit")&&!u("Edge"))&&!(u("Trident")||u("MSIE"))&&!u("Edge"),ib=-1!=Wa.toLowerCase().indexOf("webkit")&&!u("Edge"),jb=function(){var a=l.document;return a?a.documentMode:void 0},kb; -a:{var lb="",mb=function(){var a=Wa;if(hb)return/rv:([^\);]+)(\)|;)/.exec(a);if(gb)return/Edge\/([\d\.]+)/.exec(a);if(fb)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(ib)return/WebKit\/(\S+)/.exec(a);if(eb)return/(?:Version)[ \/]?(\S+)/.exec(a)}();mb&&(lb=mb?mb[1]:"");if(fb){var nb=jb();if(null!=nb&&nb>parseFloat(lb)){kb=String(nb);break a}}kb=lb}var ob=kb,pb={},qb;var rb=l.document;qb=rb&&fb?jb()||("CSS1Compat"==rb.compatMode?parseInt(ob,10):5):void 0;var sb=Object.freeze||function(a){return a};var tb=function(){};var ub=function(a){if(a.classList)return a.classList;a=a.className;return m(a)&&a.match(/\S+/g)||[]},vb=function(a){a.classList?a=a.classList.contains("fullscreen"):(a=ub(a),a=0<=Ba(a,"fullscreen"));return a},wb=function(a){a.classList?a.classList.remove("fullscreen"):vb(a)&&(a.className=Da(ub(a),function(a){return"fullscreen"!=a}).join(" "))};var yb=function(){this.Fa=xb};yb.prototype.toString=function(){return"TrustedResourceUrl{}"};var xb={};var Ab=function(){this.da="";this.Da=zb};Ab.prototype.toString=function(){return"SafeUrl{"+this.da+"}"}; -var Bb=/^(?:audio\/(?:3gpp|3gpp2|aac|midi|mp4|mpeg|ogg|x-m4a|x-wav|webm)|image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|text\/csv|video\/(?:mpeg|mp4|ogg|webm|quicktime))$/i,Db=function(a){if(Bb.test(a.type)){var b=void 0!==l.URL&&void 0!==l.URL.createObjectURL?l.URL:void 0!==l.webkitURL&&void 0!==l.webkitURL.createObjectURL?l.webkitURL:void 0!==l.createObjectURL?l:null;if(null==b)throw Error("This browser doesn't seem to support blob URLs");a=b.createObjectURL(a)}else a="about:invalid#zClosurez";return Cb(a)}, -Eb=/^data:([^;,]*);base64,[a-z0-9+\/]+=*$/i,Fb=function(a){var b=a.match(Eb);b=b&&Bb.test(b[1]);return Cb(b?a:"about:invalid#zClosurez")},zb={},Cb=function(a){var b=new Ab;b.da=a;return b};Cb("about:blank");var Gb=function(a,b){this.width=a;this.height=b};g=Gb.prototype;g.clone=function(){return new Gb(this.width,this.height)};g.toString=function(){return"("+this.width+" x "+this.height+")"};g.aspectRatio=function(){return this.width/this.height};g.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};g.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this}; -g.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};var Jb=function(a){return a?new Hb(Ib(a)):ua||(ua=new Hb)},Kb=function(a){return m(a)?document.getElementById(a):a},Ib=function(a){r(a,"Node cannot be null or undefined.");return 9==a.nodeType?a:a.ownerDocument||a.document},Hb=function(a){this.a=a||l.document||document};Hb.prototype.B=function(){return m(void 0)?this.a.getElementById(void 0):void 0};var Lb;(Lb=!fb)||(Lb=9<=Number(qb));var Mb=Lb,Nb=fb&&!db(pb,"9",function(){return 0<=Va(ob,"9")}),Ob=function(){if(!l.addEventListener||!Object.defineProperty)return!1;var a=!1,b=Object.defineProperty({},"passive",{get:function(){a=!0}});l.addEventListener("test",la,b);l.removeEventListener("test",la,b);return a}();var v=function(a,b){this.type=a;this.a=this.target=b;this.f=!1;this.ta=!0};v.prototype.h=function(){this.f=!0;this.ta=!1};var Pb=function(a,b){v.call(this,a?a.type:"");this.relatedTarget=this.a=this.target=null;this.button=this.screenY=this.screenX=this.clientY=this.clientX=0;this.key="";this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1;this.pointerId=0;this.pointerType="";this.j=null;a&&this.init(a,b)};q(Pb,v);var Qb=sb({2:"touch",3:"pen",4:"mouse"}); -Pb.prototype.init=function(a,b){var c=this.type=a.type,d=a.changedTouches?a.changedTouches[0]:null;this.target=a.target||a.srcElement;this.a=b;if(b=a.relatedTarget){if(hb){a:{try{cb(b.nodeName);var e=!0;break a}catch(f){}e=!1}e||(b=null)}}else"mouseover"==c?b=a.fromElement:"mouseout"==c&&(b=a.toElement);this.relatedTarget=b;null===d?(this.clientX=void 0!==a.clientX?a.clientX:a.pageX,this.clientY=void 0!==a.clientY?a.clientY:a.pageY,this.screenX=a.screenX||0,this.screenY=a.screenY||0):(this.clientX= -void 0!==d.clientX?d.clientX:d.pageX,this.clientY=void 0!==d.clientY?d.clientY:d.pageY,this.screenX=d.screenX||0,this.screenY=d.screenY||0);this.button=a.button;this.key=a.key||"";this.ctrlKey=a.ctrlKey;this.altKey=a.altKey;this.shiftKey=a.shiftKey;this.metaKey=a.metaKey;this.pointerId=a.pointerId||0;this.pointerType=m(a.pointerType)?a.pointerType:Qb[a.pointerType]||"";this.j=a;a.defaultPrevented&&this.h()}; -Pb.prototype.h=function(){Pb.R.h.call(this);var a=this.j;if(a.preventDefault)a.preventDefault();else if(a.returnValue=!1,Nb)try{if(a.ctrlKey||112<=a.keyCode&&123>=a.keyCode)a.keyCode=-1}catch(b){}};var Rb="closure_listenable_"+(1E6*Math.random()|0),Sb=0;var Tb=function(a,b,c,d,e){this.listener=a;this.a=null;this.src=b;this.type=c;this.capture=!!d;this.ba=e;this.key=++Sb;this.O=this.Z=!1},Ub=function(a){a.O=!0;a.listener=null;a.a=null;a.src=null;a.ba=null};var Vb=function(a){this.src=a;this.a={};this.f=0};Vb.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.a[f];a||(a=this.a[f]=[],this.f++);var h=Wb(a,b,d,e);-1<h?(b=a[h],c||(b.Z=!1)):(b=new Tb(b,this.src,f,!!d,e),b.Z=c,a.push(b));return b};var Xb=function(a,b){var c=b.type;c in a.a&&Fa(a.a[c],b)&&(Ub(b),0==a.a[c].length&&(delete a.a[c],a.f--))},Wb=function(a,b,c,d){for(var e=0;e<a.length;++e){var f=a[e];if(!f.O&&f.listener==b&&f.capture==!!c&&f.ba==d)return e}return-1};var Yb="closure_lm_"+(1E6*Math.random()|0),Zb={},$b=0,bc=function(a,b,c,d,e){if(d&&d.once)return ac(a,b,c,d,e);if(ma(b)){for(var f=0;f<b.length;f++)bc(a,b[f],c,d,e);return null}c=cc(c);a&&a[Rb]?(d=na(d)?!!d.capture:!!d,dc(a),a=a.w.add(String(b),c,!1,d,e)):a=ec(a,b,c,!1,d,e);return a},ec=function(a,b,c,d,e,f){if(!b)throw Error("Invalid event type");var h=na(e)?!!e.capture:!!e,p=fc(a);p||(a[Yb]=p=new Vb(a));c=p.add(b,c,d,h,f);if(c.a)return c;d=gc();c.a=d;d.src=a;d.listener=c;if(a.addEventListener)Ob|| -(e=h),void 0===e&&(e=!1),a.addEventListener(b.toString(),d,e);else if(a.attachEvent)a.attachEvent(hc(b.toString()),d);else if(a.addListener&&a.removeListener)r("change"===b,"MediaQueryList only has a change event"),a.addListener(d);else throw Error("addEventListener and attachEvent are unavailable.");$b++;return c},gc=function(){var a=ic,b=Mb?function(c){return a.call(b.src,b.listener,c)}:function(c){c=a.call(b.src,b.listener,c);if(!c)return c};return b},ac=function(a,b,c,d,e){if(ma(b)){for(var f= -0;f<b.length;f++)ac(a,b[f],c,d,e);return null}c=cc(c);return a&&a[Rb]?a.w.add(String(b),c,!0,na(d)?!!d.capture:!!d,e):ec(a,b,c,!0,d,e)},jc=function(a,b,c,d,e){if(ma(b))for(var f=0;f<b.length;f++)jc(a,b[f],c,d,e);else(d=na(d)?!!d.capture:!!d,c=cc(c),a&&a[Rb])?(a=a.w,b=String(b).toString(),b in a.a&&(f=a.a[b],c=Wb(f,c,d,e),-1<c&&(Ub(f[c]),Ea(f,c),0==f.length&&(delete a.a[b],a.f--)))):a&&(a=fc(a))&&(b=a.a[b.toString()],a=-1,b&&(a=Wb(b,c,d,e)),(c=-1<a?b[a]:null)&&kc(c))},kc=function(a){if("number"!=typeof a&& -a&&!a.O){var b=a.src;if(b&&b[Rb])Xb(b.w,a);else{var c=a.type,d=a.a;b.removeEventListener?b.removeEventListener(c,d,a.capture):b.detachEvent?b.detachEvent(hc(c),d):b.addListener&&b.removeListener&&b.removeListener(d);$b--;(c=fc(b))?(Xb(c,a),0==c.f&&(c.src=null,b[Yb]=null)):Ub(a)}}},hc=function(a){return a in Zb?Zb[a]:Zb[a]="on"+a},mc=function(a,b,c,d){var e=!0;if(a=fc(a))if(b=a.a[b.toString()])for(b=b.concat(),a=0;a<b.length;a++){var f=b[a];f&&f.capture==c&&!f.O&&(f=lc(f,d),e=e&&!1!==f)}return e}, -lc=function(a,b){var c=a.listener,d=a.ba||a.src;a.Z&&kc(a);return c.call(d,b)},ic=function(a,b){if(a.O)return!0;if(!Mb){if(!b)a:{b=["window","event"];for(var c=l,d=0;d<b.length;d++)if(c=c[b[d]],null==c){b=null;break a}b=c}d=b;b=new Pb(d,this);c=!0;if(!(0>d.keyCode||void 0!=d.returnValue)){a:{var e=!1;if(0==d.keyCode)try{d.keyCode=-1;break a}catch(h){e=!0}if(e||void 0==d.returnValue)d.returnValue=!0}d=[];for(e=b.a;e;e=e.parentNode)d.push(e);a=a.type;for(e=d.length-1;0<=e;e--){b.a=d[e];var f=mc(d[e], -a,!0,b);c=c&&f}for(e=0;e<d.length;e++)b.a=d[e],f=mc(d[e],a,!1,b),c=c&&f}return c}return lc(a,new Pb(b,this))},fc=function(a){a=a[Yb];return a instanceof Vb?a:null},nc="__closure_events_fn_"+(1E9*Math.random()>>>0),cc=function(a){r(a,"Listener can not be null.");if("function"==n(a))return a;r(a.handleEvent,"An object listener must have handleEvent method.");a[nc]||(a[nc]=function(b){return a.handleEvent(b)});return a[nc]};var oc=function(a){this.a=a;this.f={}};q(oc,tb);var pc=[],qc=function(a,b,c,d){ma(c)||(c&&(pc[0]=c.toString()),c=pc);for(var e=0;e<c.length;e++){var f=bc(b,c[e],d||a.handleEvent,!1,a.a||a);if(!f)break;a.f[f.key]=f}},sc=function(a,b,c){rc(a,b,"o",c,void 0)},rc=function(a,b,c,d,e,f){if(ma(c))for(var h=0;h<c.length;h++)rc(a,b,c[h],d,e,f);else(b=ac(b,c,d||a.handleEvent,e,f||a.a||a))&&(a.f[b.key]=b)};oc.prototype.handleEvent=function(){throw Error("EventHandler.handleEvent not implemented");};var w=function(){this.w=new Vb(this);this.Ba=this;this.U=null};q(w,tb);w.prototype[Rb]=!0;w.prototype.ca=function(a){this.U=a};w.prototype.removeEventListener=function(a,b,c,d){jc(this,a,b,c,d)}; -var x=function(a,b){dc(a);var c=a.U;if(c){var d=[];for(var e=1;c;c=c.U)d.push(c),r(1E3>++e,"infinite loop")}a=a.Ba;c=b.type||b;m(b)?b=new v(b,a):b instanceof v?b.target=b.target||a:(e=b,b=new v(c,a),ab(b,e));e=!0;if(d)for(var f=d.length-1;0<=f;f--){var h=b.a=d[f];e=tc(h,c,!0,b)&&e}h=b.a=a;e=tc(h,c,!0,b)&&e;e=tc(h,c,!1,b)&&e;if(d)for(f=0;f<d.length;f++)h=b.a=d[f],e=tc(h,c,!1,b)&&e;return e},tc=function(a,b,c,d){b=a.w.a[String(b)];if(!b)return!0;b=b.concat();for(var e=!0,f=0;f<b.length;++f){var h=b[f]; -if(h&&!h.O&&h.capture==c){var p=h.listener,t=h.ba||h.src;h.Z&&Xb(a.w,h);e=!1!==p.call(t,d)&&e}}return e&&0!=d.ta},dc=function(a){r(a.w,"Event target is not initialized. Did you call the superclass (goog.events.EventTarget) constructor?")};var z=function(a,b){this.a=a|0;this.f=b|0},uc={},vc={},A=function(a){return db(uc,a,function(a){return new z(a,0>a?-1:0)})},wc=function(a){var b=a|0;r(a===b,"value should be a 32-bit integer");return-128<=b&&128>b?A(b):new z(b,0>b?-1:0)},D=function(a){return isNaN(a)?A(0):a<=-xc?B():a+1>=xc?yc():0>a?C(D(-a)):new z(a%4294967296|0,a/4294967296|0)},E=function(a,b){return new z(a,b)},zc=function(a,b){if(0==a.length)throw Error("number format error: empty string");b=b||10;if(2>b||36<b)throw Error("radix out of range: "+ -b);if("-"==a.charAt(0))return C(zc(a.substring(1),b));if(0<=a.indexOf("-"))throw Error('number format error: interior "-" character: '+a);for(var c=D(Math.pow(b,8)),d=A(0),e=0;e<a.length;e+=8){var f=Math.min(8,a.length-e),h=parseInt(a.substring(e,e+f),b);8>f?(f=D(Math.pow(b,f)),d=F(d,f).add(D(h))):(d=F(d,c),d=d.add(D(h)))}return d},xc=4294967296*4294967296/2,yc=function(){return db(vc,1,function(){return E(-1,2147483647)})},B=function(){return db(vc,2,function(){return E(0,-2147483648)})},Ac=function(){return db(vc, -6,function(){return wc(16777216)})};z.prototype.toString=function(a){a=a||10;if(2>a||36<a)throw Error("radix out of range: "+a);if(Bc(this))return"0";if(0>this.f){if(this.s(B())){var b=D(a),c=Cc(this,b);b=Dc(F(c,b),this);return c.toString(a)+b.a.toString(a)}return"-"+C(this).toString(a)}c=D(Math.pow(a,6));b=this;for(var d="";;){var e=Cc(b,c),f=(Dc(b,F(e,c)).a>>>0).toString(a);b=e;if(Bc(b))return f+d;for(;6>f.length;)f="0"+f;d=""+f+d}}; -var Ec=function(a){return 0<=a.a?a.a:4294967296+a.a},Bc=function(a){return 0==a.f&&0==a.a};z.prototype.s=function(a){return this.f==a.f&&this.a==a.a};var Gc=function(a){var b=Ac();return 0>Fc(a,b)},Fc=function(a,b){if(a.s(b))return 0;var c=0>a.f,d=0>b.f;return c&&!d?-1:!c&&d?1:0>Dc(a,b).f?-1:1},C=function(a){return a.s(B())?B():E(~a.a,~a.f).add(A(1))}; -z.prototype.add=function(a){var b=this.f>>>16,c=this.f&65535,d=this.a>>>16,e=a.f>>>16,f=a.f&65535,h=a.a>>>16;a=(this.a&65535)+(a.a&65535);h=(a>>>16)+(d+h);d=h>>>16;d+=c+f;b=(d>>>16)+(b+e)&65535;return E((h&65535)<<16|a&65535,b<<16|d&65535)}; -var Dc=function(a,b){return a.add(C(b))},F=function(a,b){if(Bc(a)||Bc(b))return A(0);if(a.s(B()))return 1==(b.a&1)?B():A(0);if(b.s(B()))return 1==(a.a&1)?B():A(0);if(0>a.f)return 0>b.f?F(C(a),C(b)):C(F(C(a),b));if(0>b.f)return C(F(a,C(b)));if(Gc(a)&&Gc(b))return D((4294967296*a.f+Ec(a))*(4294967296*b.f+Ec(b)));var c=a.f>>>16,d=a.f&65535,e=a.a>>>16;a=a.a&65535;var f=b.f>>>16,h=b.f&65535,p=b.a>>>16;b=b.a&65535;var t=a*b;var y=(t>>>16)+e*b;var K=y>>>16;y=(y&65535)+a*p;K+=y>>>16;K+=d*b;var J=K>>>16;K= -(K&65535)+e*p;J+=K>>>16;K=(K&65535)+a*h;J=J+(K>>>16)+(c*b+d*p+e*h+a*f)&65535;return E((y&65535)<<16|t&65535,J<<16|K&65535)},Cc=function(a,b){if(Bc(b))throw Error("division by zero");if(Bc(a))return A(0);if(a.s(B())){if(b.s(A(1))||b.s(A(-1)))return B();if(b.s(B()))return A(1);var c=1;if(0==c)c=a;else{var d=a.f;c=32>c?E(a.a>>>c|d<<32-c,d>>c):E(d>>c-32,0<=d?0:-1)}c=Hc(Cc(c,b),1);if(c.s(A(0)))return 0>b.f?A(1):A(-1);a=Dc(a,F(b,c));return c.add(Cc(a,b))}if(b.s(B()))return A(0);if(0>a.f)return 0>b.f?Cc(C(a), -C(b)):C(Cc(C(a),b));if(0>b.f)return C(Cc(a,C(b)));for(d=A(0);0<=Fc(a,b);){c=Math.max(1,Math.floor((4294967296*a.f+Ec(a))/(4294967296*b.f+Ec(b))));var e=Math.ceil(Math.log(c)/Math.LN2);e=48>=e?1:Math.pow(2,e-48);for(var f=D(c),h=F(f,b);0>h.f||0<Fc(h,a);)c-=e,f=D(c),h=F(f,b);Bc(f)&&(f=A(1));d=d.add(f);a=Dc(a,h)}return d};z.prototype.and=function(a){return E(this.a&a.a,this.f&a.f)};z.prototype.or=function(a){return E(this.a|a.a,this.f|a.f)};z.prototype.xor=function(a){return E(this.a^a.a,this.f^a.f)}; -var Hc=function(a,b){b&=63;if(0==b)return a;var c=a.a;return 32>b?E(c<<b,a.f<<b|c>>>32-b):E(0,c<<b-32)},Ic=function(a,b){b&=63;if(0==b)return a;var c=a.f;return 32>b?E(a.a>>>b|c<<32-b,c>>>b):32==b?E(c,0):E(c>>>b-32,0)};var Jc=function(a,b){this.ea=a;this.a={};for(a=0;a<b.length;a++){var c=b[a];this.a[c.a]=c}},Kc=function(a){a=Za(a.a);Ka(a,function(a,c){return a.a-c.a});return a},Lc=function(a,b){r(!/[^0-9]/.test(b));return a.a[parseInt(b,10)]||null};var Mc=function(a,b,c){this.i=a;r(!/[^0-9]/.test(b));this.a=b;this.m=!!c.fa;this.h=!!c.l;this.f=c.b;this.j=c.type;this.w=!1;switch(this.f){case 3:case 4:case 6:case 16:case 18:case 2:case 1:this.w=!0}},Nc=function(a){return 11==a.f||10==a.f};var G=function(){this.u={};this.f=this.c().a;this.a=null};G.prototype.has=function(a){r(a.i.prototype.c()==this.c(),"The current message does not contain the given field");return null!=this.u[a.a]};var Oc=function(a,b){r(b.i.prototype.c()==a.c(),"The current message does not contain the given field");b=b.a;return a.f[b].h?null!=a.u[b]?a.u[b].length:0:null!=a.u[b]?1:0}; -G.prototype.get=function(a,b){r(a.i.prototype.c()==this.c(),"The current message does not contain the given field");return Pc(this,a.a,b)};G.prototype.set=function(a,b){r(a.i.prototype.c()==this.c(),"The current message does not contain the given field");H(this,a.a,b)};G.prototype.add=function(a,b){r(a.i.prototype.c()==this.c(),"The current message does not contain the given field");Qc(this,a.a,b)}; -G.prototype.s=function(a){if(!a||this.constructor!=a.constructor)return!1;for(var b=Kc(this.c()),c=0;c<b.length;c++){var d=b[c],e=d.a;if(null!=this.u[e]!=(null!=a.u[e]))return!1;if(null!=this.u[e]){var f=Nc(d),h=Rc(this,e);e=Rc(a,e);if(d.h){if(h.length!=e.length)return!1;for(d=0;d<h.length;d++){var p=h[d],t=e[d];if(f?!p.s(t):p!=t)return!1}}else if(f?!h.s(e):h!=e)return!1}}return!0}; -var Sc=function(a,b){r(a.constructor==b.constructor,"The source message must have the same type.");for(var c=Kc(a.c()),d=0;d<c.length;d++){var e=c[d],f=e.a;if(null!=b.u[f]){a.a&&delete a.a[e.a];var h=Nc(e);if(e.h){e=Rc(b,f)||[];for(var p=0;p<e.length;p++)Qc(a,f,h?e[p].clone():e[p])}else e=Rc(b,f),h?(h=Rc(a,f))?Sc(h,e):H(a,f,e.clone()):H(a,f,e)}}}; -G.prototype.clone=function(){var a=new this.constructor;r(a.constructor==this.constructor,"The source message must have the same type.");a!=this&&(a.u={},a.a&&(a.a={}),Sc(a,this));return a}; -var Rc=function(a,b){a=a.u[b];return null==a?null:a},Pc=function(a,b,c){var d=Rc(a,b);return a.f[b].h?(a=c||0,r(0<=a&&a<d.length,"Given index %s is out of bounds. Repeated field length: %s",a,d.length),d[a]):d},H=function(a,b,c){var d=a.f[b];14==d.f?ya(c):r(Object(c).constructor==d.j);a.u[b]=c;a.a&&(a.a[b]=c)},Qc=function(a,b,c){var d=a.f[b];14==d.f?ya(c):r(Object(c).constructor==d.j);a.u[b]||(a.u[b]=[]);a.u[b].push(c);a.a&&delete a.a[b]},I=function(a,b){var c=[],d;for(d in b)0!=d&&c.push(new Mc(a, -d,b[d]));return new Jc(a,c)};var Tc=function(){};Tc.prototype.j=function(a,b){Nc(a)&&Uc(this,b)};Tc.prototype.h=function(a,b){if(Nc(a))return b instanceof G||(a=new (a.j.prototype.c().ea),Vc(this,a,b),r(a instanceof G),b=a),b;if(14==a.f)return m(b)&&Xc.test(b)&&(a=Number(b),0<a)?a:b;if(!a.w)return b;a=a.j;if(a===String){if("number"==typeof b)return String(b)}else if(a===Number&&m(b)&&("Infinity"===b||"-Infinity"===b||"NaN"===b||Xc.test(b)))return Number(b);return b};var Xc=/^-?[0-9]+$/;var Yc={Gd:!0},Zc={Jd:!0},$c={Id:!0},ad={Hd:!0},L=function(){throw Error("Do not instantiate directly");};L.prototype.a=null;L.prototype.toString=function(){return this.$};var bd=function(){L.call(this)};q(bd,L);bd.prototype.H=Yc;var cd=function(){L.call(this)};q(cd,L);cd.prototype.H=Zc;cd.prototype.a=1;var dd=function(){L.call(this)};q(dd,L);dd.prototype.H=$c;dd.prototype.a=1;var hd=function(a,b){r(a,"Soy template may not be null.");b=a(b||ed,void 0,void 0);a=Jb().a.createElement("DIV");b=fd(b);var c=b.match(gd);r(!c,"This template starts with a %s, which cannot be a child of a <div>, as required by soy internals. Consider using goog.soy.renderElement instead.\nTemplate output: %s",c&&c[0],b);a.innerHTML=b;1==a.childNodes.length&&(b=a.firstChild,1==b.nodeType&&(a=b));return a},fd=function(a){if(!na(a))return String(a);if(a instanceof L){if(a.H===Yc)return za(a.$);if(a.H=== -ad)return Ta(a.$)}xa("Soy template output is unsafe for use as HTML: "+a);return"zSoyz"},gd=/^<(body|caption|col|colgroup|head|html|tr|td|th|tbody|thead|tfoot)>/i,ed={};var id=function(){};id.a=void 0;id.S=function(){return id.a?id.a:id.a=new id};id.prototype.a=0;var M=function(a){w.call(this);this.T=a||Jb();this.N=null;this.A=!1;this.f=null;this.ha=void 0;this.M=this.h=this.j=null};q(M,w);M.prototype.ja=id.S();M.prototype.B=function(){return this.f};var jd=function(a){a.ha||(a.ha=new oc(a));return r(a.ha)},kd=function(a,b){if(a==b)throw Error("Unable to set parent component");var c;if(c=b&&a.j&&a.N){var d=a.j;c=a.N;d.M&&c?(d=d.M,c=(null!==d&&c in d?d[c]:void 0)||null):c=null}if(c&&a.j!=b)throw Error("Unable to set parent component");a.j=b;M.R.ca.call(a,b)}; -M.prototype.ca=function(a){if(this.j&&this.j!=a)throw Error("Method not supported");M.R.ca.call(this,a)};M.prototype.aa=function(){this.f=this.T.a.createElement("DIV")};M.prototype.render=function(a){if(this.A)throw Error("Component already rendered");this.f||this.aa();a?a.insertBefore(this.f,null):this.T.a.body.appendChild(this.f);this.j&&!this.j.A||this.v()};M.prototype.v=function(){this.A=!0;ld(this,function(a){!a.A&&a.B()&&a.v()})}; -var md=function(a,b){var c=a.h?a.h.length:0;r(!!b,"Provided element must not be null.");if(b.A&&!a.A)throw Error("Component already rendered");if(0>c||c>(a.h?a.h.length:0))throw Error("Child component index out of bounds");a.M&&a.h||(a.M={},a.h=[]);if(b.j==a){var d=b.N||(b.N=":"+(b.ja.a++).toString(36));a.M[d]=b;Fa(a.h,b)}else{d=a.M;var e=b.N||(b.N=":"+(b.ja.a++).toString(36));if(null!==d&&e in d)throw Error('The object already contains the key "'+e+'"');d[e]=b}kd(b,a);Ia(a.h,c,0,b);b.A&&a.A&&b.j== -a?(a=a.f,c=a.childNodes[c]||null,c!=b.B()&&a.insertBefore(b.B(),c)):a.A&&!b.A&&b.f&&b.f.parentNode&&1==b.f.parentNode.nodeType&&b.v()},ld=function(a,b){a.h&&Ca(a.h,b,void 0)};var nd=function(a){function b(a){this.$=a}b.prototype=a.prototype;return function(a,d){a=new b(String(a));void 0!==d&&(a.a=d);return a}}(bd),sd=function(a){return null!=a&&a.H===Yc?(r(a.constructor===bd),String(String(a.$).replace(od,"").replace(pd,"<")).replace(qd,rd)):Ta(String(a))},td=function(a,b,c){a||(a=c instanceof Function?c.displayName||c.name||"unknown type name":c instanceof Object?c.constructor.displayName||c.constructor.name||Object.prototype.toString.call(c):null===c?"null":typeof c, -xa("expected param "+b+" of type !goog.soy.data.UnsanitizedText|string"+(", but got "+a)+"."));return c},ud={"\x00":"�","\t":"	","\n":" ","\x0B":"","\f":"","\r":" "," ":" ",'"':""","&":"&","'":"'","-":"-","/":"/","<":"<","=":"=",">":">","`":"`","\u0085":"…","\u00a0":" ","\u2028":"
","\u2029":"
"},rd=function(a){return ud[a]},vd={"\x00":"%00","\u0001":"%01","\u0002":"%02","\u0003":"%03","\u0004":"%04","\u0005":"%05", -"\u0006":"%06","\u0007":"%07","\b":"%08","\t":"%09","\n":"%0A","\x0B":"%0B","\f":"%0C","\r":"%0D","\u000e":"%0E","\u000f":"%0F","\u0010":"%10","\u0011":"%11","\u0012":"%12","\u0013":"%13","\u0014":"%14","\u0015":"%15","\u0016":"%16","\u0017":"%17","\u0018":"%18","\u0019":"%19","\u001a":"%1A","\u001b":"%1B","\u001c":"%1C","\u001d":"%1D","\u001e":"%1E","\u001f":"%1F"," ":"%20",'"':"%22","'":"%27","(":"%28",")":"%29","<":"%3C",">":"%3E","\\":"%5C","{":"%7B","}":"%7D","\u007f":"%7F","\u0085":"%C2%85", -"\u00a0":"%C2%A0","\u2028":"%E2%80%A8","\u2029":"%E2%80%A9","\uff01":"%EF%BC%81","\uff03":"%EF%BC%83","\uff04":"%EF%BC%84","\uff06":"%EF%BC%86","\uff07":"%EF%BC%87","\uff08":"%EF%BC%88","\uff09":"%EF%BC%89","\uff0a":"%EF%BC%8A","\uff0b":"%EF%BC%8B","\uff0c":"%EF%BC%8C","\uff0f":"%EF%BC%8F","\uff1a":"%EF%BC%9A","\uff1b":"%EF%BC%9B","\uff1d":"%EF%BC%9D","\uff1f":"%EF%BC%9F","\uff20":"%EF%BC%A0","\uff3b":"%EF%BC%BB","\uff3d":"%EF%BC%BD"},wd=function(a){return vd[a]},qd=/[\x00\x22\x27\x3c\x3e]/g,xd=/[\x00- \x22\x27-\x29\x3c\x3e\\\x7b\x7d\x7f\x85\xa0\u2028\u2029\uff01\uff03\uff04\uff06-\uff0c\uff0f\uff1a\uff1b\uff1d\uff1f\uff20\uff3b\uff3d]/g, -yd=/^(?![^#?]*\/(?:\.|%2E){2}(?:[\/?#]|$))(?:(?:https?|mailto):|[^&:\/?#]*(?:[\/?#]|$))/i,od=/<(?:!|\/?([a-zA-Z][a-zA-Z0-9:\-]*))(?:[^>'"]|"[^"]*"|'[^']*')*>/g,pd=/</g;var N=function(){G.call(this)};q(N,G);var zd=null,Ad={ud:0,oc:1,KEEP:2,Fb:3,nc:4},Bd={yd:0,Xb:1,hd:2,ic:3,qc:4},O=function(){G.call(this)};q(O,G);var Cd=null,Dd={rd:0,Pb:1,OPENED:2,Kc:3,xc:4,Jc:5,Bb:6,pd:7,Tc:8,Ib:9,Yc:10,xb:11,lc:12},Ed=function(){G.call(this)};q(Ed,G);var Fd=null,Gd=function(){G.call(this)};q(Gd,G);var Hd=null,Id=function(){G.call(this)};q(Id,G);var Jd=null,Kd=function(){G.call(this)};q(Kd,G);var Ld=null,Md=function(){G.call(this)};q(Md,G);var Nd=null,Od=function(){G.call(this)}; -q(Od,G);var Pd=null,Qd={wd:0,jd:1,kd:2,gd:3,nd:4,ld:5,md:6,Gb:7,Xc:8},Rd={xd:0,cc:1,xa:2,Aa:3,za:4,Ec:5},Sd={td:0,Wc:1,Yb:2,kc:3},Td=function(){G.call(this)};q(Td,G);var Ud=null,Vd={sd:0,Bc:1,Rc:2},Wd=function(){G.call(this)};q(Wd,G);var Xd=null,Yd={Kb:0,Jb:1,ad:2}; -N.prototype.c=function(){var a=zd;a||(zd=a=I(N,{0:{name:"InkEvent",g:"logs.proto.research.ink.InkEvent"},1:{name:"host",b:14,defaultValue:0,type:Ad},2:{name:"event_type",b:14,defaultValue:0,type:Bd},3:{name:"document_event",b:11,type:O},4:{name:"toolbar_event",b:11,type:Od},5:{name:"engine_event",b:11,type:Td},6:{name:"gms_event",b:11,type:Wd}}));return a};N.c=N.prototype.c; -O.prototype.c=function(){var a=Cd;a||(Cd=a=I(O,{0:{name:"DocumentEvent",F:N,g:"logs.proto.research.ink.InkEvent.DocumentEvent"},1:{name:"event_type",b:14,defaultValue:0,type:Dd},2:{name:"opened_event",b:11,type:Ed},3:{name:"open_cancelled_event",b:11,type:Gd},4:{name:"error_code",b:3,type:String},5:{name:"brix_error_code",b:3,type:String},6:{name:"collaborator_joined_event",b:11,type:Id},7:{name:"document_state",b:11,type:Kd}}));return a};O.c=O.prototype.c; -Ed.prototype.c=function(){var a=Fd;a||(Fd=a=I(Ed,{0:{name:"OpenedEvent",F:O,g:"logs.proto.research.ink.InkEvent.DocumentEvent.OpenedEvent"},1:{name:"millis_until_first_byte_loaded",b:3,type:String},2:{name:"millis_until_editable",b:3,type:String},3:{name:"missing_document_bounds",b:8,type:Boolean},4:{name:"was_opened_by_cosmoid",b:8,type:Boolean},5:{name:"active_users",b:3,type:String}}));return a};Ed.c=Ed.prototype.c; -Gd.prototype.c=function(){var a=Hd;a||(Hd=a=I(Gd,{0:{name:"OpenCancelledEvent",F:O,g:"logs.proto.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent"},1:{name:"time_until_cancelled",b:3,type:String}}));return a};Gd.c=Gd.prototype.c;Id.prototype.c=function(){var a=Jd;a||(Jd=a=I(Id,{0:{name:"CollaboratorJoined",F:O,g:"logs.proto.research.ink.InkEvent.DocumentEvent.CollaboratorJoined"},1:{name:"is_me",b:8,type:Boolean}}));return a};Id.c=Id.prototype.c; -Kd.prototype.c=function(){var a=Ld;a||(Ld=a=I(Kd,{0:{name:"DocumentState",F:O,g:"logs.proto.research.ink.InkEvent.DocumentEvent.DocumentState"},1:{name:"stroke_count",b:3,type:String},2:{name:"text_field",l:!0,b:11,type:Md},3:{name:"sticker_count",b:3,type:String}}));return a};Kd.c=Kd.prototype.c; -Md.prototype.c=function(){var a=Nd;a||(Nd=a=I(Md,{0:{name:"TextField",F:Kd,g:"logs.proto.research.ink.InkEvent.DocumentEvent.DocumentState.TextField"},1:{name:"character_count",b:3,type:String},2:{name:"line_count",b:3,type:String}}));return a};Md.c=Md.prototype.c; -Od.prototype.c=function(){var a=Pd;a||(Pd=a=I(Od,{0:{name:"ToolbarEvent",F:N,g:"logs.proto.research.ink.InkEvent.ToolbarEvent"},1:{name:"tool_event_type",b:14,defaultValue:0,type:Qd},2:{name:"tool_type",b:14,defaultValue:0,type:Rd},3:{name:"expand_method",b:14,defaultValue:0,type:Sd},4:{name:"color",b:5,type:Number}}));return a};Od.c=Od.prototype.c; -Td.prototype.c=function(){var a=Ud;a||(Ud=a=I(Td,{0:{name:"EngineEvent",F:N,g:"logs.proto.research.ink.InkEvent.EngineEvent"},1:{name:"engine_event_type",b:14,defaultValue:0,type:Vd},2:{name:"error_code",b:3,type:String}}));return a};Td.c=Td.prototype.c; -Wd.prototype.c=function(){var a=Xd;a||(Xd=a=I(Wd,{0:{name:"GmsEvent",F:N,g:"logs.proto.research.ink.InkEvent.GmsEvent"},1:{name:"gms_event_type",b:14,defaultValue:0,type:Yd},2:{name:"time_since_connect_start",b:3,type:String},3:{name:"failure_has_resolution",b:8,type:Boolean},4:{name:"gms_error_code",b:3,type:String}}));return a};Wd.c=Wd.prototype.c;var Zd=function(){this.a=[];this.i={value:0,length:0};this.w={value:A(0),length:0};this.f=new DataView(new ArrayBuffer(8))};q(Zd,Tc); -var Uc=function(a,b){if(null==b)return[];a.a=[];for(var c=Kc(b.c()),d=0;d<c.length;d++){var e=c[d];if(b.has(e))if(e.h)if(e.m){var f=a,h=b,p=e;e=f.a;P(f,p.a<<3|2);for(var t=e.length,y=0,K=Oc(h,p);y<K;y++){var J=h.get(p,y);f.j(p,J,!0)}h=e.splice(t,e.length-t);P(f,h.length);e.splice.apply(e,[e.length,0].concat(h))}else for(f=0,h=Oc(b,e);f<h;f++)p=b.get(e,f),a.j(e,p);else a.j(e,b.get(e))}return a.a}; -Zd.prototype.j=function(a,b,c){if(c=!c){a:{switch(a.f){default:c=!1;break a;case 17:case 18:case 8:case 3:case 14:case 5:case 13:case 4:c=0;break;case 6:case 16:case 1:c=1;break;case 9:case 12:case 11:c=2;break;case 10:c=3;break;case 7:case 15:case 2:c=5}P(this,a.a<<3|c);c=!0}c=!c}if(!c)switch(a.f){default:throw Error("Unknown field type "+a.f);case 17:P(this,b<<1^-(b>>>31));break;case 18:a=zc(b);a=Hc(a,1).xor(C(Ic(a,63)));$d(this,a);break;case 8:P(this,b?1:0);break;case 5:0<b?P(this,b):$d(this,wc(b)); -break;case 3:case 4:$d(this,zc(b));break;case 14:case 13:P(this,b);break;case 6:case 16:ae(this,zc(b),8);break;case 1:this.f.setFloat64(0,b,!0);for(a=0;8>a;a++)this.a.push(this.f.getUint8(a));break;case 9:if(null!=b)for(a=unescape(encodeURIComponent(b)),P(this,a.length),b=0;b<a.length;b++)this.a.push(a.charCodeAt(b));break;case 12:if(null!=b)for(P(this,b.length),a=0;a<b.length;a++)this.a.push(b.charCodeAt(a));break;case 10:b=Uc(new Zd,b);Ga(this.a,b);P(this,a.a<<3|4);break;case 11:b=Uc(new Zd,b); -P(this,b.length);Ga(this.a,b);break;case 7:ae(this,D(b),4);break;case 15:ae(this,wc(b),4);break;case 2:for(this.f.setFloat32(0,b,!0),a=0;4>a;a++)this.a.push(this.f.getUint8(a))}}; -var Vc=function(a,b,c){if(null!=c){c instanceof ArrayBuffer&&(c=new Uint8Array(c));for(var d=b.c(),e=0;e<c.length;){var f=be(a,c.subarray(e)),h=f.value,p=h>>3;h&=7;e+=f.length;if(f=Lc(d,p))if(f.m)for(p=be(a,c.subarray(e)),h=p.value,e+=p.length;0<h&&e<c.length;){p=a.h(f,c.subarray(e));if(!p)throw Error("Expected "+f.f);b.add(f,p.value);e+=p.length;h-=p.length}else{h=a.h(f,c.subarray(e));if(!h)throw Error("Expected "+f.f);e+=h.length;f.h?b.add(f,h.value):b.set(f,h.value)}else{f=e;p=a;e=c.subarray(e); -var t=0;switch(h){case 0:t=ce(p,e).length;break;case 1:t=8;break;case 2:e=ce(p,e);t=e.length+e.value.a;break;case 3:case 4:xa("Error deserializing group");break;case 5:t=4}e=f+t}}}}; -Zd.prototype.h=function(a,b){var c=null,d=a.f,e=ce(this,b),f=e.length;switch(d){case 17:a=e.value.a;c=a>>>1^-(a&1);break;case 18:a=e.value;c=Ic(a,1).xor(C(a.and(A(1)))).toString();break;case 8:c=e.value.s(A(1));break;case 3:case 4:c=e.value.toString();break;case 5:c=e.value.a;break;case 14:case 13:c=Ec(e.value);break;case 6:case 16:a=b.subarray(0,8);c=(new z(de(a.subarray(0,4),!0),de(a.subarray(4,8),!0))).toString();f=8;break;case 1:a=b.subarray(0,8);for(c=0;8>c;c++)this.f.setUint8(c,a[c]);c=this.f.getFloat64(0, -!0);f=8;break;case 9:a=b.subarray(e.length,e.length+e.value.a);a=ee(a);c=decodeURIComponent(escape(a));f=e.length+e.value.a;break;case 12:a=b.subarray(e.length,e.length+e.value.a);c=ee(a);f=e.length+e.value.a;break;case 10:f=c=new (a.j.prototype.c().ea);e=b;d=f.c();for(var h=0;;){var p=be(this,e),t=p.value;p=p.length;var y=t>>3;if(4==(t&7))break;h+=p;t={value:void 0,length:0};(y=Lc(d,y))&&(t=this.h(y,e.subarray(p)))&&null!==t.value&&(y.h?f.add(y,t.value):f.set(y,t.value));h+=t.length;if(e.length< -p+t.length)break;e=e.subarray(p+t.length)}f=h;b=ce(this,b.subarray(f));r(b.value.a==(a.a<<3|4),"Error deserializing group");f+=b.length;break;case 11:f=e.length+e.value.a;b=b.subarray(e.length,f);c=new (a.j.prototype.c().ea);Vc(this,c,b);break;case 7:case 15:c=de(b.subarray(0,4),15==d);f=4;break;case 2:a=b.subarray(0,4);for(c=0;4>c;c++)this.f.setUint8(c,a[c]);c=this.f.getFloat32(0,!0);f=4}return{value:c,length:f}}; -var P=function(a,b){do{var c=b&127;b>>>=7;0<b&&(c|=128);a.a.push(c)}while(0<b)},$d=function(a,b){var c=wc(127);do{var d=b.and(c).a;b=Ic(b,7);0<Fc(b,A(0))&&(d|=128);a.a.push(d)}while(0<Fc(b,A(0)))},ce=function(a,b){a=a.w;for(var c=D(0),d=0;d<b.length;d++){var e=Hc(wc(b[d]&127),7*d);c=c.or(e);if(0==(b[d]&128))break}a.value=c;a.length=d+1;return a},be=function(a,b){a=a.i;for(var c=0,d=0;d<b.length&&(c|=(b[d]&127)<<7*d,0!=(b[d]&128));d++);a.value=c;a.length=d+1;return a},ae=function(a,b,c){for(var d= -wc(255),e=0;e<c;e++){var f=b.and(d).a;a.a.push(f);b=Ic(b,8)}},de=function(a,b){for(var c=0,d=0;d<a.length;d++)c|=a[d]<<8*d;b||(c>>>=0);return c},ee=function(a){var b="";a=new Uint16Array(a);for(var c=0;c<a.length;c+=65536)b+=String.fromCharCode.apply(null,a.subarray(c,c+Math.min(65536,a.length-c)));return b};var fe=function(a){for(var b=a.U;b;)a=b,b=a.U;return a},ge=function(a,b){var c=document.createElement("CANVAS"),d=document.createElement("IMG");d.setAttribute("style","position:absolute;visibility:hidden;top:-1000px;left:-1000px;");d.crossOrigin="Anonymous";ac(d,"load",function(){var a=d.width,f=d.height;c.width=a;c.height=f;var h=c.getContext("2d");h.drawImage(d,0,0);h=h.getImageData(0,0,a,f);document.body.removeChild(d);b(h.data,new Gb(a,f))});d.setAttribute("src",a);document.body.appendChild(d)}, -he=function(a,b){var c=new N;H(c,1,a);H(c,2,1);a=new O;H(a,1,b);H(c,3,a);return c};var ie=function(a){v.call(this,"b");this.enabled=a};q(ie,v);var je=function(){v.call(this,"d")};q(je,v);var ke=function(){v.call(this,"e")};q(ke,v);var le=function(){v.call(this,"f")};q(le,v);var me=function(a){v.call(this,"g");this.callback=a};q(me,v);var ne=function(a){v.call(this,"h");this.j=a};q(ne,v);var oe=function(){v.call(this,"l")};q(oe,v);var pe=function(){G.call(this)};q(pe,G);var qe=null,Q=function(){G.call(this)};q(Q,G);var re=null;pe.prototype.c=function(){var a=qe;a||(qe=a=I(pe,{0:{name:"Point",g:"sketchology.proto.Point"},1:{name:"x",b:2,type:Number},2:{name:"y",b:2,type:Number}}));return a};pe.c=pe.prototype.c; -Q.prototype.c=function(){var a=re;a||(re=a=I(Q,{0:{name:"Rect",g:"sketchology.proto.Rect"},1:{name:"xlow",b:2,type:Number},2:{name:"xhigh",b:2,type:Number},3:{name:"ylow",b:2,type:Number},4:{name:"yhigh",b:2,type:Number}}));return a};Q.c=Q.prototype.c;var se={Wb:0,uc:1,tc:2,rc:3,sc:4,Ob:5,Nb:6,Lb:7,Mb:8,fd:9,ed:10,cd:11,dd:12,bd:13},te={Vb:0,yc:1,Db:2,Uc:3},ue=function(){G.call(this)};q(ue,G);var ve=null,we=function(){G.call(this)};q(we,G);var xe=null;ue.prototype.c=function(){var a=ve;a||(ve=a=I(ue,{0:{name:"Font",g:"sketchology.proto.text.Font"},1:{name:"postscript_font",b:14,defaultValue:0,type:se},2:{name:"name",b:9,type:String},3:{name:"asset_id",b:9,type:String},4:{name:"resource_id",b:13,type:Number}}));return a};ue.c=ue.prototype.c; -we.prototype.c=function(){var a=xe;a||(xe=a=I(we,{0:{name:"Text",g:"sketchology.proto.text.Text"},1:{name:"text",b:9,type:String},2:{name:"bounds_world",b:11,type:Q},3:{name:"font",b:11,type:ue},4:{name:"font_size_world",b:2,defaultValue:24,type:Number},5:{name:"rgba",b:13,defaultValue:255,type:Number},6:{name:"alignment",b:14,defaultValue:0,type:te}}));return a};we.c=we.prototype.c;var ye={NONE:0,Ad:1,Zc:2,jc:3,Bd:4},ze=function(){G.call(this)};q(ze,G);var Ae=null,Be=function(){G.call(this)};q(Be,G);var Ce=null,De={Y:0,hc:1,vc:2},Ee=function(){G.call(this)};q(Ee,G);var Fe=null,Ge=function(){G.call(this)};q(Ge,G);var He=null,Ie=function(){G.call(this)};q(Ie,G);var Je=null,Ke=function(){G.call(this)};q(Ke,G);var Le=null,Me=function(){G.call(this)};q(Me,G);var Ne=null,Oe=function(){G.call(this)};q(Oe,G);var Pe=null,R=function(){G.call(this)};q(R,G);var Qe=null,Re=function(){G.call(this)}; -q(Re,G);var Se=null,Te=function(){G.call(this)};q(Te,G);var Ue=null,Ve=function(){G.call(this)};q(Ve,G);var We=null,Xe=function(){G.call(this)};q(Xe,G);var Ye=null,S=function(){G.call(this)};q(S,G);var Ze=null;S.prototype.B=function(){return Pc(this,2)};var $e=function(){G.call(this)};q($e,G);var af=null,bf={Y:0,Gc:1,Ac:2,Sb:3,Pc:4,Hb:5},cf={Cb:1,Vc:2,$c:3}; -ze.prototype.c=function(){var a=Ae;a||(Ae=a=I(ze,{0:{name:"CallbackFlags",g:"sketchology.proto.CallbackFlags"},1:{name:"mesh_data_ctm",b:8,type:Boolean},2:{name:"uncompressed_outline",b:8,type:Boolean},3:{name:"compressed_input_points",b:8,type:Boolean}}));return a};ze.c=ze.prototype.c;Be.prototype.c=function(){var a=Ce;a||(Ce=a=I(Be,{0:{name:"SourceDetails",g:"sketchology.proto.SourceDetails"},1:{name:"origin",b:14,defaultValue:0,type:De},2:{name:"host_source_details",b:13,type:Number}}));return a}; -Be.c=Be.prototype.c;Ee.prototype.c=function(){var a=Fe;a||(Fe=a=I(Ee,{0:{name:"BackgroundImageInfo",g:"sketchology.proto.BackgroundImageInfo"},1:{name:"uri",b:9,type:String},3:{name:"bounds",b:11,type:Q}}));return a};Ee.c=Ee.prototype.c;Ge.prototype.c=function(){var a=He;a||(He=a=I(Ge,{0:{name:"Border",g:"sketchology.proto.Border"},1:{name:"uri",b:9,type:String},2:{name:"scale",b:2,defaultValue:1,type:Number}}));return a};Ge.c=Ge.prototype.c; -Ie.prototype.c=function(){var a=Je;a||(Je=a=I(Ie,{0:{name:"GridInfo",g:"sketchology.proto.GridInfo"},1:{name:"uri",b:9,type:String},2:{name:"rgba_multiplier",b:13,defaultValue:4294967295,type:Number},3:{name:"size_world",b:2,defaultValue:50,type:Number},4:{name:"origin",b:11,type:pe}}));return a};Ie.c=Ie.prototype.c;Ke.prototype.c=function(){var a=Le;a||(Le=a=I(Ke,{0:{name:"LOD",g:"sketchology.proto.LOD"},1:{name:"max_coverage",b:2,type:Number},2:{name:"ctm_blob",b:12,type:String}}));return a}; -Ke.c=Ke.prototype.c;Me.prototype.c=function(){var a=Ne;a||(Ne=a=I(Me,{0:{name:"Stroke",g:"sketchology.proto.Stroke"},1:{name:"shader_type",b:14,defaultValue:0,type:ye},3:{name:"lod",l:!0,b:11,type:Ke},4:{name:"abgr",b:13,type:Number},5:{name:"point_x",l:!0,fa:!0,b:17,type:Number},6:{name:"point_y",l:!0,fa:!0,b:17,type:Number},7:{name:"point_t_ms",l:!0,fa:!0,b:13,type:Number},8:{name:"deprecated_transform",b:11,type:R},9:{name:"start_time_ms",b:4,type:String}}));return a};Me.c=Me.prototype.c; -Oe.prototype.c=function(){var a=Pe;a||(Pe=a=I(Oe,{0:{name:"UncompressedStroke",g:"sketchology.proto.UncompressedStroke"},1:{name:"outline",l:!0,b:11,type:pe},2:{name:"rgba",b:13,type:Number}}));return a};Oe.c=Oe.prototype.c; -R.prototype.c=function(){var a=Qe;a||(Qe=a=I(R,{0:{name:"AffineTransform",g:"sketchology.proto.AffineTransform"},1:{name:"tx",b:2,type:Number},2:{name:"ty",b:2,type:Number},3:{name:"scale_x",b:2,defaultValue:1,type:Number},4:{name:"scale_y",b:2,defaultValue:1,type:Number},5:{name:"rotation_radians",b:2,type:Number}}));return a};R.c=R.prototype.c; -Re.prototype.c=function(){var a=Se;a||(Se=a=I(Re,{0:{name:"Element",g:"sketchology.proto.Element"},4:{name:"deprecated_uuid",b:9,type:String},5:{name:"minimum_serializer_version",b:13,type:Number},6:{name:"stroke",b:11,type:Me},9:{name:"path",b:11,type:$e},10:{name:"attributes",b:11,type:Te},11:{name:"text",b:11,type:we}}));return a};Re.c=Re.prototype.c; -Te.prototype.c=function(){var a=Ue;a||(Ue=a=I(Te,{0:{name:"ElementAttributes",g:"sketchology.proto.ElementAttributes"},1:{name:"selectable",b:8,defaultValue:!0,type:Boolean},2:{name:"magic_erasable",b:8,defaultValue:!0,type:Boolean},3:{name:"is_sticker",b:8,defaultValue:!1,type:Boolean},4:{name:"is_text",b:8,defaultValue:!1,type:Boolean},5:{name:"is_group",b:8,defaultValue:!1,type:Boolean}}));return a};Te.c=Te.prototype.c; -Ve.prototype.c=function(){var a=We;a||(We=a=I(Ve,{0:{name:"UncompressedElement",g:"sketchology.proto.UncompressedElement"},1:{name:"uncompressed_stroke",b:11,type:Oe}}));return a};Ve.c=Ve.prototype.c;Xe.prototype.c=function(){var a=Ye;a||(Ye=a=I(Xe,{0:{name:"ElementMutation",g:"sketchology.proto.ElementMutation"},1:{name:"uuid",l:!0,b:9,type:String},2:{name:"transform",l:!0,b:11,type:R}}));return a};Xe.c=Xe.prototype.c; -S.prototype.c=function(){var a=Ze;a||(Ze=a=I(S,{0:{name:"ElementBundle",g:"sketchology.proto.ElementBundle"},1:{name:"uuid",b:9,type:String},2:{name:"element",b:11,type:Re},3:{name:"transform",b:11,type:R},4:{name:"uncompressed_element",b:11,type:Ve},5:{name:"group_uuid",b:9,type:String}}));return a};S.c=S.prototype.c; -$e.prototype.c=function(){var a=af;a||(af=a=I($e,{0:{name:"Path",g:"sketchology.proto.Path"},1:{name:"segment_types",l:!0,b:14,defaultValue:0,type:bf},2:{name:"segment_counts",l:!0,b:13,type:Number},3:{name:"segment_args",l:!0,b:1,type:Number},4:{name:"radius",b:1,defaultValue:1,type:Number},5:{name:"rgba",b:13,type:Number},6:{name:"end_cap",b:14,defaultValue:2,type:cf},7:{name:"fill_rgba",b:13,type:Number}}));return a};$e.c=$e.prototype.c;var df={zd:0,$b:1,Zb:2,ac:3,Tb:4},ef=function(){G.call(this)};q(ef,G);var ff=null,gf=function(){G.call(this)};q(gf,G);var hf=null,jf=function(){G.call(this)};q(jf,G);var kf=null,lf=function(){G.call(this)};q(lf,G);var mf=null;ef.prototype.c=function(){var a=ff;a||(ff=a=I(ef,{0:{name:"AnimationCurve",g:"sketchology.proto.AnimationCurve"},1:{name:"type",b:14,defaultValue:1,type:df},2:{name:"params",l:!0,b:2,type:Number}}));return a};ef.c=ef.prototype.c; -gf.prototype.c=function(){var a=hf;a||(hf=a=I(gf,{0:{name:"ColorAnimation",g:"sketchology.proto.ColorAnimation"},1:{name:"duration",b:1,defaultValue:.5,type:Number},2:{name:"curve",b:11,type:ef},3:{name:"rgba",b:13,type:Number}}));return a};gf.c=gf.prototype.c; -jf.prototype.c=function(){var a=kf;a||(kf=a=I(jf,{0:{name:"ScaleAnimation",g:"sketchology.proto.ScaleAnimation"},1:{name:"duration",b:1,defaultValue:.5,type:Number},2:{name:"curve",b:11,type:ef},3:{name:"scale_x",b:2,type:Number},4:{name:"scale_y",b:2,type:Number}}));return a};jf.c=jf.prototype.c; -lf.prototype.c=function(){var a=mf;a||(mf=a=I(lf,{0:{name:"ElementAnimation",g:"sketchology.proto.ElementAnimation"},1:{name:"uuid",b:9,type:String},2:{name:"color_animation",b:11,type:gf},3:{name:"scale_animation",b:11,type:jf},4:{name:"next",b:11,type:lf}}));return a};lf.c=lf.prototype.c;var nf={yb:1,Ub:2},of=function(){G.call(this)};q(of,G);var pf=null,qf=function(){G.call(this)};q(qf,G);var rf=null,sf=function(){G.call(this)};q(sf,G);var tf=null,uf=function(){G.call(this)};q(uf,G);var vf=null,wf=function(){G.call(this)};q(wf,G);var xf=null,yf=function(){G.call(this)};q(yf,G);var zf=null,Af=function(){G.call(this)};q(Af,G);var Bf=null,Cf=function(){G.call(this)};q(Cf,G);var Df=null,Ef=function(){G.call(this)};q(Ef,G);var Ff=null,Gf=function(){G.call(this)};q(Gf,G); -var Hf=null,If=function(){G.call(this)};q(If,G);var Jf=null,T=function(){G.call(this)};q(T,G);var Kf=null;T.prototype.B=function(){return Pc(this,2,void 0)};var Lf=function(){G.call(this)};q(Lf,G);var Mf=null;Lf.prototype.B=function(){return Pc(this,2,void 0)};of.prototype.c=function(){var a=pf;a||(pf=a=I(of,{0:{name:"Color",g:"sketchology.proto.Color"},1:{name:"argb",b:13,type:Number}}));return a};of.c=of.prototype.c; -qf.prototype.c=function(){var a=rf;a||(rf=a=I(qf,{0:{name:"BackgroundColor",g:"sketchology.proto.BackgroundColor"},1:{name:"rgba",b:13,type:Number}}));return a};qf.c=qf.prototype.c;sf.prototype.c=function(){var a=tf;a||(tf=a=I(sf,{0:{name:"PageProperties",g:"sketchology.proto.PageProperties"},1:{name:"background_color",b:11,type:of},2:{name:"background_image",b:11,type:Ee},3:{name:"bounds",b:11,type:Q},4:{name:"border",b:11,type:Ge},5:{name:"grid_info",b:11,type:Ie}}));return a};sf.c=sf.prototype.c; -uf.prototype.c=function(){var a=vf;a||(vf=a=I(uf,{0:{name:"PerPageProperties",g:"sketchology.proto.PerPageProperties"},1:{name:"uuid",b:9,type:String},2:{name:"width",b:2,type:Number},3:{name:"height",b:2,type:Number}}));return a};uf.c=uf.prototype.c;wf.prototype.c=function(){var a=xf;a||(xf=a=I(wf,{0:{name:"AddAction",g:"sketchology.proto.AddAction"},1:{name:"uuid",b:9,type:String},2:{name:"below_element_with_uuid",b:9,type:String}}));return a};wf.c=wf.prototype.c; -yf.prototype.c=function(){var a=zf;a||(zf=a=I(yf,{0:{name:"RemoveAction",g:"sketchology.proto.RemoveAction"},1:{name:"uuid",l:!0,b:9,type:String},2:{name:"was_below_uuid",l:!0,b:9,type:String}}));return a};yf.c=yf.prototype.c;Af.prototype.c=function(){var a=Bf;a||(Bf=a=I(Af,{0:{name:"ClearAction",g:"sketchology.proto.ClearAction"},1:{name:"uuid",l:!0,b:9,type:String}}));return a};Af.c=Af.prototype.c; -Cf.prototype.c=function(){var a=Df;a||(Df=a=I(Cf,{0:{name:"ReplaceAction",g:"sketchology.proto.ReplaceAction"},1:{name:"uuid_add",l:!0,b:9,type:String},2:{name:"below_element_with_uuid",b:9,type:String},3:{name:"uuid_remove",l:!0,b:9,type:String},4:{name:"was_below_uuid",l:!0,b:9,type:String}}));return a};Cf.c=Cf.prototype.c; -Ef.prototype.c=function(){var a=Ff;a||(Ff=a=I(Ef,{0:{name:"SetTransformAction",g:"sketchology.proto.SetTransformAction"},1:{name:"uuid",l:!0,b:9,type:String},2:{name:"from_transform",l:!0,b:11,type:R},3:{name:"to_transform",l:!0,b:11,type:R}}));return a};Ef.c=Ef.prototype.c;Gf.prototype.c=function(){var a=Hf;a||(Hf=a=I(Gf,{0:{name:"SetPageBoundsAction",g:"sketchology.proto.SetPageBoundsAction"},1:{name:"old_bounds",b:11,type:Q},2:{name:"new_bounds",b:11,type:Q}}));return a};Gf.c=Gf.prototype.c; -If.prototype.c=function(){var a=Jf;a||(Jf=a=I(If,{0:{name:"StorageAction",g:"sketchology.proto.StorageAction"},1:{name:"add_action",b:11,type:wf},2:{name:"remove_action",b:11,type:yf},3:{name:"clear_action",b:11,type:Af},4:{name:"replace_action",b:11,type:Cf},5:{name:"set_transform_action",b:11,type:Ef},6:{name:"set_page_bounds_action",b:11,type:Gf}}));return a};If.c=If.prototype.c; -T.prototype.c=function(){var a=Kf;a||(Kf=a=I(T,{0:{name:"Snapshot",g:"sketchology.proto.Snapshot"},1:{name:"page_properties",b:11,type:sf},8:{name:"per_page_properties",l:!0,b:11,type:uf},2:{name:"element",l:!0,b:11,type:S},3:{name:"dead_element",l:!0,b:11,type:S},4:{name:"undo_action",l:!0,b:11,type:If},5:{name:"redo_action",l:!0,b:11,type:If},6:{name:"element_state_index",l:!0,b:14,defaultValue:1,type:nf},7:{name:"fingerprint",b:4,type:String}}));return a};T.c=T.prototype.c; -Lf.prototype.c=function(){var a=Mf;a||(Mf=a=I(Lf,{0:{name:"MutationPacket",g:"sketchology.proto.MutationPacket"},1:{name:"mutation",l:!0,b:11,type:If},2:{name:"element",l:!0,b:11,type:S}}));return a};Lf.c=Lf.prototype.c;var Nf={qd:0,xa:1,wc:2,Aa:3,zb:4,ya:6,za:8,Eb:10,Ab:11},Of={Y:0,Sc:1,ec:2,gc:3,dc:4,fc:5,Cc:6,Ic:7,Rb:8,pc:9},U=function(){G.call(this)};q(U,G);var Pf=null,V=function(){G.call(this)};q(V,G);var Qf=null,Rf=function(){G.call(this)};q(Rf,G);var Sf=null,Tf=function(){G.call(this)};q(Tf,G);var Uf=null,Vf=function(){G.call(this)};q(Vf,G);var Wf=null,Xf=function(){G.call(this)};q(Xf,G);var Yf=null,Zf=function(){G.call(this)};q(Zf,G);var $f=null,ag=function(){G.call(this)};q(ag,G);var bg=null,cg=function(){G.call(this)}; -q(cg,G);var dg=null,eg={vd:0,Cd:1,POINTS:2,Dd:3,Mc:4,Nc:5},fg=function(){G.call(this)};q(fg,G);var gg=null,hg=function(){G.call(this)};q(hg,G);var ig=null,jg={Y:0,zc:1,bc:2,Dc:3,Qc:4,Hc:5,mc:6,Oc:7,Qb:8},kg=function(){G.call(this)};q(kg,G);var lg=null,mg=function(){G.call(this)};q(mg,G);var ng=null,og=function(){G.call(this)};q(og,G);var pg=null,qg=function(){G.call(this)};q(qg,G);var rg=null,sg=function(){G.call(this)};q(sg,G);var tg=null,ug={Y:0,Fc:1,od:2,Lc:3,ya:4},vg=function(){G.call(this)}; -q(vg,G);var wg=null,xg=function(){G.call(this)};q(xg,G);var yg=null,zg=function(){G.call(this)};q(zg,G);var Ag=null,Bg=function(){G.call(this)};q(Bg,G);var Cg=null,Dg=function(){G.call(this)};q(Dg,G);var Eg=null; -U.prototype.c=function(){var a=Pf;a||(Pf=a=I(U,{0:{name:"Command",g:"sketchology.proto.Command"},1:{name:"set_viewport",b:11,type:Xf},2:{name:"tool_params",b:11,type:hg},3:{name:"add_path",b:11,type:Dg},4:{name:"camera_position",b:11,type:Q},5:{name:"page_bounds",b:11,type:Q},6:{name:"image_export",b:11,type:Zf},7:{name:"flag_assignment",b:11,type:kg},8:{name:"set_element_transforms",b:11,type:Xe},9:{name:"add_element",b:11,type:mg},10:{name:"background_image",b:11,type:Ee},11:{name:"background_color", -b:11,type:qf},12:{name:"set_out_of_bounds_color",b:11,type:og},13:{name:"set_page_border",b:11,type:Ge},14:{name:"send_input_stream",b:11,type:qg},15:{name:"sequence_point",b:11,type:vg},16:{name:"set_callback_flags",b:11,type:xg},17:{name:"set_camera_bounds_config",b:11,type:zg},18:{name:"deselect_all",b:11,type:V},19:{name:"add_image_rect",b:11,type:Bg},21:{name:"clear",b:11,type:V},22:{name:"remove_all_elements",b:11,type:V},23:{name:"undo",b:11,type:V},24:{name:"redo",b:11,type:V},25:{name:"evict_image_data", -b:11,type:Vf},26:{name:"replace_elements",b:11,type:Rf},27:{name:"commit_crop",b:11,type:V},28:{name:"element_animation",b:11,type:lf},29:{name:"set_grid",b:11,type:Ie},30:{name:"clear_grid",b:11,type:V},31:{name:"set_crop",b:11,type:Q},32:{name:"add_text",b:11,type:Tf}}));return a};U.c=U.prototype.c;V.prototype.c=function(){var a=Qf;a||(Qf=a=I(V,{0:{name:"NoArgCommand",g:"sketchology.proto.NoArgCommand"}}));return a};V.c=V.prototype.c; -Rf.prototype.c=function(){var a=Sf;a||(Sf=a=I(Rf,{0:{name:"ReplaceElementsCommand",g:"sketchology.proto.ReplaceElementsCommand"},1:{name:"uuids_to_remove",l:!0,b:9,type:String},2:{name:"paths_to_add",l:!0,b:11,type:$e}}));return a};Rf.c=Rf.prototype.c;Tf.prototype.c=function(){var a=Uf;a||(Uf=a=I(Tf,{0:{name:"AddText",g:"sketchology.proto.AddText"},1:{name:"text",b:11,type:we},2:{name:"group_uuid",b:9,type:String}}));return a};Tf.c=Tf.prototype.c; -Vf.prototype.c=function(){var a=Wf;a||(Wf=a=I(Vf,{0:{name:"EvictImageData",g:"sketchology.proto.EvictImageData"},1:{name:"uri",b:9,type:String}}));return a};Vf.c=Vf.prototype.c;Xf.prototype.c=function(){var a=Yf;a||(Yf=a=I(Xf,{0:{name:"Viewport",g:"sketchology.proto.Viewport"},1:{name:"width",b:13,type:Number},2:{name:"height",b:13,type:Number},3:{name:"ppi",b:2,type:Number}}));return a};Xf.c=Xf.prototype.c; -Zf.prototype.c=function(){var a=$f;a||($f=a=I(Zf,{0:{name:"ImageExport",g:"sketchology.proto.ImageExport"},1:{name:"max_dimension_px",b:13,defaultValue:1024,type:Number},2:{name:"should_draw_background",b:8,defaultValue:!0,type:Boolean}}));return a};Zf.c=Zf.prototype.c; -ag.prototype.c=function(){var a=bg;a||(bg=a=I(ag,{0:{name:"LinearPathAnimation",g:"sketchology.proto.LinearPathAnimation"},1:{name:"rgba_from",b:13,type:Number},2:{name:"rgba_seconds",b:1,type:Number},3:{name:"dilation_from",b:2,type:Number},4:{name:"dilation_seconds",b:1,type:Number}}));return a};ag.c=ag.prototype.c; -cg.prototype.c=function(){var a=dg;a||(dg=a=I(cg,{0:{name:"LineSize",g:"sketchology.proto.LineSize"},7:{name:"stroke_width",b:2,type:Number},8:{name:"units",b:14,defaultValue:1,type:eg},9:{name:"use_web_sizes",b:8,type:Boolean}}));return a};cg.c=cg.prototype.c;fg.prototype.c=function(){var a=gg;a||(gg=a=I(fg,{0:{name:"PusherToolParams",g:"sketchology.proto.PusherToolParams"},1:{name:"manipulate_stickers",b:8,type:Boolean},2:{name:"manipulate_text",b:8,type:Boolean}}));return a};fg.c=fg.prototype.c; -hg.prototype.c=function(){var a=ig;a||(ig=a=I(hg,{0:{name:"ToolParams",g:"sketchology.proto.ToolParams"},1:{name:"tool",b:14,defaultValue:0,type:jg},2:{name:"rgba",b:13,type:Number},3:{name:"line_size",b:11,type:cg},4:{name:"pusher_tool_params",b:11,type:fg},5:{name:"brush_type",b:14,defaultValue:0,type:Nf},6:{name:"linear_path_animation",b:11,type:ag}}));return a};hg.c=hg.prototype.c; -kg.prototype.c=function(){var a=lg;a||(lg=a=I(kg,{0:{name:"FlagAssignment",g:"sketchology.proto.FlagAssignment"},1:{name:"flag",b:14,defaultValue:0,type:Of},2:{name:"bool_value",b:8,type:Boolean}}));return a};kg.c=kg.prototype.c;mg.prototype.c=function(){var a=ng;a||(ng=a=I(mg,{0:{name:"AddElement",g:"sketchology.proto.AddElement"},1:{name:"bundle",b:11,type:S},2:{name:"below_element_with_uuid",b:9,type:String}}));return a};mg.c=mg.prototype.c; -og.prototype.c=function(){var a=pg;a||(pg=a=I(og,{0:{name:"OutOfBoundsColor",g:"sketchology.proto.OutOfBoundsColor"},1:{name:"rgba",b:13,type:Number}}));return a};og.c=og.prototype.c;qg.prototype.c=function(){var a=rg;a||(rg=a=I(qg,{0:{name:"SInputStream",g:"sketchology.proto.SInputStream"},1:{name:"screen_width",b:13,type:Number},2:{name:"screen_height",b:13,type:Number},3:{name:"screen_ppi",b:2,type:Number},4:{name:"input",l:!0,b:11,type:sg}}));return a};qg.c=qg.prototype.c; -sg.prototype.c=function(){var a=tg;a||(tg=a=I(sg,{0:{name:"SInput",g:"sketchology.proto.SInput"},1:{name:"type",b:14,defaultValue:0,type:ug},2:{name:"id",b:13,type:Number},3:{name:"flags",b:13,type:Number},4:{name:"time_s",b:1,type:Number},5:{name:"screen_pos_x",b:2,type:Number},6:{name:"screen_pos_y",b:2,type:Number},7:{name:"pressure",b:2,type:Number},8:{name:"wheel_delta",b:2,type:Number},9:{name:"tilt",b:2,type:Number},10:{name:"orientation",b:2,type:Number}}));return a};sg.c=sg.prototype.c; -vg.prototype.c=function(){var a=wg;a||(wg=a=I(vg,{0:{name:"SequencePoint",g:"sketchology.proto.SequencePoint"},1:{name:"id",b:5,type:Number}}));return a};vg.c=vg.prototype.c;xg.prototype.c=function(){var a=yg;a||(yg=a=I(xg,{0:{name:"SetCallbackFlags",g:"sketchology.proto.SetCallbackFlags"},1:{name:"source_details",b:11,type:Be},2:{name:"callback_flags",b:11,type:ze}}));return a};xg.c=xg.prototype.c; -zg.prototype.c=function(){var a=Ag;a||(Ag=a=I(zg,{0:{name:"CameraBoundsConfig",g:"sketchology.proto.CameraBoundsConfig"},1:{name:"margin_left_px",b:2,type:Number},2:{name:"margin_right_px",b:2,type:Number},3:{name:"margin_bottom_px",b:2,type:Number},4:{name:"margin_top_px",b:2,type:Number},5:{name:"fraction_padding",b:2,defaultValue:.1,type:Number}}));return a};zg.c=zg.prototype.c; -Bg.prototype.c=function(){var a=Cg;a||(Cg=a=I(Bg,{0:{name:"ImageRect",g:"sketchology.proto.ImageRect"},1:{name:"rect",b:11,type:Q},2:{name:"bitmap_uri",b:9,type:String},3:{name:"attributes",b:11,type:Te},4:{name:"rotation_radians",b:2,type:Number},5:{name:"group_uuid",b:9,type:String}}));return a};Bg.c=Bg.prototype.c; -Dg.prototype.c=function(){var a=Eg;a||(Eg=a=I(Dg,{0:{name:"AddPath",g:"sketchology.proto.AddPath"},1:{name:"path",b:11,type:$e},2:{name:"uuid",b:9,type:String},3:{name:"group_uuid",b:9,type:String}}));return a};Dg.c=Dg.prototype.c;var Fg=function(){w.call(this)};q(Fg,w);var Gg="ink_model_instances_"+Math.random();var W=function(){w.call(this);this.f="#000000";this.j=.6;this.h=!1;this.a=this.i=1;this.m="CALLIGRAPHY"};q(W,Fg);(function(a){a.S=function(b){Aa(b);var c=fe(b);(b=c[Gg])||(c[Gg]=b={});var d=a[oa]||(a[oa]=++pa),e=b[d];e?b=e:(c=new a(c),b=b[d]=c);return b}})(W);var Hg={CALLIGRAPHY:1,EDIT:2,ERASER:1,HIGHLIGHTER:1,INKPEN:1,MAGIC_ERASE:3,MARKER:1,PENCIL:1,BALLPOINT:1,BALLPOINT_IN_PEN_MODE_ELSE_MARKER:1,QUERY:4},Ig={CALLIGRAPHY:1,ERASER:6,HIGHLIGHTER:8,INKPEN:2,MARKER:3,BALLPOINT:4,BALLPOINT_IN_PEN_MODE_ELSE_MARKER:11}; -g=W.prototype;g.Ra=function(a){this.f=a;x(this,"m")};g.Sa=function(a){this.j=a;x(this,"m")};g.vb=function(a){this.h=a;x(this,"m")};g.wb=function(a){this.i=Hg[a];this.a=void 0!==Ig[a]?Ig[a]:this.a;this.m=a;x(this,"m")};g.Ma=function(){return this.m};g.Oa=function(){return this.f};g.pa=function(){return this.h?"#FFFFFF":this.f};g.qa=function(){return parseInt(this.pa().substring(1),16)};g.Pa=function(){return this.j};g.Ja=function(){return this.h};g.Na=function(){return this.a};g.Qa=function(){return this.i};var Ng=function(a){this.j=Jg(a);this.h=Kg(a);this.f=Lg(a);this.a=Mg(a)},Og=function(a){return"rgb("+[a.h,a.f,a.a].join()+")"},Pg=function(a){return new Uint32Array([a.h<<24|a.f<<16|a.a<<8|a.j])},Qg=function(a){return function(b){return b>>>a&255}},Jg=Qg(24),Kg=Qg(16),Lg=Qg(8),Mg=Qg(0),Rg=new Ng(4278190080),Sg=new Ng(4294967295),Tg=new Ng(4294638330);var Ug={},Vg=(Ug.dots="sketchology://grid_dots_0",Ug.rules="sketchology://grid_rules_0",Ug.square="sketchology://grid_square_0",Ug),Wg={},Xg=(Wg.none="",Wg.dots="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAQAAAD2e2DtAAACoElEQVR4Ae3SsW0iQABE0Y0ogJC+iC0XAy0ANdAF9IFAQrTxL7wLbAuQLlm/eSXMH32/W2MKXPp2PwVwbjCF03sB7BpMYfdeAOsGU1i/E8C9ZYMpLLu+HsC2wTQ2rwbwaNVgGquurwXw0WAqn68EcGgwnf2zARxbNJjOouMzAezdP3ECh58DuPbZYGofPb4O4NqmVYPprdp2/xvApVO71i0bvwbL1u06dxv9aoz+IwSAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACIARAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAhDArXO71i0b/BrL1u06dRlVVd3btmpMj1WbrlVVo3/36KMxNT67Vn0dQNWhRYMpLdpX/RxAHSUwpUXHeiaA2jeYzqGeDaA+G0zlo14J4NqqwTRWPV4LoDYNprGtVwO4tmwwhWX31wOodYMprOudAHYNprB7L4BTgymc3wvg0mAKt77dH6BiW7h7b3psAAAAAElFTkSuQmCC", -Wg.rules="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX///////9VfPVsAAAAAnRSTlP/AOW3MEoAAAAUSURBVHgBY4CD/1BAmDHKGGXAAAD0xe4gqLTwJgAAAABJRU5ErkJggg==",Wg.square="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX///////9VfPVsAAAAAnRSTlP/AOW3MEoAAAAWSURBVHgBY4CD+v9g8I8wY5QxyoABAGFRzuKVnN1rAAAAAElFTkSuQmCC",Wg),Yg=function(a){return(Object.entries(Vg).find(function(b){return b[1]==a})||["none",""])[0]};var Zg=function(){v.call(this,"n")};q(Zg,v);var $g=function(a,b,c){b=c||b;c=td(m(a.sa)||!1,"manifestUrl",a.sa);var d=td(m(a.ua)||!1,"useMSAA",a.ua),e=td(m(a.va)||!1,"useSingleBuffer",a.va),f=td(m(a.wa)||!1,"useSingleBufferMSAA",a.wa);a=td(m(a.P)||!1,"sengineType",a.P);b="<style"+(b&&b.ga?' nonce="'+sd(b&&b.ga)+'"':"")+'>\n #ink-engine-hwoverlay {\n display: none;\n position: absolute;\n width: 5px;\n height: 5px;\n left: 0px;\n top: 0px;\n /* Transforms and semi-transparent color are used to ensure the div\n * prevents use of a hardware overlay for the underlying canvas element,\n * despite future optimizations to the hardware overlay eligibility\n * detection in ChromeOS. See b/64569245 for details */\n background-color: rgba(0, 0, 0, 0.01);\n transform: translate3d(0.33, 0.14, 0);\n }\n /* TODO(b/69541198): Hack for hardware overlay in fullscreen mode */\n #canvas-parent.fullscreen {\n height: calc(100% - 5px);\n width: calc(100% - 10px);\n padding: 0 5px 5px 5px;\n background-color: transparent;\n }\n </style><embed id="ink-engine" use_msaa="'+ -sd(d)+'" use_single_buffer="'+sd(e)+'" use_single_buffer_msaa="'+sd(f)+'" src="';null!=c&&c.H===Zc?(r(c.constructor===cd),c=String(c).replace(xd,wd)):null!=c&&c.H===$c?(r(c.constructor===dd),c=String(c).replace(xd,wd)):c instanceof Ab?(c instanceof Ab&&c.constructor===Ab&&c.Da===zb?c=c.da:(xa("expected object of type SafeUrl, got '"+c+"' of type "+n(c)),c="type_error:SafeUrl"),c=String(c).replace(xd,wd)):c instanceof yb?(c instanceof yb&&c.constructor===yb&&c.Fa===xb?c="":(xa("expected object of type TrustedResourceUrl, got '"+ -c+"' of type "+n(c)),c="type_error:TrustedResourceUrl"),c=String(c).replace(xd,wd)):(c=String(c),yd.test(c)?c=c.replace(xd,wd):(xa("Bad value `%s` for |filterNormalizeUri",[c]),c="about:invalid#zSoyz"));return nd(b+sd(c)+'" type="application/x-nacl" sengine_type="'+sd(a)+'"><div id="ink-engine-hwoverlay"></div>')};$g.a="ink.soy.nacl.canvasHTML";var ah=function(a,b,c,d,e){M.call(this);r(a);this.Ca=a;this.m=b;this.Ga=c;this.Ea=e;this.I=0;this.K=600;this.J=800;this.G=0;this.i=new Zd;this.C=la;this.ka=this.ma=!1;this.Ha=d;this.na=[];this.V=[];this.W=[];this.oa=[];this.ia=[];this.X=[];this.L={};this.la=0};q(ah,M);ah.prototype.aa=function(){var a=!u("Macintosh")||0<=Va(bb(),"10.12.5"),b=u("CrOS"),c=u("CrOS")&&0<=Va(bb(),"10176");this.f=a=hd($g,{sa:this.Ca,ua:!!a+"",va:!!b+"",wa:!!c+"",P:this.Ha});this.a=a.querySelector("#ink-engine")}; -ah.prototype.v=function(){var a=this;this.a.addEventListener("load",function(){bh(a);a.C();ch(a,5,a.ma)})};var dh=function(a){v.call(this,"q");this.enabled=a};q(dh,v); -var eh=function(a){a.a.postMessage(["poke",""])},X=function(a,b){b=Uc(a.i,b);b=new Uint8Array(b);a.a.postMessage(["handleCommand",b.buffer])},bh=function(a){var b=a.a;fh(a,a.I,a.K,a.J,a.G);a.ka||(a.ka=!0,b.addEventListener("message",sa(function(a){if("event_type"in a.data)switch(a=a.data,a.event_type){case "exit":console.log("Engine requested exit.");break;case "debug":console.log(a.message);break;case "image_export":this.Ga(a.width,a.height,new Uint8ClampedArray(a.bytes));break;case "request_image":this.Ea(a.uri); -break;case "element_added":if(this.m){var b=this.m,c=a.uuid,f=a.encoded_element;a=a.encoded_transform;b.G.add(c);x(b,new je(c,f,a))}break;case "elements_mutated":this.m&&x(this.m,new ke(a.uuids,a.encoded_transforms));break;case "elements_removed":this.m&&x(this.m,new le(a.uuids));break;case "flag_changed":5==a.which&&(this.ma=a.enabled,x(this,new dh(a.enabled)));break;case "undo_redo_state_changed":x(this,new Zg(!!a.can_undo,!!a.can_redo));break;case "snapshot_gotten":b=new T;Vc(this.i,b,a.snapshot); -this.na.shift().call(null,b);break;case "brix_elements_converted":b=new T;Vc(this.i,b,a.snapshot);a=new sf;c=new Q;this.W.shift();f=null.La().get("bounds");H(c,2,f.Kd||0);H(c,1,f.Ld||0);H(c,4,f.Md||0);H(c,3,f.Nd||0);H(a,3,c);H(b,1,a);this.V.shift().call(null,b);break;case "snapshot_has_pending_mutations":this.oa.shift().call(null,a.has_mutations);break;case "extracted_mutation_packet":b=new Lf;Vc(this.i,b,a.extraction_packet);this.ia.shift().call(null,b);break;case "cleared_pending_mutations":b=new T; -Vc(this.i,b,a.snapshot);this.X.shift().call(null,b);break;case "hwoverlay":document.querySelector("#ink-engine-hwoverlay").style.display=a.enable?"none":"block";break;case "single_buffer":this.a.style.transform="scaleY(-1)";break;case "sequence_point_reached":a=a.id,b=this.L[a],delete this.L[a],b()}},a)));x(a,"o")},gh=function(a,b,c,d,e){a.a.postMessage(["addImageData",{imageData:b.buffer,uri:d,width:c.width,height:c.height,assetType:e}])},hh=function(a,b){var c=new qf;H(c,1,Pg(b)[0]);b=new U;H(b, -11,c);X(a,b)},ih=function(a){var b=new U,c=new V;H(b,30,c);X(a,b)},jh=function(a,b,c,d,e){a.C=function(){if(1!=d){var f=new hg;H(f,1,d);var h=new U;H(h,2,f);X(this,h)}else a.a.postMessage(["updateBrush",{brush:e,rgba:b[0],stroke_width:c}])};a.C()},ch=function(a,b,c){var d=new kg;H(d,1,b);H(d,2,!!c);b=new U;H(b,7,d);X(a,b)},fh=function(a,b,c,d,e){a.I=b;a.K=c;a.J=d;a.G=e;b=new Q;H(b,1,a.I);H(b,3,a.G);H(b,2,a.J);H(b,4,a.K);c=new U;H(c,5,b);X(a,c)}; -ah.prototype.flush=function(a){var b=new U,c=new vg;H(c,1,this.la);this.L[this.la++]=a;H(b,15,c);X(this,b)};var Y=function(a,b){var c=this;M.call(this);this.i=null;this.a=new ah(a,this,sa(this.X,this),b,sa(this.V,this));md(this,this.a);sc(jd(this),this.a,sa(function(){this.J();kh(this);x(this,"c")},this));qc(jd(this),this.a,"p",this.K);qc(jd(this),this.a,"q",function(a){x(c,new ie(a.enabled))});this.m=[];this.G=new Set;this.I=this.W=0;this.C=null;this.L=!1};q(Y,M);Y.prototype.v=function(){Y.R.v.call(this);this.a.render(this.B());var a=jd(this);r(a);this.i=W.S(this);qc(a,this.i,"m",this.J)}; -Y.prototype.X=function(a,b,c){var d=this;if(this.C){try{var e=new ImageData(c,a,b),f=document.createElement("canvas"),h=f.getContext("2d");f.width=a;f.height=b;h.putImageData(e,0,0)}catch(p){this.K(p);return}this.L?(a=function(a){d.C(Db(a))},f.msToBlob?f.msToBlob(a,"image/png"):f.toBlob(a,"image/png")):this.C(Fb(f.toDataURL()))}};Y.prototype.V=function(a){var b=this,c=Yg(a);"none"!=c&&ge(Xg[c],function(c,e){gh(b.a,c,e,a,3)})}; -var lh=function(a,b,c,d){d=d||{};var e="sketchology://background_"+a.I;a.I++;var f=new Ee;H(f,1,e);if("none"!=d.bounds){d=d.bounds||{xlow:0,ylow:0,xhigh:c.width,yhigh:c.height};var h=new Q;H(h,1,d.xlow);H(h,3,d.ylow);H(h,2,d.xhigh);H(h,4,d.yhigh);H(f,3,h)}a=a.a;gh(a,b,c,e,0);b=new U;H(b,10,f);X(a,b)};Y.prototype.J=function(){r(this.i);var a=this.i.i,b=this.i.a,c=this.i.j,d=new Ng(parseInt(this.i.f.substring(1),16));d.j=255;jh(this.a,Pg(d),c,a,b)}; -var kh=function(a){var b=new Ge;H(b,1,"sketchology://border0");H(b,2,1);ge("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAABYCAYAAABxlTA0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AgPEBYrHoEFUgAAAw1JREFUeNrt3b9uE0EQBvBvZvd8LURUkVwEkEDAm9AgQYOQKHgZWloqUMoUaVJSpAivQBEhJGhSWiAlKXz7JwXey9nE9vrOgHT3fZKVFM5F/mUyN5tIY8F2EtG/yNYucnZ21keg/57d3V1RMvzdEJjABGYITGACM+1iNz5RxGGPzCIbnT+i3RA1AjgFcADgR4zRDwTVABjHGF8AeJwOaDnYNgd29jGGED6JyMvxeDwZYvVOJpN3FxcXH0TkWfMovQpac6p39jgdMi4A7Ozs/HLOvQkhfEkurW9yDVh47+GcOxgybsre3t5P59y+937OqHUFhxAQQkBVVd85E/yOc+5bcuk0pqWLeO/hvQ+krV289x45yLqqPSRk5xym0yllZ5lOp6iqCiGEtW3C5lZwzq/DUOK9h4jUwK3GtGYFz1oEZa97cA2crJaNapozoiVk5rqCm+2h898ihn487uKiWPMPy2arYG7G7TQHM91CYAITmCEwgQnMEJjABGYITGCGwAQmMENgAhOYITCBCUwCAhOYITCBCcwQmMAEZghMYIbABCYwQ2ACE5ghMIEJzBCYwAyBCUxghsAEJjBDYAIzBP63wFkLcUX4lhAp3nu79Qr23t8lbZ37WwNuLFx7fnJycnvossfHx7dijK+WGLWrYBFBjPHh5eXl/tHR0Z0h41ZV9T7G+EREum/AThcREaiqqOpTAJ8PDw8/VlX11TnnhgArIrYsy3vn5+evy7J8NLNADrJd1xpUFcaY9BBVfSAib2foAPq7GTAZGGNSkcFaC2stjDH161+BLGsrOAEXRYGyLOsNgKqK5hbovgIng/T6R6MRiqKogVtVcPqi5k+tKIo5XOfcYICNMbDWYjQaoSzLP4BXtYqVFayqiDHCWlsjJnDnXPYG0j5UcCqy9LDWtq/gZcipHxVFMbfitec3uMX70FwP7nyTW2zyaSt236v3pipO7UJVs9pDVgU3p4n0jZqwQwBeHFlzYLPn4MXPb4Lt+5i2CJ1zgsuu4GUX2vBNk3qJnvX8jOdwv3h7O1wBYIqaD5lCtYoAAAAASUVORK5CYII=", -function(c,d){var e=a.a,f=new og;H(f,1,3873892095);var h=new U;H(h,12,f);X(e,h);gh(e,c,d,"sketchology://border0",1);h=new U;H(h,13,b);X(e,h)})};Y.prototype.K=function(a){if(x(this,new oe(a)))throw a||Error("Unhandled fatal ink error");};Y.prototype.flush=function(a){this.a.flush(a)};var mh=function(){M.call(this);this.a=null};q(mh,M);mh.prototype.v=function(){mh.R.v.call(this);this.a=W.S(this);var a=jd(this);qc(a,this.a,"m",this.i);qc(a,fe(this),"a",this.m)};mh.prototype.m=function(a){a.j?this.B().style.cursor="":this.i()}; -mh.prototype.i=function(){var a=this.a.qa(),b=8,c=document.createElement("canvas"),d=c.getContext("2d");a=new Ng(a|4278190080);b=Math.max(b,2);var e=Math.ceil(2*b);c.width=e;c.height=e;d.fillStyle=Og(127<.5*(Math.max(a.h,a.f,a.a)+Math.min(a.h,a.f,a.a))?Rg:Sg);d.beginPath();d.arc(b,b,b,0,2*Math.PI);d.closePath();d.fill();d.fillStyle=Og(a);d.beginPath();d.arc(b,b,b-1,0,2*Math.PI);d.closePath();d.fill();b="url("+c.toDataURL()+")8 8, auto";this.B().style.cursor=b};var nh=function(a,b,c){b=c||b;return nd('<div id="canvas-parent"><style'+(b&&b.ga?' nonce="'+sd(b&&b.ga)+'"':"")+'>\n #canvas-parent {\n height: 100%;\n position: relative;\n width: 100%;\n }\n #layer-container {\n height: 100%;\n position: relative;\n width: 100%;\n }\n #ink-engine {\n height: 100%;\n left: 0;\n position: absolute;\n top: 0;\n width: 100%;\n touch-action: none;\n }\n .above-ink-canvas {\n display: none;\n }\n </style><div class="above-ink-canvas"></div><div id="layer-container"></div><div class="below-ink-canvas"></div></div>')}; -nh.a="ink.soy.embedContent";var Z=function(a,b){M.call(this);this.i=a;this.m=new mh;md(this,this.m);this.a=new Y(a.f,a.P);md(this,this.a);this.C=b};q(Z,M);g=Z.prototype;g.Wa=function(){var a=new v("k");x(this,a);a.f||this.a.a.a.postMessage(["removeAll",""])};g.tb=function(){var a=new v("i");x(this,a);if(!a.f){a=this.a.a;var b=new U,c=new V;H(b,23,c);X(a,b)}a=he(this.i.a,7);x(this,new ne(a))};g.hb=function(){var a=new v("j");x(this,a);if(!a.f){a=this.a.a;var b=new U,c=new V;H(b,24,c);X(a,b)}a=he(this.i.a,8);x(this,new ne(a))}; -g.lb=function(a,b){var c=this;ge(a,function(a,e){lh(c.a,a,e);b&&b()})};g.pb=function(a,b){var c=this;ge(a,function(a,e){lh(c.a,a,e,{bounds:"none"});b&&b()})};g.kb=function(a){hh(this.a.a,a)};g.ob=function(a,b,c,d,e,f){var h=this;if("none"==a)this.ra();else{var p=Vg[a];ge(Xg[a],function(a,y){var t=h.a,J=new Ie;H(J,1,p);H(J,2,Pg(b)[0]);H(J,3,c);var Wc=new pe;H(Wc,1,d);H(Wc,2,e);H(J,4,Wc);t=t.a;gh(t,a,y,p,3);a=new U;H(a,29,J);X(t,a);f&&f()})}};g.ra=function(){ih(this.a.a)}; -g.$a=function(a,b,c,d){var e=this.a;e.C=c;e.L=!!d;c=new Zf;H(c,1,a);H(c,2,b);a=e.a;b=new U;H(b,6,c);X(a,b)};g.mb=function(a){var b=this.a.a,c=new U;H(c,16,a);X(b,c)};g.qb=function(a,b,c,d){fh(this.a.a,a,b,c,d)};g.Za=function(){throw Error("deselectAll not yet implemented for NaCl.");};g.aa=function(){this.f=hd(nh)}; -g.v=function(){Z.R.v.call(this);var a=Kb("layer-container");this.a.render(a);var b=this.m;if(b.A)throw Error("Component already rendered");if(a){var c=Ib(a);b.T&&b.T.a==c||(b.T=Jb(a));b.f=a;b.v()}else throw Error("Invalid element to decorate");qc(jd(this),this.a,"c",sa(this.C,this,this))};g.ub=function(a){var b=Kb("canvas-parent");a?b.classList?b.classList.add("fullscreen"):vb(b)||(b.className+=0<b.className.length?" fullscreen":"fullscreen"):wb(b)}; -g.Ta=function(a,b){var c=this.a;a.id||(a.id="local-"+c.W++);var d=a.id;Ia(c.m,b,0,d);c.G.has(d)?c.G.delete(d):b<c.m.length-1?(d=c.a,b=c.m[b+1],r(a),d.a.postMessage(["addElementToEngineBelow",{bundle:a,below_uuid:b}])):(b=c.a,r(a),b.a.postMessage(["addElementToEngine",{bundle:a}]));eh(c.a)};g.ib=function(a,b){for(var c=this.a,d=0;d<b;d++)c.a.a.postMessage(["removeElement",c.m[a]]),Ea(c.m,a);eh(c.a)}; -g.jb=function(){var a=this.a;a.a.a.postMessage(["clear",""]);hh(a.a,Tg);ih(a.a);a.G.clear();a.m=[];eh(a.a)};g.rb=function(a){ch(this.a.a,1,!!a)};g.nb=function(a,b){if(a.length!==b.length)throw Error("mismatch in transform array lengths");this.a.a.a.postMessage(["setElementTransforms",{uuids:a,encoded_transforms:b}])};g.fb=function(a){var b=new me(a);x(this,b);b.f||a(void 0)}; -g.Ia=function(){var a=this.a.f;r(a,"Can not call getElementStrict before rendering/decorating.");a=a.querySelector("canvas,embed");return new Gb(a.clientWidth,a.clientHeight)};g.Ka=function(){return this.i.a};g.Va=function(a,b){ch(this.a.a,a,b)};g.cb=function(a){if("makeSEngineInMemory"!==this.i.P)throw Error("Can't getSnapshot without sengineType IN_MEMORY.");var b=this.a.a;b.na.push(a);b.a.postMessage(["getSnapshot"])}; -g.gb=function(a){if("makeSEngineInMemory"!==this.i.P)throw Error("Can't loadFromSnapshot without sengineType IN_MEMORY.");var b=this.a.a;a=Uc(b.i,a);a=new Uint8Array(a);b.a.postMessage(["loadFromSnapshot",a.buffer])};g.eb=function(a){X(this.a.a,a)};g.bb=function(){throw Error("getRawEngineObject not supported for NaCl.");}; -g.Ya=function(a,b){var c=this.a.a,d=null.La().get("pages").get(0);if(!d)throw Error("unable to get page from brix document.");d=d.get("elements").Ed();for(var e=[],f=0;f<d.length;f++){var h=d[f];e.push({id:h.get("id"),proto:h.get("proto"),transform:h.get("transform")})}c.W.push(a);c.V.push(b);c.a.postMessage(["convertBrixElements",e])};g.sb=function(a,b){var c=this.a.a;a=Uc(c.i,a);a=new Uint8Array(a);c.oa.push(b);c.a.postMessage(["snapshotHasPendingMutations",a.buffer])}; -g.ab=function(a,b){var c=this.a.a;a=Uc(c.i,a);a=new Uint8Array(a);c.ia.push(b);c.a.postMessage(["extractMutationPacket",a.buffer])};g.Xa=function(a,b){var c=this.a.a;a=Uc(c.i,a);a=new Uint8Array(a);c.X.push(b);c.a.postMessage(["clearPendingMutations",a.buffer])};g.flush=function(a){this.a.flush(a)};g.Ua=function(a){ge(a,function(){throw Error("stickers not implemented on nacl yet");})};ka("ink.embed.Config",function(a){a=a||{};this.j=a.parentEl||null;this.h=a.parentComponent||null;this.f=a.nativeClientManifestUrl||null;this.a=a.logsHost||0;this.P=a.sengineType||"makeSEnginePassthroughDocument"});ka("ink.embed.EmbedComponent",Z);Z.execute=function(a,b){b=new Z(a,b);kd(b,a.h);b.render(a.j)};Z.prototype.clear=Z.prototype.Wa;Z.prototype.undo=Z.prototype.tb;Z.prototype.redo=Z.prototype.hb;Z.prototype.setBackgroundImage=Z.prototype.lb;Z.prototype.setImageToUseForPageBackground=Z.prototype.pb; -Z.prototype.setBackgroundColor=Z.prototype.kb;Z.prototype.setGrid=Z.prototype.ob;Z.prototype.clearGrid=Z.prototype.ra;Z.prototype.exportPng=Z.prototype.$a;Z.prototype.setCallbackFlags=Z.prototype.mb;Z.prototype.setPageBounds=Z.prototype.qb;Z.prototype.deselectAll=Z.prototype.Za;Z.prototype.createDom=Z.prototype.aa;Z.prototype.enterDocument=Z.prototype.v;Z.prototype.setFullscreen=Z.prototype.ub;Z.prototype.addElement=Z.prototype.Ta;Z.prototype.removeElements=Z.prototype.ib; -Z.prototype.resetCanvas=Z.prototype.jb;Z.prototype.setReadOnly=Z.prototype.rb;Z.prototype.setElementTransforms=Z.prototype.nb;Z.prototype.isEmpty=Z.prototype.fb;Z.prototype.getCanvasDimensions=Z.prototype.Ia;Z.prototype.getLogsHost=Z.prototype.Ka;Z.prototype.assignFlag=Z.prototype.Va;Z.prototype.getSnapshot=Z.prototype.cb;Z.prototype.loadFromSnapshot=Z.prototype.gb;Z.prototype.handleCommand=Z.prototype.eb;Z.prototype.getRawEngineObject=Z.prototype.bb;Z.prototype.convertBrixDocumentToSnapshot=Z.prototype.Ya; -Z.prototype.snapshotHasPendingMutations=Z.prototype.sb;Z.prototype.extractMutationPacket=Z.prototype.ab;Z.prototype.clearPendingMutations=Z.prototype.Xa;Z.prototype.flush=Z.prototype.flush;Z.prototype.addSticker=Z.prototype.Ua;ka("ink.BrushModel",W);W.getInstance=W.S;W.prototype.setColor=W.prototype.Ra;W.prototype.setStrokeWidth=W.prototype.Sa;W.prototype.setIsErasing=W.prototype.vb;W.prototype.setShape=W.prototype.wb;W.prototype.getShape=W.prototype.Ma;W.prototype.getColor=W.prototype.Oa; -W.prototype.getActiveColor=W.prototype.pa;W.prototype.getActiveColorNumericRbg=W.prototype.qa;W.prototype.getStrokeWidth=W.prototype.Pa;W.prototype.getIsErasing=W.prototype.Ja;W.prototype.getBrushType=W.prototype.Na;W.prototype.getToolType=W.prototype.Qa;
diff --git a/third_party/ink/prebuilt/wasm/glcore_base.wasm b/third_party/ink/prebuilt/wasm/glcore_base.wasm deleted file mode 100644 index f4661d9..0000000 --- a/third_party/ink/prebuilt/wasm/glcore_base.wasm +++ /dev/null Binary files differ
diff --git a/third_party/ink/prebuilt/wasm/index.html b/third_party/ink/prebuilt/wasm/index.html deleted file mode 100644 index fbf793c..0000000 --- a/third_party/ink/prebuilt/wasm/index.html +++ /dev/null
@@ -1,26 +0,0 @@ -<!DOCTYPE html> -<html> -<!-- -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. ---> - - <head> - <style type="text/css"> - body { margin: 0; } - #ink-canvas { - height: 600px; - width: 800px; - } - </style> - <link rel="icon" href="data:,"> <!-- Prevent favicon.ico requests --> - </head> - <body> - <h1>Ink demo — WebAssembly version</h1> - <div id="ink-canvas"></div> - <script>var STATIC_JS_PREFIX='.'</script> - <script src="ink_lib_binary.js"></script> - <script src="ink_demo.js"></script> - </body> -</html>
diff --git a/third_party/ink/prebuilt/wasm/ink_demo.js b/third_party/ink/prebuilt/wasm/ink_demo.js deleted file mode 100644 index 6adac66..0000000 --- a/third_party/ink/prebuilt/wasm/ink_demo.js +++ /dev/null
@@ -1,18 +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. - -(function() { - var config = new ink.embed.Config({ - parentEl: document.querySelector('#ink-canvas'), - sengineType: 'makeSEngineInMemory' - }); - ink.embed.EmbedComponent.execute(config, (embed) => { - // put the embed component on the window so it's easy to experiment in the console. - window.embed = embed; - - // change the brush color - var brushModel = ink.BrushModel.getInstance(embed); - brushModel.setColor('#FF00FF'); - }); -}());
diff --git a/third_party/ink/prebuilt/wasm/ink_lib_binary.js b/third_party/ink/prebuilt/wasm/ink_lib_binary.js deleted file mode 100644 index 235ca2d..0000000 --- a/third_party/ink/prebuilt/wasm/ink_lib_binary.js +++ /dev/null
@@ -1,522 +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. -var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(g,r,z){g!=Array.prototype&&g!=Object.prototype&&(g[r]=z.value)};$jscomp.getGlobal=function(g){return"undefined"!=typeof window&&window===g?g:"undefined"!=typeof global&&null!=global?global:g};$jscomp.global=$jscomp.getGlobal(this); -$jscomp.polyfill=function(g,r){if(r){var z=$jscomp.global;g=g.split(".");for(var I=0;I<g.length-1;I++){var J=g[I];J in z||(z[J]={});z=z[J]}g=g[g.length-1];I=z[g];r=r(I);r!=I&&null!=r&&$jscomp.defineProperty(z,g,{configurable:!0,writable:!0,value:r})}};$jscomp.polyfill("Math.imul",function(g){return g?g:g=function(g,z){g=Number(g);z=Number(z);var r=g>>>16&65535;g&=65535;var J=z>>>16&65535;z&=65535;r=r*z+g*J<<16>>>0;return g*z+r|0}},"es6","es3"); -$jscomp.polyfill("Math.clz32",function(g){return g?g:g=function(g){g=Number(g)>>>0;if(0===g)return 32;var r=0;0===(g&4294901760)&&(g<<=16,r+=16);0===(g&4278190080)&&(g<<=8,r+=8);0===(g&4026531840)&&(g<<=4,r+=4);0===(g&3221225472)&&(g<<=2,r+=2);0===(g&2147483648)&&r++;return r}},"es6","es3");$jscomp.polyfill("Math.trunc",function(g){return g?g:g=function(g){g=Number(g);if(isNaN(g)||Infinity===g||-Infinity===g||0===g)return g;var r=Math.floor(Math.abs(g));return 0>g?-r:r}},"es6","es3"); -$jscomp.SYMBOL_PREFIX="jscomp_symbol_";$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.Symbol=function(){function g(g){return $jscomp.SYMBOL_PREFIX+(g||"")+r++}var r=0;return g}(); -$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var g=$jscomp.global.Symbol.iterator;g||(g=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[g]&&$jscomp.defineProperty(Array.prototype,g,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(g){var r=0;return $jscomp.iteratorPrototype(function(){return r<g.length?{done:!1,value:g[r++]}:{done:!0}})}; -$jscomp.iteratorPrototype=function(g){$jscomp.initSymbolIterator();g={next:g};g[$jscomp.global.Symbol.iterator]=function(){return this};return g};$jscomp.makeIterator=function(g){$jscomp.initSymbolIterator();var r=g[Symbol.iterator];return r?r.call(g):$jscomp.arrayIterator(g)};$jscomp.FORCE_POLYFILL_PROMISE=!1; -$jscomp.polyfill("Promise",function(g){function r(){this.batch_=null}function z(g){return g instanceof E?g:new E(function(ia){ia(g)})}if(g&&!$jscomp.FORCE_POLYFILL_PROMISE)return g;r.prototype.asyncExecute=function(g){null==this.batch_&&(this.batch_=[],this.asyncExecuteBatch_());this.batch_.push(g);return this};r.prototype.asyncExecuteBatch_=function(){var g=this;this.asyncExecuteFunction(function(){g.executeBatch_()})};var I=$jscomp.global.setTimeout;r.prototype.asyncExecuteFunction=function(g){I(g, -0)};r.prototype.executeBatch_=function(){for(;this.batch_&&this.batch_.length;){var g=this.batch_;this.batch_=[];for(var r=0;r<g.length;++r){var z=g[r];delete g[r];try{z()}catch(X){this.asyncThrow_(X)}}}this.batch_=null};r.prototype.asyncThrow_=function(g){this.asyncExecuteFunction(function(){throw g;})};var J={PENDING:0,FULFILLED:1,REJECTED:2},E=function(g){this.state_=J.PENDING;this.result_=void 0;this.onSettledCallbacks_=[];var r=this.createResolveAndReject_();try{g(r.resolve,r.reject)}catch(Ha){r.reject(Ha)}}; -E.prototype.createResolveAndReject_=function(){function g(g){return function(ia){z||(z=!0,g.call(r,ia))}}var r=this,z=!1;return{resolve:g(this.resolveTo_),reject:g(this.reject_)}};E.prototype.resolveTo_=function(g){if(g===this)this.reject_(new TypeError("A Promise cannot resolve to itself"));else if(g instanceof E)this.settleSameAsPromise_(g);else{a:switch(typeof g){case "object":var r=null!=g;break a;case "function":r=!0;break a;default:r=!1}r?this.resolveToNonPromiseObj_(g):this.fulfill_(g)}};E.prototype.resolveToNonPromiseObj_= -function(g){var r=void 0;try{r=g.then}catch(Ha){this.reject_(Ha);return}"function"==typeof r?this.settleSameAsThenable_(r,g):this.fulfill_(g)};E.prototype.reject_=function(g){this.settle_(J.REJECTED,g)};E.prototype.fulfill_=function(g){this.settle_(J.FULFILLED,g)};E.prototype.settle_=function(g,r){if(this.state_!=J.PENDING)throw Error("Cannot settle("+g+", "+r+"): Promise already settled in state"+this.state_);this.state_=g;this.result_=r;this.executeOnSettledCallbacks_()};E.prototype.executeOnSettledCallbacks_= -function(){if(null!=this.onSettledCallbacks_){for(var g=this.onSettledCallbacks_,r=0;r<g.length;++r)g[r].call(),g[r]=null;this.onSettledCallbacks_=null}};var Sa=new r;E.prototype.settleSameAsPromise_=function(g){var r=this.createResolveAndReject_();g.callWhenSettled_(r.resolve,r.reject)};E.prototype.settleSameAsThenable_=function(g,r){var z=this.createResolveAndReject_();try{g.call(r,z.resolve,z.reject)}catch(X){z.reject(X)}};E.prototype.then=function(g,r){function z(g,r){return"function"==typeof g? -function(r){try{X(g(r))}catch(Y){D(Y)}}:r}var X,D,I=new E(function(g,r){X=g;D=r});this.callWhenSettled_(z(g,X),z(r,D));return I};E.prototype["catch"]=function(g){return this.then(void 0,g)};E.prototype.callWhenSettled_=function(g,r){function z(){switch(E.state_){case J.FULFILLED:g(E.result_);break;case J.REJECTED:r(E.result_);break;default:throw Error("Unexpected state: "+E.state_);}}var E=this;null==this.onSettledCallbacks_?Sa.asyncExecute(z):this.onSettledCallbacks_.push(function(){Sa.asyncExecute(z)})}; -E.resolve=z;E.reject=function(g){return new E(function(r,z){z(g)})};E.race=function(g){return new E(function(r,E){for(var I=$jscomp.makeIterator(g),D=I.next();!D.done;D=I.next())z(D.value).callWhenSettled_(r,E)})};E.all=function(g){var r=$jscomp.makeIterator(g),I=r.next();return I.done?z([]):new E(function(g,D){function E(r){return function(z){J[r]=z;R--;0==R&&g(J)}}var J=[],R=0;do J.push(void 0),R++,z(I.value).callWhenSettled_(E(J.length-1),D),I=r.next();while(!I.done)})};return E},"es6","es3"); -$jscomp.iteratorFromArray=function(g,r){$jscomp.initSymbolIterator();g instanceof String&&(g+="");var z=0,I={next:function(){if(z<g.length){var J=z++;return{value:r(J,g[J]),done:!1}}I.next=function(){return{done:!0,value:void 0}};return I.next()}};I[Symbol.iterator]=function(){return I};return I};$jscomp.polyfill("Array.prototype.entries",function(g){return g?g:g=function(){return $jscomp.iteratorFromArray(this,function(g,z){return[g,z]})}},"es6","es3"); -$jscomp.polyfill("Array.prototype.values",function(g){return g?g:g=function(){return $jscomp.iteratorFromArray(this,function(g,z){return z})}},"es8","es3"); -(function(g){var r=arguments;fetch(STATIC_JS_PREFIX+"/glcore_base.wasm",{credentials:"include"}).then(function(g){return g.arrayBuffer()}).then(function(z){function I(a){D(!Tb);var b=W;W=W+a+15&-16;return b}function J(a){D(oa);var b=p[oa>>2];a=b+a+15&-16;p[oa>>2]=a;return a>=pa&&(pb(),a=void 0,!a)?(p[oa>>2]=b,0):b}function E(a,b){b||(b=16);return a=Math.ceil(a/b)*b}function Sa(a){switch(a){case "i1":case "i8":return 1;case "i16":return 2;case "i32":return 4;case "i64":return 8;case "float":return 4; -case "double":return 8;default:return"*"===a[a.length-1]?4:"i"===a[0]?(a=parseInt(a.substr(1)),D(0===a%8),a/8):0}}function ia(a){ia.shown||(ia.shown={});ia.shown[a]||(ia.shown[a]=1,d.printErr(a))}function xc(a){for(var b=0;b<v.length;b++)if(!v[b])return v[b]=a,1+b;throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.";}function Ha(a,b){if(a){D(b);qb[b]||(qb[b]={});var c=qb[b];c[a]||(c[a]=1===b.length?function(){return X(b,a)}:2===b.length?function(c){return X(b, -a,[c])}:function(){return X(b,a,Array.prototype.slice.call(arguments))});return c[a]}}function X(a,b,c){return c&&c.length?d["dynCall_"+a].apply(null,[b].concat(c)):d["dynCall_"+a].call(null,b)}function D(a,b){a||G("Assertion failed: "+b)}function yc(a,b){b=b||"i8";"*"===b.charAt(b.length-1)&&(b="i32");switch(b){case "i1":return M[a>>0];case "i8":return M[a>>0];case "i16":return ja[a>>1];case "i32":return p[a>>2];case "i64":return p[a>>2];case "float":return u[a>>2];case "double":return Ua[a>>3]; -default:G("invalid type for getValue: "+b)}return null}function Ta(a,b,c,f){if("number"===typeof a){var m=!0;var d=a}else m=!1,d=a.length;var e="string"===typeof b?b:null;c=4==c?f:["function"===typeof ua?ua:I,zc,I,J][void 0===c?2:c](Math.max(d,e?1:b.length));if(m){f=c;D(0==(c&3));for(a=c+(d&-4);f<a;f+=4)p[f>>2]=0;for(a=c+d;f<a;)M[f++>>0]=0;return c}if("i8"===e)return a.subarray||a.slice?F.set(a,c):F.set(new Uint8Array(a),c),c;f=0;for(var K,h;f<d;){var g=a[f];m=e||b[f];if(0===m)f++;else{"i64"==m&& -(m="i32");var P=c+f,k=m;k=k||"i8";"*"===k.charAt(k.length-1)&&(k="i32");switch(k){case "i1":M[P>>0]=g;break;case "i8":M[P>>0]=g;break;case "i16":ja[P>>1]=g;break;case "i32":p[P>>2]=g;break;case "i64":tempI64=[g>>>0,(tempDouble=g,1<=+Vb(tempDouble)?0<tempDouble?(Wb(+Xb(tempDouble/4294967296),4294967295)|0)>>>0:~~+Yb((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)];p[P>>2]=tempI64[0];p[P+4>>2]=tempI64[1];break;case "float":u[P>>2]=g;break;case "double":Ua[P>>3]=g;break;default:G("invalid type for setValue: "+ -k)}h!==m&&(K=Sa(m),h=m);f+=K}}return c}function R(a,b){if(0===b||!a)return"";for(var c=0,f,m=0;;){f=F[a+m>>0];c|=f;if(0==f&&!b)break;m++;if(b&&m==b)break}b||(b=m);f="";if(128>c){for(;0<b;)c=String.fromCharCode.apply(String,F.subarray(a,a+Math.min(b,1024))),f=f?f+c:c,a+=1024,b-=1024;return f}return za(F,a)}function za(a,b){for(var c=b;a[c];)++c;if(16<c-b&&a.subarray&&Zb)return Zb.decode(a.subarray(b,c));for(c="";;){var f=a[b++];if(!f)return c;if(f&128){var m=a[b++]&63;if(192==(f&224))c+=String.fromCharCode((f& -31)<<6|m);else{var d=a[b++]&63;if(224==(f&240))f=(f&15)<<12|m<<6|d;else{var e=a[b++]&63;if(240==(f&248))f=(f&7)<<18|m<<12|d<<6|e;else{var K=a[b++]&63;if(248==(f&252))f=(f&3)<<24|m<<18|d<<12|e<<6|K;else{var h=a[b++]&63;f=(f&1)<<30|m<<24|d<<18|e<<12|K<<6|h}}}65536>f?c+=String.fromCharCode(f):(f-=65536,c+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else c+=String.fromCharCode(f)}}function Y(a,b,c,f){if(!(0<f))return 0;var m=c;f=c+f-1;for(var d=0;d<a.length;++d){var e=a.charCodeAt(d);55296<=e&&57343>= -e&&(e=65536+((e&1023)<<10)|a.charCodeAt(++d)&1023);if(127>=e){if(c>=f)break;b[c++]=e}else{if(2047>=e){if(c+1>=f)break;b[c++]=192|e>>6}else{if(65535>=e){if(c+2>=f)break;b[c++]=224|e>>12}else{if(2097151>=e){if(c+3>=f)break;b[c++]=240|e>>18}else{if(67108863>=e){if(c+4>=f)break;b[c++]=248|e>>24}else{if(c+5>=f)break;b[c++]=252|e>>30;b[c++]=128|e>>24&63}b[c++]=128|e>>18&63}b[c++]=128|e>>12&63}b[c++]=128|e>>6&63}b[c++]=128|e&63}}b[c]=0;return c-m}function Va(a){for(var b=0,c=0;c<a.length;++c){var f=a.charCodeAt(c); -55296<=f&&57343>=f&&(f=65536+((f&1023)<<10)|a.charCodeAt(++c)&1023);127>=f?++b:b=2047>=f?b+2:65535>=f?b+3:2097151>=f?b+4:67108863>=f?b+5:b+6}return b}function Cc(a){var b=/__Z[\w\d_]+/g;return a.replace(b,function(a){var b=a;return a===b?a:a+" ["+b+"]"})}function $b(){d.HEAP8=M=new Int8Array(V);d.HEAP16=ja=new Int16Array(V);d.HEAP32=p=new Int32Array(V);d.HEAPU8=F=new Uint8Array(V);d.HEAPU16=Aa=new Uint16Array(V);d.HEAPU32=S=new Uint32Array(V);d.HEAPF32=u=new Float32Array(V);d.HEAPF64=Ua=new Float64Array(V)} -function pb(){G("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+pa+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")}function Dc(){pb()}function Ec(){return pa}function Ia(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b();else{var c=b.func;"number"===typeof c?void 0===b.arg? -d.dynCall_v(c):d.dynCall_vi(c,b.arg):c(void 0===b.arg?null:b.arg)}}}function rb(){va++;d.monitorRunDependencies&&d.monitorRunDependencies(va)}function Wa(){va--;d.monitorRunDependencies&&d.monitorRunDependencies(va);if(0==va&&(null!==sb&&(clearInterval(sb),sb=null),Ja)){var a=Ja;Ja=null;a()}}function Xa(a){return String.prototype.startsWith?a.startsWith("data:application/octet-stream;base64,"):0===a.indexOf("data:application/octet-stream;base64,")}function Fc(){function a(){try{if(d.wasmBinary)return new Uint8Array(d.wasmBinary); -if(d.readBinary)return d.readBinary(m);throw"on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)";}catch(P){G(P)}}function b(){return d.wasmBinary||!wa&&!Z||"function"!==typeof fetch?new Promise(function(b){b(a())}):fetch(m,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+m+"'";return a.arrayBuffer()})["catch"](function(){return a()})}function c(a,c){function f(a){K= -a.exports;if(K.memory){a=K.memory;var b=d.buffer;a.byteLength<b.byteLength&&d.printErr("the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here");b=new Int8Array(b);var c=new Int8Array(a);c.set(b);d.buffer=V=a;$b()}d.asm=K;d.usingWasm=!0;Wa("wasm-instantiate")}function t(a){f(a.instance,a.module)}function n(a){b().then(function(a){return WebAssembly.instantiate(a,e)}).then(a)["catch"](function(a){d.printErr("failed to asynchronously prepare wasm: "+ -a);G(a)})}if("object"!==typeof WebAssembly)return d.printErr("no native wasm support detected"),!1;if(!(d.wasmMemory instanceof WebAssembly.Memory))return d.printErr("no native wasm Memory in use"),!1;c.memory=d.wasmMemory;e.global={NaN:NaN,Infinity:Infinity};e["global.Math"]=Math;e.env=c;rb("wasm-instantiate");if(d.instantiateWasm)try{return d.instantiateWasm(e,f)}catch(Gc){return d.printErr("Module.instantiateWasm callback failed with error: "+Gc),!1}d.wasmBinary||"function"!==typeof WebAssembly.instantiateStreaming|| -Xa(m)||"function"!==typeof fetch?n(t):WebAssembly.instantiateStreaming(fetch(m,{credentials:"same-origin"}),e).then(t)["catch"](function(a){d.printErr("wasm streaming compile failed: "+a);d.printErr("falling back to ArrayBuffer instantiation");n(t)});return{}}var f="glcore_base.wast",m="glcore_base.wasm",t="glcore_base.temp.asm.js";"function"===typeof d.locateFile&&(Xa(f)||(f=d.locateFile(f)),Xa(m)||(m=d.locateFile(m)),Xa(t)||(t=d.locateFile(t)));var e={global:null,env:null,asm2wasm:{"f64-rem":function(a, -b){return a%b},"debugger":function(){debugger}},parent:d},K=null;d.asmPreload=d.asm;var h=d.reallocBuffer;d.reallocBuffer=function(a){if("asmjs"===g)var b=h(a);else a:{var c=d.usingWasm?65536:16777216;0<a%c&&(a+=c-a%c);c=d.buffer;c=c.byteLength;if(d.usingWasm)try{var f=d.wasmMemory.grow((a-c)/65536);b=-1!==f?d.buffer=d.wasmMemory.buffer:null;break a}catch(wl){b=null;break a}b=void 0}return b};var g="";d.asm=function(a,b,f){if(!b.table){var m=d.wasmTableSize;void 0===m&&(m=1024);var e=d.wasmMaxTableSize; -b.table="object"===typeof WebAssembly&&"function"===typeof WebAssembly.Table?void 0!==e?new WebAssembly.Table({initial:m,maximum:e,element:"anyfunc"}):new WebAssembly.Table({initial:m,element:"anyfunc"}):Array(m);d.wasmTable=b.table}b.memoryBase||(b.memoryBase=d.STATIC_BASE);b.tableBase||(b.tableBase=0);(a=c(a,b,f))||G("no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods");return a}} -function Hc(a){return Ic[a]()}function Ka(){return!!Ka.uncaught_exception}function Jc(a,b,c,f){G("Assertion failed: "+R(a)+", at: "+[b?R(b):"unknown filename",c,f?R(f):"unknown function"])}function Kc(a){return ua(a)}function Lc(){da=!0;throw"Pure virtual function called!";}function Mc(a,b,c){ka.infos[a]={ptr:a,adjusted:a,type:b,destructor:c,refcount:0,caught:!1,rethrown:!1};ka.last=a;"uncaught_exception"in Ka?Ka.uncaught_exception++:Ka.uncaught_exception=1;throw a+" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch."; -}function Nc(){}function Ba(a){d.___errno_location&&(p[d.___errno_location()>>2]=a);return a}function Oc(){Ba(q.EPERM);return-1}function Pc(a,b){C.varargs=b;try{var c=C.getStreamFromFD();C.get();var f=C.get(),m=C.get(),d=C.get();a=f;e.llseek(c,a,d);p[m>>2]=c.position;c.getdents&&0===a&&0===d&&(c.getdents=null);return 0}catch(n){return"undefined"!==typeof e&&n instanceof e.ErrnoError||G(n),-n.errno}}function Qc(a,b){C.varargs=b;try{var c=C.getStreamFromFD(),f=C.get(),m=C.get();return C.doReadv(c,f, -m)}catch(t){return"undefined"!==typeof e&&t instanceof e.ErrnoError||G(t),-t.errno}}function Rc(a,b){C.varargs=b;try{var c=C.getStreamFromFD(),f=C.get(),m=C.get();return C.doWritev(c,f,m)}catch(t){return"undefined"!==typeof e&&t instanceof e.ErrnoError||G(t),-t.errno}}function Sc(a,b){C.varargs=b;try{var c=C.getStreamFromFD(),f=C.get();switch(f){case 21509:case 21505:return c.tty?0:-q.ENOTTY;case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:return c.tty?0:-q.ENOTTY;case 21519:if(!c.tty)return-q.ENOTTY; -var m=C.get();return p[m>>2]=0;case 21520:return c.tty?-q.EINVAL:-q.ENOTTY;case 21531:return m=C.get(),e.ioctl(c,f,m);case 21523:return c.tty?0:-q.ENOTTY;default:G("bad ioctl syscall "+f)}}catch(t){return"undefined"!==typeof e&&t instanceof e.ErrnoError||G(t),-t.errno}}function Tc(a,b){C.varargs=b;try{var c=C.getStreamFromFD();e.close(c);return 0}catch(f){return"undefined"!==typeof e&&f instanceof e.ErrnoError||G(f),-f.errno}}function Uc(a,b){C.varargs=b;try{var c=C.get(),f=C.get(),m=C.mappings[c]; -if(!m)return 0;if(f===m.len){var d=e.getStream(m.fd);C.doMsync(c,d,f,m.flags);C.mappings[c]=null;m.allocated&&ea(m.malloc)}return 0}catch(n){return"undefined"!==typeof e&&n instanceof e.ErrnoError||G(n),-n.errno}}function Vc(){}function ac(a){if(void 0===a)return"_unknown";a=a.replace(/[^a-zA-Z0-9_]/g,"$");var b=a.charCodeAt(0);return 48<=b&&57>=b?"_"+a:a}function Ya(a,b){a=ac(a);return function(){return b.apply(this,arguments)}}function Wc(){for(var a=0,b=5;b<T.length;++b)void 0!==T[b]&&++a;return a} -function Xc(){for(var a=5;a<T.length;++a)if(void 0!==T[a])return T[a];return null}function aa(a){switch(a){case void 0:return 1;case null:return 2;case !0:return 3;case !1:return 4;default:var b=tb.length?tb.pop():T.length;T[b]={refcount:1,value:a};return b}}function Za(a,b){var c=Ya(b,function(a){this.name=b;this.message=a;a=Error(a).stack;void 0!==a&&(this.stack=this.toString()+"\n"+a.replace(/^Error(:[^\n]*)?\n/,""))});c.prototype=Object.create(a.prototype);c.prototype.constructor=c;c.prototype.toString= -function(){return void 0===this.message?this.name:this.name+": "+this.message};return c}function Yc(){for(var a=Array(256),b=0;256>b;++b)a[b]=String.fromCharCode(b);bc=a}function O(a){for(var b="";F[a];)b+=bc[F[a++]];return b}function Zc(){return Object.keys(la).length}function $c(){var a=[],b;for(b in la)la.hasOwnProperty(b)&&a.push(la[b]);return a}function ub(){for(;La.length;){var a=La.pop();a.$$.deleteScheduled=!1;a["delete"]()}}function ad(a){Ma=a;La.length&&Ma&&Ma(ub)}function B(a){throw new Ca(a); -}function vb(a,b){for(void 0===b&&B("ptr should not be undefined");a.baseClass;)b=a.upcast(b),a=a.baseClass;return b}function ma(a){a||B("Cannot use deleted val. handle = "+a);return T[a].value}function cc(a){a=bd(a);var b=O(a);ea(a);return b}function Na(a,b){var c=xa[a];void 0===c&&B(b+" has unknown type "+cc(a));return c}function cd(a,b,c){a=O(a);b=Na(b,"wrapper");c=ma(c);var f=[].slice,d=b.registeredClass,e=d.instancePrototype;b=d.baseClass;var n=b.instancePrototype,K=d.baseClass.constructor;a= -Ya(a,function(){d.baseClass.pureVirtualFunctions.forEach(function(a){if(this[a]===n[a])throw new dc("Pure virtual function "+a+" must be implemented in JavaScript");}.bind(this));Object.defineProperty(this,"__parent",{value:e});this.__construct.apply(this,f.call(arguments))});e.__construct=function(){this===e&&B("Pass correct 'this' to __construct");var a=K.implement.apply(void 0,[this].concat(f.call(arguments))),b=a.$$;a.notifyOnDestruction();b.preservePointerOnDelete=!0;Object.defineProperties(this, -{$$:{value:b}});a=b.ptr;a=vb(d,a);la.hasOwnProperty(a)?B("Tried to register registered instance: "+a):la[a]=this};e.__destruct=function(){this===e&&B("Pass correct 'this' to __destruct");var a=this.$$.ptr;a=vb(d,a);la.hasOwnProperty(a)?delete la[a]:B("Tried to unregister unregistered instance: "+a)};a.prototype=Object.create(e);for(var h in c)a.prototype[h]=c[h];return aa(a)}function Oa(a){for(;a.length;){var b=a.pop(),c=a.pop();c(b)}}function Pa(a){return this.fromWireType(S[a>>2])}function $a(a){throw new ec(a); -}function ba(a,b,c){function f(b){b=c(b);b.length!==a.length&&$a("Mismatched type converter count");for(var f=0;f<a.length;++f)fa(a[f],b[f])}a.forEach(function(a){ab[a]=b});var d=Array(b.length),e=[],n=0;b.forEach(function(a,b){xa.hasOwnProperty(a)?d[b]=xa[a]:(e.push(a),Da.hasOwnProperty(a)||(Da[a]=[]),Da[a].push(function(){d[b]=xa[a];++n;n===e.length&&f(d)}))});0===e.length&&f(d)}function dd(a){var b=bb[a];delete bb[a];var c=b.elements,f=c.length,d=c.map(function(a){return a.getterReturnType}).concat(c.map(function(a){return a.setterArgumentType})), -e=b.rawConstructor,n=b.rawDestructor;ba([a],d,function(a){c.forEach(function(b,c){var d=a[c],m=b.getter,e=b.getterContext,t=a[c+f],n=b.setter,h=b.setterContext;b.read=function(a){return d.fromWireType(m(e,a))};b.write=function(a,b){var c=[];n(h,a,t.toWireType(c,b));Oa(c)}});return[{name:b.name,fromWireType:function(a){for(var b=Array(f),d=0;d<f;++d)b[d]=c[d].read(a);n(a);return b},toWireType:function(a,d){if(f!==d.length)throw new TypeError("Incorrect number of tuple elements for "+b.name+": expected="+ -f+", actual="+d.length);for(var m=e(),t=0;t<f;++t)c[t].write(m,d[t]);null!==a&&a.push(n,m);return m},argPackAdvance:8,readValueFromPointer:Pa,destructorFunction:n}]})}function cb(a){switch(a){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+a);}}function fa(a,b,c){c=c||{};if(!("argPackAdvance"in b))throw new TypeError("registerType registeredInstance requires argPackAdvance");var f=b.name;a||B('type "'+f+'" must have a positive integer typeid pointer'); -if(xa.hasOwnProperty(a)){if(c.ignoreDuplicateRegistrations)return;B("Cannot register type '"+f+"' twice")}xa[a]=b;delete ab[a];Da.hasOwnProperty(a)&&(b=Da[a],delete Da[a],b.forEach(function(a){a()}))}function ed(a,b,c,f,d){var m=cb(c);b=O(b);fa(a,{name:b,fromWireType:function(a){return!!a},toWireType:function(a,b){return b?f:d},argPackAdvance:8,readValueFromPointer:function(a){if(1===c)var f=M;else if(2===c)f=ja;else if(4===c)f=p;else throw new TypeError("Unknown boolean type size: "+b);return this.fromWireType(f[a>> -m])},destructorFunction:null})}function fd(a){if(!(this instanceof qa&&a instanceof qa))return!1;var b=this.$$.ptrType.registeredClass,c=this.$$.ptr,f=a.$$.ptrType.registeredClass;for(a=a.$$.ptr;b.baseClass;)c=b.upcast(c),b=b.baseClass;for(;f.baseClass;)a=f.upcast(a),f=f.baseClass;return b===f&&c===a}function wb(a){B(a.$$.ptrType.registeredClass.name+" instance already deleted")}function gd(){this.$$.ptr||wb(this);if(this.$$.preservePointerOnDelete)return this.$$.count.value+=1,this;var a=this.$$; -a={count:a.count,deleteScheduled:a.deleteScheduled,preservePointerOnDelete:a.preservePointerOnDelete,ptr:a.ptr,ptrType:a.ptrType,smartPtr:a.smartPtr,smartPtrType:a.smartPtrType};a=Object.create(Object.getPrototypeOf(this),{$$:{value:a}});a.$$.count.value+=1;a.$$.deleteScheduled=!1;return a}function hd(){this.$$.ptr||wb(this);this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete&&B("Object already scheduled for deletion");--this.$$.count.value;var a=0===this.$$.count.value;a&&(a=this.$$,a.smartPtr? -a.smartPtrType.rawDestructor(a.smartPtr):a.ptrType.registeredClass.rawDestructor(a.ptr));this.$$.preservePointerOnDelete||(this.$$.smartPtr=void 0,this.$$.ptr=void 0)}function id(){return!this.$$.ptr}function jd(){this.$$.ptr||wb(this);this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete&&B("Object already scheduled for deletion");La.push(this);1===La.length&&Ma&&Ma(ub);this.$$.deleteScheduled=!0;return this}function qa(){}function xb(a,b,c){if(void 0===a[b].overloadTable){var f=a[b];a[b]=function(){a[b].overloadTable.hasOwnProperty(arguments.length)|| -B("Function '"+c+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+a[b].overloadTable+")!");return a[b].overloadTable[arguments.length].apply(this,arguments)};a[b].overloadTable=[];a[b].overloadTable[f.argCount]=f}}function yb(a,b,c){d.hasOwnProperty(a)?((void 0===c||void 0!==d[a].overloadTable&&void 0!==d[a].overloadTable[c])&&B("Cannot register public name '"+a+"' twice"),xb(d,a,a),d.hasOwnProperty(c)&&B("Cannot register multiple overloads of a function with the same number of arguments ("+ -c+")!"),d[a].overloadTable[c]=b):(d[a]=b,void 0!==c&&(d[a].numArguments=c))}function kd(a,b,c,f,d,e,n,h){this.name=a;this.constructor=b;this.instancePrototype=c;this.rawDestructor=f;this.baseClass=d;this.getActualType=e;this.upcast=n;this.downcast=h;this.pureVirtualFunctions=[]}function db(a,b,c){for(;b!==c;)b.upcast||B("Expected null or instance of "+c.name+", got an instance of "+b.name),a=b.upcast(a),b=b.baseClass;return a}function ld(a,b){if(null===b)return this.isReference&&B("null is not a valid "+ -this.name),0;b.$$||B('Cannot pass "'+Ea(b)+'" as a '+this.name);b.$$.ptr||B("Cannot pass deleted object as a pointer of type "+this.name);a=b.$$.ptrType.registeredClass;return b=db(b.$$.ptr,a,this.registeredClass)}function md(a,b){if(null===b){this.isReference&&B("null is not a valid "+this.name);if(this.isSmartPointer){var c=this.rawConstructor();null!==a&&a.push(this.rawDestructor,c);return c}return 0}b.$$||B('Cannot pass "'+Ea(b)+'" as a '+this.name);b.$$.ptr||B("Cannot pass deleted object as a pointer of type "+ -this.name);!this.isConst&&b.$$.ptrType.isConst&&B("Cannot convert argument of type "+(b.$$.smartPtrType?b.$$.smartPtrType.name:b.$$.ptrType.name)+" to parameter type "+this.name);c=b.$$.ptrType.registeredClass;c=db(b.$$.ptr,c,this.registeredClass);if(this.isSmartPointer)switch(void 0===b.$$.smartPtr&&B("Passing raw pointer to smart pointer is illegal"),this.sharingPolicy){case 0:b.$$.smartPtrType===this?c=b.$$.smartPtr:B("Cannot convert argument of type "+(b.$$.smartPtrType?b.$$.smartPtrType.name: -b.$$.ptrType.name)+" to parameter type "+this.name);break;case 1:c=b.$$.smartPtr;break;case 2:if(b.$$.smartPtrType===this)c=b.$$.smartPtr;else{var f=b.clone();c=this.rawShare(c,aa(function(){f["delete"]()}));null!==a&&a.push(this.rawDestructor,c)}break;default:B("Unsupporting sharing policy")}return c}function nd(a,b){if(null===b)return this.isReference&&B("null is not a valid "+this.name),0;b.$$||B('Cannot pass "'+Ea(b)+'" as a '+this.name);b.$$.ptr||B("Cannot pass deleted object as a pointer of type "+ -this.name);b.$$.ptrType.isConst&&B("Cannot convert argument of type "+b.$$.ptrType.name+" to parameter type "+this.name);a=b.$$.ptrType.registeredClass;return b=db(b.$$.ptr,a,this.registeredClass)}function od(a){this.rawGetPointee&&(a=this.rawGetPointee(a));return a}function pd(a){this.rawDestructor&&this.rawDestructor(a)}function qd(a){if(null!==a)a["delete"]()}function fc(a,b,c){if(b===c)return a;if(void 0===c.baseClass)return null;a=fc(a,b,c.baseClass);return null===a?null:c.downcast(a)}function rd(a, -b){b=vb(a,b);return la[b]}function eb(a,b){b.ptrType&&b.ptr||$a("makeClassHandle requires ptr and ptrType");var c=!!b.smartPtrType,f=!!b.smartPtr;c!==f&&$a("Both smartPtrType and smartPtr must be specified");b.count={value:1};return Object.create(a,{$$:{value:b}})}function sd(a){function b(){return this.isSmartPointer?eb(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:c,smartPtrType:this,smartPtr:a}):eb(this.registeredClass.instancePrototype,{ptrType:this,ptr:a})}var c=this.getPointee(a); -if(!c)return this.destructor(a),null;var f=rd(this.registeredClass,c);if(void 0!==f){if(0===f.$$.count.value)return f.$$.ptr=c,f.$$.smartPtr=a,f.clone();f=f.clone();this.destructor(a);return f}f=this.registeredClass.getActualType(c);f=gc[f];if(!f)return b.call(this);f=this.isConst?f.constPointerType:f.pointerType;var d=fc(c,this.registeredClass,f.registeredClass);return null===d?b.call(this):this.isSmartPointer?eb(f.registeredClass.instancePrototype,{ptrType:f,ptr:d,smartPtrType:this,smartPtr:a}): -eb(f.registeredClass.instancePrototype,{ptrType:f,ptr:d})}function na(a,b,c,f,d,e,n,h,g,k,l){this.name=a;this.registeredClass=b;this.isReference=c;this.isConst=f;this.isSmartPointer=d;this.pointeeType=e;this.sharingPolicy=n;this.rawGetPointee=h;this.rawConstructor=g;this.rawShare=k;this.rawDestructor=l;d||void 0!==b.baseClass?this.toWireType=md:(this.toWireType=f?ld:nd,this.destructorFunction=null)}function hc(a,b,c){d.hasOwnProperty(a)||$a("Replacing nonexistant public symbol");void 0!==d[a].overloadTable&& -void 0!==c?d[a].overloadTable[c]=b:(d[a]=b,d[a].argCount=c)}function U(a,b){function c(a){return function(){var c=Array(arguments.length+1);c[0]=b;for(var f=0;f<arguments.length;f++)c[f+1]=arguments[f];return a.apply(null,c)}}a=O(a);if(void 0!==d["FUNCTION_TABLE_"+a])var f=d["FUNCTION_TABLE_"+a][b];else"undefined"!==typeof FUNCTION_TABLE?f=FUNCTION_TABLE[b]:(f=d.asm["dynCall_"+a],void 0===f&&(f=d.asm["dynCall_"+a.replace(/f/g,"d")],void 0===f&&B("No dynCall invoker for signature: "+a)),f=c(f));"function"!== -typeof f&&B("unknown function pointer with signature "+a+": "+b);return f}function ya(a,b){function c(a){d[a]||xa[a]||(ab[a]?ab[a].forEach(c):(f.push(a),d[a]=!0))}var f=[],d={};b.forEach(c);throw new ic(a+": "+f.map(cc).join([", "]));}function td(a,b,c,f,d,e,n,h,g,k,l,p,q){l=O(l);e=U(d,e);h&&(h=U(n,h));k&&(k=U(g,k));q=U(p,q);var m=ac(l);yb(m,function(){ya("Cannot construct "+l+" due to unbound types",[f])});ba([a,b,c],f?[f]:[],function(b){b=b[0];if(f){var c=b.registeredClass;var d=c.instancePrototype}else d= -qa.prototype;b=Ya(m,function(){if(Object.getPrototypeOf(this)!==t)throw new Ca("Use 'new' to construct "+l);if(void 0===n.constructor_body)throw new Ca(l+" has no accessible constructor");var a=n.constructor_body[arguments.length];if(void 0===a)throw new Ca("Tried to invoke ctor of "+l+" with invalid number of parameters ("+arguments.length+") - expected ("+Object.keys(n.constructor_body).toString()+") parameters instead!");return a.apply(this,arguments)});var t=Object.create(d,{constructor:{value:b}}); -b.prototype=t;var n=new kd(l,b,t,q,c,e,h,k);c=new na(l,n,!0,!1,!1);d=new na(l+"*",n,!1,!1,!1);var g=new na(l+" const*",n,!1,!0,!1);gc[a]={pointerType:d,constPointerType:g};hc(m,b);return[c,d,g]})}function zb(a,b,c,f,d){var m=b.length;2>m&&B("argTypes array size mismatch! Must at least get return value and 'this' types!");var e=null!==b[1]&&null!==c,h=!1;for(c=1;c<b.length;++c)if(null!==b[c]&&void 0===b[c].destructorFunction){h=!0;break}var g="void"!==b[0].name,k=Array(m-2);return function(){arguments.length!== -m-2&&B("function "+a+" called with "+arguments.length+" arguments, expected "+(m-2)+" args!");var c=h?[]:null,t;e&&(t=b[1].toWireType(c,this));for(var n=0;n<m-2;++n)k[n]=b[n+2].toWireType(c,arguments[n]);n=e?[d,t]:[d];var K=f.apply(null,n.concat(k));if(h)Oa(c);else for(n=e?1:2;n<b.length;n++)c=1===n?t:k[n-2],null!==b[n].destructorFunction&&b[n].destructorFunction(c);if(g)return b[0].fromWireType(K)}}function fb(a,b){for(var c=[],f=0;f<a;f++)c.push(p[(b>>2)+f]);return c}function ud(a,b,c,f,d,e,n){var m= -fb(c,f);b=O(b);e=U(d,e);ba([],[a],function(a){function f(){ya("Cannot call "+d+" due to unbound types",m)}a=a[0];var d=a.name+"."+b,t=a.registeredClass.constructor;void 0===t[b]?(f.argCount=c-1,t[b]=f):(xb(t,b,d),t[b].overloadTable[c-1]=f);ba([],m,function(a){a=[a[0],null].concat(a.slice(1));a=zb(d,a,null,e,n);void 0===t[b].overloadTable?t[b]=a:t[b].overloadTable[c-1]=a;return[]});return[]})}function vd(a,b,c,f,d,e){var m=fb(b,c);d=U(f,d);ba([],[a],function(a){a=a[0];var c="constructor "+a.name;void 0=== -a.registeredClass.constructor_body&&(a.registeredClass.constructor_body=[]);if(void 0!==a.registeredClass.constructor_body[b-1])throw new Ca("Cannot register multiple constructors with identical number of parameters ("+(b-1)+") for class '"+a.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!");a.registeredClass.constructor_body[b-1]=function(){ya("Cannot construct "+a.name+" due to unbound types",m)};ba([],m,function(f){a.registeredClass.constructor_body[b- -1]=function(){arguments.length!==b-1&&B(c+" called with "+arguments.length+" arguments, expected "+(b-1));var a=[],m=Array(b);m[0]=e;for(var t=1;t<b;++t)m[t]=f[t].toWireType(a,arguments[t-1]);m=d.apply(null,m);Oa(a);return f[0].fromWireType(m)};return[]});return[]})}function wd(a,b,c,f,d,e,n,h){var m=fb(c,f);b=O(b);e=U(d,e);ba([],[a],function(a){function f(){ya("Cannot call "+d+" due to unbound types",m)}a=a[0];var d=a.name+"."+b;h&&a.registeredClass.pureVirtualFunctions.push(b);var t=a.registeredClass.instancePrototype, -g=t[b];void 0===g||void 0===g.overloadTable&&g.className!==a.name&&g.argCount===c-2?(f.argCount=c-2,f.className=a.name,t[b]=f):(xb(t,b,d),t[b].overloadTable[c-2]=f);ba([],m,function(f){f=zb(d,f,a,e,n);void 0===t[b].overloadTable?(f.argCount=c-2,t[b]=f):t[b].overloadTable[c-2]=f;return[]});return[]})}function jc(a,b,c){a instanceof Object||B(c+' with invalid "this": '+a);a instanceof b.registeredClass.constructor||B(c+' incompatible with "this" of type '+a.constructor.name);a.$$.ptr||B("cannot call emscripten binding method "+ -c+" on deleted object");return db(a.$$.ptr,a.$$.ptrType.registeredClass,b.registeredClass)}function xd(a,b,c,f,d,e,n,h,g,k){b=O(b);d=U(f,d);ba([],[a],function(a){a=a[0];var f=a.name+"."+b,m={get:function(){ya("Cannot access "+f+" due to unbound types",[c,n])},enumerable:!0,configurable:!0};m.set=g?function(){ya("Cannot access "+f+" due to unbound types",[c,n])}:function(){B(f+" is a read-only property")};Object.defineProperty(a.registeredClass.instancePrototype,b,m);ba([],g?[c,n]:[c],function(c){var m= -c[0],t={get:function(){var b=jc(this,a,f+" getter");return m.fromWireType(d(e,b))},enumerable:!0};if(g){g=U(h,g);var n=c[1];t.set=function(b){var c=jc(this,a,f+" setter"),d=[];g(k,c,n.toWireType(d,b));Oa(d)}}Object.defineProperty(a.registeredClass.instancePrototype,b,t);return[]});return[]})}function Ab(a){4<a&&0===--T[a].refcount&&(T[a]=void 0,tb.push(a))}function yd(a,b){b=O(b);fa(a,{name:b,fromWireType:function(a){var b=T[a].value;Ab(a);return b},toWireType:function(a,b){return aa(b)},argPackAdvance:8, -readValueFromPointer:Pa,destructorFunction:null})}function zd(a,b,c){switch(b){case 0:return function(a){var b=c?M:F;return this.fromWireType(b[a])};case 1:return function(a){var b=c?ja:Aa;return this.fromWireType(b[a>>1])};case 2:return function(a){var b=c?p:S;return this.fromWireType(b[a>>2])};default:throw new TypeError("Unknown integer type: "+a);}}function Ad(a,b,c,f){function d(){}c=cb(c);b=O(b);d.values={};fa(a,{name:b,constructor:d,fromWireType:function(a){return this.constructor.values[a]}, -toWireType:function(a,b){return b.value},argPackAdvance:8,readValueFromPointer:zd(b,c,f),destructorFunction:null});yb(b,d)}function Bd(a,b,c){var f=Na(a,"enum");b=O(b);a=f.constructor;f=Object.create(f.constructor.prototype,{value:{value:c},constructor:{value:Ya(f.name+"_"+b,function(){})}});a.values[c]=f;a[b]=f}function Ea(a){if(null===a)return"null";var b=typeof a;return"object"===b||"array"===b||"function"===b?a.toString():""+a}function Cd(a,b){switch(b){case 2:return function(a){return this.fromWireType(u[a>> -2])};case 3:return function(a){return this.fromWireType(Ua[a>>3])};default:throw new TypeError("Unknown float type: "+a);}}function Dd(a,b,c){c=cb(c);b=O(b);fa(a,{name:b,fromWireType:function(a){return a},toWireType:function(a,b){if("number"!==typeof b&&"boolean"!==typeof b)throw new TypeError('Cannot convert "'+Ea(b)+'" to '+this.name);return b},argPackAdvance:8,readValueFromPointer:Cd(b,c),destructorFunction:null})}function Ed(a,b,c,f,d,e){var m=fb(b,c);a=O(a);d=U(f,d);yb(a,function(){ya("Cannot call "+ -a+" due to unbound types",m)},b-1);ba([],m,function(c){c=[c[0],null].concat(c.slice(1));hc(a,zb(a,c,null,d,e),b-1);return[]})}function Fd(a,b,c){switch(b){case 0:return c?function(a){return M[a]}:function(a){return F[a]};case 1:return c?function(a){return ja[a>>1]}:function(a){return Aa[a>>1]};case 2:return c?function(a){return p[a>>2]}:function(a){return S[a>>2]};default:throw new TypeError("Unknown integer type: "+a);}}function Gd(a,b,c,f,d){b=O(b);-1===d&&(d=4294967295);var m=cb(c),e=function(a){return a}; -if(0===f){var h=32-8*c;e=function(a){return a<<h>>>h}}var g=-1!=b.indexOf("unsigned");fa(a,{name:b,fromWireType:e,toWireType:function(a,c){if("number"!==typeof c&&"boolean"!==typeof c)throw new TypeError('Cannot convert "'+Ea(c)+'" to '+this.name);if(c<f||c>d)throw new TypeError('Passing a number "'+Ea(c)+'" from JS side to C/C++ side to an argument of type "'+b+'", which is outside the valid range ['+f+", "+d+"]!");return g?c>>>0:c|0},argPackAdvance:8,readValueFromPointer:Fd(b,m,0!==f),destructorFunction:null})} -function Hd(a,b,c){function f(a){a>>=2;var b=S,c=b[a];a=b[a+1];return new e(b.buffer,a,c)}var d=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],e=d[b];c=O(c);fa(a,{name:c,fromWireType:f,argPackAdvance:8,readValueFromPointer:f},{ignoreDuplicateRegistrations:!0})}function Id(a,b){b=O(b);fa(a,{name:b,fromWireType:function(a){for(var b=S[a>>2],c=Array(b),d=0;d<b;++d)c[d]=String.fromCharCode(F[a+4+d]);ea(a);return c.join("")},toWireType:function(a,b){function c(a, -b){return a[b]}function f(a,b){return a.charCodeAt(b)}b instanceof ArrayBuffer&&(b=new Uint8Array(b));var d;b instanceof Uint8Array?d=c:b instanceof Uint8ClampedArray?d=c:b instanceof Int8Array?d=c:"string"===typeof b?d=f:B("Cannot pass non-string to std::string");var e=b.length,h=ua(4+e);S[h>>2]=e;for(var g=0;g<e;++g){var k=d(b,g);255<k&&(ea(h),B("String has UTF-16 code units that do not fit in 8 bits"));F[h+4+g]=k}null!==a&&a.push(ea,h);return h},argPackAdvance:8,readValueFromPointer:Pa,destructorFunction:function(a){ea(a)}})} -function Jd(a,b,c){c=O(c);if(2===b){var f=function(){return Aa};var d=1}else 4===b&&(f=function(){return S},d=2);fa(a,{name:c,fromWireType:function(a){for(var b=f(),c=S[a>>2],m=Array(c),e=a+4>>d,t=0;t<c;++t)m[t]=String.fromCharCode(b[e+t]);ea(a);return m.join("")},toWireType:function(a,c){var m=f(),e=c.length,t=ua(4+e*b);S[t>>2]=e;for(var n=t+4>>d,h=0;h<e;++h)m[n+h]=c.charCodeAt(h);null!==a&&a.push(ea,t);return t},argPackAdvance:8,readValueFromPointer:Pa,destructorFunction:function(a){ea(a)}})}function Kd(a, -b,c,f,d,e){bb[a]={name:O(b),rawConstructor:U(c,f),rawDestructor:U(d,e),elements:[]}}function Ld(a,b,c,f,d,e,n,h,g){bb[a].elements.push({getterReturnType:b,getter:U(c,f),getterContext:d,setterArgumentType:e,setter:U(n,h),setterContext:g})}function Md(a,b){b=O(b);fa(a,{isVoid:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})}function Nd(a,b,c){a=ma(a);b=Na(b,"emval::as");var f=[],d=aa(f);p[c>>2]=d;return b.toWireType(f,a)}function Od(a){var b=[];p[a>>2]=aa(b);return b}function gb(a){var b= -Pd[a];return void 0===b?O(a):b}function Qd(a,b,c,f,d){a=hb[a];b=ma(b);c=gb(c);return a(b,c,Od(f),d)}function Rd(a,b,c,f){a=hb[a];b=ma(b);c=gb(c);a(b,c,null,f)}function kc(){function a(a){a.$$$embind_global$$$=a;var b="object"===typeof $$$embind_global$$$&&a.$$$embind_global$$$===a;b||delete a.$$$embind_global$$$;return b}if("object"===typeof $$$embind_global$$$)return $$$embind_global$$$;"object"===typeof global&&a(global)?$$$embind_global$$$=global:"object"===typeof g&&a(g)&&($$$embind_global$$$= -g);if("object"===typeof $$$embind_global$$$)return $$$embind_global$$$;throw Error("unable to get global object.");}function Sd(a){if(0===a)return aa(kc());a=gb(a);return aa(kc()[a])}function Td(a){var b=hb.length;hb.push(a);return b}function Ud(a,b){for(var c=Array(a),f=0;f<a;++f)c[f]=Na(p[(b>>2)+f],"parameter "+f);return c}function Vd(a,b){var c=Ud(a,b),f=c[0],d=Array(a-1);b=function(b,m,e,h){for(var t=0,n=0;n<a-1;++n)d[n]=c[n+1].readValueFromPointer(h+t),t+=c[n+1].argPackAdvance;b=b[m].apply(b, -d);for(n=0;n<a-1;++n)c[n+1].deleteObject&&c[n+1].deleteObject(d[n]);if(!f.isVoid)return f.toWireType(e,b)};return Td(b)}function Wd(a,b){a=ma(a);b=ma(b);return aa(a[b])}function Xd(a){4<a&&(T[a].refcount+=1)}function Yd(){return aa([])}function Zd(a){return aa(gb(a))}function $d(a){var b=T[a].value;Oa(b);Ab(a)}function ae(a,b,c){a=ma(a);b=ma(b);c=ma(c);a[b]=c}function be(a,b){a=Na(a,"_emval_take_value");a=a.readValueFromPointer(b);return aa(a)}function ce(){d.abort()}function ib(){G()}function de(){return ca|| -"undefined"!==typeof dateNow||(wa||Z)&&self.performance&&self.performance.now}function ee(a,b){if(0===a)a=Date.now();else if(1===a&&de())a=ib();else return Ba(q.EINVAL),-1;p[b>>2]=a/1E3|0;p[b+4>>2]=a%1E3*1E6|0;return 0}function Bb(a,b){l.mainLoop.timingMode=a;l.mainLoop.timingValue=b;if(!l.mainLoop.func)return 1;if(0==a)l.mainLoop.scheduler=function(){var a=Math.max(0,l.mainLoop.tickStartTime+b-ib())|0;setTimeout(l.mainLoop.runner,a)},l.mainLoop.method="timeout";else if(1==a)l.mainLoop.scheduler= -function(){l.requestAnimationFrame(l.mainLoop.runner)},l.mainLoop.method="rAF";else if(2==a){if("undefined"===typeof setImmediate){a=function(a){if("setimmediate"===a.data||"setimmediate"===a.data.target)a.stopPropagation(),c.shift()()};var c=[];addEventListener("message",a,!0);setImmediate=function(a){c.push(a);Z?(void 0===d.setImmediates&&(d.setImmediates=[]),d.setImmediates.push(a),postMessage({target:"setimmediate"})):postMessage("setimmediate","*")}}l.mainLoop.scheduler=function(){setImmediate(l.mainLoop.runner)}; -l.mainLoop.method="immediate"}return 0}function fe(a,b,c,f,m){d.noExitRuntime=!0;D(!l.mainLoop.func,"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.");l.mainLoop.func=a;l.mainLoop.arg=f;var e="undefined"!==typeof f?function(){d.dynCall_vi(a,f)}:function(){d.dynCall_v(a)};var n=l.mainLoop.currentlyRunningMainloop;l.mainLoop.runner=function(){if(!da)if(0<l.mainLoop.queue.length){var a= -Date.now(),b=l.mainLoop.queue.shift();b.func(b.arg);if(l.mainLoop.remainingBlockers){var c=l.mainLoop.remainingBlockers,f=0==c%1?c-1:Math.floor(c);b.counted?l.mainLoop.remainingBlockers=f:(f+=.5,l.mainLoop.remainingBlockers=(8*c+f)/9)}console.log('main loop blocker "'+b.name+'" took '+(Date.now()-a)+" ms");l.mainLoop.updateStatus();n<l.mainLoop.currentlyRunningMainloop||setTimeout(l.mainLoop.runner,0)}else n<l.mainLoop.currentlyRunningMainloop||(l.mainLoop.currentFrameNumber=l.mainLoop.currentFrameNumber+ -1|0,1==l.mainLoop.timingMode&&1<l.mainLoop.timingValue&&0!=l.mainLoop.currentFrameNumber%l.mainLoop.timingValue?l.mainLoop.scheduler():(0==l.mainLoop.timingMode&&(l.mainLoop.tickStartTime=ib()),"timeout"===l.mainLoop.method&&d.ctx&&(d.printErr("Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!"),l.mainLoop.method=""), -l.mainLoop.runIter(e),n<l.mainLoop.currentlyRunningMainloop||("object"===typeof SDL&&SDL.audio&&SDL.audio.queueNewAudioData&&SDL.audio.queueNewAudioData(),l.mainLoop.scheduler())))};m||(b&&0<b?Bb(0,1E3/b):Bb(1,1),l.mainLoop.scheduler());if(c)throw"SimulateInfiniteLoop";}function ge(a,b,c,f,d){return y.chooseConfig(a,b,c,f,d)}function he(a){w.initDisplayMode=a}function ie(){var a={antialias:0!=(w.initDisplayMode&128),depth:0!=(w.initDisplayMode&16),stencil:0!=(w.initDisplayMode&32),alpha:0!=(w.initDisplayMode& -8)};d.ctx=l.createContext(d.canvas,!0,!0,a);return d.ctx?1:0}function je(a,b,c,f){if(62E3!=a)return y.setErrorCode(12296),0;for(a=1;;){b=p[f>>2];if(12440==b)a=p[f+4>>2];else if(12344==b)break;else return y.setErrorCode(12292),0;f+=8}if(2!=a)return y.setErrorCode(12293),0;he(178);y.windowID=ie();if(0!=y.windowID)return y.setErrorCode(12288),62004;y.setErrorCode(12297);return 0}function ke(a,b){if(62E3!=a)return y.setErrorCode(12296),0;if(62002!=b)return y.setErrorCode(12293),0;y.setErrorCode(12288); -return 62006}function le(a,b){if(62E3!=a)return y.setErrorCode(12296),0;if(62004!=b)return y.setErrorCode(12294),0;y.setErrorCode(12288);return 1}function me(a,b){if(62E3!=a)return y.setErrorCode(12296),0;if(62006!=b)return y.setErrorCode(12301),1;y.currentReadSurface==b&&(y.currentReadSurface=0);y.currentDrawSurface==b&&(y.currentDrawSurface=0);y.setErrorCode(12288);return 1}function ne(){return y.currentContext}function oe(){return y.currentContext?62E3:0}function pe(a){if(12378==a)return y.currentReadSurface; -if(12377==a)return y.currentDrawSurface;y.setErrorCode(12300);return 0}function qe(){y.setErrorCode(12288);return 62E3}function re(a){return se(a)}function te(a,b,c){if(62E3==a)return b&&(p[b>>2]=1),c&&(p[c>>2]=4),y.defaultDisplayInitialized=!0,y.setErrorCode(12288),1;y.setErrorCode(12296);return 0}function ue(a,b,c,f){if(62E3!=a)return y.setErrorCode(12296),0;if(0!=f&&62004!=f)return y.setErrorCode(12294),0;if(0!=c&&62006!=c||0!=b&&62006!=b)return y.setErrorCode(12301),0;y.currentContext=f;y.currentDrawSurface= -b;y.currentReadSurface=c;y.setErrorCode(12288);return 1}function ve(){y.currentContext=0;y.currentReadSurface=0;y.currentDrawSurface=0;y.setErrorCode(12288);return 1}function we(){if(y.defaultDisplayInitialized)if(d.ctx)if(d.ctx.isContextLost())y.setErrorCode(12302);else return y.setErrorCode(12288),1;else y.setErrorCode(12290);else y.setErrorCode(12289);return 0}function xe(a,b,c){function f(){Ha(a,"vi")(b)}d.noExitRuntime=!0;0<=c?l.safeSetTimeout(f,c):l.safeRequestAnimationFrame(f)}function ye(a){k.activeTexture(a)} -function ze(a,b){k.attachShader(h.programs[a],h.shaders[b])}function Ae(a,b,c){c=R(c);k.bindAttribLocation(h.programs[a],b,c)}function Be(a,b){var c=b?h.buffers[b]:null;35051==a?k.currentPixelPackBufferBinding=b:35052==a&&(k.currentPixelUnpackBufferBinding=b);k.bindBuffer(a,c)}function Ce(a,b){k.bindFramebuffer(a,b?h.framebuffers[b]:null)}function De(){d.printErr("missing function: emscripten_glBindProgramARB");G(-1)}function Ee(a,b){k.bindRenderbuffer(a,b?h.renderbuffers[b]:null)}function Fe(a,b){k.bindTexture(a, -b?h.textures[b]:null)}function Ge(a){k.bindVertexArray(h.vaos[a])}function He(a,b,c,f){k.blendColor(a,b,c,f)}function Ie(a){k.blendEquation(a)}function Je(a,b){k.blendEquationSeparate(a,b)}function Ke(a,b){k.blendFunc(a,b)}function Le(a,b,c,f){k.blendFuncSeparate(a,b,c,f)}function Me(a,b,c,f,d,e,n,h,g,l){k.blitFramebuffer(a,b,c,f,d,e,n,h,g,l)}function Ne(a,b,c,f){c?h.currentContext.supportsWebGL2EntryPoints?k.bufferData(a,F,f,c,b):k.bufferData(a,F.subarray(c,c+b),f):k.bufferData(a,b,f)}function Oe(a, -b,c,f){h.currentContext.supportsWebGL2EntryPoints?k.bufferSubData(a,b,F,f,c):k.bufferSubData(a,b,F.subarray(f,f+c))}function Pe(a){return k.checkFramebufferStatus(a)}function Qe(a){k.clear(a)}function Re(a,b,c,f){k.clearColor(a,b,c,f)}function Se(a){k.clearDepth(a)}function Te(a){k.clearDepth(a)}function Ue(a){k.clearStencil(a)}function Ve(){d.printErr("missing function: emscripten_glClientActiveTexture");G(-1)}function We(a,b,c,f){k.colorMask(!!a,!!b,!!c,!!f)}function Xe(){d.printErr("missing function: emscripten_glColorPointer"); -G(-1)}function Ye(a){k.compileShader(h.shaders[a])}function Ze(a,b,c,f,d,e,n,g){h.currentContext.supportsWebGL2EntryPoints?k.compressedTexImage2D(a,b,c,f,d,e,F,g,n):k.compressedTexImage2D(a,b,c,f,d,e,g?F.subarray(g,g+n):null)}function $e(a,b,c,f,d,e,n,g,l){h.currentContext.supportsWebGL2EntryPoints?k.compressedTexSubImage2D(a,b,c,f,d,e,n,F,l,g):k.compressedTexSubImage2D(a,b,c,f,d,e,n,l?F.subarray(l,l+g):null)}function af(a,b,c,f,d,e,n,h){k.copyTexImage2D(a,b,c,f,d,e,n,h)}function bf(a,b,c,f,d,e,n, -h){k.copyTexSubImage2D(a,b,c,f,d,e,n,h)}function cf(){var a=h.getNewId(h.programs),b=k.createProgram();b.name=a;h.programs[a]=b;return a}function df(a){var b=h.getNewId(h.shaders);h.shaders[b]=k.createShader(a);return b}function ef(a){k.cullFace(a)}function ff(a,b){for(var c=0;c<a;c++){var f=p[b+4*c>>2],d=h.buffers[f];d&&(k.deleteBuffer(d),d.name=0,h.buffers[f]=null,f==h.currArrayBuffer&&(h.currArrayBuffer=0),f==h.currElementArrayBuffer&&(h.currElementArrayBuffer=0))}}function gf(a,b){for(var c=0;c< -a;++c){var f=p[b+4*c>>2],d=h.framebuffers[f];d&&(k.deleteFramebuffer(d),d.name=0,h.framebuffers[f]=null)}}function hf(){d.printErr("missing function: emscripten_glDeleteObjectARB");G(-1)}function jf(a){if(a){var b=h.programs[a];b?(k.deleteProgram(b),b.name=0,h.programs[a]=null,h.programInfos[a]=null):h.recordError(1281)}}function kf(a,b){for(var c=0;c<a;c++){var f=p[b+4*c>>2],d=h.renderbuffers[f];d&&(k.deleteRenderbuffer(d),d.name=0,h.renderbuffers[f]=null)}}function lf(a){if(a){var b=h.shaders[a]; -b?(k.deleteShader(b),h.shaders[a]=null):h.recordError(1281)}}function mf(a,b){for(var c=0;c<a;c++){var f=p[b+4*c>>2],d=h.textures[f];d&&(k.deleteTexture(d),d.name=0,h.textures[f]=null)}}function nf(a,b){for(var c=0;c<a;c++){var f=p[b+4*c>>2];k.deleteVertexArray(h.vaos[f]);h.vaos[f]=null}}function of(a){k.depthFunc(a)}function pf(a){k.depthMask(!!a)}function qf(a,b){k.depthRange(a,b)}function rf(a,b){k.depthRange(a,b)}function sf(a,b){k.detachShader(h.programs[a],h.shaders[b])}function tf(a){k.disable(a)} -function uf(a){k.disableVertexAttribArray(a)}function vf(a,b,c){k.drawArrays(a,b,c)}function wf(a,b,c,f){k.drawArraysInstanced(a,b,c,f)}function xf(a,b){for(var c=h.tempFixedLengthArray[a],f=0;f<a;f++)c[f]=p[b+4*f>>2];k.drawBuffers(c)}function lc(a,b,c,f){k.drawElements(a,b,c,f)}function yf(a,b,c,f,d){k.drawElementsInstanced(a,b,c,f,d)}function zf(a,b,c,f,d,e){lc(a,f,d,e);k.drawElements(a,f,d,e)}function Af(a){k.enable(a)}function Bf(){d.printErr("missing function: emscripten_glEnableClientState"); -G(-1)}function Cf(a){k.enableVertexAttribArray(a)}function Df(){k.finish()}function Ef(){k.flush()}function Ff(a,b,c,f){k.framebufferRenderbuffer(a,b,c,h.renderbuffers[f])}function Gf(a,b,c,f,d){k.framebufferTexture2D(a,b,c,h.textures[f],d)}function Hf(a){k.frontFace(a)}function If(){d.printErr("missing function: emscripten_glFrustum");G(-1)}function Jf(a,b){for(var c=0;c<a;c++){var f=k.createBuffer();if(!f){for(h.recordError(1282);c<a;)p[b+4*c++>>2]=0;break}var d=h.getNewId(h.buffers);f.name=d;h.buffers[d]= -f;p[b+4*c>>2]=d}}function Kf(a,b){for(var c=0;c<a;++c){var f=k.createFramebuffer();if(!f){for(h.recordError(1282);c<a;)p[b+4*c++>>2]=0;break}var d=h.getNewId(h.framebuffers);f.name=d;h.framebuffers[d]=f;p[b+4*c>>2]=d}}function Lf(a,b){for(var c=0;c<a;c++){var f=k.createRenderbuffer();if(!f){for(h.recordError(1282);c<a;)p[b+4*c++>>2]=0;break}var d=h.getNewId(h.renderbuffers);f.name=d;h.renderbuffers[d]=f;p[b+4*c>>2]=d}}function Mf(a,b){for(var c=0;c<a;c++){var f=k.createTexture();if(!f){for(h.recordError(1282);c< -a;)p[b+4*c++>>2]=0;break}var d=h.getNewId(h.textures);f.name=d;h.textures[d]=f;p[b+4*c>>2]=d}}function Nf(a,b){for(var c=0;c<a;c++){var f=k.createVertexArray();if(!f){for(h.recordError(1282);c<a;)p[b+4*c++>>2]=0;break}var d=h.getNewId(h.vaos);f.name=d;h.vaos[d]=f;p[b+4*c>>2]=d}}function Of(a){k.generateMipmap(a)}function Pf(a,b,c,f,d,e,n){a=h.programs[a];if(a=k.getActiveAttrib(a,b))0<c&&n?(c=Y(a.name,F,n,c),f&&(p[f>>2]=c)):f&&(p[f>>2]=0),d&&(p[d>>2]=a.size),e&&(p[e>>2]=a.type)}function Qf(a,b,c,f, -d,e,n){a=h.programs[a];if(a=k.getActiveUniform(a,b))0<c&&n?(c=Y(a.name,F,n,c),f&&(p[f>>2]=c)):f&&(p[f>>2]=0),d&&(p[d>>2]=a.size),e&&(p[e>>2]=a.type)}function Rf(a,b,c,f){a=k.getAttachedShaders(h.programs[a]);var d=a.length;d>b&&(d=b);p[c>>2]=d;for(b=0;b<d;++b)c=h.shaders.indexOf(a[b]),p[f+4*b>>2]=c}function Sf(a,b){a=h.programs[a];b=R(b);return k.getAttribLocation(a,b)}function Cb(a,b,c){if(b){var f=void 0;switch(a){case 36346:f=1;break;case 36344:"Integer"!==c&&"Integer64"!==c&&h.recordError(1280); -return;case 34814:case 36345:f=0;break;case 34466:f=k.getParameter(34467);f=f.length;break;case 33309:if(2>k.canvas.GLctxObject.version){h.recordError(1282);return}f=k.getSupportedExtensions();f=2*f.length;break;case 33307:case 33308:if(2>k.canvas.GLctxObject.version){h.recordError(1280);return}f=33307==a?3:0}if(void 0===f)switch(f=k.getParameter(a),typeof f){case "number":break;case "boolean":f=f?1:0;break;case "string":h.recordError(1280);return;case "object":if(null===f)switch(a){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 35097:case 36389:case 34068:f= -0;break;default:h.recordError(1280);return}else{if(f instanceof Float32Array||f instanceof Uint32Array||f instanceof Int32Array||f instanceof Array){for(a=0;a<f.length;++a)switch(c){case "Integer":p[b+4*a>>2]=f[a];break;case "Float":u[b+4*a>>2]=f[a];break;case "Boolean":M[b+a>>0]=f[a]?1:0;break;default:throw"internal glGet error, bad type: "+c;}return}if(f instanceof WebGLBuffer||f instanceof WebGLProgram||f instanceof WebGLFramebuffer||f instanceof WebGLRenderbuffer||f instanceof WebGLQuery||f instanceof -WebGLSampler||f instanceof WebGLSync||f instanceof WebGLTransformFeedback||f instanceof WebGLVertexArrayObject||f instanceof WebGLTexture)f=f.name|0;else{h.recordError(1280);return}}break;default:h.recordError(1280);return}switch(c){case "Integer64":tempI64=[f>>>0,(tempDouble=f,1<=+Vb(tempDouble)?0<tempDouble?(Wb(+Xb(tempDouble/4294967296),4294967295)|0)>>>0:~~+Yb((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)];p[b>>2]=tempI64[0];p[b+4>>2]=tempI64[1];break;case "Integer":p[b>>2]=f;break;case "Float":u[b>> -2]=f;break;case "Boolean":M[b>>0]=f?1:0;break;default:throw"internal glGet error, bad type: "+c;}}else h.recordError(1281)}function Tf(a,b){Cb(a,b,"Boolean")}function Uf(a,b,c){c?p[c>>2]=k.getBufferParameter(a,b):h.recordError(1281)}function Vf(){if(h.lastError){var a=h.lastError;h.lastError=0;return a}return k.getError()}function Wf(a,b){Cb(a,b,"Float")}function Xf(a,b,c,f){a=k.getFramebufferAttachmentParameter(a,b,c);p[f>>2]=a}function Yf(){d.printErr("missing function: emscripten_glGetInfoLogARB"); -G(-1)}function Zf(a,b){Cb(a,b,"Integer")}function $f(){d.printErr("missing function: emscripten_glGetObjectParameterivARB");G(-1)}function ag(){d.printErr("missing function: emscripten_glGetPointerv");G(-1)}function bg(a,b,c,f){a=k.getProgramInfoLog(h.programs[a]);null===a&&(a="(unknown error)");0<b&&f?(b=Y(a,F,f,b),c&&(p[c>>2]=b)):c&&(p[c>>2]=0)}function cg(a,b,c){if(c)if(a>=h.counter)h.recordError(1281);else{var f=h.programInfos[a];if(f)if(35716==b)a=k.getProgramInfoLog(h.programs[a]),null===a&& -(a="(unknown error)"),p[c>>2]=a.length+1;else if(35719==b)p[c>>2]=f.maxUniformLength;else if(35722==b){if(-1==f.maxAttributeLength){a=h.programs[a];var d=k.getProgramParameter(a,k.ACTIVE_ATTRIBUTES);for(b=f.maxAttributeLength=0;b<d;++b){var e=k.getActiveAttrib(a,b);f.maxAttributeLength=Math.max(f.maxAttributeLength,e.name.length+1)}}p[c>>2]=f.maxAttributeLength}else if(35381==b){if(-1==f.maxUniformBlockNameLength)for(a=h.programs[a],d=k.getProgramParameter(a,k.ACTIVE_UNIFORM_BLOCKS),b=f.maxUniformBlockNameLength= -0;b<d;++b)e=k.getActiveUniformBlockName(a,b),f.maxUniformBlockNameLength=Math.max(f.maxUniformBlockNameLength,e.length+1);p[c>>2]=f.maxUniformBlockNameLength}else p[c>>2]=k.getProgramParameter(h.programs[a],b);else h.recordError(1282)}else h.recordError(1281)}function dg(a,b,c){c?p[c>>2]=k.getRenderbufferParameter(a,b):h.recordError(1281)}function eg(a,b,c,f){a=k.getShaderInfoLog(h.shaders[a]);null===a&&(a="(unknown error)");0<b&&f?(b=Y(a,F,f,b),c&&(p[c>>2]=b)):c&&(p[c>>2]=0)}function fg(a,b,c,f){a= -k.getShaderPrecisionFormat(a,b);p[c>>2]=a.rangeMin;p[c+4>>2]=a.rangeMax;p[f>>2]=a.precision}function gg(a,b,c,f){if(a=k.getShaderSource(h.shaders[a]))0<b&&f?(b=Y(a,F,f,b),c&&(p[c>>2]=b)):c&&(p[c>>2]=0)}function hg(a,b,c){c?35716==b?(a=k.getShaderInfoLog(h.shaders[a]),null===a&&(a="(unknown error)"),p[c>>2]=a.length+1):35720==b?(a=k.getShaderSource(h.shaders[a]),a=null===a||0==a.length?0:a.length+1,p[c>>2]=a):p[c>>2]=k.getShaderParameter(h.shaders[a],b):h.recordError(1281)}function ig(a){if(h.stringCache[a])return h.stringCache[a]; -switch(a){case 7936:case 7937:case 37445:case 37446:var b=Ta(ra(k.getParameter(a)),"i8",0);break;case 7938:b=k.getParameter(k.VERSION);b=2<=k.canvas.GLctxObject.version?"OpenGL ES 3.0 ("+b+")":"OpenGL ES 2.0 ("+b+")";b=Ta(ra(b),"i8",0);break;case 7939:b=k.getSupportedExtensions();for(var c=[],f=0;f<b.length;++f)c.push(b[f]),c.push("GL_"+b[f]);b=Ta(ra(c.join(" ")),"i8",0);break;case 35724:b=k.getParameter(k.SHADING_LANGUAGE_VERSION);c=/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;c=b.match(c);null!== -c&&(3==c[1].length&&(c[1]+="0"),b="OpenGL ES GLSL ES "+c[1]+" ("+b+")");b=Ta(ra(b),"i8",0);break;default:return h.recordError(1280),0}return h.stringCache[a]=b}function jg(a,b,c){c?u[c>>2]=k.getTexParameter(a,b):h.recordError(1281)}function kg(a,b,c){c?p[c>>2]=k.getTexParameter(a,b):h.recordError(1281)}function lg(a,b){b=R(b);var c=0;if(-1!==b.indexOf("]",b.length-1)){var f=b.lastIndexOf("["),d=b.slice(f+1,-1);if(0<d.length&&(c=parseInt(d),0>c))return-1;b=b.slice(0,f)}a=h.programInfos[a];if(!a)return-1; -a=a.uniforms;return(b=a[b])&&c<b[0]?b[1]+c:-1}function mc(a,b,c,f){if(c)if(a=k.getUniform(h.programs[a],h.uniforms[b]),"number"==typeof a||"boolean"==typeof a)switch(f){case "Integer":p[c>>2]=a;break;case "Float":u[c>>2]=a;break;default:throw"internal emscriptenWebGLGetUniform() error, bad type: "+f;}else for(b=0;b<a.length;b++)switch(f){case "Integer":p[c+4*b>>2]=a[b];break;case "Float":u[c+4*b>>2]=a[b];break;default:throw"internal emscriptenWebGLGetUniform() error, bad type: "+f;}else h.recordError(1281)} -function mg(a,b,c){mc(a,b,c,"Float")}function ng(a,b,c){mc(a,b,c,"Integer")}function og(a,b,c){c?p[c>>2]=k.getVertexAttribOffset(a,b):h.recordError(1281)}function nc(a,b,c,f){if(c)if(a=k.getVertexAttrib(a,b),34975==b)p[c>>2]=a.name;else if("number"==typeof a||"boolean"==typeof a)switch(f){case "Integer":p[c>>2]=a;break;case "Float":u[c>>2]=a;break;case "FloatToInteger":p[c>>2]=Math.fround(a);break;default:throw"internal emscriptenWebGLGetVertexAttrib() error, bad type: "+f;}else for(b=0;b<a.length;b++)switch(f){case "Integer":p[c+ -4*b>>2]=a[b];break;case "Float":u[c+4*b>>2]=a[b];break;case "FloatToInteger":p[c+4*b>>2]=Math.fround(a[b]);break;default:throw"internal emscriptenWebGLGetVertexAttrib() error, bad type: "+f;}else h.recordError(1281)}function pg(a,b,c){nc(a,b,c,"Float")}function qg(a,b,c){nc(a,b,c,"FloatToInteger")}function rg(a,b){k.hint(a,b)}function sg(a){return(a=h.buffers[a])?k.isBuffer(a):0}function tg(a){return k.isEnabled(a)}function ug(a){return(a=h.framebuffers[a])?k.isFramebuffer(a):0}function vg(a){return(a= -h.programs[a])?k.isProgram(a):0}function wg(a){return(a=h.renderbuffers[a])?k.isRenderbuffer(a):0}function xg(a){return(a=h.shaders[a])?k.isShader(a):0}function yg(a){return(a=h.textures[a])?k.isTexture(a):0}function zg(a){return(a=h.vaos[a])?k.isVertexArray(a):0}function Ag(a){k.lineWidth(a)}function Bg(a){k.linkProgram(h.programs[a]);h.programInfos[a]=null;h.populateUniformTable(a)}function Cg(){throw"Legacy GL function (glLoadIdentity) called. If you want legacy GL emulation, you need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation."; -}function Dg(){d.printErr("missing function: emscripten_glLoadMatrixf");G(-1)}function Eg(){throw"Legacy GL function (glMatrixMode) called. If you want legacy GL emulation, you need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.";}function Fg(){d.printErr("missing function: emscripten_glNormalPointer");G(-1)}function Gg(a,b){3333==a?h.packAlignment=b:3317==a&&(h.unpackAlignment=b);k.pixelStorei(a,b)}function Hg(a,b){k.polygonOffset(a,b)}function Db(a,b,c,f,d){switch(b){case 6406:case 6409:case 6402:case 6403:case 36244:b= -1;break;case 6410:case 33319:case 33320:b=2;break;case 6407:case 35904:case 36248:b=3;break;case 6408:case 35906:case 36249:b=4;break;default:return h.recordError(1280),null}switch(a){case 5121:case 5120:var e=1*b;break;case 5123:case 36193:case 5131:case 5122:e=2*b;break;case 5125:case 5126:case 5124:e=4*b;break;case 34042:case 35902:case 33640:case 35899:case 34042:e=4;break;case 33635:case 32819:case 32820:e=2;break;default:return h.recordError(1280),null}b=h.unpackAlignment;c*=e;b*=Math.floor((c+ -b-1)/b);f=0>=f?0:(f-1)*b+c;switch(a){case 5120:return M.subarray(d,d+f);case 5121:return F.subarray(d,d+f);case 5122:return ja.subarray(d>>1,d+f>>1);case 5124:return p.subarray(d>>2,d+f>>2);case 5126:return u.subarray(d>>2,d+f>>2);case 5125:case 34042:case 35902:case 33640:case 35899:case 34042:return S.subarray(d>>2,d+f>>2);case 5123:case 33635:case 32819:case 32820:case 36193:case 5131:return Aa.subarray(d>>1,d+f>>1);default:return h.recordError(1280),null}}function Eb(a){switch(a){case 5120:return M; -case 5121:return F;case 5122:return ja;case 5123:case 33635:case 32819:case 32820:case 36193:case 5131:return Aa;case 5124:return p;case 5125:case 34042:case 35902:case 33640:case 35899:case 34042:return S;case 5126:return u;default:return null}}function Fb(a){switch(a){case 5120:case 5121:return 0;case 5122:case 5123:case 33635:case 32819:case 32820:case 36193:case 5131:return 1;case 5124:case 5126:case 5125:case 34042:case 35902:case 33640:case 35899:case 34042:return 2;default:return 0}}function Ig(a, -b,c,f,d,e,n){h.currentContext.supportsWebGL2EntryPoints?k.currentPixelPackBufferBinding?k.readPixels(a,b,c,f,d,e,n):k.readPixels(a,b,c,f,d,e,Eb(e),n>>Fb(e)):(n=Db(e,d,c,f,n,d))?k.readPixels(a,b,c,f,d,e,n):h.recordError(1280)}function Jg(){}function Kg(a,b,c,f){k.renderbufferStorage(a,b,c,f)}function Lg(a,b,c,f,d){k.renderbufferStorageMultisample(a,b,c,f,d)}function Mg(){d.printErr("missing function: emscripten_glRotatef");G(-1)}function Ng(a,b){k.sampleCoverage(a,!!b)}function Og(a,b,c,f){k.scissor(a, -b,c,f)}function Pg(){h.recordError(1280)}function Qg(a,b,c,f){b=h.getSource(a,b,c,f);k.shaderSource(h.shaders[a],b)}function Rg(a,b,c){k.stencilFunc(a,b,c)}function Sg(a,b,c,f){k.stencilFuncSeparate(a,b,c,f)}function Tg(a){k.stencilMask(a)}function Ug(a,b){k.stencilMaskSeparate(a,b)}function Vg(a,b,c){k.stencilOp(a,b,c)}function Wg(a,b,c,f){k.stencilOpSeparate(a,b,c,f)}function Xg(){d.printErr("missing function: emscripten_glTexCoordPointer");G(-1)}function Yg(a,b,c,f,d,e,n,g,l){if(h.currentContext.supportsWebGL2EntryPoints)k.currentPixelUnpackBufferBinding? -k.texImage2D(a,b,c,f,d,e,n,g,l):0!=l?k.texImage2D(a,b,c,f,d,e,n,g,Eb(g),l>>Fb(g)):k.texImage2D(a,b,c,f,d,e,n,g,null);else{var m=null;l&&(m=Db(g,n,f,d,l,c));k.texImage2D(a,b,c,f,d,e,n,g,m)}}function Zg(a,b,c){k.texParameterf(a,b,c)}function $g(a,b,c){c=u[c>>2];k.texParameterf(a,b,c)}function ah(a,b,c){k.texParameteri(a,b,c)}function bh(a,b,c){c=p[c>>2];k.texParameteri(a,b,c)}function ch(a,b,c,f,d,e,n,g,l){if(h.currentContext.supportsWebGL2EntryPoints)k.currentPixelUnpackBufferBinding?k.texSubImage2D(a, -b,c,f,d,e,n,g,l):0!=l?k.texSubImage2D(a,b,c,f,d,e,n,g,Eb(g),l>>Fb(g)):k.texSubImage2D(a,b,c,f,d,e,n,g,null);else{var m=null;l&&(m=Db(g,n,d,e,l,0));k.texSubImage2D(a,b,c,f,d,e,n,g,m)}}function dh(a,b){k.uniform1f(h.uniforms[a],b)}function eh(a,b,c){if(h.currentContext.supportsWebGL2EntryPoints)k.uniform1fv(h.uniforms[a],u,c>>2,b);else{if(b<=h.MINI_TEMP_BUFFER_SIZE){var f=h.miniTempBufferViews[b-1];for(var d=0;d<b;++d)f[d]=u[c+4*d>>2]}else f=u.subarray(c>>2,c+4*b>>2);k.uniform1fv(h.uniforms[a],f)}} -function fh(a,b){k.uniform1i(h.uniforms[a],b)}function gh(a,b,c){h.currentContext.supportsWebGL2EntryPoints?k.uniform1iv(h.uniforms[a],p,c>>2,b):k.uniform1iv(h.uniforms[a],p.subarray(c>>2,c+4*b>>2))}function hh(a,b,c){k.uniform2f(h.uniforms[a],b,c)}function ih(a,b,c){if(h.currentContext.supportsWebGL2EntryPoints)k.uniform2fv(h.uniforms[a],u,c>>2,2*b);else{if(2*b<=h.MINI_TEMP_BUFFER_SIZE){var f=h.miniTempBufferViews[2*b-1];for(var d=0;d<2*b;d+=2)f[d]=u[c+4*d>>2],f[d+1]=u[c+(4*d+4)>>2]}else f=u.subarray(c>> -2,c+8*b>>2);k.uniform2fv(h.uniforms[a],f)}}function jh(a,b,c){k.uniform2i(h.uniforms[a],b,c)}function kh(a,b,c){h.currentContext.supportsWebGL2EntryPoints?k.uniform2iv(h.uniforms[a],p,c>>2,2*b):k.uniform2iv(h.uniforms[a],p.subarray(c>>2,c+8*b>>2))}function lh(a,b,c,f){k.uniform3f(h.uniforms[a],b,c,f)}function mh(a,b,c){if(h.currentContext.supportsWebGL2EntryPoints)k.uniform3fv(h.uniforms[a],u,c>>2,3*b);else{if(3*b<=h.MINI_TEMP_BUFFER_SIZE){var f=h.miniTempBufferViews[3*b-1];for(var d=0;d<3*b;d+=3)f[d]= -u[c+4*d>>2],f[d+1]=u[c+(4*d+4)>>2],f[d+2]=u[c+(4*d+8)>>2]}else f=u.subarray(c>>2,c+12*b>>2);k.uniform3fv(h.uniforms[a],f)}}function nh(a,b,c,f){k.uniform3i(h.uniforms[a],b,c,f)}function oh(a,b,c){h.currentContext.supportsWebGL2EntryPoints?k.uniform3iv(h.uniforms[a],p,c>>2,3*b):k.uniform3iv(h.uniforms[a],p.subarray(c>>2,c+12*b>>2))}function ph(a,b,c,f,d){k.uniform4f(h.uniforms[a],b,c,f,d)}function qh(a,b,c){if(h.currentContext.supportsWebGL2EntryPoints)k.uniform4fv(h.uniforms[a],u,c>>2,4*b);else{if(4* -b<=h.MINI_TEMP_BUFFER_SIZE){var f=h.miniTempBufferViews[4*b-1];for(var d=0;d<4*b;d+=4)f[d]=u[c+4*d>>2],f[d+1]=u[c+(4*d+4)>>2],f[d+2]=u[c+(4*d+8)>>2],f[d+3]=u[c+(4*d+12)>>2]}else f=u.subarray(c>>2,c+16*b>>2);k.uniform4fv(h.uniforms[a],f)}}function rh(a,b,c,f,d){k.uniform4i(h.uniforms[a],b,c,f,d)}function sh(a,b,c){h.currentContext.supportsWebGL2EntryPoints?k.uniform4iv(h.uniforms[a],p,c>>2,4*b):k.uniform4iv(h.uniforms[a],p.subarray(c>>2,c+16*b>>2))}function th(a,b,c,f){if(h.currentContext.supportsWebGL2EntryPoints)k.uniformMatrix2fv(h.uniforms[a], -!!c,u,f>>2,4*b);else{if(4*b<=h.MINI_TEMP_BUFFER_SIZE){var d=h.miniTempBufferViews[4*b-1];for(var e=0;e<4*b;e+=4)d[e]=u[f+4*e>>2],d[e+1]=u[f+(4*e+4)>>2],d[e+2]=u[f+(4*e+8)>>2],d[e+3]=u[f+(4*e+12)>>2]}else d=u.subarray(f>>2,f+16*b>>2);k.uniformMatrix2fv(h.uniforms[a],!!c,d)}}function uh(a,b,c,f){if(h.currentContext.supportsWebGL2EntryPoints)k.uniformMatrix3fv(h.uniforms[a],!!c,u,f>>2,9*b);else{if(9*b<=h.MINI_TEMP_BUFFER_SIZE){var d=h.miniTempBufferViews[9*b-1];for(var e=0;e<9*b;e+=9)d[e]=u[f+4*e>>2], -d[e+1]=u[f+(4*e+4)>>2],d[e+2]=u[f+(4*e+8)>>2],d[e+3]=u[f+(4*e+12)>>2],d[e+4]=u[f+(4*e+16)>>2],d[e+5]=u[f+(4*e+20)>>2],d[e+6]=u[f+(4*e+24)>>2],d[e+7]=u[f+(4*e+28)>>2],d[e+8]=u[f+(4*e+32)>>2]}else d=u.subarray(f>>2,f+36*b>>2);k.uniformMatrix3fv(h.uniforms[a],!!c,d)}}function vh(a,b,c,f){if(h.currentContext.supportsWebGL2EntryPoints)k.uniformMatrix4fv(h.uniforms[a],!!c,u,f>>2,16*b);else{if(16*b<=h.MINI_TEMP_BUFFER_SIZE){var d=h.miniTempBufferViews[16*b-1];for(var e=0;e<16*b;e+=16)d[e]=u[f+4*e>>2],d[e+ -1]=u[f+(4*e+4)>>2],d[e+2]=u[f+(4*e+8)>>2],d[e+3]=u[f+(4*e+12)>>2],d[e+4]=u[f+(4*e+16)>>2],d[e+5]=u[f+(4*e+20)>>2],d[e+6]=u[f+(4*e+24)>>2],d[e+7]=u[f+(4*e+28)>>2],d[e+8]=u[f+(4*e+32)>>2],d[e+9]=u[f+(4*e+36)>>2],d[e+10]=u[f+(4*e+40)>>2],d[e+11]=u[f+(4*e+44)>>2],d[e+12]=u[f+(4*e+48)>>2],d[e+13]=u[f+(4*e+52)>>2],d[e+14]=u[f+(4*e+56)>>2],d[e+15]=u[f+(4*e+60)>>2]}else d=u.subarray(f>>2,f+64*b>>2);k.uniformMatrix4fv(h.uniforms[a],!!c,d)}}function wh(a){k.useProgram(a?h.programs[a]:null)}function xh(a){k.validateProgram(h.programs[a])} -function yh(a,b){k.vertexAttrib1f(a,b)}function zh(a,b){k.vertexAttrib1f(a,u[b>>2])}function Ah(a,b,c){k.vertexAttrib2f(a,b,c)}function Bh(a,b){k.vertexAttrib2f(a,u[b>>2],u[b+4>>2])}function Ch(a,b,c,f){k.vertexAttrib3f(a,b,c,f)}function Dh(a,b){k.vertexAttrib3f(a,u[b>>2],u[b+4>>2],u[b+8>>2])}function Eh(a,b,c,f,d){k.vertexAttrib4f(a,b,c,f,d)}function Fh(a,b){k.vertexAttrib4f(a,u[b>>2],u[b+4>>2],u[b+8>>2],u[b+12>>2])}function Gh(a,b){k.vertexAttribDivisor(a,b)}function Hh(a,b,c,f,d,e){k.vertexAttribPointer(a, -b,c,!!f,d,e)}function Ih(){throw"Legacy GL function (glVertexPointer) called. If you want legacy GL emulation, you need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.";}function Jh(a,b,c,f){k.viewport(a,b,c,f)}function oc(a,b){d.setThrew(a,b||1);throw"longjmp";}function Kh(a,b){oc(a,b)}function Lh(a){d.exit(a)}function Mh(a){Lh(a)}function Gb(a){if(Gb.called){var b=p[pc>>2];var c=p[b>>2]}else Gb.called=!0,ha.USER=ha.LOGNAME="web_user",ha.PATH="/",ha.PWD="/",ha.HOME="/home/web_user", -ha.LANG="C.UTF-8",ha._=d.thisProgram,c=I(1024),b=I(256),p[b>>2]=c,p[pc>>2]=b;var f=[],e=0;for(n in a)if("string"===typeof a[n]){var t=n+"="+a[n];f.push(t);e+=t.length}if(1024<e)throw Error("Environment size exceeded TOTAL_ENV_SIZE!");for(a=0;a<f.length;a++){e=t=f[a];var n=c;for(var g=0;g<e.length;++g)M[n++>>0]=e.charCodeAt(g);M[n>>0]=0;p[b+4*a>>2]=c;c+=t.length+1}p[b+4*f.length>>2]=0}function Qa(a){if(0===a)return 0;a=R(a);if(!ha.hasOwnProperty(a))return 0;Qa.ret&&ea(Qa.ret);a=ha[a];var b=Va(a)+1, -c=ua(b);c&&Y(a,M,c,b);a=c;Qa.ret=a;return Qa.ret}function Nh(a){var b=Date.now();p[a>>2]=b/1E3|0;p[a+4>>2]=b%1E3*1E3|0;return 0}function Oh(a,b,c){F.set(F.subarray(b,b+c),a);return a}function Ph(){return 0}function Qh(a){return Fa[a]||0}function Rh(a){if(0==a)return q.EINVAL;p[a>>2]=Hb;Fa[Hb]=0;Hb++;return 0}function Sh(a){return a in Fa?(delete Fa[a],0):q.EINVAL}function Th(){}function Uh(){}function Vh(a,b){if(!(a in Fa))return q.EINVAL;Fa[a]=b;return 0}function Wh(){return 0}function jb(a){return 0=== -a%4&&(0!==a%100||0===a%400)}function Ib(a,b){for(var c=0,f=0;f<=b;c+=a[f++]);return c}function kb(a,b){for(a=new Date(a.getTime());0<b;){var c=jb(a.getFullYear()),f=a.getMonth();c=(c?lb:mb)[f];if(b>c-a.getDate())b-=c-a.getDate()+1,a.setDate(1),11>f?a.setMonth(f+1):(a.setMonth(0),a.setFullYear(a.getFullYear()+1));else{a.setDate(a.getDate()+b);break}}return a}function Xh(a,b,c,f){function d(a,b,c){for(a="number"===typeof a?a.toString():a||"";a.length<b;)a=c[0]+a;return a}function e(a,b){return d(a, -b,"0")}function n(a,b){function c(a){return 0>a?-1:0<a?1:0}var f;0===(f=c(a.getFullYear()-b.getFullYear()))&&0===(f=c(a.getMonth()-b.getMonth()))&&(f=c(a.getDate()-b.getDate()));return f}function g(a){switch(a.getDay()){case 0:return new Date(a.getFullYear()-1,11,29);case 1:return a;case 2:return new Date(a.getFullYear(),0,3);case 3:return new Date(a.getFullYear(),0,2);case 4:return new Date(a.getFullYear(),0,1);case 5:return new Date(a.getFullYear()-1,11,31);case 6:return new Date(a.getFullYear()- -1,11,30)}}function h(a){a=kb(new Date(a.tm_year+1900,0,1),a.tm_yday);var b=new Date(a.getFullYear(),0,4),c=new Date(a.getFullYear()+1,0,4);b=g(b);c=g(c);return 0>=n(b,a)?0>=n(c,a)?a.getFullYear()+1:a.getFullYear():a.getFullYear()-1}var l=p[f+40>>2];f={tm_sec:p[f>>2],tm_min:p[f+4>>2],tm_hour:p[f+8>>2],tm_mday:p[f+12>>2],tm_mon:p[f+16>>2],tm_year:p[f+20>>2],tm_wday:p[f+24>>2],tm_yday:p[f+28>>2],tm_isdst:p[f+32>>2],tm_gmtoff:p[f+36>>2],tm_zone:l?R(l):""};c=R(c);l={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y", -"%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S"};for(var k in l)c=c.replace(new RegExp(k,"g"),l[k]);var q="Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),r="January February March April May June July August September October November December".split(" ");l={"%a":function(a){return q[a.tm_wday].substring(0,3)},"%A":function(a){return q[a.tm_wday]},"%b":function(a){return r[a.tm_mon].substring(0,3)},"%B":function(a){return r[a.tm_mon]}, -"%C":function(a){a=a.tm_year+1900;return e(a/100|0,2)},"%d":function(a){return e(a.tm_mday,2)},"%e":function(a){return d(a.tm_mday,2," ")},"%g":function(a){return h(a).toString().substring(2)},"%G":function(a){return h(a)},"%H":function(a){return e(a.tm_hour,2)},"%I":function(a){a=a.tm_hour;0==a?a=12:12<a&&(a-=12);return e(a,2)},"%j":function(a){return e(a.tm_mday+Ib(jb(a.tm_year+1900)?lb:mb,a.tm_mon-1),3)},"%m":function(a){return e(a.tm_mon+1,2)},"%M":function(a){return e(a.tm_min,2)},"%n":function(){return"\n"}, -"%p":function(a){return 0<=a.tm_hour&&12>a.tm_hour?"AM":"PM"},"%S":function(a){return e(a.tm_sec,2)},"%t":function(){return"\t"},"%u":function(a){a=new Date(a.tm_year+1900,a.tm_mon+1,a.tm_mday,0,0,0,0);return a.getDay()||7},"%U":function(a){var b=new Date(a.tm_year+1900,0,1),c=0===b.getDay()?b:kb(b,7-b.getDay());a=new Date(a.tm_year+1900,a.tm_mon,a.tm_mday);return 0>n(c,a)?(b=Ib(jb(a.getFullYear())?lb:mb,a.getMonth()-1)-31,c=31-c.getDate(),c=c+b+a.getDate(),e(Math.ceil(c/7),2)):0===n(c,b)?"01":"00"}, -"%V":function(a){var b=new Date(a.tm_year+1900,0,4),c=new Date(a.tm_year+1901,0,4);b=g(b);c=g(c);var f=kb(new Date(a.tm_year+1900,0,1),a.tm_yday);if(0>n(f,b))return"53";if(0>=n(c,f))return"01";a=b.getFullYear()<a.tm_year+1900?a.tm_yday+32-b.getDate():a.tm_yday+1-b.getDate();return e(Math.ceil(a/7),2)},"%w":function(a){a=new Date(a.tm_year+1900,a.tm_mon+1,a.tm_mday,0,0,0,0);return a.getDay()},"%W":function(a){var b=new Date(a.tm_year,0,1),c=1===b.getDay()?b:kb(b,0===b.getDay()?1:7-b.getDay()+1);a= -new Date(a.tm_year+1900,a.tm_mon,a.tm_mday);return 0>n(c,a)?(b=Ib(jb(a.getFullYear())?lb:mb,a.getMonth()-1)-31,c=31-c.getDate(),c=c+b+a.getDate(),e(Math.ceil(c/7),2)):0===n(c,b)?"01":"00"},"%y":function(a){return(a.tm_year+1900).toString().substring(2)},"%Y":function(a){return a.tm_year+1900},"%z":function(a){a=a.tm_gmtoff;var b=0<=a;a=Math.abs(a)/60;a=a/60*100+a%60;return(b?"+":"-")+String("0000"+a).slice(-4)},"%Z":function(a){return a.tm_zone},"%%":function(){return"%"}};for(k in l)0<=c.indexOf(k)&& -(c=c.replace(new RegExp(k,"g"),l[k](f)));k=ra(c,!1);if(k.length>b)return 0;M.set(k,a);return k.length-1}function Yh(a,b,c,f){return Xh(a,b,c,f)}function ra(a,b,c){c=0<c?c:Va(a)+1;c=Array(c);a=Y(a,c,0,c.length);b&&(c.length=a);return c}function Zh(a,b){return v[a](b)}function $h(a,b,c){return v[a](b,c)}function ai(a,b){return v[a](b)}function bi(a,b,c){return v[a](b,c)}function ci(a,b){return v[a](b)}function di(a,b,c){return v[a](b,c)}function ei(a,b,c){return v[a](b,c)}function fi(a,b,c,f,d){return v[a](b, -c,f,d)}function gi(a){return v[a]()}function hi(a,b){try{return d.dynCall_ii(a,b)}catch(c){if("number"!==typeof c&&"longjmp"!==c)throw c;d.setThrew(1,0)}}function ii(a,b){return v[a](b)}function ji(a,b,c){return v[a](b,c)}function ki(a,b,c,f){try{return d.dynCall_iiii(a,b,c,f)}catch(m){if("number"!==typeof m&&"longjmp"!==m)throw m;d.setThrew(1,0)}}function li(a,b,c,f){return v[a](b,c,f)}function mi(a,b,c,f,d){return v[a](b,c,f,d)}function ni(a,b,c,f,d){return v[a](b,c,f,d)}function oi(a,b,c,f,d,e){return v[a](b, -c,f,d,e)}function pi(a,b,c,f,d,e){return v[a](b,c,f,d,e)}function qi(a,b,c,f,d,e,n){return v[a](b,c,f,d,e,n)}function ri(a,b,c,f,d,e,n){return v[a](b,c,f,d,e,n)}function si(a,b,c,f,d,e,n,g){return v[a](b,c,f,d,e,n,g)}function ti(a,b,c,f,d,e,n,g,h){return v[a](b,c,f,d,e,n,g,h)}function ui(a,b,c,f,d,e){return v[a](b,c,f,d,e)}function vi(a,b,c,f){return v[a](b,c,f)}function wi(a,b){return v[a](b)}function xi(a){v[a]()}function yi(a,b){v[a](b)}function zi(a,b,c){v[a](b,c)}function Ai(a,b,c,f,d,e,n){v[a](b, -c,f,d,e,n)}function Bi(a,b){v[a](b)}function Ci(a,b,c){v[a](b,c)}function Di(a,b,c,f,d){v[a](b,c,f,d)}function Ei(a,b,c){v[a](b,c)}function Fi(a,b){try{d.dynCall_vi(a,b)}catch(c){if("number"!==typeof c&&"longjmp"!==c)throw c;d.setThrew(1,0)}}function Gi(a,b){v[a](b)}function Hi(a,b,c){v[a](b,c)}function Ii(a,b,c){v[a](b,c)}function Ji(a,b,c,f){v[a](b,c,f)}function Ki(a,b,c,f,d){v[a](b,c,f,d)}function Li(a,b,c,f,d,e){v[a](b,c,f,d,e)}function Mi(a,b,c,f){v[a](b,c,f)}function Ni(a,b,c){try{d.dynCall_vii(a, -b,c)}catch(f){if("number"!==typeof f&&"longjmp"!==f)throw f;d.setThrew(1,0)}}function Oi(a,b,c){v[a](b,c)}function Pi(a,b,c,f){v[a](b,c,f)}function Qi(a,b,c,f){v[a](b,c,f)}function Ri(a,b,c,f,d,e,n){v[a](b,c,f,d,e,n)}function Si(a,b,c,f){v[a](b,c,f)}function Ti(a,b,c,f,d){v[a](b,c,f,d)}function Ui(a,b,c,f,d,e,n){v[a](b,c,f,d,e,n)}function Vi(a,b,c,f,d,e,n){v[a](b,c,f,d,e,n)}function Wi(a,b,c,f,d,e,n,g){v[a](b,c,f,d,e,n,g)}function Xi(a,b,c,f,d){v[a](b,c,f,d)}function Yi(a,b,c,f,d,e,n,g){v[a](b,c, -f,d,e,n,g)}function Zi(a,b,c,f,d,e,n,g,h,k,l,p){v[a](b,c,f,d,e,n,g,h,k,l,p)}function $i(a,b,c,f,d,e){v[a](b,c,f,d,e)}function aj(a,b,c,f,d,e){v[a](b,c,f,d,e)}function bj(a,b,c,f,d,e,n,g,h){v[a](b,c,f,d,e,n,g,h)}function cj(a,b,c,f,d,e,n,g,h,k,l,p,q){v[a](b,c,f,d,e,n,g,h,k,l,p,q)}function dj(a,b,c,f,d,e,n){v[a](b,c,f,d,e,n)}function ej(a,b,c,f,d,e,n,g){v[a](b,c,f,d,e,n,g)}function fj(a,b,c,f,d,e,n,g,h){v[a](b,c,f,d,e,n,g,h)}function gj(a,b,c,f,d,e,n,g,h,k){v[a](b,c,f,d,e,n,g,h,k)}function hj(a,b,c, -f,d,e,n,g,h,k,l){v[a](b,c,f,d,e,n,g,h,k,l)}function ij(a,b,c,f,d,e){v[a](b,c,f,d,e)}function jj(a,b,c,f,d,e){v[a](b,c,f,d,e)}function kj(a,b,c){v[a](b,c)}function lj(a,b,c,f){v[a](b,c,f)}function Ga(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}function Jb(){function a(){if(!d.calledRun&&(d.calledRun=!0,!da)){qc||(qc=!0,Ia(nb));Ia(rc);if(d.onRuntimeInitialized)d.onRuntimeInitialized();if(d.postRun)for("function"==typeof d.postRun&&(d.postRun=[d.postRun]);d.postRun.length;)sc.unshift(d.postRun.shift()); -Ia(sc)}}null===tc&&(tc=Date.now());if(!(0<va)){if(d.preRun)for("function"==typeof d.preRun&&(d.preRun=[d.preRun]);d.preRun.length;)uc.unshift(d.preRun.shift());Ia(uc);0<va||d.calledRun||(d.setStatus?(d.setStatus("Running..."),setTimeout(function(){setTimeout(function(){d.setStatus("")},1);a()},1)):a())}}function mj(a,b){if(!b||!d.noExitRuntime||0!==a){if(!d.noExitRuntime&&(da=!0,ob=nj,Ia(Kb),d.onExit))d.onExit(a);ca&&process.exit(a);d.quit(a,new Ga(a))}}function G(a){if(d.onAbort)d.onAbort(a);void 0!== -a?(d.print(a),d.printErr(a),a=JSON.stringify(a)):a="";da=!0;throw"abort("+a+"). Build with -s ASSERTIONS=1 for more info.";}var d=g.Module||{};d.doNotCaptureKeyboard=!0;g.asmjsLoadingDone=!1;d.postRun=d.postRun||[];d.postRun.push(function(){g.asmjsLoadingDone=!0});"undefined"!==typeof z&&(d.wasmBinary=z);d="undefined"!==typeof d?d:{};var Ra={},sa;for(sa in d)d.hasOwnProperty(sa)&&(Ra[sa]=d[sa]);d.arguments=[];d.thisProgram="./this.program";d.quit=function(a,b){throw b;};d.preRun=[];d.postRun=[];var wa= -!1,Z=!1,ca=!1,Lb=!1;if(d.ENVIRONMENT)if("WEB"===d.ENVIRONMENT)wa=!0;else if("WORKER"===d.ENVIRONMENT)Z=!0;else if("NODE"===d.ENVIRONMENT)ca=!0;else if("SHELL"===d.ENVIRONMENT)Lb=!0;else throw Error("Module['ENVIRONMENT'] value is not valid. must be one of: WEB|WORKER|NODE|SHELL.");else wa="object"===typeof g,Z="function"===typeof importScripts,ca="object"===typeof process&&"function"===typeof require&&!wa&&!Z,Lb=!wa&&!ca&&!Z;if(ca){var Mb,Nb;d.read=function(a,b){Mb||(Mb=require("fs"));Nb||(Nb=require("path")); -a=Nb.normalize(a);a=Mb.readFileSync(a);return b?a:a.toString()};d.readBinary=function(a){a=d.read(a,!0);a.buffer||(a=new Uint8Array(a));D(a.buffer);return a};1<process.argv.length&&(d.thisProgram=process.argv[1].replace(/\\/g,"/"));d.arguments=process.argv.slice(2);"undefined"!==typeof module&&(module.exports=d);process.on("uncaughtException",function(a){if(!(a instanceof Ga))throw a;});process.on("unhandledRejection",function(){process.exit(1)});d.inspect=function(){return"[Emscripten Module object]"}}else if(Lb)"undefined"!= -typeof read&&(d.read=function(a){return read(a)}),d.readBinary=function(a){if("function"===typeof readbuffer)return new Uint8Array(readbuffer(a));a=read(a,"binary");D("object"===typeof a);return a},"undefined"!=typeof scriptArgs?d.arguments=scriptArgs:"undefined"!=typeof r&&(d.arguments=r),"function"===typeof quit&&(d.quit=function(a){quit(a)});else if(wa||Z)d.read=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},Z&&(d.readBinary=function(a){var b=new XMLHttpRequest; -b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),d.readAsync=function(a,b,c){var f=new XMLHttpRequest;f.open("GET",a,!0);f.responseType="arraybuffer";f.onload=function(){200==f.status||0==f.status&&f.response?b(f.response):c()};f.onerror=c;f.send(null)},"undefined"!=typeof r&&(d.arguments=r),d.setWindowTitle=function(a){document.title=a};d.print="undefined"!==typeof console?console.log:"undefined"!==typeof print?print:null;d.printErr="undefined"!==typeof printErr? -printErr:"undefined"!==typeof console&&console.warn||d.print;d.print=d.print;d.printErr=d.printErr;for(sa in Ra)Ra.hasOwnProperty(sa)&&(d[sa]=Ra[sa]);Ra=void 0;var v=Array(20),qb={},da=0,Zb="undefined"!==typeof TextDecoder?new TextDecoder("utf8"):void 0;"undefined"!==typeof TextDecoder&&new TextDecoder("utf-16le");var M,F,ja,Aa,p,S,u,Ua,W,Ob,ob,Pb,Qb,oa;var Rb=W=Ob=ob=Pb=Qb=oa=0;var Tb=!1;var Sb=d.TOTAL_STACK||5242880,pa=d.TOTAL_MEMORY||134217728;pa<Sb&&d.printErr("TOTAL_MEMORY should be larger than TOTAL_STACK, was "+ -pa+"! (TOTAL_STACK="+Sb+")");if(d.buffer)var V=d.buffer;else"object"===typeof WebAssembly&&"function"===typeof WebAssembly.Memory?(d.wasmMemory=new WebAssembly.Memory({initial:pa/65536,maximum:pa/65536}),V=d.wasmMemory.buffer):V=new ArrayBuffer(pa),d.buffer=V;$b();p[0]=1668509029;ja[1]=25459;if(115!==F[2]||99!==F[3])throw"Runtime error: expected the system to be little-endian!";var uc=[],nb=[],rc=[],Kb=[],sc=[],qc=!1,Vb=Math.abs,Yb=Math.ceil,Xb=Math.floor,Wb=Math.min,va=0,sb=null,Ja=null;d.preloadedImages= -{};d.preloadedAudios={};Fc();var Ic=[function(){return!!d.ctx},function(){}];Rb=1024;W=Rb+184016;nb.push({func:function(){oj()}},{func:function(){pj()}},{func:function(){qj()}},{func:function(){rj()}},{func:function(){sj()}},{func:function(){tj()}},{func:function(){uj()}},{func:function(){vj()}},{func:function(){wj()}},{func:function(){xj()}},{func:function(){yj()}},{func:function(){zj()}},{func:function(){Aj()}},{func:function(){Bj()}},{func:function(){Cj()}},{func:function(){Dj()}},{func:function(){Ej()}}, -{func:function(){Fj()}},{func:function(){Gj()}},{func:function(){Hj()}},{func:function(){Ij()}},{func:function(){Jj()}},{func:function(){Kj()}},{func:function(){Lj()}},{func:function(){Mj()}},{func:function(){Nj()}},{func:function(){Oj()}},{func:function(){Pj()}},{func:function(){Qj()}},{func:function(){Rj()}},{func:function(){Sj()}},{func:function(){Tj()}},{func:function(){Uj()}},{func:function(){Vj()}},{func:function(){Wj()}},{func:function(){Xj()}},{func:function(){Yj()}},{func:function(){Zj()}}, -{func:function(){ak()}},{func:function(){bk()}},{func:function(){ck()}},{func:function(){dk()}},{func:function(){ek()}},{func:function(){fk()}},{func:function(){gk()}},{func:function(){hk()}},{func:function(){ik()}},{func:function(){jk()}},{func:function(){kk()}},{func:function(){lk()}},{func:function(){mk()}},{func:function(){nk()}},{func:function(){ok()}},{func:function(){pk()}},{func:function(){qk()}},{func:function(){rk()}},{func:function(){sk()}},{func:function(){tk()}},{func:function(){uk()}}, -{func:function(){vk()}},{func:function(){wk()}},{func:function(){xk()}},{func:function(){yk()}},{func:function(){zk()}},{func:function(){Ak()}},{func:function(){Bk()}},{func:function(){Ck()}},{func:function(){Dk()}},{func:function(){Ek()}},{func:function(){Fk()}},{func:function(){Gk()}},{func:function(){Hk()}},{func:function(){Ik()}},{func:function(){Jk()}},{func:function(){Kk()}},{func:function(){Lk()}},{func:function(){Mk()}},{func:function(){Nk()}},{func:function(){Ok()}},{func:function(){Pk()}}, -{func:function(){Qk()}},{func:function(){Rk()}},{func:function(){Sk()}},{func:function(){Tk()}},{func:function(){Uk()}},{func:function(){Vk()}},{func:function(){Wk()}},{func:function(){Xk()}},{func:function(){Yk()}},{func:function(){Zk()}},{func:function(){$k()}},{func:function(){al()}},{func:function(){bl()}},{func:function(){cl()}},{func:function(){dl()}},{func:function(){el()}},{func:function(){fl()}},{func:function(){gl()}},{func:function(){hl()}},{func:function(){il()}},{func:function(){jl()}}, -{func:function(){kl()}},{func:function(){ll()}},{func:function(){ml()}},{func:function(){nl()}},{func:function(){ol()}},{func:function(){pl()}},{func:function(){ql()}},{func:function(){rl()}},{func:function(){sl()}},{func:function(){tl()}});d.STATIC_BASE=Rb;d.STATIC_BUMP=184016;W+=16;var ka={last:0,caught:[],infos:{},deAdjust:function(a){if(!a||ka.infos[a])return a;for(var b in ka.infos){var c=ka.infos[b];if(c.adjusted===a)return b}return a},addRef:function(a){a&&(a=ka.infos[a],a.refcount++)},decRef:function(a){if(a){var b= -ka.infos[a];D(0<b.refcount);b.refcount--;0!==b.refcount||b.rethrown||(b.destructor&&d.dynCall_vi(b.destructor,a),delete ka.infos[a],___cxa_free_exception(a))}},clearRef:function(a){a&&(a=ka.infos[a],a.refcount=0)}},q={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29, -EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38, -ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123, -EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86},ul={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device", -20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty", -40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)", -62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed", -79:"Can access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported", -97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down", -113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"},x={splitPath:function(a){var b=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return b.exec(a).slice(1)},normalizeArray:function(a,b){for(var c=0,f=a.length-1;0<=f;f--){var d=a[f];"."===d?a.splice(f,1):".."===d?(a.splice(f,1),c++):c&& -(a.splice(f,1),c--)}if(b)for(;c;c--)a.unshift("..");return a},normalize:function(a){var b="/"===a.charAt(0),c="/"===a.substr(-1);(a=x.normalizeArray(a.split("/").filter(function(a){return!!a}),!b).join("/"))||b||(a=".");a&&c&&(a+="/");return(b?"/":"")+a},dirname:function(a){var b=x.splitPath(a);a=b[0];b=b[1];if(!a&&!b)return".";b&&(b=b.substr(0,b.length-1));return a+b},basename:function(a){if("/"===a)return"/";var b=a.lastIndexOf("/");return-1===b?a:a.substr(b+1)},extname:function(a){return x.splitPath(a)[3]}, -join:function(){var a=Array.prototype.slice.call(arguments,0);return x.normalize(a.join("/"))},join2:function(a,b){return x.normalize(a+"/"+b)},resolve:function(){for(var a="",b=!1,c=arguments.length-1;-1<=c&&!b;c--){b=0<=c?arguments[c]:e.cwd();if("string"!==typeof b)throw new TypeError("Arguments to path.resolve must be strings");if(!b)return"";a=b+"/"+a;b="/"===b.charAt(0)}a=x.normalizeArray(a.split("/").filter(function(a){return!!a}),!b).join("/");return(b?"/":"")+a||"."},relative:function(a,b){function c(a){for(var b= -0;b<a.length&&""===a[b];b++);for(var c=a.length-1;0<=c&&""===a[c];c--);return b>c?[]:a.slice(b,c-b+1)}a=x.resolve(a).substr(1);b=x.resolve(b).substr(1);a=c(a.split("/"));b=c(b.split("/"));for(var f=Math.min(a.length,b.length),d=f,e=0;e<f;e++)if(a[e]!==b[e]){d=e;break}f=[];for(e=d;e<a.length;e++)f.push("..");f=f.concat(b.slice(d));return f.join("/")}},ta={ttys:[],init:function(){},shutdown:function(){},register:function(a,b){ta.ttys[a]={input:[],output:[],ops:b};e.registerDevice(a,ta.stream_ops)}, -stream_ops:{open:function(a){var b=ta.ttys[a.node.rdev];if(!b)throw new e.ErrnoError(q.ENODEV);a.tty=b;a.seekable=!1},close:function(a){a.tty.ops.flush(a.tty)},flush:function(a){a.tty.ops.flush(a.tty)},read:function(a,b,c,f){if(!a.tty||!a.tty.ops.get_char)throw new e.ErrnoError(q.ENXIO);for(var d=0,g=0;g<f;g++){try{var n=a.tty.ops.get_char(a.tty)}catch(K){throw new e.ErrnoError(q.EIO);}if(void 0===n&&0===d)throw new e.ErrnoError(q.EAGAIN);if(null===n||void 0===n)break;d++;b[c+g]=n}d&&(a.node.timestamp= -Date.now());return d},write:function(a,b,c,d){if(!a.tty||!a.tty.ops.put_char)throw new e.ErrnoError(q.ENXIO);for(var f=0;f<d;f++)try{a.tty.ops.put_char(a.tty,b[c+f])}catch(t){throw new e.ErrnoError(q.EIO);}d&&(a.node.timestamp=Date.now());return f}},default_tty_ops:{get_char:function(a){if(!a.input.length){var b=null;if(ca){b=new Buffer(256);var c=0,d="win32"!=process.platform,e=process.stdin.fd;if(d){var h=!1;try{e=N.openSync("/dev/stdin","r"),h=!0}catch(n){}}try{c=N.readSync(e,b,0,256,null)}catch(n){if(-1!= -n.toString().indexOf("EOF"))c=0;else throw n;}h&&N.closeSync(e);b=0<c?b.slice(0,c).toString("utf-8"):null}else"undefined"!=typeof g&&"function"==typeof g.prompt?(b=g.prompt("Input: "),null!==b&&(b+="\n")):"function"==typeof readline&&(b=readline(),null!==b&&(b+="\n"));if(!b)return null;a.input=ra(b,!0)}return a.input.shift()},put_char:function(a,b){null===b||10===b?(d.print(za(a.output,0)),a.output=[]):0!=b&&a.output.push(b)},flush:function(a){a.output&&0<a.output.length&&(d.print(za(a.output,0)), -a.output=[])}},default_tty1_ops:{put_char:function(a,b){null===b||10===b?(d.printErr(za(a.output,0)),a.output=[]):0!=b&&a.output.push(b)},flush:function(a){a.output&&0<a.output.length&&(d.printErr(za(a.output,0)),a.output=[])}}},A={ops_table:null,mount:function(){return A.createNode(null,"/",16895,0)},createNode:function(a,b,c,d){if(e.isBlkdev(c)||e.isFIFO(c))throw new e.ErrnoError(q.EPERM);A.ops_table||(A.ops_table={dir:{node:{getattr:A.node_ops.getattr,setattr:A.node_ops.setattr,lookup:A.node_ops.lookup, -mknod:A.node_ops.mknod,rename:A.node_ops.rename,unlink:A.node_ops.unlink,rmdir:A.node_ops.rmdir,readdir:A.node_ops.readdir,symlink:A.node_ops.symlink},stream:{llseek:A.stream_ops.llseek}},file:{node:{getattr:A.node_ops.getattr,setattr:A.node_ops.setattr},stream:{llseek:A.stream_ops.llseek,read:A.stream_ops.read,write:A.stream_ops.write,allocate:A.stream_ops.allocate,mmap:A.stream_ops.mmap,msync:A.stream_ops.msync}},link:{node:{getattr:A.node_ops.getattr,setattr:A.node_ops.setattr,readlink:A.node_ops.readlink}, -stream:{}},chrdev:{node:{getattr:A.node_ops.getattr,setattr:A.node_ops.setattr},stream:e.chrdev_stream_ops}});c=e.createNode(a,b,c,d);e.isDir(c.mode)?(c.node_ops=A.ops_table.dir.node,c.stream_ops=A.ops_table.dir.stream,c.contents={}):e.isFile(c.mode)?(c.node_ops=A.ops_table.file.node,c.stream_ops=A.ops_table.file.stream,c.usedBytes=0,c.contents=null):e.isLink(c.mode)?(c.node_ops=A.ops_table.link.node,c.stream_ops=A.ops_table.link.stream):e.isChrdev(c.mode)&&(c.node_ops=A.ops_table.chrdev.node,c.stream_ops= -A.ops_table.chrdev.stream);c.timestamp=Date.now();a&&(a.contents[b]=c);return c},getFileDataAsRegularArray:function(a){if(a.contents&&a.contents.subarray){for(var b=[],c=0;c<a.usedBytes;++c)b.push(a.contents[c]);return b}return a.contents},getFileDataAsTypedArray:function(a){return a.contents?a.contents.subarray?a.contents.subarray(0,a.usedBytes):new Uint8Array(a.contents):new Uint8Array},expandFileStorage:function(a,b){a.contents&&a.contents.subarray&&b>a.contents.length&&(a.contents=A.getFileDataAsRegularArray(a), -a.usedBytes=a.contents.length);if(!a.contents||a.contents.subarray){var c=a.contents?a.contents.length:0;c>=b||(b=Math.max(b,c*(1048576>c?2:1.125)|0),0!=c&&(b=Math.max(b,256)),c=a.contents,a.contents=new Uint8Array(b),0<a.usedBytes&&a.contents.set(c.subarray(0,a.usedBytes),0))}else for(!a.contents&&0<b&&(a.contents=[]);a.contents.length<b;)a.contents.push(0)},resizeFileStorage:function(a,b){if(a.usedBytes!=b)if(0==b)a.contents=null,a.usedBytes=0;else{if(!a.contents||a.contents.subarray){var c=a.contents; -a.contents=new Uint8Array(new ArrayBuffer(b));c&&a.contents.set(c.subarray(0,Math.min(b,a.usedBytes)))}else if(a.contents||(a.contents=[]),a.contents.length>b)a.contents.length=b;else for(;a.contents.length<b;)a.contents.push(0);a.usedBytes=b}},node_ops:{getattr:function(a){var b={};b.dev=e.isChrdev(a.mode)?a.id:1;b.ino=a.id;b.mode=a.mode;b.nlink=1;b.uid=0;b.gid=0;b.rdev=a.rdev;e.isDir(a.mode)?b.size=4096:e.isFile(a.mode)?b.size=a.usedBytes:b.size=e.isLink(a.mode)?a.link.length:0;b.atime=new Date(a.timestamp); -b.mtime=new Date(a.timestamp);b.ctime=new Date(a.timestamp);b.blksize=4096;b.blocks=Math.ceil(b.size/b.blksize);return b},setattr:function(a,b){void 0!==b.mode&&(a.mode=b.mode);void 0!==b.timestamp&&(a.timestamp=b.timestamp);void 0!==b.size&&A.resizeFileStorage(a,b.size)},lookup:function(){throw e.genericErrors[q.ENOENT];},mknod:function(a,b,c,d){return A.createNode(a,b,c,d)},rename:function(a,b,c){if(e.isDir(a.mode)){try{var d=e.lookupNode(b,c)}catch(t){}if(d)for(var m in d.contents)throw new e.ErrnoError(q.ENOTEMPTY); -}delete a.parent.contents[a.name];a.name=c;b.contents[c]=a;a.parent=b},unlink:function(a,b){delete a.contents[b]},rmdir:function(a,b){var c=e.lookupNode(a,b),d;for(d in c.contents)throw new e.ErrnoError(q.ENOTEMPTY);delete a.contents[b]},readdir:function(a){var b=[".",".."],c;for(c in a.contents)a.contents.hasOwnProperty(c)&&b.push(c);return b},symlink:function(a,b,c){a=A.createNode(a,b,41471,0);a.link=c;return a},readlink:function(a){if(!e.isLink(a.mode))throw new e.ErrnoError(q.EINVAL);return a.link}}, -stream_ops:{read:function(a,b,c,d,e){var f=a.node.contents;if(e>=a.node.usedBytes)return 0;a=Math.min(a.node.usedBytes-e,d);D(0<=a);if(8<a&&f.subarray)b.set(f.subarray(e,e+a),c);else for(d=0;d<a;d++)b[c+d]=f[e+d];return a},write:function(a,b,c,d,e,g){if(!d)return 0;a=a.node;a.timestamp=Date.now();if(b.subarray&&(!a.contents||a.contents.subarray)){if(g)return a.contents=b.subarray(c,c+d),a.usedBytes=d;if(0===a.usedBytes&&0===e)return a.contents=new Uint8Array(b.subarray(c,c+d)),a.usedBytes=d;if(e+ -d<=a.usedBytes)return a.contents.set(b.subarray(c,c+d),e),d}A.expandFileStorage(a,e+d);if(a.contents.subarray&&b.subarray)a.contents.set(b.subarray(c,c+d),e);else for(g=0;g<d;g++)a.contents[e+g]=b[c+g];a.usedBytes=Math.max(a.usedBytes,e+d);return d},llseek:function(a,b,c){1===c?b+=a.position:2===c&&e.isFile(a.node.mode)&&(b+=a.node.usedBytes);if(0>b)throw new e.ErrnoError(q.EINVAL);return b},allocate:function(a,b,c){A.expandFileStorage(a.node,b+c);a.node.usedBytes=Math.max(a.node.usedBytes,b+c)}, -mmap:function(a,b,c,d,m,g,n){if(!e.isFile(a.node.mode))throw new e.ErrnoError(q.ENODEV);c=a.node.contents;if(n&2||c.buffer!==b&&c.buffer!==b.buffer){if(0<m||m+d<a.node.usedBytes)c=c.subarray?c.subarray(m,m+d):Array.prototype.slice.call(c,m,m+d);a=!0;d=ua(d);if(!d)throw new e.ErrnoError(q.ENOMEM);b.set(c,d)}else a=!1,d=c.byteOffset;return{ptr:d,allocated:a}},msync:function(a,b,c,d,m){if(!e.isFile(a.node.mode))throw new e.ErrnoError(q.ENODEV);if(m&2)return 0;A.stream_ops.write(a,b,0,d,c,!1);return 0}}}, -L={dbs:{},indexedDB:function(){if("undefined"!==typeof indexedDB)return indexedDB;var a=null;"object"===typeof g&&(a=g.indexedDB||g.mozIndexedDB||g.webkitIndexedDB||g.msIndexedDB);D(a,"IDBFS used, but indexedDB not supported");return a},DB_VERSION:21,DB_STORE_NAME:"FILE_DATA",mount:function(a){return A.mount.apply(null,arguments)},syncfs:function(a,b,c){L.getLocalSet(a,function(d,e){if(d)return c(d);L.getRemoteSet(a,function(a,d){if(a)return c(a);a=b?d:e;d=b?e:d;L.reconcile(a,d,c)})})},getDB:function(a, -b){var c=L.dbs[a];if(c)return b(null,c);try{var d=L.indexedDB().open(a,L.DB_VERSION)}catch(m){return b(m)}if(!d)return b("Unable to connect to IndexedDB");d.onupgradeneeded=function(a){var b=a.target.result;a=a.target.transaction;b=b.objectStoreNames.contains(L.DB_STORE_NAME)?a.objectStore(L.DB_STORE_NAME):b.createObjectStore(L.DB_STORE_NAME);b.indexNames.contains("timestamp")||b.createIndex("timestamp","timestamp",{unique:!1})};d.onsuccess=function(){c=d.result;L.dbs[a]=c;b(null,c)};d.onerror=function(a){b(this.error); -a.preventDefault()}},getLocalSet:function(a,b){function c(a){return"."!==a&&".."!==a}function d(a){return function(b){return x.join2(a,b)}}var m={};for(a=e.readdir(a.mountpoint).filter(c).map(d(a.mountpoint));a.length;){var g=a.pop();try{var n=e.stat(g)}catch(K){return b(K)}e.isDir(n.mode)&&a.push.apply(a,e.readdir(g).filter(c).map(d(g)));m[g]={timestamp:n.mtime}}return b(null,{type:"local",entries:m})},getRemoteSet:function(a,b){var c={};L.getDB(a.mountpoint,function(a,d){if(a)return b(a);try{var f= -d.transaction([L.DB_STORE_NAME],"readonly");f.onerror=function(a){b(this.error);a.preventDefault()};var e=f.objectStore(L.DB_STORE_NAME),m=e.index("timestamp");m.openKeyCursor().onsuccess=function(a){a=a.target.result;if(!a)return b(null,{type:"remote",db:d,entries:c});c[a.primaryKey]={timestamp:a.key};a["continue"]()}}catch(Ac){return b(Ac)}})},loadLocalEntry:function(a,b){try{var c=e.lookupPath(a);var d=c.node;var m=e.stat(a)}catch(t){return b(t)}return e.isDir(m.mode)?b(null,{timestamp:m.mtime, -mode:m.mode}):e.isFile(m.mode)?(d.contents=A.getFileDataAsTypedArray(d),b(null,{timestamp:m.mtime,mode:m.mode,contents:d.contents})):b(Error("node type not supported"))},storeLocalEntry:function(a,b,c){try{if(e.isDir(b.mode))e.mkdir(a,b.mode);else if(e.isFile(b.mode))e.writeFile(a,b.contents,{canOwn:!0});else return c(Error("node type not supported"));e.chmod(a,b.mode);e.utime(a,b.timestamp,b.timestamp)}catch(f){return c(f)}c(null)},removeLocalEntry:function(a,b){try{e.lookupPath(a);var c=e.stat(a); -e.isDir(c.mode)?e.rmdir(a):e.isFile(c.mode)&&e.unlink(a)}catch(f){return b(f)}b(null)},loadRemoteEntry:function(a,b,c){a=a.get(b);a.onsuccess=function(a){c(null,a.target.result)};a.onerror=function(a){c(this.error);a.preventDefault()}},storeRemoteEntry:function(a,b,c,d){a=a.put(c,b);a.onsuccess=function(){d(null)};a.onerror=function(a){d(this.error);a.preventDefault()}},removeRemoteEntry:function(a,b,c){a=a["delete"](b);a.onsuccess=function(){c(null)};a.onerror=function(a){c(this.error);a.preventDefault()}}, -reconcile:function(a,b,c){function d(a){if(a){if(!d.errored)return d.errored=!0,c(a)}else if(++h>=e)return c(null)}var e=0,g=[];Object.keys(a.entries).forEach(function(c){var d=a.entries[c],f=b.entries[c];if(!f||d.timestamp>f.timestamp)g.push(c),e++});var n=[];Object.keys(b.entries).forEach(function(b){var c=a.entries[b];c||(n.push(b),e++)});if(!e)return c(null);var h=0,k="remote"===a.type?a.db:b.db;k=k.transaction([L.DB_STORE_NAME],"readwrite");var l=k.objectStore(L.DB_STORE_NAME);k.onerror=function(a){d(this.error); -a.preventDefault()};g.sort().forEach(function(a){"local"===b.type?L.loadRemoteEntry(l,a,function(b,c){if(b)return d(b);L.storeLocalEntry(a,c,d)}):L.loadLocalEntry(a,function(b,c){if(b)return d(b);L.storeRemoteEntry(l,a,c,d)})});n.sort().reverse().forEach(function(a){"local"===b.type?L.removeLocalEntry(a,d):L.removeRemoteEntry(l,a,d)})}},H={isWindows:!1,staticInit:function(){H.isWindows=!!process.platform.match(/^win/);var a=process.binding("constants");a.fs&&(a=a.fs);H.flagsForNodeMap={1024:a.O_APPEND, -64:a.O_CREAT,128:a.O_EXCL,0:a.O_RDONLY,2:a.O_RDWR,4096:a.O_SYNC,512:a.O_TRUNC,1:a.O_WRONLY}},bufferFrom:function(a){return Buffer.alloc?Buffer.from(a):new Buffer(a)},mount:function(a){D(ca);return H.createNode(null,"/",H.getMode(a.opts.root),0)},createNode:function(a,b,c){if(!e.isDir(c)&&!e.isFile(c)&&!e.isLink(c))throw new e.ErrnoError(q.EINVAL);a=e.createNode(a,b,c);a.node_ops=H.node_ops;a.stream_ops=H.stream_ops;return a},getMode:function(a){try{var b=N.lstatSync(a);H.isWindows&&(b.mode|=(b.mode& -292)>>2)}catch(c){if(!c.code)throw c;throw new e.ErrnoError(q[c.code]);}return b.mode},realPath:function(a){for(var b=[];a.parent!==a;)b.push(a.name),a=a.parent;b.push(a.mount.opts.root);b.reverse();return x.join.apply(null,b)},flagsForNode:function(a){a&=-2097153;a&=-2049;a&=-32769;a&=-524289;var b=0,c;for(c in H.flagsForNodeMap)a&c&&(b|=H.flagsForNodeMap[c],a^=c);if(a)throw new e.ErrnoError(q.EINVAL);return b},node_ops:{getattr:function(a){a=H.realPath(a);try{var b=N.lstatSync(a)}catch(c){if(!c.code)throw c; -throw new e.ErrnoError(q[c.code]);}H.isWindows&&!b.blksize&&(b.blksize=4096);H.isWindows&&!b.blocks&&(b.blocks=(b.size+b.blksize-1)/b.blksize|0);return{dev:b.dev,ino:b.ino,mode:b.mode,nlink:b.nlink,uid:b.uid,gid:b.gid,rdev:b.rdev,size:b.size,atime:b.atime,mtime:b.mtime,ctime:b.ctime,blksize:b.blksize,blocks:b.blocks}},setattr:function(a,b){var c=H.realPath(a);try{void 0!==b.mode&&(N.chmodSync(c,b.mode),a.mode=b.mode);if(void 0!==b.timestamp){var d=new Date(b.timestamp);N.utimesSync(c,d,d)}void 0!== -b.size&&N.truncateSync(c,b.size)}catch(m){if(!m.code)throw m;throw new e.ErrnoError(q[m.code]);}},lookup:function(a,b){var c=x.join2(H.realPath(a),b);c=H.getMode(c);return H.createNode(a,b,c)},mknod:function(a,b,c,d){a=H.createNode(a,b,c,d);b=H.realPath(a);try{e.isDir(a.mode)?N.mkdirSync(b,a.mode):N.writeFileSync(b,"",{mode:a.mode})}catch(m){if(!m.code)throw m;throw new e.ErrnoError(q[m.code]);}return a},rename:function(a,b,c){a=H.realPath(a);b=x.join2(H.realPath(b),c);try{N.renameSync(a,b)}catch(f){if(!f.code)throw f; -throw new e.ErrnoError(q[f.code]);}},unlink:function(a,b){a=x.join2(H.realPath(a),b);try{N.unlinkSync(a)}catch(c){if(!c.code)throw c;throw new e.ErrnoError(q[c.code]);}},rmdir:function(a,b){a=x.join2(H.realPath(a),b);try{N.rmdirSync(a)}catch(c){if(!c.code)throw c;throw new e.ErrnoError(q[c.code]);}},readdir:function(a){a=H.realPath(a);try{return N.readdirSync(a)}catch(b){if(!b.code)throw b;throw new e.ErrnoError(q[b.code]);}},symlink:function(a,b,c){a=x.join2(H.realPath(a),b);try{N.symlinkSync(c, -a)}catch(f){if(!f.code)throw f;throw new e.ErrnoError(q[f.code]);}},readlink:function(a){var b=H.realPath(a);try{return b=N.readlinkSync(b),b=vc.relative(vc.resolve(a.mount.opts.root),b)}catch(c){if(!c.code)throw c;throw new e.ErrnoError(q[c.code]);}}},stream_ops:{open:function(a){var b=H.realPath(a.node);try{e.isFile(a.node.mode)&&(a.nfd=N.openSync(b,H.flagsForNode(a.flags)))}catch(c){if(!c.code)throw c;throw new e.ErrnoError(q[c.code]);}},close:function(a){try{e.isFile(a.node.mode)&&a.nfd&&N.closeSync(a.nfd)}catch(b){if(!b.code)throw b; -throw new e.ErrnoError(q[b.code]);}},read:function(a,b,c,d,m){if(0===d)return 0;try{return N.readSync(a.nfd,H.bufferFrom(b.buffer),c,d,m)}catch(t){throw new e.ErrnoError(q[t.code]);}},write:function(a,b,c,d,m){try{return N.writeSync(a.nfd,H.bufferFrom(b.buffer),c,d,m)}catch(t){throw new e.ErrnoError(q[t.code]);}},llseek:function(a,b,c){if(1===c)b+=a.position;else if(2===c&&e.isFile(a.node.mode))try{var d=N.fstatSync(a.nfd);b+=d.size}catch(m){throw new e.ErrnoError(q[m.code]);}if(0>b)throw new e.ErrnoError(q.EINVAL); -return b}}},Q={DIR_MODE:16895,FILE_MODE:33279,reader:null,mount:function(a){function b(a){a=a.split("/");for(var b=d,c=0;c<a.length-1;c++){var f=a.slice(0,c+1).join("/");e[f]||(e[f]=Q.createNode(b,a[c],Q.DIR_MODE,0));b=e[f]}return b}function c(a){a=a.split("/");return a[a.length-1]}D(Z);Q.reader||(Q.reader=new FileReaderSync);var d=Q.createNode(null,"/",Q.DIR_MODE,0),e={};Array.prototype.forEach.call(a.opts.files||[],function(a){Q.createNode(b(a.name),c(a.name),Q.FILE_MODE,0,a,a.lastModifiedDate)}); -(a.opts.blobs||[]).forEach(function(a){Q.createNode(b(a.name),c(a.name),Q.FILE_MODE,0,a.data)});(a.opts.packages||[]).forEach(function(a){a.metadata.files.forEach(function(d){var f=d.filename.substr(1);Q.createNode(b(f),c(f),Q.FILE_MODE,0,a.blob.slice(d.start,d.end))})});return d},createNode:function(a,b,c,d,m,g){d=e.createNode(a,b,c);d.mode=c;d.node_ops=Q.node_ops;d.stream_ops=Q.stream_ops;d.timestamp=(g||new Date).getTime();D(Q.FILE_MODE!==Q.DIR_MODE);c===Q.FILE_MODE?(d.size=m.size,d.contents=m): -(d.size=4096,d.contents={});a&&(a.contents[b]=d);return d},node_ops:{getattr:function(a){return{dev:1,ino:void 0,mode:a.mode,nlink:1,uid:0,gid:0,rdev:void 0,size:a.size,atime:new Date(a.timestamp),mtime:new Date(a.timestamp),ctime:new Date(a.timestamp),blksize:4096,blocks:Math.ceil(a.size/4096)}},setattr:function(a,b){void 0!==b.mode&&(a.mode=b.mode);void 0!==b.timestamp&&(a.timestamp=b.timestamp)},lookup:function(){throw new e.ErrnoError(q.ENOENT);},mknod:function(){throw new e.ErrnoError(q.EPERM); -},rename:function(){throw new e.ErrnoError(q.EPERM);},unlink:function(){throw new e.ErrnoError(q.EPERM);},rmdir:function(){throw new e.ErrnoError(q.EPERM);},readdir:function(a){var b=[".",".."],c;for(c in a.contents)a.contents.hasOwnProperty(c)&&b.push(c);return b},symlink:function(){throw new e.ErrnoError(q.EPERM);},readlink:function(){throw new e.ErrnoError(q.EPERM);}},stream_ops:{read:function(a,b,c,d,e){if(e>=a.node.size)return 0;a=a.node.contents.slice(e,e+d);d=Q.reader.readAsArrayBuffer(a); -b.set(new Uint8Array(d),c);return a.size},write:function(){throw new e.ErrnoError(q.EIO);},llseek:function(a,b,c){1===c?b+=a.position:2===c&&e.isFile(a.node.mode)&&(b+=a.node.size);if(0>b)throw new e.ErrnoError(q.EINVAL);return b}}};W+=16;W+=16;W+=16;var e={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:!1,ignorePermissions:!0,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0, -handleFSError:function(a){if(!(a instanceof e.ErrnoError)){a:{var b=Error();if(!b.stack){try{throw Error(0);}catch(c){b=c}if(!b.stack){b="(no stack trace available)";break a}}b=b.stack.toString()}d.extraStackTrace&&(b+="\n"+d.extraStackTrace());b=Cc(b);throw a+" : "+b;}return Ba(a.errno)},lookupPath:function(a,b){a=x.resolve(e.cwd(),a);b=b||{};if(!a)return{path:"",node:null};var c={follow_mount:!0,recurse_count:0},d;for(d in c)void 0===b[d]&&(b[d]=c[d]);if(8<b.recurse_count)throw new e.ErrnoError(q.ELOOP); -a=x.normalizeArray(a.split("/").filter(function(a){return!!a}),!1);var m=e.root;c="/";for(d=0;d<a.length;d++){var g=d===a.length-1;if(g&&b.parent)break;m=e.lookupNode(m,a[d]);c=x.join2(c,a[d]);e.isMountpoint(m)&&(!g||g&&b.follow_mount)&&(m=m.mounted.root);if(!g||b.follow)for(g=0;e.isLink(m.mode);)if(m=e.readlink(c),c=x.resolve(x.dirname(c),m),m=e.lookupPath(c,{recurse_count:b.recurse_count}),m=m.node,40<g++)throw new e.ErrnoError(q.ELOOP);}return{path:c,node:m}},getPath:function(a){for(var b;;){if(e.isRoot(a))return a= -a.mount.mountpoint,b?"/"!==a[a.length-1]?a+"/"+b:a+b:a;b=b?a.name+"/"+b:a.name;a=a.parent}},hashName:function(a,b){for(var c=0,d=0;d<b.length;d++)c=(c<<5)-c+b.charCodeAt(d)|0;return(a+c>>>0)%e.nameTable.length},hashAddNode:function(a){var b=e.hashName(a.parent.id,a.name);a.name_next=e.nameTable[b];e.nameTable[b]=a},hashRemoveNode:function(a){var b=e.hashName(a.parent.id,a.name);if(e.nameTable[b]===a)e.nameTable[b]=a.name_next;else for(b=e.nameTable[b];b;){if(b.name_next===a){b.name_next=a.name_next; -break}b=b.name_next}},lookupNode:function(a,b){var c=e.mayLookup(a);if(c)throw new e.ErrnoError(c,a);c=e.hashName(a.id,b);for(c=e.nameTable[c];c;c=c.name_next){var d=c.name;if(c.parent.id===a.id&&d===b)return c}return e.lookup(a,b)},createNode:function(a,b,c,d){e.FSNode||(e.FSNode=function(a,b,c,d){a||(a=this);this.parent=a;this.mount=a.mount;this.mounted=null;this.id=e.nextInode++;this.name=b;this.mode=c;this.node_ops={};this.stream_ops={};this.rdev=d},e.FSNode.prototype={},Object.defineProperties(e.FSNode.prototype, -{read:{get:function(){return 365===(this.mode&365)},set:function(a){a?this.mode|=365:this.mode&=-366}},write:{get:function(){return 146===(this.mode&146)},set:function(a){a?this.mode|=146:this.mode&=-147}},isFolder:{get:function(){return e.isDir(this.mode)}},isDevice:{get:function(){return e.isChrdev(this.mode)}}}));a=new e.FSNode(a,b,c,d);e.hashAddNode(a);return a},destroyNode:function(a){e.hashRemoveNode(a)},isRoot:function(a){return a===a.parent},isMountpoint:function(a){return!!a.mounted},isFile:function(a){return 32768=== -(a&61440)},isDir:function(a){return 16384===(a&61440)},isLink:function(a){return 40960===(a&61440)},isChrdev:function(a){return 8192===(a&61440)},isBlkdev:function(a){return 24576===(a&61440)},isFIFO:function(a){return 4096===(a&61440)},isSocket:function(a){return 49152===(a&49152)},flagModes:{r:0,rs:1052672,"r+":2,w:577,wx:705,xw:705,"w+":578,"wx+":706,"xw+":706,a:1089,ax:1217,xa:1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function(a){var b=e.flagModes[a];if("undefined"===typeof b)throw Error("Unknown file open mode: "+ -a);return b},flagsToPermissionString:function(a){var b=["r","w","rw"][a&3];a&512&&(b+="w");return b},nodePermissions:function(a,b){if(e.ignorePermissions)return 0;if(-1===b.indexOf("r")||a.mode&292){if(-1!==b.indexOf("w")&&!(a.mode&146)||-1!==b.indexOf("x")&&!(a.mode&73))return q.EACCES}else return q.EACCES;return 0},mayLookup:function(a){var b=e.nodePermissions(a,"x");return b?b:a.node_ops.lookup?0:q.EACCES},mayCreate:function(a,b){try{return e.lookupNode(a,b),q.EEXIST}catch(c){}return e.nodePermissions(a, -"wx")},mayDelete:function(a,b,c){try{var d=e.lookupNode(a,b)}catch(m){return m.errno}if(a=e.nodePermissions(a,"wx"))return a;if(c){if(!e.isDir(d.mode))return q.ENOTDIR;if(e.isRoot(d)||e.getPath(d)===e.cwd())return q.EBUSY}else if(e.isDir(d.mode))return q.EISDIR;return 0},mayOpen:function(a,b){return a?e.isLink(a.mode)?q.ELOOP:e.isDir(a.mode)&&("r"!==e.flagsToPermissionString(b)||b&512)?q.EISDIR:e.nodePermissions(a,e.flagsToPermissionString(b)):q.ENOENT},MAX_OPEN_FDS:4096,nextfd:function(a,b){a=a|| -0;for(b=b||e.MAX_OPEN_FDS;a<=b;a++)if(!e.streams[a])return a;throw new e.ErrnoError(q.EMFILE);},getStream:function(a){return e.streams[a]},createStream:function(a,b,c){e.FSStream||(e.FSStream=function(){},e.FSStream.prototype={},Object.defineProperties(e.FSStream.prototype,{object:{get:function(){return this.node},set:function(a){this.node=a}}}));var d=new e.FSStream,m;for(m in a)d[m]=a[m];a=d;b=e.nextfd(b,c);a.fd=b;return e.streams[b]=a},closeStream:function(a){e.streams[a]=null},chrdev_stream_ops:{open:function(a){var b= -e.getDevice(a.node.rdev);a.stream_ops=b.stream_ops;a.stream_ops.open&&a.stream_ops.open(a)},llseek:function(){throw new e.ErrnoError(q.ESPIPE);}},major:function(a){return a>>8},minor:function(a){return a&255},makedev:function(a,b){return a<<8|b},registerDevice:function(a,b){e.devices[a]={stream_ops:b}},getDevice:function(a){return e.devices[a]},getMounts:function(a){var b=[];for(a=[a];a.length;){var c=a.pop();b.push(c);a.push.apply(a,c.mounts)}return b},syncfs:function(a,b){function c(a){D(0<e.syncFSRequests); -e.syncFSRequests--;return b(a)}function d(a){if(a){if(!d.errored)return d.errored=!0,c(a)}else++g>=m.length&&c(null)}"function"===typeof a&&(b=a,a=!1);e.syncFSRequests++;1<e.syncFSRequests&&console.log("warning: "+e.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work");var m=e.getMounts(e.root.mount),g=0;m.forEach(function(b){if(!b.type.syncfs)return d(null);b.type.syncfs(b,a,d)})},mount:function(a,b,c){var d="/"===c,m=!c;if(d&&e.root)throw new e.ErrnoError(q.EBUSY); -if(!d&&!m){var g=e.lookupPath(c,{follow_mount:!1});c=g.path;g=g.node;if(e.isMountpoint(g))throw new e.ErrnoError(q.EBUSY);if(!e.isDir(g.mode))throw new e.ErrnoError(q.ENOTDIR);}b={type:a,opts:b,mountpoint:c,mounts:[]};a=a.mount(b);a.mount=b;b.root=a;d?e.root=a:g&&(g.mounted=b,g.mount&&g.mount.mounts.push(b));return a},unmount:function(a){a=e.lookupPath(a,{follow_mount:!1});if(!e.isMountpoint(a.node))throw new e.ErrnoError(q.EINVAL);a=a.node;var b=a.mounted,c=e.getMounts(b);Object.keys(e.nameTable).forEach(function(a){for(a= -e.nameTable[a];a;){var b=a.name_next;-1!==c.indexOf(a.mount)&&e.destroyNode(a);a=b}});a.mounted=null;b=a.mount.mounts.indexOf(b);D(-1!==b);a.mount.mounts.splice(b,1)},lookup:function(a,b){return a.node_ops.lookup(a,b)},mknod:function(a,b,c){var d=e.lookupPath(a,{parent:!0});d=d.node;a=x.basename(a);if(!a||"."===a||".."===a)throw new e.ErrnoError(q.EINVAL);var g=e.mayCreate(d,a);if(g)throw new e.ErrnoError(g);if(!d.node_ops.mknod)throw new e.ErrnoError(q.EPERM);return d.node_ops.mknod(d,a,b,c)},create:function(a, -b){b=void 0!==b?b:438;b&=4095;b|=32768;return e.mknod(a,b,0)},mkdir:function(a,b){b=void 0!==b?b:511;b&=1023;b|=16384;return e.mknod(a,b,0)},mkdirTree:function(a,b){a=a.split("/");for(var c="",d=0;d<a.length;++d)if(a[d]){c+="/"+a[d];try{e.mkdir(c,b)}catch(m){if(m.errno!=q.EEXIST)throw m;}}},mkdev:function(a,b,c){"undefined"===typeof c&&(c=b,b=438);b|=8192;return e.mknod(a,b,c)},symlink:function(a,b){if(!x.resolve(a))throw new e.ErrnoError(q.ENOENT);var c=e.lookupPath(b,{parent:!0});c=c.node;if(!c)throw new e.ErrnoError(q.ENOENT); -b=x.basename(b);var d=e.mayCreate(c,b);if(d)throw new e.ErrnoError(d);if(!c.node_ops.symlink)throw new e.ErrnoError(q.EPERM);return c.node_ops.symlink(c,b,a)},rename:function(a,b){var c=x.dirname(a),d=x.dirname(b),g=x.basename(a),h=x.basename(b);try{var n=e.lookupPath(a,{parent:!0});var k=n.node;n=e.lookupPath(b,{parent:!0});var l=n.node}catch(P){throw new e.ErrnoError(q.EBUSY);}if(!k||!l)throw new e.ErrnoError(q.ENOENT);if(k.mount!==l.mount)throw new e.ErrnoError(q.EXDEV);n=e.lookupNode(k,g);d=x.relative(a, -d);if("."!==d.charAt(0))throw new e.ErrnoError(q.EINVAL);d=x.relative(b,c);if("."!==d.charAt(0))throw new e.ErrnoError(q.ENOTEMPTY);try{var p=e.lookupNode(l,h)}catch(P){}if(n!==p){c=e.isDir(n.mode);if(g=e.mayDelete(k,g,c))throw new e.ErrnoError(g);if(g=p?e.mayDelete(l,h,c):e.mayCreate(l,h))throw new e.ErrnoError(g);if(!k.node_ops.rename)throw new e.ErrnoError(q.EPERM);if(e.isMountpoint(n)||p&&e.isMountpoint(p))throw new e.ErrnoError(q.EBUSY);if(l!==k&&(g=e.nodePermissions(k,"w")))throw new e.ErrnoError(g); -try{e.trackingDelegate.willMovePath&&e.trackingDelegate.willMovePath(a,b)}catch(P){console.log("FS.trackingDelegate['willMovePath']('"+a+"', '"+b+"') threw an exception: "+P.message)}e.hashRemoveNode(n);try{k.node_ops.rename(n,l,h)}catch(P){throw P;}finally{e.hashAddNode(n)}try{if(e.trackingDelegate.onMovePath)e.trackingDelegate.onMovePath(a,b)}catch(P){console.log("FS.trackingDelegate['onMovePath']('"+a+"', '"+b+"') threw an exception: "+P.message)}}},rmdir:function(a){var b=e.lookupPath(a,{parent:!0}); -b=b.node;var c=x.basename(a),d=e.lookupNode(b,c),g=e.mayDelete(b,c,!0);if(g)throw new e.ErrnoError(g);if(!b.node_ops.rmdir)throw new e.ErrnoError(q.EPERM);if(e.isMountpoint(d))throw new e.ErrnoError(q.EBUSY);try{e.trackingDelegate.willDeletePath&&e.trackingDelegate.willDeletePath(a)}catch(t){console.log("FS.trackingDelegate['willDeletePath']('"+a+"') threw an exception: "+t.message)}b.node_ops.rmdir(b,c);e.destroyNode(d);try{if(e.trackingDelegate.onDeletePath)e.trackingDelegate.onDeletePath(a)}catch(t){console.log("FS.trackingDelegate['onDeletePath']('"+ -a+"') threw an exception: "+t.message)}},readdir:function(a){a=e.lookupPath(a,{follow:!0});a=a.node;if(!a.node_ops.readdir)throw new e.ErrnoError(q.ENOTDIR);return a.node_ops.readdir(a)},unlink:function(a){var b=e.lookupPath(a,{parent:!0});b=b.node;var c=x.basename(a),d=e.lookupNode(b,c),g=e.mayDelete(b,c,!1);if(g)throw new e.ErrnoError(g);if(!b.node_ops.unlink)throw new e.ErrnoError(q.EPERM);if(e.isMountpoint(d))throw new e.ErrnoError(q.EBUSY);try{e.trackingDelegate.willDeletePath&&e.trackingDelegate.willDeletePath(a)}catch(t){console.log("FS.trackingDelegate['willDeletePath']('"+ -a+"') threw an exception: "+t.message)}b.node_ops.unlink(b,c);e.destroyNode(d);try{if(e.trackingDelegate.onDeletePath)e.trackingDelegate.onDeletePath(a)}catch(t){console.log("FS.trackingDelegate['onDeletePath']('"+a+"') threw an exception: "+t.message)}},readlink:function(a){a=e.lookupPath(a);a=a.node;if(!a)throw new e.ErrnoError(q.ENOENT);if(!a.node_ops.readlink)throw new e.ErrnoError(q.EINVAL);return x.resolve(e.getPath(a.parent),a.node_ops.readlink(a))},stat:function(a,b){a=e.lookupPath(a,{follow:!b}); -a=a.node;if(!a)throw new e.ErrnoError(q.ENOENT);if(!a.node_ops.getattr)throw new e.ErrnoError(q.EPERM);return a.node_ops.getattr(a)},lstat:function(a){return e.stat(a,!0)},chmod:function(a,b,c){"string"===typeof a&&(a=e.lookupPath(a,{follow:!c}),a=a.node);if(!a.node_ops.setattr)throw new e.ErrnoError(q.EPERM);a.node_ops.setattr(a,{mode:b&4095|a.mode&-4096,timestamp:Date.now()})},lchmod:function(a,b){e.chmod(a,b,!0)},fchmod:function(a,b){a=e.getStream(a);if(!a)throw new e.ErrnoError(q.EBADF);e.chmod(a.node, -b)},chown:function(a,b,c,d){"string"===typeof a&&(a=e.lookupPath(a,{follow:!d}),a=a.node);if(!a.node_ops.setattr)throw new e.ErrnoError(q.EPERM);a.node_ops.setattr(a,{timestamp:Date.now()})},lchown:function(a,b,c){e.chown(a,b,c,!0)},fchown:function(a,b,c){a=e.getStream(a);if(!a)throw new e.ErrnoError(q.EBADF);e.chown(a.node,b,c)},truncate:function(a,b){if(0>b)throw new e.ErrnoError(q.EINVAL);"string"===typeof a&&(a=e.lookupPath(a,{follow:!0}),a=a.node);if(!a.node_ops.setattr)throw new e.ErrnoError(q.EPERM); -if(e.isDir(a.mode))throw new e.ErrnoError(q.EISDIR);if(!e.isFile(a.mode))throw new e.ErrnoError(q.EINVAL);var c=e.nodePermissions(a,"w");if(c)throw new e.ErrnoError(c);a.node_ops.setattr(a,{size:b,timestamp:Date.now()})},ftruncate:function(a,b){a=e.getStream(a);if(!a)throw new e.ErrnoError(q.EBADF);if(0===(a.flags&2097155))throw new e.ErrnoError(q.EINVAL);e.truncate(a.node,b)},utime:function(a,b,c){a=e.lookupPath(a,{follow:!0});a=a.node;a.node_ops.setattr(a,{timestamp:Math.max(b,c)})},open:function(a, -b,c,f,g){if(""===a)throw new e.ErrnoError(q.ENOENT);b="string"===typeof b?e.modeStringToFlags(b):b;c="undefined"===typeof c?438:c;c=b&64?c&4095|32768:0;if("object"===typeof a)var m=a;else{a=x.normalize(a);try{var h=e.lookupPath(a,{follow:!(b&131072)});m=h.node}catch(K){}}h=!1;if(b&64)if(m){if(b&128)throw new e.ErrnoError(q.EEXIST);}else m=e.mknod(a,c,0),h=!0;if(!m)throw new e.ErrnoError(q.ENOENT);e.isChrdev(m.mode)&&(b&=-513);if(b&65536&&!e.isDir(m.mode))throw new e.ErrnoError(q.ENOTDIR);if(!h&&(c= -e.mayOpen(m,b)))throw new e.ErrnoError(c);b&512&&e.truncate(m,0);b&=-641;f=e.createStream({node:m,path:e.getPath(m),flags:b,seekable:!0,position:0,stream_ops:m.stream_ops,ungotten:[],error:!1},f,g);f.stream_ops.open&&f.stream_ops.open(f);!d.logReadFiles||b&1||(e.readFiles||(e.readFiles={}),a in e.readFiles||(e.readFiles[a]=1,d.printErr("read file: "+a)));try{e.trackingDelegate.onOpenFile&&(g=0,1!==(b&2097155)&&(g|=e.tracking.openFlags.READ),0!==(b&2097155)&&(g|=e.tracking.openFlags.WRITE),e.trackingDelegate.onOpenFile(a, -g))}catch(K){console.log("FS.trackingDelegate['onOpenFile']('"+a+"', flags) threw an exception: "+K.message)}return f},close:function(a){a.getdents&&(a.getdents=null);try{a.stream_ops.close&&a.stream_ops.close(a)}catch(b){throw b;}finally{e.closeStream(a.fd)}},llseek:function(a,b,c){if(!a.seekable||!a.stream_ops.llseek)throw new e.ErrnoError(q.ESPIPE);a.position=a.stream_ops.llseek(a,b,c);a.ungotten=[];return a.position},read:function(a,b,c,d,g){if(0>d||0>g)throw new e.ErrnoError(q.EINVAL);if(1=== -(a.flags&2097155))throw new e.ErrnoError(q.EBADF);if(e.isDir(a.node.mode))throw new e.ErrnoError(q.EISDIR);if(!a.stream_ops.read)throw new e.ErrnoError(q.EINVAL);var f=!0;if("undefined"===typeof g)g=a.position,f=!1;else if(!a.seekable)throw new e.ErrnoError(q.ESPIPE);b=a.stream_ops.read(a,b,c,d,g);f||(a.position+=b);return b},write:function(a,b,c,d,g,h){if(0>d||0>g)throw new e.ErrnoError(q.EINVAL);if(0===(a.flags&2097155))throw new e.ErrnoError(q.EBADF);if(e.isDir(a.node.mode))throw new e.ErrnoError(q.EISDIR); -if(!a.stream_ops.write)throw new e.ErrnoError(q.EINVAL);a.flags&1024&&(g=e.llseek(a,0,2));var f=!0;if("undefined"===typeof g)g=a.position,f=!1;else if(!a.seekable)throw new e.ErrnoError(q.ESPIPE);b=a.stream_ops.write(a,b,c,d,g,h);f||(a.position+=b);try{if(a.path&&e.trackingDelegate.onWriteToFile)e.trackingDelegate.onWriteToFile(a.path)}catch(K){console.log("FS.trackingDelegate['onWriteToFile']('"+path+"') threw an exception: "+K.message)}return b},allocate:function(a,b,c){if(0>b||0>=c)throw new e.ErrnoError(q.EINVAL); -if(0===(a.flags&2097155))throw new e.ErrnoError(q.EBADF);if(!e.isFile(a.node.mode)&&!e.isDir(a.node.mode))throw new e.ErrnoError(q.ENODEV);if(!a.stream_ops.allocate)throw new e.ErrnoError(q.EOPNOTSUPP);a.stream_ops.allocate(a,b,c)},mmap:function(a,b,c,d,g,h,n){if(1===(a.flags&2097155))throw new e.ErrnoError(q.EACCES);if(!a.stream_ops.mmap)throw new e.ErrnoError(q.ENODEV);return a.stream_ops.mmap(a,b,c,d,g,h,n)},msync:function(a,b,c,d,e){return a&&a.stream_ops.msync?a.stream_ops.msync(a,b,c,d,e):0}, -munmap:function(){return 0},ioctl:function(a,b,c){if(!a.stream_ops.ioctl)throw new e.ErrnoError(q.ENOTTY);return a.stream_ops.ioctl(a,b,c)},readFile:function(a,b){b=b||{};b.flags=b.flags||"r";b.encoding=b.encoding||"binary";if("utf8"!==b.encoding&&"binary"!==b.encoding)throw Error('Invalid encoding type "'+b.encoding+'"');var c,d=e.open(a,b.flags);a=e.stat(a);a=a.size;var g=new Uint8Array(a);e.read(d,g,0,a,0);"utf8"===b.encoding?c=za(g,0):"binary"===b.encoding&&(c=g);e.close(d);return c},writeFile:function(a, -b,c){c=c||{};c.flags=c.flags||"w";a=e.open(a,c.flags,c.mode);if("string"===typeof b){var d=new Uint8Array(Va(b)+1);b=Y(b,d,0,d.length);e.write(a,d,0,b,0,c.canOwn)}else if(ArrayBuffer.isView(b))e.write(a,b,0,b.byteLength,0,c.canOwn);else throw Error("Unsupported data type");e.close(a)},cwd:function(){return e.currentPath},chdir:function(a){a=e.lookupPath(a,{follow:!0});if(null===a.node)throw new e.ErrnoError(q.ENOENT);if(!e.isDir(a.node.mode))throw new e.ErrnoError(q.ENOTDIR);var b=e.nodePermissions(a.node, -"x");if(b)throw new e.ErrnoError(b);e.currentPath=a.path},createDefaultDirectories:function(){e.mkdir("/tmp");e.mkdir("/home");e.mkdir("/home/web_user")},createDefaultDevices:function(){e.mkdir("/dev");e.registerDevice(e.makedev(1,3),{read:function(){return 0},write:function(a,b,d,e){return e}});e.mkdev("/dev/null",e.makedev(1,3));ta.register(e.makedev(5,0),ta.default_tty_ops);ta.register(e.makedev(6,0),ta.default_tty1_ops);e.mkdev("/dev/tty",e.makedev(5,0));e.mkdev("/dev/tty1",e.makedev(6,0));if("undefined"!== -typeof crypto){var a=new Uint8Array(1);var b=function(){crypto.getRandomValues(a);return a[0]}}else b=ca?function(){return require("crypto").randomBytes(1)[0]}:function(){return 256*Math.random()|0};e.createDevice("/dev","random",b);e.createDevice("/dev","urandom",b);e.mkdir("/dev/shm");e.mkdir("/dev/shm/tmp")},createSpecialDirectories:function(){e.mkdir("/proc");e.mkdir("/proc/self");e.mkdir("/proc/self/fd");e.mount({mount:function(){var a=e.createNode("/proc/self","fd",16895,73);a.node_ops={lookup:function(a, -c){a=+c;var b=e.getStream(a);if(!b)throw new e.ErrnoError(q.EBADF);a={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:function(){return b.path}}};return a.parent=a}};return a}},{},"/proc/self/fd")},createStandardStreams:function(){d.stdin?e.createDevice("/dev","stdin",d.stdin):e.symlink("/dev/tty","/dev/stdin");d.stdout?e.createDevice("/dev","stdout",null,d.stdout):e.symlink("/dev/tty","/dev/stdout");d.stderr?e.createDevice("/dev","stderr",null,d.stderr):e.symlink("/dev/tty1","/dev/stderr"); -var a=e.open("/dev/stdin","r");D(0===a.fd,"invalid handle for stdin ("+a.fd+")");a=e.open("/dev/stdout","w");D(1===a.fd,"invalid handle for stdout ("+a.fd+")");a=e.open("/dev/stderr","w");D(2===a.fd,"invalid handle for stderr ("+a.fd+")")},ensureErrnoError:function(){e.ErrnoError||(e.ErrnoError=function(a,b){this.node=b;this.setErrno=function(a){this.errno=a;for(var b in q)if(q[b]===a){this.code=b;break}};this.setErrno(a);this.message=ul[a];this.stack&&Object.defineProperty(this,"stack",{value:Error().stack, -writable:!0})},e.ErrnoError.prototype=Error(),e.ErrnoError.prototype.constructor=e.ErrnoError,[q.ENOENT].forEach(function(a){e.genericErrors[a]=new e.ErrnoError(a);e.genericErrors[a].stack="<generic error, no stack>"}))},staticInit:function(){e.ensureErrnoError();e.nameTable=Array(4096);e.mount(A,{},"/");e.createDefaultDirectories();e.createDefaultDevices();e.createSpecialDirectories();e.filesystems={MEMFS:A,IDBFS:L,NODEFS:H,WORKERFS:Q}},init:function(a,b,c){D(!e.init.initialized,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)"); -e.init.initialized=!0;e.ensureErrnoError();d.stdin=a||d.stdin;d.stdout=b||d.stdout;d.stderr=c||d.stderr;e.createStandardStreams()},quit:function(){e.init.initialized=!1;var a=d._fflush;a&&a(0);for(a=0;a<e.streams.length;a++){var b=e.streams[a];b&&e.close(b)}},getMode:function(a,b){var c=0;a&&(c|=365);b&&(c|=146);return c},joinPath:function(a,b){a=x.join.apply(null,a);b&&"/"==a[0]&&(a=a.substr(1));return a},absolutePath:function(a,b){return x.resolve(b,a)},standardizePath:function(a){return x.normalize(a)}, -findObject:function(a,b){a=e.analyzePath(a,b);if(a.exists)return a.object;Ba(a.error);return null},analyzePath:function(a,b){try{var c=e.lookupPath(a,{follow:!b});a=c.path}catch(m){}var d={isRoot:!1,exists:!1,error:0,name:null,path:null,object:null,parentExists:!1,parentPath:null,parentObject:null};try{c=e.lookupPath(a,{parent:!0}),d.parentExists=!0,d.parentPath=c.path,d.parentObject=c.node,d.name=x.basename(a),c=e.lookupPath(a,{follow:!b}),d.exists=!0,d.path=c.path,d.object=c.node,d.name=c.node.name, -d.isRoot="/"===c.path}catch(m){d.error=m.errno}return d},createFolder:function(a,b,c,d){a=x.join2("string"===typeof a?a:e.getPath(a),b);c=e.getMode(c,d);return e.mkdir(a,c)},createPath:function(a,b){a="string"===typeof a?a:e.getPath(a);for(b=b.split("/").reverse();b.length;){var c=b.pop();if(c){var d=x.join2(a,c);try{e.mkdir(d)}catch(m){}a=d}}return d},createFile:function(a,b,c,d,g){a=x.join2("string"===typeof a?a:e.getPath(a),b);d=e.getMode(d,g);return e.create(a,d)},createDataFile:function(a,b, -c,d,g,h){a=b?x.join2("string"===typeof a?a:e.getPath(a),b):a;d=e.getMode(d,g);g=e.create(a,d);if(c){if("string"===typeof c){a=Array(c.length);b=0;for(var f=c.length;b<f;++b)a[b]=c.charCodeAt(b);c=a}e.chmod(g,d|146);a=e.open(g,"w");e.write(a,c,0,c.length,0,h);e.close(a);e.chmod(g,d)}return g},createDevice:function(a,b,c,d){a=x.join2("string"===typeof a?a:e.getPath(a),b);b=e.getMode(!!c,!!d);e.createDevice.major||(e.createDevice.major=64);var f=e.makedev(e.createDevice.major++,0);e.registerDevice(f, -{open:function(a){a.seekable=!1},close:function(){d&&d.buffer&&d.buffer.length&&d(10)},read:function(a,b,d,f){for(var g=0,h=0;h<f;h++){try{var m=c()}catch(vl){throw new e.ErrnoError(q.EIO);}if(void 0===m&&0===g)throw new e.ErrnoError(q.EAGAIN);if(null===m||void 0===m)break;g++;b[d+h]=m}g&&(a.node.timestamp=Date.now());return g},write:function(a,b,c,f){for(var g=0;g<f;g++)try{d(b[c+g])}catch(P){throw new e.ErrnoError(q.EIO);}f&&(a.node.timestamp=Date.now());return g}});return e.mkdev(a,b,f)},createLink:function(a, -b,c){a=x.join2("string"===typeof a?a:e.getPath(a),b);return e.symlink(c,a)},forceLoadFile:function(a){if(a.isDevice||a.isFolder||a.link||a.contents)return!0;var b=!0;if("undefined"!==typeof XMLHttpRequest)throw Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");if(d.read)try{a.contents=ra(d.read(a.url),!0),a.usedBytes=a.contents.length}catch(c){b=!1}else throw Error("Cannot load without read() or XMLHttpRequest."); -b||Ba(q.EIO);return b},createLazyFile:function(a,b,c,d,g){function f(){this.lengthKnown=!1;this.chunks=[]}f.prototype.get=function(a){if(!(a>this.length-1||0>a)){var b=a%this.chunkSize;a=a/this.chunkSize|0;return this.getter(a)[b]}};f.prototype.setDataGetter=function(a){this.getter=a};f.prototype.cacheLength=function(){var a=new XMLHttpRequest;a.open("HEAD",c,!1);a.send(null);if(!(200<=a.status&&300>a.status||304===a.status))throw Error("Couldn't load "+c+". Status: "+a.status);var b=Number(a.getResponseHeader("Content-length")), -d,f=(d=a.getResponseHeader("Accept-Ranges"))&&"bytes"===d;a=(d=a.getResponseHeader("Content-Encoding"))&&"gzip"===d;var e=1048576;f||(e=b);var g=this;g.setDataGetter(function(a){var d=a*e,f=(a+1)*e-1;f=Math.min(f,b-1);if("undefined"===typeof g.chunks[a]){var h=g.chunks;if(d>f)throw Error("invalid range ("+d+", "+f+") or no bytes requested!");if(f>b-1)throw Error("only "+b+" bytes available! programmer error!");var m=new XMLHttpRequest;m.open("GET",c,!1);b!==e&&m.setRequestHeader("Range","bytes="+ -d+"-"+f);"undefined"!=typeof Uint8Array&&(m.responseType="arraybuffer");m.overrideMimeType&&m.overrideMimeType("text/plain; charset=x-user-defined");m.send(null);if(!(200<=m.status&&300>m.status||304===m.status))throw Error("Couldn't load "+c+". Status: "+m.status);d=void 0!==m.response?new Uint8Array(m.response||[]):ra(m.responseText||"",!0);h[a]=d}if("undefined"===typeof g.chunks[a])throw Error("doXHR failed!");return g.chunks[a]});if(a||!b)e=b=1,e=b=this.getter(0).length,console.log("LazyFiles on gzip forces download of the whole file when length is accessed"); -this._length=b;this._chunkSize=e;this.lengthKnown=!0};if("undefined"!==typeof XMLHttpRequest){if(!Z)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var h=new f;Object.defineProperties(h,{length:{get:function(){this.lengthKnown||this.cacheLength();return this._length}},chunkSize:{get:function(){this.lengthKnown||this.cacheLength();return this._chunkSize}}});h={isDevice:!1,contents:h}}else h={isDevice:!1,url:c};var m=e.createFile(a, -b,h,d,g);h.contents?m.contents=h.contents:h.url&&(m.contents=null,m.url=h.url);Object.defineProperties(m,{usedBytes:{get:function(){return this.contents.length}}});var k={};a=Object.keys(m.stream_ops);a.forEach(function(a){var b=m.stream_ops[a];k[a]=function(){if(!e.forceLoadFile(m))throw new e.ErrnoError(q.EIO);return b.apply(null,arguments)}});k.read=function(a,b,c,d,f){if(!e.forceLoadFile(m))throw new e.ErrnoError(q.EIO);a=a.node.contents;if(f>=a.length)return 0;d=Math.min(a.length-f,d);D(0<=d); -if(a.slice)for(var g=0;g<d;g++)b[c+g]=a[f+g];else for(g=0;g<d;g++)b[c+g]=a.get(f+g);return d};m.stream_ops=k;return m},createPreloadedFile:function(a,b,c,f,g,h,n,k,p,q){function m(c){function m(c){q&&q();k||e.createDataFile(a,b,c,f,g,p);h&&h();Wa(r)}var l=!1;d.preloadPlugins.forEach(function(a){!l&&a.canHandle(t)&&(a.handle(c,t,m,function(){n&&n();Wa(r)}),l=!0)});l||m(c)}l.init();var t=b?x.resolve(x.join2(a,b)):a,r="cp "+t;rb(r);"string"==typeof c?l.asyncLoad(c,function(a){m(a)},n):m(c)},indexedDB:function(){return g.indexedDB|| -g.mozIndexedDB||g.webkitIndexedDB||g.msIndexedDB},DB_NAME:function(){return"EM_FS_"+g.location.pathname},DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function(a,b,c){b=b||function(){};c=c||function(){};var d=e.indexedDB();try{var g=d.open(e.DB_NAME(),e.DB_VERSION)}catch(t){return c(t)}g.onupgradeneeded=function(){console.log("creating db");var a=g.result;a.createObjectStore(e.DB_STORE_NAME)};g.onsuccess=function(){var d=g.result;d=d.transaction([e.DB_STORE_NAME],"readwrite");var f=d.objectStore(e.DB_STORE_NAME), -h=0,m=0,k=a.length;a.forEach(function(a){a=f.put(e.analyzePath(a).object.contents,a);a.onsuccess=function(){h++;h+m==k&&(0==m?b():c())};a.onerror=function(){m++;h+m==k&&(0==m?b():c())}});d.onerror=c};g.onerror=c},loadFilesFromDB:function(a,b,c){b=b||function(){};c=c||function(){};var d=e.indexedDB();try{var g=d.open(e.DB_NAME(),e.DB_VERSION)}catch(t){return c(t)}g.onupgradeneeded=c;g.onsuccess=function(){var d=g.result;try{var f=d.transaction([e.DB_STORE_NAME],"readonly")}catch(Ub){c(Ub);return}var h= -f.objectStore(e.DB_STORE_NAME),m=0,k=0,l=a.length;a.forEach(function(a){var d=h.get(a);d.onsuccess=function(){e.analyzePath(a).exists&&e.unlink(a);e.createDataFile(x.dirname(a),x.basename(a),d.result,!0,!0,!0);m++;m+k==l&&(0==k?b():c())};d.onerror=function(){k++;m+k==l&&(0==k?b():c())}});f.onerror=c};g.onerror=c}},C={DEFAULT_POLLMASK:5,mappings:{},umask:511,calculateAt:function(a,b){if("/"!==b[0]){if(-100===a)a=e.cwd();else{a=e.getStream(a);if(!a)throw new e.ErrnoError(q.EBADF);a=a.path}b=x.join2(a, -b)}return b},doStat:function(a,b,c){try{var d=a(b)}catch(m){if(m&&m.node&&x.normalize(b)!==x.normalize(e.getPath(m.node)))return-q.ENOTDIR;throw m;}p[c>>2]=d.dev;p[c+4>>2]=0;p[c+8>>2]=d.ino;p[c+12>>2]=d.mode;p[c+16>>2]=d.nlink;p[c+20>>2]=d.uid;p[c+24>>2]=d.gid;p[c+28>>2]=d.rdev;p[c+32>>2]=0;p[c+36>>2]=d.size;p[c+40>>2]=4096;p[c+44>>2]=d.blocks;p[c+48>>2]=d.atime.getTime()/1E3|0;p[c+52>>2]=0;p[c+56>>2]=d.mtime.getTime()/1E3|0;p[c+60>>2]=0;p[c+64>>2]=d.ctime.getTime()/1E3|0;p[c+68>>2]=0;p[c+72>>2]= -d.ino;return 0},doMsync:function(a,b,c,d){a=new Uint8Array(F.subarray(a,a+c));e.msync(b,a,0,c,d)},doMkdir:function(a,b){a=x.normalize(a);"/"===a[a.length-1]&&(a=a.substr(0,a.length-1));e.mkdir(a,b,0);return 0},doMknod:function(a,b,c){switch(b&61440){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-q.EINVAL}e.mknod(a,b,c);return 0},doReadlink:function(a,b,c){if(0>=c)return-q.EINVAL;a=e.readlink(a);var d=Math.min(c,Va(a)),g=M[b+d];Y(a,F,b,c+1);M[b+d]=g;return d},doAccess:function(a, -b){if(b&-8)return-q.EINVAL;a=e.lookupPath(a,{follow:!0});a=a.node;var c="";b&4&&(c+="r");b&2&&(c+="w");b&1&&(c+="x");return c&&e.nodePermissions(a,c)?-q.EACCES:0},doDup:function(a,b,c){var d=e.getStream(c);d&&e.close(d);return e.open(a,b,0,c,c).fd},doReadv:function(a,b,c,d){for(var f=0,g=0;g<c;g++){var h=p[b+8*g>>2],k=p[b+(8*g+4)>>2];h=e.read(a,M,h,k,d);if(0>h)return-1;f+=h;if(h<k)break}return f},doWritev:function(a,b,c,d){for(var f=0,g=0;g<c;g++){var h=p[b+8*g>>2],k=p[b+(8*g+4)>>2];h=e.write(a,M, -h,k,d);if(0>h)return-1;f+=h}return f},varargs:0,get:function(){C.varargs+=4;var a=p[C.varargs-4>>2];return a},getStr:function(){var a=R(C.get());return a},getStreamFromFD:function(){var a=e.getStream(C.get());if(!a)throw new e.ErrnoError(q.EBADF);return a},getSocketFromFD:function(){var a=SOCKFS.getSocket(C.get());if(!a)throw new e.ErrnoError(q.EBADF);return a},getSocketAddress:function(a){var b=C.get(),c=C.get();if(a&&0===b)return null;a=__read_sockaddr(b,c);if(a.errno)throw new e.ErrnoError(a.errno); -a.addr=DNS.lookup_addr(a.addr)||a.addr;return a},get64:function(){var a=C.get(),b=C.get();0<=a?D(0===b):D(-1===b);return a},getZero:function(){D(0===C.get())}},tb=[],T=[{},{value:void 0},{value:null},{value:!0},{value:!1}],dc=void 0,bc=void 0,La=[],Ma=void 0,la={},Ca=void 0,xa={},bb={},Da={},ab={},ec=void 0,gc={},ic=void 0,Pd={},hb=[],l={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){l.mainLoop.scheduler= -null;l.mainLoop.currentlyRunningMainloop++},resume:function(){l.mainLoop.currentlyRunningMainloop++;var a=l.mainLoop.timingMode,b=l.mainLoop.timingValue,c=l.mainLoop.func;l.mainLoop.func=null;fe(c,0,!1,l.mainLoop.arg,!0);Bb(a,b);l.mainLoop.scheduler()},updateStatus:function(){if(d.setStatus){var a=d.statusMessage||"Please wait...",b=l.mainLoop.remainingBlockers,c=l.mainLoop.expectedBlockers;b?b<c?d.setStatus(a+" ("+(c-b)+"/"+c+")"):d.setStatus(a):d.setStatus("")}},runIter:function(a){if(!da){if(d.preMainLoop){var b= -d.preMainLoop();if(!1===b)return}try{a()}catch(c){if(c instanceof Ga)return;c&&"object"===typeof c&&c.stack&&d.printErr("exception thrown: "+[c,c.stack]);throw c;}d.postMainLoop&&d.postMainLoop()}}},isFullscreen:!1,pointerLock:!1,moduleContextCreatedCallbacks:[],workers:[],init:function(){function a(){l.pointerLock=document.pointerLockElement===d.canvas||document.mozPointerLockElement===d.canvas||document.webkitPointerLockElement===d.canvas||document.msPointerLockElement===d.canvas}d.preloadPlugins|| -(d.preloadPlugins=[]);if(!l.initted){l.initted=!0;try{l.hasBlobConstructor=!0}catch(c){l.hasBlobConstructor=!1,console.log("warning: no blob constructor, cannot create blobs with mimetypes")}l.BlobBuilder="undefined"!=typeof MozBlobBuilder?MozBlobBuilder:"undefined"!=typeof WebKitBlobBuilder?WebKitBlobBuilder:l.hasBlobConstructor?null:console.log("warning: no BlobBuilder");l.URLObject="undefined"!=typeof g?g.URL?g.URL:g.webkitURL:void 0;d.noImageDecoding||"undefined"!==typeof l.URLObject||(console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."), -d.noImageDecoding=!0);var b={canHandle:function(a){return!d.noImageDecoding&&/\.(jpg|jpeg|png|bmp)$/i.test(a)},handle:function(a,b,e,g){var c=null;if(l.hasBlobConstructor)try{c=new Blob([a],{type:l.getMimetype(b)}),c.size!==a.length&&(c=new Blob([(new Uint8Array(a)).buffer],{type:l.getMimetype(b)}))}catch(Bc){ia("Blob constructor present but fails: "+Bc+"; falling back to blob builder")}c||(c=new l.BlobBuilder,c.append((new Uint8Array(a)).buffer),c=c.getBlob());var f=l.URLObject.createObjectURL(c), -h=new Image;h.onload=function(){D(h.complete,"Image "+b+" could not be decoded");var c=document.createElement("canvas");c.width=h.width;c.height=h.height;var g=c.getContext("2d");g.drawImage(h,0,0);d.preloadedImages[b]=c;l.URLObject.revokeObjectURL(f);e&&e(a)};h.onerror=function(){console.log("Image "+f+" could not be decoded");g&&g()};h.src=f}};d.preloadPlugins.push(b);b={canHandle:function(a){return!d.noAudioDecoding&&a.substr(-4)in{".ogg":1,".wav":1,".mp3":1}},handle:function(a,b,e,g){function c(c){h|| -(h=!0,d.preloadedAudios[b]=c,e&&e(a))}function f(){h||(h=!0,d.preloadedAudios[b]=new Audio,g&&g())}var h=!1;if(l.hasBlobConstructor){try{var m=new Blob([a],{type:l.getMimetype(b)})}catch(Ub){return f()}m=l.URLObject.createObjectURL(m);var k=new Audio;k.addEventListener("canplaythrough",function(){c(k)},!1);k.onerror=function(){if(!h){console.log("warning: browser could not fully decode audio "+b+", trying slower base64 approach");var d="";for(var f=0,e=0,g=0;g<a.length;g++)for(f=f<<8|a[g],e+=8;6<= -e;){var m=f>>e-6&63;e-=6;d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[m]}2==e?(d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(f&3)<<4],d+="=="):4==e&&(d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(f&15)<<2],d+="=");k.src="data:audio/x-"+b.substr(-3)+";base64,"+d;c(k)}};k.src=m;l.safeSetTimeout(function(){c(k)},1E4)}else return f()}};d.preloadPlugins.push(b);if(b=d.canvas)b.requestPointerLock=b.requestPointerLock||b.mozRequestPointerLock|| -b.webkitRequestPointerLock||b.msRequestPointerLock||function(){},b.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock||document.msExitPointerLock||function(){},b.exitPointerLock=b.exitPointerLock.bind(document),document.addEventListener("pointerlockchange",a,!1),document.addEventListener("mozpointerlockchange",a,!1),document.addEventListener("webkitpointerlockchange",a,!1),document.addEventListener("mspointerlockchange",a,!1),d.elementPointerLock&& -b.addEventListener("click",function(a){!l.pointerLock&&d.canvas.requestPointerLock&&(d.canvas.requestPointerLock(),a.preventDefault())},!1)}},createContext:function(a,b,c,f){if(b&&d.ctx&&a==d.canvas)return d.ctx;if(b){var e={antialias:!1,alpha:!1};if(f)for(var g in f)e[g]=f[g];if(e=h.createContext(a,e))var n=h.getContext(e).GLctx}else n=a.getContext("2d");if(!n)return null;c&&(b||D("undefined"===typeof k,"cannot set in module if GLctx is used, but we are a non-GL context that would replace it"),d.ctx= -n,b&&h.makeContextCurrent(e),d.useWebGL=b,l.moduleContextCreatedCallbacks.forEach(function(a){a()}),l.init());return n},destroyContext:function(){},fullscreenHandlersInstalled:!1,lockPointer:void 0,resizeCanvas:void 0,requestFullscreen:function(a,b,c){function f(){l.isFullscreen=!1;var a=e.parentNode;(document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===a?(e.exitFullscreen=document.exitFullscreen|| -document.cancelFullScreen||document.mozCancelFullScreen||document.msExitFullscreen||document.webkitCancelFullScreen||function(){},e.exitFullscreen=e.exitFullscreen.bind(document),l.lockPointer&&e.requestPointerLock(),l.isFullscreen=!0,l.resizeCanvas&&l.setFullscreenCanvasSize()):(a.parentNode.insertBefore(e,a),a.parentNode.removeChild(a),l.resizeCanvas&&l.setWindowedCanvasSize());if(d.onFullScreen)d.onFullScreen(l.isFullscreen);if(d.onFullscreen)d.onFullscreen(l.isFullscreen);l.updateCanvasDimensions(e)} -l.lockPointer=a;l.resizeCanvas=b;l.vrDevice=c;"undefined"===typeof l.lockPointer&&(l.lockPointer=!0);"undefined"===typeof l.resizeCanvas&&(l.resizeCanvas=!1);"undefined"===typeof l.vrDevice&&(l.vrDevice=null);var e=d.canvas;l.fullscreenHandlersInstalled||(l.fullscreenHandlersInstalled=!0,document.addEventListener("fullscreenchange",f,!1),document.addEventListener("mozfullscreenchange",f,!1),document.addEventListener("webkitfullscreenchange",f,!1),document.addEventListener("MSFullscreenChange",f,!1)); -var g=document.createElement("div");e.parentNode.insertBefore(g,e);g.appendChild(e);g.requestFullscreen=g.requestFullscreen||g.mozRequestFullScreen||g.msRequestFullscreen||(g.webkitRequestFullscreen?function(){g.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}:null)||(g.webkitRequestFullScreen?function(){g.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}:null);c?g.requestFullscreen({vrDisplay:c}):g.requestFullscreen()},requestFullScreen:function(a,b,c){d.printErr("Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead."); -l.requestFullScreen=function(a,b,c){return l.requestFullscreen(a,b,c)};return l.requestFullscreen(a,b,c)},nextRAF:0,fakeRequestAnimationFrame:function(a){var b=Date.now();if(0===l.nextRAF)l.nextRAF=b+1E3/60;else for(;b+2>=l.nextRAF;)l.nextRAF+=1E3/60;b=Math.max(l.nextRAF-b,0);setTimeout(a,b)},requestAnimationFrame:function(a){"undefined"===typeof g?l.fakeRequestAnimationFrame(a):(g.requestAnimationFrame||(g.requestAnimationFrame=g.requestAnimationFrame||g.mozRequestAnimationFrame||g.webkitRequestAnimationFrame|| -g.msRequestAnimationFrame||g.oRequestAnimationFrame||l.fakeRequestAnimationFrame),g.requestAnimationFrame(a))},safeCallback:function(a){return function(){if(!da)return a.apply(null,arguments)}},allowAsyncCallbacks:!0,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function(){l.allowAsyncCallbacks=!1},resumeAsyncCallbacks:function(){l.allowAsyncCallbacks=!0;if(0<l.queuedAsyncCallbacks.length){var a=l.queuedAsyncCallbacks;l.queuedAsyncCallbacks=[];a.forEach(function(a){a()})}},safeRequestAnimationFrame:function(a){return l.requestAnimationFrame(function(){da|| -(l.allowAsyncCallbacks?a():l.queuedAsyncCallbacks.push(a))})},safeSetTimeout:function(a,b){d.noExitRuntime=!0;return setTimeout(function(){da||(l.allowAsyncCallbacks?a():l.queuedAsyncCallbacks.push(a))},b)},safeSetInterval:function(a,b){d.noExitRuntime=!0;return setInterval(function(){da||l.allowAsyncCallbacks&&a()},b)},getMimetype:function(a){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",bmp:"image/bmp",ogg:"audio/ogg",wav:"audio/wav",mp3:"audio/mpeg"}[a.substr(a.lastIndexOf(".")+1)]}, -getUserMedia:function(a){g.getUserMedia||(g.getUserMedia=navigator.getUserMedia||navigator.mozGetUserMedia);g.getUserMedia(a)},getMovementX:function(a){return a.movementX||a.mozMovementX||a.webkitMovementX||0},getMovementY:function(a){return a.movementY||a.mozMovementY||a.webkitMovementY||0},getMouseWheelDelta:function(a){switch(a.type){case "DOMMouseScroll":a=a.detail;break;case "mousewheel":a=a.wheelDelta;break;case "wheel":a=a.deltaY;break;default:throw"unrecognized mouse wheel event: "+a.type; -}return a},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(a){if(l.pointerLock)"mousemove"!=a.type&&"mozMovementX"in a?l.mouseMovementX=l.mouseMovementY=0:(l.mouseMovementX=l.getMovementX(a),l.mouseMovementY=l.getMovementY(a)),"undefined"!=typeof SDL?(l.mouseX=SDL.mouseX+l.mouseMovementX,l.mouseY=SDL.mouseY+l.mouseMovementY):(l.mouseX+=l.mouseMovementX,l.mouseY+=l.mouseMovementY);else{var b=d.canvas.getBoundingClientRect(),c=d.canvas.width, -f=d.canvas.height,e="undefined"!==typeof g.scrollX?g.scrollX:g.pageXOffset,h="undefined"!==typeof g.scrollY?g.scrollY:g.pageYOffset;if("touchstart"===a.type||"touchend"===a.type||"touchmove"===a.type){var k=a.touch;if(void 0!==k)if(e=k.pageX-(e+b.left),h=k.pageY-(h+b.top),e*=c/b.width,h*=f/b.height,b={x:e,y:h},"touchstart"===a.type)l.lastTouches[k.identifier]=b,l.touches[k.identifier]=b;else if("touchend"===a.type||"touchmove"===a.type)(a=l.touches[k.identifier])||(a=b),l.lastTouches[k.identifier]= -a,l.touches[k.identifier]=b}else k=a.pageX-(e+b.left),a=a.pageY-(h+b.top),k*=c/b.width,a*=f/b.height,l.mouseMovementX=k-l.mouseX,l.mouseMovementY=a-l.mouseY,l.mouseX=k,l.mouseY=a}},asyncLoad:function(a,b,c,f){var e=f?"":"al "+a;d.readAsync(a,function(c){D(c,'Loading data file "'+a+'" failed (no arrayBuffer).');b(new Uint8Array(c));e&&Wa(e)},function(){if(c)c();else throw'Loading data file "'+a+'" failed.';});e&&rb(e)},resizeListeners:[],updateResizeListeners:function(){var a=d.canvas;l.resizeListeners.forEach(function(b){b(a.width, -a.height)})},setCanvasSize:function(a,b,c){var f=d.canvas;l.updateCanvasDimensions(f,a,b);c||l.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if("undefined"!=typeof SDL){var a=S[SDL.screen>>2];a|=8388608;p[SDL.screen>>2]=a}l.updateResizeListeners()},setWindowedCanvasSize:function(){if("undefined"!=typeof SDL){var a=S[SDL.screen>>2];a&=-8388609;p[SDL.screen>>2]=a}l.updateResizeListeners()},updateCanvasDimensions:function(a,b,c){b&&c?(a.widthNative=b,a.heightNative= -c):(b=a.widthNative,c=a.heightNative);var f=b,e=c;d.forcedAspectRatio&&0<d.forcedAspectRatio&&(f/e<d.forcedAspectRatio?f=Math.round(e*d.forcedAspectRatio):e=Math.round(f/d.forcedAspectRatio));if((document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===a.parentNode&&"undefined"!=typeof screen){var g=Math.min(screen.width/f,screen.height/e);f=Math.round(f*g);e=Math.round(e*g)}l.resizeCanvas? -(a.width!=f&&(a.width=f),a.height!=e&&(a.height=e),"undefined"!=typeof a.style&&(a.style.removeProperty("width"),a.style.removeProperty("height"))):(a.width!=b&&(a.width=b),a.height!=c&&(a.height=c),"undefined"!=typeof a.style&&(f!=b||e!=c?(a.style.setProperty("width",f+"px","important"),a.style.setProperty("height",e+"px","important")):(a.style.removeProperty("width"),a.style.removeProperty("height"))))},wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:function(){var a=l.nextWgetRequestHandle; -l.nextWgetRequestHandle++;return a}},y={errorCode:12288,defaultDisplayInitialized:!1,currentContext:0,currentReadSurface:0,currentDrawSurface:0,stringCache:{},setErrorCode:function(a){y.errorCode=a},chooseConfig:function(a,b,c,d,e){if(62E3!=a)return y.setErrorCode(12296),0;if(!(c&&d||e))return y.setErrorCode(12300),0;e&&(p[e>>2]=1);c&&0<d&&(p[c>>2]=62002);y.setErrorCode(12288);return 1}},w={initTime:null,idleFunc:null,displayFunc:null,keyboardFunc:null,keyboardUpFunc:null,specialFunc:null,specialUpFunc:null, -reshapeFunc:null,motionFunc:null,passiveMotionFunc:null,mouseFunc:null,buttons:0,modifiers:0,initWindowWidth:256,initWindowHeight:256,initDisplayMode:18,windowX:0,windowY:0,windowWidth:0,windowHeight:0,requestedAnimationFrame:!1,saveModifiers:function(a){w.modifiers=0;a.shiftKey&&(w.modifiers+=1);a.ctrlKey&&(w.modifiers+=2);a.altKey&&(w.modifiers+=4)},onMousemove:function(a){var b=l.mouseX,c=l.mouseY;l.calculateMouseEvent(a);var e=l.mouseX,g=l.mouseY;if(e!=b||g!=c)0==w.buttons&&a.target==d.canvas&& -w.passiveMotionFunc?(a.preventDefault(),w.saveModifiers(a),d.dynCall_vii(w.passiveMotionFunc,b,c)):0!=w.buttons&&w.motionFunc&&(a.preventDefault(),w.saveModifiers(a),d.dynCall_vii(w.motionFunc,b,c))},getSpecialKey:function(a){var b=null;switch(a){case 8:b=120;break;case 46:b=111;break;case 112:b=1;break;case 113:b=2;break;case 114:b=3;break;case 115:b=4;break;case 116:b=5;break;case 117:b=6;break;case 118:b=7;break;case 119:b=8;break;case 120:b=9;break;case 121:b=10;break;case 122:b=11;break;case 123:b= -12;break;case 37:b=100;break;case 38:b=101;break;case 39:b=102;break;case 40:b=103;break;case 33:b=104;break;case 34:b=105;break;case 36:b=106;break;case 35:b=107;break;case 45:b=108;break;case 16:case 5:b=112;break;case 6:b=113;break;case 17:case 3:b=114;break;case 4:b=115;break;case 18:case 2:b=116;break;case 1:b=117}return b},getASCIIKey:function(a){if(a.ctrlKey||a.altKey||a.metaKey)return null;var b=a.keyCode;if(48<=b&&57>=b)return b;if(65<=b&&90>=b)return a.shiftKey?b:b+32;if(96<=b&&105>=b)return b- -48;if(106<=b&&111>=b)return b-106+42;switch(b){case 9:case 13:case 27:case 32:case 61:return b}a=a.shiftKey;switch(b){case 186:return a?58:59;case 187:return a?43:61;case 188:return a?60:44;case 189:return a?95:45;case 190:return a?62:46;case 191:return a?63:47;case 219:return a?123:91;case 220:return a?124:47;case 221:return a?125:93;case 222:return a?34:39}return null},onKeydown:function(a){if(w.specialFunc||w.keyboardFunc){var b=w.getSpecialKey(a.keyCode);null!==b?w.specialFunc&&(a.preventDefault(), -w.saveModifiers(a),d.dynCall_viii(w.specialFunc,b,l.mouseX,l.mouseY)):(b=w.getASCIIKey(a),null!==b&&w.keyboardFunc&&(a.preventDefault(),w.saveModifiers(a),d.dynCall_viii(w.keyboardFunc,b,l.mouseX,l.mouseY)))}},onKeyup:function(a){if(w.specialUpFunc||w.keyboardUpFunc){var b=w.getSpecialKey(a.keyCode);null!==b?w.specialUpFunc&&(a.preventDefault(),w.saveModifiers(a),d.dynCall_viii(w.specialUpFunc,b,l.mouseX,l.mouseY)):(b=w.getASCIIKey(a),null!==b&&w.keyboardUpFunc&&(a.preventDefault(),w.saveModifiers(a), -d.dynCall_viii(w.keyboardUpFunc,b,l.mouseX,l.mouseY)))}},touchHandler:function(a){if(a.target==d.canvas){var b=a.changedTouches;b=b[0];switch(a.type){case "touchstart":var c="mousedown";break;case "touchmove":c="mousemove";break;case "touchend":c="mouseup";break;default:return}var e=document.createEvent("MouseEvent");e.initMouseEvent(c,!0,!0,g,1,b.screenX,b.screenY,b.clientX,b.clientY,!1,!1,!1,!1,0,null);b.target.dispatchEvent(e);a.preventDefault()}},onMouseButtonDown:function(a){l.calculateMouseEvent(a); -w.buttons|=1<<a.button;if(a.target==d.canvas&&w.mouseFunc){try{a.target.setCapture()}catch(b){}a.preventDefault();w.saveModifiers(a);d.dynCall_viiii(w.mouseFunc,a.button,0,l.mouseX,l.mouseY)}},onMouseButtonUp:function(a){l.calculateMouseEvent(a);w.buttons&=~(1<<a.button);w.mouseFunc&&(a.preventDefault(),w.saveModifiers(a),d.dynCall_viiii(w.mouseFunc,a.button,1,l.mouseX,l.mouseY))},onMouseWheel:function(a){l.calculateMouseEvent(a);var b=-l.getMouseWheelDelta(a);b=0==b?0:0<b?Math.max(b,1):Math.min(b, --1);var c=3;0>b&&(c=4);w.mouseFunc&&(a.preventDefault(),w.saveModifiers(a),d.dynCall_viiii(w.mouseFunc,c,0,l.mouseX,l.mouseY))},onFullscreenEventChange:function(){if(document.fullscreen||document.fullScreen||document.mozFullScreen||document.webkitIsFullScreen){var a=screen.width;var b=screen.height}else a=w.windowWidth,b=w.windowHeight,document.removeEventListener("fullscreenchange",w.onFullscreenEventChange,!0),document.removeEventListener("mozfullscreenchange",w.onFullscreenEventChange,!0),document.removeEventListener("webkitfullscreenchange", -w.onFullscreenEventChange,!0);l.setCanvasSize(a,b);w.reshapeFunc&&d.dynCall_vii(w.reshapeFunc,a,b);_glutPostRedisplay()},requestFullscreen:function(){l.requestFullscreen(!1,!1)},requestFullScreen:function(){d.printErr("GLUT.requestFullScreen() is deprecated. Please call GLUT.requestFullscreen instead.");w.requestFullScreen=function(){return w.requestFullscreen()};return w.requestFullscreen()},exitFullscreen:function(){var a=document.exitFullscreen||document.cancelFullScreen||document.mozCancelFullScreen|| -document.webkitCancelFullScreen||function(){};a.apply(document,[])},cancelFullScreen:function(){d.printErr("GLUT.cancelFullScreen() is deprecated. Please call GLUT.exitFullscreen instead.");w.cancelFullScreen=function(){return w.exitFullscreen()};return w.exitFullscreen()}},h={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:[],currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],queries:[],samplers:[], -transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],programInfos:{},stringCache:{},stringiCache:{},tempFixedLengthArray:[],packAlignment:4,unpackAlignment:4,init:function(){h.miniTempBuffer=new Float32Array(h.MINI_TEMP_BUFFER_SIZE);for(var a=0;a<h.MINI_TEMP_BUFFER_SIZE;a++)h.miniTempBufferViews[a]=h.miniTempBuffer.subarray(0,a+1);for(a=0;32>a;a++)h.tempFixedLengthArray.push(Array(a))},recordError:function(a){h.lastError||(h.lastError=a)},getNewId:function(a){for(var b= -h.counter++,c=a.length;c<b;c++)a[c]=null;return b},MINI_TEMP_BUFFER_SIZE:256,miniTempBuffer:null,miniTempBufferViews:[0],getSource:function(a,b,c,d){a="";for(var e=0;e<b;++e){if(d){var f=p[d+4*e>>2];f=0>f?R(p[c+4*e>>2]):R(p[c+4*e>>2],f)}else f=R(p[c+4*e>>2]);a+=f}return a},createContext:function(a,b){function c(a){e=a.statusMessage||e}"undefined"===typeof b.majorVersion&&"undefined"===typeof b.minorVersion&&(b.majorVersion="undefined"!==typeof WebGL2RenderingContext?2:1,b.minorVersion=0);var e="?"; -try{a.addEventListener("webglcontextcreationerror",c,!1);try{if(1==b.majorVersion&&0==b.minorVersion)var g=a.getContext("webgl",b)||a.getContext("experimental-webgl",b);else if(2==b.majorVersion&&0==b.minorVersion)g=a.getContext("webgl2",b);else throw"Unsupported WebGL context version "+majorVersion+"."+minorVersion+"!";}finally{a.removeEventListener("webglcontextcreationerror",c,!1)}if(!g)throw":(";}catch(t){return d.print("Could not create canvas: "+[e,t,JSON.stringify(b)]),0}return g?a=h.registerContext(g, -b):0},registerContext:function(a,b){function c(){var a=navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);return a?parseInt(a[2],10):!1}var d=h.getNewId(h.contexts),e={handle:d,attributes:b,version:b.majorVersion,GLctx:a};e.supportsWebGL2EntryPoints=2<=e.version&&(!1===c()||58<=c());a.canvas&&(a.canvas.GLctxObject=e);h.contexts[d]=e;("undefined"===typeof b.enableExtensionsByDefault||b.enableExtensionsByDefault)&&h.initExtensions(e);return d},makeContextCurrent:function(a){a=h.contexts[a];if(!a)return!1; -k=d.ctx=a.GLctx;h.currentContext=a;return!0},getContext:function(a){return h.contexts[a]},deleteContext:function(a){h.currentContext===h.contexts[a]&&(h.currentContext=null);"object"===typeof JSEvents&&JSEvents.removeAllHandlersOnTarget(h.contexts[a].GLctx.canvas);h.contexts[a]&&h.contexts[a].GLctx.canvas&&(h.contexts[a].GLctx.canvas.GLctxObject=void 0);h.contexts[a]=null},initExtensions:function(a){a||(a=h.currentContext);if(!a.initExtensionsDone){a.initExtensionsDone=!0;var b=a.GLctx;a.maxVertexAttribs= -b.getParameter(b.MAX_VERTEX_ATTRIBS);if(2>a.version){var c=b.getExtension("ANGLE_instanced_arrays");c&&(b.vertexAttribDivisor=function(a,b){c.vertexAttribDivisorANGLE(a,b)},b.drawArraysInstanced=function(a,b,d,e){c.drawArraysInstancedANGLE(a,b,d,e)},b.drawElementsInstanced=function(a,b,d,e,f){c.drawElementsInstancedANGLE(a,b,d,e,f)});var d=b.getExtension("OES_vertex_array_object");d&&(b.createVertexArray=function(){return d.createVertexArrayOES()},b.deleteVertexArray=function(a){d.deleteVertexArrayOES(a)}, -b.bindVertexArray=function(a){d.bindVertexArrayOES(a)},b.isVertexArray=function(a){return d.isVertexArrayOES(a)});var e=b.getExtension("WEBGL_draw_buffers");e&&(b.drawBuffers=function(a,b){e.drawBuffersWEBGL(a,b)})}b.disjointTimerQueryExt=b.getExtension("EXT_disjoint_timer_query");var g="OES_texture_float OES_texture_half_float OES_standard_derivatives OES_vertex_array_object WEBGL_compressed_texture_s3tc WEBGL_depth_texture OES_element_index_uint EXT_texture_filter_anisotropic ANGLE_instanced_arrays OES_texture_float_linear OES_texture_half_float_linear WEBGL_compressed_texture_atc WEBKIT_WEBGL_compressed_texture_pvrtc WEBGL_compressed_texture_pvrtc EXT_color_buffer_half_float WEBGL_color_buffer_float EXT_frag_depth EXT_sRGB WEBGL_draw_buffers WEBGL_shared_resources EXT_shader_texture_lod EXT_color_buffer_float".split(" "); -(a=b.getSupportedExtensions())&&0<a.length&&b.getSupportedExtensions().forEach(function(a){-1!=g.indexOf(a)&&b.getExtension(a)})}},populateUniformTable:function(a){var b=h.programs[a];h.programInfos[a]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};a=h.programInfos[a];for(var c=a.uniforms,d=k.getProgramParameter(b,k.ACTIVE_UNIFORMS),e=0;e<d;++e){var g=k.getActiveUniform(b,e),l=g.name;a.maxUniformLength=Math.max(a.maxUniformLength,l.length+1);if(-1!==l.indexOf("]", -l.length-1)){var p=l.lastIndexOf("[");l=l.slice(0,p)}var q=k.getUniformLocation(b,l);if(null!=q){var r=h.getNewId(h.uniforms);c[l]=[g.size,r];h.uniforms[r]=q;for(p=1;p<g.size;++p)q=l+"["+p+"]",q=k.getUniformLocation(b,q),r=h.getNewId(h.uniforms),h.uniforms[r]=q}}}},pc=W;W+=16;var ha={},Fa={},Hb=1,lb=[31,29,31,30,31,30,31,31,30,31,30,31],mb=[31,28,31,30,31,30,31,31,30,31,30,31];e.staticInit();nb.unshift(function(){d.noFSInit||e.init.initialized||e.init()});rc.push(function(){e.ignorePermissions=!1}); -Kb.push(function(){e.quit()});nb.unshift(function(){ta.init()});Kb.push(function(){});if(ca){var N=require("fs"),vc=require("path");H.staticInit()}d.count_emval_handles=Wc;d.get_first_emval=Xc;dc=d.PureVirtualError=Za(Error,"PureVirtualError");Yc();d.getInheritedInstanceCount=Zc;d.getLiveInheritedInstances=$c;d.flushPendingDeletes=ub;d.setDelayFunction=ad;Ca=d.BindingError=Za(Error,"BindingError");ec=d.InternalError=Za(Error,"InternalError");qa.prototype.isAliasOf=fd;qa.prototype.clone=gd;qa.prototype["delete"]= -hd;qa.prototype.isDeleted=id;qa.prototype.deleteLater=jd;na.prototype.getPointee=od;na.prototype.destructor=pd;na.prototype.argPackAdvance=8;na.prototype.readValueFromPointer=Pa;na.prototype.deleteObject=qd;na.prototype.fromWireType=sd;ic=d.UnboundTypeError=Za(Error,"UnboundTypeError");ib=ca?function(){var a=process.hrtime();return 1E3*a[0]+a[1]/1E6}:"undefined"!==typeof dateNow?dateNow:"object"===typeof self&&self.performance&&"function"===typeof self.performance.now?function(){return self.performance.now()}: -"object"===typeof performance&&"function"===typeof performance.now?function(){return performance.now()}:Date.now;d.requestFullScreen=function(a,b,c){d.printErr("Module.requestFullScreen is deprecated. Please call Module.requestFullscreen instead.");d.requestFullScreen=d.requestFullscreen;l.requestFullScreen(a,b,c)};d.requestFullscreen=function(a,b,c){l.requestFullscreen(a,b,c)};d.requestAnimationFrame=function(a){l.requestAnimationFrame(a)};d.setCanvasSize=function(a,b,c){l.setCanvasSize(a,b,c)}; -d.pauseMainLoop=function(){l.mainLoop.pause()};d.resumeMainLoop=function(){l.mainLoop.resume()};d.getUserMedia=function(){l.getUserMedia()};d.createContext=function(a,b,c,d){return l.createContext(a,b,c,d)};var k;h.init();Gb(ha);oa=I(4);Ob=ob=E(W);Pb=Ob+Sb;Qb=E(Pb);p[oa>>2]=Qb;Tb=!0;d.wasmTableSize=7616;d.wasmMaxTableSize=7616;d.asmGlobalArg={};d.asmLibraryArg={abort:G,enlargeMemory:Dc,getTotalMemory:Ec,abortOnCannotGrowMemory:pb,jsCall_di:Zh,jsCall_dii:$h,jsCall_ff:ai,jsCall_fff:bi,jsCall_fi:ci, -jsCall_fif:di,jsCall_fii:ei,jsCall_fiiif:fi,jsCall_i:gi,invoke_ii:hi,jsCall_ii:ii,jsCall_iii:ji,invoke_iiii:ki,jsCall_iiii:li,jsCall_iiiid:mi,jsCall_iiiii:ni,jsCall_iiiiid:oi,jsCall_iiiiii:pi,jsCall_iiiiiid:qi,jsCall_iiiiiii:ri,jsCall_iiiiiiii:si,jsCall_iiiiiiiii:ti,jsCall_iiiiij:ui,jsCall_iijj:vi,jsCall_ji:wi,jsCall_v:xi,jsCall_vd:yi,jsCall_vdd:zi,jsCall_vdddddd:Ai,jsCall_vf:Bi,jsCall_vff:Ci,jsCall_vffff:Di,jsCall_vfi:Ei,invoke_vi:Fi,jsCall_vi:Gi,jsCall_vid:Hi,jsCall_vif:Ii,jsCall_viff:Ji,jsCall_vifff:Ki, -jsCall_viffff:Li,jsCall_vifi:Mi,invoke_vii:Ni,jsCall_vii:Oi,jsCall_viid:Pi,jsCall_viif:Qi,jsCall_viifiii:Ri,jsCall_viii:Si,jsCall_viiid:Ti,jsCall_viiifif:Ui,jsCall_viiifii:Vi,jsCall_viiifiii:Wi,jsCall_viiii:Xi,jsCall_viiiidff:Yi,jsCall_viiiidffffff:Zi,jsCall_viiiif:$i,jsCall_viiiii:aj,jsCall_viiiiidff:bj,jsCall_viiiiidffffff:cj,jsCall_viiiiii:dj,jsCall_viiiiiii:ej,jsCall_viiiiiiii:fj,jsCall_viiiiiiiii:gj,jsCall_viiiiiiiiii:hj,jsCall_viiiij:ij,jsCall_viijii:jj,jsCall_vij:kj,jsCall_viji:lj,__ZSt18uncaught_exceptionv:Ka, -___assert_fail:Jc,___cxa_allocate_exception:Kc,___cxa_pure_virtual:Lc,___cxa_throw:Mc,___lock:Nc,___map_file:Oc,___setErrNo:Ba,___syscall140:Pc,___syscall145:Qc,___syscall146:Rc,___syscall54:Sc,___syscall6:Tc,___syscall91:Uc,___unlock:Vc,__embind_create_inheriting_constructor:cd,__embind_finalize_value_array:dd,__embind_register_bool:ed,__embind_register_class:td,__embind_register_class_class_function:ud,__embind_register_class_constructor:vd,__embind_register_class_function:wd,__embind_register_class_property:xd, -__embind_register_emval:yd,__embind_register_enum:Ad,__embind_register_enum_value:Bd,__embind_register_float:Dd,__embind_register_function:Ed,__embind_register_integer:Gd,__embind_register_memory_view:Hd,__embind_register_std_string:Id,__embind_register_std_wstring:Jd,__embind_register_value_array:Kd,__embind_register_value_array_element:Ld,__embind_register_void:Md,__emval_as:Nd,__emval_call_method:Qd,__emval_call_void_method:Rd,__emval_decref:Ab,__emval_get_global:Sd,__emval_get_method_caller:Vd, -__emval_get_property:Wd,__emval_incref:Xd,__emval_new_array:Yd,__emval_new_cstring:Zd,__emval_run_destructors:$d,__emval_set_property:ae,__emval_take_value:be,_abort:ce,_clock_gettime:ee,_eglChooseConfig:ge,_eglCreateContext:je,_eglCreateWindowSurface:ke,_eglDestroyContext:le,_eglDestroySurface:me,_eglGetCurrentContext:ne,_eglGetCurrentDisplay:oe,_eglGetCurrentSurface:pe,_eglGetDisplay:qe,_eglGetProcAddress:re,_eglInitialize:te,_eglMakeCurrent:ue,_eglReleaseThread:ve,_eglSwapBuffers:we,_emscripten_asm_const_i:Hc, -_emscripten_async_call:xe,_emscripten_glActiveTexture:ye,_emscripten_glAttachShader:ze,_emscripten_glBindAttribLocation:Ae,_emscripten_glBindBuffer:Be,_emscripten_glBindFramebuffer:Ce,_emscripten_glBindProgramARB:De,_emscripten_glBindRenderbuffer:Ee,_emscripten_glBindTexture:Fe,_emscripten_glBindVertexArray:Ge,_emscripten_glBlendColor:He,_emscripten_glBlendEquation:Ie,_emscripten_glBlendEquationSeparate:Je,_emscripten_glBlendFunc:Ke,_emscripten_glBlendFuncSeparate:Le,_emscripten_glBlitFramebuffer:Me, -_emscripten_glBufferData:Ne,_emscripten_glBufferSubData:Oe,_emscripten_glCheckFramebufferStatus:Pe,_emscripten_glClear:Qe,_emscripten_glClearColor:Re,_emscripten_glClearDepth:Se,_emscripten_glClearDepthf:Te,_emscripten_glClearStencil:Ue,_emscripten_glClientActiveTexture:Ve,_emscripten_glColorMask:We,_emscripten_glColorPointer:Xe,_emscripten_glCompileShader:Ye,_emscripten_glCompressedTexImage2D:Ze,_emscripten_glCompressedTexSubImage2D:$e,_emscripten_glCopyTexImage2D:af,_emscripten_glCopyTexSubImage2D:bf, -_emscripten_glCreateProgram:cf,_emscripten_glCreateShader:df,_emscripten_glCullFace:ef,_emscripten_glDeleteBuffers:ff,_emscripten_glDeleteFramebuffers:gf,_emscripten_glDeleteObjectARB:hf,_emscripten_glDeleteProgram:jf,_emscripten_glDeleteRenderbuffers:kf,_emscripten_glDeleteShader:lf,_emscripten_glDeleteTextures:mf,_emscripten_glDeleteVertexArrays:nf,_emscripten_glDepthFunc:of,_emscripten_glDepthMask:pf,_emscripten_glDepthRange:qf,_emscripten_glDepthRangef:rf,_emscripten_glDetachShader:sf,_emscripten_glDisable:tf, -_emscripten_glDisableVertexAttribArray:uf,_emscripten_glDrawArrays:vf,_emscripten_glDrawArraysInstanced:wf,_emscripten_glDrawBuffers:xf,_emscripten_glDrawElements:lc,_emscripten_glDrawElementsInstanced:yf,_emscripten_glDrawRangeElements:zf,_emscripten_glEnable:Af,_emscripten_glEnableClientState:Bf,_emscripten_glEnableVertexAttribArray:Cf,_emscripten_glFinish:Df,_emscripten_glFlush:Ef,_emscripten_glFramebufferRenderbuffer:Ff,_emscripten_glFramebufferTexture2D:Gf,_emscripten_glFrontFace:Hf,_emscripten_glFrustum:If, -_emscripten_glGenBuffers:Jf,_emscripten_glGenFramebuffers:Kf,_emscripten_glGenRenderbuffers:Lf,_emscripten_glGenTextures:Mf,_emscripten_glGenVertexArrays:Nf,_emscripten_glGenerateMipmap:Of,_emscripten_glGetActiveAttrib:Pf,_emscripten_glGetActiveUniform:Qf,_emscripten_glGetAttachedShaders:Rf,_emscripten_glGetAttribLocation:Sf,_emscripten_glGetBooleanv:Tf,_emscripten_glGetBufferParameteriv:Uf,_emscripten_glGetError:Vf,_emscripten_glGetFloatv:Wf,_emscripten_glGetFramebufferAttachmentParameteriv:Xf,_emscripten_glGetInfoLogARB:Yf, -_emscripten_glGetIntegerv:Zf,_emscripten_glGetObjectParameterivARB:$f,_emscripten_glGetPointerv:ag,_emscripten_glGetProgramInfoLog:bg,_emscripten_glGetProgramiv:cg,_emscripten_glGetRenderbufferParameteriv:dg,_emscripten_glGetShaderInfoLog:eg,_emscripten_glGetShaderPrecisionFormat:fg,_emscripten_glGetShaderSource:gg,_emscripten_glGetShaderiv:hg,_emscripten_glGetString:ig,_emscripten_glGetTexParameterfv:jg,_emscripten_glGetTexParameteriv:kg,_emscripten_glGetUniformLocation:lg,_emscripten_glGetUniformfv:mg, -_emscripten_glGetUniformiv:ng,_emscripten_glGetVertexAttribPointerv:og,_emscripten_glGetVertexAttribfv:pg,_emscripten_glGetVertexAttribiv:qg,_emscripten_glHint:rg,_emscripten_glIsBuffer:sg,_emscripten_glIsEnabled:tg,_emscripten_glIsFramebuffer:ug,_emscripten_glIsProgram:vg,_emscripten_glIsRenderbuffer:wg,_emscripten_glIsShader:xg,_emscripten_glIsTexture:yg,_emscripten_glIsVertexArray:zg,_emscripten_glLineWidth:Ag,_emscripten_glLinkProgram:Bg,_emscripten_glLoadIdentity:Cg,_emscripten_glLoadMatrixf:Dg, -_emscripten_glMatrixMode:Eg,_emscripten_glNormalPointer:Fg,_emscripten_glPixelStorei:Gg,_emscripten_glPolygonOffset:Hg,_emscripten_glReadPixels:Ig,_emscripten_glReleaseShaderCompiler:Jg,_emscripten_glRenderbufferStorage:Kg,_emscripten_glRenderbufferStorageMultisample:Lg,_emscripten_glRotatef:Mg,_emscripten_glSampleCoverage:Ng,_emscripten_glScissor:Og,_emscripten_glShaderBinary:Pg,_emscripten_glShaderSource:Qg,_emscripten_glStencilFunc:Rg,_emscripten_glStencilFuncSeparate:Sg,_emscripten_glStencilMask:Tg, -_emscripten_glStencilMaskSeparate:Ug,_emscripten_glStencilOp:Vg,_emscripten_glStencilOpSeparate:Wg,_emscripten_glTexCoordPointer:Xg,_emscripten_glTexImage2D:Yg,_emscripten_glTexParameterf:Zg,_emscripten_glTexParameterfv:$g,_emscripten_glTexParameteri:ah,_emscripten_glTexParameteriv:bh,_emscripten_glTexSubImage2D:ch,_emscripten_glUniform1f:dh,_emscripten_glUniform1fv:eh,_emscripten_glUniform1i:fh,_emscripten_glUniform1iv:gh,_emscripten_glUniform2f:hh,_emscripten_glUniform2fv:ih,_emscripten_glUniform2i:jh, -_emscripten_glUniform2iv:kh,_emscripten_glUniform3f:lh,_emscripten_glUniform3fv:mh,_emscripten_glUniform3i:nh,_emscripten_glUniform3iv:oh,_emscripten_glUniform4f:ph,_emscripten_glUniform4fv:qh,_emscripten_glUniform4i:rh,_emscripten_glUniform4iv:sh,_emscripten_glUniformMatrix2fv:th,_emscripten_glUniformMatrix3fv:uh,_emscripten_glUniformMatrix4fv:vh,_emscripten_glUseProgram:wh,_emscripten_glValidateProgram:xh,_emscripten_glVertexAttrib1f:yh,_emscripten_glVertexAttrib1fv:zh,_emscripten_glVertexAttrib2f:Ah, -_emscripten_glVertexAttrib2fv:Bh,_emscripten_glVertexAttrib3f:Ch,_emscripten_glVertexAttrib3fv:Dh,_emscripten_glVertexAttrib4f:Eh,_emscripten_glVertexAttrib4fv:Fh,_emscripten_glVertexAttribDivisor:Gh,_emscripten_glVertexAttribPointer:Hh,_emscripten_glVertexPointer:Ih,_emscripten_glViewport:Jh,_emscripten_longjmp:Kh,_emscripten_memcpy_big:Oh,_exit:Mh,_getenv:Qa,_gettimeofday:Nh,_longjmp:oc,_pthread_cond_wait:Ph,_pthread_getspecific:Qh,_pthread_key_create:Rh,_pthread_key_delete:Sh,_pthread_mutex_destroy:Th, -_pthread_mutex_init:Uh,_pthread_setspecific:Vh,_sched_yield:Wh,_strftime_l:Yh,DYNAMICTOP_PTR:oa,STACKTOP:ob};var wc=d.asm(d.asmGlobalArg,d.asmLibraryArg,V);d.asm=wc;var oj=d.__GLOBAL__I_000101=function(){return d.asm.__GLOBAL__I_000101.apply(null,arguments)},dk=d.__GLOBAL__sub_I_animation_controller_cc=function(){return d.asm.__GLOBAL__sub_I_animation_controller_cc.apply(null,arguments)},Nj=d.__GLOBAL__sub_I_background_renderer_cc=function(){return d.asm.__GLOBAL__sub_I_background_renderer_cc.apply(null, -arguments)},ik=d.__GLOBAL__sub_I_background_state_cc=function(){return d.asm.__GLOBAL__sub_I_background_state_cc.apply(null,arguments)},Xk=d.__GLOBAL__sub_I_ballpoint_cc=function(){return d.asm.__GLOBAL__sub_I_ballpoint_cc.apply(null,arguments)},Mk=d.__GLOBAL__sub_I_bezier_path_converter_cc=function(){return d.asm.__GLOBAL__sub_I_bezier_path_converter_cc.apply(null,arguments)},Tj=d.__GLOBAL__sub_I_bind_cpp=function(){return d.asm.__GLOBAL__sub_I_bind_cpp.apply(null,arguments)},Tk=d.__GLOBAL__sub_I_builddata_globals_cc= -function(){return d.asm.__GLOBAL__sub_I_builddata_globals_cc.apply(null,arguments)},Nk=d.__GLOBAL__sub_I_bundle_proto_converter_cc=function(){return d.asm.__GLOBAL__sub_I_bundle_proto_converter_cc.apply(null,arguments)},al=d.__GLOBAL__sub_I_camera_controller_cc=function(){return d.asm.__GLOBAL__sub_I_camera_controller_cc.apply(null,arguments)},bl=d.__GLOBAL__sub_I_camera_movement_constraint_cc=function(){return d.asm.__GLOBAL__sub_I_camera_movement_constraint_cc.apply(null,arguments)},jl=d.__GLOBAL__sub_I_crop_controller_cc= -function(){return d.asm.__GLOBAL__sub_I_crop_controller_cc.apply(null,arguments)},tk=d.__GLOBAL__sub_I_crop_mode_cc=function(){return d.asm.__GLOBAL__sub_I_crop_mode_cc.apply(null,arguments)},kl=d.__GLOBAL__sub_I_crop_tool_cc=function(){return d.asm.__GLOBAL__sub_I_crop_tool_cc.apply(null,arguments)},rk=d.__GLOBAL__sub_I_dbg_helper_cc=function(){return d.asm.__GLOBAL__sub_I_dbg_helper_cc.apply(null,arguments)},Oj=d.__GLOBAL__sub_I_dbrender_target_cc=function(){return d.asm.__GLOBAL__sub_I_dbrender_target_cc.apply(null, -arguments)},vk=d.__GLOBAL__sub_I_default_services_cc=function(){return d.asm.__GLOBAL__sub_I_default_services_cc.apply(null,arguments)},fk=d.__GLOBAL__sub_I_direct_renderer_cc=function(){return d.asm.__GLOBAL__sub_I_direct_renderer_cc.apply(null,arguments)},Yj=d.__GLOBAL__sub_I_document_cc=function(){return d.asm.__GLOBAL__sub_I_document_cc.apply(null,arguments)},wk=d.__GLOBAL__sub_I_document_storage_cc=function(){return d.asm.__GLOBAL__sub_I_document_storage_cc.apply(null,arguments)},$k=d.__GLOBAL__sub_I_drag_reco_cc= -function(){return d.asm.__GLOBAL__sub_I_drag_reco_cc.apply(null,arguments)},il=d.__GLOBAL__sub_I_edit_tool_cc=function(){return d.asm.__GLOBAL__sub_I_edit_tool_cc.apply(null,arguments)},Hj=d.__GLOBAL__sub_I_element_animation_cc=function(){return d.asm.__GLOBAL__sub_I_element_animation_cc.apply(null,arguments)},Ej=d.__GLOBAL__sub_I_element_bundle_cc=function(){return d.asm.__GLOBAL__sub_I_element_bundle_cc.apply(null,arguments)},gl=d.__GLOBAL__sub_I_element_manipulation_tool_cc=function(){return d.asm.__GLOBAL__sub_I_element_manipulation_tool_cc.apply(null, -arguments)},fl=d.__GLOBAL__sub_I_element_manipulation_tool_renderer_cc=function(){return d.asm.__GLOBAL__sub_I_element_manipulation_tool_renderer_cc.apply(null,arguments)},wj=d.__GLOBAL__sub_I_element_notifier_cc=function(){return d.asm.__GLOBAL__sub_I_element_notifier_cc.apply(null,arguments)},Mj=d.__GLOBAL__sub_I_element_renderer_cc=function(){return d.asm.__GLOBAL__sub_I_element_renderer_cc.apply(null,arguments)},hl=d.__GLOBAL__sub_I_embind_cc=function(){return d.asm.__GLOBAL__sub_I_embind_cc.apply(null, -arguments)},Rk=d.__GLOBAL__sub_I_extension_defaults_cc=function(){return d.asm.__GLOBAL__sub_I_extension_defaults_cc.apply(null,arguments)},Ik=d.__GLOBAL__sub_I_filter_chooser_tool_cc=function(){return d.asm.__GLOBAL__sub_I_filter_chooser_tool_cc.apply(null,arguments)},Zj=d.__GLOBAL__sub_I_flags_cc=function(){return d.asm.__GLOBAL__sub_I_flags_cc.apply(null,arguments)},ck=d.__GLOBAL__sub_I_frame_state_cc=function(){return d.asm.__GLOBAL__sub_I_frame_state_cc.apply(null,arguments)},jk=d.__GLOBAL__sub_I_gl_resource_manager_cc= -function(){return d.asm.__GLOBAL__sub_I_gl_resource_manager_cc.apply(null,arguments)},tl=d.__GLOBAL__sub_I_grid_manager_cc=function(){return d.asm.__GLOBAL__sub_I_grid_manager_cc.apply(null,arguments)},Wk=d.__GLOBAL__sub_I_highlighter_cc=function(){return d.asm.__GLOBAL__sub_I_highlighter_cc.apply(null,arguments)},pk=d.__GLOBAL__sub_I_id_map_cc=function(){return d.asm.__GLOBAL__sub_I_id_map_cc.apply(null,arguments)},Bk=d.__GLOBAL__sub_I_image_exporter_cc=function(){return d.asm.__GLOBAL__sub_I_image_exporter_cc.apply(null, -arguments)},xk=d.__GLOBAL__sub_I_in_memory_storage_cc=function(){return d.asm.__GLOBAL__sub_I_in_memory_storage_cc.apply(null,arguments)},bk=d.__GLOBAL__sub_I_input_dispatch_cc=function(){return d.asm.__GLOBAL__sub_I_input_dispatch_cc.apply(null,arguments)},ak=d.__GLOBAL__sub_I_input_handler_cc=function(){return d.asm.__GLOBAL__sub_I_input_handler_cc.apply(null,arguments)},kk=d.__GLOBAL__sub_I_interleaved_attribute_set_cc=function(){return d.asm.__GLOBAL__sub_I_interleaved_attribute_set_cc.apply(null, -arguments)},Sj=d.__GLOBAL__sub_I_iostream_cpp=function(){return d.asm.__GLOBAL__sub_I_iostream_cpp.apply(null,arguments)},Vk=d.__GLOBAL__sub_I_line_animation_cc=function(){return d.asm.__GLOBAL__sub_I_line_animation_cc.apply(null,arguments)},sk=d.__GLOBAL__sub_I_line_builder_cc=function(){return d.asm.__GLOBAL__sub_I_line_builder_cc.apply(null,arguments)},ql=d.__GLOBAL__sub_I_line_converter_cc=function(){return d.asm.__GLOBAL__sub_I_line_converter_cc.apply(null,arguments)},Zk=d.__GLOBAL__sub_I_line_modifier_cc= -function(){return d.asm.__GLOBAL__sub_I_line_modifier_cc.apply(null,arguments)},Yk=d.__GLOBAL__sub_I_line_modifier_factory_cc=function(){return d.asm.__GLOBAL__sub_I_line_modifier_factory_cc.apply(null,arguments)},Hk=d.__GLOBAL__sub_I_line_tool_cc=function(){return d.asm.__GLOBAL__sub_I_line_tool_cc.apply(null,arguments)},rl=d.__GLOBAL__sub_I_line_tool_data_sink_cc=function(){return d.asm.__GLOBAL__sub_I_line_tool_data_sink_cc.apply(null,arguments)},Uj=d.__GLOBAL__sub_I_logging_cc=function(){return d.asm.__GLOBAL__sub_I_logging_cc.apply(null, -arguments)},ml=d.__GLOBAL__sub_I_magic_eraser_cc=function(){return d.asm.__GLOBAL__sub_I_magic_eraser_cc.apply(null,arguments)},nl=d.__GLOBAL__sub_I_magic_eraser_stylus_handler_cc=function(){return d.asm.__GLOBAL__sub_I_magic_eraser_stylus_handler_cc.apply(null,arguments)},Kk=d.__GLOBAL__sub_I_mesh_converter_cc=function(){return d.asm.__GLOBAL__sub_I_mesh_converter_cc.apply(null,arguments)},qk=d.__GLOBAL__sub_I_mesh_renderer_cc=function(){return d.asm.__GLOBAL__sub_I_mesh_renderer_cc.apply(null,arguments)}, -rj=d.__GLOBAL__sub_I_mesh_serializer_provider_cc=function(){return d.asm.__GLOBAL__sub_I_mesh_serializer_provider_cc.apply(null,arguments)},ok=d.__GLOBAL__sub_I_mesh_shader_cc=function(){return d.asm.__GLOBAL__sub_I_mesh_shader_cc.apply(null,arguments)},Cj=d.__GLOBAL__sub_I_msaa_cc=function(){return d.asm.__GLOBAL__sub_I_msaa_cc.apply(null,arguments)},zj=d.__GLOBAL__sub_I_msaa_shim_cc=function(){return d.asm.__GLOBAL__sub_I_msaa_shim_cc.apply(null,arguments)},Sk=d.__GLOBAL__sub_I_mutations_cc=function(){return d.asm.__GLOBAL__sub_I_mutations_cc.apply(null, -arguments)},nk=d.__GLOBAL__sub_I_packed_mesh_shaders_cc=function(){return d.asm.__GLOBAL__sub_I_packed_mesh_shaders_cc.apply(null,arguments)},Gj=d.__GLOBAL__sub_I_page_border_cc=function(){return d.asm.__GLOBAL__sub_I_page_border_cc.apply(null,arguments)},Fj=d.__GLOBAL__sub_I_page_manager_cc=function(){return d.asm.__GLOBAL__sub_I_page_manager_cc.apply(null,arguments)},cl=d.__GLOBAL__sub_I_pan_handler_cc=function(){return d.asm.__GLOBAL__sub_I_pan_handler_cc.apply(null,arguments)},Fk=d.__GLOBAL__sub_I_particle_builder_cc= -function(){return d.asm.__GLOBAL__sub_I_particle_builder_cc.apply(null,arguments)},sl=d.__GLOBAL__sub_I_particle_manager_cc=function(){return d.asm.__GLOBAL__sub_I_particle_manager_cc.apply(null,arguments)},uj=d.__GLOBAL__sub_I_poly_store_cc=function(){return d.asm.__GLOBAL__sub_I_poly_store_cc.apply(null,arguments)},sj=d.__GLOBAL__sub_I_processed_element_cc=function(){return d.asm.__GLOBAL__sub_I_processed_element_cc.apply(null,arguments)},Xj=d.__GLOBAL__sub_I_proto_validators_cc=function(){return d.asm.__GLOBAL__sub_I_proto_validators_cc.apply(null, -arguments)},vj=d.__GLOBAL__sub_I_public_events_cc=function(){return d.asm.__GLOBAL__sub_I_public_events_cc.apply(null,arguments)},el=d.__GLOBAL__sub_I_pusher_selector_cc=function(){return d.asm.__GLOBAL__sub_I_pusher_selector_cc.apply(null,arguments)},Dk=d.__GLOBAL__sub_I_pusher_tool_cc=function(){return d.asm.__GLOBAL__sub_I_pusher_tool_cc.apply(null,arguments)},Ck=d.__GLOBAL__sub_I_query_tool_cc=function(){return d.asm.__GLOBAL__sub_I_query_tool_cc.apply(null,arguments)},Rj=d.__GLOBAL__sub_I_rand_funcs_cc= -function(){return d.asm.__GLOBAL__sub_I_rand_funcs_cc.apply(null,arguments)},Uk=d.__GLOBAL__sub_I_rect_selection_tool_cc=function(){return d.asm.__GLOBAL__sub_I_rect_selection_tool_cc.apply(null,arguments)},dl=d.__GLOBAL__sub_I_rect_selector_cc=function(){return d.asm.__GLOBAL__sub_I_rect_selector_cc.apply(null,arguments)},yj=d.__GLOBAL__sub_I_region_query_cc=function(){return d.asm.__GLOBAL__sub_I_region_query_cc.apply(null,arguments)},Bj=d.__GLOBAL__sub_I_render_target_cc=function(){return d.asm.__GLOBAL__sub_I_render_target_cc.apply(null, -arguments)},Pk=d.__GLOBAL__sub_I_root_controller_cc=function(){return d.asm.__GLOBAL__sub_I_root_controller_cc.apply(null,arguments)},Gk=d.__GLOBAL__sub_I_root_renderer_cc=function(){return d.asm.__GLOBAL__sub_I_root_renderer_cc.apply(null,arguments)},ol=d.__GLOBAL__sub_I_scene_drawable_cc=function(){return d.asm.__GLOBAL__sub_I_scene_drawable_cc.apply(null,arguments)},pl=d.__GLOBAL__sub_I_scene_element_adder_cc=function(){return d.asm.__GLOBAL__sub_I_scene_element_adder_cc.apply(null,arguments)}, -xj=d.__GLOBAL__sub_I_scene_graph_cc=function(){return d.asm.__GLOBAL__sub_I_scene_graph_cc.apply(null,arguments)},Qk=d.__GLOBAL__sub_I_sengine_cc=function(){return d.asm.__GLOBAL__sub_I_sengine_cc.apply(null,arguments)},Jk=d.__GLOBAL__sub_I_sequence_point_task_cc=function(){return d.asm.__GLOBAL__sub_I_sequence_point_task_cc.apply(null,arguments)},tj=d.__GLOBAL__sub_I_serialized_element_cc=function(){return d.asm.__GLOBAL__sub_I_serialized_element_cc.apply(null,arguments)},mk=d.__GLOBAL__sub_I_shader_cc= -function(){return d.asm.__GLOBAL__sub_I_shader_cc.apply(null,arguments)},Kj=d.__GLOBAL__sub_I_shape_cc=function(){return d.asm.__GLOBAL__sub_I_shape_cc.apply(null,arguments)},Lj=d.__GLOBAL__sub_I_shape_renderer_cc=function(){return d.asm.__GLOBAL__sub_I_shape_renderer_cc.apply(null,arguments)},Qj=d.__GLOBAL__sub_I_single_partition_renderer_cc=function(){return d.asm.__GLOBAL__sub_I_single_partition_renderer_cc.apply(null,arguments)},Ak=d.__GLOBAL__sub_I_single_user_document_cc=function(){return d.asm.__GLOBAL__sub_I_single_user_document_cc.apply(null, -arguments)},pj=d.__GLOBAL__sub_I_spatial_index_factory_cc=function(){return d.asm.__GLOBAL__sub_I_spatial_index_factory_cc.apply(null,arguments)},Vj=d.__GLOBAL__sub_I_status_cc=function(){return d.asm.__GLOBAL__sub_I_status_cc.apply(null,arguments)},zk=d.__GLOBAL__sub_I_storage_action_cc=function(){return d.asm.__GLOBAL__sub_I_storage_action_cc.apply(null,arguments)},qj=d.__GLOBAL__sub_I_stroke_cc=function(){return d.asm.__GLOBAL__sub_I_stroke_cc.apply(null,arguments)},Lk=d.__GLOBAL__sub_I_stroke_outline_converter_cc= -function(){return d.asm.__GLOBAL__sub_I_stroke_outline_converter_cc.apply(null,arguments)},Ek=d.__GLOBAL__sub_I_tessellated_line_cc=function(){return d.asm.__GLOBAL__sub_I_tessellated_line_cc.apply(null,arguments)},Ij=d.__GLOBAL__sub_I_text_cc=function(){return d.asm.__GLOBAL__sub_I_text_cc.apply(null,arguments)},Jj=d.__GLOBAL__sub_I_text_texture_provider_cc=function(){return d.asm.__GLOBAL__sub_I_text_texture_provider_cc.apply(null,arguments)},hk=d.__GLOBAL__sub_I_texture_manager_cc=function(){return d.asm.__GLOBAL__sub_I_texture_manager_cc.apply(null, -arguments)},Dj=d.__GLOBAL__sub_I_texture_rtree_creator_cc=function(){return d.asm.__GLOBAL__sub_I_texture_rtree_creator_cc.apply(null,arguments)},Aj=d.__GLOBAL__sub_I_textured_quad_renderer_cc=function(){return d.asm.__GLOBAL__sub_I_textured_quad_renderer_cc.apply(null,arguments)},lk=d.__GLOBAL__sub_I_textured_shader_cc=function(){return d.asm.__GLOBAL__sub_I_textured_shader_cc.apply(null,arguments)},ll=d.__GLOBAL__sub_I_tool_controller_cc=function(){return d.asm.__GLOBAL__sub_I_tool_controller_cc.apply(null, -arguments)},Pj=d.__GLOBAL__sub_I_triple_buffered_renderer_cc=function(){return d.asm.__GLOBAL__sub_I_triple_buffered_renderer_cc.apply(null,arguments)},yk=d.__GLOBAL__sub_I_undo_manager_cc=function(){return d.asm.__GLOBAL__sub_I_undo_manager_cc.apply(null,arguments)},Ok=d.__GLOBAL__sub_I_unsafe_scene_helper_cc=function(){return d.asm.__GLOBAL__sub_I_unsafe_scene_helper_cc.apply(null,arguments)},uk=d.__GLOBAL__sub_I_update_loop_cc=function(){return d.asm.__GLOBAL__sub_I_update_loop_cc.apply(null,arguments)}, -Wj=d.__GLOBAL__sub_I_uuid_cc=function(){return d.asm.__GLOBAL__sub_I_uuid_cc.apply(null,arguments)},ek=d.__GLOBAL__sub_I_uuid_generator_cc=function(){return d.asm.__GLOBAL__sub_I_uuid_generator_cc.apply(null,arguments)},gk=d.__GLOBAL__sub_I_web_task_runner_cc=function(){return d.asm.__GLOBAL__sub_I_web_task_runner_cc.apply(null,arguments)};d.___errno_location=function(){return d.asm.___errno_location.apply(null,arguments)};var bd=d.___getTypeName=function(){return d.asm.___getTypeName.apply(null, -arguments)},se=d._emscripten_GetProcAddress=function(){return d.asm._emscripten_GetProcAddress.apply(null,arguments)},ea=d._free=function(){return d.asm._free.apply(null,arguments)},ua=d._malloc=function(){return d.asm._malloc.apply(null,arguments)};d.setThrew=function(){return d.asm.setThrew.apply(null,arguments)};var zc=d.stackAlloc=function(){return d.asm.stackAlloc.apply(null,arguments)};d.dynCall_di=function(){return d.asm.dynCall_di.apply(null,arguments)};d.dynCall_dii=function(){return d.asm.dynCall_dii.apply(null, -arguments)};d.dynCall_ff=function(){return d.asm.dynCall_ff.apply(null,arguments)};d.dynCall_fff=function(){return d.asm.dynCall_fff.apply(null,arguments)};d.dynCall_fi=function(){return d.asm.dynCall_fi.apply(null,arguments)};d.dynCall_fif=function(){return d.asm.dynCall_fif.apply(null,arguments)};d.dynCall_fii=function(){return d.asm.dynCall_fii.apply(null,arguments)};d.dynCall_fiiif=function(){return d.asm.dynCall_fiiif.apply(null,arguments)};d.dynCall_i=function(){return d.asm.dynCall_i.apply(null, -arguments)};d.dynCall_ii=function(){return d.asm.dynCall_ii.apply(null,arguments)};d.dynCall_iii=function(){return d.asm.dynCall_iii.apply(null,arguments)};d.dynCall_iiii=function(){return d.asm.dynCall_iiii.apply(null,arguments)};d.dynCall_iiiid=function(){return d.asm.dynCall_iiiid.apply(null,arguments)};d.dynCall_iiiii=function(){return d.asm.dynCall_iiiii.apply(null,arguments)};d.dynCall_iiiiid=function(){return d.asm.dynCall_iiiiid.apply(null,arguments)};d.dynCall_iiiiii=function(){return d.asm.dynCall_iiiiii.apply(null, -arguments)};d.dynCall_iiiiiid=function(){return d.asm.dynCall_iiiiiid.apply(null,arguments)};d.dynCall_iiiiiii=function(){return d.asm.dynCall_iiiiiii.apply(null,arguments)};d.dynCall_iiiiiiii=function(){return d.asm.dynCall_iiiiiiii.apply(null,arguments)};d.dynCall_iiiiiiiii=function(){return d.asm.dynCall_iiiiiiiii.apply(null,arguments)};d.dynCall_iiiiij=function(){return d.asm.dynCall_iiiiij.apply(null,arguments)};d.dynCall_iijj=function(){return d.asm.dynCall_iijj.apply(null,arguments)};d.dynCall_ji= -function(){return d.asm.dynCall_ji.apply(null,arguments)};d.dynCall_v=function(){return d.asm.dynCall_v.apply(null,arguments)};d.dynCall_vd=function(){return d.asm.dynCall_vd.apply(null,arguments)};d.dynCall_vdd=function(){return d.asm.dynCall_vdd.apply(null,arguments)};d.dynCall_vdddddd=function(){return d.asm.dynCall_vdddddd.apply(null,arguments)};d.dynCall_vf=function(){return d.asm.dynCall_vf.apply(null,arguments)};d.dynCall_vff=function(){return d.asm.dynCall_vff.apply(null,arguments)};d.dynCall_vffff= -function(){return d.asm.dynCall_vffff.apply(null,arguments)};d.dynCall_vfi=function(){return d.asm.dynCall_vfi.apply(null,arguments)};d.dynCall_vi=function(){return d.asm.dynCall_vi.apply(null,arguments)};d.dynCall_vid=function(){return d.asm.dynCall_vid.apply(null,arguments)};d.dynCall_vif=function(){return d.asm.dynCall_vif.apply(null,arguments)};d.dynCall_viff=function(){return d.asm.dynCall_viff.apply(null,arguments)};d.dynCall_vifff=function(){return d.asm.dynCall_vifff.apply(null,arguments)}; -d.dynCall_viffff=function(){return d.asm.dynCall_viffff.apply(null,arguments)};d.dynCall_vifi=function(){return d.asm.dynCall_vifi.apply(null,arguments)};d.dynCall_vii=function(){return d.asm.dynCall_vii.apply(null,arguments)};d.dynCall_viid=function(){return d.asm.dynCall_viid.apply(null,arguments)};d.dynCall_viif=function(){return d.asm.dynCall_viif.apply(null,arguments)};d.dynCall_viifiii=function(){return d.asm.dynCall_viifiii.apply(null,arguments)};d.dynCall_viii=function(){return d.asm.dynCall_viii.apply(null, -arguments)};d.dynCall_viiid=function(){return d.asm.dynCall_viiid.apply(null,arguments)};d.dynCall_viiifif=function(){return d.asm.dynCall_viiifif.apply(null,arguments)};d.dynCall_viiifii=function(){return d.asm.dynCall_viiifii.apply(null,arguments)};d.dynCall_viiifiii=function(){return d.asm.dynCall_viiifiii.apply(null,arguments)};d.dynCall_viiii=function(){return d.asm.dynCall_viiii.apply(null,arguments)};d.dynCall_viiiidff=function(){return d.asm.dynCall_viiiidff.apply(null,arguments)};d.dynCall_viiiidffffff= -function(){return d.asm.dynCall_viiiidffffff.apply(null,arguments)};d.dynCall_viiiif=function(){return d.asm.dynCall_viiiif.apply(null,arguments)};d.dynCall_viiiii=function(){return d.asm.dynCall_viiiii.apply(null,arguments)};d.dynCall_viiiiidff=function(){return d.asm.dynCall_viiiiidff.apply(null,arguments)};d.dynCall_viiiiidffffff=function(){return d.asm.dynCall_viiiiidffffff.apply(null,arguments)};d.dynCall_viiiiii=function(){return d.asm.dynCall_viiiiii.apply(null,arguments)};d.dynCall_viiiiiii= -function(){return d.asm.dynCall_viiiiiii.apply(null,arguments)};d.dynCall_viiiiiiii=function(){return d.asm.dynCall_viiiiiiii.apply(null,arguments)};d.dynCall_viiiiiiiii=function(){return d.asm.dynCall_viiiiiiiii.apply(null,arguments)};d.dynCall_viiiiiiiiii=function(){return d.asm.dynCall_viiiiiiiiii.apply(null,arguments)};d.dynCall_viiiij=function(){return d.asm.dynCall_viiiij.apply(null,arguments)};d.dynCall_viijii=function(){return d.asm.dynCall_viijii.apply(null,arguments)};d.dynCall_vij=function(){return d.asm.dynCall_vij.apply(null, -arguments)};d.dynCall_viji=function(){return d.asm.dynCall_viji.apply(null,arguments)};d.asm=wc;d.getValue=yc;d.Pointer_stringify=R;d.addFunction=xc;Ga.prototype=Error();Ga.prototype.constructor=Ga;var nj,tc=null;Ja=function b(){d.calledRun||Jb();d.calledRun||(Ja=b)};d.run=Jb;d.exit=mj;d.abort=G;if(d.preInit)for("function"==typeof d.preInit&&(d.preInit=[d.preInit]);0<d.preInit.length;)d.preInit.pop()();d.noExitRuntime=!0;Jb();g.Module=d;g.Browser=l})})(window); -var h,aa="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)},ba="undefined"!=typeof window&&window===this?this:"undefined"!=typeof global&&null!=global?global:this,ca=function(){ca=function(){};ba.Symbol||(ba.Symbol=da)},da=function(){var a=0;return function(b){return"jscomp_symbol_"+(b||"")+a++}}(),fa=function(){ca();var a=ba.Symbol.iterator;a||(a=ba.Symbol.iterator=ba.Symbol("iterator"));"function"!=typeof Array.prototype[a]&& -aa(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return ea(this)}});fa=function(){}},ea=function(a){var b=0;return ha(function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}})},ha=function(a){fa();a={next:a};a[ba.Symbol.iterator]=function(){return this};return a},ia=function(a){fa();var b=a[Symbol.iterator];return b?b.call(a):ea(a)},ja=function(a,b){if(b){var c=ba;a=a.split(".");for(var d=0;d<a.length-1;d++){var e=a[d];e in c||(c[e]={});c=c[e]}a=a[a.length-1];d=c[a];b=b(d); -b!=d&&null!=b&&aa(c,a,{configurable:!0,writable:!0,value:b})}};ja("Array.prototype.find",function(a){return a?a:function(a,c){a:{var b=this;b instanceof String&&(b=String(b));for(var e=b.length,f=0;f<e;f++){var g=b[f];if(a.call(c,g,f,b)){a=g;break a}}a=void 0}return a}});var k=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};ja("Object.entries",function(a){return a?a:function(a){var b=[],d;for(d in a)k(a,d)&&b.push([d,a[d]]);return b}}); -ja("WeakMap",function(a){function b(a){k(a,d)||aa(a,d,{value:{}})}function c(a){var c=Object[a];c&&(Object[a]=function(a){b(a);return c(a)})}if(function(){if(!a||!Object.seal)return!1;try{var b=Object.seal({}),c=Object.seal({}),d=new a([[b,2],[c,3]]);if(2!=d.get(b)||3!=d.get(c))return!1;d.delete(b);d.set(c,4);return!d.has(b)&&4==d.get(c)}catch(u){return!1}}())return a;var d="$jscomp_hidden_"+Math.random();c("freeze");c("preventExtensions");c("seal");var e=0,f=function(a){this.a=(e+=Math.random()+ -1).toString();if(a){ca();fa();a=ia(a);for(var b;!(b=a.next()).done;)b=b.value,this.set(b[0],b[1])}};f.prototype.set=function(a,c){b(a);if(!k(a,d))throw Error("WeakMap key fail: "+a);a[d][this.a]=c;return this};f.prototype.get=function(a){return k(a,d)?a[d][this.a]:void 0};f.prototype.has=function(a){return k(a,d)&&k(a[d],this.a)};f.prototype.delete=function(a){return k(a,d)&&k(a[d],this.a)?delete a[d][this.a]:!1};return f}); -ja("Map",function(a){if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var b=Object.seal({x:4}),c=new a(ia([[b,"s"]]));if("s"!=c.get(b)||1!=c.size||c.get({x:4})||c.set({x:4},"t")!=c||2!=c.size)return!1;var d=c.entries(),e=d.next();if(e.done||e.value[0]!=b||"s"!=e.value[1])return!1;e=d.next();return e.done||4!=e.value[0].x||"t"!=e.value[1]||!d.next().done?!1:!0}catch(O){return!1}}())return a;ca();fa();var b=new WeakMap,c=function(a){this.a= -{};this.b=f();this.size=0;if(a){a=ia(a);for(var b;!(b=a.next()).done;)b=b.value,this.set(b[0],b[1])}};c.prototype.set=function(a,b){var c=d(this,a);c.list||(c.list=this.a[c.id]=[]);c.u?c.u.value=b:(c.u={next:this.b,G:this.b.G,head:this.b,key:a,value:b},c.list.push(c.u),this.b.G.next=c.u,this.b.G=c.u,this.size++);return this};c.prototype.delete=function(a){a=d(this,a);return a.u&&a.list?(a.list.splice(a.index,1),a.list.length||delete this.a[a.id],a.u.G.next=a.u.next,a.u.next.G=a.u.G,a.u.head=null, -this.size--,!0):!1};c.prototype.clear=function(){this.a={};this.b=this.b.G=f();this.size=0};c.prototype.has=function(a){return!!d(this,a).u};c.prototype.get=function(a){return(a=d(this,a).u)&&a.value};c.prototype.entries=function(){return e(this,function(a){return[a.key,a.value]})};c.prototype.keys=function(){return e(this,function(a){return a.key})};c.prototype.values=function(){return e(this,function(a){return a.value})};c.prototype.forEach=function(a,b){for(var c=this.entries(),d;!(d=c.next()).done;)d= -d.value,a.call(b,d[1],d[0],this)};c.prototype[Symbol.iterator]=c.prototype.entries;var d=function(a,c){var d=c&&typeof c;"object"==d||"function"==d?b.has(c)?d=b.get(c):(d=""+ ++g,b.set(c,d)):d="p_"+c;var e=a.a[d];if(e&&k(a.a,d))for(a=0;a<e.length;a++){var f=e[a];if(c!==c&&f.key!==f.key||c===f.key)return{id:d,list:e,index:a,u:f}}return{id:d,list:e,index:-1,u:void 0}},e=function(a,b){var c=a.b;return ha(function(){if(c){for(;c.head!=a.b;)c=c.G;for(;c.next!=c.head;)return c=c.next,{done:!1,value:b(c)}; -c=null}return{done:!0,value:void 0}})},f=function(){var a={};return a.G=a.next=a.head=a},g=0;return c}); -ja("Set",function(a){if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var b=Object.seal({x:4}),d=new a(ia([b]));if(!d.has(b)||1!=d.size||d.add(b)!=d||1!=d.size||d.add({x:4})!=d||2!=d.size)return!1;var e=d.entries(),f=e.next();if(f.done||f.value[0]!=b||f.value[1]!=b)return!1;f=e.next();return f.done||f.value[0]==b||4!=f.value[0].x||f.value[1]!=f.value[0]?!1:e.next().done}catch(g){return!1}}())return a;ca();fa();var b=function(a){this.a=new Map; -if(a){a=ia(a);for(var b;!(b=a.next()).done;)this.add(b.value)}this.size=this.a.size};b.prototype.add=function(a){this.a.set(a,a);this.size=this.a.size;return this};b.prototype.delete=function(a){a=this.a.delete(a);this.size=this.a.size;return a};b.prototype.clear=function(){this.a.clear();this.size=0};b.prototype.has=function(a){return this.a.has(a)};b.prototype.entries=function(){return this.a.entries()};b.prototype.values=function(){return this.a.values()};b.prototype.keys=b.prototype.values;b.prototype[Symbol.iterator]= -b.prototype.values;b.prototype.forEach=function(a,b){var c=this;this.a.forEach(function(d){return a.call(b,d,d,c)})};return b}); -var l=this,n=function(a){return void 0!==a},q=function(a){return"string"==typeof a},ka=function(){},la=function(a){a.ha=void 0;a.w=function(){return a.ha?a.ha:a.ha=new a}},ma=function(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array"; -if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null";else if("function"==b&&"undefined"==typeof a.call)return"object";return b},na=function(a){return"array"==ma(a)},oa=function(a){var b=typeof a;return"object"==b&&null!=a||"function"==b},pa="closure_uid_"+(1E9*Math.random()>>>0),qa=0,ra=function(a,b,c){return a.call.apply(a.bind,arguments)},sa=function(a,b,c){if(!a)throw Error();if(2<arguments.length){var d= -Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}return function(){return a.apply(b,arguments)}},r=function(a,b,c){Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf("native code")?r=ra:r=sa;return r.apply(null,arguments)},ta=function(a,b){a=a.split(".");var c=l;a[0]in c||"undefined"==typeof c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)!a.length&& -n(b)?c[d]=b:c[d]&&c[d]!==Object.prototype[d]?c=c[d]:c=c[d]={}},t=function(a,b){function c(){}c.prototype=b.prototype;a.S=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.bd=function(a,c,f){for(var d=Array(arguments.length-2),e=2;e<arguments.length;e++)d[e-2]=arguments[e];return b.prototype[c].apply(a,d)}};var ua=function(a){if(Error.captureStackTrace)Error.captureStackTrace(this,ua);else{var b=Error().stack;b&&(this.stack=b)}a&&(this.message=String(a))};t(ua,Error);ua.prototype.name="CustomError";var va;var wa=function(a,b){a=a.split("%s");for(var c="",d=a.length-1,e=0;e<d;e++)c+=a[e]+(e<b.length?b[e]:"%s");ua.call(this,c+a[d])};t(wa,ua);wa.prototype.name="AssertionError"; -var xa=function(a,b,c,d){var e="Assertion failed";if(c){e+=": "+c;var f=d}else a&&(e+=": "+a,f=b);throw new wa(""+e,f||[]);},v=function(a,b,c){a||xa("",null,b,Array.prototype.slice.call(arguments,2));return a},ya=function(a,b){throw new wa("Failure"+(a?": "+a:""),Array.prototype.slice.call(arguments,1));},za=function(a,b,c){"number"==typeof a||xa("Expected number but got %s: %s.",[ma(a),a],b,Array.prototype.slice.call(arguments,2))},Aa=function(a,b,c){q(a)||xa("Expected string but got %s: %s.",[ma(a), -a],b,Array.prototype.slice.call(arguments,2));return a},Ba=function(a,b,c){oa(a)||xa("Expected object but got %s: %s.",[ma(a),a],b,Array.prototype.slice.call(arguments,2))};var Ca=Array.prototype.indexOf?function(a,b){v(null!=a.length);return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if(q(a))return q(b)&&1==b.length?a.indexOf(b,0):-1;for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1},Da=Array.prototype.forEach?function(a,b,c){v(null!=a.length);Array.prototype.forEach.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=q(a)?a.split(""):a,f=0;f<d;f++)f in e&&b.call(c,e[f],f,a)},Ea=Array.prototype.filter?function(a,b){v(null!=a.length);return Array.prototype.filter.call(a, -b,void 0)}:function(a,b){for(var c=a.length,d=[],e=0,f=q(a)?a.split(""):a,g=0;g<c;g++)if(g in f){var m=f[g];b.call(void 0,m,g,a)&&(d[e++]=m)}return d},Fa=Array.prototype.reduce?function(a,b,c){v(null!=a.length);return Array.prototype.reduce.call(a,b,c)}:function(a,b,c){var d=c;Da(a,function(c,f){d=b.call(void 0,d,c,f,a)});return d},Ha=function(a,b){b=Ca(a,b);var c;(c=0<=b)&&Ga(a,b);return c},Ga=function(a,b){v(null!=a.length);Array.prototype.splice.call(a,b,1)},Ia=function(a,b){for(var c=1;c<arguments.length;c++){var d= -arguments[c],e=d,f=ma(e);if("array"==f||"object"==f&&"number"==typeof e.length){e=a.length||0;f=d.length||0;a.length=e+f;for(var g=0;g<f;g++)a[e+g]=d[g]}else a.push(d)}},Ka=function(a,b,c,d){v(null!=a.length);Array.prototype.splice.apply(a,Ja(arguments,1))},Ja=function(a,b,c){v(null!=a.length);return 2>=arguments.length?Array.prototype.slice.call(a,b):Array.prototype.slice.call(a,b,c)},Ma=function(a,b){a.sort(b||La)},La=function(a,b){return a>b?1:a<b?-1:0};var Na=String.prototype.trim?function(a){return a.trim()}:function(a){return/^[\s\xa0]*([\s\S]*?)[\s\xa0]*$/.exec(a)[1]},Va=function(a){if(!Oa.test(a))return a;-1!=a.indexOf("&")&&(a=a.replace(Pa,"&"));-1!=a.indexOf("<")&&(a=a.replace(Qa,"<"));-1!=a.indexOf(">")&&(a=a.replace(Ra,">"));-1!=a.indexOf('"')&&(a=a.replace(Sa,"""));-1!=a.indexOf("'")&&(a=a.replace(Ta,"'"));-1!=a.indexOf("\x00")&&(a=a.replace(Ua,"�"));return a},Pa=/&/g,Qa=/</g,Ra=/>/g,Sa=/"/g,Ta=/'/g,Ua=/\x00/g,Oa= -/[\x00&<>"']/,Xa=function(a,b){var c=0;a=Na(String(a)).split(".");b=Na(String(b)).split(".");for(var d=Math.max(a.length,b.length),e=0;0==c&&e<d;e++){var f=a[e]||"",g=b[e]||"";do{f=/(\d*)(\D*)(.*)/.exec(f)||["","","",""];g=/(\d*)(\D*)(.*)/.exec(g)||["","","",""];if(0==f[0].length&&0==g[0].length)break;c=Wa(0==f[1].length?0:parseInt(f[1],10),0==g[1].length?0:parseInt(g[1],10))||Wa(0==f[2].length,0==g[2].length)||Wa(f[2],g[2]);f=f[3];g=g[3]}while(0==c)}return c},Wa=function(a,b){return a<b?-1:a>b?1: -0};var Ya;a:{var Za=l.navigator;if(Za){var $a=Za.userAgent;if($a){Ya=$a;break a}}Ya=""}var w=function(a){return-1!=Ya.indexOf(a)};var ab=function(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b},bb="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),cb=function(a,b){for(var c,d,e=1;e<arguments.length;e++){d=arguments[e];for(c in d)a[c]=d[c];for(var f=0;f<bb.length;f++)c=bb[f],Object.prototype.hasOwnProperty.call(d,c)&&(a[c]=d[c])}};var db=function(a){db[" "](a);return a};db[" "]=ka;var eb=function(a,b,c){return Object.prototype.hasOwnProperty.call(a,b)?a[b]:a[b]=c(b)};var fb=w("Opera"),gb=w("Trident")||w("MSIE"),hb=w("Edge"),ib=w("Gecko")&&!(-1!=Ya.toLowerCase().indexOf("webkit")&&!w("Edge"))&&!(w("Trident")||w("MSIE"))&&!w("Edge"),jb=-1!=Ya.toLowerCase().indexOf("webkit")&&!w("Edge"),kb=w("Macintosh"),lb=function(){var a=l.document;return a?a.documentMode:void 0},mb; -a:{var nb="",ob=function(){var a=Ya;if(ib)return/rv:([^\);]+)(\)|;)/.exec(a);if(hb)return/Edge\/([\d\.]+)/.exec(a);if(gb)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(jb)return/WebKit\/(\S+)/.exec(a);if(fb)return/(?:Version)[ \/]?(\S+)/.exec(a)}();ob&&(nb=ob?ob[1]:"");if(gb){var pb=lb();if(null!=pb&&pb>parseFloat(nb)){mb=String(pb);break a}}mb=nb}var qb=mb,rb={},sb=function(a){return eb(rb,a,function(){return 0<=Xa(qb,a)})},tb;var ub=l.document; -tb=ub&&gb?lb()||("CSS1Compat"==ub.compatMode?parseInt(qb,10):5):void 0;var vb=Object.freeze||function(a){return a};var wb=function(){};var xb=function(a){if(a.classList)return a.classList;a=a.className;return q(a)&&a.match(/\S+/g)||[]},yb=function(a){a.classList?a=a.classList.contains("fullscreen"):(a=xb(a),a=0<=Ca(a,"fullscreen"));return a},zb=function(a){a.classList?a.classList.remove("fullscreen"):yb(a)&&(a.className=Ea(xb(a),function(a){return"fullscreen"!=a}).join(" "))};var Ab=function(){this.a=""};Ab.prototype.toString=function(){return"SafeUrl{"+this.a+"}"}; -var Bb=/^(?:audio\/(?:3gpp|3gpp2|aac|midi|mp4|mpeg|ogg|x-m4a|x-wav|webm)|image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|text\/csv|video\/(?:mpeg|mp4|ogg|webm|quicktime))$/i,Db=function(a){if(Bb.test(a.type)){var b=n(l.URL)&&n(l.URL.createObjectURL)?l.URL:n(l.webkitURL)&&n(l.webkitURL.createObjectURL)?l.webkitURL:n(l.createObjectURL)?l:null;if(null==b)throw Error("This browser doesn't seem to support blob URLs");a=b.createObjectURL(a)}else a="about:invalid#zClosurez";return Cb(a)},Eb=/^data:([^;,]*);base64,[a-z0-9+\/]+=*$/i, -Fb=function(a){var b=a.match(Eb);b=b&&Bb.test(b[1]);return Cb(b?a:"about:invalid#zClosurez")},Cb=function(a){var b=new Ab;b.a=a;return b};Cb("about:blank");var Gb=function(a){return Fa(arguments,function(a,c){return a+c},0)},Hb=function(a){return Gb.apply(null,arguments)/arguments.length};var Ib=function(a,b){this.x=n(a)?a:0;this.a=n(b)?b:0};h=Ib.prototype;h.clone=function(){return new Ib(this.x,this.a)};h.toString=function(){return"("+this.x+", "+this.a+")"};h.s=function(a){return a instanceof Ib&&(this==a?!0:this&&a?this.x==a.x&&this.a==a.a:!1)};h.ceil=function(){this.x=Math.ceil(this.x);this.a=Math.ceil(this.a);return this};h.floor=function(){this.x=Math.floor(this.x);this.a=Math.floor(this.a);return this};h.round=function(){this.x=Math.round(this.x);this.a=Math.round(this.a);return this};var Jb=function(a,b){this.width=a;this.height=b};h=Jb.prototype;h.clone=function(){return new Jb(this.width,this.height)};h.toString=function(){return"("+this.width+" x "+this.height+")"};h.za=function(){return this.width*this.height};h.aspectRatio=function(){return this.width/this.height};h.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};h.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this}; -h.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};var Mb=function(a){return a?new Kb(Lb(a)):va||(va=new Kb)},Ob=function(a){return q(a)?document.getElementById(a):a},Lb=function(a){v(a,"Node cannot be null or undefined.");return 9==a.nodeType?a:a.ownerDocument||a.document},Qb=function(){var a=window;return n(a.devicePixelRatio)?a.devicePixelRatio:a.matchMedia?Pb(3)||Pb(2)||Pb(1.5)||Pb(1)||.75:1},Pb=function(a){return window.matchMedia("(min-resolution: "+a+"dppx),(min--moz-device-pixel-ratio: "+a+"),(min-resolution: "+96*a+"dpi)").matches?a:0},Kb= -function(a){this.a=a||l.document||document};Kb.prototype.F=function(){return q(void 0)?this.a.getElementById(void 0):void 0};var Rb=!gb||9<=Number(tb),Sb=gb&&!sb("9"),Tb=function(){if(!l.addEventListener||!Object.defineProperty)return!1;var a=!1,b=Object.defineProperty({},"passive",{get:function(){a=!0}});l.addEventListener("test",ka,b);l.removeEventListener("test",ka,b);return a}();var x=function(a,b){this.type=a;this.a=this.target=b;this.b=!1;this.ra=!0};x.prototype.preventDefault=function(){this.b=!0;this.ra=!1};var Ub=function(a,b){x.call(this,a?a.type:"");this.relatedTarget=this.a=this.target=null;this.button=this.screenY=this.screenX=this.clientY=this.clientX=0;this.key="";this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1;this.pointerId=0;this.pointerType="";this.g=null;a&&this.init(a,b)};t(Ub,x);var Vb=vb({2:"touch",3:"pen",4:"mouse"}); -Ub.prototype.init=function(a,b){var c=this.type=a.type,d=a.changedTouches?a.changedTouches[0]:null;this.target=a.target||a.srcElement;this.a=b;if(b=a.relatedTarget){if(ib){a:{try{db(b.nodeName);var e=!0;break a}catch(f){}e=!1}e||(b=null)}}else"mouseover"==c?b=a.fromElement:"mouseout"==c&&(b=a.toElement);this.relatedTarget=b;null===d?(this.clientX=void 0!==a.clientX?a.clientX:a.pageX,this.clientY=void 0!==a.clientY?a.clientY:a.pageY,this.screenX=a.screenX||0,this.screenY=a.screenY||0):(this.clientX= -void 0!==d.clientX?d.clientX:d.pageX,this.clientY=void 0!==d.clientY?d.clientY:d.pageY,this.screenX=d.screenX||0,this.screenY=d.screenY||0);this.button=a.button;this.key=a.key||"";this.ctrlKey=a.ctrlKey;this.altKey=a.altKey;this.shiftKey=a.shiftKey;this.metaKey=a.metaKey;this.pointerId=a.pointerId||0;this.pointerType=q(a.pointerType)?a.pointerType:Vb[a.pointerType]||"";this.g=a;a.defaultPrevented&&this.preventDefault()}; -Ub.prototype.preventDefault=function(){Ub.S.preventDefault.call(this);var a=this.g;if(a.preventDefault)a.preventDefault();else if(a.returnValue=!1,Sb)try{if(a.ctrlKey||112<=a.keyCode&&123>=a.keyCode)a.keyCode=-1}catch(b){}};var Wb="closure_listenable_"+(1E6*Math.random()|0),Xb=0;var Yb=function(a,b,c,d,e){this.listener=a;this.a=null;this.src=b;this.type=c;this.capture=!!d;this.$=e;this.key=++Xb;this.R=this.X=!1},Zb=function(a){a.R=!0;a.listener=null;a.a=null;a.src=null;a.$=null};var $b=function(a){this.src=a;this.a={};this.b=0};$b.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.a[f];a||(a=this.a[f]=[],this.b++);var g=ac(a,b,d,e);-1<g?(b=a[g],c||(b.X=!1)):(b=new Yb(b,this.src,f,!!d,e),b.X=c,a.push(b));return b};var bc=function(a,b){var c=b.type;c in a.a&&Ha(a.a[c],b)&&(Zb(b),0==a.a[c].length&&(delete a.a[c],a.b--))},ac=function(a,b,c,d){for(var e=0;e<a.length;++e){var f=a[e];if(!f.R&&f.listener==b&&f.capture==!!c&&f.$==d)return e}return-1};var cc="closure_lm_"+(1E6*Math.random()|0),dc={},ec=0,gc=function(a,b,c,d,e){if(d&&d.once)return fc(a,b,c,d,e);if(na(b)){for(var f=0;f<b.length;f++)gc(a,b[f],c,d,e);return null}c=hc(c);a&&a[Wb]?(d=oa(d)?!!d.capture:!!d,ic(a),a=a.P.add(String(b),c,!1,d,e)):a=jc(a,b,c,!1,d,e);return a},jc=function(a,b,c,d,e,f){if(!b)throw Error("Invalid event type");var g=oa(e)?!!e.capture:!!e,m=kc(a);m||(a[cc]=m=new $b(a));c=m.add(b,c,d,g,f);if(c.a)return c;d=lc();c.a=d;d.src=a;d.listener=c;if(a.addEventListener)Tb|| -(e=g),void 0===e&&(e=!1),a.addEventListener(b.toString(),d,e);else if(a.attachEvent)a.attachEvent(mc(b.toString()),d);else if(a.addListener&&a.removeListener)v("change"===b,"MediaQueryList only has a change event"),a.addListener(d);else throw Error("addEventListener and attachEvent are unavailable.");ec++;return c},lc=function(){var a=nc,b=Rb?function(c){return a.call(b.src,b.listener,c)}:function(c){c=a.call(b.src,b.listener,c);if(!c)return c};return b},fc=function(a,b,c,d,e){if(na(b)){for(var f= -0;f<b.length;f++)fc(a,b[f],c,d,e);return null}c=hc(c);return a&&a[Wb]?a.P.add(String(b),c,!0,oa(d)?!!d.capture:!!d,e):jc(a,b,c,!0,d,e)},oc=function(a,b,c,d,e){if(na(b))for(var f=0;f<b.length;f++)oc(a,b[f],c,d,e);else(d=oa(d)?!!d.capture:!!d,c=hc(c),a&&a[Wb])?(a=a.P,b=String(b).toString(),b in a.a&&(f=a.a[b],c=ac(f,c,d,e),-1<c&&(Zb(f[c]),Ga(f,c),0==f.length&&(delete a.a[b],a.b--)))):a&&(a=kc(a))&&(b=a.a[b.toString()],a=-1,b&&(a=ac(b,c,d,e)),(c=-1<a?b[a]:null)&&pc(c))},pc=function(a){if("number"!=typeof a&& -a&&!a.R){var b=a.src;if(b&&b[Wb])bc(b.P,a);else{var c=a.type,d=a.a;b.removeEventListener?b.removeEventListener(c,d,a.capture):b.detachEvent?b.detachEvent(mc(c),d):b.addListener&&b.removeListener&&b.removeListener(d);ec--;(c=kc(b))?(bc(c,a),0==c.b&&(c.src=null,b[cc]=null)):Zb(a)}}},mc=function(a){return a in dc?dc[a]:dc[a]="on"+a},rc=function(a,b,c,d){var e=!0;if(a=kc(a))if(b=a.a[b.toString()])for(b=b.concat(),a=0;a<b.length;a++){var f=b[a];f&&f.capture==c&&!f.R&&(f=qc(f,d),e=e&&!1!==f)}return e}, -qc=function(a,b){var c=a.listener,d=a.$||a.src;a.X&&pc(a);return c.call(d,b)},nc=function(a,b){if(a.R)return!0;if(!Rb){if(!b)a:{b=["window","event"];for(var c=l,d=0;d<b.length;d++)if(c=c[b[d]],null==c){b=null;break a}b=c}d=b;b=new Ub(d,this);c=!0;if(!(0>d.keyCode||void 0!=d.returnValue)){a:{var e=!1;if(0==d.keyCode)try{d.keyCode=-1;break a}catch(g){e=!0}if(e||void 0==d.returnValue)d.returnValue=!0}d=[];for(e=b.a;e;e=e.parentNode)d.push(e);a=a.type;for(e=d.length-1;0<=e;e--){b.a=d[e];var f=rc(d[e], -a,!0,b);c=c&&f}for(e=0;e<d.length;e++)b.a=d[e],f=rc(d[e],a,!1,b),c=c&&f}return c}return qc(a,new Ub(b,this))},kc=function(a){a=a[cc];return a instanceof $b?a:null},sc="__closure_events_fn_"+(1E9*Math.random()>>>0),hc=function(a){v(a,"Listener can not be null.");if("function"==ma(a))return a;v(a.handleEvent,"An object listener must have handleEvent method.");a[sc]||(a[sc]=function(b){return a.handleEvent(b)});return a[sc]};var tc=function(a){this.a=a;this.b={}};t(tc,wb);var uc=[],vc=function(a,b,c,d){na(c)||(c&&(uc[0]=c.toString()),c=uc);for(var e=0;e<c.length;e++){var f=gc(b,c[e],d||a.handleEvent,!1,a.a||a);if(!f)break;a.b[f.key]=f}},xc=function(a,b,c){wc(a,b,"p",c,void 0)},wc=function(a,b,c,d,e,f){if(na(c))for(var g=0;g<c.length;g++)wc(a,b,c[g],d,e,f);else(b=fc(b,c,d||a.handleEvent,e,f||a.a||a))&&(a.b[b.key]=b)};tc.prototype.handleEvent=function(){throw Error("EventHandler.handleEvent not implemented");};var y=function(){this.P=new $b(this);this.sa=this;this.T=null};t(y,wb);y.prototype[Wb]=!0;y.prototype.W=function(a){this.T=a};y.prototype.removeEventListener=function(a,b,c,d){oc(this,a,b,c,d)}; -var A=function(a,b){ic(a);var c=a.T;if(c){var d=[];for(var e=1;c;c=c.T)d.push(c),v(1E3>++e,"infinite loop")}a=a.sa;c=b.type||b;q(b)?b=new x(b,a):b instanceof x?b.target=b.target||a:(e=b,b=new x(c,a),cb(b,e));e=!0;if(d)for(var f=d.length-1;0<=f;f--){var g=b.a=d[f];e=yc(g,c,!0,b)&&e}g=b.a=a;e=yc(g,c,!0,b)&&e;e=yc(g,c,!1,b)&&e;if(d)for(f=0;f<d.length;f++)g=b.a=d[f],e=yc(g,c,!1,b)&&e;return e},yc=function(a,b,c,d){b=a.P.a[String(b)];if(!b)return!0;b=b.concat();for(var e=!0,f=0;f<b.length;++f){var g=b[f]; -if(g&&!g.R&&g.capture==c){var m=g.listener,p=g.$||g.src;g.X&&bc(a.P,g);e=!1!==m.call(p,d)&&e}}return e&&0!=d.ra},ic=function(a){v(a.P,"Event target is not initialized. Did you call the superclass (goog.events.EventTarget) constructor?")};var B=function(a,b){this.a=a|0;this.b=b|0},zc={},Bc={},C=function(a){return eb(zc,a,function(a){return new B(a,0>a?-1:0)})},Cc=function(a){var b=a|0;v(a===b,"value should be a 32-bit integer");return-128<=b&&128>b?C(b):new B(b,0>b?-1:0)},F=function(a){return isNaN(a)?C(0):a<=-Dc?D():a+1>=Dc?Ec():0>a?E(F(-a)):new B(a%4294967296|0,a/4294967296|0)},G=function(a,b){return new B(a,b)},Fc=function(a,b){if(0==a.length)throw Error("number format error: empty string");b=b||10;if(2>b||36<b)throw Error("radix out of range: "+ -b);if("-"==a.charAt(0))return E(Fc(a.substring(1),b));if(0<=a.indexOf("-"))throw Error('number format error: interior "-" character: '+a);for(var c=F(Math.pow(b,8)),d=C(0),e=0;e<a.length;e+=8){var f=Math.min(8,a.length-e),g=parseInt(a.substring(e,e+f),b);8>f?(f=F(Math.pow(b,f)),d=H(d,f).add(F(g))):(d=H(d,c),d=d.add(F(g)))}return d},Dc=4294967296*4294967296/2,Ec=function(){return eb(Bc,1,function(){return G(-1,2147483647)})},D=function(){return eb(Bc,2,function(){return G(0,-2147483648)})},Gc=function(){return eb(Bc, -6,function(){return Cc(16777216)})};B.prototype.toString=function(a){a=a||10;if(2>a||36<a)throw Error("radix out of range: "+a);if(Hc(this))return"0";if(0>this.b){if(this.s(D())){var b=F(a),c=Ic(this,b);b=Jc(H(c,b),this);return c.toString(a)+b.a.toString(a)}return"-"+E(this).toString(a)}c=F(Math.pow(a,6));b=this;for(var d="";;){var e=Ic(b,c),f=(Jc(b,H(e,c)).a>>>0).toString(a);b=e;if(Hc(b))return f+d;for(;6>f.length;)f="0"+f;d=""+f+d}}; -var Kc=function(a){return 0<=a.a?a.a:4294967296+a.a},Hc=function(a){return 0==a.b&&0==a.a};B.prototype.s=function(a){return this.b==a.b&&this.a==a.a};var Mc=function(a){var b=Gc();return 0>Lc(a,b)},Lc=function(a,b){if(a.s(b))return 0;var c=0>a.b,d=0>b.b;return c&&!d?-1:!c&&d?1:0>Jc(a,b).b?-1:1},E=function(a){return a.s(D())?D():G(~a.a,~a.b).add(C(1))}; -B.prototype.add=function(a){var b=this.b>>>16,c=this.b&65535,d=this.a>>>16,e=a.b>>>16,f=a.b&65535,g=a.a>>>16;a=(this.a&65535)+(a.a&65535);g=(a>>>16)+(d+g);d=g>>>16;d+=c+f;b=(d>>>16)+(b+e)&65535;return G((g&65535)<<16|a&65535,b<<16|d&65535)}; -var Jc=function(a,b){return a.add(E(b))},H=function(a,b){if(Hc(a)||Hc(b))return C(0);if(a.s(D()))return 1==(b.a&1)?D():C(0);if(b.s(D()))return 1==(a.a&1)?D():C(0);if(0>a.b)return 0>b.b?H(E(a),E(b)):E(H(E(a),b));if(0>b.b)return E(H(a,E(b)));if(Mc(a)&&Mc(b))return F((4294967296*a.b+Kc(a))*(4294967296*b.b+Kc(b)));var c=a.b>>>16,d=a.b&65535,e=a.a>>>16;a=a.a&65535;var f=b.b>>>16,g=b.b&65535,m=b.a>>>16;b=b.a&65535;var p=a*b;var u=(p>>>16)+e*b;var z=u>>>16;u=(u&65535)+a*m;z+=u>>>16;z+=d*b;var O=z>>>16;z= -(z&65535)+e*m;O+=z>>>16;z=(z&65535)+a*g;O=O+(z>>>16)+(c*b+d*m+e*g+a*f)&65535;return G((u&65535)<<16|p&65535,O<<16|z&65535)},Ic=function(a,b){if(Hc(b))throw Error("division by zero");if(Hc(a))return C(0);if(a.s(D())){if(b.s(C(1))||b.s(C(-1)))return D();if(b.s(D()))return C(1);var c=1;if(0==c)c=a;else{var d=a.b;c=32>c?G(a.a>>>c|d<<32-c,d>>c):G(d>>c-32,0<=d?0:-1)}c=Nc(Ic(c,b),1);if(c.s(C(0)))return 0>b.b?C(1):C(-1);a=Jc(a,H(b,c));return c.add(Ic(a,b))}if(b.s(D()))return C(0);if(0>a.b)return 0>b.b?Ic(E(a), -E(b)):E(Ic(E(a),b));if(0>b.b)return E(Ic(a,E(b)));for(d=C(0);0<=Lc(a,b);){c=Math.max(1,Math.floor((4294967296*a.b+Kc(a))/(4294967296*b.b+Kc(b))));var e=Math.ceil(Math.log(c)/Math.LN2);e=48>=e?1:Math.pow(2,e-48);for(var f=F(c),g=H(f,b);0>g.b||0<Lc(g,a);)c-=e,f=F(c),g=H(f,b);Hc(f)&&(f=C(1));d=d.add(f);a=Jc(a,g)}return d};B.prototype.and=function(a){return G(this.a&a.a,this.b&a.b)};B.prototype.or=function(a){return G(this.a|a.a,this.b|a.b)};B.prototype.xor=function(a){return G(this.a^a.a,this.b^a.b)}; -var Nc=function(a,b){b&=63;if(0==b)return a;var c=a.a;return 32>b?G(c<<b,a.b<<b|c>>>32-b):G(0,c<<b-32)},Oc=function(a,b){b&=63;if(0==b)return a;var c=a.b;return 32>b?G(a.a>>>b|c<<32-b,c>>>b):32==b?G(c,0):G(c>>>b-32,0)};var Pc=function(a,b){this.ia=a;this.a={};for(a=0;a<b.length;a++){var c=b[a];this.a[c.a]=c}},Qc=function(a){a=ab(a.a);Ma(a,function(a,c){return a.a-c.a});return a},Rc=function(a,b){v(!/[^0-9]/.test(b));return a.a[parseInt(b,10)]||null};var Sc=function(a,b,c){this.i=a;v(!/[^0-9]/.test(b));this.a=b;this.o=!!c.ja;this.g=!!c.m;this.b=c.c;this.h=c.type;this.l=!1;switch(this.b){case 3:case 4:case 6:case 16:case 18:case 2:case 1:this.l=!0}},Tc=function(a){return 11==a.b||10==a.b};var I=function(){this.A={};this.b=this.f().a;this.a=null};I.prototype.has=function(a){v(a.i.prototype.f()==this.f(),"The current message does not contain the given field");return null!=this.A[a.a]};var Uc=function(a,b){v(b.i.prototype.f()==a.f(),"The current message does not contain the given field");b=b.a;return a.b[b].g?null!=a.A[b]?a.A[b].length:0:null!=a.A[b]?1:0}; -I.prototype.get=function(a,b){v(a.i.prototype.f()==this.f(),"The current message does not contain the given field");return Vc(this,a.a,b)};I.prototype.set=function(a,b){v(a.i.prototype.f()==this.f(),"The current message does not contain the given field");J(this,a.a,b)};I.prototype.add=function(a,b){v(a.i.prototype.f()==this.f(),"The current message does not contain the given field");Wc(this,a.a,b)}; -I.prototype.s=function(a){if(!a||this.constructor!=a.constructor)return!1;for(var b=Qc(this.f()),c=0;c<b.length;c++){var d=b[c],e=d.a;if(null!=this.A[e]!=(null!=a.A[e]))return!1;if(null!=this.A[e]){var f=Tc(d),g=Xc(this,e);e=Xc(a,e);if(d.g){if(g.length!=e.length)return!1;for(d=0;d<g.length;d++){var m=g[d],p=e[d];if(f?!m.s(p):m!=p)return!1}}else if(f?!g.s(e):g!=e)return!1}}return!0}; -var Yc=function(a,b){v(a.constructor==b.constructor,"The source message must have the same type.");for(var c=Qc(a.f()),d=0;d<c.length;d++){var e=c[d],f=e.a;if(null!=b.A[f]){a.a&&delete a.a[e.a];var g=Tc(e);if(e.g){e=Xc(b,f)||[];for(var m=0;m<e.length;m++)Wc(a,f,g?e[m].clone():e[m])}else e=Xc(b,f),g?(g=Xc(a,f))?Yc(g,e):J(a,f,e.clone()):J(a,f,e)}}}; -I.prototype.clone=function(){var a=new this.constructor;v(a.constructor==this.constructor,"The source message must have the same type.");a!=this&&(a.A={},a.a&&(a.a={}),Yc(a,this));return a}; -var Xc=function(a,b){a=a.A[b];return null==a?null:a},Vc=function(a,b,c){var d=Xc(a,b);return a.b[b].g?(a=c||0,v(0<=a&&a<d.length,"Given index %s is out of bounds. Repeated field length: %s",a,d.length),d[a]):d},J=function(a,b,c){var d=a.b[b];14==d.b?za(c):v(Object(c).constructor==d.h);a.A[b]=c;a.a&&(a.a[b]=c)},Wc=function(a,b,c){var d=a.b[b];14==d.b?za(c):v(Object(c).constructor==d.h);a.A[b]||(a.A[b]=[]);a.A[b].push(c);a.a&&delete a.a[b]},K=function(a,b){var c=[],d;for(d in b)0!=d&&c.push(new Sc(a, -d,b[d]));return new Pc(a,c)};var Zc=function(){};Zc.prototype.h=function(a,b){Tc(a)&&this.i(b)};Zc.prototype.g=function(a,b){if(Tc(a))return b instanceof I||(a=new (a.h.prototype.f().ia),this.l(a,b),v(a instanceof I),b=a),b;if(14==a.b)return q(b)&&$c.test(b)&&(a=Number(b),0<a)?a:b;if(!a.l)return b;a=a.h;if(a===String){if("number"==typeof b)return String(b)}else if(a===Number&&q(b)&&("Infinity"===b||"-Infinity"===b||"NaN"===b||$c.test(b)))return Number(b);return b};var $c=/^-?[0-9]+$/;var ad={dd:!0},bd={ed:!0},cd=function(){throw Error("Do not instantiate directly");};cd.prototype.a=null;cd.prototype.toString=function(){return this.Y};var dd=function(){cd.call(this)};t(dd,cd);dd.prototype.ga=ad;var hd=function(a){v(a,"Soy template may not be null.");var b=a(ed,void 0,void 0);a=Mb().a.createElement("DIV");b=fd(b);var c=b.match(gd);v(!c,"This template starts with a %s, which cannot be a child of a <div>, as required by soy internals. Consider using goog.soy.renderElement instead.\nTemplate output: %s",c&&c[0],b);a.innerHTML=b;1==a.childNodes.length&&(b=a.firstChild,1==b.nodeType&&(a=b));return a},fd=function(a){if(!oa(a))return String(a);if(a instanceof cd){if(a.ga===ad)return Aa(a.Y);if(a.ga=== -bd)return Va(a.Y)}ya("Soy template output is unsafe for use as HTML: "+a);return"zSoyz"},gd=/^<(body|caption|col|colgroup|head|html|tr|td|th|tbody|thead|tfoot)>/i,ed={};var id=function(a){try{var b=a.getBoundingClientRect()}catch(c){return{left:0,top:0,right:0,bottom:0}}gb&&a.ownerDocument.body&&(a=a.ownerDocument,b.left-=a.documentElement.clientLeft+a.body.clientLeft,b.top-=a.documentElement.clientTop+a.body.clientTop);return b},kd=function(a){var b=jd;a:{var c=Lb(a);if(c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a,null))){c=c.display||c.getPropertyValue("display")||"";break a}c=""}c||(c=a.currentStyle?a.currentStyle.display: -null);if("none"!=(c||a.style&&a.style.display))return b(a);c=a.style;var d=c.display,e=c.visibility,f=c.position;c.visibility="hidden";c.position="absolute";c.display="inline";a=b(a);c.display=d;c.position=f;c.visibility=e;return a},jd=function(a){var b=a.offsetWidth,c=a.offsetHeight,d=jb&&!b&&!c;return n(b)&&!d||!a.getBoundingClientRect?new Jb(b,c):(a=id(a),new Jb(a.right-a.left,a.bottom-a.top))};var ld=function(){};la(ld);ld.prototype.a=0;var L=function(a){y.call(this);this.V=a||Mb();this.K=null;this.D=!1;this.i=null;this.ba=void 0;this.J=this.o=this.v=null};t(L,y);L.prototype.la=ld.w();L.prototype.F=function(){return this.i}; -var md=function(a){a=a.i;v(a,"Can not call getElementStrict before rendering/decorating.");return a},nd=function(a){a.ba||(a.ba=new tc(a));return v(a.ba)},od=function(a,b){if(a==b)throw Error("Unable to set parent component");var c;if(c=b&&a.v&&a.K){var d=a.v;c=a.K;d.J&&c?(d=d.J,c=(null!==d&&c in d?d[c]:void 0)||null):c=null}if(c&&a.v!=b)throw Error("Unable to set parent component");a.v=b;L.S.W.call(a,b)}; -L.prototype.W=function(a){if(this.v&&this.v!=a)throw Error("Method not supported");L.S.W.call(this,a)};L.prototype.Z=function(){this.i=this.V.a.createElement("DIV")};L.prototype.render=function(a){if(this.D)throw Error("Component already rendered");this.i||this.Z();a?a.insertBefore(this.i,null):this.V.a.body.appendChild(this.i);this.v&&!this.v.D||this.C()};L.prototype.C=function(){this.D=!0;pd(this,function(a){!a.D&&a.F()&&a.C()})}; -var qd=function(a,b){var c=a.o?a.o.length:0;v(!!b,"Provided element must not be null.");if(b.D&&!a.D)throw Error("Component already rendered");if(0>c||c>(a.o?a.o.length:0))throw Error("Child component index out of bounds");a.J&&a.o||(a.J={},a.o=[]);if(b.v==a){var d=b.K||(b.K=":"+(b.la.a++).toString(36));a.J[d]=b;Ha(a.o,b)}else{d=a.J;var e=b.K||(b.K=":"+(b.la.a++).toString(36));if(null!==d&&e in d)throw Error('The object already contains the key "'+e+'"');d[e]=b}od(b,a);Ka(a.o,c,0,b);b.D&&a.D&&b.v== -a?(a=a.i,c=a.childNodes[c]||null,c!=b.F()&&a.insertBefore(b.F(),c)):a.D&&!b.D&&b.i&&b.i.parentNode&&1==b.i.parentNode.nodeType&&b.C()},pd=function(a,b){a.o&&Da(a.o,b,void 0)};var rd=function(a){function b(a){this.Y=a}b.prototype=a.prototype;return function(a,d){a=new b(String(a));void 0!==d&&(a.a=d);return a}}(dd),sd={"\x00":"�","\t":"	","\n":" ","\x0B":"","\f":"","\r":" "," ":" ",'"':""","&":"&","'":"'","-":"-","/":"/","<":"<","=":"=",">":">","`":"`","\u0085":"…","\u00a0":" ","\u2028":"
","\u2029":"
"},td=function(a){return sd[a]},ud=/[\x00\x22\x27\x3c\x3e]/g,vd=/<(?:!|\/?([a-zA-Z][a-zA-Z0-9:\-]*))(?:[^>'"]|"[^"]*"|'[^']*')*>/g, -wd=/</g;var M=function(){I.call(this)};t(M,I);var xd=null,yd={Vc:0,dc:1,KEEP:2,Hb:3,cc:4},zd={Yc:0,Wb:1,Kc:2,Zb:3,ec:4},N=function(){I.call(this)};t(N,I);var Ad=null,Bd={Sc:0,Rb:1,OPENED:2,sc:3,kc:4,rc:5,Db:6,Qc:7,vc:8,Kb:9,Ac:10,Bb:11,bc:12},Cd=function(){I.call(this)};t(Cd,I);var Dd=null,Ed=function(){I.call(this)};t(Ed,I);var Fd=null,Gd=function(){I.call(this)};t(Gd,I);var Hd=null,Id=function(){I.call(this)};t(Id,I);var Jd=null,Kd=function(){I.call(this)};t(Kd,I);var Ld=null,Md=function(){I.call(this)}; -t(Md,I);var Nd=null,Od={Wc:0,Lc:1,Mc:2,Jc:3,Pc:4,Nc:5,Oc:6,Ib:7,zc:8},Pd={Xc:0,Yb:1,Fb:2,pc:3,jc:4,oc:5},Qd={Uc:0,yc:1,Xb:2,ac:3},Rd=function(){I.call(this)};t(Rd,I);var Sd=null,Td={Tc:0,nc:1,uc:2},Ud=function(){I.call(this)};t(Ud,I);var Vd=null,Wd={Mb:0,Lb:1,Dc:2}; -M.prototype.f=function(){var a=xd;a||(xd=a=K(M,{0:{name:"InkEvent",j:"logs.proto.research.ink.InkEvent"},1:{name:"host",c:14,defaultValue:0,type:yd},2:{name:"event_type",c:14,defaultValue:0,type:zd},3:{name:"document_event",c:11,type:N},4:{name:"toolbar_event",c:11,type:Md},5:{name:"engine_event",c:11,type:Rd},6:{name:"gms_event",c:11,type:Ud}}));return a};M.f=M.prototype.f; -N.prototype.f=function(){var a=Ad;a||(Ad=a=K(N,{0:{name:"DocumentEvent",I:M,j:"logs.proto.research.ink.InkEvent.DocumentEvent"},1:{name:"event_type",c:14,defaultValue:0,type:Bd},2:{name:"opened_event",c:11,type:Cd},3:{name:"open_cancelled_event",c:11,type:Ed},4:{name:"error_code",c:3,type:String},5:{name:"brix_error_code",c:3,type:String},6:{name:"collaborator_joined_event",c:11,type:Gd},7:{name:"document_state",c:11,type:Id}}));return a};N.f=N.prototype.f; -Cd.prototype.f=function(){var a=Dd;a||(Dd=a=K(Cd,{0:{name:"OpenedEvent",I:N,j:"logs.proto.research.ink.InkEvent.DocumentEvent.OpenedEvent"},1:{name:"millis_until_first_byte_loaded",c:3,type:String},2:{name:"millis_until_editable",c:3,type:String},3:{name:"missing_document_bounds",c:8,type:Boolean},4:{name:"was_opened_by_cosmoid",c:8,type:Boolean},5:{name:"active_users",c:3,type:String}}));return a};Cd.f=Cd.prototype.f; -Ed.prototype.f=function(){var a=Fd;a||(Fd=a=K(Ed,{0:{name:"OpenCancelledEvent",I:N,j:"logs.proto.research.ink.InkEvent.DocumentEvent.OpenCancelledEvent"},1:{name:"time_until_cancelled",c:3,type:String}}));return a};Ed.f=Ed.prototype.f;Gd.prototype.f=function(){var a=Hd;a||(Hd=a=K(Gd,{0:{name:"CollaboratorJoined",I:N,j:"logs.proto.research.ink.InkEvent.DocumentEvent.CollaboratorJoined"},1:{name:"is_me",c:8,type:Boolean}}));return a};Gd.f=Gd.prototype.f; -Id.prototype.f=function(){var a=Jd;a||(Jd=a=K(Id,{0:{name:"DocumentState",I:N,j:"logs.proto.research.ink.InkEvent.DocumentEvent.DocumentState"},1:{name:"stroke_count",c:3,type:String},2:{name:"text_field",m:!0,c:11,type:Kd},3:{name:"sticker_count",c:3,type:String}}));return a};Id.f=Id.prototype.f; -Kd.prototype.f=function(){var a=Ld;a||(Ld=a=K(Kd,{0:{name:"TextField",I:Id,j:"logs.proto.research.ink.InkEvent.DocumentEvent.DocumentState.TextField"},1:{name:"character_count",c:3,type:String},2:{name:"line_count",c:3,type:String}}));return a};Kd.f=Kd.prototype.f; -Md.prototype.f=function(){var a=Nd;a||(Nd=a=K(Md,{0:{name:"ToolbarEvent",I:M,j:"logs.proto.research.ink.InkEvent.ToolbarEvent"},1:{name:"tool_event_type",c:14,defaultValue:0,type:Od},2:{name:"tool_type",c:14,defaultValue:0,type:Pd},3:{name:"expand_method",c:14,defaultValue:0,type:Qd},4:{name:"color",c:5,type:Number}}));return a};Md.f=Md.prototype.f; -Rd.prototype.f=function(){var a=Sd;a||(Sd=a=K(Rd,{0:{name:"EngineEvent",I:M,j:"logs.proto.research.ink.InkEvent.EngineEvent"},1:{name:"engine_event_type",c:14,defaultValue:0,type:Td},2:{name:"error_code",c:3,type:String}}));return a};Rd.f=Rd.prototype.f; -Ud.prototype.f=function(){var a=Vd;a||(Vd=a=K(Ud,{0:{name:"GmsEvent",I:M,j:"logs.proto.research.ink.InkEvent.GmsEvent"},1:{name:"gms_event_type",c:14,defaultValue:0,type:Wd},2:{name:"time_since_connect_start",c:3,type:String},3:{name:"failure_has_resolution",c:8,type:Boolean},4:{name:"gms_error_code",c:3,type:String}}));return a};Ud.f=Ud.prototype.f;var P=function(){this.a=[];this.o={value:0,length:0};this.v={value:C(0),length:0};this.b=new DataView(new ArrayBuffer(8))};t(P,Zc); -P.prototype.i=function(a){if(null==a)return[];this.a=[];for(var b=Qc(a.f()),c=0;c<b.length;c++){var d=b[c];if(a.has(d))if(d.g)if(d.o){var e=a,f=d;d=this.a;Q(this,f.a<<3|2);for(var g=d.length,m=0,p=Uc(e,f);m<p;m++){var u=e.get(f,m);this.h(f,u,!0)}e=d.splice(g,d.length-g);Q(this,e.length);d.splice.apply(d,[d.length,0].concat(e))}else for(e=0,f=Uc(a,d);e<f;e++)g=a.get(d,e),this.h(d,g);else this.h(d,a.get(d))}return this.a}; -P.prototype.h=function(a,b,c){if(c=!c){a:{switch(a.b){default:c=!1;break a;case 17:case 18:case 8:case 3:case 14:case 5:case 13:case 4:c=0;break;case 6:case 16:case 1:c=1;break;case 9:case 12:case 11:c=2;break;case 10:c=3;break;case 7:case 15:case 2:c=5}Q(this,a.a<<3|c);c=!0}c=!c}if(!c)switch(a.b){default:throw Error("Unknown field type "+a.b);case 17:Q(this,b<<1^-(b>>>31));break;case 18:a=Fc(b);a=Nc(a,1).xor(E(Oc(a,63)));Xd(this,a);break;case 8:Q(this,b?1:0);break;case 5:0<b?Q(this,b):Xd(this,Cc(b)); -break;case 3:case 4:Xd(this,Fc(b));break;case 14:case 13:Q(this,b);break;case 6:case 16:Yd(this,Fc(b),8);break;case 1:this.b.setFloat64(0,b,!0);for(a=0;8>a;a++)this.a.push(this.b.getUint8(a));break;case 9:if(null!=b)for(a=unescape(encodeURIComponent(b)),Q(this,a.length),b=0;b<a.length;b++)this.a.push(a.charCodeAt(b));break;case 12:if(null!=b)for(Q(this,b.length),a=0;a<b.length;a++)this.a.push(b.charCodeAt(a));break;case 10:b=(new P).i(b);Ia(this.a,b);Q(this,a.a<<3|4);break;case 11:b=(new P).i(b); -Q(this,b.length);Ia(this.a,b);break;case 7:Yd(this,F(b),4);break;case 15:Yd(this,Cc(b),4);break;case 2:for(this.b.setFloat32(0,b,!0),a=0;4>a;a++)this.a.push(this.b.getUint8(a))}}; -P.prototype.l=function(a,b){if(null==b)return b;b instanceof ArrayBuffer&&(b=new Uint8Array(b));for(var c=a.f(),d=0;d<b.length;){var e=Zd(this,b.subarray(d)),f=e.value,g=f>>3;f&=7;d+=e.length;if(e=Rc(c,g))if(e.o)for(g=Zd(this,b.subarray(d)),f=g.value,d+=g.length;0<f&&d<b.length;){g=this.g(e,b.subarray(d));if(!g)throw Error("Expected "+e.b);a.add(e,g.value);d+=g.length;f-=g.length}else{f=this.g(e,b.subarray(d));if(!f)throw Error("Expected "+e.b);d+=f.length;e.g?a.add(e,f.value):a.set(e,f.value)}else{e= -d;d=b.subarray(d);g=0;switch(f){case 0:g=$d(this,d).length;break;case 1:g=8;break;case 2:d=$d(this,d);g=d.length+d.value.a;break;case 3:case 4:ya("Error deserializing group");break;case 5:g=4}d=e+g}}}; -P.prototype.g=function(a,b){var c=null,d=a.b,e=$d(this,b),f=e.length;switch(d){case 17:a=e.value.a;c=a>>>1^-(a&1);break;case 18:a=e.value;c=Oc(a,1).xor(E(a.and(C(1)))).toString();break;case 8:c=e.value.s(C(1));break;case 3:case 4:c=e.value.toString();break;case 5:c=e.value.a;break;case 14:case 13:c=Kc(e.value);break;case 6:case 16:a=b.subarray(0,8);c=(new B(ae(a.subarray(0,4),!0),ae(a.subarray(4,8),!0))).toString();f=8;break;case 1:a=b.subarray(0,8);for(c=0;8>c;c++)this.b.setUint8(c,a[c]);c=this.b.getFloat64(0, -!0);f=8;break;case 9:a=b.subarray(e.length,e.length+e.value.a);a=be(a);c=decodeURIComponent(escape(a));f=e.length+e.value.a;break;case 12:a=b.subarray(e.length,e.length+e.value.a);c=be(a);f=e.length+e.value.a;break;case 10:f=c=new (a.h.prototype.f().ia);e=b;d=f.f();for(var g=0;;){var m=Zd(this,e),p=m.value;m=m.length;var u=p>>3;if(4==(p&7))break;g+=m;p={value:void 0,length:0};(u=Rc(d,u))&&(p=this.g(u,e.subarray(m)))&&null!==p.value&&(u.g?f.add(u,p.value):f.set(u,p.value));g+=p.length;if(e.length< -m+p.length)break;e=e.subarray(m+p.length)}f=g;b=$d(this,b.subarray(f));v(b.value.a==(a.a<<3|4),"Error deserializing group");f+=b.length;break;case 11:f=e.length+e.value.a;b=b.subarray(e.length,f);c=new (a.h.prototype.f().ia);this.l(c,b);break;case 7:case 15:c=ae(b.subarray(0,4),15==d);f=4;break;case 2:a=b.subarray(0,4);for(c=0;4>c;c++)this.b.setUint8(c,a[c]);c=this.b.getFloat32(0,!0);f=4}return{value:c,length:f}}; -var Q=function(a,b){do{var c=b&127;b>>>=7;0<b&&(c|=128);a.a.push(c)}while(0<b)},Xd=function(a,b){var c=Cc(127);do{var d=b.and(c).a;b=Oc(b,7);0<Lc(b,C(0))&&(d|=128);a.a.push(d)}while(0<Lc(b,C(0)))},$d=function(a,b){a=a.v;for(var c=F(0),d=0;d<b.length;d++){var e=Nc(Cc(b[d]&127),7*d);c=c.or(e);if(0==(b[d]&128))break}a.value=c;a.length=d+1;return a},Zd=function(a,b){a=a.o;for(var c=0,d=0;d<b.length&&(c|=(b[d]&127)<<7*d,0!=(b[d]&128));d++);a.value=c;a.length=d+1;return a},Yd=function(a,b,c){for(var d= -Cc(255),e=0;e<c;e++){var f=b.and(d).a;a.a.push(f);b=Oc(b,8)}},ae=function(a,b){for(var c=0,d=0;d<a.length;d++)c|=a[d]<<8*d;b||(c>>>=0);return c},be=function(a){var b="";a=new Uint16Array(a);for(var c=0;c<a.length;c+=65536)b+=String.fromCharCode.apply(null,a.subarray(c,c+Math.min(65536,a.length-c)));return b};var ce=function(a){for(var b=a.T;b;)a=b,b=a.T;return a},de=function(a,b){var c=document.createElement("CANVAS"),d=document.createElement("IMG");d.setAttribute("style","position:absolute;visibility:hidden;top:-1000px;left:-1000px;");d.crossOrigin="Anonymous";fc(d,"load",function(){var a=d.width,f=d.height;c.width=a;c.height=f;var g=c.getContext("2d");g.drawImage(d,0,0);g=g.getImageData(0,0,a,f);document.body.removeChild(d);b(g.data,new Jb(a,f))});d.setAttribute("src",a);document.body.appendChild(d)}, -ee=function(a,b){var c=new M;J(c,1,a);J(c,2,1);a=new N;J(a,1,b);J(c,3,a);return c};var fe=function(a){x.call(this,"b");this.enabled=a};t(fe,x);var ge=function(){x.call(this,"d")};t(ge,x);var he=function(){x.call(this,"e")};t(he,x);var ie=function(){x.call(this,"f")};t(ie,x);var je=function(a){x.call(this,"g");this.callback=a};t(je,x);var ke=function(){x.call(this,"h")};t(ke,x);var le=function(){x.call(this,"l")};t(le,x);var me=function(){I.call(this)};t(me,I);var ne=null,R=function(){I.call(this)};t(R,I);var oe=null;me.prototype.f=function(){var a=ne;a||(ne=a=K(me,{0:{name:"Point",j:"sketchology.proto.Point"},1:{name:"x",c:2,type:Number},2:{name:"y",c:2,type:Number}}));return a};me.f=me.prototype.f; -R.prototype.f=function(){var a=oe;a||(oe=a=K(R,{0:{name:"Rect",j:"sketchology.proto.Rect"},1:{name:"xlow",c:2,type:Number},2:{name:"xhigh",c:2,type:Number},3:{name:"ylow",c:2,type:Number},4:{name:"yhigh",c:2,type:Number}}));return a};R.f=R.prototype.f;var pe={Vb:0,ic:1,hc:2,fc:3,gc:4,Qb:5,Pb:6,Nb:7,Ob:8,Ic:9,Hc:10,Fc:11,Gc:12,Ec:13},qe={Ub:0,lc:1,Gb:2,wc:3},re=function(){I.call(this)};t(re,I);var se=null,te=function(){I.call(this)};t(te,I);var ue=null;re.prototype.f=function(){var a=se;a||(se=a=K(re,{0:{name:"Font",j:"sketchology.proto.text.Font"},1:{name:"postscript_font",c:14,defaultValue:0,type:pe},2:{name:"name",c:9,type:String},3:{name:"asset_id",c:9,type:String},4:{name:"resource_id",c:13,type:Number}}));return a};re.f=re.prototype.f; -te.prototype.f=function(){var a=ue;a||(ue=a=K(te,{0:{name:"Text",j:"sketchology.proto.text.Text"},1:{name:"text",c:9,type:String},2:{name:"bounds_world",c:11,type:R},3:{name:"font",c:11,type:re},4:{name:"font_size_world",c:2,defaultValue:24,type:Number},5:{name:"rgba",c:13,defaultValue:255,type:Number},6:{name:"alignment",c:14,defaultValue:0,type:qe}}));return a};te.f=te.prototype.f;var ve={NONE:0,Zc:1,Bc:2,$b:3,$c:4},we=function(){I.call(this)};t(we,I);var xe=null,ye=function(){I.call(this)};t(ye,I);var ze=null,Ae=function(){I.call(this)};t(Ae,I);var Be=null,Ce=function(){I.call(this)};t(Ce,I);var De=null,Ee=function(){I.call(this)};t(Ee,I);var Fe=null,Ge=function(){I.call(this)};t(Ge,I);var He=null,S=function(){I.call(this)};t(S,I);var Ie=null,Je=function(){I.call(this)};t(Je,I);var Ke=null,Le=function(){I.call(this)};t(Le,I);var Me=null,Ne=function(){I.call(this)};t(Ne,I); -var Oe=null,T=function(){I.call(this)};t(T,I);var Pe=null;T.prototype.F=function(){return Vc(this,2)};var Qe=function(){I.call(this)};t(Qe,I);var Re=null,Se={Rc:0,qc:1,mc:2,Sb:3,tc:4,Jb:5},Te={Eb:1,xc:2,Cc:3};we.prototype.f=function(){var a=xe;a||(xe=a=K(we,{0:{name:"BackgroundImageInfo",j:"sketchology.proto.BackgroundImageInfo"},1:{name:"uri",c:9,type:String},3:{name:"bounds",c:11,type:R}}));return a};we.f=we.prototype.f; -ye.prototype.f=function(){var a=ze;a||(ze=a=K(ye,{0:{name:"Border",j:"sketchology.proto.Border"},1:{name:"uri",c:9,type:String},2:{name:"scale",c:2,defaultValue:1,type:Number}}));return a};ye.f=ye.prototype.f;Ae.prototype.f=function(){var a=Be;a||(Be=a=K(Ae,{0:{name:"GridInfo",j:"sketchology.proto.GridInfo"},1:{name:"uri",c:9,type:String},2:{name:"rgba_multiplier",c:13,defaultValue:4294967295,type:Number},3:{name:"size_world",c:2,defaultValue:50,type:Number},4:{name:"origin",c:11,type:me}}));return a}; -Ae.f=Ae.prototype.f;Ce.prototype.f=function(){var a=De;a||(De=a=K(Ce,{0:{name:"LOD",j:"sketchology.proto.LOD"},1:{name:"max_coverage",c:2,type:Number},2:{name:"ctm_blob",c:12,type:String}}));return a};Ce.f=Ce.prototype.f; -Ee.prototype.f=function(){var a=Fe;a||(Fe=a=K(Ee,{0:{name:"Stroke",j:"sketchology.proto.Stroke"},1:{name:"shader_type",c:14,defaultValue:0,type:ve},3:{name:"lod",m:!0,c:11,type:Ce},4:{name:"abgr",c:13,type:Number},5:{name:"point_x",m:!0,ja:!0,c:17,type:Number},6:{name:"point_y",m:!0,ja:!0,c:17,type:Number},7:{name:"point_t_ms",m:!0,ja:!0,c:13,type:Number},8:{name:"deprecated_transform",c:11,type:S},9:{name:"start_time_ms",c:4,type:String}}));return a};Ee.f=Ee.prototype.f; -Ge.prototype.f=function(){var a=He;a||(He=a=K(Ge,{0:{name:"UncompressedStroke",j:"sketchology.proto.UncompressedStroke"},1:{name:"outline",m:!0,c:11,type:me},2:{name:"rgba",c:13,type:Number}}));return a};Ge.f=Ge.prototype.f; -S.prototype.f=function(){var a=Ie;a||(Ie=a=K(S,{0:{name:"AffineTransform",j:"sketchology.proto.AffineTransform"},1:{name:"tx",c:2,type:Number},2:{name:"ty",c:2,type:Number},3:{name:"scale_x",c:2,defaultValue:1,type:Number},4:{name:"scale_y",c:2,defaultValue:1,type:Number},5:{name:"rotation_radians",c:2,type:Number}}));return a};S.f=S.prototype.f; -Je.prototype.f=function(){var a=Ke;a||(Ke=a=K(Je,{0:{name:"Element",j:"sketchology.proto.Element"},4:{name:"deprecated_uuid",c:9,type:String},5:{name:"minimum_serializer_version",c:13,type:Number},6:{name:"stroke",c:11,type:Ee},9:{name:"path",c:11,type:Qe},10:{name:"attributes",c:11,type:Le},11:{name:"text",c:11,type:te}}));return a};Je.f=Je.prototype.f; -Le.prototype.f=function(){var a=Me;a||(Me=a=K(Le,{0:{name:"ElementAttributes",j:"sketchology.proto.ElementAttributes"},1:{name:"selectable",c:8,defaultValue:!0,type:Boolean},2:{name:"magic_erasable",c:8,defaultValue:!0,type:Boolean},3:{name:"is_sticker",c:8,defaultValue:!1,type:Boolean},4:{name:"is_text",c:8,defaultValue:!1,type:Boolean},5:{name:"is_group",c:8,defaultValue:!1,type:Boolean}}));return a};Le.f=Le.prototype.f; -Ne.prototype.f=function(){var a=Oe;a||(Oe=a=K(Ne,{0:{name:"UncompressedElement",j:"sketchology.proto.UncompressedElement"},1:{name:"uncompressed_stroke",c:11,type:Ge}}));return a};Ne.f=Ne.prototype.f;T.prototype.f=function(){var a=Pe;a||(Pe=a=K(T,{0:{name:"ElementBundle",j:"sketchology.proto.ElementBundle"},1:{name:"uuid",c:9,type:String},2:{name:"element",c:11,type:Je},3:{name:"transform",c:11,type:S},4:{name:"uncompressed_element",c:11,type:Ne},5:{name:"group_uuid",c:9,type:String}}));return a}; -T.f=T.prototype.f;Qe.prototype.f=function(){var a=Re;a||(Re=a=K(Qe,{0:{name:"Path",j:"sketchology.proto.Path"},1:{name:"segment_types",m:!0,c:14,defaultValue:0,type:Se},2:{name:"segment_counts",m:!0,c:13,type:Number},3:{name:"segment_args",m:!0,c:1,type:Number},4:{name:"radius",c:1,defaultValue:1,type:Number},5:{name:"rgba",c:13,type:Number},6:{name:"end_cap",c:14,defaultValue:2,type:Te},7:{name:"fill_rgba",c:13,type:Number}}));return a};Qe.f=Qe.prototype.f;var Ue={Cb:1,Tb:2},Ve=function(){I.call(this)};t(Ve,I);var We=null,Xe=function(){I.call(this)};t(Xe,I);var Ye=null,Ze=function(){I.call(this)};t(Ze,I);var $e=null,af=function(){I.call(this)};t(af,I);var bf=null,cf=function(){I.call(this)};t(cf,I);var df=null,ef=function(){I.call(this)};t(ef,I);var ff=null,gf=function(){I.call(this)};t(gf,I);var hf=null,jf=function(){I.call(this)};t(jf,I);var kf=null,lf=function(){I.call(this)};t(lf,I);var mf=null,nf=function(){I.call(this)};t(nf,I); -var of=null,U=function(){I.call(this)};t(U,I);var pf=null;U.prototype.F=function(){return Vc(this,2,void 0)};var qf=function(){I.call(this)};t(qf,I);var rf=null;qf.prototype.F=function(){return Vc(this,2,void 0)};Ve.prototype.f=function(){var a=We;a||(We=a=K(Ve,{0:{name:"Color",j:"sketchology.proto.Color"},1:{name:"argb",c:13,type:Number}}));return a};Ve.f=Ve.prototype.f; -Xe.prototype.f=function(){var a=Ye;a||(Ye=a=K(Xe,{0:{name:"PageProperties",j:"sketchology.proto.PageProperties"},1:{name:"background_color",c:11,type:Ve},2:{name:"background_image",c:11,type:we},3:{name:"bounds",c:11,type:R},4:{name:"border",c:11,type:ye},5:{name:"grid_info",c:11,type:Ae}}));return a};Xe.f=Xe.prototype.f; -Ze.prototype.f=function(){var a=$e;a||($e=a=K(Ze,{0:{name:"PerPageProperties",j:"sketchology.proto.PerPageProperties"},1:{name:"uuid",c:9,type:String},2:{name:"width",c:2,type:Number},3:{name:"height",c:2,type:Number}}));return a};Ze.f=Ze.prototype.f;af.prototype.f=function(){var a=bf;a||(bf=a=K(af,{0:{name:"AddAction",j:"sketchology.proto.AddAction"},1:{name:"uuid",c:9,type:String},2:{name:"below_element_with_uuid",c:9,type:String}}));return a};af.f=af.prototype.f; -cf.prototype.f=function(){var a=df;a||(df=a=K(cf,{0:{name:"RemoveAction",j:"sketchology.proto.RemoveAction"},1:{name:"uuid",m:!0,c:9,type:String},2:{name:"was_below_uuid",m:!0,c:9,type:String}}));return a};cf.f=cf.prototype.f;ef.prototype.f=function(){var a=ff;a||(ff=a=K(ef,{0:{name:"ClearAction",j:"sketchology.proto.ClearAction"},1:{name:"uuid",m:!0,c:9,type:String}}));return a};ef.f=ef.prototype.f; -gf.prototype.f=function(){var a=hf;a||(hf=a=K(gf,{0:{name:"ReplaceAction",j:"sketchology.proto.ReplaceAction"},1:{name:"uuid_add",m:!0,c:9,type:String},2:{name:"below_element_with_uuid",c:9,type:String},3:{name:"uuid_remove",m:!0,c:9,type:String},4:{name:"was_below_uuid",m:!0,c:9,type:String}}));return a};gf.f=gf.prototype.f; -jf.prototype.f=function(){var a=kf;a||(kf=a=K(jf,{0:{name:"SetTransformAction",j:"sketchology.proto.SetTransformAction"},1:{name:"uuid",m:!0,c:9,type:String},2:{name:"from_transform",m:!0,c:11,type:S},3:{name:"to_transform",m:!0,c:11,type:S}}));return a};jf.f=jf.prototype.f;lf.prototype.f=function(){var a=mf;a||(mf=a=K(lf,{0:{name:"SetPageBoundsAction",j:"sketchology.proto.SetPageBoundsAction"},1:{name:"old_bounds",c:11,type:R},2:{name:"new_bounds",c:11,type:R}}));return a};lf.f=lf.prototype.f; -nf.prototype.f=function(){var a=of;a||(of=a=K(nf,{0:{name:"StorageAction",j:"sketchology.proto.StorageAction"},1:{name:"add_action",c:11,type:af},2:{name:"remove_action",c:11,type:cf},3:{name:"clear_action",c:11,type:ef},4:{name:"replace_action",c:11,type:gf},5:{name:"set_transform_action",c:11,type:jf},6:{name:"set_page_bounds_action",c:11,type:lf}}));return a};nf.f=nf.prototype.f; -U.prototype.f=function(){var a=pf;a||(pf=a=K(U,{0:{name:"Snapshot",j:"sketchology.proto.Snapshot"},1:{name:"page_properties",c:11,type:Xe},8:{name:"per_page_properties",m:!0,c:11,type:Ze},2:{name:"element",m:!0,c:11,type:T},3:{name:"dead_element",m:!0,c:11,type:T},4:{name:"undo_action",m:!0,c:11,type:nf},5:{name:"redo_action",m:!0,c:11,type:nf},6:{name:"element_state_index",m:!0,c:14,defaultValue:1,type:Ue},7:{name:"fingerprint",c:4,type:String}}));return a};U.f=U.prototype.f; -qf.prototype.f=function(){var a=rf;a||(rf=a=K(qf,{0:{name:"MutationPacket",j:"sketchology.proto.MutationPacket"},1:{name:"mutation",m:!0,c:11,type:nf},2:{name:"element",m:!0,c:11,type:T}}));return a};qf.f=qf.prototype.f;var sf=function(){I.call(this)};t(sf,I);var tf=null;sf.prototype.f=function(){var a=tf;a||(tf=a=K(sf,{0:{name:"ImageExport",j:"sketchology.proto.ImageExport"},1:{name:"max_dimension_px",c:13,defaultValue:1024,type:Number},2:{name:"should_draw_background",c:8,defaultValue:!0,type:Boolean}}));return a};sf.f=sf.prototype.f;var uf=function(){y.call(this)};t(uf,y);var vf="ink_model_instances_"+Math.random();var V=function(){y.call(this);this.b="#000000";this.h=.6;this.g=!1;this.a=this.i=1;this.l="CALLIGRAPHY"};t(V,uf);(function(a){a.w=function(b){Ba(b);var c=ce(b);(b=c[vf])||(c[vf]=b={});var d=a[pa]||(a[pa]=++qa),e=b[d];e?b=e:(c=new a(c),b=b[d]=c);return b}})(V);var wf={CALLIGRAPHY:1,EDIT:2,ERASER:1,HIGHLIGHTER:1,INKPEN:1,MAGIC_ERASE:3,MARKER:1,PENCIL:1,BALLPOINT:1,BALLPOINT_IN_PEN_MODE_ELSE_MARKER:1,QUERY:4},xf={CALLIGRAPHY:1,ERASER:6,HIGHLIGHTER:8,INKPEN:2,MARKER:3,BALLPOINT:4,BALLPOINT_IN_PEN_MODE_ELSE_MARKER:11}; -h=V.prototype;h.Oa=function(a){this.b=a;A(this,"m")};h.zb=function(a){this.h=a;A(this,"m")};h.xb=function(a){this.g=a;A(this,"m")};h.yb=function(a){this.i=wf[a];this.a=void 0!==xf[a]?xf[a]:this.a;this.l=a;A(this,"m")};h.Ga=function(){return this.l};h.Ma=function(){return this.b};h.oa=function(){return this.g?"#FFFFFF":this.b};h.pa=function(){return parseInt(this.oa().substring(1),16)};h.Ha=function(){return this.h};h.Da=function(){return this.g};h.Ba=function(){return this.a};h.Na=function(){return this.i};var Cf=function(a){this.h=yf(a);this.g=zf(a);this.b=Af(a);this.a=Bf(a)},Df=function(a){return"rgb("+[a.g,a.b,a.a].join()+")"},Ef=function(a){return new Uint32Array([a.g<<24|a.b<<16|a.a<<8|a.h])},Ff=function(a){return function(b){return b>>>a&255}},yf=Ff(24),zf=Ff(16),Af=Ff(8),Bf=Ff(0),Gf=new Cf(4278190080),Hf=new Cf(4294967295),If=new Cf(4294638330);var Jf={},Kf=(Jf.dots="sketchology://grid_dots_0",Jf.rules="sketchology://grid_rules_0",Jf.square="sketchology://grid_square_0",Jf),Lf={},Mf=(Lf.none="",Lf.dots="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAQAAAD2e2DtAAACoElEQVR4Ae3SsW0iQABE0Y0ogJC+iC0XAy0ANdAF9IFAQrTxL7wLbAuQLlm/eSXMH32/W2MKXPp2PwVwbjCF03sB7BpMYfdeAOsGU1i/E8C9ZYMpLLu+HsC2wTQ2rwbwaNVgGquurwXw0WAqn68EcGgwnf2zARxbNJjOouMzAezdP3ECh58DuPbZYGofPb4O4NqmVYPprdp2/xvApVO71i0bvwbL1u06dxv9aoz+IwSAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACIARAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAhDArXO71i0b/BrL1u06dRlVVd3btmpMj1WbrlVVo3/36KMxNT67Vn0dQNWhRYMpLdpX/RxAHSUwpUXHeiaA2jeYzqGeDaA+G0zlo14J4NqqwTRWPV4LoDYNprGtVwO4tmwwhWX31wOodYMprOudAHYNprB7L4BTgymc3wvg0mAKt77dH6BiW7h7b3psAAAAAElFTkSuQmCC", -Lf.rules="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX///////9VfPVsAAAAAnRSTlP/AOW3MEoAAAAUSURBVHgBY4CD/1BAmDHKGGXAAAD0xe4gqLTwJgAAAABJRU5ErkJggg==",Lf.square="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX///////9VfPVsAAAAAnRSTlP/AOW3MEoAAAAWSURBVHgBY4CD+v9g8I8wY5QxyoABAGFRzuKVnN1rAAAAAElFTkSuQmCC",Lf),Nf=function(a){return(Object.entries(Kf).find(function(b){return b[1]==a})||["none",""])[0]};var Of=function(){this.a=l.Module;v(this.a);new P;this.g=this.a.HEAPU8;this.h=r(this.a._malloc,this.a);this.b=r(this.a._free,this.a)};la(Of);var Pf=function(a,b,c){return a.a[b]&&a.a[b].extend?a.a[b].extend(b,c):null};var W=function(a,b,c){var d=Pf(Of.w(),"ClientBitmap",W.prototype);return d?(W=d,new W(a,b,c)):null};W.prototype.i=function(a,b,c){this.__parent.__construct.call(this,[b.width,b.height],c);this.a=a;this.b=void 0};W.prototype.g=function(){this.b&&Of.w().b(this.b);this.__parent.__destruct.call(this)};W.prototype.h=function(){if(!this.b){var a=Of.w();this.b=a.h(this.a.length*this.a.BYTES_PER_ELEMENT);a.g.set(this.a,this.b)}return this.b};ta("ink.ClientBitmap",W);W.prototype.__construct=W.prototype.i; -W.prototype.__destruct=W.prototype.g;W.prototype.imageByteData=W.prototype.h;var Qf=function(){x.call(this,"n")};t(Qf,x);var Rf=function(){y.call(this);this.a=null;this.i=r(this.K,this);this.v=this.o=0;this.g=[];this.b=this.h=60;this.l=1/60};t(Rf,y);Rf.prototype.start=function(){this.a||(this.a=requestAnimationFrame(this.i))};Rf.prototype.B=function(a){var b=this.b;this.b=a;this.l=1/a;0==b&&0<a&&this.start()};Rf.prototype.J=function(){return this.b};var Sf=function(a){0==a.b&&a.B(60)}; -Rf.prototype.K=function(a){if(0==this.b)this.a=null,this.h=0;else{this.a=requestAnimationFrame(this.i);if(l.SHOW_FPS){var b=a-this.v;this.v=a;this.g.push(b);5<this.g.length&&(b=Hb.apply(null,this.g),this.h=Math.round(1E3/b),this.g=[],window.console.log("FPS:",this.h))}b=Math.round(a-this.o);60!==this.b&&b<Math.round(1E3*this.l)||(A(this,"o"),this.o=a)}};var Tf=function(){this.a=[];this.g=[];this.b=[];this.h=!1;this.i=r(Tf.prototype.l,this)};la(Tf);var Uf=function(a,b,c){var d=a.a.indexOf(b);-1===d?(a.a.push(b),a.g.push([c]),a.b.push(kd(b))):a.g[d].push(c);a.h||(a.h=!0,window.requestAnimationFrame(a.i))};Tf.prototype.l=function(){for(var a=0,b=this.a.length;a<b;a++){var c=this.a[a],d=this.g[a],e=this.b[a],f=kd(c);if(!(e==f||e&&f&&e.width==f.width&&e.height==f.height)){this.b[a]=f;e=0;for(var g=d.length;e<g;e++)d[e](c,f)}}this.h&&window.requestAnimationFrame(this.i)};var Vf=function(){return rd('<canvas id="ink-engine"></canvas>')};Vf.a="ink.soy.asm.canvasHTML";var X=function(a,b,c,d,e,f,g,m,p){var u=Pf(Of.w(),"Host",X.prototype);if(u)return X=u,new X(a,b,c,d,e,f,g,m,p);throw Error("Bindings are uninitialized.");};h=X.prototype;h.Pa=function(a,b,c,d,e,f,g,m,p){this.__parent.__construct.call(this);this.g=a;this.L=b;this.i=c;this.a=d;this.b=e;this.h=f;this.da=g;this.ca=m;this.U=p};h.Ia=function(){return this.a()};h.Ab=function(a){this.i(a)};h.Aa=function(){var a=Of.w().a.ctx;a.bindFramebuffer(a.FRAMEBUFFER,null)};h.vb=function(a){this.U(a)}; -h.Ja=function(a,b,c){var d=this.L;d.l.add(a);A(d,new ge(a,b,c))};h.Ka=function(a,b){A(this.L,new he(a,b))};h.La=function(a){A(this.L,new ie(a))};h.sb=function(a,b,c){this.b(a,b,new Uint8ClampedArray(c.buffer,c.byteOffset,c.byteLength))}; -h.Fa=function(){var a;if(!(a=!this.g)&&(a=w("Macintosh"))){a=Ya;var b="";w("Windows")?(b=/Windows (?:NT|Phone) ([0-9.]+)/,b=(a=b.exec(a))?a[1]:"0.0"):w("iPhone")&&!w("iPod")&&!w("iPad")||w("iPad")||w("iPod")?(b=/(?:iPhone|iPod|iPad|CPU)\s+OS\s+(\S+)/,b=(a=b.exec(a))&&a[1].replace(/_/g,".")):w("Macintosh")?(b=/Mac OS X ([0-9_.]+)/,b=(a=b.exec(a))?a[1].replace(/_/g,"."):"10"):w("Android")?(b=/Android\s+([^\);]+)(\)|;)/,b=(a=b.exec(a))&&a[1]):w("CrOS")&&(b=/(?:CrOS\s+(?:i686|x86_64)\s+([0-9.]+))/,b= -(a=b.exec(a))&&a[1]);a=!(0<=Xa(b||"","10.12.5"))}return"asmjs/webgl"+(a?1:2)};h.tb=function(a){this.ca(a)};h.rb=function(a,b){this.h(a,b)};h.ub=function(a,b){this.da(a,b)};ta("ink.HostController",X);X.prototype.__construct=X.prototype.Pa;X.prototype.setTargetFPS=X.prototype.Ab;X.prototype.getTargetFPS=X.prototype.Ia;X.prototype.bindScreen=X.prototype.Aa;X.prototype.requestImage=X.prototype.vb;X.prototype.handleElementCreated=X.prototype.Ja;X.prototype.handleElementsMutated=X.prototype.Ka; -X.prototype.handleElementsRemoved=X.prototype.La;X.prototype.onImageExportComplete=X.prototype.sb;X.prototype.getPlatformId=X.prototype.Fa;X.prototype.onSequencePointReached=X.prototype.tb;X.prototype.onFlagChanged=X.prototype.rb;X.prototype.onUndoRedoStateChanged=X.prototype.ub;P.prototype.serialize=P.prototype.i;P.prototype.deserializeTo=P.prototype.l;var Y=function(a,b,c,d,e){var f=this;L.call(this);this.b=null;this.h=new P;this.L=b;this.xa=c;this.U=e;this.H=0;this.O=600;this.N=800;this.M=0;this.g=Qb();this.B=null;this.ea=!1;this.l=new Rf;this.l.W(this);vc(nd(this),this.l,"o",r(this.ua,this));ta("ink.SketchologyEngineWrapper.exit",function(){A(f,"q");var a=f.l;null!==a.a&&(cancelAnimationFrame(a.a),a.a=null);f.a=null});this.ya=d;this.fa={};this.na=this.ma=0};t(Y,L); -Y.prototype.Z=function(){this.i=hd(Vf)};Y.prototype.C=function(){var a=r(function(){setTimeout(r(this.wa,this),0)},this);l.asmjsLoadingDone?a():(l.Module=l.Module||{},l.Module.postRun=l.Module.postRun||[],l.Module.postRun.push(a));V.w(this);vc(nd(this),md(this),"webglcontextlost",this.ka)};var Wf=function(a){x.call(this,"r");this.enabled=a};t(Wf,x);Y.prototype.ka=function(){A(this,"q")}; -Y.prototype.wa=function(){var a=this;this.b=Of.w();var b=md(this);Xf(this);var c=!!b.getContext("webgl2"),d={antialias:!0,majorVersion:c?2:1,minorVersion:0};l.Module.canvas=b;if(d=l.Browser.createContext(b,!0,!0,d)){d.clearColor(1,1,1,1);c=new X(c,this.L,r(this.l.B,this.l),r(this.l.J,this.l),this.xa,function(b,c){5==b&&A(a,new Wf(c))},r(this.da,this),r(this.ca,this),this.U);d=Math.floor(Math.random()*Math.pow(2,52));var e=Yf(this);try{this.a=Module[this.ya](c,e,d)}finally{e["delete"]()}Zf(this,this.H, -this.O,this.N,this.M);Uf(Tf.w(),b,r(this.va,this));c=l.PointerEvent?["pointerdown","pointerup","pointercancel","pointermove","wheel"]:"mousedown mouseup mousemove wheel touchstart touchend touchmove touchcancel".split(" ");d=r(this.aa,this);for(e=0;e<c.length;e++)b.addEventListener(c[e],d,{passive:!1});l.window.addEventListener("mouseup",d);l.PointerEvent&&l.window.addEventListener("pointerup",function(b){"mouse"==b.pointerType&&a.aa(b)});gc(b,"contextmenu",function(a){a.preventDefault()});this.l.start(); -A(this,"p")}else this.ka()};var Yf=function(a){var b=new (Of.w().a.ViewportProto);b.width=md(a).width||800*a.g;b.height=md(a).height||600*a.g;b.ppi=96*a.g;return b};Y.prototype.va=function(a,b){Xf(this,b);if(b.za()){a=Yf(this);try{this.a.setViewport(a)}finally{a["delete"]()}}}; -var Xf=function(a,b){var c=md(a);b=b||kd(c);c.width=b.width*a.g;c.height=b.height*a.g},$f=function(a,b,c,d,e){try{var f=new W(b,c,Module.ImageFormat.RGBA_8888),g=new a.b.a.ImageInfoProto;g.uri=d;g.asset_type=Module.AssetType.values[e];a.a.addImageData(g,f)}finally{if(f)f["delete"]();if(g)g["delete"]()}},ag=function(a,b){try{var c=new a.b.a.BackgroundColorProto;c.rgba=Ef(b)[0];a.a.document().SetBackgroundColor(c)}finally{if(c)c["delete"]()}};Y.prototype.ua=function(){this.a.draw()}; -Y.prototype.aa=function(a){var b=bg(a.type);if(l.PointerEvent&&a instanceof PointerEvent){if(PointerEvent.prototype.getCoalescedEvents){var c=a.getCoalescedEvents();if(1<c.length){a=ia(c);for(b=a.next();!b.done;b=a.next())this.aa(b.value);return}}if("pen"==a.pointerType)"pointerdown"!=a.type&&!this.ea||a.buttons&2||("pointerdown"==a.type&&(this.ea=!0),"pointerup"==a.type&&(this.ea=!1),c=cg()/1E3,a.buttons&32&&b.push(Module.InputFlag.ERASER),b=dg(b),this.a.dispatchInputFull(Module.InputType.PEN,a.pointerId, -b,c,a.offsetX*this.g,a.offsetY*this.g,0,a.pressure,0,0));else if("touch"==a.pointerType)eg(this,b,a.pointerId,a.offsetX,a.offsetY);else if("mouse"==a.pointerType)switch(a.type){case "pointerdown":fg(this,b,a);break;case "pointerup":gg(this,b,a);break;case "pointermove":hg(this,b,a)}}else if(l.TouchEvent&&a instanceof TouchEvent)for(var d=c=null,e=0;e<a.changedTouches.length;e++){var f=a.changedTouches[e],g=f.target;if(c===g)var m=d;else{var p=Lb(g);Ba(g,"Parameter is required");m=new Ib(0,0);var u= -p?Lb(p):document;u=!gb||9<=Number(tb)||"CSS1Compat"==Mb(u).a.compatMode?u.documentElement:u.body;if(g!=u){u=id(g);var z=Mb(p).a;p=z.scrollingElement?z.scrollingElement:jb||"CSS1Compat"!=z.compatMode?z.body||z.documentElement:z.documentElement;z=z.parentWindow||z.defaultView;p=gb&&sb("10")&&z.pageYOffset!=p.scrollTop?new Ib(p.scrollLeft,p.scrollTop):new Ib(z.pageXOffset||p.scrollLeft,z.pageYOffset||p.scrollTop);m.x=u.left+p.x;m.a=u.top+p.a}}c!=g&&(c=g,d=m);eg(this,b,f.identifier,f.pageX-m.x,f.pageY- -m.a)}else if(a instanceof WheelEvent)c=a.wheelDeltaY?a.wheelDeltaY:1===a.deltaMode?-40*a.deltaY:-a.deltaY,0!=c&&(0<c?(d=Module.MouseIds.MOUSEWHEELUP,b.push(Module.InputFlag.WHEELUP)):(d=Module.MouseIds.MOUSEWHEELDOWN,b.push(Module.InputFlag.WHEELDOWN)),e=cg()/1E3,b=dg(b),this.a.dispatchInputFull(Module.InputType.MOUSE,d.value,b,e,a.offsetX*this.g,a.offsetY*this.g,c,-1,0,0),a.preventDefault());else if(a instanceof MouseEvent)switch(a.type){case "mousedown":fg(this,b,a);break;case "mouseup":gg(this, -b,a);break;case "mousemove":hg(this,b,a)}}; -var bg=function(a){switch(a){case "pointerdown":case "mousedown":case "touchstart":return[Module.InputFlag.TDOWN,Module.InputFlag.INCONTACT];case "pointerup":case "mouseup":case "touchend":return[Module.InputFlag.TUP];case "pointermove":case "mousemove":case "touchmove":return[Module.InputFlag.INCONTACT];case "pointercancel":case "touchcancel":return[Module.InputFlag.TUP,Module.InputFlag.CANCEL]}return[0]},dg=function(a){var b=0;Da(a,function(a){b|=a.value});return b},cg=function(){return window.performance&& -Math.floor(window.performance.now())||Date.now()},eg=function(a,b,c,d,e){var f=cg()/1E3;b=dg(b);a.a.dispatchInput(Module.InputType.TOUCH,c,b,f,d*a.g,e*a.g)},fg=function(a,b,c){if(0!=c.button||jb&&kb&&c.ctrlKey){var d=Module.MouseIds.MOUSERIGHT;b.push(Module.InputFlag.RIGHT)}else d=Module.MouseIds.MOUSELEFT,b.push(Module.InputFlag.LEFT);if(null==a.B){a.B=d;var e=cg()/1E3;b=dg(b);a.a.dispatchInput(Module.InputType.MOUSE,d.value,b,e,c.offsetX*a.g,c.offsetY*a.g);l.PointerEvent||c.preventDefault()}},gg= -function(a,b,c){if(0!=c.button||jb&&kb&&c.ctrlKey){var d=Module.MouseIds.MOUSERIGHT;b.push(Module.InputFlag.RIGHT)}else d=Module.MouseIds.MOUSELEFT,b.push(Module.InputFlag.LEFT);if(null!=a.B&&a.B===d){a.B=null;var e=cg()/1E3;b=dg(b);a.a.dispatchInput(Module.InputType.MOUSE,d.value,b,e,c.offsetX*a.g,c.offsetY*a.g);l.PointerEvent||c.preventDefault()}},hg=function(a,b,c){var d=Module.MouseIds.MOUSEHOVER;if(1==(c.buttons&1)&&!(jb&&kb&&c.ctrlKey))d=Module.MouseIds.MOUSELEFT,b.push(Module.InputFlag.LEFT); -else if(2==(c.buttons&2)||1==(c.buttons&1)&&jb&&kb&&c.ctrlKey)d=Module.MouseIds.MOUSERIGHT,b.push(Module.InputFlag.RIGHT);if(null!=a.B&&a.B===d){var e=cg()/1E3;b=dg(b);a.a.dispatchInput(Module.InputType.MOUSE,d.value,b,e,c.offsetX*a.g,c.offsetY*a.g);l.PointerEvent||c.preventDefault()}},Zf=function(a,b,c,d,e){a.H=b;a.O=c;a.N=d;a.M=e;b=new a.b.a.RectProto;try{b.xlow=a.H,b.ylow=a.M,b.xhigh=a.N,b.yhigh=a.O,a.a.document().SetPageBounds(b)}finally{b["delete"]()}}; -Y.prototype.da=function(a,b){A(this,new Qf(a,b))}; -var ig=function(a,b){var c=a.a.document().GetSnapshot(Module.SnapshotQuery.INCLUDE_UNDO_STACK),d=new U;c.copyToJs(d,a.h);setTimeout(function(){b(d)})},jg=function(a,b){var c=new U,d=null.cd(),e=d.get("pages").get(0);if(!e)throw Error("unable to get page from brix document.");e=e.get("elements").ad();for(var f=0;f<e.length;f++)try{var g=new a.b.a.ElementBundleProto,m=e[f];if(!Module.brixElementToElementBundle(m.get("id"),m.get("proto"),m.get("transform"),g))throw Error("Unable to convert brix element to element bundle."); -var p=new T;g.copyToJs(p,a.h);Wc(c,2,p)}finally{g["delete"]()}g=new Xe;m=new R;d=d.get("bounds");J(m,2,d.fd||0);J(m,1,d.gd||0);J(m,4,d.hd||0);J(m,3,d.jd||0);J(g,3,m);J(c,1,g);try{var u=new a.b.a.SnapshotProto;u.initFromJs(c,a.h);Module.SetFingerprint(u);c=new U;u.copyToJs(c,a.h)}finally{u["delete"]()}setTimeout(function(){b(c)})},kg=function(a,b,c){try{var d=new a.b.a.SnapshotProto;d.initFromJs(b,a.h);var e=Module.SnapshotHasPendingMutations(d)}finally{d["delete"]()}setTimeout(function(){c(!!e)})}, -lg=function(a,b,c){try{var d=new a.b.a.SnapshotProto;d.initFromJs(b,a.h);var e=new a.b.a.MutationPacketProto;if(!Module.ExtractMutationPacket(d,e))throw setTimeout(function(){c(null)}),Error("Unable to extract mutation packet");var f=new qf;e.copyToJs(f,a.h)}finally{if(d["delete"](),e)e["delete"]()}setTimeout(function(){c(f)})},mg=function(a,b,c){try{var d=new a.b.a.SnapshotProto;d.initFromJs(b,a.h);var e=new a.b.a.SnapshotProto;if(!Module.ClearPendingMutations(d,e))throw setTimeout(function(){c(null)}), -Error("Unable to clear pending mutations");var f=new U;e.copyToJs(f,a.h)}finally{if(d["delete"](),e)e["delete"]()}setTimeout(function(){c(f)})};Y.prototype.flush=function(a){this.fa[this.ma]=a;try{var b=new this.b.a.SequencePointProto;b.id=this.ma++;this.a.addSequencePoint(b)}finally{b["delete"]()}};Y.prototype.ca=function(a){var b=this.fa[a];delete this.fa[a];b()};var og=function(a,b){var c=this;L.call(this);this.b=null;this.a=new Y(a,this,r(this.O,this),b,r(this.U,this));qd(this,this.a);xc(nd(this),this.a,r(function(){this.B();ng(this);A(this,"c")},this));vc(nd(this),this.a,"q",this.L);vc(nd(this),this.a,"r",function(a){A(c,new fe(a.enabled))});this.g=[];this.l=new Set;this.H=this.N=0;this.h=null;this.M=!1};t(og,L);og.prototype.C=function(){og.S.C.call(this);this.a.render(this.F());var a=nd(this);v(a);this.b=V.w(this);vc(a,this.b,"m",this.B)}; -og.prototype.O=function(a,b,c){var d=this;if(this.h){try{var e=new ImageData(c,a,b),f=document.createElement("canvas"),g=f.getContext("2d");f.width=a;f.height=b;g.putImageData(e,0,0)}catch(m){this.L(m);return}this.M?(a=function(a){d.h(Db(a))},f.msToBlob?f.msToBlob(a,"image/png"):f.toBlob(a,"image/png")):this.h(Fb(f.toDataURL()))}};og.prototype.U=function(a){var b=this,c=Nf(a);"none"!=c&&de(Mf[c],function(c,e){$f(b.a,c,e,a,3)})}; -var pg=function(a,b,c,d){d=d||{};var e="sketchology://background_"+a.H;a.H++;var f=new we;J(f,1,e);if("none"!=d.bounds){d=d.bounds||{xlow:0,ylow:0,xhigh:c.width,yhigh:c.height};var g=new R;J(g,1,d.xlow);J(g,3,d.ylow);J(g,2,d.xhigh);J(g,4,d.yhigh);J(f,3,g)}a=a.a;try{$f(a,b,c,e,0);var m=new a.b.a.BackgroundImageInfoProto;m.initFromJs(f,a.h);a.a.document().SetBackgroundImage(m)}finally{if(m)m["delete"]()}}; -og.prototype.B=function(){v(this.b);var a=this.b.i,b=this.b.a,c=this.b.h,d=new Cf(parseInt(this.b.b.substring(1),16));d.h=255;var e=this.a;d=Ef(d);try{var f=new e.b.a.ToolParamsProto;f.tool=Module.ToolType.values[a];1==a&&(f.brush_type=Module.BrushType.values[b],f.rgba=d[0],f.mutable_line_size().stroke_width=c,f.mutable_line_size().use_web_sizes=!0,f.mutable_line_size().units=Module.BrushSizeType.PERCENT_WORLD);e.a.setToolParams(f)}finally{if(f)f["delete"]()}}; -var ng=function(a){var b=new ye;J(b,1,"sketchology://border0");J(b,2,1);de("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAABYCAYAAABxlTA0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AgPEBYrHoEFUgAAAw1JREFUeNrt3b9uE0EQBvBvZvd8LURUkVwEkEDAm9AgQYOQKHgZWloqUMoUaVJSpAivQBEhJGhSWiAlKXz7JwXey9nE9vrOgHT3fZKVFM5F/mUyN5tIY8F2EtG/yNYucnZ21keg/57d3V1RMvzdEJjABGYITGACM+1iNz5RxGGPzCIbnT+i3RA1AjgFcADgR4zRDwTVABjHGF8AeJwOaDnYNgd29jGGED6JyMvxeDwZYvVOJpN3FxcXH0TkWfMovQpac6p39jgdMi4A7Ozs/HLOvQkhfEkurW9yDVh47+GcOxgybsre3t5P59y+937OqHUFhxAQQkBVVd85E/yOc+5bcuk0pqWLeO/hvQ+krV289x45yLqqPSRk5xym0yllZ5lOp6iqCiGEtW3C5lZwzq/DUOK9h4jUwK3GtGYFz1oEZa97cA2crJaNapozoiVk5rqCm+2h898ihn487uKiWPMPy2arYG7G7TQHM91CYAITmCEwgQnMEJjABGYITGCGwAQmMENgAhOYITCBCUwCAhOYITCBCcwQmMAEZghMYIbABCYwQ2ACE5ghMIEJzBCYwAyBCUxghsAEJjBDYAIzBP63wFkLcUX4lhAp3nu79Qr23t8lbZ37WwNuLFx7fnJycnvossfHx7dijK+WGLWrYBFBjPHh5eXl/tHR0Z0h41ZV9T7G+EREum/AThcREaiqqOpTAJ8PDw8/VlX11TnnhgArIrYsy3vn5+evy7J8NLNADrJd1xpUFcaY9BBVfSAib2foAPq7GTAZGGNSkcFaC2stjDH161+BLGsrOAEXRYGyLOsNgKqK5hbovgIng/T6R6MRiqKogVtVcPqi5k+tKIo5XOfcYICNMbDWYjQaoSzLP4BXtYqVFayqiDHCWlsjJnDnXPYG0j5UcCqy9LDWtq/gZcipHxVFMbfitec3uMX70FwP7nyTW2zyaSt236v3pipO7UJVs9pDVgU3p4n0jZqwQwBeHFlzYLPn4MXPb4Lt+5i2CJ1zgsuu4GUX2vBNk3qJnvX8jOdwv3h7O1wBYIqaD5lCtYoAAAAASUVORK5CYII=", -function(c,d){var e=a.a;try{var f=new e.b.a.OutOfBoundsColorProto;f.rgba=3873892095;e.a.setOutOfBoundsColor(f);$f(e,c,d,"sketchology://border0",1);var g=new e.b.a.BorderProto;g.initFromJs(b,e.h);e.a.document().SetPageBorder(g)}finally{if(f)f["delete"]();if(g)g["delete"]()}})};og.prototype.L=function(a){if(A(this,new le(a)))throw a||Error("Unhandled fatal ink error");};og.prototype.flush=function(a){this.a.flush(a)};var qg=function(){L.call(this);this.a=null};t(qg,L);qg.prototype.C=function(){qg.S.C.call(this);this.a=V.w(this);var a=nd(this);vc(a,this.a,"m",this.b);vc(a,ce(this),"a",this.g)};qg.prototype.g=function(a){a.g?this.F().style.cursor="":this.b()}; -qg.prototype.b=function(){var a=this.a.pa(),b=8,c=document.createElement("canvas"),d=c.getContext("2d");a=new Cf(a|4278190080);b=Math.max(b,2);var e=Math.ceil(2*b);c.width=e;c.height=e;d.fillStyle=Df(127<.5*(Math.max(a.g,a.b,a.a)+Math.min(a.g,a.b,a.a))?Gf:Hf);d.beginPath();d.arc(b,b,b,0,2*Math.PI);d.closePath();d.fill();d.fillStyle=Df(a);d.beginPath();d.arc(b,b,b-1,0,2*Math.PI);d.closePath();d.fill();b="url("+c.toDataURL()+")8 8, auto";this.F().style.cursor=b};var rg=function(a,b,c){(b=c||b)&&b.ta?(a=b&&b.ta,null!=a&&a.ga===ad?(v(a.constructor===dd),a=String(a.Y).replace(vd,"").replace(wd,"<"),a=String(a).replace(ud,td)):a=Va(String(a)),a=' nonce="'+a+'"'):a="";return rd('<div id="canvas-parent"><style'+a+'>\n #canvas-parent {\n height: 100%;\n position: relative;\n width: 100%;\n }\n #layer-container {\n height: 100%;\n position: relative;\n width: 100%;\n }\n #ink-engine {\n height: 100%;\n left: 0;\n position: absolute;\n top: 0;\n width: 100%;\n touch-action: none;\n }\n .above-ink-canvas {\n display: none;\n }\n </style><div class="above-ink-canvas"></div><div id="layer-container"></div><div class="below-ink-canvas"></div></div>')}; -rg.a="ink.soy.embedContent";var Z=function(a,b){L.call(this);this.b=a;this.g=new qg;qd(this,this.g);this.a=new og(a.g,a.b);qd(this,this.a);this.h=b};t(Z,L);h=Z.prototype;h.Ta=function(){var a=new x("k");A(this,a);a.b||this.a.a.a.document().RemoveAll()};h.qb=function(){var a=new x("i");A(this,a);a.b||this.a.a.a.document().Undo();a=ee(this.b.a,7);A(this,new ke(a))};h.eb=function(){var a=new x("j");A(this,a);a.b||this.a.a.a.document().Redo();a=ee(this.b.a,8);A(this,new ke(a))}; -h.ib=function(a,b){var c=this;de(a,function(a,e){pg(c.a,a,e);b&&b()})};h.mb=function(a,b){var c=this;de(a,function(a,e){pg(c.a,a,e,{bounds:"none"});b&&b()})};h.hb=function(a){ag(this.a.a,a)}; -h.lb=function(a,b,c,d,e,f){var g=this;if("none"==a)this.qa();else{var m=Kf[a];de(Mf[a],function(a,u){var p=g.a,O=new Ae;J(O,1,m);J(O,2,Ef(b)[0]);J(O,3,c);var Ac=new me;J(Ac,1,d);J(Ac,2,e);J(O,4,Ac);p=p.a;try{$f(p,a,u,m,3);var Nb=new p.b.a.GridInfoProto;Nb.initFromJs(O,p.h);p.a.setGrid(Nb)}finally{if(Nb)Nb["delete"]()}f&&f()})}};h.qa=function(){this.a.a.a.clearGrid()}; -h.Xa=function(a,b,c,d){var e=this.a;e.h=c;e.M=!!d;c=new sf;J(c,1,a);J(c,2,b);a=e.a;try{var f=new a.b.a.ImageExportProto;f.initFromJs(c,a.h);a.a.startImageExport(f)}finally{if(f)f["delete"]()}};h.jb=function(a){var b=this.a.a;try{var c=new b.b.a.SetCallbackFlagsProto;c.initFromJs(a,b.h);b.a.setCallbackFlags(c)}finally{c["delete"]()}};h.nb=function(a,b,c,d){Zf(this.a.a,a,b,c,d)};h.Wa=function(){this.a.a.a.deselectAll()};h.Z=function(){this.i=hd(rg)}; -h.C=function(){Z.S.C.call(this);var a=Ob("layer-container");this.a.render(a);var b=this.g;if(b.D)throw Error("Component already rendered");if(a){var c=Lb(a);b.V&&b.V.a==c||(b.V=Mb(a));b.i=a;b.C()}else throw Error("Invalid element to decorate");vc(nd(this),this.a,"c",r(this.h,this,this))};h.wb=function(a){var b=Ob("canvas-parent");a?b.classList?b.classList.add("fullscreen"):yb(b)||(b.className+=0<b.className.length?" fullscreen":"fullscreen"):zb(b)}; -h.Qa=function(a,b){var c=this.a;a.id||(a.id="local-"+c.N++);var d=a.id;Ka(c.g,b,0,d);c.l.has(d)?c.l.delete(d):b<c.g.length-1?(d=c.a,b=c.g[b+1],v(a),v(d.a),Module.addBrixElementToEngineBelow(d.a,a.id,a.proto,a.transform,b)):(b=c.a,v(a),v(b.a),Module.addBrixElementToEngine(b.a,a.id,a.proto,a.transform));Sf(c.a.l)}; -h.fb=function(a,b){for(var c=this.a,d=0;d<b;d++){var e=void 0,f=c.a,g=c.g[a];v(f.a);try{e=new f.b.a.VectorString,e.push_back(g),f.a.document().Remove(e)}finally{if(e)e["delete"]()}Ga(c.g,a)}Sf(c.a.l)};h.gb=function(){var a=this.a;a.a.a.clear();ag(a.a,If);a.a.a.clearGrid();a.l.clear();a.g=[];Sf(a.a.l)};h.ob=function(a){this.a.a.a.assignFlag(Module.Flag.values[1],!!a)}; -h.kb=function(a,b){var c=this.a.a;v(c.a);if(a.length!==b.length)throw Error("mismatch in transform array lengths");var d=new c.b.a.VectorString;try{var e=new c.b.a.VectorString;try{for(var f=0;f<a.length;f++)d.push_back(a[f]),e.push_back(b[f]);Module.sendBrixMutationToEngine(c.a,d,e)}finally{e["delete"]()}}finally{d["delete"]()}};h.bb=function(a){var b=new je(a);A(this,b);b.b||a(void 0)};h.Ca=function(){var a=md(this.a).querySelector("canvas,embed");return new Jb(a.clientWidth,a.clientHeight)}; -h.Ea=function(){return this.b.a};h.Sa=function(a,b){this.a.a.a.assignFlag(Module.Flag.values[a],!!b)};h.$a=function(a){if("makeSEngineInMemory"!==this.b.b)throw Error("Can't getSnapshot without sengineType IN_MEMORY.");ig(this.a.a,a)};h.cb=function(a){if("makeSEngineInMemory"!==this.b.b)throw Error("Can't loadFromSnapshot without sengineType IN_MEMORY.");var b=this.a.a;try{var c=new b.b.a.SnapshotProto;c.initFromJs(a,b.h);Module.loadFromSnapshot(b.a,c)}finally{if(c)c["delete"]()}}; -h.ab=function(a){var b=this.a.a;try{var c=new b.b.a.CommandProto;c.initFromJs(a,b.h);b.a.handleCommand(c)}finally{if(c)c["delete"]()}};h.Za=function(){return this.a.a.a};h.Va=function(a,b){jg(this.a.a,b)};h.pb=function(a,b){kg(this.a.a,a,b)};h.Ya=function(a,b){lg(this.a.a,a,b)};h.Ua=function(a,b){mg(this.a.a,a,b)};h.flush=function(a){this.a.flush(a)}; -h.Ra=function(a,b){var c=this;de(a,function(a,e){var d=c.a.a;try{var g="sketchology://sticker_"+d.na;d.na++;$f(d,a,e,g,2);var m=new d.b.a.ImageRectProto,p=m.mutable_rect();p.xlow=(d.N-d.H-e.width)/2;p.xhigh=(d.N-d.H+e.width)/2;p.ylow=(d.O-d.M-e.width)/2;p.yhigh=(d.O-d.M+e.width)/2;m.bitmap_uri=g;m.mutable_attributes().is_sticker=!0;d.a.addImageRect(m)}finally{if(m)m["delete"]()}b&&b()})};ta("ink.embed.Config",function(a){a=a||{};this.i=a.parentEl||null;this.h=a.parentComponent||null;this.g=a.nativeClientManifestUrl||null;this.a=a.logsHost||0;this.b=a.sengineType||"makeSEnginePassthroughDocument"});ta("ink.embed.EmbedComponent",Z);Z.execute=function(a,b){b=new Z(a,b);od(b,a.h);b.render(a.i)};Z.prototype.clear=Z.prototype.Ta;Z.prototype.undo=Z.prototype.qb;Z.prototype.redo=Z.prototype.eb;Z.prototype.setBackgroundImage=Z.prototype.ib;Z.prototype.setImageToUseForPageBackground=Z.prototype.mb; -Z.prototype.setBackgroundColor=Z.prototype.hb;Z.prototype.setGrid=Z.prototype.lb;Z.prototype.clearGrid=Z.prototype.qa;Z.prototype.exportPng=Z.prototype.Xa;Z.prototype.setCallbackFlags=Z.prototype.jb;Z.prototype.setPageBounds=Z.prototype.nb;Z.prototype.deselectAll=Z.prototype.Wa;Z.prototype.createDom=Z.prototype.Z;Z.prototype.enterDocument=Z.prototype.C;Z.prototype.setFullscreen=Z.prototype.wb;Z.prototype.addElement=Z.prototype.Qa;Z.prototype.removeElements=Z.prototype.fb;Z.prototype.resetCanvas=Z.prototype.gb; -Z.prototype.setReadOnly=Z.prototype.ob;Z.prototype.setElementTransforms=Z.prototype.kb;Z.prototype.isEmpty=Z.prototype.bb;Z.prototype.getCanvasDimensions=Z.prototype.Ca;Z.prototype.getLogsHost=Z.prototype.Ea;Z.prototype.assignFlag=Z.prototype.Sa;Z.prototype.getSnapshot=Z.prototype.$a;Z.prototype.loadFromSnapshot=Z.prototype.cb;Z.prototype.handleCommand=Z.prototype.ab;Z.prototype.getRawEngineObject=Z.prototype.Za;Z.prototype.convertBrixDocumentToSnapshot=Z.prototype.Va; -Z.prototype.snapshotHasPendingMutations=Z.prototype.pb;Z.prototype.extractMutationPacket=Z.prototype.Ya;Z.prototype.clearPendingMutations=Z.prototype.Ua;Z.prototype.flush=Z.prototype.flush;Z.prototype.addSticker=Z.prototype.Ra;ta("ink.BrushModel",V);V.getInstance=V.w;V.prototype.setColor=V.prototype.Oa;V.prototype.setStrokeWidth=V.prototype.zb;V.prototype.setIsErasing=V.prototype.xb;V.prototype.setShape=V.prototype.yb;V.prototype.getShape=V.prototype.Ga;V.prototype.getColor=V.prototype.Ma; -V.prototype.getActiveColor=V.prototype.oa;V.prototype.getActiveColorNumericRbg=V.prototype.pa;V.prototype.getStrokeWidth=V.prototype.Ha;V.prototype.getIsErasing=V.prototype.Da;V.prototype.getBrushType=V.prototype.Ba;V.prototype.getToolType=V.prototype.Na;
diff --git a/third_party/ink/sketchology/proto/animations.pb.js b/third_party/ink/sketchology/proto/animations.pb.js deleted file mode 100644 index da7702c..0000000 --- a/third_party/ink/sketchology/proto/animations.pb.js +++ /dev/null
@@ -1,984 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Protocol Buffer 2 Copyright 2008 Google Inc. -// All other code copyright its respective owners. - -/** - * @fileoverview Generated Protocol Buffer code for file - * third_party/sketchology/proto/animations.proto. - * Generated by //net/proto2/compiler/public:protocol_compiler. - * @suppress {messageConventions} - */ - -goog.provide('sketchology.proto.AnimationCurve'); -goog.provide('sketchology.proto.ColorAnimation'); -goog.provide('sketchology.proto.ScaleAnimation'); -goog.provide('sketchology.proto.ElementAnimation'); -goog.provide('sketchology.proto.CurveType'); - -goog.require('goog.proto2.Message'); - - -/** - * Enumeration CurveType. - * @enum {number} - */ -sketchology.proto.CurveType = { - UNSPECIFIED_CURVE_TYPE: 0, - EASE_IN_OUT: 1, - EASE_IN: 2, - EASE_OUT: 3, - CUSTOM_CUBIC_BEZIER: 4 -}; - - - -/** - * Message AnimationCurve. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.AnimationCurve = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.AnimationCurve, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.AnimationCurve.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.AnimationCurve} The cloned message. - * @override - */ -sketchology.proto.AnimationCurve.prototype.clone; - - -/** - * Gets the value of the type field. - * @return {?sketchology.proto.CurveType} The value. - */ -sketchology.proto.AnimationCurve.prototype.getType = function() { - return /** @type {?sketchology.proto.CurveType} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the type field or the default value if not set. - * @return {!sketchology.proto.CurveType} The value. - */ -sketchology.proto.AnimationCurve.prototype.getTypeOrDefault = function() { - return /** @type {!sketchology.proto.CurveType} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the type field. - * @param {!sketchology.proto.CurveType} value The value. - */ -sketchology.proto.AnimationCurve.prototype.setType = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the type field has a value. - */ -sketchology.proto.AnimationCurve.prototype.hasType = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the type field. - */ -sketchology.proto.AnimationCurve.prototype.typeCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the type field. - */ -sketchology.proto.AnimationCurve.prototype.clearType = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the params field at the index given. - * @param {number} index The index to lookup. - * @return {?number} The value. - */ -sketchology.proto.AnimationCurve.prototype.getParams = function(index) { - return /** @type {?number} */ (this.get$Value(2, index)); -}; - - -/** - * Gets the value of the params field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {number} The value. - */ -sketchology.proto.AnimationCurve.prototype.getParamsOrDefault = function(index) { - return /** @type {number} */ (this.get$ValueOrDefault(2, index)); -}; - - -/** - * Adds a value to the params field. - * @param {number} value The value to add. - */ -sketchology.proto.AnimationCurve.prototype.addParams = function(value) { - this.add$Value(2, value); -}; - - -/** - * Returns the array of values in the params field. - * @return {!Array<number>} The values in the field. - */ -sketchology.proto.AnimationCurve.prototype.paramsArray = function() { - return /** @type {!Array<number>} */ (this.array$Values(2)); -}; - - -/** - * @return {boolean} Whether the params field has a value. - */ -sketchology.proto.AnimationCurve.prototype.hasParams = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the params field. - */ -sketchology.proto.AnimationCurve.prototype.paramsCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the params field. - */ -sketchology.proto.AnimationCurve.prototype.clearParams = function() { - this.clear$Field(2); -}; - - - -/** - * Message ColorAnimation. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ColorAnimation = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ColorAnimation, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ColorAnimation.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ColorAnimation} The cloned message. - * @override - */ -sketchology.proto.ColorAnimation.prototype.clone; - - -/** - * Gets the value of the duration field. - * @return {?number} The value. - */ -sketchology.proto.ColorAnimation.prototype.getDuration = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the duration field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.ColorAnimation.prototype.getDurationOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the duration field. - * @param {number} value The value. - */ -sketchology.proto.ColorAnimation.prototype.setDuration = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the duration field has a value. - */ -sketchology.proto.ColorAnimation.prototype.hasDuration = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the duration field. - */ -sketchology.proto.ColorAnimation.prototype.durationCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the duration field. - */ -sketchology.proto.ColorAnimation.prototype.clearDuration = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the curve field. - * @return {?sketchology.proto.AnimationCurve} The value. - */ -sketchology.proto.ColorAnimation.prototype.getCurve = function() { - return /** @type {?sketchology.proto.AnimationCurve} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the curve field or the default value if not set. - * @return {!sketchology.proto.AnimationCurve} The value. - */ -sketchology.proto.ColorAnimation.prototype.getCurveOrDefault = function() { - return /** @type {!sketchology.proto.AnimationCurve} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the curve field. - * @param {!sketchology.proto.AnimationCurve} value The value. - */ -sketchology.proto.ColorAnimation.prototype.setCurve = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the curve field has a value. - */ -sketchology.proto.ColorAnimation.prototype.hasCurve = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the curve field. - */ -sketchology.proto.ColorAnimation.prototype.curveCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the curve field. - */ -sketchology.proto.ColorAnimation.prototype.clearCurve = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the rgba field. - * @return {?number} The value. - */ -sketchology.proto.ColorAnimation.prototype.getRgba = function() { - return /** @type {?number} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the rgba field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.ColorAnimation.prototype.getRgbaOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the rgba field. - * @param {number} value The value. - */ -sketchology.proto.ColorAnimation.prototype.setRgba = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the rgba field has a value. - */ -sketchology.proto.ColorAnimation.prototype.hasRgba = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the rgba field. - */ -sketchology.proto.ColorAnimation.prototype.rgbaCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the rgba field. - */ -sketchology.proto.ColorAnimation.prototype.clearRgba = function() { - this.clear$Field(3); -}; - - - -/** - * Message ScaleAnimation. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ScaleAnimation = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ScaleAnimation, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ScaleAnimation.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ScaleAnimation} The cloned message. - * @override - */ -sketchology.proto.ScaleAnimation.prototype.clone; - - -/** - * Gets the value of the duration field. - * @return {?number} The value. - */ -sketchology.proto.ScaleAnimation.prototype.getDuration = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the duration field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.ScaleAnimation.prototype.getDurationOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the duration field. - * @param {number} value The value. - */ -sketchology.proto.ScaleAnimation.prototype.setDuration = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the duration field has a value. - */ -sketchology.proto.ScaleAnimation.prototype.hasDuration = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the duration field. - */ -sketchology.proto.ScaleAnimation.prototype.durationCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the duration field. - */ -sketchology.proto.ScaleAnimation.prototype.clearDuration = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the curve field. - * @return {?sketchology.proto.AnimationCurve} The value. - */ -sketchology.proto.ScaleAnimation.prototype.getCurve = function() { - return /** @type {?sketchology.proto.AnimationCurve} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the curve field or the default value if not set. - * @return {!sketchology.proto.AnimationCurve} The value. - */ -sketchology.proto.ScaleAnimation.prototype.getCurveOrDefault = function() { - return /** @type {!sketchology.proto.AnimationCurve} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the curve field. - * @param {!sketchology.proto.AnimationCurve} value The value. - */ -sketchology.proto.ScaleAnimation.prototype.setCurve = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the curve field has a value. - */ -sketchology.proto.ScaleAnimation.prototype.hasCurve = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the curve field. - */ -sketchology.proto.ScaleAnimation.prototype.curveCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the curve field. - */ -sketchology.proto.ScaleAnimation.prototype.clearCurve = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the scale_x field. - * @return {?number} The value. - */ -sketchology.proto.ScaleAnimation.prototype.getScaleX = function() { - return /** @type {?number} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the scale_x field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.ScaleAnimation.prototype.getScaleXOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the scale_x field. - * @param {number} value The value. - */ -sketchology.proto.ScaleAnimation.prototype.setScaleX = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the scale_x field has a value. - */ -sketchology.proto.ScaleAnimation.prototype.hasScaleX = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the scale_x field. - */ -sketchology.proto.ScaleAnimation.prototype.scaleXCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the scale_x field. - */ -sketchology.proto.ScaleAnimation.prototype.clearScaleX = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the scale_y field. - * @return {?number} The value. - */ -sketchology.proto.ScaleAnimation.prototype.getScaleY = function() { - return /** @type {?number} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the scale_y field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.ScaleAnimation.prototype.getScaleYOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the scale_y field. - * @param {number} value The value. - */ -sketchology.proto.ScaleAnimation.prototype.setScaleY = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the scale_y field has a value. - */ -sketchology.proto.ScaleAnimation.prototype.hasScaleY = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the scale_y field. - */ -sketchology.proto.ScaleAnimation.prototype.scaleYCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the scale_y field. - */ -sketchology.proto.ScaleAnimation.prototype.clearScaleY = function() { - this.clear$Field(4); -}; - - - -/** - * Message ElementAnimation. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ElementAnimation = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ElementAnimation, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ElementAnimation.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ElementAnimation} The cloned message. - * @override - */ -sketchology.proto.ElementAnimation.prototype.clone; - - -/** - * Gets the value of the uuid field. - * @return {?string} The value. - */ -sketchology.proto.ElementAnimation.prototype.getUuid = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the uuid field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.ElementAnimation.prototype.getUuidOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the uuid field. - * @param {string} value The value. - */ -sketchology.proto.ElementAnimation.prototype.setUuid = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the uuid field has a value. - */ -sketchology.proto.ElementAnimation.prototype.hasUuid = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uuid field. - */ -sketchology.proto.ElementAnimation.prototype.uuidCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uuid field. - */ -sketchology.proto.ElementAnimation.prototype.clearUuid = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the color_animation field. - * @return {?sketchology.proto.ColorAnimation} The value. - */ -sketchology.proto.ElementAnimation.prototype.getColorAnimation = function() { - return /** @type {?sketchology.proto.ColorAnimation} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the color_animation field or the default value if not set. - * @return {!sketchology.proto.ColorAnimation} The value. - */ -sketchology.proto.ElementAnimation.prototype.getColorAnimationOrDefault = function() { - return /** @type {!sketchology.proto.ColorAnimation} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the color_animation field. - * @param {!sketchology.proto.ColorAnimation} value The value. - */ -sketchology.proto.ElementAnimation.prototype.setColorAnimation = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the color_animation field has a value. - */ -sketchology.proto.ElementAnimation.prototype.hasColorAnimation = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the color_animation field. - */ -sketchology.proto.ElementAnimation.prototype.colorAnimationCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the color_animation field. - */ -sketchology.proto.ElementAnimation.prototype.clearColorAnimation = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the scale_animation field. - * @return {?sketchology.proto.ScaleAnimation} The value. - */ -sketchology.proto.ElementAnimation.prototype.getScaleAnimation = function() { - return /** @type {?sketchology.proto.ScaleAnimation} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the scale_animation field or the default value if not set. - * @return {!sketchology.proto.ScaleAnimation} The value. - */ -sketchology.proto.ElementAnimation.prototype.getScaleAnimationOrDefault = function() { - return /** @type {!sketchology.proto.ScaleAnimation} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the scale_animation field. - * @param {!sketchology.proto.ScaleAnimation} value The value. - */ -sketchology.proto.ElementAnimation.prototype.setScaleAnimation = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the scale_animation field has a value. - */ -sketchology.proto.ElementAnimation.prototype.hasScaleAnimation = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the scale_animation field. - */ -sketchology.proto.ElementAnimation.prototype.scaleAnimationCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the scale_animation field. - */ -sketchology.proto.ElementAnimation.prototype.clearScaleAnimation = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the next field. - * @return {?sketchology.proto.ElementAnimation} The value. - */ -sketchology.proto.ElementAnimation.prototype.getNext = function() { - return /** @type {?sketchology.proto.ElementAnimation} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the next field or the default value if not set. - * @return {!sketchology.proto.ElementAnimation} The value. - */ -sketchology.proto.ElementAnimation.prototype.getNextOrDefault = function() { - return /** @type {!sketchology.proto.ElementAnimation} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the next field. - * @param {!sketchology.proto.ElementAnimation} value The value. - */ -sketchology.proto.ElementAnimation.prototype.setNext = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the next field has a value. - */ -sketchology.proto.ElementAnimation.prototype.hasNext = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the next field. - */ -sketchology.proto.ElementAnimation.prototype.nextCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the next field. - */ -sketchology.proto.ElementAnimation.prototype.clearNext = function() { - this.clear$Field(4); -}; - - -/** @override */ -sketchology.proto.AnimationCurve.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.AnimationCurve.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'AnimationCurve', - fullName: 'sketchology.proto.AnimationCurve' - }, - 1: { - name: 'type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.CurveType.EASE_IN_OUT, - type: sketchology.proto.CurveType - }, - 2: { - name: 'params', - repeated: true, - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - } - }; - sketchology.proto.AnimationCurve.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.AnimationCurve, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.AnimationCurve.getDescriptor = - sketchology.proto.AnimationCurve.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ColorAnimation.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ColorAnimation.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ColorAnimation', - fullName: 'sketchology.proto.ColorAnimation' - }, - 1: { - name: 'duration', - fieldType: goog.proto2.Message.FieldType.DOUBLE, - defaultValue: 0.5, - type: Number - }, - 2: { - name: 'curve', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.AnimationCurve - }, - 3: { - name: 'rgba', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - } - }; - sketchology.proto.ColorAnimation.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ColorAnimation, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ColorAnimation.getDescriptor = - sketchology.proto.ColorAnimation.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ScaleAnimation.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ScaleAnimation.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ScaleAnimation', - fullName: 'sketchology.proto.ScaleAnimation' - }, - 1: { - name: 'duration', - fieldType: goog.proto2.Message.FieldType.DOUBLE, - defaultValue: 0.5, - type: Number - }, - 2: { - name: 'curve', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.AnimationCurve - }, - 3: { - name: 'scale_x', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 4: { - name: 'scale_y', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - } - }; - sketchology.proto.ScaleAnimation.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ScaleAnimation, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ScaleAnimation.getDescriptor = - sketchology.proto.ScaleAnimation.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ElementAnimation.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ElementAnimation.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ElementAnimation', - fullName: 'sketchology.proto.ElementAnimation' - }, - 1: { - name: 'uuid', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 2: { - name: 'color_animation', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ColorAnimation - }, - 3: { - name: 'scale_animation', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ScaleAnimation - }, - 4: { - name: 'next', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ElementAnimation - } - }; - sketchology.proto.ElementAnimation.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ElementAnimation, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ElementAnimation.getDescriptor = - sketchology.proto.ElementAnimation.prototype.getDescriptor;
diff --git a/third_party/ink/sketchology/proto/document.pb.js b/third_party/ink/sketchology/proto/document.pb.js deleted file mode 100644 index 1826d1c5..0000000 --- a/third_party/ink/sketchology/proto/document.pb.js +++ /dev/null
@@ -1,2831 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Protocol Buffer 2 Copyright 2008 Google Inc. -// All other code copyright its respective owners. - -/** - * @fileoverview Generated Protocol Buffer code for file - * third_party/sketchology/proto/document.proto. - * Generated by //net/proto2/compiler/public:protocol_compiler. - * @suppress {messageConventions} - */ - -goog.provide('sketchology.proto.Color'); -goog.provide('sketchology.proto.BackgroundColor'); -goog.provide('sketchology.proto.PageProperties'); -goog.provide('sketchology.proto.AddAction'); -goog.provide('sketchology.proto.RemoveAction'); -goog.provide('sketchology.proto.ClearAction'); -goog.provide('sketchology.proto.ReplaceAction'); -goog.provide('sketchology.proto.SetTransformAction'); -goog.provide('sketchology.proto.SetPageBoundsAction'); -goog.provide('sketchology.proto.StorageAction'); -goog.provide('sketchology.proto.Snapshot'); -goog.provide('sketchology.proto.MutationPacket'); -goog.provide('sketchology.proto.StorageActionState'); -goog.provide('sketchology.proto.ElementState'); - -goog.require('goog.proto2.Message'); -goog.require('sketchology.proto.AffineTransform'); -goog.require('sketchology.proto.BackgroundImageInfo'); -goog.require('sketchology.proto.Border'); -goog.require('sketchology.proto.ElementBundle'); -goog.require('sketchology.proto.Rect'); - - -/** - * Enumeration StorageActionState. - * @enum {number} - */ -sketchology.proto.StorageActionState = { - APPLIED: 1, - UNDONE: 2 -}; - - -/** - * Enumeration ElementState. - * @enum {number} - */ -sketchology.proto.ElementState = { - ALIVE: 1, - DEAD: 2 -}; - - - -/** - * Message Color. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.Color = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.Color, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.Color.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.Color} The cloned message. - * @override - */ -sketchology.proto.Color.prototype.clone; - - -/** - * Gets the value of the argb field. - * @return {?number} The value. - */ -sketchology.proto.Color.prototype.getArgb = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the argb field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Color.prototype.getArgbOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the argb field. - * @param {number} value The value. - */ -sketchology.proto.Color.prototype.setArgb = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the argb field has a value. - */ -sketchology.proto.Color.prototype.hasArgb = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the argb field. - */ -sketchology.proto.Color.prototype.argbCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the argb field. - */ -sketchology.proto.Color.prototype.clearArgb = function() { - this.clear$Field(1); -}; - - - -/** - * Message BackgroundColor. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.BackgroundColor = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.BackgroundColor, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.BackgroundColor.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.BackgroundColor} The cloned message. - * @override - */ -sketchology.proto.BackgroundColor.prototype.clone; - - -/** - * Gets the value of the rgba field. - * @return {?number} The value. - */ -sketchology.proto.BackgroundColor.prototype.getRgba = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the rgba field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.BackgroundColor.prototype.getRgbaOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the rgba field. - * @param {number} value The value. - */ -sketchology.proto.BackgroundColor.prototype.setRgba = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the rgba field has a value. - */ -sketchology.proto.BackgroundColor.prototype.hasRgba = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the rgba field. - */ -sketchology.proto.BackgroundColor.prototype.rgbaCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the rgba field. - */ -sketchology.proto.BackgroundColor.prototype.clearRgba = function() { - this.clear$Field(1); -}; - - - -/** - * Message PageProperties. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.PageProperties = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.PageProperties, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.PageProperties.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.PageProperties} The cloned message. - * @override - */ -sketchology.proto.PageProperties.prototype.clone; - - -/** - * Gets the value of the background_color field. - * @return {?sketchology.proto.Color} The value. - */ -sketchology.proto.PageProperties.prototype.getBackgroundColor = function() { - return /** @type {?sketchology.proto.Color} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the background_color field or the default value if not set. - * @return {!sketchology.proto.Color} The value. - */ -sketchology.proto.PageProperties.prototype.getBackgroundColorOrDefault = function() { - return /** @type {!sketchology.proto.Color} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the background_color field. - * @param {!sketchology.proto.Color} value The value. - */ -sketchology.proto.PageProperties.prototype.setBackgroundColor = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the background_color field has a value. - */ -sketchology.proto.PageProperties.prototype.hasBackgroundColor = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the background_color field. - */ -sketchology.proto.PageProperties.prototype.backgroundColorCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the background_color field. - */ -sketchology.proto.PageProperties.prototype.clearBackgroundColor = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the background_image field. - * @return {?sketchology.proto.BackgroundImageInfo} The value. - */ -sketchology.proto.PageProperties.prototype.getBackgroundImage = function() { - return /** @type {?sketchology.proto.BackgroundImageInfo} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the background_image field or the default value if not set. - * @return {!sketchology.proto.BackgroundImageInfo} The value. - */ -sketchology.proto.PageProperties.prototype.getBackgroundImageOrDefault = function() { - return /** @type {!sketchology.proto.BackgroundImageInfo} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the background_image field. - * @param {!sketchology.proto.BackgroundImageInfo} value The value. - */ -sketchology.proto.PageProperties.prototype.setBackgroundImage = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the background_image field has a value. - */ -sketchology.proto.PageProperties.prototype.hasBackgroundImage = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the background_image field. - */ -sketchology.proto.PageProperties.prototype.backgroundImageCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the background_image field. - */ -sketchology.proto.PageProperties.prototype.clearBackgroundImage = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the bounds field. - * @return {?sketchology.proto.Rect} The value. - */ -sketchology.proto.PageProperties.prototype.getBounds = function() { - return /** @type {?sketchology.proto.Rect} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the bounds field or the default value if not set. - * @return {!sketchology.proto.Rect} The value. - */ -sketchology.proto.PageProperties.prototype.getBoundsOrDefault = function() { - return /** @type {!sketchology.proto.Rect} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the bounds field. - * @param {!sketchology.proto.Rect} value The value. - */ -sketchology.proto.PageProperties.prototype.setBounds = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the bounds field has a value. - */ -sketchology.proto.PageProperties.prototype.hasBounds = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the bounds field. - */ -sketchology.proto.PageProperties.prototype.boundsCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the bounds field. - */ -sketchology.proto.PageProperties.prototype.clearBounds = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the border field. - * @return {?sketchology.proto.Border} The value. - */ -sketchology.proto.PageProperties.prototype.getBorder = function() { - return /** @type {?sketchology.proto.Border} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the border field or the default value if not set. - * @return {!sketchology.proto.Border} The value. - */ -sketchology.proto.PageProperties.prototype.getBorderOrDefault = function() { - return /** @type {!sketchology.proto.Border} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the border field. - * @param {!sketchology.proto.Border} value The value. - */ -sketchology.proto.PageProperties.prototype.setBorder = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the border field has a value. - */ -sketchology.proto.PageProperties.prototype.hasBorder = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the border field. - */ -sketchology.proto.PageProperties.prototype.borderCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the border field. - */ -sketchology.proto.PageProperties.prototype.clearBorder = function() { - this.clear$Field(4); -}; - - - -/** - * Message AddAction. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.AddAction = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.AddAction, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.AddAction.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.AddAction} The cloned message. - * @override - */ -sketchology.proto.AddAction.prototype.clone; - - -/** - * Gets the value of the uuid field. - * @return {?string} The value. - */ -sketchology.proto.AddAction.prototype.getUuid = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the uuid field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.AddAction.prototype.getUuidOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the uuid field. - * @param {string} value The value. - */ -sketchology.proto.AddAction.prototype.setUuid = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the uuid field has a value. - */ -sketchology.proto.AddAction.prototype.hasUuid = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uuid field. - */ -sketchology.proto.AddAction.prototype.uuidCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uuid field. - */ -sketchology.proto.AddAction.prototype.clearUuid = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the below_element_with_uuid field. - * @return {?string} The value. - */ -sketchology.proto.AddAction.prototype.getBelowElementWithUuid = function() { - return /** @type {?string} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the below_element_with_uuid field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.AddAction.prototype.getBelowElementWithUuidOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the below_element_with_uuid field. - * @param {string} value The value. - */ -sketchology.proto.AddAction.prototype.setBelowElementWithUuid = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the below_element_with_uuid field has a value. - */ -sketchology.proto.AddAction.prototype.hasBelowElementWithUuid = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the below_element_with_uuid field. - */ -sketchology.proto.AddAction.prototype.belowElementWithUuidCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the below_element_with_uuid field. - */ -sketchology.proto.AddAction.prototype.clearBelowElementWithUuid = function() { - this.clear$Field(2); -}; - - - -/** - * Message RemoveAction. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.RemoveAction = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.RemoveAction, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.RemoveAction.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.RemoveAction} The cloned message. - * @override - */ -sketchology.proto.RemoveAction.prototype.clone; - - -/** - * Gets the value of the uuid field at the index given. - * @param {number} index The index to lookup. - * @return {?string} The value. - */ -sketchology.proto.RemoveAction.prototype.getUuid = function(index) { - return /** @type {?string} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the uuid field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {string} The value. - */ -sketchology.proto.RemoveAction.prototype.getUuidOrDefault = function(index) { - return /** @type {string} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the uuid field. - * @param {string} value The value to add. - */ -sketchology.proto.RemoveAction.prototype.addUuid = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the uuid field. - * @return {!Array<string>} The values in the field. - */ -sketchology.proto.RemoveAction.prototype.uuidArray = function() { - return /** @type {!Array<string>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the uuid field has a value. - */ -sketchology.proto.RemoveAction.prototype.hasUuid = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uuid field. - */ -sketchology.proto.RemoveAction.prototype.uuidCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uuid field. - */ -sketchology.proto.RemoveAction.prototype.clearUuid = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the was_below_uuid field at the index given. - * @param {number} index The index to lookup. - * @return {?string} The value. - */ -sketchology.proto.RemoveAction.prototype.getWasBelowUuid = function(index) { - return /** @type {?string} */ (this.get$Value(2, index)); -}; - - -/** - * Gets the value of the was_below_uuid field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {string} The value. - */ -sketchology.proto.RemoveAction.prototype.getWasBelowUuidOrDefault = function(index) { - return /** @type {string} */ (this.get$ValueOrDefault(2, index)); -}; - - -/** - * Adds a value to the was_below_uuid field. - * @param {string} value The value to add. - */ -sketchology.proto.RemoveAction.prototype.addWasBelowUuid = function(value) { - this.add$Value(2, value); -}; - - -/** - * Returns the array of values in the was_below_uuid field. - * @return {!Array<string>} The values in the field. - */ -sketchology.proto.RemoveAction.prototype.wasBelowUuidArray = function() { - return /** @type {!Array<string>} */ (this.array$Values(2)); -}; - - -/** - * @return {boolean} Whether the was_below_uuid field has a value. - */ -sketchology.proto.RemoveAction.prototype.hasWasBelowUuid = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the was_below_uuid field. - */ -sketchology.proto.RemoveAction.prototype.wasBelowUuidCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the was_below_uuid field. - */ -sketchology.proto.RemoveAction.prototype.clearWasBelowUuid = function() { - this.clear$Field(2); -}; - - - -/** - * Message ClearAction. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ClearAction = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ClearAction, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ClearAction.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ClearAction} The cloned message. - * @override - */ -sketchology.proto.ClearAction.prototype.clone; - - -/** - * Gets the value of the uuid field at the index given. - * @param {number} index The index to lookup. - * @return {?string} The value. - */ -sketchology.proto.ClearAction.prototype.getUuid = function(index) { - return /** @type {?string} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the uuid field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {string} The value. - */ -sketchology.proto.ClearAction.prototype.getUuidOrDefault = function(index) { - return /** @type {string} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the uuid field. - * @param {string} value The value to add. - */ -sketchology.proto.ClearAction.prototype.addUuid = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the uuid field. - * @return {!Array<string>} The values in the field. - */ -sketchology.proto.ClearAction.prototype.uuidArray = function() { - return /** @type {!Array<string>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the uuid field has a value. - */ -sketchology.proto.ClearAction.prototype.hasUuid = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uuid field. - */ -sketchology.proto.ClearAction.prototype.uuidCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uuid field. - */ -sketchology.proto.ClearAction.prototype.clearUuid = function() { - this.clear$Field(1); -}; - - - -/** - * Message ReplaceAction. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ReplaceAction = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ReplaceAction, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ReplaceAction.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ReplaceAction} The cloned message. - * @override - */ -sketchology.proto.ReplaceAction.prototype.clone; - - -/** - * Gets the value of the uuid_add field at the index given. - * @param {number} index The index to lookup. - * @return {?string} The value. - */ -sketchology.proto.ReplaceAction.prototype.getUuidAdd = function(index) { - return /** @type {?string} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the uuid_add field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {string} The value. - */ -sketchology.proto.ReplaceAction.prototype.getUuidAddOrDefault = function(index) { - return /** @type {string} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the uuid_add field. - * @param {string} value The value to add. - */ -sketchology.proto.ReplaceAction.prototype.addUuidAdd = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the uuid_add field. - * @return {!Array<string>} The values in the field. - */ -sketchology.proto.ReplaceAction.prototype.uuidAddArray = function() { - return /** @type {!Array<string>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the uuid_add field has a value. - */ -sketchology.proto.ReplaceAction.prototype.hasUuidAdd = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uuid_add field. - */ -sketchology.proto.ReplaceAction.prototype.uuidAddCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uuid_add field. - */ -sketchology.proto.ReplaceAction.prototype.clearUuidAdd = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the below_element_with_uuid field. - * @return {?string} The value. - */ -sketchology.proto.ReplaceAction.prototype.getBelowElementWithUuid = function() { - return /** @type {?string} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the below_element_with_uuid field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.ReplaceAction.prototype.getBelowElementWithUuidOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the below_element_with_uuid field. - * @param {string} value The value. - */ -sketchology.proto.ReplaceAction.prototype.setBelowElementWithUuid = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the below_element_with_uuid field has a value. - */ -sketchology.proto.ReplaceAction.prototype.hasBelowElementWithUuid = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the below_element_with_uuid field. - */ -sketchology.proto.ReplaceAction.prototype.belowElementWithUuidCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the below_element_with_uuid field. - */ -sketchology.proto.ReplaceAction.prototype.clearBelowElementWithUuid = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the uuid_remove field at the index given. - * @param {number} index The index to lookup. - * @return {?string} The value. - */ -sketchology.proto.ReplaceAction.prototype.getUuidRemove = function(index) { - return /** @type {?string} */ (this.get$Value(3, index)); -}; - - -/** - * Gets the value of the uuid_remove field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {string} The value. - */ -sketchology.proto.ReplaceAction.prototype.getUuidRemoveOrDefault = function(index) { - return /** @type {string} */ (this.get$ValueOrDefault(3, index)); -}; - - -/** - * Adds a value to the uuid_remove field. - * @param {string} value The value to add. - */ -sketchology.proto.ReplaceAction.prototype.addUuidRemove = function(value) { - this.add$Value(3, value); -}; - - -/** - * Returns the array of values in the uuid_remove field. - * @return {!Array<string>} The values in the field. - */ -sketchology.proto.ReplaceAction.prototype.uuidRemoveArray = function() { - return /** @type {!Array<string>} */ (this.array$Values(3)); -}; - - -/** - * @return {boolean} Whether the uuid_remove field has a value. - */ -sketchology.proto.ReplaceAction.prototype.hasUuidRemove = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the uuid_remove field. - */ -sketchology.proto.ReplaceAction.prototype.uuidRemoveCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the uuid_remove field. - */ -sketchology.proto.ReplaceAction.prototype.clearUuidRemove = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the was_below_uuid field at the index given. - * @param {number} index The index to lookup. - * @return {?string} The value. - */ -sketchology.proto.ReplaceAction.prototype.getWasBelowUuid = function(index) { - return /** @type {?string} */ (this.get$Value(4, index)); -}; - - -/** - * Gets the value of the was_below_uuid field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {string} The value. - */ -sketchology.proto.ReplaceAction.prototype.getWasBelowUuidOrDefault = function(index) { - return /** @type {string} */ (this.get$ValueOrDefault(4, index)); -}; - - -/** - * Adds a value to the was_below_uuid field. - * @param {string} value The value to add. - */ -sketchology.proto.ReplaceAction.prototype.addWasBelowUuid = function(value) { - this.add$Value(4, value); -}; - - -/** - * Returns the array of values in the was_below_uuid field. - * @return {!Array<string>} The values in the field. - */ -sketchology.proto.ReplaceAction.prototype.wasBelowUuidArray = function() { - return /** @type {!Array<string>} */ (this.array$Values(4)); -}; - - -/** - * @return {boolean} Whether the was_below_uuid field has a value. - */ -sketchology.proto.ReplaceAction.prototype.hasWasBelowUuid = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the was_below_uuid field. - */ -sketchology.proto.ReplaceAction.prototype.wasBelowUuidCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the was_below_uuid field. - */ -sketchology.proto.ReplaceAction.prototype.clearWasBelowUuid = function() { - this.clear$Field(4); -}; - - - -/** - * Message SetTransformAction. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.SetTransformAction = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.SetTransformAction, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.SetTransformAction.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.SetTransformAction} The cloned message. - * @override - */ -sketchology.proto.SetTransformAction.prototype.clone; - - -/** - * Gets the value of the uuid field at the index given. - * @param {number} index The index to lookup. - * @return {?string} The value. - */ -sketchology.proto.SetTransformAction.prototype.getUuid = function(index) { - return /** @type {?string} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the uuid field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {string} The value. - */ -sketchology.proto.SetTransformAction.prototype.getUuidOrDefault = function(index) { - return /** @type {string} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the uuid field. - * @param {string} value The value to add. - */ -sketchology.proto.SetTransformAction.prototype.addUuid = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the uuid field. - * @return {!Array<string>} The values in the field. - */ -sketchology.proto.SetTransformAction.prototype.uuidArray = function() { - return /** @type {!Array<string>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the uuid field has a value. - */ -sketchology.proto.SetTransformAction.prototype.hasUuid = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uuid field. - */ -sketchology.proto.SetTransformAction.prototype.uuidCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uuid field. - */ -sketchology.proto.SetTransformAction.prototype.clearUuid = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the from_transform field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.AffineTransform} The value. - */ -sketchology.proto.SetTransformAction.prototype.getFromTransform = function(index) { - return /** @type {?sketchology.proto.AffineTransform} */ (this.get$Value(2, index)); -}; - - -/** - * Gets the value of the from_transform field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.AffineTransform} The value. - */ -sketchology.proto.SetTransformAction.prototype.getFromTransformOrDefault = function(index) { - return /** @type {!sketchology.proto.AffineTransform} */ (this.get$ValueOrDefault(2, index)); -}; - - -/** - * Adds a value to the from_transform field. - * @param {!sketchology.proto.AffineTransform} value The value to add. - */ -sketchology.proto.SetTransformAction.prototype.addFromTransform = function(value) { - this.add$Value(2, value); -}; - - -/** - * Returns the array of values in the from_transform field. - * @return {!Array<!sketchology.proto.AffineTransform>} The values in the field. - */ -sketchology.proto.SetTransformAction.prototype.fromTransformArray = function() { - return /** @type {!Array<!sketchology.proto.AffineTransform>} */ (this.array$Values(2)); -}; - - -/** - * @return {boolean} Whether the from_transform field has a value. - */ -sketchology.proto.SetTransformAction.prototype.hasFromTransform = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the from_transform field. - */ -sketchology.proto.SetTransformAction.prototype.fromTransformCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the from_transform field. - */ -sketchology.proto.SetTransformAction.prototype.clearFromTransform = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the to_transform field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.AffineTransform} The value. - */ -sketchology.proto.SetTransformAction.prototype.getToTransform = function(index) { - return /** @type {?sketchology.proto.AffineTransform} */ (this.get$Value(3, index)); -}; - - -/** - * Gets the value of the to_transform field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.AffineTransform} The value. - */ -sketchology.proto.SetTransformAction.prototype.getToTransformOrDefault = function(index) { - return /** @type {!sketchology.proto.AffineTransform} */ (this.get$ValueOrDefault(3, index)); -}; - - -/** - * Adds a value to the to_transform field. - * @param {!sketchology.proto.AffineTransform} value The value to add. - */ -sketchology.proto.SetTransformAction.prototype.addToTransform = function(value) { - this.add$Value(3, value); -}; - - -/** - * Returns the array of values in the to_transform field. - * @return {!Array<!sketchology.proto.AffineTransform>} The values in the field. - */ -sketchology.proto.SetTransformAction.prototype.toTransformArray = function() { - return /** @type {!Array<!sketchology.proto.AffineTransform>} */ (this.array$Values(3)); -}; - - -/** - * @return {boolean} Whether the to_transform field has a value. - */ -sketchology.proto.SetTransformAction.prototype.hasToTransform = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the to_transform field. - */ -sketchology.proto.SetTransformAction.prototype.toTransformCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the to_transform field. - */ -sketchology.proto.SetTransformAction.prototype.clearToTransform = function() { - this.clear$Field(3); -}; - - - -/** - * Message SetPageBoundsAction. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.SetPageBoundsAction = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.SetPageBoundsAction, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.SetPageBoundsAction.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.SetPageBoundsAction} The cloned message. - * @override - */ -sketchology.proto.SetPageBoundsAction.prototype.clone; - - -/** - * Gets the value of the old_bounds field. - * @return {?sketchology.proto.Rect} The value. - */ -sketchology.proto.SetPageBoundsAction.prototype.getOldBounds = function() { - return /** @type {?sketchology.proto.Rect} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the old_bounds field or the default value if not set. - * @return {!sketchology.proto.Rect} The value. - */ -sketchology.proto.SetPageBoundsAction.prototype.getOldBoundsOrDefault = function() { - return /** @type {!sketchology.proto.Rect} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the old_bounds field. - * @param {!sketchology.proto.Rect} value The value. - */ -sketchology.proto.SetPageBoundsAction.prototype.setOldBounds = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the old_bounds field has a value. - */ -sketchology.proto.SetPageBoundsAction.prototype.hasOldBounds = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the old_bounds field. - */ -sketchology.proto.SetPageBoundsAction.prototype.oldBoundsCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the old_bounds field. - */ -sketchology.proto.SetPageBoundsAction.prototype.clearOldBounds = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the new_bounds field. - * @return {?sketchology.proto.Rect} The value. - */ -sketchology.proto.SetPageBoundsAction.prototype.getNewBounds = function() { - return /** @type {?sketchology.proto.Rect} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the new_bounds field or the default value if not set. - * @return {!sketchology.proto.Rect} The value. - */ -sketchology.proto.SetPageBoundsAction.prototype.getNewBoundsOrDefault = function() { - return /** @type {!sketchology.proto.Rect} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the new_bounds field. - * @param {!sketchology.proto.Rect} value The value. - */ -sketchology.proto.SetPageBoundsAction.prototype.setNewBounds = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the new_bounds field has a value. - */ -sketchology.proto.SetPageBoundsAction.prototype.hasNewBounds = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the new_bounds field. - */ -sketchology.proto.SetPageBoundsAction.prototype.newBoundsCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the new_bounds field. - */ -sketchology.proto.SetPageBoundsAction.prototype.clearNewBounds = function() { - this.clear$Field(2); -}; - - - -/** - * Message StorageAction. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.StorageAction = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.StorageAction, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.StorageAction.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.StorageAction} The cloned message. - * @override - */ -sketchology.proto.StorageAction.prototype.clone; - - -/** - * Gets the value of the add_action field. - * @return {?sketchology.proto.AddAction} The value. - */ -sketchology.proto.StorageAction.prototype.getAddAction = function() { - return /** @type {?sketchology.proto.AddAction} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the add_action field or the default value if not set. - * @return {!sketchology.proto.AddAction} The value. - */ -sketchology.proto.StorageAction.prototype.getAddActionOrDefault = function() { - return /** @type {!sketchology.proto.AddAction} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the add_action field. - * @param {!sketchology.proto.AddAction} value The value. - */ -sketchology.proto.StorageAction.prototype.setAddAction = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the add_action field has a value. - */ -sketchology.proto.StorageAction.prototype.hasAddAction = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the add_action field. - */ -sketchology.proto.StorageAction.prototype.addActionCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the add_action field. - */ -sketchology.proto.StorageAction.prototype.clearAddAction = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the remove_action field. - * @return {?sketchology.proto.RemoveAction} The value. - */ -sketchology.proto.StorageAction.prototype.getRemoveAction = function() { - return /** @type {?sketchology.proto.RemoveAction} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the remove_action field or the default value if not set. - * @return {!sketchology.proto.RemoveAction} The value. - */ -sketchology.proto.StorageAction.prototype.getRemoveActionOrDefault = function() { - return /** @type {!sketchology.proto.RemoveAction} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the remove_action field. - * @param {!sketchology.proto.RemoveAction} value The value. - */ -sketchology.proto.StorageAction.prototype.setRemoveAction = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the remove_action field has a value. - */ -sketchology.proto.StorageAction.prototype.hasRemoveAction = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the remove_action field. - */ -sketchology.proto.StorageAction.prototype.removeActionCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the remove_action field. - */ -sketchology.proto.StorageAction.prototype.clearRemoveAction = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the clear_action field. - * @return {?sketchology.proto.ClearAction} The value. - */ -sketchology.proto.StorageAction.prototype.getClearAction = function() { - return /** @type {?sketchology.proto.ClearAction} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the clear_action field or the default value if not set. - * @return {!sketchology.proto.ClearAction} The value. - */ -sketchology.proto.StorageAction.prototype.getClearActionOrDefault = function() { - return /** @type {!sketchology.proto.ClearAction} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the clear_action field. - * @param {!sketchology.proto.ClearAction} value The value. - */ -sketchology.proto.StorageAction.prototype.setClearAction = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the clear_action field has a value. - */ -sketchology.proto.StorageAction.prototype.hasClearAction = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the clear_action field. - */ -sketchology.proto.StorageAction.prototype.clearActionCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the clear_action field. - */ -sketchology.proto.StorageAction.prototype.clearClearAction = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the replace_action field. - * @return {?sketchology.proto.ReplaceAction} The value. - */ -sketchology.proto.StorageAction.prototype.getReplaceAction = function() { - return /** @type {?sketchology.proto.ReplaceAction} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the replace_action field or the default value if not set. - * @return {!sketchology.proto.ReplaceAction} The value. - */ -sketchology.proto.StorageAction.prototype.getReplaceActionOrDefault = function() { - return /** @type {!sketchology.proto.ReplaceAction} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the replace_action field. - * @param {!sketchology.proto.ReplaceAction} value The value. - */ -sketchology.proto.StorageAction.prototype.setReplaceAction = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the replace_action field has a value. - */ -sketchology.proto.StorageAction.prototype.hasReplaceAction = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the replace_action field. - */ -sketchology.proto.StorageAction.prototype.replaceActionCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the replace_action field. - */ -sketchology.proto.StorageAction.prototype.clearReplaceAction = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the set_transform_action field. - * @return {?sketchology.proto.SetTransformAction} The value. - */ -sketchology.proto.StorageAction.prototype.getSetTransformAction = function() { - return /** @type {?sketchology.proto.SetTransformAction} */ (this.get$Value(5)); -}; - - -/** - * Gets the value of the set_transform_action field or the default value if not set. - * @return {!sketchology.proto.SetTransformAction} The value. - */ -sketchology.proto.StorageAction.prototype.getSetTransformActionOrDefault = function() { - return /** @type {!sketchology.proto.SetTransformAction} */ (this.get$ValueOrDefault(5)); -}; - - -/** - * Sets the value of the set_transform_action field. - * @param {!sketchology.proto.SetTransformAction} value The value. - */ -sketchology.proto.StorageAction.prototype.setSetTransformAction = function(value) { - this.set$Value(5, value); -}; - - -/** - * @return {boolean} Whether the set_transform_action field has a value. - */ -sketchology.proto.StorageAction.prototype.hasSetTransformAction = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the set_transform_action field. - */ -sketchology.proto.StorageAction.prototype.setTransformActionCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the set_transform_action field. - */ -sketchology.proto.StorageAction.prototype.clearSetTransformAction = function() { - this.clear$Field(5); -}; - - -/** - * Gets the value of the set_page_bounds_action field. - * @return {?sketchology.proto.SetPageBoundsAction} The value. - */ -sketchology.proto.StorageAction.prototype.getSetPageBoundsAction = function() { - return /** @type {?sketchology.proto.SetPageBoundsAction} */ (this.get$Value(6)); -}; - - -/** - * Gets the value of the set_page_bounds_action field or the default value if not set. - * @return {!sketchology.proto.SetPageBoundsAction} The value. - */ -sketchology.proto.StorageAction.prototype.getSetPageBoundsActionOrDefault = function() { - return /** @type {!sketchology.proto.SetPageBoundsAction} */ (this.get$ValueOrDefault(6)); -}; - - -/** - * Sets the value of the set_page_bounds_action field. - * @param {!sketchology.proto.SetPageBoundsAction} value The value. - */ -sketchology.proto.StorageAction.prototype.setSetPageBoundsAction = function(value) { - this.set$Value(6, value); -}; - - -/** - * @return {boolean} Whether the set_page_bounds_action field has a value. - */ -sketchology.proto.StorageAction.prototype.hasSetPageBoundsAction = function() { - return this.has$Value(6); -}; - - -/** - * @return {number} The number of values in the set_page_bounds_action field. - */ -sketchology.proto.StorageAction.prototype.setPageBoundsActionCount = function() { - return this.count$Values(6); -}; - - -/** - * Clears the values in the set_page_bounds_action field. - */ -sketchology.proto.StorageAction.prototype.clearSetPageBoundsAction = function() { - this.clear$Field(6); -}; - - - -/** - * Message Snapshot. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.Snapshot = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.Snapshot, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.Snapshot.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.Snapshot} The cloned message. - * @override - */ -sketchology.proto.Snapshot.prototype.clone; - - -/** - * Gets the value of the page_properties field. - * @return {?sketchology.proto.PageProperties} The value. - */ -sketchology.proto.Snapshot.prototype.getPageProperties = function() { - return /** @type {?sketchology.proto.PageProperties} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the page_properties field or the default value if not set. - * @return {!sketchology.proto.PageProperties} The value. - */ -sketchology.proto.Snapshot.prototype.getPagePropertiesOrDefault = function() { - return /** @type {!sketchology.proto.PageProperties} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the page_properties field. - * @param {!sketchology.proto.PageProperties} value The value. - */ -sketchology.proto.Snapshot.prototype.setPageProperties = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the page_properties field has a value. - */ -sketchology.proto.Snapshot.prototype.hasPageProperties = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the page_properties field. - */ -sketchology.proto.Snapshot.prototype.pagePropertiesCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the page_properties field. - */ -sketchology.proto.Snapshot.prototype.clearPageProperties = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the element field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.ElementBundle} The value. - */ -sketchology.proto.Snapshot.prototype.getElement = function(index) { - return /** @type {?sketchology.proto.ElementBundle} */ (this.get$Value(2, index)); -}; - - -/** - * Gets the value of the element field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.ElementBundle} The value. - */ -sketchology.proto.Snapshot.prototype.getElementOrDefault = function(index) { - return /** @type {!sketchology.proto.ElementBundle} */ (this.get$ValueOrDefault(2, index)); -}; - - -/** - * Adds a value to the element field. - * @param {!sketchology.proto.ElementBundle} value The value to add. - */ -sketchology.proto.Snapshot.prototype.addElement = function(value) { - this.add$Value(2, value); -}; - - -/** - * Returns the array of values in the element field. - * @return {!Array<!sketchology.proto.ElementBundle>} The values in the field. - */ -sketchology.proto.Snapshot.prototype.elementArray = function() { - return /** @type {!Array<!sketchology.proto.ElementBundle>} */ (this.array$Values(2)); -}; - - -/** - * @return {boolean} Whether the element field has a value. - */ -sketchology.proto.Snapshot.prototype.hasElement = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the element field. - */ -sketchology.proto.Snapshot.prototype.elementCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the element field. - */ -sketchology.proto.Snapshot.prototype.clearElement = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the dead_element field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.ElementBundle} The value. - */ -sketchology.proto.Snapshot.prototype.getDeadElement = function(index) { - return /** @type {?sketchology.proto.ElementBundle} */ (this.get$Value(3, index)); -}; - - -/** - * Gets the value of the dead_element field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.ElementBundle} The value. - */ -sketchology.proto.Snapshot.prototype.getDeadElementOrDefault = function(index) { - return /** @type {!sketchology.proto.ElementBundle} */ (this.get$ValueOrDefault(3, index)); -}; - - -/** - * Adds a value to the dead_element field. - * @param {!sketchology.proto.ElementBundle} value The value to add. - */ -sketchology.proto.Snapshot.prototype.addDeadElement = function(value) { - this.add$Value(3, value); -}; - - -/** - * Returns the array of values in the dead_element field. - * @return {!Array<!sketchology.proto.ElementBundle>} The values in the field. - */ -sketchology.proto.Snapshot.prototype.deadElementArray = function() { - return /** @type {!Array<!sketchology.proto.ElementBundle>} */ (this.array$Values(3)); -}; - - -/** - * @return {boolean} Whether the dead_element field has a value. - */ -sketchology.proto.Snapshot.prototype.hasDeadElement = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the dead_element field. - */ -sketchology.proto.Snapshot.prototype.deadElementCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the dead_element field. - */ -sketchology.proto.Snapshot.prototype.clearDeadElement = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the undo_action field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.StorageAction} The value. - */ -sketchology.proto.Snapshot.prototype.getUndoAction = function(index) { - return /** @type {?sketchology.proto.StorageAction} */ (this.get$Value(4, index)); -}; - - -/** - * Gets the value of the undo_action field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.StorageAction} The value. - */ -sketchology.proto.Snapshot.prototype.getUndoActionOrDefault = function(index) { - return /** @type {!sketchology.proto.StorageAction} */ (this.get$ValueOrDefault(4, index)); -}; - - -/** - * Adds a value to the undo_action field. - * @param {!sketchology.proto.StorageAction} value The value to add. - */ -sketchology.proto.Snapshot.prototype.addUndoAction = function(value) { - this.add$Value(4, value); -}; - - -/** - * Returns the array of values in the undo_action field. - * @return {!Array<!sketchology.proto.StorageAction>} The values in the field. - */ -sketchology.proto.Snapshot.prototype.undoActionArray = function() { - return /** @type {!Array<!sketchology.proto.StorageAction>} */ (this.array$Values(4)); -}; - - -/** - * @return {boolean} Whether the undo_action field has a value. - */ -sketchology.proto.Snapshot.prototype.hasUndoAction = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the undo_action field. - */ -sketchology.proto.Snapshot.prototype.undoActionCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the undo_action field. - */ -sketchology.proto.Snapshot.prototype.clearUndoAction = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the redo_action field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.StorageAction} The value. - */ -sketchology.proto.Snapshot.prototype.getRedoAction = function(index) { - return /** @type {?sketchology.proto.StorageAction} */ (this.get$Value(5, index)); -}; - - -/** - * Gets the value of the redo_action field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.StorageAction} The value. - */ -sketchology.proto.Snapshot.prototype.getRedoActionOrDefault = function(index) { - return /** @type {!sketchology.proto.StorageAction} */ (this.get$ValueOrDefault(5, index)); -}; - - -/** - * Adds a value to the redo_action field. - * @param {!sketchology.proto.StorageAction} value The value to add. - */ -sketchology.proto.Snapshot.prototype.addRedoAction = function(value) { - this.add$Value(5, value); -}; - - -/** - * Returns the array of values in the redo_action field. - * @return {!Array<!sketchology.proto.StorageAction>} The values in the field. - */ -sketchology.proto.Snapshot.prototype.redoActionArray = function() { - return /** @type {!Array<!sketchology.proto.StorageAction>} */ (this.array$Values(5)); -}; - - -/** - * @return {boolean} Whether the redo_action field has a value. - */ -sketchology.proto.Snapshot.prototype.hasRedoAction = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the redo_action field. - */ -sketchology.proto.Snapshot.prototype.redoActionCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the redo_action field. - */ -sketchology.proto.Snapshot.prototype.clearRedoAction = function() { - this.clear$Field(5); -}; - - -/** - * Gets the value of the element_state_index field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.ElementState} The value. - */ -sketchology.proto.Snapshot.prototype.getElementStateIndex = function(index) { - return /** @type {?sketchology.proto.ElementState} */ (this.get$Value(6, index)); -}; - - -/** - * Gets the value of the element_state_index field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.ElementState} The value. - */ -sketchology.proto.Snapshot.prototype.getElementStateIndexOrDefault = function(index) { - return /** @type {!sketchology.proto.ElementState} */ (this.get$ValueOrDefault(6, index)); -}; - - -/** - * Adds a value to the element_state_index field. - * @param {!sketchology.proto.ElementState} value The value to add. - */ -sketchology.proto.Snapshot.prototype.addElementStateIndex = function(value) { - this.add$Value(6, value); -}; - - -/** - * Returns the array of values in the element_state_index field. - * @return {!Array<!sketchology.proto.ElementState>} The values in the field. - */ -sketchology.proto.Snapshot.prototype.elementStateIndexArray = function() { - return /** @type {!Array<!sketchology.proto.ElementState>} */ (this.array$Values(6)); -}; - - -/** - * @return {boolean} Whether the element_state_index field has a value. - */ -sketchology.proto.Snapshot.prototype.hasElementStateIndex = function() { - return this.has$Value(6); -}; - - -/** - * @return {number} The number of values in the element_state_index field. - */ -sketchology.proto.Snapshot.prototype.elementStateIndexCount = function() { - return this.count$Values(6); -}; - - -/** - * Clears the values in the element_state_index field. - */ -sketchology.proto.Snapshot.prototype.clearElementStateIndex = function() { - this.clear$Field(6); -}; - - -/** - * Gets the value of the fingerprint field. - * @return {?string} The value. - */ -sketchology.proto.Snapshot.prototype.getFingerprint = function() { - return /** @type {?string} */ (this.get$Value(7)); -}; - - -/** - * Gets the value of the fingerprint field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.Snapshot.prototype.getFingerprintOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(7)); -}; - - -/** - * Sets the value of the fingerprint field. - * @param {string} value The value. - */ -sketchology.proto.Snapshot.prototype.setFingerprint = function(value) { - this.set$Value(7, value); -}; - - -/** - * @return {boolean} Whether the fingerprint field has a value. - */ -sketchology.proto.Snapshot.prototype.hasFingerprint = function() { - return this.has$Value(7); -}; - - -/** - * @return {number} The number of values in the fingerprint field. - */ -sketchology.proto.Snapshot.prototype.fingerprintCount = function() { - return this.count$Values(7); -}; - - -/** - * Clears the values in the fingerprint field. - */ -sketchology.proto.Snapshot.prototype.clearFingerprint = function() { - this.clear$Field(7); -}; - - - -/** - * Message MutationPacket. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.MutationPacket = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.MutationPacket, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.MutationPacket.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.MutationPacket} The cloned message. - * @override - */ -sketchology.proto.MutationPacket.prototype.clone; - - -/** - * Gets the value of the mutation field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.StorageAction} The value. - */ -sketchology.proto.MutationPacket.prototype.getMutation = function(index) { - return /** @type {?sketchology.proto.StorageAction} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the mutation field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.StorageAction} The value. - */ -sketchology.proto.MutationPacket.prototype.getMutationOrDefault = function(index) { - return /** @type {!sketchology.proto.StorageAction} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the mutation field. - * @param {!sketchology.proto.StorageAction} value The value to add. - */ -sketchology.proto.MutationPacket.prototype.addMutation = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the mutation field. - * @return {!Array<!sketchology.proto.StorageAction>} The values in the field. - */ -sketchology.proto.MutationPacket.prototype.mutationArray = function() { - return /** @type {!Array<!sketchology.proto.StorageAction>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the mutation field has a value. - */ -sketchology.proto.MutationPacket.prototype.hasMutation = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the mutation field. - */ -sketchology.proto.MutationPacket.prototype.mutationCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the mutation field. - */ -sketchology.proto.MutationPacket.prototype.clearMutation = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the element field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.ElementBundle} The value. - */ -sketchology.proto.MutationPacket.prototype.getElement = function(index) { - return /** @type {?sketchology.proto.ElementBundle} */ (this.get$Value(2, index)); -}; - - -/** - * Gets the value of the element field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.ElementBundle} The value. - */ -sketchology.proto.MutationPacket.prototype.getElementOrDefault = function(index) { - return /** @type {!sketchology.proto.ElementBundle} */ (this.get$ValueOrDefault(2, index)); -}; - - -/** - * Adds a value to the element field. - * @param {!sketchology.proto.ElementBundle} value The value to add. - */ -sketchology.proto.MutationPacket.prototype.addElement = function(value) { - this.add$Value(2, value); -}; - - -/** - * Returns the array of values in the element field. - * @return {!Array<!sketchology.proto.ElementBundle>} The values in the field. - */ -sketchology.proto.MutationPacket.prototype.elementArray = function() { - return /** @type {!Array<!sketchology.proto.ElementBundle>} */ (this.array$Values(2)); -}; - - -/** - * @return {boolean} Whether the element field has a value. - */ -sketchology.proto.MutationPacket.prototype.hasElement = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the element field. - */ -sketchology.proto.MutationPacket.prototype.elementCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the element field. - */ -sketchology.proto.MutationPacket.prototype.clearElement = function() { - this.clear$Field(2); -}; - - -/** @override */ -sketchology.proto.Color.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.Color.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'Color', - fullName: 'sketchology.proto.Color' - }, - 1: { - name: 'argb', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - } - }; - sketchology.proto.Color.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.Color, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.Color.getDescriptor = - sketchology.proto.Color.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.BackgroundColor.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.BackgroundColor.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'BackgroundColor', - fullName: 'sketchology.proto.BackgroundColor' - }, - 1: { - name: 'rgba', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - } - }; - sketchology.proto.BackgroundColor.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.BackgroundColor, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.BackgroundColor.getDescriptor = - sketchology.proto.BackgroundColor.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.PageProperties.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.PageProperties.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'PageProperties', - fullName: 'sketchology.proto.PageProperties' - }, - 1: { - name: 'background_color', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Color - }, - 2: { - name: 'background_image', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.BackgroundImageInfo - }, - 3: { - name: 'bounds', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Rect - }, - 4: { - name: 'border', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Border - } - }; - sketchology.proto.PageProperties.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.PageProperties, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.PageProperties.getDescriptor = - sketchology.proto.PageProperties.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.AddAction.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.AddAction.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'AddAction', - fullName: 'sketchology.proto.AddAction' - }, - 1: { - name: 'uuid', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 2: { - name: 'below_element_with_uuid', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - } - }; - sketchology.proto.AddAction.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.AddAction, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.AddAction.getDescriptor = - sketchology.proto.AddAction.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.RemoveAction.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.RemoveAction.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'RemoveAction', - fullName: 'sketchology.proto.RemoveAction' - }, - 1: { - name: 'uuid', - repeated: true, - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 2: { - name: 'was_below_uuid', - repeated: true, - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - } - }; - sketchology.proto.RemoveAction.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.RemoveAction, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.RemoveAction.getDescriptor = - sketchology.proto.RemoveAction.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ClearAction.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ClearAction.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ClearAction', - fullName: 'sketchology.proto.ClearAction' - }, - 1: { - name: 'uuid', - repeated: true, - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - } - }; - sketchology.proto.ClearAction.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ClearAction, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ClearAction.getDescriptor = - sketchology.proto.ClearAction.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ReplaceAction.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ReplaceAction.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ReplaceAction', - fullName: 'sketchology.proto.ReplaceAction' - }, - 1: { - name: 'uuid_add', - repeated: true, - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 2: { - name: 'below_element_with_uuid', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 3: { - name: 'uuid_remove', - repeated: true, - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 4: { - name: 'was_below_uuid', - repeated: true, - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - } - }; - sketchology.proto.ReplaceAction.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ReplaceAction, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ReplaceAction.getDescriptor = - sketchology.proto.ReplaceAction.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.SetTransformAction.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.SetTransformAction.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'SetTransformAction', - fullName: 'sketchology.proto.SetTransformAction' - }, - 1: { - name: 'uuid', - repeated: true, - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 2: { - name: 'from_transform', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.AffineTransform - }, - 3: { - name: 'to_transform', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.AffineTransform - } - }; - sketchology.proto.SetTransformAction.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.SetTransformAction, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.SetTransformAction.getDescriptor = - sketchology.proto.SetTransformAction.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.SetPageBoundsAction.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.SetPageBoundsAction.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'SetPageBoundsAction', - fullName: 'sketchology.proto.SetPageBoundsAction' - }, - 1: { - name: 'old_bounds', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Rect - }, - 2: { - name: 'new_bounds', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Rect - } - }; - sketchology.proto.SetPageBoundsAction.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.SetPageBoundsAction, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.SetPageBoundsAction.getDescriptor = - sketchology.proto.SetPageBoundsAction.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.StorageAction.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.StorageAction.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'StorageAction', - fullName: 'sketchology.proto.StorageAction' - }, - 1: { - name: 'add_action', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.AddAction - }, - 2: { - name: 'remove_action', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.RemoveAction - }, - 3: { - name: 'clear_action', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ClearAction - }, - 4: { - name: 'replace_action', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ReplaceAction - }, - 5: { - name: 'set_transform_action', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.SetTransformAction - }, - 6: { - name: 'set_page_bounds_action', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.SetPageBoundsAction - } - }; - sketchology.proto.StorageAction.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.StorageAction, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.StorageAction.getDescriptor = - sketchology.proto.StorageAction.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.Snapshot.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.Snapshot.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'Snapshot', - fullName: 'sketchology.proto.Snapshot' - }, - 1: { - name: 'page_properties', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.PageProperties - }, - 2: { - name: 'element', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ElementBundle - }, - 3: { - name: 'dead_element', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ElementBundle - }, - 4: { - name: 'undo_action', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.StorageAction - }, - 5: { - name: 'redo_action', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.StorageAction - }, - 6: { - name: 'element_state_index', - repeated: true, - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.ElementState.ALIVE, - type: sketchology.proto.ElementState - }, - 7: { - name: 'fingerprint', - fieldType: goog.proto2.Message.FieldType.UINT64, - type: String - } - }; - sketchology.proto.Snapshot.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.Snapshot, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.Snapshot.getDescriptor = - sketchology.proto.Snapshot.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.MutationPacket.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.MutationPacket.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'MutationPacket', - fullName: 'sketchology.proto.MutationPacket' - }, - 1: { - name: 'mutation', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.StorageAction - }, - 2: { - name: 'element', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ElementBundle - } - }; - sketchology.proto.MutationPacket.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.MutationPacket, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.MutationPacket.getDescriptor = - sketchology.proto.MutationPacket.prototype.getDescriptor;
diff --git a/third_party/ink/sketchology/proto/elements.pb.js b/third_party/ink/sketchology/proto/elements.pb.js deleted file mode 100644 index 4c0de6a6..0000000 --- a/third_party/ink/sketchology/proto/elements.pb.js +++ /dev/null
@@ -1,3976 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Protocol Buffer 2 Copyright 2008 Google Inc. -// All other code copyright its respective owners. - -/** - * @fileoverview Generated Protocol Buffer code for file - * third_party/sketchology/proto/elements.proto. - * Generated by //net/proto2/compiler/public:protocol_compiler. - * @suppress {messageConventions} - */ - -goog.provide('sketchology.proto.CallbackFlags'); -goog.provide('sketchology.proto.SourceDetails'); -goog.provide('sketchology.proto.SourceDetails.Origin'); -goog.provide('sketchology.proto.BackgroundImageInfo'); -goog.provide('sketchology.proto.Border'); -goog.provide('sketchology.proto.LOD'); -goog.provide('sketchology.proto.Stroke'); -goog.provide('sketchology.proto.UncompressedStroke'); -goog.provide('sketchology.proto.AffineTransform'); -goog.provide('sketchology.proto.Element'); -goog.provide('sketchology.proto.ElementAttributes'); -goog.provide('sketchology.proto.UncompressedElement'); -goog.provide('sketchology.proto.ElementMutation'); -goog.provide('sketchology.proto.ElementIdList'); -goog.provide('sketchology.proto.Point'); -goog.provide('sketchology.proto.ElementBundle'); -goog.provide('sketchology.proto.Path'); -goog.provide('sketchology.proto.Path.SegmentType'); -goog.provide('sketchology.proto.Path.EndCapType'); -goog.provide('sketchology.proto.ShaderType'); - -goog.require('goog.proto2.Message'); -goog.require('sketchology.proto.Rect'); - - -/** - * Enumeration ShaderType. - * @enum {number} - */ -sketchology.proto.ShaderType = { - NONE: 0, - VERTEX_COLORED: 1, - SOLID_COLORED: 2, - ERASE: 3, - VERTEX_TEXTURED: 4 -}; - - - -/** - * Message CallbackFlags. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.CallbackFlags = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.CallbackFlags, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.CallbackFlags.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.CallbackFlags} The cloned message. - * @override - */ -sketchology.proto.CallbackFlags.prototype.clone; - - -/** - * Gets the value of the mesh_data_ctm field. - * @return {?boolean} The value. - */ -sketchology.proto.CallbackFlags.prototype.getMeshDataCtm = function() { - return /** @type {?boolean} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the mesh_data_ctm field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.CallbackFlags.prototype.getMeshDataCtmOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the mesh_data_ctm field. - * @param {boolean} value The value. - */ -sketchology.proto.CallbackFlags.prototype.setMeshDataCtm = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the mesh_data_ctm field has a value. - */ -sketchology.proto.CallbackFlags.prototype.hasMeshDataCtm = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the mesh_data_ctm field. - */ -sketchology.proto.CallbackFlags.prototype.meshDataCtmCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the mesh_data_ctm field. - */ -sketchology.proto.CallbackFlags.prototype.clearMeshDataCtm = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the uncompressed_outline field. - * @return {?boolean} The value. - */ -sketchology.proto.CallbackFlags.prototype.getUncompressedOutline = function() { - return /** @type {?boolean} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the uncompressed_outline field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.CallbackFlags.prototype.getUncompressedOutlineOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the uncompressed_outline field. - * @param {boolean} value The value. - */ -sketchology.proto.CallbackFlags.prototype.setUncompressedOutline = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the uncompressed_outline field has a value. - */ -sketchology.proto.CallbackFlags.prototype.hasUncompressedOutline = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the uncompressed_outline field. - */ -sketchology.proto.CallbackFlags.prototype.uncompressedOutlineCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the uncompressed_outline field. - */ -sketchology.proto.CallbackFlags.prototype.clearUncompressedOutline = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the compressed_input_points field. - * @return {?boolean} The value. - */ -sketchology.proto.CallbackFlags.prototype.getCompressedInputPoints = function() { - return /** @type {?boolean} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the compressed_input_points field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.CallbackFlags.prototype.getCompressedInputPointsOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the compressed_input_points field. - * @param {boolean} value The value. - */ -sketchology.proto.CallbackFlags.prototype.setCompressedInputPoints = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the compressed_input_points field has a value. - */ -sketchology.proto.CallbackFlags.prototype.hasCompressedInputPoints = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the compressed_input_points field. - */ -sketchology.proto.CallbackFlags.prototype.compressedInputPointsCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the compressed_input_points field. - */ -sketchology.proto.CallbackFlags.prototype.clearCompressedInputPoints = function() { - this.clear$Field(3); -}; - - - -/** - * Message SourceDetails. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.SourceDetails = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.SourceDetails, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.SourceDetails.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.SourceDetails} The cloned message. - * @override - */ -sketchology.proto.SourceDetails.prototype.clone; - - -/** - * Gets the value of the origin field. - * @return {?sketchology.proto.SourceDetails.Origin} The value. - */ -sketchology.proto.SourceDetails.prototype.getOrigin = function() { - return /** @type {?sketchology.proto.SourceDetails.Origin} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the origin field or the default value if not set. - * @return {!sketchology.proto.SourceDetails.Origin} The value. - */ -sketchology.proto.SourceDetails.prototype.getOriginOrDefault = function() { - return /** @type {!sketchology.proto.SourceDetails.Origin} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the origin field. - * @param {!sketchology.proto.SourceDetails.Origin} value The value. - */ -sketchology.proto.SourceDetails.prototype.setOrigin = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the origin field has a value. - */ -sketchology.proto.SourceDetails.prototype.hasOrigin = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the origin field. - */ -sketchology.proto.SourceDetails.prototype.originCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the origin field. - */ -sketchology.proto.SourceDetails.prototype.clearOrigin = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the host_source_details field. - * @return {?number} The value. - */ -sketchology.proto.SourceDetails.prototype.getHostSourceDetails = function() { - return /** @type {?number} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the host_source_details field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SourceDetails.prototype.getHostSourceDetailsOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the host_source_details field. - * @param {number} value The value. - */ -sketchology.proto.SourceDetails.prototype.setHostSourceDetails = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the host_source_details field has a value. - */ -sketchology.proto.SourceDetails.prototype.hasHostSourceDetails = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the host_source_details field. - */ -sketchology.proto.SourceDetails.prototype.hostSourceDetailsCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the host_source_details field. - */ -sketchology.proto.SourceDetails.prototype.clearHostSourceDetails = function() { - this.clear$Field(2); -}; - - -/** - * Enumeration Origin. - * @enum {number} - */ -sketchology.proto.SourceDetails.Origin = { - UNKNOWN: 0, - ENGINE: 1, - HOST: 2 -}; - - - -/** - * Message BackgroundImageInfo. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.BackgroundImageInfo = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.BackgroundImageInfo, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.BackgroundImageInfo.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.BackgroundImageInfo} The cloned message. - * @override - */ -sketchology.proto.BackgroundImageInfo.prototype.clone; - - -/** - * Gets the value of the uri field. - * @return {?string} The value. - */ -sketchology.proto.BackgroundImageInfo.prototype.getUri = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the uri field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.BackgroundImageInfo.prototype.getUriOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the uri field. - * @param {string} value The value. - */ -sketchology.proto.BackgroundImageInfo.prototype.setUri = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the uri field has a value. - */ -sketchology.proto.BackgroundImageInfo.prototype.hasUri = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uri field. - */ -sketchology.proto.BackgroundImageInfo.prototype.uriCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uri field. - */ -sketchology.proto.BackgroundImageInfo.prototype.clearUri = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the bounds field. - * @return {?sketchology.proto.Rect} The value. - */ -sketchology.proto.BackgroundImageInfo.prototype.getBounds = function() { - return /** @type {?sketchology.proto.Rect} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the bounds field or the default value if not set. - * @return {!sketchology.proto.Rect} The value. - */ -sketchology.proto.BackgroundImageInfo.prototype.getBoundsOrDefault = function() { - return /** @type {!sketchology.proto.Rect} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the bounds field. - * @param {!sketchology.proto.Rect} value The value. - */ -sketchology.proto.BackgroundImageInfo.prototype.setBounds = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the bounds field has a value. - */ -sketchology.proto.BackgroundImageInfo.prototype.hasBounds = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the bounds field. - */ -sketchology.proto.BackgroundImageInfo.prototype.boundsCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the bounds field. - */ -sketchology.proto.BackgroundImageInfo.prototype.clearBounds = function() { - this.clear$Field(3); -}; - - - -/** - * Message Border. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.Border = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.Border, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.Border.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.Border} The cloned message. - * @override - */ -sketchology.proto.Border.prototype.clone; - - -/** - * Gets the value of the uri field. - * @return {?string} The value. - */ -sketchology.proto.Border.prototype.getUri = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the uri field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.Border.prototype.getUriOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the uri field. - * @param {string} value The value. - */ -sketchology.proto.Border.prototype.setUri = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the uri field has a value. - */ -sketchology.proto.Border.prototype.hasUri = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uri field. - */ -sketchology.proto.Border.prototype.uriCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uri field. - */ -sketchology.proto.Border.prototype.clearUri = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the scale field. - * @return {?number} The value. - */ -sketchology.proto.Border.prototype.getScale = function() { - return /** @type {?number} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the scale field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Border.prototype.getScaleOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the scale field. - * @param {number} value The value. - */ -sketchology.proto.Border.prototype.setScale = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the scale field has a value. - */ -sketchology.proto.Border.prototype.hasScale = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the scale field. - */ -sketchology.proto.Border.prototype.scaleCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the scale field. - */ -sketchology.proto.Border.prototype.clearScale = function() { - this.clear$Field(2); -}; - - - -/** - * Message LOD. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.LOD = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.LOD, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.LOD.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.LOD} The cloned message. - * @override - */ -sketchology.proto.LOD.prototype.clone; - - -/** - * Gets the value of the max_coverage field. - * @return {?number} The value. - */ -sketchology.proto.LOD.prototype.getMaxCoverage = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the max_coverage field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.LOD.prototype.getMaxCoverageOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the max_coverage field. - * @param {number} value The value. - */ -sketchology.proto.LOD.prototype.setMaxCoverage = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the max_coverage field has a value. - */ -sketchology.proto.LOD.prototype.hasMaxCoverage = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the max_coverage field. - */ -sketchology.proto.LOD.prototype.maxCoverageCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the max_coverage field. - */ -sketchology.proto.LOD.prototype.clearMaxCoverage = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the ctm_blob field. - * @return {?string} The value. - */ -sketchology.proto.LOD.prototype.getCtmBlob = function() { - return /** @type {?string} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the ctm_blob field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.LOD.prototype.getCtmBlobOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the ctm_blob field. - * @param {string} value The value. - */ -sketchology.proto.LOD.prototype.setCtmBlob = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the ctm_blob field has a value. - */ -sketchology.proto.LOD.prototype.hasCtmBlob = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the ctm_blob field. - */ -sketchology.proto.LOD.prototype.ctmBlobCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the ctm_blob field. - */ -sketchology.proto.LOD.prototype.clearCtmBlob = function() { - this.clear$Field(2); -}; - - - -/** - * Message Stroke. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.Stroke = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.Stroke, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.Stroke.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.Stroke} The cloned message. - * @override - */ -sketchology.proto.Stroke.prototype.clone; - - -/** - * Gets the value of the shader_type field. - * @return {?sketchology.proto.ShaderType} The value. - */ -sketchology.proto.Stroke.prototype.getShaderType = function() { - return /** @type {?sketchology.proto.ShaderType} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the shader_type field or the default value if not set. - * @return {!sketchology.proto.ShaderType} The value. - */ -sketchology.proto.Stroke.prototype.getShaderTypeOrDefault = function() { - return /** @type {!sketchology.proto.ShaderType} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the shader_type field. - * @param {!sketchology.proto.ShaderType} value The value. - */ -sketchology.proto.Stroke.prototype.setShaderType = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the shader_type field has a value. - */ -sketchology.proto.Stroke.prototype.hasShaderType = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the shader_type field. - */ -sketchology.proto.Stroke.prototype.shaderTypeCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the shader_type field. - */ -sketchology.proto.Stroke.prototype.clearShaderType = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the lod field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.LOD} The value. - */ -sketchology.proto.Stroke.prototype.getLod = function(index) { - return /** @type {?sketchology.proto.LOD} */ (this.get$Value(3, index)); -}; - - -/** - * Gets the value of the lod field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.LOD} The value. - */ -sketchology.proto.Stroke.prototype.getLodOrDefault = function(index) { - return /** @type {!sketchology.proto.LOD} */ (this.get$ValueOrDefault(3, index)); -}; - - -/** - * Adds a value to the lod field. - * @param {!sketchology.proto.LOD} value The value to add. - */ -sketchology.proto.Stroke.prototype.addLod = function(value) { - this.add$Value(3, value); -}; - - -/** - * Returns the array of values in the lod field. - * @return {!Array<!sketchology.proto.LOD>} The values in the field. - */ -sketchology.proto.Stroke.prototype.lodArray = function() { - return /** @type {!Array<!sketchology.proto.LOD>} */ (this.array$Values(3)); -}; - - -/** - * @return {boolean} Whether the lod field has a value. - */ -sketchology.proto.Stroke.prototype.hasLod = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the lod field. - */ -sketchology.proto.Stroke.prototype.lodCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the lod field. - */ -sketchology.proto.Stroke.prototype.clearLod = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the abgr field. - * @return {?number} The value. - */ -sketchology.proto.Stroke.prototype.getAbgr = function() { - return /** @type {?number} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the abgr field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Stroke.prototype.getAbgrOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the abgr field. - * @param {number} value The value. - */ -sketchology.proto.Stroke.prototype.setAbgr = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the abgr field has a value. - */ -sketchology.proto.Stroke.prototype.hasAbgr = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the abgr field. - */ -sketchology.proto.Stroke.prototype.abgrCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the abgr field. - */ -sketchology.proto.Stroke.prototype.clearAbgr = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the point_x field at the index given. - * @param {number} index The index to lookup. - * @return {?number} The value. - */ -sketchology.proto.Stroke.prototype.getPointX = function(index) { - return /** @type {?number} */ (this.get$Value(5, index)); -}; - - -/** - * Gets the value of the point_x field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {number} The value. - */ -sketchology.proto.Stroke.prototype.getPointXOrDefault = function(index) { - return /** @type {number} */ (this.get$ValueOrDefault(5, index)); -}; - - -/** - * Adds a value to the point_x field. - * @param {number} value The value to add. - */ -sketchology.proto.Stroke.prototype.addPointX = function(value) { - this.add$Value(5, value); -}; - - -/** - * Returns the array of values in the point_x field. - * @return {!Array<number>} The values in the field. - */ -sketchology.proto.Stroke.prototype.pointXArray = function() { - return /** @type {!Array<number>} */ (this.array$Values(5)); -}; - - -/** - * @return {boolean} Whether the point_x field has a value. - */ -sketchology.proto.Stroke.prototype.hasPointX = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the point_x field. - */ -sketchology.proto.Stroke.prototype.pointXCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the point_x field. - */ -sketchology.proto.Stroke.prototype.clearPointX = function() { - this.clear$Field(5); -}; - - -/** - * Gets the value of the point_y field at the index given. - * @param {number} index The index to lookup. - * @return {?number} The value. - */ -sketchology.proto.Stroke.prototype.getPointY = function(index) { - return /** @type {?number} */ (this.get$Value(6, index)); -}; - - -/** - * Gets the value of the point_y field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {number} The value. - */ -sketchology.proto.Stroke.prototype.getPointYOrDefault = function(index) { - return /** @type {number} */ (this.get$ValueOrDefault(6, index)); -}; - - -/** - * Adds a value to the point_y field. - * @param {number} value The value to add. - */ -sketchology.proto.Stroke.prototype.addPointY = function(value) { - this.add$Value(6, value); -}; - - -/** - * Returns the array of values in the point_y field. - * @return {!Array<number>} The values in the field. - */ -sketchology.proto.Stroke.prototype.pointYArray = function() { - return /** @type {!Array<number>} */ (this.array$Values(6)); -}; - - -/** - * @return {boolean} Whether the point_y field has a value. - */ -sketchology.proto.Stroke.prototype.hasPointY = function() { - return this.has$Value(6); -}; - - -/** - * @return {number} The number of values in the point_y field. - */ -sketchology.proto.Stroke.prototype.pointYCount = function() { - return this.count$Values(6); -}; - - -/** - * Clears the values in the point_y field. - */ -sketchology.proto.Stroke.prototype.clearPointY = function() { - this.clear$Field(6); -}; - - -/** - * Gets the value of the point_t_ms field at the index given. - * @param {number} index The index to lookup. - * @return {?number} The value. - */ -sketchology.proto.Stroke.prototype.getPointTMs = function(index) { - return /** @type {?number} */ (this.get$Value(7, index)); -}; - - -/** - * Gets the value of the point_t_ms field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {number} The value. - */ -sketchology.proto.Stroke.prototype.getPointTMsOrDefault = function(index) { - return /** @type {number} */ (this.get$ValueOrDefault(7, index)); -}; - - -/** - * Adds a value to the point_t_ms field. - * @param {number} value The value to add. - */ -sketchology.proto.Stroke.prototype.addPointTMs = function(value) { - this.add$Value(7, value); -}; - - -/** - * Returns the array of values in the point_t_ms field. - * @return {!Array<number>} The values in the field. - */ -sketchology.proto.Stroke.prototype.pointTMsArray = function() { - return /** @type {!Array<number>} */ (this.array$Values(7)); -}; - - -/** - * @return {boolean} Whether the point_t_ms field has a value. - */ -sketchology.proto.Stroke.prototype.hasPointTMs = function() { - return this.has$Value(7); -}; - - -/** - * @return {number} The number of values in the point_t_ms field. - */ -sketchology.proto.Stroke.prototype.pointTMsCount = function() { - return this.count$Values(7); -}; - - -/** - * Clears the values in the point_t_ms field. - */ -sketchology.proto.Stroke.prototype.clearPointTMs = function() { - this.clear$Field(7); -}; - - -/** - * Gets the value of the deprecated_transform field. - * @return {?sketchology.proto.AffineTransform} The value. - */ -sketchology.proto.Stroke.prototype.getDeprecatedTransform = function() { - return /** @type {?sketchology.proto.AffineTransform} */ (this.get$Value(8)); -}; - - -/** - * Gets the value of the deprecated_transform field or the default value if not set. - * @return {!sketchology.proto.AffineTransform} The value. - */ -sketchology.proto.Stroke.prototype.getDeprecatedTransformOrDefault = function() { - return /** @type {!sketchology.proto.AffineTransform} */ (this.get$ValueOrDefault(8)); -}; - - -/** - * Sets the value of the deprecated_transform field. - * @param {!sketchology.proto.AffineTransform} value The value. - */ -sketchology.proto.Stroke.prototype.setDeprecatedTransform = function(value) { - this.set$Value(8, value); -}; - - -/** - * @return {boolean} Whether the deprecated_transform field has a value. - */ -sketchology.proto.Stroke.prototype.hasDeprecatedTransform = function() { - return this.has$Value(8); -}; - - -/** - * @return {number} The number of values in the deprecated_transform field. - */ -sketchology.proto.Stroke.prototype.deprecatedTransformCount = function() { - return this.count$Values(8); -}; - - -/** - * Clears the values in the deprecated_transform field. - */ -sketchology.proto.Stroke.prototype.clearDeprecatedTransform = function() { - this.clear$Field(8); -}; - - -/** - * Gets the value of the start_time_ms field. - * @return {?string} The value. - */ -sketchology.proto.Stroke.prototype.getStartTimeMs = function() { - return /** @type {?string} */ (this.get$Value(9)); -}; - - -/** - * Gets the value of the start_time_ms field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.Stroke.prototype.getStartTimeMsOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(9)); -}; - - -/** - * Sets the value of the start_time_ms field. - * @param {string} value The value. - */ -sketchology.proto.Stroke.prototype.setStartTimeMs = function(value) { - this.set$Value(9, value); -}; - - -/** - * @return {boolean} Whether the start_time_ms field has a value. - */ -sketchology.proto.Stroke.prototype.hasStartTimeMs = function() { - return this.has$Value(9); -}; - - -/** - * @return {number} The number of values in the start_time_ms field. - */ -sketchology.proto.Stroke.prototype.startTimeMsCount = function() { - return this.count$Values(9); -}; - - -/** - * Clears the values in the start_time_ms field. - */ -sketchology.proto.Stroke.prototype.clearStartTimeMs = function() { - this.clear$Field(9); -}; - - - -/** - * Message UncompressedStroke. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.UncompressedStroke = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.UncompressedStroke, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.UncompressedStroke.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.UncompressedStroke} The cloned message. - * @override - */ -sketchology.proto.UncompressedStroke.prototype.clone; - - -/** - * Gets the value of the outline field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.Point} The value. - */ -sketchology.proto.UncompressedStroke.prototype.getOutline = function(index) { - return /** @type {?sketchology.proto.Point} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the outline field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.Point} The value. - */ -sketchology.proto.UncompressedStroke.prototype.getOutlineOrDefault = function(index) { - return /** @type {!sketchology.proto.Point} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the outline field. - * @param {!sketchology.proto.Point} value The value to add. - */ -sketchology.proto.UncompressedStroke.prototype.addOutline = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the outline field. - * @return {!Array<!sketchology.proto.Point>} The values in the field. - */ -sketchology.proto.UncompressedStroke.prototype.outlineArray = function() { - return /** @type {!Array<!sketchology.proto.Point>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the outline field has a value. - */ -sketchology.proto.UncompressedStroke.prototype.hasOutline = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the outline field. - */ -sketchology.proto.UncompressedStroke.prototype.outlineCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the outline field. - */ -sketchology.proto.UncompressedStroke.prototype.clearOutline = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the rgba field. - * @return {?number} The value. - */ -sketchology.proto.UncompressedStroke.prototype.getRgba = function() { - return /** @type {?number} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the rgba field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.UncompressedStroke.prototype.getRgbaOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the rgba field. - * @param {number} value The value. - */ -sketchology.proto.UncompressedStroke.prototype.setRgba = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the rgba field has a value. - */ -sketchology.proto.UncompressedStroke.prototype.hasRgba = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the rgba field. - */ -sketchology.proto.UncompressedStroke.prototype.rgbaCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the rgba field. - */ -sketchology.proto.UncompressedStroke.prototype.clearRgba = function() { - this.clear$Field(2); -}; - - - -/** - * Message AffineTransform. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.AffineTransform = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.AffineTransform, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.AffineTransform.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.AffineTransform} The cloned message. - * @override - */ -sketchology.proto.AffineTransform.prototype.clone; - - -/** - * Gets the value of the tx field. - * @return {?number} The value. - */ -sketchology.proto.AffineTransform.prototype.getTx = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the tx field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.AffineTransform.prototype.getTxOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the tx field. - * @param {number} value The value. - */ -sketchology.proto.AffineTransform.prototype.setTx = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the tx field has a value. - */ -sketchology.proto.AffineTransform.prototype.hasTx = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the tx field. - */ -sketchology.proto.AffineTransform.prototype.txCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the tx field. - */ -sketchology.proto.AffineTransform.prototype.clearTx = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the ty field. - * @return {?number} The value. - */ -sketchology.proto.AffineTransform.prototype.getTy = function() { - return /** @type {?number} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the ty field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.AffineTransform.prototype.getTyOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the ty field. - * @param {number} value The value. - */ -sketchology.proto.AffineTransform.prototype.setTy = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the ty field has a value. - */ -sketchology.proto.AffineTransform.prototype.hasTy = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the ty field. - */ -sketchology.proto.AffineTransform.prototype.tyCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the ty field. - */ -sketchology.proto.AffineTransform.prototype.clearTy = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the scale_x field. - * @return {?number} The value. - */ -sketchology.proto.AffineTransform.prototype.getScaleX = function() { - return /** @type {?number} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the scale_x field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.AffineTransform.prototype.getScaleXOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the scale_x field. - * @param {number} value The value. - */ -sketchology.proto.AffineTransform.prototype.setScaleX = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the scale_x field has a value. - */ -sketchology.proto.AffineTransform.prototype.hasScaleX = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the scale_x field. - */ -sketchology.proto.AffineTransform.prototype.scaleXCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the scale_x field. - */ -sketchology.proto.AffineTransform.prototype.clearScaleX = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the scale_y field. - * @return {?number} The value. - */ -sketchology.proto.AffineTransform.prototype.getScaleY = function() { - return /** @type {?number} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the scale_y field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.AffineTransform.prototype.getScaleYOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the scale_y field. - * @param {number} value The value. - */ -sketchology.proto.AffineTransform.prototype.setScaleY = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the scale_y field has a value. - */ -sketchology.proto.AffineTransform.prototype.hasScaleY = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the scale_y field. - */ -sketchology.proto.AffineTransform.prototype.scaleYCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the scale_y field. - */ -sketchology.proto.AffineTransform.prototype.clearScaleY = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the rotation_radians field. - * @return {?number} The value. - */ -sketchology.proto.AffineTransform.prototype.getRotationRadians = function() { - return /** @type {?number} */ (this.get$Value(5)); -}; - - -/** - * Gets the value of the rotation_radians field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.AffineTransform.prototype.getRotationRadiansOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(5)); -}; - - -/** - * Sets the value of the rotation_radians field. - * @param {number} value The value. - */ -sketchology.proto.AffineTransform.prototype.setRotationRadians = function(value) { - this.set$Value(5, value); -}; - - -/** - * @return {boolean} Whether the rotation_radians field has a value. - */ -sketchology.proto.AffineTransform.prototype.hasRotationRadians = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the rotation_radians field. - */ -sketchology.proto.AffineTransform.prototype.rotationRadiansCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the rotation_radians field. - */ -sketchology.proto.AffineTransform.prototype.clearRotationRadians = function() { - this.clear$Field(5); -}; - - - -/** - * Message Element. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.Element = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.Element, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.Element.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.Element} The cloned message. - * @override - */ -sketchology.proto.Element.prototype.clone; - - -/** - * Gets the value of the deprecated_uuid field. - * @return {?string} The value. - */ -sketchology.proto.Element.prototype.getDeprecatedUuid = function() { - return /** @type {?string} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the deprecated_uuid field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.Element.prototype.getDeprecatedUuidOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the deprecated_uuid field. - * @param {string} value The value. - */ -sketchology.proto.Element.prototype.setDeprecatedUuid = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the deprecated_uuid field has a value. - */ -sketchology.proto.Element.prototype.hasDeprecatedUuid = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the deprecated_uuid field. - */ -sketchology.proto.Element.prototype.deprecatedUuidCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the deprecated_uuid field. - */ -sketchology.proto.Element.prototype.clearDeprecatedUuid = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the minimum_serializer_version field. - * @return {?number} The value. - */ -sketchology.proto.Element.prototype.getMinimumSerializerVersion = function() { - return /** @type {?number} */ (this.get$Value(5)); -}; - - -/** - * Gets the value of the minimum_serializer_version field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Element.prototype.getMinimumSerializerVersionOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(5)); -}; - - -/** - * Sets the value of the minimum_serializer_version field. - * @param {number} value The value. - */ -sketchology.proto.Element.prototype.setMinimumSerializerVersion = function(value) { - this.set$Value(5, value); -}; - - -/** - * @return {boolean} Whether the minimum_serializer_version field has a value. - */ -sketchology.proto.Element.prototype.hasMinimumSerializerVersion = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the minimum_serializer_version field. - */ -sketchology.proto.Element.prototype.minimumSerializerVersionCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the minimum_serializer_version field. - */ -sketchology.proto.Element.prototype.clearMinimumSerializerVersion = function() { - this.clear$Field(5); -}; - - -/** - * Gets the value of the stroke field. - * @return {?sketchology.proto.Stroke} The value. - */ -sketchology.proto.Element.prototype.getStroke = function() { - return /** @type {?sketchology.proto.Stroke} */ (this.get$Value(6)); -}; - - -/** - * Gets the value of the stroke field or the default value if not set. - * @return {!sketchology.proto.Stroke} The value. - */ -sketchology.proto.Element.prototype.getStrokeOrDefault = function() { - return /** @type {!sketchology.proto.Stroke} */ (this.get$ValueOrDefault(6)); -}; - - -/** - * Sets the value of the stroke field. - * @param {!sketchology.proto.Stroke} value The value. - */ -sketchology.proto.Element.prototype.setStroke = function(value) { - this.set$Value(6, value); -}; - - -/** - * @return {boolean} Whether the stroke field has a value. - */ -sketchology.proto.Element.prototype.hasStroke = function() { - return this.has$Value(6); -}; - - -/** - * @return {number} The number of values in the stroke field. - */ -sketchology.proto.Element.prototype.strokeCount = function() { - return this.count$Values(6); -}; - - -/** - * Clears the values in the stroke field. - */ -sketchology.proto.Element.prototype.clearStroke = function() { - this.clear$Field(6); -}; - - -/** - * Gets the value of the path field. - * @return {?sketchology.proto.Path} The value. - */ -sketchology.proto.Element.prototype.getPath = function() { - return /** @type {?sketchology.proto.Path} */ (this.get$Value(9)); -}; - - -/** - * Gets the value of the path field or the default value if not set. - * @return {!sketchology.proto.Path} The value. - */ -sketchology.proto.Element.prototype.getPathOrDefault = function() { - return /** @type {!sketchology.proto.Path} */ (this.get$ValueOrDefault(9)); -}; - - -/** - * Sets the value of the path field. - * @param {!sketchology.proto.Path} value The value. - */ -sketchology.proto.Element.prototype.setPath = function(value) { - this.set$Value(9, value); -}; - - -/** - * @return {boolean} Whether the path field has a value. - */ -sketchology.proto.Element.prototype.hasPath = function() { - return this.has$Value(9); -}; - - -/** - * @return {number} The number of values in the path field. - */ -sketchology.proto.Element.prototype.pathCount = function() { - return this.count$Values(9); -}; - - -/** - * Clears the values in the path field. - */ -sketchology.proto.Element.prototype.clearPath = function() { - this.clear$Field(9); -}; - - -/** - * Gets the value of the attributes field. - * @return {?sketchology.proto.ElementAttributes} The value. - */ -sketchology.proto.Element.prototype.getAttributes = function() { - return /** @type {?sketchology.proto.ElementAttributes} */ (this.get$Value(10)); -}; - - -/** - * Gets the value of the attributes field or the default value if not set. - * @return {!sketchology.proto.ElementAttributes} The value. - */ -sketchology.proto.Element.prototype.getAttributesOrDefault = function() { - return /** @type {!sketchology.proto.ElementAttributes} */ (this.get$ValueOrDefault(10)); -}; - - -/** - * Sets the value of the attributes field. - * @param {!sketchology.proto.ElementAttributes} value The value. - */ -sketchology.proto.Element.prototype.setAttributes = function(value) { - this.set$Value(10, value); -}; - - -/** - * @return {boolean} Whether the attributes field has a value. - */ -sketchology.proto.Element.prototype.hasAttributes = function() { - return this.has$Value(10); -}; - - -/** - * @return {number} The number of values in the attributes field. - */ -sketchology.proto.Element.prototype.attributesCount = function() { - return this.count$Values(10); -}; - - -/** - * Clears the values in the attributes field. - */ -sketchology.proto.Element.prototype.clearAttributes = function() { - this.clear$Field(10); -}; - - - -/** - * Message ElementAttributes. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ElementAttributes = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ElementAttributes, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ElementAttributes.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ElementAttributes} The cloned message. - * @override - */ -sketchology.proto.ElementAttributes.prototype.clone; - - -/** - * Gets the value of the selectable field. - * @return {?boolean} The value. - */ -sketchology.proto.ElementAttributes.prototype.getSelectable = function() { - return /** @type {?boolean} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the selectable field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.ElementAttributes.prototype.getSelectableOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the selectable field. - * @param {boolean} value The value. - */ -sketchology.proto.ElementAttributes.prototype.setSelectable = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the selectable field has a value. - */ -sketchology.proto.ElementAttributes.prototype.hasSelectable = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the selectable field. - */ -sketchology.proto.ElementAttributes.prototype.selectableCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the selectable field. - */ -sketchology.proto.ElementAttributes.prototype.clearSelectable = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the magic_erasable field. - * @return {?boolean} The value. - */ -sketchology.proto.ElementAttributes.prototype.getMagicErasable = function() { - return /** @type {?boolean} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the magic_erasable field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.ElementAttributes.prototype.getMagicErasableOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the magic_erasable field. - * @param {boolean} value The value. - */ -sketchology.proto.ElementAttributes.prototype.setMagicErasable = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the magic_erasable field has a value. - */ -sketchology.proto.ElementAttributes.prototype.hasMagicErasable = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the magic_erasable field. - */ -sketchology.proto.ElementAttributes.prototype.magicErasableCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the magic_erasable field. - */ -sketchology.proto.ElementAttributes.prototype.clearMagicErasable = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the is_sticker field. - * @return {?boolean} The value. - */ -sketchology.proto.ElementAttributes.prototype.getIsSticker = function() { - return /** @type {?boolean} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the is_sticker field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.ElementAttributes.prototype.getIsStickerOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the is_sticker field. - * @param {boolean} value The value. - */ -sketchology.proto.ElementAttributes.prototype.setIsSticker = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the is_sticker field has a value. - */ -sketchology.proto.ElementAttributes.prototype.hasIsSticker = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the is_sticker field. - */ -sketchology.proto.ElementAttributes.prototype.isStickerCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the is_sticker field. - */ -sketchology.proto.ElementAttributes.prototype.clearIsSticker = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the is_text field. - * @return {?boolean} The value. - */ -sketchology.proto.ElementAttributes.prototype.getIsText = function() { - return /** @type {?boolean} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the is_text field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.ElementAttributes.prototype.getIsTextOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the is_text field. - * @param {boolean} value The value. - */ -sketchology.proto.ElementAttributes.prototype.setIsText = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the is_text field has a value. - */ -sketchology.proto.ElementAttributes.prototype.hasIsText = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the is_text field. - */ -sketchology.proto.ElementAttributes.prototype.isTextCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the is_text field. - */ -sketchology.proto.ElementAttributes.prototype.clearIsText = function() { - this.clear$Field(4); -}; - - - -/** - * Message UncompressedElement. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.UncompressedElement = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.UncompressedElement, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.UncompressedElement.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.UncompressedElement} The cloned message. - * @override - */ -sketchology.proto.UncompressedElement.prototype.clone; - - -/** - * Gets the value of the uncompressed_stroke field. - * @return {?sketchology.proto.UncompressedStroke} The value. - */ -sketchology.proto.UncompressedElement.prototype.getUncompressedStroke = function() { - return /** @type {?sketchology.proto.UncompressedStroke} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the uncompressed_stroke field or the default value if not set. - * @return {!sketchology.proto.UncompressedStroke} The value. - */ -sketchology.proto.UncompressedElement.prototype.getUncompressedStrokeOrDefault = function() { - return /** @type {!sketchology.proto.UncompressedStroke} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the uncompressed_stroke field. - * @param {!sketchology.proto.UncompressedStroke} value The value. - */ -sketchology.proto.UncompressedElement.prototype.setUncompressedStroke = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the uncompressed_stroke field has a value. - */ -sketchology.proto.UncompressedElement.prototype.hasUncompressedStroke = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uncompressed_stroke field. - */ -sketchology.proto.UncompressedElement.prototype.uncompressedStrokeCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uncompressed_stroke field. - */ -sketchology.proto.UncompressedElement.prototype.clearUncompressedStroke = function() { - this.clear$Field(1); -}; - - - -/** - * Message ElementMutation. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ElementMutation = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ElementMutation, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ElementMutation.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ElementMutation} The cloned message. - * @override - */ -sketchology.proto.ElementMutation.prototype.clone; - - -/** - * Gets the value of the uuid field at the index given. - * @param {number} index The index to lookup. - * @return {?string} The value. - */ -sketchology.proto.ElementMutation.prototype.getUuid = function(index) { - return /** @type {?string} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the uuid field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {string} The value. - */ -sketchology.proto.ElementMutation.prototype.getUuidOrDefault = function(index) { - return /** @type {string} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the uuid field. - * @param {string} value The value to add. - */ -sketchology.proto.ElementMutation.prototype.addUuid = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the uuid field. - * @return {!Array<string>} The values in the field. - */ -sketchology.proto.ElementMutation.prototype.uuidArray = function() { - return /** @type {!Array<string>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the uuid field has a value. - */ -sketchology.proto.ElementMutation.prototype.hasUuid = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uuid field. - */ -sketchology.proto.ElementMutation.prototype.uuidCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uuid field. - */ -sketchology.proto.ElementMutation.prototype.clearUuid = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the transform field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.AffineTransform} The value. - */ -sketchology.proto.ElementMutation.prototype.getTransform = function(index) { - return /** @type {?sketchology.proto.AffineTransform} */ (this.get$Value(2, index)); -}; - - -/** - * Gets the value of the transform field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.AffineTransform} The value. - */ -sketchology.proto.ElementMutation.prototype.getTransformOrDefault = function(index) { - return /** @type {!sketchology.proto.AffineTransform} */ (this.get$ValueOrDefault(2, index)); -}; - - -/** - * Adds a value to the transform field. - * @param {!sketchology.proto.AffineTransform} value The value to add. - */ -sketchology.proto.ElementMutation.prototype.addTransform = function(value) { - this.add$Value(2, value); -}; - - -/** - * Returns the array of values in the transform field. - * @return {!Array<!sketchology.proto.AffineTransform>} The values in the field. - */ -sketchology.proto.ElementMutation.prototype.transformArray = function() { - return /** @type {!Array<!sketchology.proto.AffineTransform>} */ (this.array$Values(2)); -}; - - -/** - * @return {boolean} Whether the transform field has a value. - */ -sketchology.proto.ElementMutation.prototype.hasTransform = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the transform field. - */ -sketchology.proto.ElementMutation.prototype.transformCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the transform field. - */ -sketchology.proto.ElementMutation.prototype.clearTransform = function() { - this.clear$Field(2); -}; - - - -/** - * Message ElementIdList. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ElementIdList = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ElementIdList, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ElementIdList.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ElementIdList} The cloned message. - * @override - */ -sketchology.proto.ElementIdList.prototype.clone; - - -/** - * Gets the value of the uuid field at the index given. - * @param {number} index The index to lookup. - * @return {?string} The value. - */ -sketchology.proto.ElementIdList.prototype.getUuid = function(index) { - return /** @type {?string} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the uuid field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {string} The value. - */ -sketchology.proto.ElementIdList.prototype.getUuidOrDefault = function(index) { - return /** @type {string} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the uuid field. - * @param {string} value The value to add. - */ -sketchology.proto.ElementIdList.prototype.addUuid = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the uuid field. - * @return {!Array<string>} The values in the field. - */ -sketchology.proto.ElementIdList.prototype.uuidArray = function() { - return /** @type {!Array<string>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the uuid field has a value. - */ -sketchology.proto.ElementIdList.prototype.hasUuid = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uuid field. - */ -sketchology.proto.ElementIdList.prototype.uuidCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uuid field. - */ -sketchology.proto.ElementIdList.prototype.clearUuid = function() { - this.clear$Field(1); -}; - - - -/** - * Message Point. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.Point = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.Point, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.Point.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.Point} The cloned message. - * @override - */ -sketchology.proto.Point.prototype.clone; - - -/** - * Gets the value of the x field. - * @return {?number} The value. - */ -sketchology.proto.Point.prototype.getX = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the x field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Point.prototype.getXOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the x field. - * @param {number} value The value. - */ -sketchology.proto.Point.prototype.setX = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the x field has a value. - */ -sketchology.proto.Point.prototype.hasX = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the x field. - */ -sketchology.proto.Point.prototype.xCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the x field. - */ -sketchology.proto.Point.prototype.clearX = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the y field. - * @return {?number} The value. - */ -sketchology.proto.Point.prototype.getY = function() { - return /** @type {?number} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the y field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Point.prototype.getYOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the y field. - * @param {number} value The value. - */ -sketchology.proto.Point.prototype.setY = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the y field has a value. - */ -sketchology.proto.Point.prototype.hasY = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the y field. - */ -sketchology.proto.Point.prototype.yCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the y field. - */ -sketchology.proto.Point.prototype.clearY = function() { - this.clear$Field(2); -}; - - - -/** - * Message ElementBundle. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ElementBundle = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ElementBundle, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ElementBundle.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ElementBundle} The cloned message. - * @override - */ -sketchology.proto.ElementBundle.prototype.clone; - - -/** - * Gets the value of the uuid field. - * @return {?string} The value. - */ -sketchology.proto.ElementBundle.prototype.getUuid = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the uuid field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.ElementBundle.prototype.getUuidOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the uuid field. - * @param {string} value The value. - */ -sketchology.proto.ElementBundle.prototype.setUuid = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the uuid field has a value. - */ -sketchology.proto.ElementBundle.prototype.hasUuid = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uuid field. - */ -sketchology.proto.ElementBundle.prototype.uuidCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uuid field. - */ -sketchology.proto.ElementBundle.prototype.clearUuid = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the element field. - * @return {?sketchology.proto.Element} The value. - */ -sketchology.proto.ElementBundle.prototype.getElement = function() { - return /** @type {?sketchology.proto.Element} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the element field or the default value if not set. - * @return {!sketchology.proto.Element} The value. - */ -sketchology.proto.ElementBundle.prototype.getElementOrDefault = function() { - return /** @type {!sketchology.proto.Element} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the element field. - * @param {!sketchology.proto.Element} value The value. - */ -sketchology.proto.ElementBundle.prototype.setElement = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the element field has a value. - */ -sketchology.proto.ElementBundle.prototype.hasElement = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the element field. - */ -sketchology.proto.ElementBundle.prototype.elementCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the element field. - */ -sketchology.proto.ElementBundle.prototype.clearElement = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the transform field. - * @return {?sketchology.proto.AffineTransform} The value. - */ -sketchology.proto.ElementBundle.prototype.getTransform = function() { - return /** @type {?sketchology.proto.AffineTransform} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the transform field or the default value if not set. - * @return {!sketchology.proto.AffineTransform} The value. - */ -sketchology.proto.ElementBundle.prototype.getTransformOrDefault = function() { - return /** @type {!sketchology.proto.AffineTransform} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the transform field. - * @param {!sketchology.proto.AffineTransform} value The value. - */ -sketchology.proto.ElementBundle.prototype.setTransform = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the transform field has a value. - */ -sketchology.proto.ElementBundle.prototype.hasTransform = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the transform field. - */ -sketchology.proto.ElementBundle.prototype.transformCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the transform field. - */ -sketchology.proto.ElementBundle.prototype.clearTransform = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the uncompressed_element field. - * @return {?sketchology.proto.UncompressedElement} The value. - */ -sketchology.proto.ElementBundle.prototype.getUncompressedElement = function() { - return /** @type {?sketchology.proto.UncompressedElement} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the uncompressed_element field or the default value if not set. - * @return {!sketchology.proto.UncompressedElement} The value. - */ -sketchology.proto.ElementBundle.prototype.getUncompressedElementOrDefault = function() { - return /** @type {!sketchology.proto.UncompressedElement} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the uncompressed_element field. - * @param {!sketchology.proto.UncompressedElement} value The value. - */ -sketchology.proto.ElementBundle.prototype.setUncompressedElement = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the uncompressed_element field has a value. - */ -sketchology.proto.ElementBundle.prototype.hasUncompressedElement = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the uncompressed_element field. - */ -sketchology.proto.ElementBundle.prototype.uncompressedElementCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the uncompressed_element field. - */ -sketchology.proto.ElementBundle.prototype.clearUncompressedElement = function() { - this.clear$Field(4); -}; - - - -/** - * Message Path. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.Path = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.Path, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.Path.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.Path} The cloned message. - * @override - */ -sketchology.proto.Path.prototype.clone; - - -/** - * Gets the value of the segment_types field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.Path.SegmentType} The value. - */ -sketchology.proto.Path.prototype.getSegmentTypes = function(index) { - return /** @type {?sketchology.proto.Path.SegmentType} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the segment_types field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.Path.SegmentType} The value. - */ -sketchology.proto.Path.prototype.getSegmentTypesOrDefault = function(index) { - return /** @type {!sketchology.proto.Path.SegmentType} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the segment_types field. - * @param {!sketchology.proto.Path.SegmentType} value The value to add. - */ -sketchology.proto.Path.prototype.addSegmentTypes = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the segment_types field. - * @return {!Array<!sketchology.proto.Path.SegmentType>} The values in the field. - */ -sketchology.proto.Path.prototype.segmentTypesArray = function() { - return /** @type {!Array<!sketchology.proto.Path.SegmentType>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the segment_types field has a value. - */ -sketchology.proto.Path.prototype.hasSegmentTypes = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the segment_types field. - */ -sketchology.proto.Path.prototype.segmentTypesCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the segment_types field. - */ -sketchology.proto.Path.prototype.clearSegmentTypes = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the segment_counts field at the index given. - * @param {number} index The index to lookup. - * @return {?number} The value. - */ -sketchology.proto.Path.prototype.getSegmentCounts = function(index) { - return /** @type {?number} */ (this.get$Value(2, index)); -}; - - -/** - * Gets the value of the segment_counts field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {number} The value. - */ -sketchology.proto.Path.prototype.getSegmentCountsOrDefault = function(index) { - return /** @type {number} */ (this.get$ValueOrDefault(2, index)); -}; - - -/** - * Adds a value to the segment_counts field. - * @param {number} value The value to add. - */ -sketchology.proto.Path.prototype.addSegmentCounts = function(value) { - this.add$Value(2, value); -}; - - -/** - * Returns the array of values in the segment_counts field. - * @return {!Array<number>} The values in the field. - */ -sketchology.proto.Path.prototype.segmentCountsArray = function() { - return /** @type {!Array<number>} */ (this.array$Values(2)); -}; - - -/** - * @return {boolean} Whether the segment_counts field has a value. - */ -sketchology.proto.Path.prototype.hasSegmentCounts = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the segment_counts field. - */ -sketchology.proto.Path.prototype.segmentCountsCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the segment_counts field. - */ -sketchology.proto.Path.prototype.clearSegmentCounts = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the segment_args field at the index given. - * @param {number} index The index to lookup. - * @return {?number} The value. - */ -sketchology.proto.Path.prototype.getSegmentArgs = function(index) { - return /** @type {?number} */ (this.get$Value(3, index)); -}; - - -/** - * Gets the value of the segment_args field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {number} The value. - */ -sketchology.proto.Path.prototype.getSegmentArgsOrDefault = function(index) { - return /** @type {number} */ (this.get$ValueOrDefault(3, index)); -}; - - -/** - * Adds a value to the segment_args field. - * @param {number} value The value to add. - */ -sketchology.proto.Path.prototype.addSegmentArgs = function(value) { - this.add$Value(3, value); -}; - - -/** - * Returns the array of values in the segment_args field. - * @return {!Array<number>} The values in the field. - */ -sketchology.proto.Path.prototype.segmentArgsArray = function() { - return /** @type {!Array<number>} */ (this.array$Values(3)); -}; - - -/** - * @return {boolean} Whether the segment_args field has a value. - */ -sketchology.proto.Path.prototype.hasSegmentArgs = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the segment_args field. - */ -sketchology.proto.Path.prototype.segmentArgsCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the segment_args field. - */ -sketchology.proto.Path.prototype.clearSegmentArgs = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the radius field. - * @return {?number} The value. - */ -sketchology.proto.Path.prototype.getRadius = function() { - return /** @type {?number} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the radius field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Path.prototype.getRadiusOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the radius field. - * @param {number} value The value. - */ -sketchology.proto.Path.prototype.setRadius = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the radius field has a value. - */ -sketchology.proto.Path.prototype.hasRadius = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the radius field. - */ -sketchology.proto.Path.prototype.radiusCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the radius field. - */ -sketchology.proto.Path.prototype.clearRadius = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the rgba field. - * @return {?number} The value. - */ -sketchology.proto.Path.prototype.getRgba = function() { - return /** @type {?number} */ (this.get$Value(5)); -}; - - -/** - * Gets the value of the rgba field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Path.prototype.getRgbaOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(5)); -}; - - -/** - * Sets the value of the rgba field. - * @param {number} value The value. - */ -sketchology.proto.Path.prototype.setRgba = function(value) { - this.set$Value(5, value); -}; - - -/** - * @return {boolean} Whether the rgba field has a value. - */ -sketchology.proto.Path.prototype.hasRgba = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the rgba field. - */ -sketchology.proto.Path.prototype.rgbaCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the rgba field. - */ -sketchology.proto.Path.prototype.clearRgba = function() { - this.clear$Field(5); -}; - - -/** - * Gets the value of the end_cap field. - * @return {?sketchology.proto.Path.EndCapType} The value. - */ -sketchology.proto.Path.prototype.getEndCap = function() { - return /** @type {?sketchology.proto.Path.EndCapType} */ (this.get$Value(6)); -}; - - -/** - * Gets the value of the end_cap field or the default value if not set. - * @return {!sketchology.proto.Path.EndCapType} The value. - */ -sketchology.proto.Path.prototype.getEndCapOrDefault = function() { - return /** @type {!sketchology.proto.Path.EndCapType} */ (this.get$ValueOrDefault(6)); -}; - - -/** - * Sets the value of the end_cap field. - * @param {!sketchology.proto.Path.EndCapType} value The value. - */ -sketchology.proto.Path.prototype.setEndCap = function(value) { - this.set$Value(6, value); -}; - - -/** - * @return {boolean} Whether the end_cap field has a value. - */ -sketchology.proto.Path.prototype.hasEndCap = function() { - return this.has$Value(6); -}; - - -/** - * @return {number} The number of values in the end_cap field. - */ -sketchology.proto.Path.prototype.endCapCount = function() { - return this.count$Values(6); -}; - - -/** - * Clears the values in the end_cap field. - */ -sketchology.proto.Path.prototype.clearEndCap = function() { - this.clear$Field(6); -}; - - -/** - * Gets the value of the fill_rgba field. - * @return {?number} The value. - */ -sketchology.proto.Path.prototype.getFillRgba = function() { - return /** @type {?number} */ (this.get$Value(7)); -}; - - -/** - * Gets the value of the fill_rgba field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Path.prototype.getFillRgbaOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(7)); -}; - - -/** - * Sets the value of the fill_rgba field. - * @param {number} value The value. - */ -sketchology.proto.Path.prototype.setFillRgba = function(value) { - this.set$Value(7, value); -}; - - -/** - * @return {boolean} Whether the fill_rgba field has a value. - */ -sketchology.proto.Path.prototype.hasFillRgba = function() { - return this.has$Value(7); -}; - - -/** - * @return {number} The number of values in the fill_rgba field. - */ -sketchology.proto.Path.prototype.fillRgbaCount = function() { - return this.count$Values(7); -}; - - -/** - * Clears the values in the fill_rgba field. - */ -sketchology.proto.Path.prototype.clearFillRgba = function() { - this.clear$Field(7); -}; - - -/** - * Enumeration SegmentType. - * @enum {number} - */ -sketchology.proto.Path.SegmentType = { - UNKNOWN: 0, - MOVE_TO: 1, - LINE_TO: 2, - CURVE_TO: 3, - QUAD_TO: 4, - CLOSE: 5 -}; - - -/** - * Enumeration EndCapType. - * @enum {number} - */ -sketchology.proto.Path.EndCapType = { - BUTT: 1, - ROUND: 2, - SQUARE: 3 -}; - - -/** @override */ -sketchology.proto.CallbackFlags.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.CallbackFlags.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'CallbackFlags', - fullName: 'sketchology.proto.CallbackFlags' - }, - 1: { - name: 'mesh_data_ctm', - fieldType: goog.proto2.Message.FieldType.BOOL, - type: Boolean - }, - 2: { - name: 'uncompressed_outline', - fieldType: goog.proto2.Message.FieldType.BOOL, - type: Boolean - }, - 3: { - name: 'compressed_input_points', - fieldType: goog.proto2.Message.FieldType.BOOL, - type: Boolean - } - }; - sketchology.proto.CallbackFlags.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.CallbackFlags, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.CallbackFlags.getDescriptor = - sketchology.proto.CallbackFlags.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.SourceDetails.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.SourceDetails.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'SourceDetails', - fullName: 'sketchology.proto.SourceDetails' - }, - 1: { - name: 'origin', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.SourceDetails.Origin.UNKNOWN, - type: sketchology.proto.SourceDetails.Origin - }, - 2: { - name: 'host_source_details', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - } - }; - sketchology.proto.SourceDetails.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.SourceDetails, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.SourceDetails.getDescriptor = - sketchology.proto.SourceDetails.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.BackgroundImageInfo.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.BackgroundImageInfo.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'BackgroundImageInfo', - fullName: 'sketchology.proto.BackgroundImageInfo' - }, - 1: { - name: 'uri', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 3: { - name: 'bounds', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Rect - } - }; - sketchology.proto.BackgroundImageInfo.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.BackgroundImageInfo, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.BackgroundImageInfo.getDescriptor = - sketchology.proto.BackgroundImageInfo.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.Border.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.Border.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'Border', - fullName: 'sketchology.proto.Border' - }, - 1: { - name: 'uri', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 2: { - name: 'scale', - fieldType: goog.proto2.Message.FieldType.FLOAT, - defaultValue: 1, - type: Number - } - }; - sketchology.proto.Border.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.Border, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.Border.getDescriptor = - sketchology.proto.Border.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.LOD.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.LOD.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'LOD', - fullName: 'sketchology.proto.LOD' - }, - 1: { - name: 'max_coverage', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 2: { - name: 'ctm_blob', - fieldType: goog.proto2.Message.FieldType.BYTES, - type: String - } - }; - sketchology.proto.LOD.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.LOD, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.LOD.getDescriptor = - sketchology.proto.LOD.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.Stroke.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.Stroke.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'Stroke', - fullName: 'sketchology.proto.Stroke' - }, - 1: { - name: 'shader_type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.ShaderType.NONE, - type: sketchology.proto.ShaderType - }, - 3: { - name: 'lod', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.LOD - }, - 4: { - name: 'abgr', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 5: { - name: 'point_x', - repeated: true, - packed: true, - fieldType: goog.proto2.Message.FieldType.SINT32, - type: Number - }, - 6: { - name: 'point_y', - repeated: true, - packed: true, - fieldType: goog.proto2.Message.FieldType.SINT32, - type: Number - }, - 7: { - name: 'point_t_ms', - repeated: true, - packed: true, - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 8: { - name: 'deprecated_transform', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.AffineTransform - }, - 9: { - name: 'start_time_ms', - fieldType: goog.proto2.Message.FieldType.UINT64, - type: String - } - }; - sketchology.proto.Stroke.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.Stroke, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.Stroke.getDescriptor = - sketchology.proto.Stroke.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.UncompressedStroke.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.UncompressedStroke.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'UncompressedStroke', - fullName: 'sketchology.proto.UncompressedStroke' - }, - 1: { - name: 'outline', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Point - }, - 2: { - name: 'rgba', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - } - }; - sketchology.proto.UncompressedStroke.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.UncompressedStroke, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.UncompressedStroke.getDescriptor = - sketchology.proto.UncompressedStroke.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.AffineTransform.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.AffineTransform.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'AffineTransform', - fullName: 'sketchology.proto.AffineTransform' - }, - 1: { - name: 'tx', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 2: { - name: 'ty', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 3: { - name: 'scale_x', - fieldType: goog.proto2.Message.FieldType.FLOAT, - defaultValue: 1, - type: Number - }, - 4: { - name: 'scale_y', - fieldType: goog.proto2.Message.FieldType.FLOAT, - defaultValue: 1, - type: Number - }, - 5: { - name: 'rotation_radians', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - } - }; - sketchology.proto.AffineTransform.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.AffineTransform, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.AffineTransform.getDescriptor = - sketchology.proto.AffineTransform.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.Element.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.Element.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'Element', - fullName: 'sketchology.proto.Element' - }, - 4: { - name: 'deprecated_uuid', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 5: { - name: 'minimum_serializer_version', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 6: { - name: 'stroke', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Stroke - }, - 9: { - name: 'path', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Path - }, - 10: { - name: 'attributes', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ElementAttributes - } - }; - sketchology.proto.Element.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.Element, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.Element.getDescriptor = - sketchology.proto.Element.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ElementAttributes.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ElementAttributes.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ElementAttributes', - fullName: 'sketchology.proto.ElementAttributes' - }, - 1: { - name: 'selectable', - fieldType: goog.proto2.Message.FieldType.BOOL, - defaultValue: true, - type: Boolean - }, - 2: { - name: 'magic_erasable', - fieldType: goog.proto2.Message.FieldType.BOOL, - defaultValue: true, - type: Boolean - }, - 3: { - name: 'is_sticker', - fieldType: goog.proto2.Message.FieldType.BOOL, - defaultValue: false, - type: Boolean - }, - 4: { - name: 'is_text', - fieldType: goog.proto2.Message.FieldType.BOOL, - defaultValue: false, - type: Boolean - } - }; - sketchology.proto.ElementAttributes.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ElementAttributes, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ElementAttributes.getDescriptor = - sketchology.proto.ElementAttributes.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.UncompressedElement.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.UncompressedElement.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'UncompressedElement', - fullName: 'sketchology.proto.UncompressedElement' - }, - 1: { - name: 'uncompressed_stroke', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.UncompressedStroke - } - }; - sketchology.proto.UncompressedElement.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.UncompressedElement, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.UncompressedElement.getDescriptor = - sketchology.proto.UncompressedElement.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ElementMutation.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ElementMutation.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ElementMutation', - fullName: 'sketchology.proto.ElementMutation' - }, - 1: { - name: 'uuid', - repeated: true, - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 2: { - name: 'transform', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.AffineTransform - } - }; - sketchology.proto.ElementMutation.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ElementMutation, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ElementMutation.getDescriptor = - sketchology.proto.ElementMutation.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ElementIdList.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ElementIdList.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ElementIdList', - fullName: 'sketchology.proto.ElementIdList' - }, - 1: { - name: 'uuid', - repeated: true, - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - } - }; - sketchology.proto.ElementIdList.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ElementIdList, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ElementIdList.getDescriptor = - sketchology.proto.ElementIdList.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.Point.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.Point.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'Point', - fullName: 'sketchology.proto.Point' - }, - 1: { - name: 'x', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 2: { - name: 'y', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - } - }; - sketchology.proto.Point.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.Point, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.Point.getDescriptor = - sketchology.proto.Point.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ElementBundle.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ElementBundle.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ElementBundle', - fullName: 'sketchology.proto.ElementBundle' - }, - 1: { - name: 'uuid', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 2: { - name: 'element', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Element - }, - 3: { - name: 'transform', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.AffineTransform - }, - 4: { - name: 'uncompressed_element', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.UncompressedElement - } - }; - sketchology.proto.ElementBundle.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ElementBundle, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ElementBundle.getDescriptor = - sketchology.proto.ElementBundle.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.Path.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.Path.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'Path', - fullName: 'sketchology.proto.Path' - }, - 1: { - name: 'segment_types', - repeated: true, - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.Path.SegmentType.UNKNOWN, - type: sketchology.proto.Path.SegmentType - }, - 2: { - name: 'segment_counts', - repeated: true, - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 3: { - name: 'segment_args', - repeated: true, - fieldType: goog.proto2.Message.FieldType.DOUBLE, - type: Number - }, - 4: { - name: 'radius', - fieldType: goog.proto2.Message.FieldType.DOUBLE, - defaultValue: 1, - type: Number - }, - 5: { - name: 'rgba', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 6: { - name: 'end_cap', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.Path.EndCapType.ROUND, - type: sketchology.proto.Path.EndCapType - }, - 7: { - name: 'fill_rgba', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - } - }; - sketchology.proto.Path.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.Path, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.Path.getDescriptor = - sketchology.proto.Path.prototype.getDescriptor;
diff --git a/third_party/ink/sketchology/proto/rect_bounds.pb.js b/third_party/ink/sketchology/proto/rect_bounds.pb.js deleted file mode 100644 index ef41a1d1..0000000 --- a/third_party/ink/sketchology/proto/rect_bounds.pb.js +++ /dev/null
@@ -1,525 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Protocol Buffer 2 Copyright 2008 Google Inc. -// All other code copyright its respective owners. - -/** - * @fileoverview Generated Protocol Buffer code for file - * third_party/sketchology/proto/rect_bounds.proto. - * Generated by //net/proto2/compiler/public:protocol_compiler. - * @suppress {messageConventions} - */ - -goog.provide('sketchology.proto.Rect'); -goog.provide('sketchology.proto.RectBounds'); - -goog.require('goog.proto2.Message'); - - - -/** - * Message Rect. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.Rect = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.Rect, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.Rect.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.Rect} The cloned message. - * @override - */ -sketchology.proto.Rect.prototype.clone; - - -/** - * Gets the value of the xlow field. - * @return {?number} The value. - */ -sketchology.proto.Rect.prototype.getXlow = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the xlow field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Rect.prototype.getXlowOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the xlow field. - * @param {number} value The value. - */ -sketchology.proto.Rect.prototype.setXlow = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the xlow field has a value. - */ -sketchology.proto.Rect.prototype.hasXlow = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the xlow field. - */ -sketchology.proto.Rect.prototype.xlowCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the xlow field. - */ -sketchology.proto.Rect.prototype.clearXlow = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the xhigh field. - * @return {?number} The value. - */ -sketchology.proto.Rect.prototype.getXhigh = function() { - return /** @type {?number} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the xhigh field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Rect.prototype.getXhighOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the xhigh field. - * @param {number} value The value. - */ -sketchology.proto.Rect.prototype.setXhigh = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the xhigh field has a value. - */ -sketchology.proto.Rect.prototype.hasXhigh = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the xhigh field. - */ -sketchology.proto.Rect.prototype.xhighCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the xhigh field. - */ -sketchology.proto.Rect.prototype.clearXhigh = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the ylow field. - * @return {?number} The value. - */ -sketchology.proto.Rect.prototype.getYlow = function() { - return /** @type {?number} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the ylow field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Rect.prototype.getYlowOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the ylow field. - * @param {number} value The value. - */ -sketchology.proto.Rect.prototype.setYlow = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the ylow field has a value. - */ -sketchology.proto.Rect.prototype.hasYlow = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the ylow field. - */ -sketchology.proto.Rect.prototype.ylowCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the ylow field. - */ -sketchology.proto.Rect.prototype.clearYlow = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the yhigh field. - * @return {?number} The value. - */ -sketchology.proto.Rect.prototype.getYhigh = function() { - return /** @type {?number} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the yhigh field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Rect.prototype.getYhighOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the yhigh field. - * @param {number} value The value. - */ -sketchology.proto.Rect.prototype.setYhigh = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the yhigh field has a value. - */ -sketchology.proto.Rect.prototype.hasYhigh = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the yhigh field. - */ -sketchology.proto.Rect.prototype.yhighCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the yhigh field. - */ -sketchology.proto.Rect.prototype.clearYhigh = function() { - this.clear$Field(4); -}; - - - -/** - * Message RectBounds. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.RectBounds = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.RectBounds, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.RectBounds.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.RectBounds} The cloned message. - * @override - */ -sketchology.proto.RectBounds.prototype.clone; - - -/** - * Gets the value of the mbr field. - * @return {?sketchology.proto.Rect} The value. - */ -sketchology.proto.RectBounds.prototype.getMbr = function() { - return /** @type {?sketchology.proto.Rect} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the mbr field or the default value if not set. - * @return {!sketchology.proto.Rect} The value. - */ -sketchology.proto.RectBounds.prototype.getMbrOrDefault = function() { - return /** @type {!sketchology.proto.Rect} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the mbr field. - * @param {!sketchology.proto.Rect} value The value. - */ -sketchology.proto.RectBounds.prototype.setMbr = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the mbr field has a value. - */ -sketchology.proto.RectBounds.prototype.hasMbr = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the mbr field. - */ -sketchology.proto.RectBounds.prototype.mbrCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the mbr field. - */ -sketchology.proto.RectBounds.prototype.clearMbr = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the fit_rects field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.Rect} The value. - */ -sketchology.proto.RectBounds.prototype.getFitRects = function(index) { - return /** @type {?sketchology.proto.Rect} */ (this.get$Value(2, index)); -}; - - -/** - * Gets the value of the fit_rects field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.Rect} The value. - */ -sketchology.proto.RectBounds.prototype.getFitRectsOrDefault = function(index) { - return /** @type {!sketchology.proto.Rect} */ (this.get$ValueOrDefault(2, index)); -}; - - -/** - * Adds a value to the fit_rects field. - * @param {!sketchology.proto.Rect} value The value to add. - */ -sketchology.proto.RectBounds.prototype.addFitRects = function(value) { - this.add$Value(2, value); -}; - - -/** - * Returns the array of values in the fit_rects field. - * @return {!Array<!sketchology.proto.Rect>} The values in the field. - */ -sketchology.proto.RectBounds.prototype.fitRectsArray = function() { - return /** @type {!Array<!sketchology.proto.Rect>} */ (this.array$Values(2)); -}; - - -/** - * @return {boolean} Whether the fit_rects field has a value. - */ -sketchology.proto.RectBounds.prototype.hasFitRects = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the fit_rects field. - */ -sketchology.proto.RectBounds.prototype.fitRectsCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the fit_rects field. - */ -sketchology.proto.RectBounds.prototype.clearFitRects = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the max_dim field. - * @return {?number} The value. - */ -sketchology.proto.RectBounds.prototype.getMaxDim = function() { - return /** @type {?number} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the max_dim field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.RectBounds.prototype.getMaxDimOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the max_dim field. - * @param {number} value The value. - */ -sketchology.proto.RectBounds.prototype.setMaxDim = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the max_dim field has a value. - */ -sketchology.proto.RectBounds.prototype.hasMaxDim = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the max_dim field. - */ -sketchology.proto.RectBounds.prototype.maxDimCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the max_dim field. - */ -sketchology.proto.RectBounds.prototype.clearMaxDim = function() { - this.clear$Field(3); -}; - - -/** @override */ -sketchology.proto.Rect.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.Rect.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'Rect', - fullName: 'sketchology.proto.Rect' - }, - 1: { - name: 'xlow', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 2: { - name: 'xhigh', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 3: { - name: 'ylow', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 4: { - name: 'yhigh', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - } - }; - sketchology.proto.Rect.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.Rect, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.Rect.getDescriptor = - sketchology.proto.Rect.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.RectBounds.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.RectBounds.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'RectBounds', - fullName: 'sketchology.proto.RectBounds' - }, - 1: { - name: 'mbr', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Rect - }, - 2: { - name: 'fit_rects', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Rect - }, - 3: { - name: 'max_dim', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - } - }; - sketchology.proto.RectBounds.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.RectBounds, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.RectBounds.getDescriptor = - sketchology.proto.RectBounds.prototype.getDescriptor;
diff --git a/third_party/ink/sketchology/proto/sengine.pb.js b/third_party/ink/sketchology/proto/sengine.pb.js deleted file mode 100644 index 56bd87d..0000000 --- a/third_party/ink/sketchology/proto/sengine.pb.js +++ /dev/null
@@ -1,8196 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Protocol Buffer 2 Copyright 2008 Google Inc. -// All other code copyright its respective owners. - -/** - * @fileoverview Generated Protocol Buffer code for file - * third_party/sketchology/proto/sengine.proto. - * Generated by //net/proto2/compiler/public:protocol_compiler. - * @suppress {messageConventions} - */ - -goog.provide('sketchology.proto.Command'); -goog.provide('sketchology.proto.CommandList'); -goog.provide('sketchology.proto.NoArgCommand'); -goog.provide('sketchology.proto.ReplaceElementsCommand'); -goog.provide('sketchology.proto.EvictImageData'); -goog.provide('sketchology.proto.Viewport'); -goog.provide('sketchology.proto.ImageExport'); -goog.provide('sketchology.proto.LinearPathAnimation'); -goog.provide('sketchology.proto.LineSize'); -goog.provide('sketchology.proto.LineSize.SizeType'); -goog.provide('sketchology.proto.PusherToolParams'); -goog.provide('sketchology.proto.ToolParams'); -goog.provide('sketchology.proto.ToolParams.ToolType'); -goog.provide('sketchology.proto.FlagAssignment'); -goog.provide('sketchology.proto.AddElement'); -goog.provide('sketchology.proto.OutOfBoundsColor'); -goog.provide('sketchology.proto.SInputStream'); -goog.provide('sketchology.proto.SInput'); -goog.provide('sketchology.proto.SInput.InputType'); -goog.provide('sketchology.proto.SimulatedInput'); -goog.provide('sketchology.proto.SequencePoint'); -goog.provide('sketchology.proto.SetCallbackFlags'); -goog.provide('sketchology.proto.EngineState'); -goog.provide('sketchology.proto.CameraBoundsConfig'); -goog.provide('sketchology.proto.ImageInfo'); -goog.provide('sketchology.proto.ImageInfo.AssetType'); -goog.provide('sketchology.proto.ImageRect'); -goog.provide('sketchology.proto.GridInfo'); -goog.provide('sketchology.proto.CreateDocument'); -goog.provide('sketchology.proto.AddPath'); -goog.provide('sketchology.proto.PusherPositionUpdate'); -goog.provide('sketchology.proto.ElementQueryData'); -goog.provide('sketchology.proto.ElementQueryItem'); -goog.provide('sketchology.proto.SelectionState'); -goog.provide('sketchology.proto.ToolEvent'); -goog.provide('sketchology.proto.RenderingStrategy'); -goog.provide('sketchology.proto.BrushType'); -goog.provide('sketchology.proto.Flag'); -goog.provide('sketchology.proto.DocumentType'); -goog.provide('sketchology.proto.StorageType'); - -goog.require('goog.proto2.Message'); -goog.require('sketchology.proto.BackgroundColor'); -goog.require('sketchology.proto.BackgroundImageInfo'); -goog.require('sketchology.proto.Border'); -goog.require('sketchology.proto.CallbackFlags'); -goog.require('sketchology.proto.ElementAnimation'); -goog.require('sketchology.proto.ElementAttributes'); -goog.require('sketchology.proto.ElementBundle'); -goog.require('sketchology.proto.ElementMutation'); -goog.require('sketchology.proto.Path'); -goog.require('sketchology.proto.Point'); -goog.require('sketchology.proto.Rect'); -goog.require('sketchology.proto.Snapshot'); -goog.require('sketchology.proto.SourceDetails'); - - -/** - * Enumeration RenderingStrategy. - * @enum {number} - */ -sketchology.proto.RenderingStrategy = { - UNKNOWN_RENDERER: 0, - BUFFERED_RENDERER: 1, - DIRECT_RENDERER: 2 -}; - - -/** - * Enumeration BrushType. - * @enum {number} - */ -sketchology.proto.BrushType = { - UNKNOWN_BRUSH: 0, - CALLIGRAPHY: 1, - INKPEN: 2, - MARKER: 3, - BALLPOINT: 4, - PENCIL: 5, - ERASER: 6, - AIRBRUSH: 7, - HIGHLIGHTER: 8, - GRADIENT: 9, - CHISEL: 10, - BALLPOINT_IN_PEN_MODE_ELSE_MARKER: 11 -}; - - -/** - * Enumeration Flag. - * @enum {number} - */ -sketchology.proto.Flag = { - UNKNOWN: 0, - READ_ONLY_MODE: 1, - ENABLE_PAN_ZOOM: 2, - ENABLE_ROTATION: 3, - ENABLE_AUTO_PEN_MODE: 4, - ENABLE_PEN_MODE: 5, - LOW_MEMORY_MODE: 6, - OPAQUE_PREDICTED_SEGMENT: 7 -}; - - -/** - * Enumeration DocumentType. - * @enum {number} - */ -sketchology.proto.DocumentType = { - UNKNOWN_DOCUMENT_TYPE: 0, - SINGLE_USER_DOCUMENT: 1, - PASSTHROUGH_DOCUMENT: 2 -}; - - -/** - * Enumeration StorageType. - * @enum {number} - */ -sketchology.proto.StorageType = { - UNKNOWN_STORAGE_TYPE: 0, - IN_MEMORY_STORAGE: 1, - SQLITE_STORAGE: 2 -}; - - - -/** - * Message Command. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.Command = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.Command, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.Command.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.Command} The cloned message. - * @override - */ -sketchology.proto.Command.prototype.clone; - - -/** - * Gets the value of the set_viewport field. - * @return {?sketchology.proto.Viewport} The value. - */ -sketchology.proto.Command.prototype.getSetViewport = function() { - return /** @type {?sketchology.proto.Viewport} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the set_viewport field or the default value if not set. - * @return {!sketchology.proto.Viewport} The value. - */ -sketchology.proto.Command.prototype.getSetViewportOrDefault = function() { - return /** @type {!sketchology.proto.Viewport} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the set_viewport field. - * @param {!sketchology.proto.Viewport} value The value. - */ -sketchology.proto.Command.prototype.setSetViewport = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the set_viewport field has a value. - */ -sketchology.proto.Command.prototype.hasSetViewport = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the set_viewport field. - */ -sketchology.proto.Command.prototype.setViewportCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the set_viewport field. - */ -sketchology.proto.Command.prototype.clearSetViewport = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the tool_params field. - * @return {?sketchology.proto.ToolParams} The value. - */ -sketchology.proto.Command.prototype.getToolParams = function() { - return /** @type {?sketchology.proto.ToolParams} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the tool_params field or the default value if not set. - * @return {!sketchology.proto.ToolParams} The value. - */ -sketchology.proto.Command.prototype.getToolParamsOrDefault = function() { - return /** @type {!sketchology.proto.ToolParams} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the tool_params field. - * @param {!sketchology.proto.ToolParams} value The value. - */ -sketchology.proto.Command.prototype.setToolParams = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the tool_params field has a value. - */ -sketchology.proto.Command.prototype.hasToolParams = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the tool_params field. - */ -sketchology.proto.Command.prototype.toolParamsCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the tool_params field. - */ -sketchology.proto.Command.prototype.clearToolParams = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the add_path field. - * @return {?sketchology.proto.AddPath} The value. - */ -sketchology.proto.Command.prototype.getAddPath = function() { - return /** @type {?sketchology.proto.AddPath} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the add_path field or the default value if not set. - * @return {!sketchology.proto.AddPath} The value. - */ -sketchology.proto.Command.prototype.getAddPathOrDefault = function() { - return /** @type {!sketchology.proto.AddPath} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the add_path field. - * @param {!sketchology.proto.AddPath} value The value. - */ -sketchology.proto.Command.prototype.setAddPath = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the add_path field has a value. - */ -sketchology.proto.Command.prototype.hasAddPath = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the add_path field. - */ -sketchology.proto.Command.prototype.addPathCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the add_path field. - */ -sketchology.proto.Command.prototype.clearAddPath = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the camera_position field. - * @return {?sketchology.proto.Rect} The value. - */ -sketchology.proto.Command.prototype.getCameraPosition = function() { - return /** @type {?sketchology.proto.Rect} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the camera_position field or the default value if not set. - * @return {!sketchology.proto.Rect} The value. - */ -sketchology.proto.Command.prototype.getCameraPositionOrDefault = function() { - return /** @type {!sketchology.proto.Rect} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the camera_position field. - * @param {!sketchology.proto.Rect} value The value. - */ -sketchology.proto.Command.prototype.setCameraPosition = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the camera_position field has a value. - */ -sketchology.proto.Command.prototype.hasCameraPosition = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the camera_position field. - */ -sketchology.proto.Command.prototype.cameraPositionCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the camera_position field. - */ -sketchology.proto.Command.prototype.clearCameraPosition = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the page_bounds field. - * @return {?sketchology.proto.Rect} The value. - */ -sketchology.proto.Command.prototype.getPageBounds = function() { - return /** @type {?sketchology.proto.Rect} */ (this.get$Value(5)); -}; - - -/** - * Gets the value of the page_bounds field or the default value if not set. - * @return {!sketchology.proto.Rect} The value. - */ -sketchology.proto.Command.prototype.getPageBoundsOrDefault = function() { - return /** @type {!sketchology.proto.Rect} */ (this.get$ValueOrDefault(5)); -}; - - -/** - * Sets the value of the page_bounds field. - * @param {!sketchology.proto.Rect} value The value. - */ -sketchology.proto.Command.prototype.setPageBounds = function(value) { - this.set$Value(5, value); -}; - - -/** - * @return {boolean} Whether the page_bounds field has a value. - */ -sketchology.proto.Command.prototype.hasPageBounds = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the page_bounds field. - */ -sketchology.proto.Command.prototype.pageBoundsCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the page_bounds field. - */ -sketchology.proto.Command.prototype.clearPageBounds = function() { - this.clear$Field(5); -}; - - -/** - * Gets the value of the image_export field. - * @return {?sketchology.proto.ImageExport} The value. - */ -sketchology.proto.Command.prototype.getImageExport = function() { - return /** @type {?sketchology.proto.ImageExport} */ (this.get$Value(6)); -}; - - -/** - * Gets the value of the image_export field or the default value if not set. - * @return {!sketchology.proto.ImageExport} The value. - */ -sketchology.proto.Command.prototype.getImageExportOrDefault = function() { - return /** @type {!sketchology.proto.ImageExport} */ (this.get$ValueOrDefault(6)); -}; - - -/** - * Sets the value of the image_export field. - * @param {!sketchology.proto.ImageExport} value The value. - */ -sketchology.proto.Command.prototype.setImageExport = function(value) { - this.set$Value(6, value); -}; - - -/** - * @return {boolean} Whether the image_export field has a value. - */ -sketchology.proto.Command.prototype.hasImageExport = function() { - return this.has$Value(6); -}; - - -/** - * @return {number} The number of values in the image_export field. - */ -sketchology.proto.Command.prototype.imageExportCount = function() { - return this.count$Values(6); -}; - - -/** - * Clears the values in the image_export field. - */ -sketchology.proto.Command.prototype.clearImageExport = function() { - this.clear$Field(6); -}; - - -/** - * Gets the value of the flag_assignment field. - * @return {?sketchology.proto.FlagAssignment} The value. - */ -sketchology.proto.Command.prototype.getFlagAssignment = function() { - return /** @type {?sketchology.proto.FlagAssignment} */ (this.get$Value(7)); -}; - - -/** - * Gets the value of the flag_assignment field or the default value if not set. - * @return {!sketchology.proto.FlagAssignment} The value. - */ -sketchology.proto.Command.prototype.getFlagAssignmentOrDefault = function() { - return /** @type {!sketchology.proto.FlagAssignment} */ (this.get$ValueOrDefault(7)); -}; - - -/** - * Sets the value of the flag_assignment field. - * @param {!sketchology.proto.FlagAssignment} value The value. - */ -sketchology.proto.Command.prototype.setFlagAssignment = function(value) { - this.set$Value(7, value); -}; - - -/** - * @return {boolean} Whether the flag_assignment field has a value. - */ -sketchology.proto.Command.prototype.hasFlagAssignment = function() { - return this.has$Value(7); -}; - - -/** - * @return {number} The number of values in the flag_assignment field. - */ -sketchology.proto.Command.prototype.flagAssignmentCount = function() { - return this.count$Values(7); -}; - - -/** - * Clears the values in the flag_assignment field. - */ -sketchology.proto.Command.prototype.clearFlagAssignment = function() { - this.clear$Field(7); -}; - - -/** - * Gets the value of the set_element_transforms field. - * @return {?sketchology.proto.ElementMutation} The value. - */ -sketchology.proto.Command.prototype.getSetElementTransforms = function() { - return /** @type {?sketchology.proto.ElementMutation} */ (this.get$Value(8)); -}; - - -/** - * Gets the value of the set_element_transforms field or the default value if not set. - * @return {!sketchology.proto.ElementMutation} The value. - */ -sketchology.proto.Command.prototype.getSetElementTransformsOrDefault = function() { - return /** @type {!sketchology.proto.ElementMutation} */ (this.get$ValueOrDefault(8)); -}; - - -/** - * Sets the value of the set_element_transforms field. - * @param {!sketchology.proto.ElementMutation} value The value. - */ -sketchology.proto.Command.prototype.setSetElementTransforms = function(value) { - this.set$Value(8, value); -}; - - -/** - * @return {boolean} Whether the set_element_transforms field has a value. - */ -sketchology.proto.Command.prototype.hasSetElementTransforms = function() { - return this.has$Value(8); -}; - - -/** - * @return {number} The number of values in the set_element_transforms field. - */ -sketchology.proto.Command.prototype.setElementTransformsCount = function() { - return this.count$Values(8); -}; - - -/** - * Clears the values in the set_element_transforms field. - */ -sketchology.proto.Command.prototype.clearSetElementTransforms = function() { - this.clear$Field(8); -}; - - -/** - * Gets the value of the add_element field. - * @return {?sketchology.proto.AddElement} The value. - */ -sketchology.proto.Command.prototype.getAddElement = function() { - return /** @type {?sketchology.proto.AddElement} */ (this.get$Value(9)); -}; - - -/** - * Gets the value of the add_element field or the default value if not set. - * @return {!sketchology.proto.AddElement} The value. - */ -sketchology.proto.Command.prototype.getAddElementOrDefault = function() { - return /** @type {!sketchology.proto.AddElement} */ (this.get$ValueOrDefault(9)); -}; - - -/** - * Sets the value of the add_element field. - * @param {!sketchology.proto.AddElement} value The value. - */ -sketchology.proto.Command.prototype.setAddElement = function(value) { - this.set$Value(9, value); -}; - - -/** - * @return {boolean} Whether the add_element field has a value. - */ -sketchology.proto.Command.prototype.hasAddElement = function() { - return this.has$Value(9); -}; - - -/** - * @return {number} The number of values in the add_element field. - */ -sketchology.proto.Command.prototype.addElementCount = function() { - return this.count$Values(9); -}; - - -/** - * Clears the values in the add_element field. - */ -sketchology.proto.Command.prototype.clearAddElement = function() { - this.clear$Field(9); -}; - - -/** - * Gets the value of the background_image field. - * @return {?sketchology.proto.BackgroundImageInfo} The value. - */ -sketchology.proto.Command.prototype.getBackgroundImage = function() { - return /** @type {?sketchology.proto.BackgroundImageInfo} */ (this.get$Value(10)); -}; - - -/** - * Gets the value of the background_image field or the default value if not set. - * @return {!sketchology.proto.BackgroundImageInfo} The value. - */ -sketchology.proto.Command.prototype.getBackgroundImageOrDefault = function() { - return /** @type {!sketchology.proto.BackgroundImageInfo} */ (this.get$ValueOrDefault(10)); -}; - - -/** - * Sets the value of the background_image field. - * @param {!sketchology.proto.BackgroundImageInfo} value The value. - */ -sketchology.proto.Command.prototype.setBackgroundImage = function(value) { - this.set$Value(10, value); -}; - - -/** - * @return {boolean} Whether the background_image field has a value. - */ -sketchology.proto.Command.prototype.hasBackgroundImage = function() { - return this.has$Value(10); -}; - - -/** - * @return {number} The number of values in the background_image field. - */ -sketchology.proto.Command.prototype.backgroundImageCount = function() { - return this.count$Values(10); -}; - - -/** - * Clears the values in the background_image field. - */ -sketchology.proto.Command.prototype.clearBackgroundImage = function() { - this.clear$Field(10); -}; - - -/** - * Gets the value of the background_color field. - * @return {?sketchology.proto.BackgroundColor} The value. - */ -sketchology.proto.Command.prototype.getBackgroundColor = function() { - return /** @type {?sketchology.proto.BackgroundColor} */ (this.get$Value(11)); -}; - - -/** - * Gets the value of the background_color field or the default value if not set. - * @return {!sketchology.proto.BackgroundColor} The value. - */ -sketchology.proto.Command.prototype.getBackgroundColorOrDefault = function() { - return /** @type {!sketchology.proto.BackgroundColor} */ (this.get$ValueOrDefault(11)); -}; - - -/** - * Sets the value of the background_color field. - * @param {!sketchology.proto.BackgroundColor} value The value. - */ -sketchology.proto.Command.prototype.setBackgroundColor = function(value) { - this.set$Value(11, value); -}; - - -/** - * @return {boolean} Whether the background_color field has a value. - */ -sketchology.proto.Command.prototype.hasBackgroundColor = function() { - return this.has$Value(11); -}; - - -/** - * @return {number} The number of values in the background_color field. - */ -sketchology.proto.Command.prototype.backgroundColorCount = function() { - return this.count$Values(11); -}; - - -/** - * Clears the values in the background_color field. - */ -sketchology.proto.Command.prototype.clearBackgroundColor = function() { - this.clear$Field(11); -}; - - -/** - * Gets the value of the set_out_of_bounds_color field. - * @return {?sketchology.proto.OutOfBoundsColor} The value. - */ -sketchology.proto.Command.prototype.getSetOutOfBoundsColor = function() { - return /** @type {?sketchology.proto.OutOfBoundsColor} */ (this.get$Value(12)); -}; - - -/** - * Gets the value of the set_out_of_bounds_color field or the default value if not set. - * @return {!sketchology.proto.OutOfBoundsColor} The value. - */ -sketchology.proto.Command.prototype.getSetOutOfBoundsColorOrDefault = function() { - return /** @type {!sketchology.proto.OutOfBoundsColor} */ (this.get$ValueOrDefault(12)); -}; - - -/** - * Sets the value of the set_out_of_bounds_color field. - * @param {!sketchology.proto.OutOfBoundsColor} value The value. - */ -sketchology.proto.Command.prototype.setSetOutOfBoundsColor = function(value) { - this.set$Value(12, value); -}; - - -/** - * @return {boolean} Whether the set_out_of_bounds_color field has a value. - */ -sketchology.proto.Command.prototype.hasSetOutOfBoundsColor = function() { - return this.has$Value(12); -}; - - -/** - * @return {number} The number of values in the set_out_of_bounds_color field. - */ -sketchology.proto.Command.prototype.setOutOfBoundsColorCount = function() { - return this.count$Values(12); -}; - - -/** - * Clears the values in the set_out_of_bounds_color field. - */ -sketchology.proto.Command.prototype.clearSetOutOfBoundsColor = function() { - this.clear$Field(12); -}; - - -/** - * Gets the value of the set_page_border field. - * @return {?sketchology.proto.Border} The value. - */ -sketchology.proto.Command.prototype.getSetPageBorder = function() { - return /** @type {?sketchology.proto.Border} */ (this.get$Value(13)); -}; - - -/** - * Gets the value of the set_page_border field or the default value if not set. - * @return {!sketchology.proto.Border} The value. - */ -sketchology.proto.Command.prototype.getSetPageBorderOrDefault = function() { - return /** @type {!sketchology.proto.Border} */ (this.get$ValueOrDefault(13)); -}; - - -/** - * Sets the value of the set_page_border field. - * @param {!sketchology.proto.Border} value The value. - */ -sketchology.proto.Command.prototype.setSetPageBorder = function(value) { - this.set$Value(13, value); -}; - - -/** - * @return {boolean} Whether the set_page_border field has a value. - */ -sketchology.proto.Command.prototype.hasSetPageBorder = function() { - return this.has$Value(13); -}; - - -/** - * @return {number} The number of values in the set_page_border field. - */ -sketchology.proto.Command.prototype.setPageBorderCount = function() { - return this.count$Values(13); -}; - - -/** - * Clears the values in the set_page_border field. - */ -sketchology.proto.Command.prototype.clearSetPageBorder = function() { - this.clear$Field(13); -}; - - -/** - * Gets the value of the send_input_stream field. - * @return {?sketchology.proto.SInputStream} The value. - */ -sketchology.proto.Command.prototype.getSendInputStream = function() { - return /** @type {?sketchology.proto.SInputStream} */ (this.get$Value(14)); -}; - - -/** - * Gets the value of the send_input_stream field or the default value if not set. - * @return {!sketchology.proto.SInputStream} The value. - */ -sketchology.proto.Command.prototype.getSendInputStreamOrDefault = function() { - return /** @type {!sketchology.proto.SInputStream} */ (this.get$ValueOrDefault(14)); -}; - - -/** - * Sets the value of the send_input_stream field. - * @param {!sketchology.proto.SInputStream} value The value. - */ -sketchology.proto.Command.prototype.setSendInputStream = function(value) { - this.set$Value(14, value); -}; - - -/** - * @return {boolean} Whether the send_input_stream field has a value. - */ -sketchology.proto.Command.prototype.hasSendInputStream = function() { - return this.has$Value(14); -}; - - -/** - * @return {number} The number of values in the send_input_stream field. - */ -sketchology.proto.Command.prototype.sendInputStreamCount = function() { - return this.count$Values(14); -}; - - -/** - * Clears the values in the send_input_stream field. - */ -sketchology.proto.Command.prototype.clearSendInputStream = function() { - this.clear$Field(14); -}; - - -/** - * Gets the value of the sequence_point field. - * @return {?sketchology.proto.SequencePoint} The value. - */ -sketchology.proto.Command.prototype.getSequencePoint = function() { - return /** @type {?sketchology.proto.SequencePoint} */ (this.get$Value(15)); -}; - - -/** - * Gets the value of the sequence_point field or the default value if not set. - * @return {!sketchology.proto.SequencePoint} The value. - */ -sketchology.proto.Command.prototype.getSequencePointOrDefault = function() { - return /** @type {!sketchology.proto.SequencePoint} */ (this.get$ValueOrDefault(15)); -}; - - -/** - * Sets the value of the sequence_point field. - * @param {!sketchology.proto.SequencePoint} value The value. - */ -sketchology.proto.Command.prototype.setSequencePoint = function(value) { - this.set$Value(15, value); -}; - - -/** - * @return {boolean} Whether the sequence_point field has a value. - */ -sketchology.proto.Command.prototype.hasSequencePoint = function() { - return this.has$Value(15); -}; - - -/** - * @return {number} The number of values in the sequence_point field. - */ -sketchology.proto.Command.prototype.sequencePointCount = function() { - return this.count$Values(15); -}; - - -/** - * Clears the values in the sequence_point field. - */ -sketchology.proto.Command.prototype.clearSequencePoint = function() { - this.clear$Field(15); -}; - - -/** - * Gets the value of the set_callback_flags field. - * @return {?sketchology.proto.SetCallbackFlags} The value. - */ -sketchology.proto.Command.prototype.getSetCallbackFlags = function() { - return /** @type {?sketchology.proto.SetCallbackFlags} */ (this.get$Value(16)); -}; - - -/** - * Gets the value of the set_callback_flags field or the default value if not set. - * @return {!sketchology.proto.SetCallbackFlags} The value. - */ -sketchology.proto.Command.prototype.getSetCallbackFlagsOrDefault = function() { - return /** @type {!sketchology.proto.SetCallbackFlags} */ (this.get$ValueOrDefault(16)); -}; - - -/** - * Sets the value of the set_callback_flags field. - * @param {!sketchology.proto.SetCallbackFlags} value The value. - */ -sketchology.proto.Command.prototype.setSetCallbackFlags = function(value) { - this.set$Value(16, value); -}; - - -/** - * @return {boolean} Whether the set_callback_flags field has a value. - */ -sketchology.proto.Command.prototype.hasSetCallbackFlags = function() { - return this.has$Value(16); -}; - - -/** - * @return {number} The number of values in the set_callback_flags field. - */ -sketchology.proto.Command.prototype.setCallbackFlagsCount = function() { - return this.count$Values(16); -}; - - -/** - * Clears the values in the set_callback_flags field. - */ -sketchology.proto.Command.prototype.clearSetCallbackFlags = function() { - this.clear$Field(16); -}; - - -/** - * Gets the value of the set_camera_bounds_config field. - * @return {?sketchology.proto.CameraBoundsConfig} The value. - */ -sketchology.proto.Command.prototype.getSetCameraBoundsConfig = function() { - return /** @type {?sketchology.proto.CameraBoundsConfig} */ (this.get$Value(17)); -}; - - -/** - * Gets the value of the set_camera_bounds_config field or the default value if not set. - * @return {!sketchology.proto.CameraBoundsConfig} The value. - */ -sketchology.proto.Command.prototype.getSetCameraBoundsConfigOrDefault = function() { - return /** @type {!sketchology.proto.CameraBoundsConfig} */ (this.get$ValueOrDefault(17)); -}; - - -/** - * Sets the value of the set_camera_bounds_config field. - * @param {!sketchology.proto.CameraBoundsConfig} value The value. - */ -sketchology.proto.Command.prototype.setSetCameraBoundsConfig = function(value) { - this.set$Value(17, value); -}; - - -/** - * @return {boolean} Whether the set_camera_bounds_config field has a value. - */ -sketchology.proto.Command.prototype.hasSetCameraBoundsConfig = function() { - return this.has$Value(17); -}; - - -/** - * @return {number} The number of values in the set_camera_bounds_config field. - */ -sketchology.proto.Command.prototype.setCameraBoundsConfigCount = function() { - return this.count$Values(17); -}; - - -/** - * Clears the values in the set_camera_bounds_config field. - */ -sketchology.proto.Command.prototype.clearSetCameraBoundsConfig = function() { - this.clear$Field(17); -}; - - -/** - * Gets the value of the deselect_all field. - * @return {?sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getDeselectAll = function() { - return /** @type {?sketchology.proto.NoArgCommand} */ (this.get$Value(18)); -}; - - -/** - * Gets the value of the deselect_all field or the default value if not set. - * @return {!sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getDeselectAllOrDefault = function() { - return /** @type {!sketchology.proto.NoArgCommand} */ (this.get$ValueOrDefault(18)); -}; - - -/** - * Sets the value of the deselect_all field. - * @param {!sketchology.proto.NoArgCommand} value The value. - */ -sketchology.proto.Command.prototype.setDeselectAll = function(value) { - this.set$Value(18, value); -}; - - -/** - * @return {boolean} Whether the deselect_all field has a value. - */ -sketchology.proto.Command.prototype.hasDeselectAll = function() { - return this.has$Value(18); -}; - - -/** - * @return {number} The number of values in the deselect_all field. - */ -sketchology.proto.Command.prototype.deselectAllCount = function() { - return this.count$Values(18); -}; - - -/** - * Clears the values in the deselect_all field. - */ -sketchology.proto.Command.prototype.clearDeselectAll = function() { - this.clear$Field(18); -}; - - -/** - * Gets the value of the add_image_rect field. - * @return {?sketchology.proto.ImageRect} The value. - */ -sketchology.proto.Command.prototype.getAddImageRect = function() { - return /** @type {?sketchology.proto.ImageRect} */ (this.get$Value(19)); -}; - - -/** - * Gets the value of the add_image_rect field or the default value if not set. - * @return {!sketchology.proto.ImageRect} The value. - */ -sketchology.proto.Command.prototype.getAddImageRectOrDefault = function() { - return /** @type {!sketchology.proto.ImageRect} */ (this.get$ValueOrDefault(19)); -}; - - -/** - * Sets the value of the add_image_rect field. - * @param {!sketchology.proto.ImageRect} value The value. - */ -sketchology.proto.Command.prototype.setAddImageRect = function(value) { - this.set$Value(19, value); -}; - - -/** - * @return {boolean} Whether the add_image_rect field has a value. - */ -sketchology.proto.Command.prototype.hasAddImageRect = function() { - return this.has$Value(19); -}; - - -/** - * @return {number} The number of values in the add_image_rect field. - */ -sketchology.proto.Command.prototype.addImageRectCount = function() { - return this.count$Values(19); -}; - - -/** - * Clears the values in the add_image_rect field. - */ -sketchology.proto.Command.prototype.clearAddImageRect = function() { - this.clear$Field(19); -}; - - -/** - * Gets the value of the clear field. - * @return {?sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getClear = function() { - return /** @type {?sketchology.proto.NoArgCommand} */ (this.get$Value(21)); -}; - - -/** - * Gets the value of the clear field or the default value if not set. - * @return {!sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getClearOrDefault = function() { - return /** @type {!sketchology.proto.NoArgCommand} */ (this.get$ValueOrDefault(21)); -}; - - -/** - * Sets the value of the clear field. - * @param {!sketchology.proto.NoArgCommand} value The value. - */ -sketchology.proto.Command.prototype.setClear = function(value) { - this.set$Value(21, value); -}; - - -/** - * @return {boolean} Whether the clear field has a value. - */ -sketchology.proto.Command.prototype.hasClear = function() { - return this.has$Value(21); -}; - - -/** - * @return {number} The number of values in the clear field. - */ -sketchology.proto.Command.prototype.clearCount = function() { - return this.count$Values(21); -}; - - -/** - * Clears the values in the clear field. - */ -sketchology.proto.Command.prototype.clearClear = function() { - this.clear$Field(21); -}; - - -/** - * Gets the value of the remove_all_elements field. - * @return {?sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getRemoveAllElements = function() { - return /** @type {?sketchology.proto.NoArgCommand} */ (this.get$Value(22)); -}; - - -/** - * Gets the value of the remove_all_elements field or the default value if not set. - * @return {!sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getRemoveAllElementsOrDefault = function() { - return /** @type {!sketchology.proto.NoArgCommand} */ (this.get$ValueOrDefault(22)); -}; - - -/** - * Sets the value of the remove_all_elements field. - * @param {!sketchology.proto.NoArgCommand} value The value. - */ -sketchology.proto.Command.prototype.setRemoveAllElements = function(value) { - this.set$Value(22, value); -}; - - -/** - * @return {boolean} Whether the remove_all_elements field has a value. - */ -sketchology.proto.Command.prototype.hasRemoveAllElements = function() { - return this.has$Value(22); -}; - - -/** - * @return {number} The number of values in the remove_all_elements field. - */ -sketchology.proto.Command.prototype.removeAllElementsCount = function() { - return this.count$Values(22); -}; - - -/** - * Clears the values in the remove_all_elements field. - */ -sketchology.proto.Command.prototype.clearRemoveAllElements = function() { - this.clear$Field(22); -}; - - -/** - * Gets the value of the undo field. - * @return {?sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getUndo = function() { - return /** @type {?sketchology.proto.NoArgCommand} */ (this.get$Value(23)); -}; - - -/** - * Gets the value of the undo field or the default value if not set. - * @return {!sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getUndoOrDefault = function() { - return /** @type {!sketchology.proto.NoArgCommand} */ (this.get$ValueOrDefault(23)); -}; - - -/** - * Sets the value of the undo field. - * @param {!sketchology.proto.NoArgCommand} value The value. - */ -sketchology.proto.Command.prototype.setUndo = function(value) { - this.set$Value(23, value); -}; - - -/** - * @return {boolean} Whether the undo field has a value. - */ -sketchology.proto.Command.prototype.hasUndo = function() { - return this.has$Value(23); -}; - - -/** - * @return {number} The number of values in the undo field. - */ -sketchology.proto.Command.prototype.undoCount = function() { - return this.count$Values(23); -}; - - -/** - * Clears the values in the undo field. - */ -sketchology.proto.Command.prototype.clearUndo = function() { - this.clear$Field(23); -}; - - -/** - * Gets the value of the redo field. - * @return {?sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getRedo = function() { - return /** @type {?sketchology.proto.NoArgCommand} */ (this.get$Value(24)); -}; - - -/** - * Gets the value of the redo field or the default value if not set. - * @return {!sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getRedoOrDefault = function() { - return /** @type {!sketchology.proto.NoArgCommand} */ (this.get$ValueOrDefault(24)); -}; - - -/** - * Sets the value of the redo field. - * @param {!sketchology.proto.NoArgCommand} value The value. - */ -sketchology.proto.Command.prototype.setRedo = function(value) { - this.set$Value(24, value); -}; - - -/** - * @return {boolean} Whether the redo field has a value. - */ -sketchology.proto.Command.prototype.hasRedo = function() { - return this.has$Value(24); -}; - - -/** - * @return {number} The number of values in the redo field. - */ -sketchology.proto.Command.prototype.redoCount = function() { - return this.count$Values(24); -}; - - -/** - * Clears the values in the redo field. - */ -sketchology.proto.Command.prototype.clearRedo = function() { - this.clear$Field(24); -}; - - -/** - * Gets the value of the evict_image_data field. - * @return {?sketchology.proto.EvictImageData} The value. - */ -sketchology.proto.Command.prototype.getEvictImageData = function() { - return /** @type {?sketchology.proto.EvictImageData} */ (this.get$Value(25)); -}; - - -/** - * Gets the value of the evict_image_data field or the default value if not set. - * @return {!sketchology.proto.EvictImageData} The value. - */ -sketchology.proto.Command.prototype.getEvictImageDataOrDefault = function() { - return /** @type {!sketchology.proto.EvictImageData} */ (this.get$ValueOrDefault(25)); -}; - - -/** - * Sets the value of the evict_image_data field. - * @param {!sketchology.proto.EvictImageData} value The value. - */ -sketchology.proto.Command.prototype.setEvictImageData = function(value) { - this.set$Value(25, value); -}; - - -/** - * @return {boolean} Whether the evict_image_data field has a value. - */ -sketchology.proto.Command.prototype.hasEvictImageData = function() { - return this.has$Value(25); -}; - - -/** - * @return {number} The number of values in the evict_image_data field. - */ -sketchology.proto.Command.prototype.evictImageDataCount = function() { - return this.count$Values(25); -}; - - -/** - * Clears the values in the evict_image_data field. - */ -sketchology.proto.Command.prototype.clearEvictImageData = function() { - this.clear$Field(25); -}; - - -/** - * Gets the value of the replace_elements field. - * @return {?sketchology.proto.ReplaceElementsCommand} The value. - */ -sketchology.proto.Command.prototype.getReplaceElements = function() { - return /** @type {?sketchology.proto.ReplaceElementsCommand} */ (this.get$Value(26)); -}; - - -/** - * Gets the value of the replace_elements field or the default value if not set. - * @return {!sketchology.proto.ReplaceElementsCommand} The value. - */ -sketchology.proto.Command.prototype.getReplaceElementsOrDefault = function() { - return /** @type {!sketchology.proto.ReplaceElementsCommand} */ (this.get$ValueOrDefault(26)); -}; - - -/** - * Sets the value of the replace_elements field. - * @param {!sketchology.proto.ReplaceElementsCommand} value The value. - */ -sketchology.proto.Command.prototype.setReplaceElements = function(value) { - this.set$Value(26, value); -}; - - -/** - * @return {boolean} Whether the replace_elements field has a value. - */ -sketchology.proto.Command.prototype.hasReplaceElements = function() { - return this.has$Value(26); -}; - - -/** - * @return {number} The number of values in the replace_elements field. - */ -sketchology.proto.Command.prototype.replaceElementsCount = function() { - return this.count$Values(26); -}; - - -/** - * Clears the values in the replace_elements field. - */ -sketchology.proto.Command.prototype.clearReplaceElements = function() { - this.clear$Field(26); -}; - - -/** - * Gets the value of the commit_crop field. - * @return {?sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getCommitCrop = function() { - return /** @type {?sketchology.proto.NoArgCommand} */ (this.get$Value(27)); -}; - - -/** - * Gets the value of the commit_crop field or the default value if not set. - * @return {!sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getCommitCropOrDefault = function() { - return /** @type {!sketchology.proto.NoArgCommand} */ (this.get$ValueOrDefault(27)); -}; - - -/** - * Sets the value of the commit_crop field. - * @param {!sketchology.proto.NoArgCommand} value The value. - */ -sketchology.proto.Command.prototype.setCommitCrop = function(value) { - this.set$Value(27, value); -}; - - -/** - * @return {boolean} Whether the commit_crop field has a value. - */ -sketchology.proto.Command.prototype.hasCommitCrop = function() { - return this.has$Value(27); -}; - - -/** - * @return {number} The number of values in the commit_crop field. - */ -sketchology.proto.Command.prototype.commitCropCount = function() { - return this.count$Values(27); -}; - - -/** - * Clears the values in the commit_crop field. - */ -sketchology.proto.Command.prototype.clearCommitCrop = function() { - this.clear$Field(27); -}; - - -/** - * Gets the value of the element_animation field. - * @return {?sketchology.proto.ElementAnimation} The value. - */ -sketchology.proto.Command.prototype.getElementAnimation = function() { - return /** @type {?sketchology.proto.ElementAnimation} */ (this.get$Value(28)); -}; - - -/** - * Gets the value of the element_animation field or the default value if not set. - * @return {!sketchology.proto.ElementAnimation} The value. - */ -sketchology.proto.Command.prototype.getElementAnimationOrDefault = function() { - return /** @type {!sketchology.proto.ElementAnimation} */ (this.get$ValueOrDefault(28)); -}; - - -/** - * Sets the value of the element_animation field. - * @param {!sketchology.proto.ElementAnimation} value The value. - */ -sketchology.proto.Command.prototype.setElementAnimation = function(value) { - this.set$Value(28, value); -}; - - -/** - * @return {boolean} Whether the element_animation field has a value. - */ -sketchology.proto.Command.prototype.hasElementAnimation = function() { - return this.has$Value(28); -}; - - -/** - * @return {number} The number of values in the element_animation field. - */ -sketchology.proto.Command.prototype.elementAnimationCount = function() { - return this.count$Values(28); -}; - - -/** - * Clears the values in the element_animation field. - */ -sketchology.proto.Command.prototype.clearElementAnimation = function() { - this.clear$Field(28); -}; - - -/** - * Gets the value of the set_grid field. - * @return {?sketchology.proto.GridInfo} The value. - */ -sketchology.proto.Command.prototype.getSetGrid = function() { - return /** @type {?sketchology.proto.GridInfo} */ (this.get$Value(29)); -}; - - -/** - * Gets the value of the set_grid field or the default value if not set. - * @return {!sketchology.proto.GridInfo} The value. - */ -sketchology.proto.Command.prototype.getSetGridOrDefault = function() { - return /** @type {!sketchology.proto.GridInfo} */ (this.get$ValueOrDefault(29)); -}; - - -/** - * Sets the value of the set_grid field. - * @param {!sketchology.proto.GridInfo} value The value. - */ -sketchology.proto.Command.prototype.setSetGrid = function(value) { - this.set$Value(29, value); -}; - - -/** - * @return {boolean} Whether the set_grid field has a value. - */ -sketchology.proto.Command.prototype.hasSetGrid = function() { - return this.has$Value(29); -}; - - -/** - * @return {number} The number of values in the set_grid field. - */ -sketchology.proto.Command.prototype.setGridCount = function() { - return this.count$Values(29); -}; - - -/** - * Clears the values in the set_grid field. - */ -sketchology.proto.Command.prototype.clearSetGrid = function() { - this.clear$Field(29); -}; - - -/** - * Gets the value of the clear_grid field. - * @return {?sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getClearGrid = function() { - return /** @type {?sketchology.proto.NoArgCommand} */ (this.get$Value(30)); -}; - - -/** - * Gets the value of the clear_grid field or the default value if not set. - * @return {!sketchology.proto.NoArgCommand} The value. - */ -sketchology.proto.Command.prototype.getClearGridOrDefault = function() { - return /** @type {!sketchology.proto.NoArgCommand} */ (this.get$ValueOrDefault(30)); -}; - - -/** - * Sets the value of the clear_grid field. - * @param {!sketchology.proto.NoArgCommand} value The value. - */ -sketchology.proto.Command.prototype.setClearGrid = function(value) { - this.set$Value(30, value); -}; - - -/** - * @return {boolean} Whether the clear_grid field has a value. - */ -sketchology.proto.Command.prototype.hasClearGrid = function() { - return this.has$Value(30); -}; - - -/** - * @return {number} The number of values in the clear_grid field. - */ -sketchology.proto.Command.prototype.clearGridCount = function() { - return this.count$Values(30); -}; - - -/** - * Clears the values in the clear_grid field. - */ -sketchology.proto.Command.prototype.clearClearGrid = function() { - this.clear$Field(30); -}; - - - -/** - * Message CommandList. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.CommandList = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.CommandList, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.CommandList.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.CommandList} The cloned message. - * @override - */ -sketchology.proto.CommandList.prototype.clone; - - -/** - * Gets the value of the commands field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.Command} The value. - */ -sketchology.proto.CommandList.prototype.getCommands = function(index) { - return /** @type {?sketchology.proto.Command} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the commands field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.Command} The value. - */ -sketchology.proto.CommandList.prototype.getCommandsOrDefault = function(index) { - return /** @type {!sketchology.proto.Command} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the commands field. - * @param {!sketchology.proto.Command} value The value to add. - */ -sketchology.proto.CommandList.prototype.addCommands = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the commands field. - * @return {!Array<!sketchology.proto.Command>} The values in the field. - */ -sketchology.proto.CommandList.prototype.commandsArray = function() { - return /** @type {!Array<!sketchology.proto.Command>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the commands field has a value. - */ -sketchology.proto.CommandList.prototype.hasCommands = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the commands field. - */ -sketchology.proto.CommandList.prototype.commandsCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the commands field. - */ -sketchology.proto.CommandList.prototype.clearCommands = function() { - this.clear$Field(1); -}; - - - -/** - * Message NoArgCommand. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.NoArgCommand = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.NoArgCommand, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.NoArgCommand.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.NoArgCommand} The cloned message. - * @override - */ -sketchology.proto.NoArgCommand.prototype.clone; - - - -/** - * Message ReplaceElementsCommand. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ReplaceElementsCommand = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ReplaceElementsCommand, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ReplaceElementsCommand.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ReplaceElementsCommand} The cloned message. - * @override - */ -sketchology.proto.ReplaceElementsCommand.prototype.clone; - - -/** - * Gets the value of the uuids_to_remove field at the index given. - * @param {number} index The index to lookup. - * @return {?string} The value. - */ -sketchology.proto.ReplaceElementsCommand.prototype.getUuidsToRemove = function(index) { - return /** @type {?string} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the uuids_to_remove field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {string} The value. - */ -sketchology.proto.ReplaceElementsCommand.prototype.getUuidsToRemoveOrDefault = function(index) { - return /** @type {string} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the uuids_to_remove field. - * @param {string} value The value to add. - */ -sketchology.proto.ReplaceElementsCommand.prototype.addUuidsToRemove = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the uuids_to_remove field. - * @return {!Array<string>} The values in the field. - */ -sketchology.proto.ReplaceElementsCommand.prototype.uuidsToRemoveArray = function() { - return /** @type {!Array<string>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the uuids_to_remove field has a value. - */ -sketchology.proto.ReplaceElementsCommand.prototype.hasUuidsToRemove = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uuids_to_remove field. - */ -sketchology.proto.ReplaceElementsCommand.prototype.uuidsToRemoveCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uuids_to_remove field. - */ -sketchology.proto.ReplaceElementsCommand.prototype.clearUuidsToRemove = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the paths_to_add field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.Path} The value. - */ -sketchology.proto.ReplaceElementsCommand.prototype.getPathsToAdd = function(index) { - return /** @type {?sketchology.proto.Path} */ (this.get$Value(2, index)); -}; - - -/** - * Gets the value of the paths_to_add field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.Path} The value. - */ -sketchology.proto.ReplaceElementsCommand.prototype.getPathsToAddOrDefault = function(index) { - return /** @type {!sketchology.proto.Path} */ (this.get$ValueOrDefault(2, index)); -}; - - -/** - * Adds a value to the paths_to_add field. - * @param {!sketchology.proto.Path} value The value to add. - */ -sketchology.proto.ReplaceElementsCommand.prototype.addPathsToAdd = function(value) { - this.add$Value(2, value); -}; - - -/** - * Returns the array of values in the paths_to_add field. - * @return {!Array<!sketchology.proto.Path>} The values in the field. - */ -sketchology.proto.ReplaceElementsCommand.prototype.pathsToAddArray = function() { - return /** @type {!Array<!sketchology.proto.Path>} */ (this.array$Values(2)); -}; - - -/** - * @return {boolean} Whether the paths_to_add field has a value. - */ -sketchology.proto.ReplaceElementsCommand.prototype.hasPathsToAdd = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the paths_to_add field. - */ -sketchology.proto.ReplaceElementsCommand.prototype.pathsToAddCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the paths_to_add field. - */ -sketchology.proto.ReplaceElementsCommand.prototype.clearPathsToAdd = function() { - this.clear$Field(2); -}; - - - -/** - * Message EvictImageData. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.EvictImageData = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.EvictImageData, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.EvictImageData.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.EvictImageData} The cloned message. - * @override - */ -sketchology.proto.EvictImageData.prototype.clone; - - -/** - * Gets the value of the uri field. - * @return {?string} The value. - */ -sketchology.proto.EvictImageData.prototype.getUri = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the uri field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.EvictImageData.prototype.getUriOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the uri field. - * @param {string} value The value. - */ -sketchology.proto.EvictImageData.prototype.setUri = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the uri field has a value. - */ -sketchology.proto.EvictImageData.prototype.hasUri = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uri field. - */ -sketchology.proto.EvictImageData.prototype.uriCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uri field. - */ -sketchology.proto.EvictImageData.prototype.clearUri = function() { - this.clear$Field(1); -}; - - - -/** - * Message Viewport. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.Viewport = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.Viewport, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.Viewport.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.Viewport} The cloned message. - * @override - */ -sketchology.proto.Viewport.prototype.clone; - - -/** - * Gets the value of the fbo_handle field. - * @return {?number} The value. - */ -sketchology.proto.Viewport.prototype.getFboHandle = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the fbo_handle field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Viewport.prototype.getFboHandleOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the fbo_handle field. - * @param {number} value The value. - */ -sketchology.proto.Viewport.prototype.setFboHandle = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the fbo_handle field has a value. - */ -sketchology.proto.Viewport.prototype.hasFboHandle = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the fbo_handle field. - */ -sketchology.proto.Viewport.prototype.fboHandleCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the fbo_handle field. - */ -sketchology.proto.Viewport.prototype.clearFboHandle = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the width field. - * @return {?number} The value. - */ -sketchology.proto.Viewport.prototype.getWidth = function() { - return /** @type {?number} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the width field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Viewport.prototype.getWidthOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the width field. - * @param {number} value The value. - */ -sketchology.proto.Viewport.prototype.setWidth = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the width field has a value. - */ -sketchology.proto.Viewport.prototype.hasWidth = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the width field. - */ -sketchology.proto.Viewport.prototype.widthCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the width field. - */ -sketchology.proto.Viewport.prototype.clearWidth = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the height field. - * @return {?number} The value. - */ -sketchology.proto.Viewport.prototype.getHeight = function() { - return /** @type {?number} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the height field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Viewport.prototype.getHeightOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the height field. - * @param {number} value The value. - */ -sketchology.proto.Viewport.prototype.setHeight = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the height field has a value. - */ -sketchology.proto.Viewport.prototype.hasHeight = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the height field. - */ -sketchology.proto.Viewport.prototype.heightCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the height field. - */ -sketchology.proto.Viewport.prototype.clearHeight = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the ppi field. - * @return {?number} The value. - */ -sketchology.proto.Viewport.prototype.getPpi = function() { - return /** @type {?number} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the ppi field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.Viewport.prototype.getPpiOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the ppi field. - * @param {number} value The value. - */ -sketchology.proto.Viewport.prototype.setPpi = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the ppi field has a value. - */ -sketchology.proto.Viewport.prototype.hasPpi = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the ppi field. - */ -sketchology.proto.Viewport.prototype.ppiCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the ppi field. - */ -sketchology.proto.Viewport.prototype.clearPpi = function() { - this.clear$Field(4); -}; - - - -/** - * Message ImageExport. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ImageExport = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ImageExport, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ImageExport.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ImageExport} The cloned message. - * @override - */ -sketchology.proto.ImageExport.prototype.clone; - - -/** - * Gets the value of the max_dimension_px field. - * @return {?number} The value. - */ -sketchology.proto.ImageExport.prototype.getMaxDimensionPx = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the max_dimension_px field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.ImageExport.prototype.getMaxDimensionPxOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the max_dimension_px field. - * @param {number} value The value. - */ -sketchology.proto.ImageExport.prototype.setMaxDimensionPx = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the max_dimension_px field has a value. - */ -sketchology.proto.ImageExport.prototype.hasMaxDimensionPx = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the max_dimension_px field. - */ -sketchology.proto.ImageExport.prototype.maxDimensionPxCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the max_dimension_px field. - */ -sketchology.proto.ImageExport.prototype.clearMaxDimensionPx = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the should_draw_background field. - * @return {?boolean} The value. - */ -sketchology.proto.ImageExport.prototype.getShouldDrawBackground = function() { - return /** @type {?boolean} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the should_draw_background field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.ImageExport.prototype.getShouldDrawBackgroundOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the should_draw_background field. - * @param {boolean} value The value. - */ -sketchology.proto.ImageExport.prototype.setShouldDrawBackground = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the should_draw_background field has a value. - */ -sketchology.proto.ImageExport.prototype.hasShouldDrawBackground = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the should_draw_background field. - */ -sketchology.proto.ImageExport.prototype.shouldDrawBackgroundCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the should_draw_background field. - */ -sketchology.proto.ImageExport.prototype.clearShouldDrawBackground = function() { - this.clear$Field(2); -}; - - - -/** - * Message LinearPathAnimation. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.LinearPathAnimation = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.LinearPathAnimation, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.LinearPathAnimation.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.LinearPathAnimation} The cloned message. - * @override - */ -sketchology.proto.LinearPathAnimation.prototype.clone; - - -/** - * Gets the value of the rgba_from field. - * @return {?number} The value. - */ -sketchology.proto.LinearPathAnimation.prototype.getRgbaFrom = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the rgba_from field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.LinearPathAnimation.prototype.getRgbaFromOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the rgba_from field. - * @param {number} value The value. - */ -sketchology.proto.LinearPathAnimation.prototype.setRgbaFrom = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the rgba_from field has a value. - */ -sketchology.proto.LinearPathAnimation.prototype.hasRgbaFrom = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the rgba_from field. - */ -sketchology.proto.LinearPathAnimation.prototype.rgbaFromCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the rgba_from field. - */ -sketchology.proto.LinearPathAnimation.prototype.clearRgbaFrom = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the rgba_seconds field. - * @return {?number} The value. - */ -sketchology.proto.LinearPathAnimation.prototype.getRgbaSeconds = function() { - return /** @type {?number} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the rgba_seconds field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.LinearPathAnimation.prototype.getRgbaSecondsOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the rgba_seconds field. - * @param {number} value The value. - */ -sketchology.proto.LinearPathAnimation.prototype.setRgbaSeconds = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the rgba_seconds field has a value. - */ -sketchology.proto.LinearPathAnimation.prototype.hasRgbaSeconds = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the rgba_seconds field. - */ -sketchology.proto.LinearPathAnimation.prototype.rgbaSecondsCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the rgba_seconds field. - */ -sketchology.proto.LinearPathAnimation.prototype.clearRgbaSeconds = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the dilation_from field. - * @return {?number} The value. - */ -sketchology.proto.LinearPathAnimation.prototype.getDilationFrom = function() { - return /** @type {?number} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the dilation_from field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.LinearPathAnimation.prototype.getDilationFromOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the dilation_from field. - * @param {number} value The value. - */ -sketchology.proto.LinearPathAnimation.prototype.setDilationFrom = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the dilation_from field has a value. - */ -sketchology.proto.LinearPathAnimation.prototype.hasDilationFrom = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the dilation_from field. - */ -sketchology.proto.LinearPathAnimation.prototype.dilationFromCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the dilation_from field. - */ -sketchology.proto.LinearPathAnimation.prototype.clearDilationFrom = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the dilation_seconds field. - * @return {?number} The value. - */ -sketchology.proto.LinearPathAnimation.prototype.getDilationSeconds = function() { - return /** @type {?number} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the dilation_seconds field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.LinearPathAnimation.prototype.getDilationSecondsOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the dilation_seconds field. - * @param {number} value The value. - */ -sketchology.proto.LinearPathAnimation.prototype.setDilationSeconds = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the dilation_seconds field has a value. - */ -sketchology.proto.LinearPathAnimation.prototype.hasDilationSeconds = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the dilation_seconds field. - */ -sketchology.proto.LinearPathAnimation.prototype.dilationSecondsCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the dilation_seconds field. - */ -sketchology.proto.LinearPathAnimation.prototype.clearDilationSeconds = function() { - this.clear$Field(4); -}; - - - -/** - * Message LineSize. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.LineSize = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.LineSize, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.LineSize.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.LineSize} The cloned message. - * @override - */ -sketchology.proto.LineSize.prototype.clone; - - -/** - * Gets the value of the stroke_width field. - * @return {?number} The value. - */ -sketchology.proto.LineSize.prototype.getStrokeWidth = function() { - return /** @type {?number} */ (this.get$Value(7)); -}; - - -/** - * Gets the value of the stroke_width field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.LineSize.prototype.getStrokeWidthOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(7)); -}; - - -/** - * Sets the value of the stroke_width field. - * @param {number} value The value. - */ -sketchology.proto.LineSize.prototype.setStrokeWidth = function(value) { - this.set$Value(7, value); -}; - - -/** - * @return {boolean} Whether the stroke_width field has a value. - */ -sketchology.proto.LineSize.prototype.hasStrokeWidth = function() { - return this.has$Value(7); -}; - - -/** - * @return {number} The number of values in the stroke_width field. - */ -sketchology.proto.LineSize.prototype.strokeWidthCount = function() { - return this.count$Values(7); -}; - - -/** - * Clears the values in the stroke_width field. - */ -sketchology.proto.LineSize.prototype.clearStrokeWidth = function() { - this.clear$Field(7); -}; - - -/** - * Gets the value of the units field. - * @return {?sketchology.proto.LineSize.SizeType} The value. - */ -sketchology.proto.LineSize.prototype.getUnits = function() { - return /** @type {?sketchology.proto.LineSize.SizeType} */ (this.get$Value(8)); -}; - - -/** - * Gets the value of the units field or the default value if not set. - * @return {!sketchology.proto.LineSize.SizeType} The value. - */ -sketchology.proto.LineSize.prototype.getUnitsOrDefault = function() { - return /** @type {!sketchology.proto.LineSize.SizeType} */ (this.get$ValueOrDefault(8)); -}; - - -/** - * Sets the value of the units field. - * @param {!sketchology.proto.LineSize.SizeType} value The value. - */ -sketchology.proto.LineSize.prototype.setUnits = function(value) { - this.set$Value(8, value); -}; - - -/** - * @return {boolean} Whether the units field has a value. - */ -sketchology.proto.LineSize.prototype.hasUnits = function() { - return this.has$Value(8); -}; - - -/** - * @return {number} The number of values in the units field. - */ -sketchology.proto.LineSize.prototype.unitsCount = function() { - return this.count$Values(8); -}; - - -/** - * Clears the values in the units field. - */ -sketchology.proto.LineSize.prototype.clearUnits = function() { - this.clear$Field(8); -}; - - -/** - * Enumeration SizeType. - * @enum {number} - */ -sketchology.proto.LineSize.SizeType = { - UNKNOWN_SIZE: 0, - WORLD_UNITS: 1, - POINTS: 2, - ZOOM_INDEPENDENT_DP: 3, - PERCENT_WORLD: 4, - PERCENT_ZOOM_INDEPENDENT: 5 -}; - - - -/** - * Message PusherToolParams. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.PusherToolParams = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.PusherToolParams, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.PusherToolParams.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.PusherToolParams} The cloned message. - * @override - */ -sketchology.proto.PusherToolParams.prototype.clone; - - -/** - * Gets the value of the manipulate_stickers field. - * @return {?boolean} The value. - */ -sketchology.proto.PusherToolParams.prototype.getManipulateStickers = function() { - return /** @type {?boolean} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the manipulate_stickers field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.PusherToolParams.prototype.getManipulateStickersOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the manipulate_stickers field. - * @param {boolean} value The value. - */ -sketchology.proto.PusherToolParams.prototype.setManipulateStickers = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the manipulate_stickers field has a value. - */ -sketchology.proto.PusherToolParams.prototype.hasManipulateStickers = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the manipulate_stickers field. - */ -sketchology.proto.PusherToolParams.prototype.manipulateStickersCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the manipulate_stickers field. - */ -sketchology.proto.PusherToolParams.prototype.clearManipulateStickers = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the manipulate_text field. - * @return {?boolean} The value. - */ -sketchology.proto.PusherToolParams.prototype.getManipulateText = function() { - return /** @type {?boolean} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the manipulate_text field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.PusherToolParams.prototype.getManipulateTextOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the manipulate_text field. - * @param {boolean} value The value. - */ -sketchology.proto.PusherToolParams.prototype.setManipulateText = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the manipulate_text field has a value. - */ -sketchology.proto.PusherToolParams.prototype.hasManipulateText = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the manipulate_text field. - */ -sketchology.proto.PusherToolParams.prototype.manipulateTextCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the manipulate_text field. - */ -sketchology.proto.PusherToolParams.prototype.clearManipulateText = function() { - this.clear$Field(2); -}; - - - -/** - * Message ToolParams. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ToolParams = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ToolParams, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ToolParams.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ToolParams} The cloned message. - * @override - */ -sketchology.proto.ToolParams.prototype.clone; - - -/** - * Gets the value of the tool field. - * @return {?sketchology.proto.ToolParams.ToolType} The value. - */ -sketchology.proto.ToolParams.prototype.getTool = function() { - return /** @type {?sketchology.proto.ToolParams.ToolType} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the tool field or the default value if not set. - * @return {!sketchology.proto.ToolParams.ToolType} The value. - */ -sketchology.proto.ToolParams.prototype.getToolOrDefault = function() { - return /** @type {!sketchology.proto.ToolParams.ToolType} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the tool field. - * @param {!sketchology.proto.ToolParams.ToolType} value The value. - */ -sketchology.proto.ToolParams.prototype.setTool = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the tool field has a value. - */ -sketchology.proto.ToolParams.prototype.hasTool = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the tool field. - */ -sketchology.proto.ToolParams.prototype.toolCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the tool field. - */ -sketchology.proto.ToolParams.prototype.clearTool = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the rgba field. - * @return {?number} The value. - */ -sketchology.proto.ToolParams.prototype.getRgba = function() { - return /** @type {?number} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the rgba field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.ToolParams.prototype.getRgbaOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the rgba field. - * @param {number} value The value. - */ -sketchology.proto.ToolParams.prototype.setRgba = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the rgba field has a value. - */ -sketchology.proto.ToolParams.prototype.hasRgba = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the rgba field. - */ -sketchology.proto.ToolParams.prototype.rgbaCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the rgba field. - */ -sketchology.proto.ToolParams.prototype.clearRgba = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the line_size field. - * @return {?sketchology.proto.LineSize} The value. - */ -sketchology.proto.ToolParams.prototype.getLineSize = function() { - return /** @type {?sketchology.proto.LineSize} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the line_size field or the default value if not set. - * @return {!sketchology.proto.LineSize} The value. - */ -sketchology.proto.ToolParams.prototype.getLineSizeOrDefault = function() { - return /** @type {!sketchology.proto.LineSize} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the line_size field. - * @param {!sketchology.proto.LineSize} value The value. - */ -sketchology.proto.ToolParams.prototype.setLineSize = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the line_size field has a value. - */ -sketchology.proto.ToolParams.prototype.hasLineSize = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the line_size field. - */ -sketchology.proto.ToolParams.prototype.lineSizeCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the line_size field. - */ -sketchology.proto.ToolParams.prototype.clearLineSize = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the pusher_tool_params field. - * @return {?sketchology.proto.PusherToolParams} The value. - */ -sketchology.proto.ToolParams.prototype.getPusherToolParams = function() { - return /** @type {?sketchology.proto.PusherToolParams} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the pusher_tool_params field or the default value if not set. - * @return {!sketchology.proto.PusherToolParams} The value. - */ -sketchology.proto.ToolParams.prototype.getPusherToolParamsOrDefault = function() { - return /** @type {!sketchology.proto.PusherToolParams} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the pusher_tool_params field. - * @param {!sketchology.proto.PusherToolParams} value The value. - */ -sketchology.proto.ToolParams.prototype.setPusherToolParams = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the pusher_tool_params field has a value. - */ -sketchology.proto.ToolParams.prototype.hasPusherToolParams = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the pusher_tool_params field. - */ -sketchology.proto.ToolParams.prototype.pusherToolParamsCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the pusher_tool_params field. - */ -sketchology.proto.ToolParams.prototype.clearPusherToolParams = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the brush_type field. - * @return {?sketchology.proto.BrushType} The value. - */ -sketchology.proto.ToolParams.prototype.getBrushType = function() { - return /** @type {?sketchology.proto.BrushType} */ (this.get$Value(5)); -}; - - -/** - * Gets the value of the brush_type field or the default value if not set. - * @return {!sketchology.proto.BrushType} The value. - */ -sketchology.proto.ToolParams.prototype.getBrushTypeOrDefault = function() { - return /** @type {!sketchology.proto.BrushType} */ (this.get$ValueOrDefault(5)); -}; - - -/** - * Sets the value of the brush_type field. - * @param {!sketchology.proto.BrushType} value The value. - */ -sketchology.proto.ToolParams.prototype.setBrushType = function(value) { - this.set$Value(5, value); -}; - - -/** - * @return {boolean} Whether the brush_type field has a value. - */ -sketchology.proto.ToolParams.prototype.hasBrushType = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the brush_type field. - */ -sketchology.proto.ToolParams.prototype.brushTypeCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the brush_type field. - */ -sketchology.proto.ToolParams.prototype.clearBrushType = function() { - this.clear$Field(5); -}; - - -/** - * Gets the value of the linear_path_animation field. - * @return {?sketchology.proto.LinearPathAnimation} The value. - */ -sketchology.proto.ToolParams.prototype.getLinearPathAnimation = function() { - return /** @type {?sketchology.proto.LinearPathAnimation} */ (this.get$Value(6)); -}; - - -/** - * Gets the value of the linear_path_animation field or the default value if not set. - * @return {!sketchology.proto.LinearPathAnimation} The value. - */ -sketchology.proto.ToolParams.prototype.getLinearPathAnimationOrDefault = function() { - return /** @type {!sketchology.proto.LinearPathAnimation} */ (this.get$ValueOrDefault(6)); -}; - - -/** - * Sets the value of the linear_path_animation field. - * @param {!sketchology.proto.LinearPathAnimation} value The value. - */ -sketchology.proto.ToolParams.prototype.setLinearPathAnimation = function(value) { - this.set$Value(6, value); -}; - - -/** - * @return {boolean} Whether the linear_path_animation field has a value. - */ -sketchology.proto.ToolParams.prototype.hasLinearPathAnimation = function() { - return this.has$Value(6); -}; - - -/** - * @return {number} The number of values in the linear_path_animation field. - */ -sketchology.proto.ToolParams.prototype.linearPathAnimationCount = function() { - return this.count$Values(6); -}; - - -/** - * Clears the values in the linear_path_animation field. - */ -sketchology.proto.ToolParams.prototype.clearLinearPathAnimation = function() { - this.clear$Field(6); -}; - - -/** - * Enumeration ToolType. - * @enum {number} - */ -sketchology.proto.ToolParams.ToolType = { - UNKNOWN: 0, - LINE: 1, - EDIT: 2, - MAGIC_ERASE: 3, - QUERY: 4, - NOTOOL: 5, - FILTER_CHOOSER: 6, - PUSHER: 7, - CROP: 8 -}; - - - -/** - * Message FlagAssignment. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.FlagAssignment = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.FlagAssignment, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.FlagAssignment.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.FlagAssignment} The cloned message. - * @override - */ -sketchology.proto.FlagAssignment.prototype.clone; - - -/** - * Gets the value of the flag field. - * @return {?sketchology.proto.Flag} The value. - */ -sketchology.proto.FlagAssignment.prototype.getFlag = function() { - return /** @type {?sketchology.proto.Flag} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the flag field or the default value if not set. - * @return {!sketchology.proto.Flag} The value. - */ -sketchology.proto.FlagAssignment.prototype.getFlagOrDefault = function() { - return /** @type {!sketchology.proto.Flag} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the flag field. - * @param {!sketchology.proto.Flag} value The value. - */ -sketchology.proto.FlagAssignment.prototype.setFlag = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the flag field has a value. - */ -sketchology.proto.FlagAssignment.prototype.hasFlag = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the flag field. - */ -sketchology.proto.FlagAssignment.prototype.flagCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the flag field. - */ -sketchology.proto.FlagAssignment.prototype.clearFlag = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the bool_value field. - * @return {?boolean} The value. - */ -sketchology.proto.FlagAssignment.prototype.getBoolValue = function() { - return /** @type {?boolean} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the bool_value field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.FlagAssignment.prototype.getBoolValueOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the bool_value field. - * @param {boolean} value The value. - */ -sketchology.proto.FlagAssignment.prototype.setBoolValue = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the bool_value field has a value. - */ -sketchology.proto.FlagAssignment.prototype.hasBoolValue = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the bool_value field. - */ -sketchology.proto.FlagAssignment.prototype.boolValueCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the bool_value field. - */ -sketchology.proto.FlagAssignment.prototype.clearBoolValue = function() { - this.clear$Field(2); -}; - - - -/** - * Message AddElement. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.AddElement = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.AddElement, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.AddElement.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.AddElement} The cloned message. - * @override - */ -sketchology.proto.AddElement.prototype.clone; - - -/** - * Gets the value of the bundle field. - * @return {?sketchology.proto.ElementBundle} The value. - */ -sketchology.proto.AddElement.prototype.getBundle = function() { - return /** @type {?sketchology.proto.ElementBundle} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the bundle field or the default value if not set. - * @return {!sketchology.proto.ElementBundle} The value. - */ -sketchology.proto.AddElement.prototype.getBundleOrDefault = function() { - return /** @type {!sketchology.proto.ElementBundle} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the bundle field. - * @param {!sketchology.proto.ElementBundle} value The value. - */ -sketchology.proto.AddElement.prototype.setBundle = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the bundle field has a value. - */ -sketchology.proto.AddElement.prototype.hasBundle = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the bundle field. - */ -sketchology.proto.AddElement.prototype.bundleCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the bundle field. - */ -sketchology.proto.AddElement.prototype.clearBundle = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the below_element_with_uuid field. - * @return {?string} The value. - */ -sketchology.proto.AddElement.prototype.getBelowElementWithUuid = function() { - return /** @type {?string} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the below_element_with_uuid field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.AddElement.prototype.getBelowElementWithUuidOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the below_element_with_uuid field. - * @param {string} value The value. - */ -sketchology.proto.AddElement.prototype.setBelowElementWithUuid = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the below_element_with_uuid field has a value. - */ -sketchology.proto.AddElement.prototype.hasBelowElementWithUuid = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the below_element_with_uuid field. - */ -sketchology.proto.AddElement.prototype.belowElementWithUuidCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the below_element_with_uuid field. - */ -sketchology.proto.AddElement.prototype.clearBelowElementWithUuid = function() { - this.clear$Field(2); -}; - - - -/** - * Message OutOfBoundsColor. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.OutOfBoundsColor = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.OutOfBoundsColor, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.OutOfBoundsColor.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.OutOfBoundsColor} The cloned message. - * @override - */ -sketchology.proto.OutOfBoundsColor.prototype.clone; - - -/** - * Gets the value of the rgba field. - * @return {?number} The value. - */ -sketchology.proto.OutOfBoundsColor.prototype.getRgba = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the rgba field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.OutOfBoundsColor.prototype.getRgbaOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the rgba field. - * @param {number} value The value. - */ -sketchology.proto.OutOfBoundsColor.prototype.setRgba = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the rgba field has a value. - */ -sketchology.proto.OutOfBoundsColor.prototype.hasRgba = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the rgba field. - */ -sketchology.proto.OutOfBoundsColor.prototype.rgbaCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the rgba field. - */ -sketchology.proto.OutOfBoundsColor.prototype.clearRgba = function() { - this.clear$Field(1); -}; - - - -/** - * Message SInputStream. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.SInputStream = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.SInputStream, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.SInputStream.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.SInputStream} The cloned message. - * @override - */ -sketchology.proto.SInputStream.prototype.clone; - - -/** - * Gets the value of the screen_width field. - * @return {?number} The value. - */ -sketchology.proto.SInputStream.prototype.getScreenWidth = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the screen_width field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SInputStream.prototype.getScreenWidthOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the screen_width field. - * @param {number} value The value. - */ -sketchology.proto.SInputStream.prototype.setScreenWidth = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the screen_width field has a value. - */ -sketchology.proto.SInputStream.prototype.hasScreenWidth = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the screen_width field. - */ -sketchology.proto.SInputStream.prototype.screenWidthCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the screen_width field. - */ -sketchology.proto.SInputStream.prototype.clearScreenWidth = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the screen_height field. - * @return {?number} The value. - */ -sketchology.proto.SInputStream.prototype.getScreenHeight = function() { - return /** @type {?number} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the screen_height field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SInputStream.prototype.getScreenHeightOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the screen_height field. - * @param {number} value The value. - */ -sketchology.proto.SInputStream.prototype.setScreenHeight = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the screen_height field has a value. - */ -sketchology.proto.SInputStream.prototype.hasScreenHeight = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the screen_height field. - */ -sketchology.proto.SInputStream.prototype.screenHeightCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the screen_height field. - */ -sketchology.proto.SInputStream.prototype.clearScreenHeight = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the screen_ppi field. - * @return {?number} The value. - */ -sketchology.proto.SInputStream.prototype.getScreenPpi = function() { - return /** @type {?number} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the screen_ppi field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SInputStream.prototype.getScreenPpiOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the screen_ppi field. - * @param {number} value The value. - */ -sketchology.proto.SInputStream.prototype.setScreenPpi = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the screen_ppi field has a value. - */ -sketchology.proto.SInputStream.prototype.hasScreenPpi = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the screen_ppi field. - */ -sketchology.proto.SInputStream.prototype.screenPpiCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the screen_ppi field. - */ -sketchology.proto.SInputStream.prototype.clearScreenPpi = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the input field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.SInput} The value. - */ -sketchology.proto.SInputStream.prototype.getInput = function(index) { - return /** @type {?sketchology.proto.SInput} */ (this.get$Value(4, index)); -}; - - -/** - * Gets the value of the input field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.SInput} The value. - */ -sketchology.proto.SInputStream.prototype.getInputOrDefault = function(index) { - return /** @type {!sketchology.proto.SInput} */ (this.get$ValueOrDefault(4, index)); -}; - - -/** - * Adds a value to the input field. - * @param {!sketchology.proto.SInput} value The value to add. - */ -sketchology.proto.SInputStream.prototype.addInput = function(value) { - this.add$Value(4, value); -}; - - -/** - * Returns the array of values in the input field. - * @return {!Array<!sketchology.proto.SInput>} The values in the field. - */ -sketchology.proto.SInputStream.prototype.inputArray = function() { - return /** @type {!Array<!sketchology.proto.SInput>} */ (this.array$Values(4)); -}; - - -/** - * @return {boolean} Whether the input field has a value. - */ -sketchology.proto.SInputStream.prototype.hasInput = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the input field. - */ -sketchology.proto.SInputStream.prototype.inputCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the input field. - */ -sketchology.proto.SInputStream.prototype.clearInput = function() { - this.clear$Field(4); -}; - - - -/** - * Message SInput. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.SInput = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.SInput, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.SInput.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.SInput} The cloned message. - * @override - */ -sketchology.proto.SInput.prototype.clone; - - -/** - * Gets the value of the type field. - * @return {?sketchology.proto.SInput.InputType} The value. - */ -sketchology.proto.SInput.prototype.getType = function() { - return /** @type {?sketchology.proto.SInput.InputType} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the type field or the default value if not set. - * @return {!sketchology.proto.SInput.InputType} The value. - */ -sketchology.proto.SInput.prototype.getTypeOrDefault = function() { - return /** @type {!sketchology.proto.SInput.InputType} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the type field. - * @param {!sketchology.proto.SInput.InputType} value The value. - */ -sketchology.proto.SInput.prototype.setType = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the type field has a value. - */ -sketchology.proto.SInput.prototype.hasType = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the type field. - */ -sketchology.proto.SInput.prototype.typeCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the type field. - */ -sketchology.proto.SInput.prototype.clearType = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the id field. - * @return {?number} The value. - */ -sketchology.proto.SInput.prototype.getId = function() { - return /** @type {?number} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the id field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SInput.prototype.getIdOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the id field. - * @param {number} value The value. - */ -sketchology.proto.SInput.prototype.setId = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the id field has a value. - */ -sketchology.proto.SInput.prototype.hasId = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the id field. - */ -sketchology.proto.SInput.prototype.idCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the id field. - */ -sketchology.proto.SInput.prototype.clearId = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the flags field. - * @return {?number} The value. - */ -sketchology.proto.SInput.prototype.getFlags = function() { - return /** @type {?number} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the flags field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SInput.prototype.getFlagsOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the flags field. - * @param {number} value The value. - */ -sketchology.proto.SInput.prototype.setFlags = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the flags field has a value. - */ -sketchology.proto.SInput.prototype.hasFlags = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the flags field. - */ -sketchology.proto.SInput.prototype.flagsCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the flags field. - */ -sketchology.proto.SInput.prototype.clearFlags = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the time_s field. - * @return {?number} The value. - */ -sketchology.proto.SInput.prototype.getTimeS = function() { - return /** @type {?number} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the time_s field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SInput.prototype.getTimeSOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the time_s field. - * @param {number} value The value. - */ -sketchology.proto.SInput.prototype.setTimeS = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the time_s field has a value. - */ -sketchology.proto.SInput.prototype.hasTimeS = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the time_s field. - */ -sketchology.proto.SInput.prototype.timeSCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the time_s field. - */ -sketchology.proto.SInput.prototype.clearTimeS = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the screen_pos_x field. - * @return {?number} The value. - */ -sketchology.proto.SInput.prototype.getScreenPosX = function() { - return /** @type {?number} */ (this.get$Value(5)); -}; - - -/** - * Gets the value of the screen_pos_x field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SInput.prototype.getScreenPosXOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(5)); -}; - - -/** - * Sets the value of the screen_pos_x field. - * @param {number} value The value. - */ -sketchology.proto.SInput.prototype.setScreenPosX = function(value) { - this.set$Value(5, value); -}; - - -/** - * @return {boolean} Whether the screen_pos_x field has a value. - */ -sketchology.proto.SInput.prototype.hasScreenPosX = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the screen_pos_x field. - */ -sketchology.proto.SInput.prototype.screenPosXCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the screen_pos_x field. - */ -sketchology.proto.SInput.prototype.clearScreenPosX = function() { - this.clear$Field(5); -}; - - -/** - * Gets the value of the screen_pos_y field. - * @return {?number} The value. - */ -sketchology.proto.SInput.prototype.getScreenPosY = function() { - return /** @type {?number} */ (this.get$Value(6)); -}; - - -/** - * Gets the value of the screen_pos_y field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SInput.prototype.getScreenPosYOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(6)); -}; - - -/** - * Sets the value of the screen_pos_y field. - * @param {number} value The value. - */ -sketchology.proto.SInput.prototype.setScreenPosY = function(value) { - this.set$Value(6, value); -}; - - -/** - * @return {boolean} Whether the screen_pos_y field has a value. - */ -sketchology.proto.SInput.prototype.hasScreenPosY = function() { - return this.has$Value(6); -}; - - -/** - * @return {number} The number of values in the screen_pos_y field. - */ -sketchology.proto.SInput.prototype.screenPosYCount = function() { - return this.count$Values(6); -}; - - -/** - * Clears the values in the screen_pos_y field. - */ -sketchology.proto.SInput.prototype.clearScreenPosY = function() { - this.clear$Field(6); -}; - - -/** - * Gets the value of the pressure field. - * @return {?number} The value. - */ -sketchology.proto.SInput.prototype.getPressure = function() { - return /** @type {?number} */ (this.get$Value(7)); -}; - - -/** - * Gets the value of the pressure field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SInput.prototype.getPressureOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(7)); -}; - - -/** - * Sets the value of the pressure field. - * @param {number} value The value. - */ -sketchology.proto.SInput.prototype.setPressure = function(value) { - this.set$Value(7, value); -}; - - -/** - * @return {boolean} Whether the pressure field has a value. - */ -sketchology.proto.SInput.prototype.hasPressure = function() { - return this.has$Value(7); -}; - - -/** - * @return {number} The number of values in the pressure field. - */ -sketchology.proto.SInput.prototype.pressureCount = function() { - return this.count$Values(7); -}; - - -/** - * Clears the values in the pressure field. - */ -sketchology.proto.SInput.prototype.clearPressure = function() { - this.clear$Field(7); -}; - - -/** - * Gets the value of the wheel_delta field. - * @return {?number} The value. - */ -sketchology.proto.SInput.prototype.getWheelDelta = function() { - return /** @type {?number} */ (this.get$Value(8)); -}; - - -/** - * Gets the value of the wheel_delta field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SInput.prototype.getWheelDeltaOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(8)); -}; - - -/** - * Sets the value of the wheel_delta field. - * @param {number} value The value. - */ -sketchology.proto.SInput.prototype.setWheelDelta = function(value) { - this.set$Value(8, value); -}; - - -/** - * @return {boolean} Whether the wheel_delta field has a value. - */ -sketchology.proto.SInput.prototype.hasWheelDelta = function() { - return this.has$Value(8); -}; - - -/** - * @return {number} The number of values in the wheel_delta field. - */ -sketchology.proto.SInput.prototype.wheelDeltaCount = function() { - return this.count$Values(8); -}; - - -/** - * Clears the values in the wheel_delta field. - */ -sketchology.proto.SInput.prototype.clearWheelDelta = function() { - this.clear$Field(8); -}; - - -/** - * Gets the value of the tilt field. - * @return {?number} The value. - */ -sketchology.proto.SInput.prototype.getTilt = function() { - return /** @type {?number} */ (this.get$Value(9)); -}; - - -/** - * Gets the value of the tilt field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SInput.prototype.getTiltOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(9)); -}; - - -/** - * Sets the value of the tilt field. - * @param {number} value The value. - */ -sketchology.proto.SInput.prototype.setTilt = function(value) { - this.set$Value(9, value); -}; - - -/** - * @return {boolean} Whether the tilt field has a value. - */ -sketchology.proto.SInput.prototype.hasTilt = function() { - return this.has$Value(9); -}; - - -/** - * @return {number} The number of values in the tilt field. - */ -sketchology.proto.SInput.prototype.tiltCount = function() { - return this.count$Values(9); -}; - - -/** - * Clears the values in the tilt field. - */ -sketchology.proto.SInput.prototype.clearTilt = function() { - this.clear$Field(9); -}; - - -/** - * Gets the value of the orientation field. - * @return {?number} The value. - */ -sketchology.proto.SInput.prototype.getOrientation = function() { - return /** @type {?number} */ (this.get$Value(10)); -}; - - -/** - * Gets the value of the orientation field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SInput.prototype.getOrientationOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(10)); -}; - - -/** - * Sets the value of the orientation field. - * @param {number} value The value. - */ -sketchology.proto.SInput.prototype.setOrientation = function(value) { - this.set$Value(10, value); -}; - - -/** - * @return {boolean} Whether the orientation field has a value. - */ -sketchology.proto.SInput.prototype.hasOrientation = function() { - return this.has$Value(10); -}; - - -/** - * @return {number} The number of values in the orientation field. - */ -sketchology.proto.SInput.prototype.orientationCount = function() { - return this.count$Values(10); -}; - - -/** - * Clears the values in the orientation field. - */ -sketchology.proto.SInput.prototype.clearOrientation = function() { - this.clear$Field(10); -}; - - -/** - * Enumeration InputType. - * @enum {number} - */ -sketchology.proto.SInput.InputType = { - UNKNOWN: 0, - MOUSE: 1, - TOUCH: 2, - PEN: 3, - ERASER: 4 -}; - - - -/** - * Message SimulatedInput. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.SimulatedInput = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.SimulatedInput, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.SimulatedInput.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.SimulatedInput} The cloned message. - * @override - */ -sketchology.proto.SimulatedInput.prototype.clone; - - -/** - * Gets the value of the xs field at the index given. - * @param {number} index The index to lookup. - * @return {?number} The value. - */ -sketchology.proto.SimulatedInput.prototype.getXs = function(index) { - return /** @type {?number} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the xs field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {number} The value. - */ -sketchology.proto.SimulatedInput.prototype.getXsOrDefault = function(index) { - return /** @type {number} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the xs field. - * @param {number} value The value to add. - */ -sketchology.proto.SimulatedInput.prototype.addXs = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the xs field. - * @return {!Array<number>} The values in the field. - */ -sketchology.proto.SimulatedInput.prototype.xsArray = function() { - return /** @type {!Array<number>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the xs field has a value. - */ -sketchology.proto.SimulatedInput.prototype.hasXs = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the xs field. - */ -sketchology.proto.SimulatedInput.prototype.xsCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the xs field. - */ -sketchology.proto.SimulatedInput.prototype.clearXs = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the ys field at the index given. - * @param {number} index The index to lookup. - * @return {?number} The value. - */ -sketchology.proto.SimulatedInput.prototype.getYs = function(index) { - return /** @type {?number} */ (this.get$Value(2, index)); -}; - - -/** - * Gets the value of the ys field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {number} The value. - */ -sketchology.proto.SimulatedInput.prototype.getYsOrDefault = function(index) { - return /** @type {number} */ (this.get$ValueOrDefault(2, index)); -}; - - -/** - * Adds a value to the ys field. - * @param {number} value The value to add. - */ -sketchology.proto.SimulatedInput.prototype.addYs = function(value) { - this.add$Value(2, value); -}; - - -/** - * Returns the array of values in the ys field. - * @return {!Array<number>} The values in the field. - */ -sketchology.proto.SimulatedInput.prototype.ysArray = function() { - return /** @type {!Array<number>} */ (this.array$Values(2)); -}; - - -/** - * @return {boolean} Whether the ys field has a value. - */ -sketchology.proto.SimulatedInput.prototype.hasYs = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the ys field. - */ -sketchology.proto.SimulatedInput.prototype.ysCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the ys field. - */ -sketchology.proto.SimulatedInput.prototype.clearYs = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the ts_secs field at the index given. - * @param {number} index The index to lookup. - * @return {?number} The value. - */ -sketchology.proto.SimulatedInput.prototype.getTsSecs = function(index) { - return /** @type {?number} */ (this.get$Value(3, index)); -}; - - -/** - * Gets the value of the ts_secs field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {number} The value. - */ -sketchology.proto.SimulatedInput.prototype.getTsSecsOrDefault = function(index) { - return /** @type {number} */ (this.get$ValueOrDefault(3, index)); -}; - - -/** - * Adds a value to the ts_secs field. - * @param {number} value The value to add. - */ -sketchology.proto.SimulatedInput.prototype.addTsSecs = function(value) { - this.add$Value(3, value); -}; - - -/** - * Returns the array of values in the ts_secs field. - * @return {!Array<number>} The values in the field. - */ -sketchology.proto.SimulatedInput.prototype.tsSecsArray = function() { - return /** @type {!Array<number>} */ (this.array$Values(3)); -}; - - -/** - * @return {boolean} Whether the ts_secs field has a value. - */ -sketchology.proto.SimulatedInput.prototype.hasTsSecs = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the ts_secs field. - */ -sketchology.proto.SimulatedInput.prototype.tsSecsCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the ts_secs field. - */ -sketchology.proto.SimulatedInput.prototype.clearTsSecs = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the source_details field. - * @return {?sketchology.proto.SourceDetails} The value. - */ -sketchology.proto.SimulatedInput.prototype.getSourceDetails = function() { - return /** @type {?sketchology.proto.SourceDetails} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the source_details field or the default value if not set. - * @return {!sketchology.proto.SourceDetails} The value. - */ -sketchology.proto.SimulatedInput.prototype.getSourceDetailsOrDefault = function() { - return /** @type {!sketchology.proto.SourceDetails} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the source_details field. - * @param {!sketchology.proto.SourceDetails} value The value. - */ -sketchology.proto.SimulatedInput.prototype.setSourceDetails = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the source_details field has a value. - */ -sketchology.proto.SimulatedInput.prototype.hasSourceDetails = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the source_details field. - */ -sketchology.proto.SimulatedInput.prototype.sourceDetailsCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the source_details field. - */ -sketchology.proto.SimulatedInput.prototype.clearSourceDetails = function() { - this.clear$Field(4); -}; - - - -/** - * Message SequencePoint. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.SequencePoint = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.SequencePoint, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.SequencePoint.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.SequencePoint} The cloned message. - * @override - */ -sketchology.proto.SequencePoint.prototype.clone; - - -/** - * Gets the value of the id field. - * @return {?number} The value. - */ -sketchology.proto.SequencePoint.prototype.getId = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the id field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.SequencePoint.prototype.getIdOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the id field. - * @param {number} value The value. - */ -sketchology.proto.SequencePoint.prototype.setId = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the id field has a value. - */ -sketchology.proto.SequencePoint.prototype.hasId = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the id field. - */ -sketchology.proto.SequencePoint.prototype.idCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the id field. - */ -sketchology.proto.SequencePoint.prototype.clearId = function() { - this.clear$Field(1); -}; - - - -/** - * Message SetCallbackFlags. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.SetCallbackFlags = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.SetCallbackFlags, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.SetCallbackFlags.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.SetCallbackFlags} The cloned message. - * @override - */ -sketchology.proto.SetCallbackFlags.prototype.clone; - - -/** - * Gets the value of the source_details field. - * @return {?sketchology.proto.SourceDetails} The value. - */ -sketchology.proto.SetCallbackFlags.prototype.getSourceDetails = function() { - return /** @type {?sketchology.proto.SourceDetails} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the source_details field or the default value if not set. - * @return {!sketchology.proto.SourceDetails} The value. - */ -sketchology.proto.SetCallbackFlags.prototype.getSourceDetailsOrDefault = function() { - return /** @type {!sketchology.proto.SourceDetails} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the source_details field. - * @param {!sketchology.proto.SourceDetails} value The value. - */ -sketchology.proto.SetCallbackFlags.prototype.setSourceDetails = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the source_details field has a value. - */ -sketchology.proto.SetCallbackFlags.prototype.hasSourceDetails = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the source_details field. - */ -sketchology.proto.SetCallbackFlags.prototype.sourceDetailsCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the source_details field. - */ -sketchology.proto.SetCallbackFlags.prototype.clearSourceDetails = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the callback_flags field. - * @return {?sketchology.proto.CallbackFlags} The value. - */ -sketchology.proto.SetCallbackFlags.prototype.getCallbackFlags = function() { - return /** @type {?sketchology.proto.CallbackFlags} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the callback_flags field or the default value if not set. - * @return {!sketchology.proto.CallbackFlags} The value. - */ -sketchology.proto.SetCallbackFlags.prototype.getCallbackFlagsOrDefault = function() { - return /** @type {!sketchology.proto.CallbackFlags} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the callback_flags field. - * @param {!sketchology.proto.CallbackFlags} value The value. - */ -sketchology.proto.SetCallbackFlags.prototype.setCallbackFlags = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the callback_flags field has a value. - */ -sketchology.proto.SetCallbackFlags.prototype.hasCallbackFlags = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the callback_flags field. - */ -sketchology.proto.SetCallbackFlags.prototype.callbackFlagsCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the callback_flags field. - */ -sketchology.proto.SetCallbackFlags.prototype.clearCallbackFlags = function() { - this.clear$Field(2); -}; - - - -/** - * Message EngineState. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.EngineState = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.EngineState, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.EngineState.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.EngineState} The cloned message. - * @override - */ -sketchology.proto.EngineState.prototype.clone; - - -/** - * Gets the value of the camera_position field. - * @return {?sketchology.proto.Rect} The value. - */ -sketchology.proto.EngineState.prototype.getCameraPosition = function() { - return /** @type {?sketchology.proto.Rect} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the camera_position field or the default value if not set. - * @return {!sketchology.proto.Rect} The value. - */ -sketchology.proto.EngineState.prototype.getCameraPositionOrDefault = function() { - return /** @type {!sketchology.proto.Rect} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the camera_position field. - * @param {!sketchology.proto.Rect} value The value. - */ -sketchology.proto.EngineState.prototype.setCameraPosition = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the camera_position field has a value. - */ -sketchology.proto.EngineState.prototype.hasCameraPosition = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the camera_position field. - */ -sketchology.proto.EngineState.prototype.cameraPositionCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the camera_position field. - */ -sketchology.proto.EngineState.prototype.clearCameraPosition = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the page_bounds field. - * @return {?sketchology.proto.Rect} The value. - */ -sketchology.proto.EngineState.prototype.getPageBounds = function() { - return /** @type {?sketchology.proto.Rect} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the page_bounds field or the default value if not set. - * @return {!sketchology.proto.Rect} The value. - */ -sketchology.proto.EngineState.prototype.getPageBoundsOrDefault = function() { - return /** @type {!sketchology.proto.Rect} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the page_bounds field. - * @param {!sketchology.proto.Rect} value The value. - */ -sketchology.proto.EngineState.prototype.setPageBounds = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the page_bounds field has a value. - */ -sketchology.proto.EngineState.prototype.hasPageBounds = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the page_bounds field. - */ -sketchology.proto.EngineState.prototype.pageBoundsCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the page_bounds field. - */ -sketchology.proto.EngineState.prototype.clearPageBounds = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the selection_is_live field. - * @return {?boolean} The value. - */ -sketchology.proto.EngineState.prototype.getSelectionIsLive = function() { - return /** @type {?boolean} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the selection_is_live field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.EngineState.prototype.getSelectionIsLiveOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the selection_is_live field. - * @param {boolean} value The value. - */ -sketchology.proto.EngineState.prototype.setSelectionIsLive = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the selection_is_live field has a value. - */ -sketchology.proto.EngineState.prototype.hasSelectionIsLive = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the selection_is_live field. - */ -sketchology.proto.EngineState.prototype.selectionIsLiveCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the selection_is_live field. - */ -sketchology.proto.EngineState.prototype.clearSelectionIsLive = function() { - this.clear$Field(3); -}; - - - -/** - * Message CameraBoundsConfig. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.CameraBoundsConfig = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.CameraBoundsConfig, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.CameraBoundsConfig.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.CameraBoundsConfig} The cloned message. - * @override - */ -sketchology.proto.CameraBoundsConfig.prototype.clone; - - -/** - * Gets the value of the margin_left_px field. - * @return {?number} The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.getMarginLeftPx = function() { - return /** @type {?number} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the margin_left_px field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.getMarginLeftPxOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the margin_left_px field. - * @param {number} value The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.setMarginLeftPx = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the margin_left_px field has a value. - */ -sketchology.proto.CameraBoundsConfig.prototype.hasMarginLeftPx = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the margin_left_px field. - */ -sketchology.proto.CameraBoundsConfig.prototype.marginLeftPxCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the margin_left_px field. - */ -sketchology.proto.CameraBoundsConfig.prototype.clearMarginLeftPx = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the margin_right_px field. - * @return {?number} The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.getMarginRightPx = function() { - return /** @type {?number} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the margin_right_px field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.getMarginRightPxOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the margin_right_px field. - * @param {number} value The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.setMarginRightPx = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the margin_right_px field has a value. - */ -sketchology.proto.CameraBoundsConfig.prototype.hasMarginRightPx = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the margin_right_px field. - */ -sketchology.proto.CameraBoundsConfig.prototype.marginRightPxCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the margin_right_px field. - */ -sketchology.proto.CameraBoundsConfig.prototype.clearMarginRightPx = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the margin_bottom_px field. - * @return {?number} The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.getMarginBottomPx = function() { - return /** @type {?number} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the margin_bottom_px field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.getMarginBottomPxOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the margin_bottom_px field. - * @param {number} value The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.setMarginBottomPx = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the margin_bottom_px field has a value. - */ -sketchology.proto.CameraBoundsConfig.prototype.hasMarginBottomPx = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the margin_bottom_px field. - */ -sketchology.proto.CameraBoundsConfig.prototype.marginBottomPxCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the margin_bottom_px field. - */ -sketchology.proto.CameraBoundsConfig.prototype.clearMarginBottomPx = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the margin_top_px field. - * @return {?number} The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.getMarginTopPx = function() { - return /** @type {?number} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the margin_top_px field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.getMarginTopPxOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the margin_top_px field. - * @param {number} value The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.setMarginTopPx = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the margin_top_px field has a value. - */ -sketchology.proto.CameraBoundsConfig.prototype.hasMarginTopPx = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the margin_top_px field. - */ -sketchology.proto.CameraBoundsConfig.prototype.marginTopPxCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the margin_top_px field. - */ -sketchology.proto.CameraBoundsConfig.prototype.clearMarginTopPx = function() { - this.clear$Field(4); -}; - - -/** - * Gets the value of the fraction_padding field. - * @return {?number} The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.getFractionPadding = function() { - return /** @type {?number} */ (this.get$Value(5)); -}; - - -/** - * Gets the value of the fraction_padding field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.getFractionPaddingOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(5)); -}; - - -/** - * Sets the value of the fraction_padding field. - * @param {number} value The value. - */ -sketchology.proto.CameraBoundsConfig.prototype.setFractionPadding = function(value) { - this.set$Value(5, value); -}; - - -/** - * @return {boolean} Whether the fraction_padding field has a value. - */ -sketchology.proto.CameraBoundsConfig.prototype.hasFractionPadding = function() { - return this.has$Value(5); -}; - - -/** - * @return {number} The number of values in the fraction_padding field. - */ -sketchology.proto.CameraBoundsConfig.prototype.fractionPaddingCount = function() { - return this.count$Values(5); -}; - - -/** - * Clears the values in the fraction_padding field. - */ -sketchology.proto.CameraBoundsConfig.prototype.clearFractionPadding = function() { - this.clear$Field(5); -}; - - - -/** - * Message ImageInfo. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ImageInfo = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ImageInfo, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ImageInfo.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ImageInfo} The cloned message. - * @override - */ -sketchology.proto.ImageInfo.prototype.clone; - - -/** - * Gets the value of the uri field. - * @return {?string} The value. - */ -sketchology.proto.ImageInfo.prototype.getUri = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the uri field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.ImageInfo.prototype.getUriOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the uri field. - * @param {string} value The value. - */ -sketchology.proto.ImageInfo.prototype.setUri = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the uri field has a value. - */ -sketchology.proto.ImageInfo.prototype.hasUri = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uri field. - */ -sketchology.proto.ImageInfo.prototype.uriCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uri field. - */ -sketchology.proto.ImageInfo.prototype.clearUri = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the asset_type field. - * @return {?sketchology.proto.ImageInfo.AssetType} The value. - */ -sketchology.proto.ImageInfo.prototype.getAssetType = function() { - return /** @type {?sketchology.proto.ImageInfo.AssetType} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the asset_type field or the default value if not set. - * @return {!sketchology.proto.ImageInfo.AssetType} The value. - */ -sketchology.proto.ImageInfo.prototype.getAssetTypeOrDefault = function() { - return /** @type {!sketchology.proto.ImageInfo.AssetType} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the asset_type field. - * @param {!sketchology.proto.ImageInfo.AssetType} value The value. - */ -sketchology.proto.ImageInfo.prototype.setAssetType = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the asset_type field has a value. - */ -sketchology.proto.ImageInfo.prototype.hasAssetType = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the asset_type field. - */ -sketchology.proto.ImageInfo.prototype.assetTypeCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the asset_type field. - */ -sketchology.proto.ImageInfo.prototype.clearAssetType = function() { - this.clear$Field(2); -}; - - -/** - * Enumeration AssetType. - * @enum {number} - */ -sketchology.proto.ImageInfo.AssetType = { - DEFAULT: 0, - BORDER: 1, - STICKER: 2, - GRID: 3 -}; - - - -/** - * Message ImageRect. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ImageRect = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ImageRect, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ImageRect.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ImageRect} The cloned message. - * @override - */ -sketchology.proto.ImageRect.prototype.clone; - - -/** - * Gets the value of the rect field. - * @return {?sketchology.proto.Rect} The value. - */ -sketchology.proto.ImageRect.prototype.getRect = function() { - return /** @type {?sketchology.proto.Rect} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the rect field or the default value if not set. - * @return {!sketchology.proto.Rect} The value. - */ -sketchology.proto.ImageRect.prototype.getRectOrDefault = function() { - return /** @type {!sketchology.proto.Rect} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the rect field. - * @param {!sketchology.proto.Rect} value The value. - */ -sketchology.proto.ImageRect.prototype.setRect = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the rect field has a value. - */ -sketchology.proto.ImageRect.prototype.hasRect = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the rect field. - */ -sketchology.proto.ImageRect.prototype.rectCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the rect field. - */ -sketchology.proto.ImageRect.prototype.clearRect = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the bitmap_uri field. - * @return {?string} The value. - */ -sketchology.proto.ImageRect.prototype.getBitmapUri = function() { - return /** @type {?string} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the bitmap_uri field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.ImageRect.prototype.getBitmapUriOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the bitmap_uri field. - * @param {string} value The value. - */ -sketchology.proto.ImageRect.prototype.setBitmapUri = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the bitmap_uri field has a value. - */ -sketchology.proto.ImageRect.prototype.hasBitmapUri = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the bitmap_uri field. - */ -sketchology.proto.ImageRect.prototype.bitmapUriCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the bitmap_uri field. - */ -sketchology.proto.ImageRect.prototype.clearBitmapUri = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the attributes field. - * @return {?sketchology.proto.ElementAttributes} The value. - */ -sketchology.proto.ImageRect.prototype.getAttributes = function() { - return /** @type {?sketchology.proto.ElementAttributes} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the attributes field or the default value if not set. - * @return {!sketchology.proto.ElementAttributes} The value. - */ -sketchology.proto.ImageRect.prototype.getAttributesOrDefault = function() { - return /** @type {!sketchology.proto.ElementAttributes} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the attributes field. - * @param {!sketchology.proto.ElementAttributes} value The value. - */ -sketchology.proto.ImageRect.prototype.setAttributes = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the attributes field has a value. - */ -sketchology.proto.ImageRect.prototype.hasAttributes = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the attributes field. - */ -sketchology.proto.ImageRect.prototype.attributesCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the attributes field. - */ -sketchology.proto.ImageRect.prototype.clearAttributes = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the rotation_radians field. - * @return {?number} The value. - */ -sketchology.proto.ImageRect.prototype.getRotationRadians = function() { - return /** @type {?number} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the rotation_radians field or the default value if not set. - * @return {number} The value. - */ -sketchology.proto.ImageRect.prototype.getRotationRadiansOrDefault = function() { - return /** @type {number} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the rotation_radians field. - * @param {number} value The value. - */ -sketchology.proto.ImageRect.prototype.setRotationRadians = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the rotation_radians field has a value. - */ -sketchology.proto.ImageRect.prototype.hasRotationRadians = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the rotation_radians field. - */ -sketchology.proto.ImageRect.prototype.rotationRadiansCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the rotation_radians field. - */ -sketchology.proto.ImageRect.prototype.clearRotationRadians = function() { - this.clear$Field(4); -}; - - - -/** - * Message GridInfo. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.GridInfo = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.GridInfo, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.GridInfo.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.GridInfo} The cloned message. - * @override - */ -sketchology.proto.GridInfo.prototype.clone; - - -/** - * Gets the value of the uri field. - * @return {?string} The value. - */ -sketchology.proto.GridInfo.prototype.getUri = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the uri field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.GridInfo.prototype.getUriOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the uri field. - * @param {string} value The value. - */ -sketchology.proto.GridInfo.prototype.setUri = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the uri field has a value. - */ -sketchology.proto.GridInfo.prototype.hasUri = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uri field. - */ -sketchology.proto.GridInfo.prototype.uriCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uri field. - */ -sketchology.proto.GridInfo.prototype.clearUri = function() { - this.clear$Field(1); -}; - - - -/** - * Message CreateDocument. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.CreateDocument = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.CreateDocument, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.CreateDocument.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.CreateDocument} The cloned message. - * @override - */ -sketchology.proto.CreateDocument.prototype.clone; - - -/** - * Gets the value of the document_type field. - * @return {?sketchology.proto.DocumentType} The value. - */ -sketchology.proto.CreateDocument.prototype.getDocumentType = function() { - return /** @type {?sketchology.proto.DocumentType} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the document_type field or the default value if not set. - * @return {!sketchology.proto.DocumentType} The value. - */ -sketchology.proto.CreateDocument.prototype.getDocumentTypeOrDefault = function() { - return /** @type {!sketchology.proto.DocumentType} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the document_type field. - * @param {!sketchology.proto.DocumentType} value The value. - */ -sketchology.proto.CreateDocument.prototype.setDocumentType = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the document_type field has a value. - */ -sketchology.proto.CreateDocument.prototype.hasDocumentType = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the document_type field. - */ -sketchology.proto.CreateDocument.prototype.documentTypeCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the document_type field. - */ -sketchology.proto.CreateDocument.prototype.clearDocumentType = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the storage_type field. - * @return {?sketchology.proto.StorageType} The value. - */ -sketchology.proto.CreateDocument.prototype.getStorageType = function() { - return /** @type {?sketchology.proto.StorageType} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the storage_type field or the default value if not set. - * @return {!sketchology.proto.StorageType} The value. - */ -sketchology.proto.CreateDocument.prototype.getStorageTypeOrDefault = function() { - return /** @type {!sketchology.proto.StorageType} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the storage_type field. - * @param {!sketchology.proto.StorageType} value The value. - */ -sketchology.proto.CreateDocument.prototype.setStorageType = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the storage_type field has a value. - */ -sketchology.proto.CreateDocument.prototype.hasStorageType = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the storage_type field. - */ -sketchology.proto.CreateDocument.prototype.storageTypeCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the storage_type field. - */ -sketchology.proto.CreateDocument.prototype.clearStorageType = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the storage_path field. - * @return {?string} The value. - */ -sketchology.proto.CreateDocument.prototype.getStoragePath = function() { - return /** @type {?string} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the storage_path field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.CreateDocument.prototype.getStoragePathOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the storage_path field. - * @param {string} value The value. - */ -sketchology.proto.CreateDocument.prototype.setStoragePath = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the storage_path field has a value. - */ -sketchology.proto.CreateDocument.prototype.hasStoragePath = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the storage_path field. - */ -sketchology.proto.CreateDocument.prototype.storagePathCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the storage_path field. - */ -sketchology.proto.CreateDocument.prototype.clearStoragePath = function() { - this.clear$Field(3); -}; - - -/** - * Gets the value of the snapshot field. - * @return {?sketchology.proto.Snapshot} The value. - */ -sketchology.proto.CreateDocument.prototype.getSnapshot = function() { - return /** @type {?sketchology.proto.Snapshot} */ (this.get$Value(4)); -}; - - -/** - * Gets the value of the snapshot field or the default value if not set. - * @return {!sketchology.proto.Snapshot} The value. - */ -sketchology.proto.CreateDocument.prototype.getSnapshotOrDefault = function() { - return /** @type {!sketchology.proto.Snapshot} */ (this.get$ValueOrDefault(4)); -}; - - -/** - * Sets the value of the snapshot field. - * @param {!sketchology.proto.Snapshot} value The value. - */ -sketchology.proto.CreateDocument.prototype.setSnapshot = function(value) { - this.set$Value(4, value); -}; - - -/** - * @return {boolean} Whether the snapshot field has a value. - */ -sketchology.proto.CreateDocument.prototype.hasSnapshot = function() { - return this.has$Value(4); -}; - - -/** - * @return {number} The number of values in the snapshot field. - */ -sketchology.proto.CreateDocument.prototype.snapshotCount = function() { - return this.count$Values(4); -}; - - -/** - * Clears the values in the snapshot field. - */ -sketchology.proto.CreateDocument.prototype.clearSnapshot = function() { - this.clear$Field(4); -}; - - - -/** - * Message AddPath. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.AddPath = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.AddPath, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.AddPath.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.AddPath} The cloned message. - * @override - */ -sketchology.proto.AddPath.prototype.clone; - - -/** - * Gets the value of the path field. - * @return {?sketchology.proto.Path} The value. - */ -sketchology.proto.AddPath.prototype.getPath = function() { - return /** @type {?sketchology.proto.Path} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the path field or the default value if not set. - * @return {!sketchology.proto.Path} The value. - */ -sketchology.proto.AddPath.prototype.getPathOrDefault = function() { - return /** @type {!sketchology.proto.Path} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the path field. - * @param {!sketchology.proto.Path} value The value. - */ -sketchology.proto.AddPath.prototype.setPath = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the path field has a value. - */ -sketchology.proto.AddPath.prototype.hasPath = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the path field. - */ -sketchology.proto.AddPath.prototype.pathCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the path field. - */ -sketchology.proto.AddPath.prototype.clearPath = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the uuid field. - * @return {?string} The value. - */ -sketchology.proto.AddPath.prototype.getUuid = function() { - return /** @type {?string} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the uuid field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.AddPath.prototype.getUuidOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the uuid field. - * @param {string} value The value. - */ -sketchology.proto.AddPath.prototype.setUuid = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the uuid field has a value. - */ -sketchology.proto.AddPath.prototype.hasUuid = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the uuid field. - */ -sketchology.proto.AddPath.prototype.uuidCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the uuid field. - */ -sketchology.proto.AddPath.prototype.clearUuid = function() { - this.clear$Field(2); -}; - - - -/** - * Message PusherPositionUpdate. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.PusherPositionUpdate = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.PusherPositionUpdate, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.PusherPositionUpdate.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.PusherPositionUpdate} The cloned message. - * @override - */ -sketchology.proto.PusherPositionUpdate.prototype.clone; - - -/** - * Gets the value of the uuid field. - * @return {?string} The value. - */ -sketchology.proto.PusherPositionUpdate.prototype.getUuid = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the uuid field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.PusherPositionUpdate.prototype.getUuidOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the uuid field. - * @param {string} value The value. - */ -sketchology.proto.PusherPositionUpdate.prototype.setUuid = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the uuid field has a value. - */ -sketchology.proto.PusherPositionUpdate.prototype.hasUuid = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uuid field. - */ -sketchology.proto.PusherPositionUpdate.prototype.uuidCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uuid field. - */ -sketchology.proto.PusherPositionUpdate.prototype.clearUuid = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the pointer_location field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.Point} The value. - */ -sketchology.proto.PusherPositionUpdate.prototype.getPointerLocation = function(index) { - return /** @type {?sketchology.proto.Point} */ (this.get$Value(2, index)); -}; - - -/** - * Gets the value of the pointer_location field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.Point} The value. - */ -sketchology.proto.PusherPositionUpdate.prototype.getPointerLocationOrDefault = function(index) { - return /** @type {!sketchology.proto.Point} */ (this.get$ValueOrDefault(2, index)); -}; - - -/** - * Adds a value to the pointer_location field. - * @param {!sketchology.proto.Point} value The value to add. - */ -sketchology.proto.PusherPositionUpdate.prototype.addPointerLocation = function(value) { - this.add$Value(2, value); -}; - - -/** - * Returns the array of values in the pointer_location field. - * @return {!Array<!sketchology.proto.Point>} The values in the field. - */ -sketchology.proto.PusherPositionUpdate.prototype.pointerLocationArray = function() { - return /** @type {!Array<!sketchology.proto.Point>} */ (this.array$Values(2)); -}; - - -/** - * @return {boolean} Whether the pointer_location field has a value. - */ -sketchology.proto.PusherPositionUpdate.prototype.hasPointerLocation = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the pointer_location field. - */ -sketchology.proto.PusherPositionUpdate.prototype.pointerLocationCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the pointer_location field. - */ -sketchology.proto.PusherPositionUpdate.prototype.clearPointerLocation = function() { - this.clear$Field(2); -}; - - - -/** - * Message ElementQueryData. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ElementQueryData = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ElementQueryData, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ElementQueryData.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ElementQueryData} The cloned message. - * @override - */ -sketchology.proto.ElementQueryData.prototype.clone; - - -/** - * Gets the value of the item field at the index given. - * @param {number} index The index to lookup. - * @return {?sketchology.proto.ElementQueryItem} The value. - */ -sketchology.proto.ElementQueryData.prototype.getItem = function(index) { - return /** @type {?sketchology.proto.ElementQueryItem} */ (this.get$Value(1, index)); -}; - - -/** - * Gets the value of the item field at the index given or the default value if not set. - * @param {number} index The index to lookup. - * @return {!sketchology.proto.ElementQueryItem} The value. - */ -sketchology.proto.ElementQueryData.prototype.getItemOrDefault = function(index) { - return /** @type {!sketchology.proto.ElementQueryItem} */ (this.get$ValueOrDefault(1, index)); -}; - - -/** - * Adds a value to the item field. - * @param {!sketchology.proto.ElementQueryItem} value The value to add. - */ -sketchology.proto.ElementQueryData.prototype.addItem = function(value) { - this.add$Value(1, value); -}; - - -/** - * Returns the array of values in the item field. - * @return {!Array<!sketchology.proto.ElementQueryItem>} The values in the field. - */ -sketchology.proto.ElementQueryData.prototype.itemArray = function() { - return /** @type {!Array<!sketchology.proto.ElementQueryItem>} */ (this.array$Values(1)); -}; - - -/** - * @return {boolean} Whether the item field has a value. - */ -sketchology.proto.ElementQueryData.prototype.hasItem = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the item field. - */ -sketchology.proto.ElementQueryData.prototype.itemCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the item field. - */ -sketchology.proto.ElementQueryData.prototype.clearItem = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the up_world_location field. - * @return {?sketchology.proto.Point} The value. - */ -sketchology.proto.ElementQueryData.prototype.getUpWorldLocation = function() { - return /** @type {?sketchology.proto.Point} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the up_world_location field or the default value if not set. - * @return {!sketchology.proto.Point} The value. - */ -sketchology.proto.ElementQueryData.prototype.getUpWorldLocationOrDefault = function() { - return /** @type {!sketchology.proto.Point} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the up_world_location field. - * @param {!sketchology.proto.Point} value The value. - */ -sketchology.proto.ElementQueryData.prototype.setUpWorldLocation = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the up_world_location field has a value. - */ -sketchology.proto.ElementQueryData.prototype.hasUpWorldLocation = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the up_world_location field. - */ -sketchology.proto.ElementQueryData.prototype.upWorldLocationCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the up_world_location field. - */ -sketchology.proto.ElementQueryData.prototype.clearUpWorldLocation = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the down_world_location field. - * @return {?sketchology.proto.Point} The value. - */ -sketchology.proto.ElementQueryData.prototype.getDownWorldLocation = function() { - return /** @type {?sketchology.proto.Point} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the down_world_location field or the default value if not set. - * @return {!sketchology.proto.Point} The value. - */ -sketchology.proto.ElementQueryData.prototype.getDownWorldLocationOrDefault = function() { - return /** @type {!sketchology.proto.Point} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the down_world_location field. - * @param {!sketchology.proto.Point} value The value. - */ -sketchology.proto.ElementQueryData.prototype.setDownWorldLocation = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the down_world_location field has a value. - */ -sketchology.proto.ElementQueryData.prototype.hasDownWorldLocation = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the down_world_location field. - */ -sketchology.proto.ElementQueryData.prototype.downWorldLocationCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the down_world_location field. - */ -sketchology.proto.ElementQueryData.prototype.clearDownWorldLocation = function() { - this.clear$Field(3); -}; - - - -/** - * Message ElementQueryItem. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ElementQueryItem = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ElementQueryItem, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ElementQueryItem.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ElementQueryItem} The cloned message. - * @override - */ -sketchology.proto.ElementQueryItem.prototype.clone; - - -/** - * Gets the value of the uuid field. - * @return {?string} The value. - */ -sketchology.proto.ElementQueryItem.prototype.getUuid = function() { - return /** @type {?string} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the uuid field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.ElementQueryItem.prototype.getUuidOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the uuid field. - * @param {string} value The value. - */ -sketchology.proto.ElementQueryItem.prototype.setUuid = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the uuid field has a value. - */ -sketchology.proto.ElementQueryItem.prototype.hasUuid = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the uuid field. - */ -sketchology.proto.ElementQueryItem.prototype.uuidCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the uuid field. - */ -sketchology.proto.ElementQueryItem.prototype.clearUuid = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the world_bounds field. - * @return {?sketchology.proto.Rect} The value. - */ -sketchology.proto.ElementQueryItem.prototype.getWorldBounds = function() { - return /** @type {?sketchology.proto.Rect} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the world_bounds field or the default value if not set. - * @return {!sketchology.proto.Rect} The value. - */ -sketchology.proto.ElementQueryItem.prototype.getWorldBoundsOrDefault = function() { - return /** @type {!sketchology.proto.Rect} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the world_bounds field. - * @param {!sketchology.proto.Rect} value The value. - */ -sketchology.proto.ElementQueryItem.prototype.setWorldBounds = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the world_bounds field has a value. - */ -sketchology.proto.ElementQueryItem.prototype.hasWorldBounds = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the world_bounds field. - */ -sketchology.proto.ElementQueryItem.prototype.worldBoundsCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the world_bounds field. - */ -sketchology.proto.ElementQueryItem.prototype.clearWorldBounds = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the uri field. - * @return {?string} The value. - */ -sketchology.proto.ElementQueryItem.prototype.getUri = function() { - return /** @type {?string} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the uri field or the default value if not set. - * @return {string} The value. - */ -sketchology.proto.ElementQueryItem.prototype.getUriOrDefault = function() { - return /** @type {string} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the uri field. - * @param {string} value The value. - */ -sketchology.proto.ElementQueryItem.prototype.setUri = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the uri field has a value. - */ -sketchology.proto.ElementQueryItem.prototype.hasUri = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the uri field. - */ -sketchology.proto.ElementQueryItem.prototype.uriCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the uri field. - */ -sketchology.proto.ElementQueryItem.prototype.clearUri = function() { - this.clear$Field(3); -}; - - - -/** - * Message SelectionState. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.SelectionState = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.SelectionState, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.SelectionState.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.SelectionState} The cloned message. - * @override - */ -sketchology.proto.SelectionState.prototype.clone; - - -/** - * Gets the value of the anything_selected field. - * @return {?boolean} The value. - */ -sketchology.proto.SelectionState.prototype.getAnythingSelected = function() { - return /** @type {?boolean} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the anything_selected field or the default value if not set. - * @return {boolean} The value. - */ -sketchology.proto.SelectionState.prototype.getAnythingSelectedOrDefault = function() { - return /** @type {boolean} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the anything_selected field. - * @param {boolean} value The value. - */ -sketchology.proto.SelectionState.prototype.setAnythingSelected = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the anything_selected field has a value. - */ -sketchology.proto.SelectionState.prototype.hasAnythingSelected = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the anything_selected field. - */ -sketchology.proto.SelectionState.prototype.anythingSelectedCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the anything_selected field. - */ -sketchology.proto.SelectionState.prototype.clearAnythingSelected = function() { - this.clear$Field(1); -}; - - - -/** - * Message ToolEvent. - * @constructor - * @extends {goog.proto2.Message} - * @final - */ -sketchology.proto.ToolEvent = function() { - goog.proto2.Message.call(this); -}; -goog.inherits(sketchology.proto.ToolEvent, goog.proto2.Message); - - -/** - * Descriptor for this message, deserialized lazily in getDescriptor(). - * @private {?goog.proto2.Descriptor} - */ -sketchology.proto.ToolEvent.descriptor_ = null; - - -/** - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type. - * @return {!sketchology.proto.ToolEvent} The cloned message. - * @override - */ -sketchology.proto.ToolEvent.prototype.clone; - - -/** - * Gets the value of the pusher_position_update field. - * @return {?sketchology.proto.PusherPositionUpdate} The value. - */ -sketchology.proto.ToolEvent.prototype.getPusherPositionUpdate = function() { - return /** @type {?sketchology.proto.PusherPositionUpdate} */ (this.get$Value(1)); -}; - - -/** - * Gets the value of the pusher_position_update field or the default value if not set. - * @return {!sketchology.proto.PusherPositionUpdate} The value. - */ -sketchology.proto.ToolEvent.prototype.getPusherPositionUpdateOrDefault = function() { - return /** @type {!sketchology.proto.PusherPositionUpdate} */ (this.get$ValueOrDefault(1)); -}; - - -/** - * Sets the value of the pusher_position_update field. - * @param {!sketchology.proto.PusherPositionUpdate} value The value. - */ -sketchology.proto.ToolEvent.prototype.setPusherPositionUpdate = function(value) { - this.set$Value(1, value); -}; - - -/** - * @return {boolean} Whether the pusher_position_update field has a value. - */ -sketchology.proto.ToolEvent.prototype.hasPusherPositionUpdate = function() { - return this.has$Value(1); -}; - - -/** - * @return {number} The number of values in the pusher_position_update field. - */ -sketchology.proto.ToolEvent.prototype.pusherPositionUpdateCount = function() { - return this.count$Values(1); -}; - - -/** - * Clears the values in the pusher_position_update field. - */ -sketchology.proto.ToolEvent.prototype.clearPusherPositionUpdate = function() { - this.clear$Field(1); -}; - - -/** - * Gets the value of the element_query_data field. - * @return {?sketchology.proto.ElementQueryData} The value. - */ -sketchology.proto.ToolEvent.prototype.getElementQueryData = function() { - return /** @type {?sketchology.proto.ElementQueryData} */ (this.get$Value(2)); -}; - - -/** - * Gets the value of the element_query_data field or the default value if not set. - * @return {!sketchology.proto.ElementQueryData} The value. - */ -sketchology.proto.ToolEvent.prototype.getElementQueryDataOrDefault = function() { - return /** @type {!sketchology.proto.ElementQueryData} */ (this.get$ValueOrDefault(2)); -}; - - -/** - * Sets the value of the element_query_data field. - * @param {!sketchology.proto.ElementQueryData} value The value. - */ -sketchology.proto.ToolEvent.prototype.setElementQueryData = function(value) { - this.set$Value(2, value); -}; - - -/** - * @return {boolean} Whether the element_query_data field has a value. - */ -sketchology.proto.ToolEvent.prototype.hasElementQueryData = function() { - return this.has$Value(2); -}; - - -/** - * @return {number} The number of values in the element_query_data field. - */ -sketchology.proto.ToolEvent.prototype.elementQueryDataCount = function() { - return this.count$Values(2); -}; - - -/** - * Clears the values in the element_query_data field. - */ -sketchology.proto.ToolEvent.prototype.clearElementQueryData = function() { - this.clear$Field(2); -}; - - -/** - * Gets the value of the selection_state field. - * @return {?sketchology.proto.SelectionState} The value. - */ -sketchology.proto.ToolEvent.prototype.getSelectionState = function() { - return /** @type {?sketchology.proto.SelectionState} */ (this.get$Value(3)); -}; - - -/** - * Gets the value of the selection_state field or the default value if not set. - * @return {!sketchology.proto.SelectionState} The value. - */ -sketchology.proto.ToolEvent.prototype.getSelectionStateOrDefault = function() { - return /** @type {!sketchology.proto.SelectionState} */ (this.get$ValueOrDefault(3)); -}; - - -/** - * Sets the value of the selection_state field. - * @param {!sketchology.proto.SelectionState} value The value. - */ -sketchology.proto.ToolEvent.prototype.setSelectionState = function(value) { - this.set$Value(3, value); -}; - - -/** - * @return {boolean} Whether the selection_state field has a value. - */ -sketchology.proto.ToolEvent.prototype.hasSelectionState = function() { - return this.has$Value(3); -}; - - -/** - * @return {number} The number of values in the selection_state field. - */ -sketchology.proto.ToolEvent.prototype.selectionStateCount = function() { - return this.count$Values(3); -}; - - -/** - * Clears the values in the selection_state field. - */ -sketchology.proto.ToolEvent.prototype.clearSelectionState = function() { - this.clear$Field(3); -}; - - -/** @override */ -sketchology.proto.Command.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.Command.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'Command', - fullName: 'sketchology.proto.Command' - }, - 1: { - name: 'set_viewport', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Viewport - }, - 2: { - name: 'tool_params', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ToolParams - }, - 3: { - name: 'add_path', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.AddPath - }, - 4: { - name: 'camera_position', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Rect - }, - 5: { - name: 'page_bounds', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Rect - }, - 6: { - name: 'image_export', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ImageExport - }, - 7: { - name: 'flag_assignment', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.FlagAssignment - }, - 8: { - name: 'set_element_transforms', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ElementMutation - }, - 9: { - name: 'add_element', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.AddElement - }, - 10: { - name: 'background_image', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.BackgroundImageInfo - }, - 11: { - name: 'background_color', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.BackgroundColor - }, - 12: { - name: 'set_out_of_bounds_color', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.OutOfBoundsColor - }, - 13: { - name: 'set_page_border', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Border - }, - 14: { - name: 'send_input_stream', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.SInputStream - }, - 15: { - name: 'sequence_point', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.SequencePoint - }, - 16: { - name: 'set_callback_flags', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.SetCallbackFlags - }, - 17: { - name: 'set_camera_bounds_config', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.CameraBoundsConfig - }, - 18: { - name: 'deselect_all', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.NoArgCommand - }, - 19: { - name: 'add_image_rect', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ImageRect - }, - 21: { - name: 'clear', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.NoArgCommand - }, - 22: { - name: 'remove_all_elements', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.NoArgCommand - }, - 23: { - name: 'undo', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.NoArgCommand - }, - 24: { - name: 'redo', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.NoArgCommand - }, - 25: { - name: 'evict_image_data', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.EvictImageData - }, - 26: { - name: 'replace_elements', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ReplaceElementsCommand - }, - 27: { - name: 'commit_crop', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.NoArgCommand - }, - 28: { - name: 'element_animation', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ElementAnimation - }, - 29: { - name: 'set_grid', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.GridInfo - }, - 30: { - name: 'clear_grid', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.NoArgCommand - } - }; - sketchology.proto.Command.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.Command, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.Command.getDescriptor = - sketchology.proto.Command.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.CommandList.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.CommandList.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'CommandList', - fullName: 'sketchology.proto.CommandList' - }, - 1: { - name: 'commands', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Command - } - }; - sketchology.proto.CommandList.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.CommandList, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.CommandList.getDescriptor = - sketchology.proto.CommandList.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.NoArgCommand.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.NoArgCommand.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'NoArgCommand', - fullName: 'sketchology.proto.NoArgCommand' - } - }; - sketchology.proto.NoArgCommand.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.NoArgCommand, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.NoArgCommand.getDescriptor = - sketchology.proto.NoArgCommand.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ReplaceElementsCommand.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ReplaceElementsCommand.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ReplaceElementsCommand', - fullName: 'sketchology.proto.ReplaceElementsCommand' - }, - 1: { - name: 'uuids_to_remove', - repeated: true, - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 2: { - name: 'paths_to_add', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Path - } - }; - sketchology.proto.ReplaceElementsCommand.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ReplaceElementsCommand, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ReplaceElementsCommand.getDescriptor = - sketchology.proto.ReplaceElementsCommand.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.EvictImageData.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.EvictImageData.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'EvictImageData', - fullName: 'sketchology.proto.EvictImageData' - }, - 1: { - name: 'uri', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - } - }; - sketchology.proto.EvictImageData.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.EvictImageData, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.EvictImageData.getDescriptor = - sketchology.proto.EvictImageData.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.Viewport.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.Viewport.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'Viewport', - fullName: 'sketchology.proto.Viewport' - }, - 1: { - name: 'fbo_handle', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 2: { - name: 'width', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 3: { - name: 'height', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 4: { - name: 'ppi', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - } - }; - sketchology.proto.Viewport.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.Viewport, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.Viewport.getDescriptor = - sketchology.proto.Viewport.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ImageExport.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ImageExport.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ImageExport', - fullName: 'sketchology.proto.ImageExport' - }, - 1: { - name: 'max_dimension_px', - fieldType: goog.proto2.Message.FieldType.UINT32, - defaultValue: 1024, - type: Number - }, - 2: { - name: 'should_draw_background', - fieldType: goog.proto2.Message.FieldType.BOOL, - defaultValue: true, - type: Boolean - } - }; - sketchology.proto.ImageExport.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ImageExport, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ImageExport.getDescriptor = - sketchology.proto.ImageExport.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.LinearPathAnimation.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.LinearPathAnimation.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'LinearPathAnimation', - fullName: 'sketchology.proto.LinearPathAnimation' - }, - 1: { - name: 'rgba_from', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 2: { - name: 'rgba_seconds', - fieldType: goog.proto2.Message.FieldType.DOUBLE, - type: Number - }, - 3: { - name: 'dilation_from', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 4: { - name: 'dilation_seconds', - fieldType: goog.proto2.Message.FieldType.DOUBLE, - type: Number - } - }; - sketchology.proto.LinearPathAnimation.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.LinearPathAnimation, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.LinearPathAnimation.getDescriptor = - sketchology.proto.LinearPathAnimation.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.LineSize.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.LineSize.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'LineSize', - fullName: 'sketchology.proto.LineSize' - }, - 7: { - name: 'stroke_width', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 8: { - name: 'units', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.LineSize.SizeType.WORLD_UNITS, - type: sketchology.proto.LineSize.SizeType - } - }; - sketchology.proto.LineSize.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.LineSize, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.LineSize.getDescriptor = - sketchology.proto.LineSize.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.PusherToolParams.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.PusherToolParams.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'PusherToolParams', - fullName: 'sketchology.proto.PusherToolParams' - }, - 1: { - name: 'manipulate_stickers', - fieldType: goog.proto2.Message.FieldType.BOOL, - type: Boolean - }, - 2: { - name: 'manipulate_text', - fieldType: goog.proto2.Message.FieldType.BOOL, - type: Boolean - } - }; - sketchology.proto.PusherToolParams.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.PusherToolParams, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.PusherToolParams.getDescriptor = - sketchology.proto.PusherToolParams.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ToolParams.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ToolParams.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ToolParams', - fullName: 'sketchology.proto.ToolParams' - }, - 1: { - name: 'tool', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.ToolParams.ToolType.UNKNOWN, - type: sketchology.proto.ToolParams.ToolType - }, - 2: { - name: 'rgba', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 3: { - name: 'line_size', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.LineSize - }, - 4: { - name: 'pusher_tool_params', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.PusherToolParams - }, - 5: { - name: 'brush_type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.BrushType.UNKNOWN_BRUSH, - type: sketchology.proto.BrushType - }, - 6: { - name: 'linear_path_animation', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.LinearPathAnimation - } - }; - sketchology.proto.ToolParams.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ToolParams, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ToolParams.getDescriptor = - sketchology.proto.ToolParams.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.FlagAssignment.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.FlagAssignment.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'FlagAssignment', - fullName: 'sketchology.proto.FlagAssignment' - }, - 1: { - name: 'flag', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.Flag.UNKNOWN, - type: sketchology.proto.Flag - }, - 2: { - name: 'bool_value', - fieldType: goog.proto2.Message.FieldType.BOOL, - type: Boolean - } - }; - sketchology.proto.FlagAssignment.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.FlagAssignment, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.FlagAssignment.getDescriptor = - sketchology.proto.FlagAssignment.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.AddElement.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.AddElement.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'AddElement', - fullName: 'sketchology.proto.AddElement' - }, - 1: { - name: 'bundle', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ElementBundle - }, - 2: { - name: 'below_element_with_uuid', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - } - }; - sketchology.proto.AddElement.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.AddElement, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.AddElement.getDescriptor = - sketchology.proto.AddElement.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.OutOfBoundsColor.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.OutOfBoundsColor.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'OutOfBoundsColor', - fullName: 'sketchology.proto.OutOfBoundsColor' - }, - 1: { - name: 'rgba', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - } - }; - sketchology.proto.OutOfBoundsColor.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.OutOfBoundsColor, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.OutOfBoundsColor.getDescriptor = - sketchology.proto.OutOfBoundsColor.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.SInputStream.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.SInputStream.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'SInputStream', - fullName: 'sketchology.proto.SInputStream' - }, - 1: { - name: 'screen_width', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 2: { - name: 'screen_height', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 3: { - name: 'screen_ppi', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 4: { - name: 'input', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.SInput - } - }; - sketchology.proto.SInputStream.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.SInputStream, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.SInputStream.getDescriptor = - sketchology.proto.SInputStream.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.SInput.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.SInput.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'SInput', - fullName: 'sketchology.proto.SInput' - }, - 1: { - name: 'type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.SInput.InputType.UNKNOWN, - type: sketchology.proto.SInput.InputType - }, - 2: { - name: 'id', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 3: { - name: 'flags', - fieldType: goog.proto2.Message.FieldType.UINT32, - type: Number - }, - 4: { - name: 'time_s', - fieldType: goog.proto2.Message.FieldType.DOUBLE, - type: Number - }, - 5: { - name: 'screen_pos_x', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 6: { - name: 'screen_pos_y', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 7: { - name: 'pressure', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 8: { - name: 'wheel_delta', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 9: { - name: 'tilt', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 10: { - name: 'orientation', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - } - }; - sketchology.proto.SInput.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.SInput, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.SInput.getDescriptor = - sketchology.proto.SInput.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.SimulatedInput.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.SimulatedInput.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'SimulatedInput', - fullName: 'sketchology.proto.SimulatedInput' - }, - 1: { - name: 'xs', - repeated: true, - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 2: { - name: 'ys', - repeated: true, - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 3: { - name: 'ts_secs', - repeated: true, - fieldType: goog.proto2.Message.FieldType.DOUBLE, - type: Number - }, - 4: { - name: 'source_details', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.SourceDetails - } - }; - sketchology.proto.SimulatedInput.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.SimulatedInput, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.SimulatedInput.getDescriptor = - sketchology.proto.SimulatedInput.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.SequencePoint.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.SequencePoint.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'SequencePoint', - fullName: 'sketchology.proto.SequencePoint' - }, - 1: { - name: 'id', - fieldType: goog.proto2.Message.FieldType.INT32, - type: Number - } - }; - sketchology.proto.SequencePoint.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.SequencePoint, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.SequencePoint.getDescriptor = - sketchology.proto.SequencePoint.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.SetCallbackFlags.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.SetCallbackFlags.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'SetCallbackFlags', - fullName: 'sketchology.proto.SetCallbackFlags' - }, - 1: { - name: 'source_details', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.SourceDetails - }, - 2: { - name: 'callback_flags', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.CallbackFlags - } - }; - sketchology.proto.SetCallbackFlags.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.SetCallbackFlags, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.SetCallbackFlags.getDescriptor = - sketchology.proto.SetCallbackFlags.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.EngineState.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.EngineState.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'EngineState', - fullName: 'sketchology.proto.EngineState' - }, - 1: { - name: 'camera_position', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Rect - }, - 2: { - name: 'page_bounds', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Rect - }, - 3: { - name: 'selection_is_live', - fieldType: goog.proto2.Message.FieldType.BOOL, - type: Boolean - } - }; - sketchology.proto.EngineState.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.EngineState, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.EngineState.getDescriptor = - sketchology.proto.EngineState.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.CameraBoundsConfig.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.CameraBoundsConfig.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'CameraBoundsConfig', - fullName: 'sketchology.proto.CameraBoundsConfig' - }, - 1: { - name: 'margin_left_px', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 2: { - name: 'margin_right_px', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 3: { - name: 'margin_bottom_px', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 4: { - name: 'margin_top_px', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - }, - 5: { - name: 'fraction_padding', - fieldType: goog.proto2.Message.FieldType.FLOAT, - defaultValue: 0.1, - type: Number - } - }; - sketchology.proto.CameraBoundsConfig.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.CameraBoundsConfig, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.CameraBoundsConfig.getDescriptor = - sketchology.proto.CameraBoundsConfig.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ImageInfo.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ImageInfo.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ImageInfo', - fullName: 'sketchology.proto.ImageInfo' - }, - 1: { - name: 'uri', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 2: { - name: 'asset_type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.ImageInfo.AssetType.DEFAULT, - type: sketchology.proto.ImageInfo.AssetType - } - }; - sketchology.proto.ImageInfo.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ImageInfo, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ImageInfo.getDescriptor = - sketchology.proto.ImageInfo.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ImageRect.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ImageRect.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ImageRect', - fullName: 'sketchology.proto.ImageRect' - }, - 1: { - name: 'rect', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Rect - }, - 2: { - name: 'bitmap_uri', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 3: { - name: 'attributes', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ElementAttributes - }, - 4: { - name: 'rotation_radians', - fieldType: goog.proto2.Message.FieldType.FLOAT, - type: Number - } - }; - sketchology.proto.ImageRect.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ImageRect, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ImageRect.getDescriptor = - sketchology.proto.ImageRect.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.GridInfo.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.GridInfo.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'GridInfo', - fullName: 'sketchology.proto.GridInfo' - }, - 1: { - name: 'uri', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - } - }; - sketchology.proto.GridInfo.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.GridInfo, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.GridInfo.getDescriptor = - sketchology.proto.GridInfo.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.CreateDocument.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.CreateDocument.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'CreateDocument', - fullName: 'sketchology.proto.CreateDocument' - }, - 1: { - name: 'document_type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.DocumentType.SINGLE_USER_DOCUMENT, - type: sketchology.proto.DocumentType - }, - 2: { - name: 'storage_type', - fieldType: goog.proto2.Message.FieldType.ENUM, - defaultValue: sketchology.proto.StorageType.IN_MEMORY_STORAGE, - type: sketchology.proto.StorageType - }, - 3: { - name: 'storage_path', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 4: { - name: 'snapshot', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Snapshot - } - }; - sketchology.proto.CreateDocument.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.CreateDocument, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.CreateDocument.getDescriptor = - sketchology.proto.CreateDocument.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.AddPath.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.AddPath.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'AddPath', - fullName: 'sketchology.proto.AddPath' - }, - 1: { - name: 'path', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Path - }, - 2: { - name: 'uuid', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - } - }; - sketchology.proto.AddPath.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.AddPath, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.AddPath.getDescriptor = - sketchology.proto.AddPath.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.PusherPositionUpdate.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.PusherPositionUpdate.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'PusherPositionUpdate', - fullName: 'sketchology.proto.PusherPositionUpdate' - }, - 1: { - name: 'uuid', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 2: { - name: 'pointer_location', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Point - } - }; - sketchology.proto.PusherPositionUpdate.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.PusherPositionUpdate, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.PusherPositionUpdate.getDescriptor = - sketchology.proto.PusherPositionUpdate.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ElementQueryData.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ElementQueryData.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ElementQueryData', - fullName: 'sketchology.proto.ElementQueryData' - }, - 1: { - name: 'item', - repeated: true, - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ElementQueryItem - }, - 2: { - name: 'up_world_location', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Point - }, - 3: { - name: 'down_world_location', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Point - } - }; - sketchology.proto.ElementQueryData.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ElementQueryData, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ElementQueryData.getDescriptor = - sketchology.proto.ElementQueryData.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ElementQueryItem.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ElementQueryItem.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ElementQueryItem', - fullName: 'sketchology.proto.ElementQueryItem' - }, - 1: { - name: 'uuid', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - }, - 2: { - name: 'world_bounds', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.Rect - }, - 3: { - name: 'uri', - fieldType: goog.proto2.Message.FieldType.STRING, - type: String - } - }; - sketchology.proto.ElementQueryItem.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ElementQueryItem, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ElementQueryItem.getDescriptor = - sketchology.proto.ElementQueryItem.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.SelectionState.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.SelectionState.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'SelectionState', - fullName: 'sketchology.proto.SelectionState' - }, - 1: { - name: 'anything_selected', - fieldType: goog.proto2.Message.FieldType.BOOL, - type: Boolean - } - }; - sketchology.proto.SelectionState.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.SelectionState, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.SelectionState.getDescriptor = - sketchology.proto.SelectionState.prototype.getDescriptor; - - -/** @override */ -sketchology.proto.ToolEvent.prototype.getDescriptor = function() { - var descriptor = sketchology.proto.ToolEvent.descriptor_; - if (!descriptor) { - // The descriptor is created lazily when we instantiate a new instance. - var descriptorObj = { - 0: { - name: 'ToolEvent', - fullName: 'sketchology.proto.ToolEvent' - }, - 1: { - name: 'pusher_position_update', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.PusherPositionUpdate - }, - 2: { - name: 'element_query_data', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.ElementQueryData - }, - 3: { - name: 'selection_state', - fieldType: goog.proto2.Message.FieldType.MESSAGE, - type: sketchology.proto.SelectionState - } - }; - sketchology.proto.ToolEvent.descriptor_ = descriptor = - goog.proto2.Message.createDescriptor( - sketchology.proto.ToolEvent, descriptorObj); - } - return descriptor; -}; - - -/** @nocollapse */ -sketchology.proto.ToolEvent.getDescriptor = - sketchology.proto.ToolEvent.prototype.getDescriptor;
diff --git a/third_party/ink/sketchology/public/js/common/brush_model.js b/third_party/ink/sketchology/public/js/common/brush_model.js deleted file mode 100644 index 8ffbe4c0..0000000 --- a/third_party/ink/sketchology/public/js/common/brush_model.js +++ /dev/null
@@ -1,243 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -goog.provide('ink.BrushModel'); - -goog.require('goog.events'); -goog.require('goog.events.EventTarget'); -goog.require('ink.Model'); -goog.require('sketchology.proto.BrushType'); -goog.require('sketchology.proto.ToolParams.ToolType'); - - - -/** - * Holds the state of the ink brush. Toolbar widgets update BrushModel, which in - * turn dispatches CHANGE events to update the toolbar components' states. - * @constructor - * @extends {ink.Model} - * @param {!goog.events.EventTarget} root Unused - */ -ink.BrushModel = function(root) { - ink.BrushModel.base(this, 'constructor'); - /** - * Last brush color (not including erase color). - * @private {string} - */ - this.color_ = ink.BrushModel.DEFAULT_DRAW_COLOR; - - /** - * The active stroke width of the brush (includes erase size). - * @private {number} - */ - this.strokeWidth_ = ink.BrushModel.DEFAULT_DRAW_SIZE; - - /** - * @private {boolean} - */ - this.isErasing_ = ink.BrushModel.DEFAULT_ISERASING; - - /** - * @private {sketchology.proto.ToolParams.ToolType} - */ - this.toolType_ = sketchology.proto.ToolParams.ToolType.LINE; - - /** - * @private {sketchology.proto.BrushType} - */ - this.brushType_ = sketchology.proto.BrushType.CALLIGRAPHY; - - /** - * @private {string} - */ - this.shape_ = 'CALLIGRAPHY'; -}; -goog.inherits(ink.BrushModel, ink.Model); -ink.Model.addGetter(ink.BrushModel); - - -/** - * @const {string} - */ -ink.BrushModel.DEFAULT_DRAW_COLOR = '#000000'; - - -/** - * @const {number} - */ -ink.BrushModel.DEFAULT_DRAW_SIZE = 0.6; - - -/** - * @const {string} - */ -ink.BrushModel.DEFAULT_ERASE_COLOR = '#FFFFFF'; - -/** - * @const {boolean} - */ -ink.BrushModel.DEFAULT_ISERASING = false; - - -/** - * The events fired by the BrushModel. - * @enum {string} The event types for the BrushModel. - */ -ink.BrushModel.EventType = { - /** - * Fired when the BrushModel is changed. - */ - CHANGE: goog.events.getUniqueId('change') -}; - - -/** - * @const {Object} - */ -ink.BrushModel.SHAPE_TO_TOOLTYPE = { - 'AIRBRUSH': sketchology.proto.ToolParams.ToolType.LINE, - 'CALLIGRAPHY': sketchology.proto.ToolParams.ToolType.LINE, - 'EDIT': sketchology.proto.ToolParams.ToolType.EDIT, - 'ERASER': sketchology.proto.ToolParams.ToolType.LINE, - 'HIGHLIGHTER': sketchology.proto.ToolParams.ToolType.LINE, - 'INKPEN': sketchology.proto.ToolParams.ToolType.LINE, - 'MAGIC_ERASE': sketchology.proto.ToolParams.ToolType.MAGIC_ERASE, - 'MARKER': sketchology.proto.ToolParams.ToolType.LINE, - 'PENCIL': sketchology.proto.ToolParams.ToolType.LINE, - 'BALLPOINT': sketchology.proto.ToolParams.ToolType.LINE, - 'BALLPOINT_IN_PEN_MODE_ELSE_MARKER': - sketchology.proto.ToolParams.ToolType.LINE, - 'QUERY': sketchology.proto.ToolParams.ToolType.QUERY, -}; - - -/** - * @const {Object} - */ -ink.BrushModel.SHAPE_TO_BRUSHTYPE = { - 'AIRBRUSH': sketchology.proto.BrushType.AIRBRUSH, - 'CALLIGRAPHY': sketchology.proto.BrushType.CALLIGRAPHY, - 'ERASER': sketchology.proto.BrushType.ERASER, - 'HIGHLIGHTER': sketchology.proto.BrushType.HIGHLIGHTER, - 'INKPEN': sketchology.proto.BrushType.INKPEN, - 'MARKER': sketchology.proto.BrushType.MARKER, - 'BALLPOINT': sketchology.proto.BrushType.BALLPOINT, - 'BALLPOINT_IN_PEN_MODE_ELSE_MARKER': - sketchology.proto.BrushType.BALLPOINT_IN_PEN_MODE_ELSE_MARKER, - 'PENCIL': sketchology.proto.BrushType.PENCIL, -}; - - -/** - * @param {string} color The color in hex. - */ -ink.BrushModel.prototype.setColor = function(color) { - this.color_ = color; - this.dispatchEvent(ink.BrushModel.EventType.CHANGE); -}; - - -/** - * @param {number} strokeWidth The brush's stroke width. - */ -ink.BrushModel.prototype.setStrokeWidth = function(strokeWidth) { - this.strokeWidth_ = strokeWidth; - this.dispatchEvent(ink.BrushModel.EventType.CHANGE); -}; - - -/** - * @param {boolean} isErasing Whether user is erasing or not. - */ -ink.BrushModel.prototype.setIsErasing = function(isErasing) { - this.isErasing_ = isErasing; - this.dispatchEvent(ink.BrushModel.EventType.CHANGE); -}; - - -/** - * @param {string} shape The brush shape, which is either a brush type or a tool - * type. If it's a brush type, implies tool type LINE. - */ -ink.BrushModel.prototype.setShape = function(shape) { - this.toolType_ = ink.BrushModel.SHAPE_TO_TOOLTYPE[shape]; - this.brushType_ = ink.BrushModel.SHAPE_TO_BRUSHTYPE[shape] !== undefined ? - ink.BrushModel.SHAPE_TO_BRUSHTYPE[shape] : - this.brushType_; - this.shape_ = shape; - this.dispatchEvent(ink.BrushModel.EventType.CHANGE); -}; - - -/** - * @return {string} The last used shape. - */ -ink.BrushModel.prototype.getShape = function() { - return this.shape_; -}; - - -/** - * @return {string} The last draw color in hex (excluding erase color). - */ -ink.BrushModel.prototype.getColor = function() { - return this.color_; -}; - - -/** - * Gets the current color being drawn on the screen (including erase color). - * @return {string} The brush color in hex. - */ -ink.BrushModel.prototype.getActiveColor = function() { - if (!this.isErasing_) { - return this.color_; - } else { - return ink.BrushModel.DEFAULT_ERASE_COLOR; - } -}; - - -/** - * Wraps getActiveColor() by returning the numeric rgb of the color. - * @return {number} The brush color in numeric rbg. - */ -ink.BrushModel.prototype.getActiveColorNumericRbg = function() { - return parseInt(this.getActiveColor().substring(1), 16); -}; - - -/** - * @return {number} Percentage size for stroke width, [0, 1]. - * - * See sengine.proto SizeType - */ -ink.BrushModel.prototype.getStrokeWidth = function() { - return this.strokeWidth_; -}; - - -/** - * @return {boolean} Whether user is erasing. - */ -ink.BrushModel.prototype.getIsErasing = function() { - return this.isErasing_; -}; - - -/** - * @return {sketchology.proto.BrushType} The brush type for line - * tool. - */ -ink.BrushModel.prototype.getBrushType = function() { - return this.brushType_; -}; - - -/** - * @return {sketchology.proto.ToolParams.ToolType} The tool type. - */ -ink.BrushModel.prototype.getToolType = function() { - return this.toolType_; -}; -
diff --git a/third_party/ink/sketchology/public/js/common/color.js b/third_party/ink/sketchology/public/js/common/color.js deleted file mode 100644 index 1a61210..0000000 --- a/third_party/ink/sketchology/public/js/common/color.js +++ /dev/null
@@ -1,113 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -goog.provide('ink.Color'); - - - -/** - * 32bit color representation. Each channels is a 8 bit uint. - * @param {number} argb The 32-bit color. - * @constructor - * @struct - */ -ink.Color = function(argb) { - /** @type {number} */ - this.argb = argb; - - /** @type {number} */ - this.a = ink.Color.alphaFromArgb(argb); - - /** @type {number} */ - this.r = ink.Color.redFromArgb(argb); - - /** @type {number} */ - this.g = ink.Color.greenFromArgb(argb); - - /** @type {number} */ - this.b = ink.Color.blueFromArgb(argb); -}; - - -/** - * @return {string} The color string (excluding alpha) that can be used as a - * fillStyle. - */ -ink.Color.prototype.getRgbString = function() { - return 'rgb(' + [this.r, this.g, this.b].join(',') + ')'; -}; - - -/** @return {string} The color string that can be used as a fillStyle. */ -ink.Color.prototype.getRgbaString = function() { - return 'rgba(' + [this.r, this.g, this.b, this.a / 255].join(',') + ')'; -}; - - -/** @return {Uint32Array} color as rgba 32-bit unsigned integer */ -ink.Color.prototype.getRgbaUint32 = function() { - return new Uint32Array( - [(this.r << 24) | (this.g << 16) | (this.b << 8) | this.a]); -}; - - -/** - * @return {number} The alpha in the range 0-1 that can be used as a - * globalAlpha. - */ -ink.Color.prototype.getAlphaAsFloat = function() { - return this.a / 255; -}; - - -/** - * Helper function that returns a function that right logical shifts by the - * provided amount and masks off the result. - * @param {number} shiftAmount The amount that the function should shift by. - * @return {!Function} - * @private - */ -ink.Color.shiftAndMask_ = function(shiftAmount) { - return function(argb) { - return (argb >>> shiftAmount) & 0xFF; - }; -}; - - -/** - * @param {number} argb The argb number. - * @return {number} alpha in the range 0 to 255. - */ -ink.Color.alphaFromArgb = ink.Color.shiftAndMask_(24); - - -/** - * @param {number} argb The argb number. - * @return {number} red in the range 0 to 255. - */ -ink.Color.redFromArgb = ink.Color.shiftAndMask_(16); - - -/** - * @param {number} argb The argb number. - * @return {number} green in the range 0 to 255. - */ -ink.Color.greenFromArgb = ink.Color.shiftAndMask_(8); - - -/** - * @param {number} argb The argb number. - * @return {number} blue in the range 0 to 255. - */ -ink.Color.blueFromArgb = ink.Color.shiftAndMask_(0); - - -/** @type {!ink.Color} */ -ink.Color.BLACK = new ink.Color(0xFF000000); - - -/** @type {!ink.Color} */ -ink.Color.WHITE = new ink.Color(0xFFFFFFFF); - -/** @type {!ink.Color} */ -ink.Color.DEFAULT_BACKGROUND_COLOR = new ink.Color(0xFFFAFAFA);
diff --git a/third_party/ink/sketchology/public/js/common/element_listener.js b/third_party/ink/sketchology/public/js/common/element_listener.js deleted file mode 100644 index a149f25..0000000 --- a/third_party/ink/sketchology/public/js/common/element_listener.js +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -/** - * @fileoverview Element listener interface declaration - */ -goog.provide('ink.ElementListener'); - -/** - * @interface - */ -ink.ElementListener = function() {}; - -/** - * @param {string} uuid - * @param {string} encodedElement - * @param {string} encodedTransform - */ -ink.ElementListener.prototype.onElementCreated = function( - uuid, encodedElement, encodedTransform) {}; - -/** - * @param {Array.<string>} uuids - * @param {Array.<string>} encodedTransforms - */ -ink.ElementListener.prototype.onElementsMutated = function( - uuids, encodedTransforms) {}; - -/** - * @param {Array.<string>} uuids - */ -ink.ElementListener.prototype.onElementsRemoved = function(uuids) {};
diff --git a/third_party/ink/sketchology/public/js/common/model.js b/third_party/ink/sketchology/public/js/common/model.js deleted file mode 100644 index 0a726a4..0000000 --- a/third_party/ink/sketchology/public/js/common/model.js +++ /dev/null
@@ -1,89 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -goog.provide('ink.Model'); - -goog.require('goog.asserts'); -goog.require('goog.events.EventTarget'); -goog.require('ink.util'); - - - -/** - * A generic model base class. Each models here is a singleton per EventTarget - * hierarchy tree. - * - * @extends {goog.events.EventTarget} - * @constructor - * @struct - */ -ink.Model = function() { - ink.Model.base(this, 'constructor'); -}; -goog.inherits(ink.Model, goog.events.EventTarget); - - -/** - * The models are attached to the root parent EventTargets. To have the models - * be automatically gc properly the relevant models need to actually be - * properties of those EventTargets. This property is initialized to avoid - * collisions with other JavaScript on the same page, similarly to the property - * that goog.getUid uses. - * @private {string} - */ -ink.Model.MODEL_INSTANCES_PROPERTY_ = 'ink_model_instances_' + Math.random(); - - -/** - * Adds the getter to the model constructor, allowing for the simpler - * ink.BrushModel.getInstance(this); instead of - * ink.Model.get(ink.BrushModel, this); - * @param {!function(new:ink.Model, !goog.events.EventTarget)} modelCtor - * The model constructor. - */ -ink.Model.addGetter = function(modelCtor) { - /** - * @param {!goog.events.EventTarget} observer - * @return {!ink.Model} - */ - modelCtor.getInstance = function(observer) { - goog.asserts.assertObject(observer); - return ink.Model.get(modelCtor, observer); - }; -}; - - -/** - * Gets the relevant model for the provided viewer. The viewer should be a - * goog.ui.Component that has entered the document or a goog.events.EventTarget - * that has already had its parentEventTarget set. - * - * Note: This currently assumes that the provided models are singletons per - * EventTarget hierarchy tree. A more flexible design for deciding what level - * to have models should be added here if usage demands it. - * - * @param {!function(new:ink.Model, !goog.events.EventTarget)} modelCtor - * @param {!goog.events.EventTarget} observer - * @return {!ink.Model} - */ -ink.Model.get = function(modelCtor, observer) { - // TODO(esrauch): Maybe this should be implemented based on dom elements - // instead of the goog.ui.Component hierarchy. As it is, a stray setParent() - // call could cause the Model instance to suprisingly change for the same - // observer. On the other hand, reading the dom is slower and also can cause - // a brower reflow unnecessarily and this way also allows for vanilla - // EventTargets to get the relevant Models. - var root = ink.util.getRootParentComponent(observer); - var models = root[ink.Model.MODEL_INSTANCES_PROPERTY_]; - if (!models) { - root[ink.Model.MODEL_INSTANCES_PROPERTY_] = models = {}; - } - var key = goog.getUid(modelCtor); - var oldInstance = models[key]; - if (oldInstance) { - return oldInstance; - } - var newInstance = new modelCtor(root); - models[key] = newInstance; - return newInstance; -};
diff --git a/third_party/ink/sketchology/public/js/common/proto_serializer.js b/third_party/ink/sketchology/public/js/common/proto_serializer.js deleted file mode 100644 index dc99eeb..0000000 --- a/third_party/ink/sketchology/public/js/common/proto_serializer.js +++ /dev/null
@@ -1,77 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -goog.provide('ink.ProtoSerializer'); - - -goog.require('goog.crypt.base64'); -goog.require('goog.proto2.ObjectSerializer'); // for debugging -goog.require('net.proto2.contrib.WireSerializer'); - - - -/** - * A proto serializer / deserializer to and from base-64 encoded wire format. - * @constructor - * @struct - */ -ink.ProtoSerializer = function() { - /** @private {!net.proto2.contrib.WireSerializer} */ - this.wireSerializer_ = new net.proto2.contrib.WireSerializer(); -}; - - -/** - * @param {!goog.proto2.Message} e proto to serialize - * @return {string} The serialized proto as a base 64 encoded string. - */ -ink.ProtoSerializer.prototype.serializeToBase64 = function(e) { - var buf = this.wireSerializer_.serialize(e); - return goog.crypt.base64.encodeByteArray(buf); -}; - - -/** - * Deserializes the given opaque serialized object to a jspb object. - * - * @param {string} item serialized object as base64 text - * @param {!goog.proto2.Message} proto Proto to deserialize into - * @return {!goog.proto2.Message} - */ -ink.ProtoSerializer.prototype.safeDeserialize = function(item, proto) { - var buf = goog.crypt.base64.decodeStringToByteArray(item); - this.wireSerializer_.deserializeTo(proto, new Uint8Array(buf)); - return proto; -}; - - -/** - * @param {!sketchology.proto.Element} p - * @return {boolean} Whether the provided Element appears valid. - * @private - */ -ink.ProtoSerializer.prototype.isValid_ = function(p) { - if (p == null) { - return false; - } - - if (!p.hasStroke()) { - return false; - } - - return true; -}; - - -/** - * Returns a human-readable representation of a proto. - * - * @param {!goog.proto2.Message} p The proto to debug. - * @return {string} A nice string to ponder. - * @private - */ -ink.ProtoSerializer.prototype.debugProto_ = function(p) { - var obj = new goog.proto2.ObjectSerializer( - goog.proto2.ObjectSerializer.KeyOption.NAME).serialize(p); - return JSON.stringify(obj, null, ' '); -};
diff --git a/third_party/ink/sketchology/public/js/common/undo_state_change_event.js b/third_party/ink/sketchology/public/js/common/undo_state_change_event.js deleted file mode 100644 index 5b65a277..0000000 --- a/third_party/ink/sketchology/public/js/common/undo_state_change_event.js +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -goog.provide('ink.UndoStateChangeEvent'); - -goog.require('goog.events'); -goog.require('goog.events.Event'); - - - -/** - * @param {boolean} canUndo Whether there is undo state available. - * @param {boolean} canRedo Whether there is redo state available. - * @constructor - * @struct - * @extends {goog.events.Event} - */ -ink.UndoStateChangeEvent = function(canUndo, canRedo) { - ink.UndoStateChangeEvent.base( - this, 'constructor',ink.UndoStateChangeEvent.EVENT_TYPE); - this.canUndo = canUndo; - this.canRedo = canRedo; -}; -goog.inherits(ink.UndoStateChangeEvent, goog.events.Event); - - -/** @type {string} */ -ink.UndoStateChangeEvent.EVENT_TYPE = goog.events.getUniqueId('undo-state');
diff --git a/third_party/ink/sketchology/public/js/common/util.js b/third_party/ink/sketchology/public/js/common/util.js deleted file mode 100644 index 85fd56e..0000000 --- a/third_party/ink/sketchology/public/js/common/util.js +++ /dev/null
@@ -1,292 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -goog.provide('ink.util'); - -goog.require('goog.dom'); -goog.require('goog.events'); -goog.require('goog.math.Size'); -goog.require('protos.research.ink.InkEvent'); - - -/** @enum {string} */ -ink.util.SEngineType = { - IN_MEMORY: 'makeSEngineInMemory', - LONGFORM: 'makeLongformSEngine', - PASSTHROUGH_DOCUMENT: 'makeSEnginePassthroughDocument' -}; - - -/** - * @typedef {{ - * getModel: (function():ink.util.RealtimeModel) - * }} - */ -ink.util.RealtimeDocument; - - -/** - * @typedef {{ - * getRoot: (function():ink.util.RealtimeRoot) - * }} - */ -ink.util.RealtimeModel; - - -/** - * @typedef {{ - * get: (function(string):ink.util.RealtimePages) - * }} - */ -ink.util.RealtimeRoot; - - -/** - * @typedef {{ - * get: (function(number):ink.util.RealtimePage), - * xhigh: number, - * xlow: number, - * yhigh: number, - * ylow: number - * }} - */ -ink.util.RealtimePages; - - -/** - * @typedef {{ - * get: (function(string):ink.util.RealtimeElements) - * }} - */ -ink.util.RealtimePage; - - -/** - * @typedef {{ - * asArray: (function():Array.<ink.util.RealtimeElement>) - * }} - */ -ink.util.RealtimeElements; - - -/** - * @typedef {{ - * get: (function(string):string) - * }} - */ -ink.util.RealtimeElement; - - -/** - * Wrapper used for event handlers to pass the event target instead of the - * event. - * @param {!Function} callback The event handler function. - * @param {Object=} opt_handler Element in whole scope to call the callback. - * @return {!Function} Wrapped function. - */ -ink.util.eventTargetWrapper = function(callback, opt_handler) { - return function(evt) { - var self = /** @type {Object} */ (this); - callback.call(opt_handler || self, evt.target); - }; -}; - - -/** - * @param {!goog.events.EventTarget} child The child to get the root parent - * EventTarget for. - * @return {!goog.events.EventTarget} The root parent. - * TODO(esrauch): Rename this function and consider moving it to a new - * whiteboard/util.js file. - */ -ink.util.getRootParentComponent = function(child) { - var current = child; - var parent = current.getParentEventTarget(); - while (parent) { - current = parent; - parent = current.getParentEventTarget(); - } - return current; -}; - - -/** - * Downloads an image, renders it to a canvas, returns the raw bytes. - * @param {string} imgSrc - * @param {Function} callback - */ -ink.util.getImageBytes = function(imgSrc, callback) { - var canvasElement = goog.dom.createElement(goog.dom.TagName.CANVAS); - var imgElement = goog.dom.createElement(goog.dom.TagName.IMG); - imgElement.setAttribute( - 'style', - 'position:absolute;visibility:hidden;top:-1000px;left:-1000px;'); - imgElement.crossOrigin = 'Anonymous'; - - goog.events.listenOnce(imgElement, 'load', function() { - var width = imgElement.width; - var height = imgElement.height; - canvasElement.width = width; - canvasElement.height = height; - var ctx = canvasElement.getContext('2d'); - ctx.drawImage(imgElement, 0, 0); - var data = ctx.getImageData(0, 0, width, height); - - document.body.removeChild(imgElement); - - callback(data.data, new goog.math.Size(width, height)); - }); - - imgElement.setAttribute('src', imgSrc); - document.body.appendChild(imgElement); -}; - - -/** - * Creates document events. - * @param {!protos.research.ink.InkEvent.Host} host - * @param {!protos.research.ink.InkEvent.DocumentEvent.DocumentEventType} type - * @return {!protos.research.ink.InkEvent} - */ -ink.util.createDocumentEvent = function(host, type) { - var eventProto = new protos.research.ink.InkEvent(); - eventProto.setHost(host); - eventProto.setEventType( - protos.research.ink.InkEvent.EventType.DOCUMENT_EVENT); - var documentEvent = new protos.research.ink.InkEvent.DocumentEvent(); - documentEvent.setEventType(type); - eventProto.setDocumentEvent(documentEvent); - return eventProto; -}; - - -/** - * Helper for constructing a document created event - * - * @param {!protos.research.ink.InkEvent.Host} host - * @param {!protos.research.ink.InkEvent.DocumentEvent.DocumentState} state - * @param {number} firstLoadTime (which is when the first byte is loaded) - * @param {number} startLoadTime (which is when the document is first editable). - * @return {!protos.research.ink.InkEvent} - */ -ink.util.createDocumentOpenedEvent = function( - host, state, firstLoadTime, startLoadTime) { - var type = - protos.research.ink.InkEvent.DocumentEvent.DocumentEventType.OPENED; - var ev = ink.util.createDocumentEvent(host, type); - var openedEvent = - new protos.research.ink.InkEvent.DocumentEvent.OpenedEvent(); - openedEvent.setMillisUntilFirstByteLoaded(firstLoadTime.toString()); - openedEvent.setMillisUntilEditable((goog.now() - startLoadTime).toString()); - var documentEvent = ev.getDocumentEventOrDefault(); - documentEvent.setOpenedEvent(openedEvent); - documentEvent.setDocumentState(state); - return ev; -}; - - -/** - * Helper for constructing a collaborator joined logging event. - * - * @param {!protos.research.ink.InkEvent.Host} host - * @param {!protos.research.ink.InkEvent.DocumentEvent.DocumentState} state - * @param {boolean} isMe - * @return {!protos.research.ink.InkEvent} - */ -ink.util.createCollaboratorJoinedDocumentEvent = function(host, state, isMe) { - var type = protos.research.ink.InkEvent.DocumentEvent.DocumentEventType - .COLLABORATOR_JOINED; - var ev = ink.util.createDocumentEvent(host, type); - var collaboratorJoinedEvent = - new protos.research.ink.InkEvent.DocumentEvent.CollaboratorJoined(); - collaboratorJoinedEvent.setIsMe(isMe); - var documentEvent = ev.getDocumentEventOrDefault(); - documentEvent.setCollaboratorJoinedEvent(collaboratorJoinedEvent); - documentEvent.setDocumentState(state); - return ev; -}; - - -/** - * @const - */ -ink.util.SHAPE_TO_LOG_TOOLTYPE = { - 'CALLIGRAPHY': protos.research.ink.InkEvent.ToolbarEvent.ToolType.CALLIGRAPHY, - 'EDIT': protos.research.ink.InkEvent.ToolbarEvent.ToolType.EDIT_TOOL, - 'HIGHLIGHTER': protos.research.ink.InkEvent.ToolbarEvent.ToolType.HIGHLIGHTER, - 'MAGIC_ERASE': protos.research.ink.InkEvent.ToolbarEvent.ToolType.MAGIC_ERASER, - 'MARKER': protos.research.ink.InkEvent.ToolbarEvent.ToolType.MARKER -}; - - -/** - * Creates toolbar events. - * @param {protos.research.ink.InkEvent.Host} host - * @param {protos.research.ink.InkEvent.ToolbarEvent.ToolEventType} type - * @param {string} toolType - * @param {string} color - * @return {protos.research.ink.InkEvent} - */ -ink.util.createToolbarEvent = function(host, type, toolType, color) { - var eventProto = new protos.research.ink.InkEvent(); - eventProto.setHost(host); - eventProto.setEventType(protos.research.ink.InkEvent.EventType.TOOLBAR_EVENT); - var toolbarEvent = new protos.research.ink.InkEvent.ToolbarEvent(); - // Alpha is always 0xFF. This does #RRGGBB -> #AARRGGBB -> 0xAARRGGBB. - var colorAsNumber = parseInt('ff' + color.substring(1, 7), 16); - toolbarEvent.setColor(colorAsNumber); - toolbarEvent.setToolType( - ink.util.SHAPE_TO_LOG_TOOLTYPE[toolType] || - protos.research.ink.InkEvent.ToolbarEvent.ToolType.UNKNOWN_TOOL_TYPE); - toolbarEvent.setToolEventType(type); - eventProto.setToolbarEvent(toolbarEvent); - return eventProto; -}; - - -// Note: These helpers are included here because we do not use the closure -// browser event wrappers to avoid additional GC pauses. Logic forked from -// cs/piper///depot/google3/javascript/closure/events/browserevent.js?l=337 - -/** - * "Action button" is MouseEvent.button equal to 0 (main button) and no - * control-key for Mac right-click action. The button property is the one - * that was responsible for triggering a mousedown or mouseup event. - * - * @param {MouseEvent} evt - * @return {boolean} - */ -ink.util.isMouseActionButton = function(evt) { - return evt.button == 0 && - !(goog.userAgent.WEBKIT && goog.userAgent.MAC && evt.ctrlKey); -}; - - -/** - * MouseEvent.buttons has 1 (main button) held down, and no control-key - * for Mac right-click drag. This is for which button is currently held down, - * e.g. during a mousemove event. - * - * @param {MouseEvent} evt - * @return {boolean} - */ -ink.util.hasMouseActionButton = function(evt) { - return (evt.buttons & 1) == 1 && - !(goog.userAgent.WEBKIT && goog.userAgent.MAC && evt.ctrlKey); -}; - - -/** - * Checks MouseEvent.buttons has 2 (secondary button) held down, or 1 (main - * button) with control key for Mac right-click drag. This is for which - * button is currently held down, e.g. during a mousemove event. - * - * @param {MouseEvent} evt - * @return {boolean} - */ -ink.util.hasMouseSecondaryButton = function(evt) { - return (evt.buttons & 2) == 2 || - ((evt.buttons & 1) == 1 && goog.userAgent.WEBKIT && - goog.userAgent.MAC && evt.ctrlKey); -}; -
diff --git a/third_party/ink/sketchology/public/nacl/embed.soy.js b/third_party/ink/sketchology/public/nacl/embed.soy.js deleted file mode 100644 index e0b4325..0000000 --- a/third_party/ink/sketchology/public/nacl/embed.soy.js +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// This file was automatically generated from embed.soy. -// Please don't edit this file by hand. - -/** - * @fileoverview Templates in namespace ink.soy.nacl. - * @public - */ - -goog.provide('ink.soy.nacl.canvasHTML'); - -goog.require('goog.soy.data.SanitizedContent'); -goog.require('soy'); -goog.require('soy.asserts'); -goog.require('soydata.VERY_UNSAFE'); - - -/** - * @param {ink.soy.nacl.canvasHTML.Params} opt_data - * @param {Object<string, *>=} opt_ijData - * @param {Object<string, *>=} opt_ijData_deprecated - * @return {!goog.soy.data.SanitizedHtml} - * @suppress {checkTypes} - */ -ink.soy.nacl.canvasHTML = function(opt_data, opt_ijData, opt_ijData_deprecated) { - opt_ijData = opt_ijData_deprecated || opt_ijData; - /** @type {!goog.soy.data.SanitizedContent|string} */ - var manifestUrl = soy.asserts.assertType(goog.isString(opt_data.manifestUrl) || opt_data.manifestUrl instanceof goog.soy.data.SanitizedContent, 'manifestUrl', opt_data.manifestUrl, '!goog.soy.data.SanitizedContent|string'); - /** @type {!goog.soy.data.SanitizedContent|string} */ - var useMSAA = soy.asserts.assertType(goog.isString(opt_data.useMSAA) || opt_data.useMSAA instanceof goog.soy.data.SanitizedContent, 'useMSAA', opt_data.useMSAA, '!goog.soy.data.SanitizedContent|string'); - /** @type {!goog.soy.data.SanitizedContent|string} */ - var useSingleBuffer = soy.asserts.assertType(goog.isString(opt_data.useSingleBuffer) || opt_data.useSingleBuffer instanceof goog.soy.data.SanitizedContent, 'useSingleBuffer', opt_data.useSingleBuffer, '!goog.soy.data.SanitizedContent|string'); - /** @type {!goog.soy.data.SanitizedContent|string} */ - var sengineType = soy.asserts.assertType(goog.isString(opt_data.sengineType) || opt_data.sengineType instanceof goog.soy.data.SanitizedContent, 'sengineType', opt_data.sengineType, '!goog.soy.data.SanitizedContent|string'); - return soydata.VERY_UNSAFE.ordainSanitizedHtml(((goog.DEBUG && soy.$$debugSoyTemplateInfo) ? '<!--dta_of(ink.soy.nacl.canvasHTML, third_party/sketchology/public/nacl/embed.soy, 3)-->' : '') + '<style' + (opt_ijData && opt_ijData.csp_nonce ? ' nonce="' + soy.$$escapeHtmlAttribute(opt_ijData && opt_ijData.csp_nonce) + '"' : '') + '>\n #ink-engine-hwoverlay {\n display: none;\n position: absolute;\n width: 5px;\n height: 5px;\n left: 0px;\n top: 0px;\n /* Transforms and semi-transparent color are used to ensure the div\n * prevents use of a hardware overlay for the underlying canvas element,\n * despite future optimizations to the hardware overlay eligibility\n * detection in ChromeOS. See b/64569245 for details */\n background-color: rgba(0, 0, 0, 0.01);\n transform: translate3d(0.33, 0.14, 0);\n }\n </style><embed id="ink-engine" use_msaa="' + soy.$$escapeHtmlAttribute(useMSAA) + '" use_single_buffer="' + soy.$$escapeHtmlAttribute(useSingleBuffer) + '" src="' + soy.$$escapeHtmlAttribute(soy.$$filterNormalizeUri(manifestUrl)) + '" type="application/x-nacl" sengine_type="' + soy.$$escapeHtmlAttribute(sengineType) + '"><div id="ink-engine-hwoverlay"></div>' + ((goog.DEBUG && soy.$$debugSoyTemplateInfo) ? '<!--dta_cf(ink.soy.nacl.canvasHTML)-->' : '')); -}; -/** - * @typedef {{ - * manifestUrl: (!goog.soy.data.SanitizedContent|string), - * useMSAA: (!goog.soy.data.SanitizedContent|string), - * useSingleBuffer: (!goog.soy.data.SanitizedContent|string), - * sengineType: (!goog.soy.data.SanitizedContent|string), - * }} - */ -ink.soy.nacl.canvasHTML.Params; -if (goog.DEBUG) { - ink.soy.nacl.canvasHTML.soyTemplateName = 'ink.soy.nacl.canvasHTML'; -}
diff --git a/third_party/ink/sketchology/public/nacl/sketchology_engine_wrapper.js b/third_party/ink/sketchology/public/nacl/sketchology_engine_wrapper.js deleted file mode 100644 index 8ef2088..0000000 --- a/third_party/ink/sketchology/public/nacl/sketchology_engine_wrapper.js +++ /dev/null
@@ -1,764 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -/** - * @fileoverview Wrapper to call the Sketchology engine. - */ - -goog.provide('ink.SketchologyEngineWrapper'); - -goog.require('goog.asserts'); -goog.require('goog.events'); -goog.require('goog.labs.userAgent.platform'); -goog.require('goog.math.Box'); -goog.require('goog.math.Coordinate'); -goog.require('goog.math.Rect'); -goog.require('goog.math.Size'); -goog.require('goog.soy'); -goog.require('goog.ui.Component'); -goog.require('ink.Color'); -goog.require('ink.ElementListener'); -goog.require('ink.UndoStateChangeEvent'); -goog.require('ink.soy.nacl.canvasHTML'); -goog.require('ink.util'); -goog.require('net.proto2.contrib.WireSerializer'); -goog.require('sketchology.proto.BackgroundColor'); -goog.require('sketchology.proto.BackgroundImageInfo'); -goog.require('sketchology.proto.Command'); -goog.require('sketchology.proto.Flag'); -goog.require('sketchology.proto.FlagAssignment'); -goog.require('sketchology.proto.ImageInfo'); -goog.require('sketchology.proto.MutationPacket'); -goog.require('sketchology.proto.NoArgCommand'); -goog.require('sketchology.proto.OutOfBoundsColor'); -goog.require('sketchology.proto.PageProperties'); -goog.require('sketchology.proto.Rect'); -goog.require('sketchology.proto.SequencePoint'); -goog.require('sketchology.proto.SetCallbackFlags'); -goog.require('sketchology.proto.Snapshot'); -goog.require('sketchology.proto.ToolParams'); - - - -/** - * @param {?string} engineUrl URL to the native client manifest file - * @param {ink.ElementListener} elementListener - * @param {function(number, number, Uint8ClampedArray)} onImageExportComplete - * @param {!ink.util.SEngineType} sengineType - * @struct - * @constructor - * @extends {goog.ui.Component} - */ -ink.SketchologyEngineWrapper = function( - engineUrl, elementListener, onImageExportComplete, sengineType) { - ink.SketchologyEngineWrapper.base(this, 'constructor'); - - goog.asserts.assert(engineUrl); - /** @private {string} */ - this.engineUrl_ = engineUrl; - - /** @private {ink.ElementListener} */ - this.elementListener_ = elementListener; - - /** @private {function(number, number, Uint8ClampedArray)} */ - this.onImageExportComplete_ = onImageExportComplete; - - // default document bounds - this.pageLeft_ = 0; - this.pageTop_ = 600; - this.pageRight_ = 800; - this.pageBottom_ = 0; - - /** - * Protocol Buffer wire format serializer. - * @type {!net.proto2.contrib.WireSerializer} - * @private - */ - this.wireSerializer_ = new net.proto2.contrib.WireSerializer(); - - /** @private */ - this.lastBrushUpdate_ = goog.nullFunction; - - /** @private */ - this.penModeEnabled_ = false; - - /** @private {boolean} */ - this.listenersAdded_ = false; - - /** @private {string} */ - this.sengineType_ = /** @type {string} */ (sengineType); - - /** @private {Array.<function(!sketchology.proto.Snapshot)>} */ - this.snapshotCallbacks_ = []; - - /** @private {Array.<function(!sketchology.proto.Snapshot)>} */ - this.brixConversionCallbacks_ = []; - - /** @private {Array.<!ink.util.RealtimeDocument>} */ - this.brixDocuments_ = []; - - /** @private {Array.<function(boolean)>} */ - this.snapshotHasPendingMutationsCallbacks_ = []; - - /** @private {Array.<function(sketchology.proto.MutationPacket)>} */ - this.extractMutationPacketCallbacks_ = []; - - /** @private {Array.<function(sketchology.proto.Snapshot)>} */ - this.clearPendingMutationsCallbacks_ = []; - - /** @private {Element} */ - this.engineElement_; - - /** @private {Object<number, !Function>} */ - this.sequencePointCallbacks_ = {}; - - /** @private {number} */ - this.nextSequencePointId_ = 0; -}; -goog.inherits(ink.SketchologyEngineWrapper, goog.ui.Component); - -/** @override */ -ink.SketchologyEngineWrapper.prototype.createDom = function() { - const useMSAA = !goog.labs.userAgent.platform.isMacintosh() || - // MSAA is disabled for MacOS 10.12.4 and prior: b/38280481 - goog.labs.userAgent.platform.isVersionOrHigher('10.12.5'); - const useSingleBuffer = goog.labs.userAgent.platform.isChromeOS(); - const elem = goog.soy.renderAsElement(ink.soy.nacl.canvasHTML, { - manifestUrl: this.engineUrl_, - useMSAA: !!useMSAA + '', - useSingleBuffer: !!useSingleBuffer + '', - sengineType: this.sengineType_ - }); - this.setElementInternal(elem); - this.engineElement_ = elem.querySelector('#ink-engine'); -}; - -/** @override */ -ink.SketchologyEngineWrapper.prototype.enterDocument = function() { - this.engineElement_.addEventListener(goog.events.EventType.LOAD, () => { - this.initGl(); - this.lastBrushUpdate_(); - this.assignFlag( - sketchology.proto.Flag.ENABLE_PEN_MODE, this.penModeEnabled_); - }); -}; - - -/** @enum {string} */ -ink.SketchologyEngineWrapper.EventType = { - CANVAS_INITIALIZED: goog.events.getUniqueId('gl_canvas_initialized'), - CANVAS_FATAL_ERROR: goog.events.getUniqueId('fatal_error'), - PEN_MODE_ENABLED: goog.events.getUniqueId('pen_mode_enabled') -}; - - -/** - * An event fired when pen mode is enabled or disabled. - * - * @param {boolean} enabled - * - * @extends {goog.events.Event} - * @constructor - * @struct - */ -ink.SketchologyEngineWrapper.PenModeEnabled = function(enabled) { - ink.SketchologyEngineWrapper.PenModeEnabled.base(this, 'constructor', - ink.SketchologyEngineWrapper.EventType.PEN_MODE_ENABLED); - - /** @type {boolean} */ - this.enabled = enabled; -}; -goog.inherits(ink.SketchologyEngineWrapper.PenModeEnabled, goog.events.Event); - - -/** Poke the engine to wake up and start drawing */ -ink.SketchologyEngineWrapper.prototype.poke = function() { - this.engineElement_.postMessage(['poke', '']); -}; - -/** - * Global exit function for emscripten to call. - * @export - */ -ink.SketchologyEngineWrapper.exit = function() { - console.log('Engine requested exit.'); -}; - -/** - * @param {sketchology.proto.Command} command - */ -ink.SketchologyEngineWrapper.prototype.handleCommand = function(command) { - var commandBytes = this.wireSerializer_.serialize(command); - var buf = new Uint8Array(commandBytes); - this.engineElement_.postMessage(['handleCommand', buf.buffer]); -}; - -/** - * Tells the engine to handle a message received remotely. - * - * @param {!Object<string, string>} bundle - */ -ink.SketchologyEngineWrapper.prototype.addElement = function(bundle) { - goog.asserts.assert(bundle); - this.engineElement_.postMessage(['addElementToEngine', {'bundle': bundle}]); -}; - - -/** - * Add an encoded element bundle to the engine. - * - * @param {!Object<string, string>} bundle - * @param {string} belowUUID - */ -ink.SketchologyEngineWrapper.prototype.addElementBelow = function( - bundle, belowUUID) { - goog.asserts.assert(bundle); - this.engineElement_.postMessage( - ['addElementToEngineBelow', {'bundle': bundle, 'below_uuid': belowUUID}]); -}; - - -/** - * @param {string} uuid - */ -ink.SketchologyEngineWrapper.prototype.removeElement = function(uuid) { - this.engineElement_.postMessage(['removeElement', uuid]); -}; - - -/** - * NaCl does its own GL initialization, so we just hook up listeners. - */ -ink.SketchologyEngineWrapper.prototype.initGl = function() { - var elem = this.engineElement_; - this.setPageBounds( - this.pageLeft_, this.pageTop_, this.pageRight_, this.pageBottom_); - if (!this.listenersAdded_) { - this.listenersAdded_ = true; - elem.addEventListener('message', goog.bind(function(msg) { - if (!('event_type' in msg['data'])) { - return; // Unknown event type! - } - var data = msg['data']; - switch (data['event_type']) { - case 'exit': - ink.SketchologyEngineWrapper.exit(); - break; - case 'debug': - if (goog.DEBUG) { - console.log(data['message']); - } - break; - case 'image_export': - this.onImageExportComplete_( - data['width'], data['height'], - new Uint8ClampedArray(data['bytes'])); - break; - case 'element_added': - if (this.elementListener_) { - this.elementListener_.onElementCreated(data['uuid'], - data['encoded_element'], data['encoded_transform']); - } - break; - case 'elements_mutated': - if (this.elementListener_) { - this.elementListener_.onElementsMutated(data['uuids'], - data['encoded_transforms']); - } - break; - case 'elements_removed': - if (this.elementListener_) { - this.elementListener_.onElementsRemoved(data['uuids']); - } - break; - case 'flag_changed': - if (data['which'] == sketchology.proto.Flag.ENABLE_PEN_MODE) { - this.penModeEnabled_ = data['enabled']; - this.dispatchEvent( - new ink.SketchologyEngineWrapper.PenModeEnabled( - data['enabled'])); - } - break; - case 'undo_redo_state_changed': - this.dispatchEvent(new ink.UndoStateChangeEvent( - !!data['can_undo'], !!data['can_redo'])); - break; - case 'snapshot_gotten': - var proto = new sketchology.proto.Snapshot(); - this.wireSerializer_.deserializeTo(proto, data['snapshot']); - this.snapshotCallbacks_.shift().call(null, proto); - break; - case 'brix_elements_converted': - var proto = new sketchology.proto.Snapshot(); - this.wireSerializer_.deserializeTo(proto, data['snapshot']); - var pageProperties = new sketchology.proto.PageProperties(); - var rect = new sketchology.proto.Rect(); - var brixDoc = this.brixDocuments_.shift(); - var model = brixDoc.getModel(); - var root = model.getRoot(); - var brixBounds = root.get('bounds'); - rect.setXhigh(brixBounds.xhigh || 0); - rect.setXlow(brixBounds.xlow || 0); - rect.setYhigh(brixBounds.yhigh || 0); - rect.setYlow(brixBounds.ylow || 0); - pageProperties.setBounds(rect); - proto.setPageProperties(pageProperties); - this.brixConversionCallbacks_.shift().call(null, proto); - break; - case 'snapshot_has_pending_mutations': - this.snapshotHasPendingMutationsCallbacks_.shift().call( - null, data['has_mutations']); - break; - case 'extracted_mutation_packet': - var proto = new sketchology.proto.MutationPacket(); - this.wireSerializer_.deserializeTo(proto, data['extraction_packet']); - this.extractMutationPacketCallbacks_.shift().call(null, proto); - break; - case 'cleared_pending_mutations': - var proto = new sketchology.proto.Snapshot(); - this.wireSerializer_.deserializeTo(proto, data['snapshot']); - this.clearPendingMutationsCallbacks_.shift().call(null, proto); - break; - case 'hwoverlay': - this.setHardwareOverlay(!!data['enable']); - break; - case 'single_buffer': - // If the Native Client module was able to obtain a single buffered - // graphics context, flip the embed element to allow promotion to - // hardware overlay on Eve in landscape mode. - // TODO(b/64569245): Add support for all device orientations - this.engineElement_.style.transform = 'scaleY(-1)'; - break; - case 'sequence_point_reached': - var id = data['id']; - var cb = this.sequencePointCallbacks_[id]; - delete this.sequencePointCallbacks_[id]; - cb(); - break; - } - }, this)); - } - this.dispatchEvent(ink.SketchologyEngineWrapper.EventType.CANVAS_INITIALIZED); -}; - - -/** - * Sets the border image. - * @param {Uint8ClampedArray} data - * @param {goog.math.Size} size - * @param {string} uri - * @param {!sketchology.proto.Border} borderImageProto - * @param {number} outOfBoundsColor The out of bounds color in rgba 8888. - */ -ink.SketchologyEngineWrapper.prototype.setBorderImage = function( - data, size, uri, borderImageProto, outOfBoundsColor) { - var outOfBoundsColorProto = new sketchology.proto.OutOfBoundsColor(); - outOfBoundsColorProto.setRgba(outOfBoundsColor); - var commandProto = new sketchology.proto.Command(); - commandProto.setSetOutOfBoundsColor(outOfBoundsColorProto); - this.handleCommand(commandProto); - - var msg = { - 'imageData': data.buffer, - 'uri': uri, - 'width': size.width, - 'height': size.height, - 'assetType': sketchology.proto.ImageInfo.AssetType.BORDER - }; - this.engineElement_.postMessage(['addImageData', msg]); - - commandProto = new sketchology.proto.Command(); - commandProto.setSetPageBorder(borderImageProto); - this.handleCommand(commandProto); -}; - - -/** - * Sets the background image from a data URI. - * - * @param {Uint8ClampedArray} data - * @param {goog.math.Size} size - * @param {string} uri - * @param {!sketchology.proto.BackgroundImageInfo} bgImageProto - */ -ink.SketchologyEngineWrapper.prototype.setBackgroundImage = function( - data, size, uri, bgImageProto) { - var msg = { - 'imageData': data.buffer, - 'uri': uri, - 'width': size.width, - 'height': size.height, - 'assetType': sketchology.proto.ImageInfo.AssetType.DEFAULT - }; - this.engineElement_.postMessage(['addImageData', msg]); - - var commandProto = new sketchology.proto.Command(); - commandProto.setBackgroundImage(bgImageProto); - this.handleCommand(commandProto); -}; - - -/** - * Set the background color - * @param {ink.Color} color - */ -ink.SketchologyEngineWrapper.prototype.setBackgroundColor = function(color) { - var bgColorProto = new sketchology.proto.BackgroundColor(); - bgColorProto.setRgba(color.getRgbaUint32()[0]); - var commandProto = new sketchology.proto.Command(); - commandProto.setBackgroundColor(bgColorProto); - this.handleCommand(commandProto); -}; - - -/** - * Sets the camera position. - * - * @param {!goog.math.Rect} cameraRect The camera rect. - */ -ink.SketchologyEngineWrapper.prototype.setCamera = function(cameraRect) { - var camera = cameraRect.toBox(); - var rectProto = new sketchology.proto.Rect(); - // Top and bottom are reversed in Sketchology for "reasons." - rectProto.setYhigh(camera.bottom); - rectProto.setXhigh(camera.right); - rectProto.setYlow(camera.top); - rectProto.setXlow(camera.left); - var commandProto = new sketchology.proto.Command(); - commandProto.setCameraPosition(rectProto); - this.handleCommand(commandProto); -}; - - -/** - * @private - * @param {sketchology.proto.Rect} rectProto rect js proto with top/bottom - * reversed - * @return {goog.math.Rect} proper CSS rect with top/bottom correct - */ -ink.SketchologyEngineWrapper.prototype.convertRect_ = function(rectProto) { - // Top and bottom are reversed in Sketchology for "reasons." - var box = new goog.math.Box( - rectProto.getYlowOrDefault(), rectProto.getXhighOrDefault(), - rectProto.getYhighOrDefault(), rectProto.getXlowOrDefault()); - return box ? - goog.math.Rect.createFromBox(box) : - null; -}; - - -/** - * Create a scaled rectangle with a given size/center scaled by factor. - * - * @param {!goog.math.Coordinate} center - * @param {!goog.math.Size} size - * @param {number} factor The scale factor - * - * @return {goog.math.Rect} The scaled rectangle. - * @private - */ -ink.SketchologyEngineWrapper.prototype.getScaledRect_ = function( - center, size, factor) { - size.width /= factor; - size.height /= factor; - - var x = center.x - size.width / 2; - var y = center.y - size.height / 2; - - var cameraRect = new goog.math.Rect(x, y, size.width, size.height); - - goog.asserts.assert( - Math.round(cameraRect.getCenter().x) === Math.round(center.x) && - Math.round(cameraRect.getCenter().y) === Math.round(center.y)); - - return cameraRect; -}; - - -/** - * Sets the brush parameters. - * - * @param {Uint32Array} color rgba 32-bit unsigned color - * @param {number} strokeWidth brush size percent [0,1] - * @param {sketchology.proto.ToolParams.ToolType} toolType - * @param {sketchology.proto.BrushType} brushType - */ -ink.SketchologyEngineWrapper.prototype.brushUpdate = - function(color, strokeWidth, toolType, brushType) { - var self = this; - this.lastBrushUpdate_ = function() { - // LINE tools need special handling - if (toolType != sketchology.proto.ToolParams.ToolType.LINE) { - var toolParamsProto = new sketchology.proto.ToolParams(); - toolParamsProto.setTool(toolType); - var commandProto = new sketchology.proto.Command(); - commandProto.setToolParams(toolParamsProto); - this.handleCommand(commandProto); - } else { - var updateBrushData = { - 'brush': brushType, - 'rgba': color[0], - 'stroke_width': strokeWidth - }; - self.engineElement_.postMessage(['updateBrush', updateBrushData]); - } - }; - this.lastBrushUpdate_(); -}; - - -/** Clears the canvas. */ -ink.SketchologyEngineWrapper.prototype.clear = function() { - this.engineElement_.postMessage(['clear', '']); -}; - - -/** Removes all elements from the document. */ -ink.SketchologyEngineWrapper.prototype.removeAll = function() { - this.engineElement_.postMessage(['removeAll', '']); -}; - - -/** - * Sets or unsets readOnly on the canvas. - * @param {boolean} readOnly - */ -ink.SketchologyEngineWrapper.prototype.setReadOnly = function(readOnly) { - this.assignFlag(sketchology.proto.Flag.READ_ONLY_MODE, !!readOnly); -}; - - -/** - * Assign a flag on the canvas - * @param {sketchology.proto.Flag} flag - * @param {boolean} enable - */ -ink.SketchologyEngineWrapper.prototype.assignFlag = function(flag, enable) { - var flagProto = new sketchology.proto.FlagAssignment(); - flagProto.setFlag(flag); - flagProto.setBoolValue(!!enable); - var commandProto = new sketchology.proto.Command(); - commandProto.setFlagAssignment(flagProto); - this.handleCommand(commandProto); -}; - - - - -/** - * Sets element transforms. - * @param {Array.<string>} uuids - * @param {Array.<string>} encodedTransforms - */ -ink.SketchologyEngineWrapper.prototype.setElementTransforms = function( - uuids, encodedTransforms) { - if (uuids.length !== encodedTransforms.length) { - throw new Error('mismatch in transform array lengths'); - } - this.engineElement_.postMessage([ - 'setElementTransforms', - {'uuids': uuids, 'encoded_transforms': encodedTransforms} - ]); -}; - -/** - * Set callback flags for what data is attached to element callbacks. - * @param {!sketchology.proto.SetCallbackFlags} setCallbackFlags - */ -ink.SketchologyEngineWrapper.prototype.setCallbackFlags = function( - setCallbackFlags) { - var commandProto = new sketchology.proto.Command(); - commandProto.setSetCallbackFlags(setCallbackFlags); - this.handleCommand(commandProto); -}; - - -/** - * Sets the size of the page. - * @param {number} left - * @param {number} top - * @param {number} right - * @param {number} bottom - */ -ink.SketchologyEngineWrapper.prototype.setPageBounds = - function(left, top, right, bottom) { - this.pageLeft_ = left; - this.pageTop_ = top; - this.pageRight_ = right; - this.pageBottom_ = bottom; - var pageBounds = new sketchology.proto.Rect(); - pageBounds.setXlow(this.pageLeft_); - pageBounds.setYlow(this.pageBottom_); - pageBounds.setXhigh(this.pageRight_); - pageBounds.setYhigh(this.pageTop_); - var commandProto = new sketchology.proto.Command(); - commandProto.setPageBounds(pageBounds); - this.handleCommand(commandProto); -}; - - -/** - * Deselects anything selected with the edit tool. - */ -ink.SketchologyEngineWrapper.prototype.deselectAll = function() { - throw new Error('deselectAll not yet implemented for NaCl.'); -}; - - -/** - * Start the PNG export process. - * - * @param {!sketchology.proto.ImageExport} exportProto - */ -ink.SketchologyEngineWrapper.prototype.exportPng = function(exportProto) { - var commandProto = new sketchology.proto.Command(); - commandProto.setImageExport(exportProto); - this.handleCommand(commandProto); -}; - - -/** - * Simple undo. - */ -ink.SketchologyEngineWrapper.prototype.undo = function() { - var commandProto = new sketchology.proto.Command(); - commandProto.setUndo(new sketchology.proto.NoArgCommand()); - this.handleCommand(commandProto); -}; - - -/** - * Simple redo. - */ -ink.SketchologyEngineWrapper.prototype.redo = function() { - var commandProto = new sketchology.proto.Command(); - commandProto.setRedo(new sketchology.proto.NoArgCommand()); - this.handleCommand(commandProto); -}; - - -/** - * Returns the current snapshot. - * @param {function(!sketchology.proto.Snapshot)} callback - */ -ink.SketchologyEngineWrapper.prototype.getSnapshot = function(callback) { - this.snapshotCallbacks_.push(callback); - this.engineElement_.postMessage(['getSnapshot']); -}; - - -/** - * Loads a document from a snapshot. - * - * @param {!sketchology.proto.Snapshot} snapshotProto - */ -ink.SketchologyEngineWrapper.prototype.loadFromSnapshot = - function(snapshotProto) { - var bytes = this.wireSerializer_.serialize(snapshotProto); - var buf = new Uint8Array(bytes); - this.engineElement_.postMessage(['loadFromSnapshot', buf.buffer]); -}; - - -/** - * Gets the raw engine object. Do not use this. - * @return {Object} - */ -ink.SketchologyEngineWrapper.prototype.getRawEngineObject = function() { - throw new Error('getRawEngineObject not supported for NaCl.'); -}; - - -/** - * Generates a snapshot based on a brix document. - * @param {!ink.util.RealtimeDocument} brixDoc - * @param {function(!sketchology.proto.Snapshot)} callback - */ -ink.SketchologyEngineWrapper.prototype.convertBrixDocumentToSnapshot = - function(brixDoc, callback) { - var model = brixDoc.getModel(); - var root = model.getRoot(); - var pages = root.get('pages'); - var page = pages.get(0); - if (!page) { - throw Error('unable to get page from brix document.'); - } - var elements = page.get('elements').asArray(); - - var jsonElements = []; - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - jsonElements.push({'id': element.get('id'), - 'proto': element.get('proto'), - 'transform': element.get('transform')}); - } - this.brixDocuments_.push(brixDoc); - this.brixConversionCallbacks_.push(callback); - this.engineElement_.postMessage(['convertBrixElements', jsonElements]); -}; - - -/** - * @param {!sketchology.proto.Snapshot} snapshot - * @param {function(boolean)} callback - */ -ink.SketchologyEngineWrapper.prototype.snapshotHasPendingMutations = - function(snapshot, callback) { - var bytes = this.wireSerializer_.serialize(snapshot); - var buf = new Uint8Array(bytes); - this.snapshotHasPendingMutationsCallbacks_.push(callback); - this.engineElement_.postMessage(['snapshotHasPendingMutations', buf.buffer]); -}; - - -/** - * @param {!sketchology.proto.Snapshot} snapshot - * @param {function(sketchology.proto.MutationPacket)} callback - */ -ink.SketchologyEngineWrapper.prototype.extractMutationPacket = - function(snapshot, callback) { - var bytes = this.wireSerializer_.serialize(snapshot); - var buf = new Uint8Array(bytes); - this.extractMutationPacketCallbacks_.push(callback); - this.engineElement_.postMessage(['extractMutationPacket', buf.buffer]); -}; - - -/** - * @param {!sketchology.proto.Snapshot} snapshot - * @param {function(sketchology.proto.Snapshot)} callback - */ -ink.SketchologyEngineWrapper.prototype.clearPendingMutations = function( - snapshot, callback) { - var bytes = this.wireSerializer_.serialize(snapshot); - var buf = new Uint8Array(bytes); - this.clearPendingMutationsCallbacks_.push(callback); - this.engineElement_.postMessage(['clearPendingMutations', buf.buffer]); -}; - - -/** - * Enable or disable hardware overlay by hiding or showing a 1-pixel div over - * the canvas. - * - * @param {boolean} enable - */ -ink.SketchologyEngineWrapper.prototype.setHardwareOverlay = function(enable) { - document.querySelector('#ink-engine-hwoverlay').style.display = - enable ? 'none' : 'block'; -}; - - -/** - * Calls the given callback once all previous asynchronous engine operations - * have been applied. - * @param {!Function} callback - */ -ink.SketchologyEngineWrapper.prototype.flush = function(callback) { - var commandProto = new sketchology.proto.Command(); - var sp = new sketchology.proto.SequencePoint(); - sp.setId(this.nextSequencePointId_); - this.sequencePointCallbacks_[this.nextSequencePointId_++] = callback; - commandProto.setSequencePoint(sp); - this.handleCommand(commandProto); -};
diff --git a/third_party/ink/template/soy/soyutils_usegoog.js b/third_party/ink/template/soy/soyutils_usegoog.js deleted file mode 100644 index 8720f1ca..0000000 --- a/third_party/ink/template/soy/soyutils_usegoog.js +++ /dev/null
@@ -1,2401 +0,0 @@ -/* - * Copyright 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * Utility functions and classes for Soy gencode - * - * <p> - * This file contains utilities that should only be called by Soy-generated - * JS code. Please do not use these functions directly from - * your hand-written code. Their names all start with '$$', or exist within the - * soydata.VERY_UNSAFE namespace. - * - * <p>TODO(lukes): ensure that the above pattern is actually followed - * consistently. - * - * @author Garrett Boyer - * @author Mike Samuel - * @author Kai Huang - * @author Aharon Lanin - */ -goog.provide('soy'); -goog.provide('soy.asserts'); -goog.provide('soy.esc'); -goog.provide('soydata'); -goog.provide('soydata.SanitizedHtml'); -goog.provide('soydata.VERY_UNSAFE'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.debug'); -goog.require('goog.format'); -goog.require('goog.html.SafeHtml'); -goog.require('goog.html.SafeScript'); -goog.require('goog.html.SafeStyle'); -goog.require('goog.html.SafeStyleSheet'); -goog.require('goog.html.SafeUrl'); -goog.require('goog.html.TrustedResourceUrl'); -goog.require('goog.html.uncheckedconversions'); -goog.require('goog.i18n.BidiFormatter'); -goog.require('goog.i18n.bidi'); -goog.require('goog.object'); -goog.require('goog.soy.data.SanitizedContent'); -goog.require('goog.soy.data.SanitizedContentKind'); -goog.require('goog.soy.data.SanitizedCss'); -goog.require('goog.soy.data.SanitizedHtml'); -goog.require('goog.soy.data.SanitizedHtmlAttribute'); -goog.require('goog.soy.data.SanitizedJs'); -goog.require('goog.soy.data.SanitizedStyle'); -goog.require('goog.soy.data.SanitizedTrustedResourceUri'); -goog.require('goog.soy.data.SanitizedUri'); -goog.require('goog.soy.data.UnsanitizedText'); -goog.require('goog.string'); -goog.require('goog.string.Const'); - -// ----------------------------------------------------------------------------- -// soydata: Defines typed strings, e.g. an HTML string {@code "a<b>c"} is -// semantically distinct from the plain text string {@code "a<b>c"} and smart -// templates can take that distinction into account. - -/** - * Checks whether a given value is of a given content kind. - * - * @param {*} value The value to be examined. - * @param {goog.soy.data.SanitizedContentKind} contentKind The desired content - * kind. - * @return {boolean} Whether the given value is of the given kind. - * @private - */ -soydata.isContentKind_ = function(value, contentKind) { - // TODO(aharon): This function should really include the assert on - // value.constructor that is currently sprinkled at most of the call sites. - // Unfortunately, that would require a (debug-mode-only) switch statement. - // TODO(aharon): Perhaps we should get rid of the contentKind property - // altogether and only at the constructor. - return value != null && value.contentKind === contentKind; -}; - - -/** - * Returns a given value's contentDir property, constrained to a - * goog.i18n.bidi.Dir value or null. Returns null if the value is null, - * undefined, a primitive or does not have a contentDir property, or the - * property's value is not 1 (for LTR), -1 (for RTL), or 0 (for neutral). - * - * @param {*} value The value whose contentDir property, if any, is to - * be returned. - * @return {?goog.i18n.bidi.Dir} The contentDir property. - */ -soydata.getContentDir = function(value) { - if (value != null) { - switch (value.contentDir) { - case goog.i18n.bidi.Dir.LTR: - return goog.i18n.bidi.Dir.LTR; - case goog.i18n.bidi.Dir.RTL: - return goog.i18n.bidi.Dir.RTL; - case goog.i18n.bidi.Dir.NEUTRAL: - return goog.i18n.bidi.Dir.NEUTRAL; - } - } - return null; -}; - - -/** - * This class is only a holder for {@code soydata.SanitizedHtml.from}. Do not - * instantiate or extend it. Use {@code goog.soy.data.SanitizedHtml} instead. - * - * @constructor - * @extends {goog.soy.data.SanitizedHtml} - * @abstract - */ -soydata.SanitizedHtml = function() { - soydata.SanitizedHtml.base(this, 'constructor'); // Throws an exception. -}; -goog.inherits(soydata.SanitizedHtml, goog.soy.data.SanitizedHtml); - -/** - * Returns a SanitizedHtml object for a particular value. The content direction - * is preserved. - * - * This HTML-escapes the value unless it is already SanitizedHtml or SafeHtml. - * - * @param {*} value The value to convert. If it is already a SanitizedHtml - * object, it is left alone. - * @return {!goog.soy.data.SanitizedHtml} A SanitizedHtml object derived from - * the stringified value. It is escaped unless the input is SanitizedHtml or - * SafeHtml. - */ -soydata.SanitizedHtml.from = function(value) { - // The check is soydata.isContentKind_() inlined for performance. - if (value != null && - value.contentKind === goog.soy.data.SanitizedContentKind.HTML) { - goog.asserts.assert(value.constructor === goog.soy.data.SanitizedHtml); - return /** @type {!goog.soy.data.SanitizedHtml} */ (value); - } - if (value instanceof goog.html.SafeHtml) { - return soydata.VERY_UNSAFE.ordainSanitizedHtml( - goog.html.SafeHtml.unwrap(value), value.getDirection()); - } - return soydata.VERY_UNSAFE.ordainSanitizedHtml( - soy.esc.$$escapeHtmlHelper(String(value)), soydata.getContentDir(value)); -}; - - -/** - * Empty string, used as a type in Soy templates. - * @enum {string} - * @private - */ -soydata.$$EMPTY_STRING_ = { - VALUE: '' -}; - - -/** - * Creates a factory for SanitizedContent types. - * - * This is a hack so that the soydata.VERY_UNSAFE.ordainSanitized* can - * instantiate Sanitized* classes, without making the Sanitized* constructors - * publicly usable. Requiring all construction to use the VERY_UNSAFE names - * helps callers and their reviewers easily tell that creating SanitizedContent - * is not always safe and calls for careful review. - * - * @param {function(new: T)} ctor A constructor. - * @return {!function(*, ?goog.i18n.bidi.Dir=): T} A factory that takes - * content and an optional content direction and returns a new instance. If - * the content direction is undefined, ctor.prototype.contentDir is used. - * @template T - * @private - */ -soydata.$$makeSanitizedContentFactory_ = function(ctor) { - /** - * @param {string} content - * @constructor - * @extends {goog.soy.data.SanitizedContent} - */ - function InstantiableCtor(content) { - /** @override */ - this.content = content; - } - InstantiableCtor.prototype = ctor.prototype; - /** - * Creates a ctor-type SanitizedContent instance. - * - * @param {*} content The content to put in the instance. - * @param {?goog.i18n.bidi.Dir=} opt_contentDir The content direction. If - * undefined, ctor.prototype.contentDir is used. - * @return {!goog.soy.data.SanitizedContent} The new instance. It is actually - * of type T above (ctor's type, a descendant of SanitizedContent), but - * there is no way to express that here. - */ - function sanitizedContentFactory(content, opt_contentDir) { - var result = new InstantiableCtor(String(content)); - if (opt_contentDir !== undefined) { - result.contentDir = opt_contentDir; - } - return result; - } - return sanitizedContentFactory; -}; - - -/** - * Creates a factory for SanitizedContent types that should always have their - * default directionality. - * - * This is a hack so that the soydata.VERY_UNSAFE.ordainSanitized* can - * instantiate Sanitized* classes, without making the Sanitized* constructors - * publicly usable. Requiring all construction to use the VERY_UNSAFE names - * helps callers and their reviewers easily tell that creating SanitizedContent - * is not always safe and calls for careful review. - * - * @param {function(new: T, string)} ctor A constructor. - * @return {!function(*): T} A factory that takes content and returns a new - * instance (with default directionality, i.e. ctor.prototype.contentDir). - * @template T - * @private - */ -soydata.$$makeSanitizedContentFactoryWithDefaultDirOnly_ = function(ctor) { - /** - * @param {string} content - * @constructor - * @extends {goog.soy.data.SanitizedContent} - */ - function InstantiableCtor(content) { - /** @override */ - this.content = content; - } - InstantiableCtor.prototype = ctor.prototype; - /** - * Creates a ctor-type SanitizedContent instance. - * - * @param {*} content The content to put in the instance. - * @return {!goog.soy.data.SanitizedContent} The new instance. It is actually - * of type T above (ctor's type, a descendant of SanitizedContent), but - * there is no way to express that here. - */ - function sanitizedContentFactory(content) { - var result = new InstantiableCtor(String(content)); - return result; - } - return sanitizedContentFactory; -}; - - -// ----------------------------------------------------------------------------- -// Sanitized content ordainers. Please use these with extreme caution (with the -// exception of markUnsanitizedText). A good recommendation is to limit usage -// of these to just a handful of files in your source tree where usages can be -// carefully audited. - - -/** - * Protects a string from being used in an noAutoescaped context. - * - * This is useful for content where there is significant risk of accidental - * unescaped usage in a Soy template. A great case is for user-controlled - * data that has historically been a source of vulernabilities. - * - * @param {*} content Text to protect. - * @param {?goog.i18n.bidi.Dir=} opt_contentDir The content direction; null if - * unknown and thus to be estimated when necessary. Default: null. - * @return {!goog.soy.data.UnsanitizedText} A wrapper that is rejected by the - * Soy noAutoescape print directive. - */ -soydata.markUnsanitizedText = function(content, opt_contentDir) { - return new goog.soy.data.UnsanitizedText(content, opt_contentDir); -}; - - -/** - * Takes a leap of faith that the provided content is "safe" HTML. - * - * @param {*} content A string of HTML that can safely be embedded in - * a PCDATA context in your app. If you would be surprised to find that an - * HTML sanitizer produced {@code s} (e.g. it runs code or fetches bad URLs) - * and you wouldn't write a template that produces {@code s} on security or - * privacy grounds, then don't pass {@code s} here. - * @param {?goog.i18n.bidi.Dir=} opt_contentDir The content direction; null if - * unknown and thus to be estimated when necessary. Default: null. - * @return {!goog.soy.data.SanitizedHtml} Sanitized content wrapper that - * indicates to Soy not to escape when printed as HTML. - */ -soydata.VERY_UNSAFE.ordainSanitizedHtml = - soydata.$$makeSanitizedContentFactory_(goog.soy.data.SanitizedHtml); - - -/** - * Takes a leap of faith that the provided content is "safe" (non-attacker- - * controlled, XSS-free) Javascript. - * - * @param {*} content Javascript source that when evaluated does not - * execute any attacker-controlled scripts. - * @return {!goog.soy.data.SanitizedJs} Sanitized content wrapper that indicates - * to Soy not to escape when printed as Javascript source. - */ -soydata.VERY_UNSAFE.ordainSanitizedJs = - soydata.$$makeSanitizedContentFactoryWithDefaultDirOnly_( - goog.soy.data.SanitizedJs); - - -/** - * Takes a leap of faith that the provided content is "safe" to use as a URI - * in a Soy template. - * - * This creates a Soy SanitizedContent object which indicates to Soy there is - * no need to escape it when printed as a URI (e.g. in an href or src - * attribute), such as if it's already been encoded or if it's a Javascript: - * URI. - * - * @param {*} content A chunk of URI that the caller knows is safe to - * emit in a template. - * @return {!goog.soy.data.SanitizedUri} Sanitized content wrapper that - * indicates to Soy not to escape or filter when printed in URI context. - */ -soydata.VERY_UNSAFE.ordainSanitizedUri = - soydata.$$makeSanitizedContentFactoryWithDefaultDirOnly_( - goog.soy.data.SanitizedUri); - - -/** - * Takes a leap of faith that the provided content is "safe" to use as a - * TrustedResourceUri in a Soy template. - * - * This creates a Soy SanitizedContent object which indicates to Soy there is - * no need to filter it when printed as a TrustedResourceUri. - * - * @param {*} content A chunk of TrustedResourceUri such as that the caller - * knows is safe to emit in a template. - * @return {!goog.soy.data.SanitizedTrustedResourceUri} Sanitized content - * wrapper that indicates to Soy not to escape or filter when printed in - * TrustedResourceUri context. - */ -soydata.VERY_UNSAFE.ordainSanitizedTrustedResourceUri = - soydata.$$makeSanitizedContentFactoryWithDefaultDirOnly_( - goog.soy.data.SanitizedTrustedResourceUri); - - -/** - * Takes a leap of faith that the provided content is "safe" to use as an - * HTML attribute. - * - * @param {*} content An attribute name and value, such as - * {@code dir="ltr"}. - * @return {!goog.soy.data.SanitizedHtmlAttribute} Sanitized content wrapper - * that indicates to Soy not to escape when printed as an HTML attribute. - */ -soydata.VERY_UNSAFE.ordainSanitizedHtmlAttribute = - soydata.$$makeSanitizedContentFactoryWithDefaultDirOnly_( - goog.soy.data.SanitizedHtmlAttribute); - - -/** - * Takes a leap of faith that the provided content is "safe" to use as STYLE - * in a style attribute. - * - * @param {*} content CSS, such as {@code color:#c3d9ff}. - * @return {!goog.soy.data.SanitizedStyle} Sanitized style wrapper that - * indicates to Soy there is no need to escape or filter when printed in CSS - * context. - */ -soydata.VERY_UNSAFE.ordainSanitizedStyle = - soydata.$$makeSanitizedContentFactoryWithDefaultDirOnly_( - goog.soy.data.SanitizedStyle); - - -/** - * Takes a leap of faith that the provided content is "safe" to use as CSS - * in a style block. - * - * @param {*} content CSS, such as {@code color:#c3d9ff}. - * @return {!goog.soy.data.SanitizedCss} Sanitized CSS wrapper that indicates to - * Soy there is no need to escape or filter when printed in CSS context. - */ -soydata.VERY_UNSAFE.ordainSanitizedCss = - soydata.$$makeSanitizedContentFactoryWithDefaultDirOnly_( - goog.soy.data.SanitizedCss); - - -// ----------------------------------------------------------------------------- -// Soy-generated utilities in the soy namespace. Contains implementations for -// common soyfunctions (e.g. keys()) and escaping/print directives. - - -/** - * Whether the locale is right-to-left. - * - * @type {boolean} - */ -soy.$$IS_LOCALE_RTL = goog.i18n.bidi.IS_RTL; - - -/** - * Builds an augmented map. The returned map will contain mappings from both - * the base map and the additional map. If the same key appears in both, then - * the value from the additional map will be visible, while the value from the - * base map will be hidden. The base map will be used, but not modified. - * - * @param {!Object} baseMap The original map to augment. - * @param {!Object} additionalMap A map containing the additional mappings. - * @return {!Object} An augmented map containing both the original and - * additional mappings. - */ -soy.$$augmentMap = function(baseMap, additionalMap) { - return soy.$$assignDefaults(soy.$$assignDefaults({}, additionalMap), baseMap); -}; - - -/** - * Copies extra properties into an object if they do not already exist. The - * destination object is mutated in the process. - * - * @param {!Object} obj The destination object to update. - * @param {!Object} defaults An object with default properties to apply. - * @return {!Object} The destination object for convenience. - */ -soy.$$assignDefaults = function(obj, defaults) { - for (var key in defaults) { - if (!(key in obj)) { - obj[key] = defaults[key]; - } - } - - return obj; -}; - - -/** - * Checks that the given map key is a string. - * @param {*} key Key to check. - * @return {string} The given key. - */ -soy.$$checkMapKey = function(key) { - // TODO: Support map literal with nonstring key. - if ((typeof key) != 'string') { - throw Error( - 'Map literal\'s key expression must evaluate to string' + - ' (encountered type "' + (typeof key) + '").'); - } - return key; -}; - - -/** - * Gets the keys in a map as an array. There are no guarantees on the order. - * @param {Object} map The map to get the keys of. - * @return {!Array<string>} The array of keys in the given map. - */ -soy.$$getMapKeys = function(map) { - var mapKeys = []; - for (var key in map) { - mapKeys.push(key); - } - return mapKeys; -}; - - -/** - * Returns the argument if it is not null. - * - * @param {T} val The value to check - * @return {T} val if is isn't null - * @template T - */ -soy.$$checkNotNull = function(val) { - if (val == null) { - throw Error('unexpected null value'); - } - return val; -}; - - -/** - * Parses the given string into a base 10 integer. Returns null if parse is - * unsuccessful. - * @param {string} str The string to parse - * @return {?number} The string parsed as a base 10 integer, or null if - * unsuccessful - */ -soy.$$parseInt = function(str) { - var parsed = parseInt(str, 10); - return isNaN(parsed) ? null : parsed; -}; - - -/** - * Parses the given string into a float. Returns null if parse is unsuccessful. - * @param {string} str The string to parse - * @return {?number} The string parsed as a float, or null if unsuccessful. - */ -soy.$$parseFloat = function(str) { - var parsed = parseFloat(str); - return isNaN(parsed) ? null : parsed; -}; - - -/** - * Gets a consistent unique id for the given delegate template name. Two calls - * to this function will return the same id if and only if the input names are - * the same. - * - * <p> Important: This function must always be called with a string constant. - * - * <p> If Closure Compiler is not being used, then this is just this identity - * function. If Closure Compiler is being used, then each call to this function - * will be replaced with a short string constant, which will be consistent per - * input name. - * - * @param {string} delTemplateName The delegate template name for which to get a - * consistent unique id. - * @return {string} A unique id that is consistent per input name. - * - * @idGenerator {consistent} - */ -soy.$$getDelTemplateId = function(delTemplateName) { - return delTemplateName; -}; - - -/** - * Map from registered delegate template key to the priority of the - * implementation. - * @type {Object} - * @private - */ -soy.$$DELEGATE_REGISTRY_PRIORITIES_ = {}; - -/** - * Map from registered delegate template key to the implementation function. - * @type {Object} - * @private - */ -soy.$$DELEGATE_REGISTRY_FUNCTIONS_ = {}; - - -/** - * Registers a delegate implementation. If the same delegate template key (id - * and variant) has been registered previously, then priority values are - * compared and only the higher priority implementation is stored (if - * priorities are equal, an error is thrown). - * - * @param {string} delTemplateId The delegate template id. - * @param {string} delTemplateVariant The delegate template variant (can be - * empty string). - * @param {number} delPriority The implementation's priority value. - * @param {Function} delFn The implementation function. - */ -soy.$$registerDelegateFn = function( - delTemplateId, delTemplateVariant, delPriority, delFn) { - - var mapKey = 'key_' + delTemplateId + ':' + delTemplateVariant; - var currPriority = soy.$$DELEGATE_REGISTRY_PRIORITIES_[mapKey]; - if (currPriority === undefined || delPriority > currPriority) { - // Registering new or higher-priority function: replace registry entry. - soy.$$DELEGATE_REGISTRY_PRIORITIES_[mapKey] = delPriority; - soy.$$DELEGATE_REGISTRY_FUNCTIONS_[mapKey] = delFn; - } else if (delPriority == currPriority) { - // Registering same-priority function: error. - throw Error( - 'Encountered two active delegates with the same priority ("' + - delTemplateId + ':' + delTemplateVariant + '").'); - } else { - // Registering lower-priority function: do nothing. - } -}; - - -/** - * Retrieves the (highest-priority) implementation that has been registered for - * a given delegate template key (id and variant). If no implementation has - * been registered for the key, then the fallback is the same id with empty - * variant. If the fallback is also not registered, and allowsEmptyDefault is - * true, then returns an implementation that is equivalent to an empty template - * (i.e. rendered output would be empty string). - * - * @param {string} delTemplateId The delegate template id. - * @param {string} delTemplateVariant The delegate template variant (can be - * empty string). - * @param {boolean} allowsEmptyDefault Whether to default to the empty template - * function if there's no active implementation. - * @return {Function} The retrieved implementation function. - */ -soy.$$getDelegateFn = function( - delTemplateId, delTemplateVariant, allowsEmptyDefault) { - - var delFn = soy.$$DELEGATE_REGISTRY_FUNCTIONS_[ - 'key_' + delTemplateId + ':' + delTemplateVariant]; - if (! delFn && delTemplateVariant != '') { - // Fallback to empty variant. - delFn = soy.$$DELEGATE_REGISTRY_FUNCTIONS_['key_' + delTemplateId + ':']; - } - - if (delFn) { - return delFn; - } else if (allowsEmptyDefault) { - return soy.$$EMPTY_TEMPLATE_FN_; - } else { - throw Error( - 'Found no active impl for delegate call to "' + delTemplateId + ':' + - delTemplateVariant + '" (and not allowemptydefault="true").'); - } -}; - - -/** - * Private helper soy.$$getDelegateFn(). This is the empty template function - * that is returned whenever there's no delegate implementation found. - * - * @param {Object<string, *>=} opt_data - * @param {Object<string, *>=} opt_ijData - * @param {Object<string, *>=} opt_ijData_deprecated TODO(b/36644846): remove - * @return {string} - * @private - */ -soy.$$EMPTY_TEMPLATE_FN_ = function( - opt_data, opt_ijData, opt_ijData_deprecated) { - return ''; -}; - - -// ----------------------------------------------------------------------------- -// Internal sanitized content wrappers. - - -/** - * Creates a SanitizedContent factory for SanitizedContent types for internal - * Soy let and param blocks. - * - * This is a hack within Soy so that SanitizedContent objects created via let - * and param blocks will truth-test as false if they are empty string. - * Tricking the Javascript runtime to treat empty SanitizedContent as falsey is - * not possible, and changing the Soy compiler to wrap every boolean statement - * for just this purpose is impractical. Instead, we just avoid wrapping empty - * string as SanitizedContent, since it's a no-op for empty strings anyways. - * - * @param {function(new: T)} ctor A constructor. - * @return {!function(*, ?goog.i18n.bidi.Dir=): (T|soydata.$$EMPTY_STRING_)} - * A factory that takes content and an optional content direction and - * returns a new instance, or an empty string. If the content direction is - * undefined, ctor.prototype.contentDir is used. - * @template T - * @private - */ -soydata.$$makeSanitizedContentFactoryForInternalBlocks_ = function(ctor) { - /** - * @param {string} content - * @constructor - * @extends {goog.soy.data.SanitizedContent} - */ - function InstantiableCtor(content) { - /** @override */ - this.content = content; - } - InstantiableCtor.prototype = ctor.prototype; - /** - * Creates a ctor-type SanitizedContent instance. - * - * @param {*} content The content to put in the instance. - * @param {?goog.i18n.bidi.Dir=} opt_contentDir The content direction. If - * undefined, ctor.prototype.contentDir is used. - * @return {!goog.soy.data.SanitizedContent|soydata.$$EMPTY_STRING_} The new - * instance, or an empty string. A new instance is actually of type T - * above (ctor's type, a descendant of SanitizedContent), but there's no - * way to express that here. - */ - function sanitizedContentFactory(content, opt_contentDir) { - var contentString = String(content); - if (!contentString) { - return soydata.$$EMPTY_STRING_.VALUE; - } - var result = new InstantiableCtor(contentString); - if (opt_contentDir !== undefined) { - result.contentDir = opt_contentDir; - } - return result; - } - return sanitizedContentFactory; -}; - - -/** - * Creates a SanitizedContent factory for SanitizedContent types that should - * always have their default directionality for internal Soy let and param - * blocks. - * - * This is a hack within Soy so that SanitizedContent objects created via let - * and param blocks will truth-test as false if they are empty string. - * Tricking the Javascript runtime to treat empty SanitizedContent as falsey is - * not possible, and changing the Soy compiler to wrap every boolean statement - * for just this purpose is impractical. Instead, we just avoid wrapping empty - * string as SanitizedContent, since it's a no-op for empty strings anyways. - * - * @param {function(new: T)} ctor A constructor. - * @return {!function(*): (T|soydata.$$EMPTY_STRING_)} A - * factory that takes content and returns a - * new instance (with default directionality, i.e. - * ctor.prototype.contentDir), or an empty string. - * @template T - * @private - */ -soydata.$$makeSanitizedContentFactoryWithDefaultDirOnlyForInternalBlocks_ = - function(ctor) { - /** - * @param {string} content - * @constructor - * @extends {goog.soy.data.SanitizedContent} - */ - function InstantiableCtor(content) { - /** @override */ - this.content = content; - } - InstantiableCtor.prototype = ctor.prototype; - /** - * Creates a ctor-type SanitizedContent instance. - * - * @param {*} content The content to put in the instance. - * @return {!goog.soy.data.SanitizedContent|soydata.$$EMPTY_STRING_} The new - * instance, or an empty string. A new instance is actually of type T - * above (ctor's type, a descendant of SanitizedContent), but there's no - * way to express that here. - */ - function sanitizedContentFactory(content) { - var contentString = String(content); - if (!contentString) { - return soydata.$$EMPTY_STRING_.VALUE; - } - var result = new InstantiableCtor(contentString); - return result; - } - return sanitizedContentFactory; -}; - - -/** - * Creates kind="text" block contents (internal use only). - * - * @param {*} content Text. - * @param {?goog.i18n.bidi.Dir=} opt_contentDir The content direction; null if - * unknown and thus to be estimated when necessary. Default: null. - * @return {!goog.soy.data.UnsanitizedText|soydata.$$EMPTY_STRING_} Wrapped result. - */ -soydata.$$markUnsanitizedTextForInternalBlocks = function( - content, opt_contentDir) { - var contentString = String(content); - if (!contentString) { - return soydata.$$EMPTY_STRING_.VALUE; - } - return new goog.soy.data.UnsanitizedText(contentString, opt_contentDir); -}; - - -/** - * Creates kind="html" block contents (internal use only). - * - * @param {*} content Text. - * @param {?goog.i18n.bidi.Dir=} opt_contentDir The content direction; null if - * unknown and thus to be estimated when necessary. Default: null. - * @return {!goog.soy.data.SanitizedHtml|soydata.$$EMPTY_STRING_} Wrapped - * result. - */ -soydata.VERY_UNSAFE.$$ordainSanitizedHtmlForInternalBlocks = - soydata.$$makeSanitizedContentFactoryForInternalBlocks_( - goog.soy.data.SanitizedHtml); - - -/** - * Creates kind="js" block contents (internal use only). - * - * @param {*} content Text. - * @return {!goog.soy.data.SanitizedJs|soydata.$$EMPTY_STRING_} Wrapped result. - */ -soydata.VERY_UNSAFE.$$ordainSanitizedJsForInternalBlocks = - soydata.$$makeSanitizedContentFactoryWithDefaultDirOnlyForInternalBlocks_( - goog.soy.data.SanitizedJs); - - -/** - * Creates kind="trustedResourceUri" block contents (internal use only). - * - * @param {*} content Text. - * @return {goog.soy.data.SanitizedTrustedResourceUri|soydata.$$EMPTY_STRING_} - * Wrapped result. - */ -soydata.VERY_UNSAFE.$$ordainSanitizedTrustedResourceUriForInternalBlocks = - soydata.$$makeSanitizedContentFactoryWithDefaultDirOnlyForInternalBlocks_( - goog.soy.data.SanitizedTrustedResourceUri); - - -/** - * Creates kind="uri" block contents (internal use only). - * - * @param {*} content Text. - * @return {goog.soy.data.SanitizedUri|soydata.$$EMPTY_STRING_} Wrapped result. - */ -soydata.VERY_UNSAFE.$$ordainSanitizedUriForInternalBlocks = - soydata.$$makeSanitizedContentFactoryWithDefaultDirOnlyForInternalBlocks_( - goog.soy.data.SanitizedUri); - - -/** - * Creates kind="attributes" block contents (internal use only). - * - * @param {*} content Text. - * @return {goog.soy.data.SanitizedHtmlAttribute|soydata.$$EMPTY_STRING_} - * Wrapped result. - */ -soydata.VERY_UNSAFE.$$ordainSanitizedAttributesForInternalBlocks = - soydata.$$makeSanitizedContentFactoryWithDefaultDirOnlyForInternalBlocks_( - goog.soy.data.SanitizedHtmlAttribute); - - -/** - * Creates kind="style" block contents (internal use only). - * - * @param {*} content Text. - * @return {goog.soy.data.SanitizedStyle|soydata.$$EMPTY_STRING_} Wrapped - * result. - */ -soydata.VERY_UNSAFE.$$ordainSanitizedStyleForInternalBlocks = - soydata.$$makeSanitizedContentFactoryWithDefaultDirOnlyForInternalBlocks_( - goog.soy.data.SanitizedStyle); - - -/** - * Creates kind="css" block contents (internal use only). - * - * @param {*} content Text. - * @return {goog.soy.data.SanitizedCss|soydata.$$EMPTY_STRING_} Wrapped result. - */ -soydata.VERY_UNSAFE.$$ordainSanitizedCssForInternalBlocks = - soydata.$$makeSanitizedContentFactoryWithDefaultDirOnlyForInternalBlocks_( - goog.soy.data.SanitizedCss); - - -// ----------------------------------------------------------------------------- -// Escape/filter/normalize. - - -/** - * Returns a SanitizedHtml object for a particular value. The content direction - * is preserved. - * - * This HTML-escapes the value unless it is already SanitizedHtml. Escapes - * double quote '"' in addition to '&', '<', and '>' so that a string can be - * included in an HTML tag attribute value within double quotes. - * - * @param {*} value The value to convert. If it is already a SanitizedHtml - * object, it is left alone. - * @return {!goog.soy.data.SanitizedHtml} An escaped version of value. - */ -soy.$$escapeHtml = function(value) { - return soydata.SanitizedHtml.from(value); -}; - - -/** - * Strips unsafe tags to convert a string of untrusted HTML into HTML that - * is safe to embed. The content direction is preserved. - * - * @param {?} value The string-like value to be escaped. May not be a string, - * but the value will be coerced to a string. - * @param {Array<string>=} opt_safeTags Additional tag names to whitelist. - * @return {!goog.soy.data.SanitizedHtml} A sanitized and normalized version of - * value. - */ -soy.$$cleanHtml = function(value, opt_safeTags) { - if (soydata.isContentKind_(value, goog.soy.data.SanitizedContentKind.HTML)) { - goog.asserts.assert(value.constructor === goog.soy.data.SanitizedHtml); - return /** @type {!goog.soy.data.SanitizedHtml} */ (value); - } - var tagWhitelist; - if (opt_safeTags) { - tagWhitelist = goog.object.createSet(opt_safeTags); - goog.object.extend(tagWhitelist, soy.esc.$$SAFE_TAG_WHITELIST_); - } else { - tagWhitelist = soy.esc.$$SAFE_TAG_WHITELIST_; - } - return soydata.VERY_UNSAFE.ordainSanitizedHtml( - soy.$$stripHtmlTags(value, tagWhitelist), soydata.getContentDir(value)); -}; - - -/** - * Escapes HTML, except preserves entities. - * - * Used mainly internally for escaping message strings in attribute and rcdata - * context, where we explicitly want to preserve any existing entities. - * - * @param {*} value Value to normalize. - * @return {string} A value safe to insert in HTML without any quotes or angle - * brackets. - */ -soy.$$normalizeHtml = function(value) { - return soy.esc.$$normalizeHtmlHelper(value); -}; - - -/** - * Escapes HTML special characters in a string so that it can be embedded in - * RCDATA. - * <p> - * Escapes HTML special characters so that the value will not prematurely end - * the body of a tag like {@code <textarea>} or {@code <title>}. RCDATA tags - * cannot contain other HTML entities, so it is not strictly necessary to escape - * HTML special characters except when part of that text looks like an HTML - * entity or like a close tag : {@code </textarea>}. - * <p> - * Will normalize known safe HTML to make sure that sanitized HTML (which could - * contain an innocuous {@code </textarea>} don't prematurely end an RCDATA - * element. - * - * @param {?} value The string-like value to be escaped. May not be a string, - * but the value will be coerced to a string. - * @return {string} An escaped version of value. - */ -soy.$$escapeHtmlRcdata = function(value) { - if (soydata.isContentKind_(value, goog.soy.data.SanitizedContentKind.HTML)) { - goog.asserts.assert(value.constructor === goog.soy.data.SanitizedHtml); - return soy.esc.$$normalizeHtmlHelper(value.getContent()); - } - return soy.esc.$$escapeHtmlHelper(value); -}; - - -/** - * Matches any/only HTML5 void elements' start tags. - * See http://www.w3.org/TR/html-markup/syntax.html#syntax-elements - * @type {RegExp} - * @private - */ -soy.$$HTML5_VOID_ELEMENTS_ = new RegExp( - '^<(?:area|base|br|col|command|embed|hr|img|input' + - '|keygen|link|meta|param|source|track|wbr)\\b'); - - -/** - * Removes HTML tags from a string of known safe HTML. - * If opt_tagWhitelist is not specified or is empty, then - * the result can be used as an attribute value. - * - * @param {*} value The HTML to be escaped. May not be a string, but the - * value will be coerced to a string. - * @param {Object<string, boolean>=} opt_tagWhitelist Has an own property whose - * name is a lower-case tag name and whose value is {@code 1} for - * each element that is allowed in the output. - * @return {string} A representation of value without disallowed tags, - * HTML comments, or other non-text content. - */ -soy.$$stripHtmlTags = function(value, opt_tagWhitelist) { - if (!opt_tagWhitelist) { - // If we have no white-list, then use a fast track which elides all tags. - return String(value).replace(soy.esc.$$HTML_TAG_REGEX_, '') - // This is just paranoia since callers should normalize the result - // anyway, but if they didn't, it would be necessary to ensure that - // after the first replace non-tag uses of < do not recombine into - // tags as in "<<foo>script>alert(1337)</<foo>script>". - .replace(soy.esc.$$LT_REGEX_, '<'); - } - - // Escapes '[' so that we can use [123] below to mark places where tags - // have been removed. - var html = String(value).replace(/\[/g, '['); - - // Consider all uses of '<' and replace whitelisted tags with markers like - // [1] which are indices into a list of approved tag names. - // Replace all other uses of < and > with entities. - var tags = []; - var attrs = []; - html = html.replace( - soy.esc.$$HTML_TAG_REGEX_, - function(tok, tagName) { - if (tagName) { - tagName = tagName.toLowerCase(); - if (opt_tagWhitelist.hasOwnProperty(tagName) && - opt_tagWhitelist[tagName]) { - var isClose = tok.charAt(1) == '/'; - var index = tags.length; - var start = '</'; - var attributes = ''; - if (!isClose) { - start = '<'; - var match; - while ((match = soy.esc.$$HTML_ATTRIBUTE_REGEX_.exec(tok))) { - if (match[1] && match[1].toLowerCase() == 'dir') { - var dir = match[2]; - if (dir) { - if (dir.charAt(0) == '\'' || dir.charAt(0) == '"') { - dir = dir.substr(1, dir.length - 2); - } - dir = dir.toLowerCase(); - if (dir == 'ltr' || dir == 'rtl' || dir == 'auto') { - attributes = ' dir="' + dir + '"'; - } - } - break; - } - } - soy.esc.$$HTML_ATTRIBUTE_REGEX_.lastIndex = 0; - } - tags[index] = start + tagName + '>'; - attrs[index] = attributes; - return '[' + index + ']'; - } - } - return ''; - }); - - // Escape HTML special characters. Now there are no '<' in html that could - // start a tag. - html = soy.esc.$$normalizeHtmlHelper(html); - - var finalCloseTags = soy.$$balanceTags_(tags); - - // Now html contains no tags or less-than characters that could become - // part of a tag via a replacement operation and tags only contains - // approved tags. - // Reinsert the white-listed tags. - html = html.replace(/\[(\d+)\]/g, function(_, index) { - if (attrs[index] && tags[index]) { - return tags[index].substr(0, tags[index].length - 1) + attrs[index] + '>'; - } - return tags[index]; - }); - - // Close any still open tags. - // This prevents unclosed formatting elements like <ol> and <table> from - // breaking the layout of containing HTML. - return html + finalCloseTags; -}; - - -/** - * Make sure that tag boundaries are not broken by Safe CSS when embedded in a - * {@code <style>} element. - * @param {string} css - * @return {string} - * @private - */ -soy.$$embedCssIntoHtml_ = function(css) { - // Port of a method of the same name in - // com.google.template.soy.shared.restricted.Sanitizers - return css.replace(/<\//g, '<\\/').replace(/\]\]>/g, ']]\\>'); -}; - - -/** - * Throw out any close tags that don't correspond to start tags. - * If {@code <table>} is used for formatting, embedded HTML shouldn't be able - * to use a mismatched {@code </table>} to break page layout. - * - * @param {Array<string>} tags Array of open/close tags (e.g. '<p>', '</p>') - * that will be modified in place to be either an open tag, one or more close - * tags concatenated, or the empty string. - * @return {string} zero or more closed tags that close all elements that are - * opened in tags but not closed. - * @private - */ -soy.$$balanceTags_ = function(tags) { - var open = []; - for (var i = 0, n = tags.length; i < n; ++i) { - var tag = tags[i]; - if (tag.charAt(1) == '/') { - var openTagIndex = goog.array.lastIndexOf(open, tag); - if (openTagIndex < 0) { - tags[i] = ''; // Drop close tag with no corresponding open tag. - } else { - tags[i] = open.slice(openTagIndex).reverse().join(''); - open.length = openTagIndex; - } - } else if (tag == '<li>' && - goog.array.lastIndexOf(open, '</ol>') < 0 && - goog.array.lastIndexOf(open, '</ul>') < 0) { - // Drop <li> if it isn't nested in a parent <ol> or <ul>. - tags[i] = ''; - } else if (!soy.$$HTML5_VOID_ELEMENTS_.test(tag)) { - open.push('</' + tag.substring(1)); - } - } - return open.reverse().join(''); -}; - - -/** - * Escapes HTML special characters in an HTML attribute value. - * - * @param {?} value The HTML to be escaped. May not be a string, but the - * value will be coerced to a string. - * @return {string} An escaped version of value. - */ -soy.$$escapeHtmlAttribute = function(value) { - // NOTE: We don't accept ATTRIBUTES here because ATTRIBUTES is actually not - // the attribute value context, but instead k/v pairs. - if (soydata.isContentKind_(value, goog.soy.data.SanitizedContentKind.HTML)) { - // NOTE: After removing tags, we also escape quotes ("normalize") so that - // the HTML can be embedded in attribute context. - goog.asserts.assert(value.constructor === goog.soy.data.SanitizedHtml); - return soy.esc.$$normalizeHtmlHelper( - soy.$$stripHtmlTags(value.getContent())); - } - return soy.esc.$$escapeHtmlHelper(value); -}; - - -/** - * Escapes HTML special characters in a string including space and other - * characters that can end an unquoted HTML attribute value. - * - * @param {?} value The HTML to be escaped. May not be a string, but the - * value will be coerced to a string. - * @return {string} An escaped version of value. - */ -soy.$$escapeHtmlAttributeNospace = function(value) { - if (soydata.isContentKind_(value, goog.soy.data.SanitizedContentKind.HTML)) { - goog.asserts.assert(value.constructor === goog.soy.data.SanitizedHtml); - return soy.esc.$$normalizeHtmlNospaceHelper( - soy.$$stripHtmlTags(value.getContent())); - } - return soy.esc.$$escapeHtmlNospaceHelper(value); -}; - - -/** - * Filters out strings that cannot be a substring of a valid HTML attribute. - * - * Note the input is expected to be key=value pairs. - * - * @param {?} value The value to escape. May not be a string, but the value - * will be coerced to a string. - * @return {string} A valid HTML attribute name part or name/value pair. - * {@code "zSoyz"} if the input is invalid. - */ -soy.$$filterHtmlAttributes = function(value) { - // NOTE: Explicitly no support for SanitizedContentKind.HTML, since that is - // meaningless in this context, which is generally *between* html attributes. - if (soydata.isContentKind_( - value, goog.soy.data.SanitizedContentKind.ATTRIBUTES)) { - goog.asserts.assert( - value.constructor === goog.soy.data.SanitizedHtmlAttribute); - // Add a space at the end to ensure this won't get merged into following - // attributes, unless the interpretation is unambiguous (ending with quotes - // or a space). - return value.getContent().replace(/([^"'\s])$/, '$1 '); - } - // TODO: Dynamically inserting attributes that aren't marked as trusted is - // probably unnecessary. Any filtering done here will either be inadequate - // for security or not flexible enough. Having clients use kind="attributes" - // in parameters seems like a wiser idea. - return soy.esc.$$filterHtmlAttributesHelper(value); -}; - - -/** - * Filters out strings that cannot be a substring of a valid HTML element name. - * - * @param {*} value The value to escape. May not be a string, but the value - * will be coerced to a string. - * @return {string} A valid HTML element name part. - * {@code "zSoyz"} if the input is invalid. - */ -soy.$$filterHtmlElementName = function(value) { - // NOTE: We don't accept any SanitizedContent here. HTML indicates valid - // PCDATA, not tag names. A sloppy developer shouldn't be able to cause an - // exploit: - // ... {let userInput}script src=http://evil.com/evil.js{/let} ... - // ... {param tagName kind="html"}{$userInput}{/param} ... - // ... <{$tagName}>Hello World</{$tagName}> - return soy.esc.$$filterHtmlElementNameHelper(value); -}; - - -/** - * Escapes characters in the value to make it valid content for a JS string - * literal. - * - * @param {*} value The value to escape. May not be a string, but the value - * will be coerced to a string. - * @return {string} An escaped version of value. - */ -soy.$$escapeJsString = function(value) { - return soy.esc.$$escapeJsStringHelper(value); -}; - - -/** - * Encodes a value as a JavaScript literal. - * - * @param {*} value The value to escape. May not be a string, but the value - * will be coerced to a string. - * @return {string} A JavaScript code representation of the input. - */ -soy.$$escapeJsValue = function(value) { - // We surround values with spaces so that they can't be interpolated into - // identifiers by accident. - // We could use parentheses but those might be interpreted as a function call. - if (value == null) { // Intentionally matches undefined. - // Java returns null from maps where there is no corresponding key while - // JS returns undefined. - // We always output null for compatibility with Java which does not have a - // distinct undefined value. - return ' null '; - } - if (soydata.isContentKind_(value, goog.soy.data.SanitizedContentKind.JS)) { - goog.asserts.assert(value.constructor === goog.soy.data.SanitizedJs); - return value.getContent(); - } - if (value instanceof goog.html.SafeScript) { - return goog.html.SafeScript.unwrap(value); - } - switch (typeof value) { - case 'boolean': case 'number': - return ' ' + value + ' '; - default: - return "'" + soy.esc.$$escapeJsStringHelper(String(value)) + "'"; - } -}; - - -/** - * Escapes characters in the string to make it valid content for a JS regular - * expression literal. - * - * @param {*} value The value to escape. May not be a string, but the value - * will be coerced to a string. - * @return {string} An escaped version of value. - */ -soy.$$escapeJsRegex = function(value) { - return soy.esc.$$escapeJsRegexHelper(value); -}; - - -/** - * Matches all URI mark characters that conflict with HTML attribute delimiters - * or that cannot appear in a CSS uri. - * From <a href="http://www.w3.org/TR/CSS2/grammar.html">G.2: CSS grammar</a> - * <pre> - * url ([!#$%&*-~]|{nonascii}|{escape})* - * </pre> - * - * @type {RegExp} - * @private - */ -soy.$$problematicUriMarks_ = /['()]/g; - -/** - * @param {string} ch A single character in {@link soy.$$problematicUriMarks_}. - * @return {string} - * @private - */ -soy.$$pctEncode_ = function(ch) { - return '%' + ch.charCodeAt(0).toString(16); -}; - -/** - * Escapes a string so that it can be safely included in a URI. - * - * @param {*} value The value to escape. May not be a string, but the value - * will be coerced to a string. - * @return {string} An escaped version of value. - */ -soy.$$escapeUri = function(value) { - // NOTE: We don't check for SanitizedUri or SafeUri, because just because - // something is already a valid complete URL doesn't mean we don't want to - // encode it as a component. For example, it would be bad if - // ?redirect={$url} didn't escape ampersands, because in that template, the - // continue URL should be treated as a single unit. - - // Apostophes and parentheses are not matched by encodeURIComponent. - // They are technically special in URIs, but only appear in the obsolete mark - // production in Appendix D.2 of RFC 3986, so can be encoded without changing - // semantics. - var encoded = soy.esc.$$escapeUriHelper(value); - soy.$$problematicUriMarks_.lastIndex = 0; - if (soy.$$problematicUriMarks_.test(encoded)) { - return encoded.replace(soy.$$problematicUriMarks_, soy.$$pctEncode_); - } - return encoded; -}; - - -/** - * Removes rough edges from a URI by escaping any raw HTML/JS string delimiters. - * - * @param {*} value The value to escape. May not be a string, but the value - * will be coerced to a string. - * @return {string} An escaped version of value. - */ -soy.$$normalizeUri = function(value) { - return soy.esc.$$normalizeUriHelper(value); -}; - - -/** - * Vets a URI's protocol and removes rough edges from a URI by escaping - * any raw HTML/JS string delimiters. - * - * @param {?} value The value to escape. May not be a string, but the value - * will be coerced to a string. - * @return {string} An escaped version of value. - */ -soy.$$filterNormalizeUri = function(value) { - if (soydata.isContentKind_(value, goog.soy.data.SanitizedContentKind.URI)) { - goog.asserts.assert(value.constructor === goog.soy.data.SanitizedUri); - return soy.$$normalizeUri(value); - } - if (soydata.isContentKind_(value, - goog.soy.data.SanitizedContentKind.TRUSTED_RESOURCE_URI)) { - goog.asserts.assert( - value.constructor === goog.soy.data.SanitizedTrustedResourceUri); - return soy.$$normalizeUri(value); - } - if (value instanceof goog.html.SafeUrl) { - return soy.$$normalizeUri(goog.html.SafeUrl.unwrap(value)); - } - if (value instanceof goog.html.TrustedResourceUrl) { - return soy.$$normalizeUri(goog.html.TrustedResourceUrl.unwrap(value)); - } - return soy.esc.$$filterNormalizeUriHelper(value); -}; - - -/** - * Vets a URI for usage as an image source. - * - * @param {?} value The value to filter. Might not be a string, but the value - * will be coerced to a string. - * @return {string} An escaped version of value. - */ -soy.$$filterNormalizeMediaUri = function(value) { - // Image URIs are filtered strictly more loosely than other types of URIs. - // TODO(shwetakarwa): Add tests for this in soyutils_test_helper while adding - // tests for filterTrustedResourceUri. - if (soydata.isContentKind_(value, goog.soy.data.SanitizedContentKind.URI)) { - goog.asserts.assert(value.constructor === goog.soy.data.SanitizedUri); - return soy.$$normalizeUri(value); - } - if (soydata.isContentKind_(value, - goog.soy.data.SanitizedContentKind.TRUSTED_RESOURCE_URI)) { - goog.asserts.assert( - value.constructor === goog.soy.data.SanitizedTrustedResourceUri); - return soy.$$normalizeUri(value); - } - if (value instanceof goog.html.SafeUrl) { - return soy.$$normalizeUri(goog.html.SafeUrl.unwrap(value)); - } - if (value instanceof goog.html.TrustedResourceUrl) { - return soy.$$normalizeUri(goog.html.TrustedResourceUrl.unwrap(value)); - } - return soy.esc.$$filterNormalizeMediaUriHelper(value); -}; - - -/** - * Vets a URI for usage as a resource. Makes sure the input value is a compile - * time constant or a TrustedResouce not in attacker's control. - * - * @param {?} value The value to filter. - * @return {string} The value content. - */ -soy.$$filterTrustedResourceUri = function(value) { - if (soydata.isContentKind_(value, - goog.soy.data.SanitizedContentKind.TRUSTED_RESOURCE_URI)) { - goog.asserts.assert( - value.constructor === goog.soy.data.SanitizedTrustedResourceUri); - return value.getContent(); - } - if (value instanceof goog.html.TrustedResourceUrl) { - return goog.html.TrustedResourceUrl.unwrap(value); - } - goog.asserts.fail('Bad value `%s` for |filterTrustedResourceUri', - [String(value)]); - return 'about:invalid#zSoyz'; -}; - - -/** - * For any resource string/variable which has - * |blessStringAsTrustedResuorceUrlForLegacy directive return the value as is. - * - * @param {*} value The value to be blessed. Might not be a string - * @return {*} value Return current value. - */ -soy.$$blessStringAsTrustedResourceUrlForLegacy = function(value) { - return value; -}; - - -/** - * Allows only data-protocol image URI's. - * - * @param {*} value The value to process. May not be a string, but the value - * will be coerced to a string. - * @return {!goog.soy.data.SanitizedUri} An escaped version of value. - */ -soy.$$filterImageDataUri = function(value) { - // NOTE: Even if it's a SanitizedUri, we will still filter it. - return soydata.VERY_UNSAFE.ordainSanitizedUri( - soy.esc.$$filterImageDataUriHelper(value)); -}; - - -/** - * Allows only tel URIs. - * - * @param {*} value The value to process. May not be a string, but the value - * will be coerced to a string. - * @return {!goog.soy.data.SanitizedUri} An escaped version of value. - */ -soy.$$filterTelUri = function(value) { - // NOTE: Even if it's a SanitizedUri, we will still filter it. - return soydata.VERY_UNSAFE.ordainSanitizedUri( - soy.esc.$$filterTelUriHelper(value)); -}; - - -/** - * Escapes a string so it can safely be included inside a quoted CSS string. - * - * @param {*} value The value to escape. May not be a string, but the value - * will be coerced to a string. - * @return {string} An escaped version of value. - */ -soy.$$escapeCssString = function(value) { - return soy.esc.$$escapeCssStringHelper(value); -}; - - -/** - * Encodes a value as a CSS identifier part, keyword, or quantity. - * - * @param {?} value The value to escape. May not be a string, but the value - * will be coerced to a string. - * @return {string} A safe CSS identifier part, keyword, or quanitity. - */ -soy.$$filterCssValue = function(value) { - if (soydata.isContentKind_(value, goog.soy.data.SanitizedContentKind.CSS)) { - goog.asserts.assertInstanceof(value, goog.soy.data.SanitizedCss); - return soy.$$embedCssIntoHtml_(value.getContent()); - } - // Uses == to intentionally match null and undefined for Java compatibility. - if (value == null) { - return ''; - } - if (value instanceof goog.html.SafeStyle) { - return soy.$$embedCssIntoHtml_(goog.html.SafeStyle.unwrap(value)); - } - // Note: SoyToJsSrcCompiler uses soy.$$filterCssValue both for the contents of - // <style> (list of rules) and for the contents of style="" (one set of - // declarations). We support SafeStyleSheet here to be used inside <style> but - // it also wrongly allows it inside style="". We should instead change - // SoyToJsSrcCompiler to use a different function inside <style>. - if (value instanceof goog.html.SafeStyleSheet) { - return soy.$$embedCssIntoHtml_(goog.html.SafeStyleSheet.unwrap(value)); - } - return soy.esc.$$filterCssValueHelper(value); -}; - - -/** - * Sanity-checks noAutoescape input for explicitly tainted content. - * - * SanitizedContentKind.TEXT is used to explicitly mark input that was never - * meant to be used unescaped. - * - * @param {?} value The value to filter. - * @return {*} The value, that we dearly hope will not cause an attack. - */ -soy.$$filterNoAutoescape = function(value) { - if (soydata.isContentKind_(value, goog.soy.data.SanitizedContentKind.TEXT)) { - // Fail in development mode. - goog.asserts.fail( - 'Tainted SanitizedContentKind.TEXT for |noAutoescape: `%s`', - [value.getContent()]); - // Return innocuous data in production. - return 'zSoyz'; - } - - return value; -}; - - -// ----------------------------------------------------------------------------- -// Basic directives/functions. - - -/** - * Converts \r\n, \r, and \n to <br>s - * @param {*} value The string in which to convert newlines. - * @return {string|!goog.soy.data.SanitizedHtml} A copy of {@code value} with - * converted newlines. If {@code value} is SanitizedHtml, the return value - * is also SanitizedHtml, of the same known directionality. - */ -soy.$$changeNewlineToBr = function(value) { - var result = goog.string.newLineToBr(String(value), false); - if (soydata.isContentKind_(value, goog.soy.data.SanitizedContentKind.HTML)) { - return soydata.VERY_UNSAFE.ordainSanitizedHtml( - result, soydata.getContentDir(value)); - } - return result; -}; - - -/** - * Inserts word breaks ('wbr' tags) into a HTML string at a given interval. The - * counter is reset if a space is encountered. Word breaks aren't inserted into - * HTML tags or entities. Entites count towards the character count; HTML tags - * do not. - * - * @param {*} value The HTML string to insert word breaks into. Can be other - * types, but the value will be coerced to a string. - * @param {number} maxCharsBetweenWordBreaks Maximum number of non-space - * characters to allow before adding a word break. - * @return {string|!goog.soy.data.SanitizedHtml} The string including word - * breaks. If {@code value} is SanitizedHtml, the return value - * is also SanitizedHtml, of the same known directionality. - * @deprecated The |insertWordBreaks directive is deprecated. - * Prefer wrapping with CSS white-space: break-word. - */ -soy.$$insertWordBreaks = function(value, maxCharsBetweenWordBreaks) { - var result = goog.format.insertWordBreaks( - String(value), maxCharsBetweenWordBreaks); - if (soydata.isContentKind_(value, goog.soy.data.SanitizedContentKind.HTML)) { - return soydata.VERY_UNSAFE.ordainSanitizedHtml( - result, soydata.getContentDir(value)); - } - return result; -}; - - -/** - * Truncates a string to a given max length (if it's currently longer), - * optionally adding ellipsis at the end. - * - * @param {*} str The string to truncate. Can be other types, but the value will - * be coerced to a string. - * @param {number} maxLen The maximum length of the string after truncation - * (including ellipsis, if applicable). - * @param {boolean} doAddEllipsis Whether to add ellipsis if the string needs - * truncation. - * @return {string} The string after truncation. - */ -soy.$$truncate = function(str, maxLen, doAddEllipsis) { - - str = String(str); - if (str.length <= maxLen) { - return str; // no need to truncate - } - - // If doAddEllipsis, either reduce maxLen to compensate, or else if maxLen is - // too small, just turn off doAddEllipsis. - if (doAddEllipsis) { - if (maxLen > 3) { - maxLen -= 3; - } else { - doAddEllipsis = false; - } - } - - // Make sure truncating at maxLen doesn't cut up a unicode surrogate pair. - if (soy.$$isHighSurrogate_(str.charCodeAt(maxLen - 1)) && - soy.$$isLowSurrogate_(str.charCodeAt(maxLen))) { - maxLen -= 1; - } - - // Truncate. - str = str.substring(0, maxLen); - - // Add ellipsis. - if (doAddEllipsis) { - str += '...'; - } - - return str; -}; - -/** - * Private helper for $$truncate() to check whether a char is a high surrogate. - * @param {number} cc The codepoint to check. - * @return {boolean} Whether the given codepoint is a unicode high surrogate. - * @private - */ -soy.$$isHighSurrogate_ = function(cc) { - return 0xD800 <= cc && cc <= 0xDBFF; -}; - -/** - * Private helper for $$truncate() to check whether a char is a low surrogate. - * @param {number} cc The codepoint to check. - * @return {boolean} Whether the given codepoint is a unicode low surrogate. - * @private - */ -soy.$$isLowSurrogate_ = function(cc) { - return 0xDC00 <= cc && cc <= 0xDFFF; -}; - - -// ----------------------------------------------------------------------------- -// Bidi directives/functions. - - -/** - * Cache of bidi formatter by context directionality, so we don't keep on - * creating new objects. - * @type {!Object<!goog.i18n.BidiFormatter>} - * @private - */ -soy.$$bidiFormatterCache_ = {}; - - -/** - * Returns cached bidi formatter for bidiGlobalDir, or creates a new one. - * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1 - * if rtl, 0 if unknown. - * @return {!goog.i18n.BidiFormatter} A formatter for bidiGlobalDir. - * @private - */ -soy.$$getBidiFormatterInstance_ = function(bidiGlobalDir) { - return soy.$$bidiFormatterCache_[bidiGlobalDir] || - (soy.$$bidiFormatterCache_[bidiGlobalDir] = - new goog.i18n.BidiFormatter(bidiGlobalDir)); -}; - - -/** - * Estimate the overall directionality of text. If opt_isHtml, makes sure to - * ignore the LTR nature of the mark-up and escapes in text, making the logic - * suitable for HTML and HTML-escaped text. - * If text has a goog.i18n.bidi.Dir-valued contentDir, this is used instead of - * estimating the directionality. - * - * @param {*} text The content whose directionality is to be estimated. - * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped. - * Default: false. - * @return {number} 1 if text is LTR, -1 if it is RTL, and 0 if it is neutral. - */ -soy.$$bidiTextDir = function(text, opt_isHtml) { - var contentDir = soydata.getContentDir(text); - if (contentDir != null) { - return contentDir; - } - var isHtml = opt_isHtml || - soydata.isContentKind_(text, goog.soy.data.SanitizedContentKind.HTML); - return goog.i18n.bidi.estimateDirection(text + '', isHtml); -}; - - -/** - * Returns 'dir="ltr"' or 'dir="rtl"', depending on text's estimated - * directionality, if it is not the same as bidiGlobalDir. - * Otherwise, returns the empty string. - * If opt_isHtml, makes sure to ignore the LTR nature of the mark-up and escapes - * in text, making the logic suitable for HTML and HTML-escaped text. - * If text has a goog.i18n.bidi.Dir-valued contentDir, this is used instead of - * estimating the directionality. - * - * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1 - * if rtl, 0 if unknown. - * @param {*} text The content whose directionality is to be estimated. - * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped. - * Default: false. - * @return {!goog.soy.data.SanitizedHtmlAttribute} 'dir="rtl"' for RTL text in - * non-RTL context; 'dir="ltr"' for LTR text in non-LTR context; - * else, the empty string. - */ -soy.$$bidiDirAttr = function(bidiGlobalDir, text, opt_isHtml) { - var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir); - var contentDir = soydata.getContentDir(text); - if (contentDir == null) { - var isHtml = opt_isHtml || - soydata.isContentKind_(text, goog.soy.data.SanitizedContentKind.HTML); - contentDir = goog.i18n.bidi.estimateDirection(text + '', isHtml); - } - return soydata.VERY_UNSAFE.ordainSanitizedHtmlAttribute( - formatter.knownDirAttr(contentDir)); -}; - - -/** - * Returns a Unicode BiDi mark matching bidiGlobalDir (LRM or RLM) if the - * directionality or the exit directionality of text are opposite to - * bidiGlobalDir. Otherwise returns the empty string. - * If opt_isHtml, makes sure to ignore the LTR nature of the mark-up and escapes - * in text, making the logic suitable for HTML and HTML-escaped text. - * If text has a goog.i18n.bidi.Dir-valued contentDir, this is used instead of - * estimating the directionality. - * - * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1 - * if rtl, 0 if unknown. - * @param {*} text The content whose directionality is to be estimated. - * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped. - * Default: false. - * @return {string} A Unicode bidi mark matching bidiGlobalDir, or the empty - * string when text's overall and exit directionalities both match - * bidiGlobalDir, or bidiGlobalDir is 0 (unknown). - */ -soy.$$bidiMarkAfter = function(bidiGlobalDir, text, opt_isHtml) { - var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir); - var isHtml = opt_isHtml || - soydata.isContentKind_(text, goog.soy.data.SanitizedContentKind.HTML); - return formatter.markAfterKnownDir(soydata.getContentDir(text), text + '', - isHtml); -}; - - -/** - * Returns text wrapped in a <span dir="ltr|rtl"> according to its - * directionality - but only if that is neither neutral nor the same as the - * global context. Otherwise, returns text unchanged. - * Always treats text as HTML/HTML-escaped, i.e. ignores mark-up and escapes - * when estimating text's directionality. - * If text has a goog.i18n.bidi.Dir-valued contentDir, this is used instead of - * estimating the directionality. - * - * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1 - * if rtl, 0 if unknown. - * @param {*} text The string to be wrapped. Can be other types, but the value - * will be coerced to a string. - * @return {!goog.soy.data.SanitizedContent|string} The wrapped text. - */ -soy.$$bidiSpanWrap = function(bidiGlobalDir, text) { - var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir); - - // We always treat the value as HTML, because span-wrapping is only useful - // when its output will be treated as HTML (without escaping), and because - // |bidiSpanWrap is not itself specified to do HTML escaping in Soy. (Both - // explicit and automatic HTML escaping, if any, is done before calling - // |bidiSpanWrap because the BidiSpanWrapDirective Java class implements - // SanitizedContentOperator, but this does not mean that the input has to be - // HTML SanitizedContent. In legacy usage, a string that is not - // SanitizedContent is often printed in an autoescape="false" template or by - // a print with a |noAutoescape, in which case our input is just SoyData.) If - // the output will be treated as HTML, the input had better be safe - // HTML/HTML-escaped (even if it isn't HTML SanitizedData), or we have an XSS - // opportunity and a much bigger problem than bidi garbling. - var html = goog.html.uncheckedconversions. - safeHtmlFromStringKnownToSatisfyTypeContract( - goog.string.Const.from( - 'Soy |bidiSpanWrap is applied on an autoescaped text.'), - String(text)); - var wrappedHtml = formatter.spanWrapSafeHtmlWithKnownDir( - soydata.getContentDir(text), html); - - // Like other directives whose Java class implements SanitizedContentOperator, - // |bidiSpanWrap is called after the escaping (if any) has already been done, - // and thus there is no need for it to produce actual SanitizedContent. - return goog.html.SafeHtml.unwrap(wrappedHtml); -}; - - -/** - * Returns text wrapped in Unicode BiDi formatting characters according to its - * directionality, i.e. either LRE or RLE at the beginning and PDF at the end - - * but only if text's directionality is neither neutral nor the same as the - * global context. Otherwise, returns text unchanged. - * Only treats SanitizedHtml as HTML/HTML-escaped, i.e. ignores mark-up - * and escapes when estimating text's directionality. - * If text has a goog.i18n.bidi.Dir-valued contentDir, this is used instead of - * estimating the directionality. - * - * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1 - * if rtl, 0 if unknown. - * @param {*} text The string to be wrapped. Can be other types, but the value - * will be coerced to a string. - * @return {!goog.soy.data.SanitizedContent|string} The wrapped string. - */ -soy.$$bidiUnicodeWrap = function(bidiGlobalDir, text) { - var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir); - - // We treat the value as HTML if and only if it says it's HTML, even though in - // legacy usage, we sometimes have an HTML string (not SanitizedContent) that - // is passed to an autoescape="false" template or a {print $foo|noAutoescape}, - // with the output going into an HTML context without escaping. We simply have - // no way of knowing if this is what is happening when we get - // non-SanitizedContent input, and most of the time it isn't. - var isHtml = - soydata.isContentKind_(text, goog.soy.data.SanitizedContentKind.HTML); - var wrappedText = formatter.unicodeWrapWithKnownDir( - soydata.getContentDir(text), text + '', isHtml); - - // Bidi-wrapping a value converts it to the context directionality. Since it - // does not cost us anything, we will indicate this known direction in the - // output SanitizedContent, even though the intended consumer of that - // information - a bidi wrapping directive - has already been run. - var wrappedTextDir = formatter.getContextDir(); - - // Unicode-wrapping UnsanitizedText gives UnsanitizedText. - // Unicode-wrapping safe HTML or JS string data gives valid, safe HTML or JS - // string data. - // ATTENTION: Do these need to be ...ForInternalBlocks()? - if (soydata.isContentKind_(text, goog.soy.data.SanitizedContentKind.TEXT)) { - return new goog.soy.data.UnsanitizedText(wrappedText, wrappedTextDir); - } - if (isHtml) { - return soydata.VERY_UNSAFE.ordainSanitizedHtml(wrappedText, wrappedTextDir); - } - - // Unicode-wrapping does not conform to the syntax of the other types of - // content. For lack of anything better to do, we we do not declare a content - // kind at all by falling through to the non-SanitizedContent case below. - // TODO(aharon): Consider throwing a runtime error on receipt of - // SanitizedContent other than TEXT, HTML, or JS_STR_CHARS. - - // The input was not SanitizedContent, so our output isn't SanitizedContent - // either. - return wrappedText; -}; - -// ----------------------------------------------------------------------------- -// Assertion methods used by runtime. - -/** - * Checks if the type assertion is true if goog.asserts.ENABLE_ASSERTS is - * true. Report errors on runtime types if goog.DEBUG is true. - * @param {boolean} condition The type check condition. - * @param {string} paramName The Soy name of the parameter. - * @param {?} param The JS object for the parameter. - * @param {!string} jsDocTypeStr SoyDoc type str. - * @return {?} the param value - * @throws {goog.asserts.AssertionError} When the condition evaluates to false. - */ -soy.asserts.assertType = function(condition, paramName, param, jsDocTypeStr) { - if (goog.asserts.ENABLE_ASSERTS && !condition) { - var msg = 'expected param ' + paramName + ' of type ' + jsDocTypeStr + - (goog.DEBUG ? (', but got ' + goog.debug.runtimeType(param)) : '') + - '.'; - goog.asserts.fail(msg); - } - return param; -}; - -// ----------------------------------------------------------------------------- -// Used for inspecting Soy template information from rendered pages. - -/** - * Whether we should generate additional HTML comments. - * @type {boolean} - */ -soy.$$debugSoyTemplateInfo = false; - -if (goog.DEBUG) { - /** - * Configures whether we should generate additional HTML comments for - * inspecting Soy template information from rendered pages. - * @param {boolean} debugSoyTemplateInfo - */ - soy.setDebugSoyTemplateInfo = function(debugSoyTemplateInfo) { - soy.$$debugSoyTemplateInfo = debugSoyTemplateInfo; - }; -} - -// ----------------------------------------------------------------------------- -// Generated code. - - -// START GENERATED CODE FOR ESCAPERS. - -/** - * @type {function (*) : string} - */ -soy.esc.$$escapeHtmlHelper = function(v) { - return goog.string.htmlEscape(String(v)); -}; - -/** - * @type {function (*) : string} - */ -soy.esc.$$escapeUriHelper = function(v) { - return goog.string.urlEncode(String(v)); -}; - -/** - * Maps characters to the escaped versions for the named escape directives. - * @private {!Object<string, string>} - */ -soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_ = { - '\x00': '\x26#0;', - '\x09': '\x26#9;', - '\x0a': '\x26#10;', - '\x0b': '\x26#11;', - '\x0c': '\x26#12;', - '\x0d': '\x26#13;', - ' ': '\x26#32;', - '\x22': '\x26quot;', - '\x26': '\x26amp;', - '\x27': '\x26#39;', - '-': '\x26#45;', - '\/': '\x26#47;', - '\x3c': '\x26lt;', - '\x3d': '\x26#61;', - '\x3e': '\x26gt;', - '`': '\x26#96;', - '\x85': '\x26#133;', - '\xa0': '\x26#160;', - '\u2028': '\x26#8232;', - '\u2029': '\x26#8233;' -}; - -/** - * A function that can be used with String.replace. - * @param {string} ch A single character matched by a compatible matcher. - * @return {string} A token in the output language. - * @private - */ -soy.esc.$$REPLACER_FOR_NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_ = function(ch) { - return soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_[ch]; -}; - -/** - * Maps characters to the escaped versions for the named escape directives. - * @private {!Object<string, string>} - */ -soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_ = { - '\x00': '\\x00', - '\x08': '\\x08', - '\x09': '\\t', - '\x0a': '\\n', - '\x0b': '\\x0b', - '\x0c': '\\f', - '\x0d': '\\r', - '\x22': '\\x22', - '$': '\\x24', - '\x26': '\\x26', - '\x27': '\\x27', - '(': '\\x28', - ')': '\\x29', - '*': '\\x2a', - '+': '\\x2b', - ',': '\\x2c', - '-': '\\x2d', - '.': '\\x2e', - '\/': '\\\/', - ':': '\\x3a', - '\x3c': '\\x3c', - '\x3d': '\\x3d', - '\x3e': '\\x3e', - '?': '\\x3f', - '\x5b': '\\x5b', - '\\': '\\\\', - '\x5d': '\\x5d', - '^': '\\x5e', - '\x7b': '\\x7b', - '|': '\\x7c', - '\x7d': '\\x7d', - '\x85': '\\x85', - '\u2028': '\\u2028', - '\u2029': '\\u2029' -}; - -/** - * A function that can be used with String.replace. - * @param {string} ch A single character matched by a compatible matcher. - * @return {string} A token in the output language. - * @private - */ -soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_ = function(ch) { - return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_[ch]; -}; - -/** - * Maps characters to the escaped versions for the named escape directives. - * @private {!Object<string, string>} - */ -soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_CSS_STRING_ = { - '\x00': '\\0 ', - '\x08': '\\8 ', - '\x09': '\\9 ', - '\x0a': '\\a ', - '\x0b': '\\b ', - '\x0c': '\\c ', - '\x0d': '\\d ', - '\x22': '\\22 ', - '\x26': '\\26 ', - '\x27': '\\27 ', - '(': '\\28 ', - ')': '\\29 ', - '*': '\\2a ', - '\/': '\\2f ', - ':': '\\3a ', - ';': '\\3b ', - '\x3c': '\\3c ', - '\x3d': '\\3d ', - '\x3e': '\\3e ', - '@': '\\40 ', - '\\': '\\5c ', - '\x7b': '\\7b ', - '\x7d': '\\7d ', - '\x85': '\\85 ', - '\xa0': '\\a0 ', - '\u2028': '\\2028 ', - '\u2029': '\\2029 ' -}; - -/** - * A function that can be used with String.replace. - * @param {string} ch A single character matched by a compatible matcher. - * @return {string} A token in the output language. - * @private - */ -soy.esc.$$REPLACER_FOR_ESCAPE_CSS_STRING_ = function(ch) { - return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_CSS_STRING_[ch]; -}; - -/** - * Maps characters to the escaped versions for the named escape directives. - * @private {!Object<string, string>} - */ -soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI__AND__FILTER_NORMALIZE_MEDIA_URI_ = { - '\x00': '%00', - '\x01': '%01', - '\x02': '%02', - '\x03': '%03', - '\x04': '%04', - '\x05': '%05', - '\x06': '%06', - '\x07': '%07', - '\x08': '%08', - '\x09': '%09', - '\x0a': '%0A', - '\x0b': '%0B', - '\x0c': '%0C', - '\x0d': '%0D', - '\x0e': '%0E', - '\x0f': '%0F', - '\x10': '%10', - '\x11': '%11', - '\x12': '%12', - '\x13': '%13', - '\x14': '%14', - '\x15': '%15', - '\x16': '%16', - '\x17': '%17', - '\x18': '%18', - '\x19': '%19', - '\x1a': '%1A', - '\x1b': '%1B', - '\x1c': '%1C', - '\x1d': '%1D', - '\x1e': '%1E', - '\x1f': '%1F', - ' ': '%20', - '\x22': '%22', - '\x27': '%27', - '(': '%28', - ')': '%29', - '\x3c': '%3C', - '\x3e': '%3E', - '\\': '%5C', - '\x7b': '%7B', - '\x7d': '%7D', - '\x7f': '%7F', - '\x85': '%C2%85', - '\xa0': '%C2%A0', - '\u2028': '%E2%80%A8', - '\u2029': '%E2%80%A9', - '\uff01': '%EF%BC%81', - '\uff03': '%EF%BC%83', - '\uff04': '%EF%BC%84', - '\uff06': '%EF%BC%86', - '\uff07': '%EF%BC%87', - '\uff08': '%EF%BC%88', - '\uff09': '%EF%BC%89', - '\uff0a': '%EF%BC%8A', - '\uff0b': '%EF%BC%8B', - '\uff0c': '%EF%BC%8C', - '\uff0f': '%EF%BC%8F', - '\uff1a': '%EF%BC%9A', - '\uff1b': '%EF%BC%9B', - '\uff1d': '%EF%BC%9D', - '\uff1f': '%EF%BC%9F', - '\uff20': '%EF%BC%A0', - '\uff3b': '%EF%BC%BB', - '\uff3d': '%EF%BC%BD' -}; - -/** - * A function that can be used with String.replace. - * @param {string} ch A single character matched by a compatible matcher. - * @return {string} A token in the output language. - * @private - */ -soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI__AND__FILTER_NORMALIZE_MEDIA_URI_ = function(ch) { - return soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI__AND__FILTER_NORMALIZE_MEDIA_URI_[ch]; -}; - -/** - * Matches characters that need to be escaped for the named directives. - * @private {!RegExp} - */ -soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_ = /[\x00\x22\x27\x3c\x3e]/g; - -/** - * Matches characters that need to be escaped for the named directives. - * @private {!RegExp} - */ -soy.esc.$$MATCHER_FOR_ESCAPE_HTML_NOSPACE_ = /[\x00\x09-\x0d \x22\x26\x27\x2d\/\x3c-\x3e`\x85\xa0\u2028\u2029]/g; - -/** - * Matches characters that need to be escaped for the named directives. - * @private {!RegExp} - */ -soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_NOSPACE_ = /[\x00\x09-\x0d \x22\x27\x2d\/\x3c-\x3e`\x85\xa0\u2028\u2029]/g; - -/** - * Matches characters that need to be escaped for the named directives. - * @private {!RegExp} - */ -soy.esc.$$MATCHER_FOR_ESCAPE_JS_STRING_ = /[\x00\x08-\x0d\x22\x26\x27\/\x3c-\x3e\x5b-\x5d\x7b\x7d\x85\u2028\u2029]/g; - -/** - * Matches characters that need to be escaped for the named directives. - * @private {!RegExp} - */ -soy.esc.$$MATCHER_FOR_ESCAPE_JS_REGEX_ = /[\x00\x08-\x0d\x22\x24\x26-\/\x3a\x3c-\x3f\x5b-\x5e\x7b-\x7d\x85\u2028\u2029]/g; - -/** - * Matches characters that need to be escaped for the named directives. - * @private {!RegExp} - */ -soy.esc.$$MATCHER_FOR_ESCAPE_CSS_STRING_ = /[\x00\x08-\x0d\x22\x26-\x2a\/\x3a-\x3e@\\\x7b\x7d\x85\xa0\u2028\u2029]/g; - -/** - * Matches characters that need to be escaped for the named directives. - * @private {!RegExp} - */ -soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI__AND__FILTER_NORMALIZE_MEDIA_URI_ = /[\x00- \x22\x27-\x29\x3c\x3e\\\x7b\x7d\x7f\x85\xa0\u2028\u2029\uff01\uff03\uff04\uff06-\uff0c\uff0f\uff1a\uff1b\uff1d\uff1f\uff20\uff3b\uff3d]/g; - -/** - * A pattern that vets values produced by the named directives. - * @private {!RegExp} - */ -soy.esc.$$FILTER_FOR_FILTER_CSS_VALUE_ = /^(?!-*(?:expression|(?:moz-)?binding))(?!\s+)(?:[.#]?-?(?:[_a-z0-9-]+)(?:-[_a-z0-9-]+)*-?|(?:rgb|hsl)a?\([0-9.%,\u0020]+\)|-?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[a-z]{1,2}|%)?|!important|\s+)*$/i; - -/** - * A pattern that vets values produced by the named directives. - * @private {!RegExp} - */ -soy.esc.$$FILTER_FOR_FILTER_NORMALIZE_URI_ = /^(?![^#?]*\/(?:\.|%2E){2}(?:[\/?#]|$))(?:(?:https?|mailto):|[^&:\/?#]*(?:[\/?#]|$))/i; - -/** - * A pattern that vets values produced by the named directives. - * @private {!RegExp} - */ -soy.esc.$$FILTER_FOR_FILTER_NORMALIZE_MEDIA_URI_ = /^[^&:\/?#]*(?:[\/?#]|$)|^https?:|^data:image\/[a-z0-9+]+;base64,[a-z0-9+\/]+=*$|^blob:/i; - -/** - * A pattern that vets values produced by the named directives. - * @private {!RegExp} - */ -soy.esc.$$FILTER_FOR_FILTER_IMAGE_DATA_URI_ = /^data:image\/(?:bmp|gif|jpe?g|png|tiff|webp);base64,[a-z0-9+\/]+=*$/i; - -/** - * A pattern that vets values produced by the named directives. - * @private {!RegExp} - */ -soy.esc.$$FILTER_FOR_FILTER_TEL_URI_ = /^tel:[0-9a-z;=\-+._!~*'\u0020\/():&$#?@,]+$/i; - -/** - * A pattern that vets values produced by the named directives. - * @private {!RegExp} - */ -soy.esc.$$FILTER_FOR_FILTER_HTML_ATTRIBUTES_ = /^(?!on|src|(?:style|action|archive|background|cite|classid|codebase|data|dsync|href|longdesc|usemap)\s*$)(?:[a-z0-9_$:-]*)$/i; - -/** - * A pattern that vets values produced by the named directives. - * @private {!RegExp} - */ -soy.esc.$$FILTER_FOR_FILTER_HTML_ELEMENT_NAME_ = /^(?!script|style|title|textarea|xmp|no)[a-z0-9_$:-]*$/i; - -/** - * A helper for the Soy directive |normalizeHtml - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$normalizeHtmlHelper = function(value) { - var str = String(value); - return str.replace( - soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_, - soy.esc.$$REPLACER_FOR_NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_); -}; - -/** - * A helper for the Soy directive |escapeHtmlNospace - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$escapeHtmlNospaceHelper = function(value) { - var str = String(value); - return str.replace( - soy.esc.$$MATCHER_FOR_ESCAPE_HTML_NOSPACE_, - soy.esc.$$REPLACER_FOR_NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_); -}; - -/** - * A helper for the Soy directive |normalizeHtmlNospace - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$normalizeHtmlNospaceHelper = function(value) { - var str = String(value); - return str.replace( - soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_NOSPACE_, - soy.esc.$$REPLACER_FOR_NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_); -}; - -/** - * A helper for the Soy directive |escapeJsString - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$escapeJsStringHelper = function(value) { - var str = String(value); - return str.replace( - soy.esc.$$MATCHER_FOR_ESCAPE_JS_STRING_, - soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_); -}; - -/** - * A helper for the Soy directive |escapeJsRegex - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$escapeJsRegexHelper = function(value) { - var str = String(value); - return str.replace( - soy.esc.$$MATCHER_FOR_ESCAPE_JS_REGEX_, - soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_); -}; - -/** - * A helper for the Soy directive |escapeCssString - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$escapeCssStringHelper = function(value) { - var str = String(value); - return str.replace( - soy.esc.$$MATCHER_FOR_ESCAPE_CSS_STRING_, - soy.esc.$$REPLACER_FOR_ESCAPE_CSS_STRING_); -}; - -/** - * A helper for the Soy directive |filterCssValue - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$filterCssValueHelper = function(value) { - var str = String(value); - if (!soy.esc.$$FILTER_FOR_FILTER_CSS_VALUE_.test(str)) { - goog.asserts.fail('Bad value `%s` for |filterCssValue', [str]); - return 'zSoyz'; - } - return str; -}; - -/** - * A helper for the Soy directive |normalizeUri - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$normalizeUriHelper = function(value) { - var str = String(value); - return str.replace( - soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI__AND__FILTER_NORMALIZE_MEDIA_URI_, - soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI__AND__FILTER_NORMALIZE_MEDIA_URI_); -}; - -/** - * A helper for the Soy directive |filterNormalizeUri - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$filterNormalizeUriHelper = function(value) { - var str = String(value); - if (!soy.esc.$$FILTER_FOR_FILTER_NORMALIZE_URI_.test(str)) { - goog.asserts.fail('Bad value `%s` for |filterNormalizeUri', [str]); - return 'about:invalid#zSoyz'; - } - return str.replace( - soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI__AND__FILTER_NORMALIZE_MEDIA_URI_, - soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI__AND__FILTER_NORMALIZE_MEDIA_URI_); -}; - -/** - * A helper for the Soy directive |filterNormalizeMediaUri - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$filterNormalizeMediaUriHelper = function(value) { - var str = String(value); - if (!soy.esc.$$FILTER_FOR_FILTER_NORMALIZE_MEDIA_URI_.test(str)) { - goog.asserts.fail('Bad value `%s` for |filterNormalizeMediaUri', [str]); - return 'about:invalid#zSoyz'; - } - return str.replace( - soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI__AND__FILTER_NORMALIZE_MEDIA_URI_, - soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI__AND__FILTER_NORMALIZE_MEDIA_URI_); -}; - -/** - * A helper for the Soy directive |filterImageDataUri - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$filterImageDataUriHelper = function(value) { - var str = String(value); - if (!soy.esc.$$FILTER_FOR_FILTER_IMAGE_DATA_URI_.test(str)) { - goog.asserts.fail('Bad value `%s` for |filterImageDataUri', [str]); - return 'data:image/gif;base64,zSoyz'; - } - return str; -}; - -/** - * A helper for the Soy directive |filterTelUri - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$filterTelUriHelper = function(value) { - var str = String(value); - if (!soy.esc.$$FILTER_FOR_FILTER_TEL_URI_.test(str)) { - goog.asserts.fail('Bad value `%s` for |filterTelUri', [str]); - return 'about:invalid#zSoyz'; - } - return str; -}; - -/** - * A helper for the Soy directive |filterHtmlAttributes - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$filterHtmlAttributesHelper = function(value) { - var str = String(value); - if (!soy.esc.$$FILTER_FOR_FILTER_HTML_ATTRIBUTES_.test(str)) { - goog.asserts.fail('Bad value `%s` for |filterHtmlAttributes', [str]); - return 'zSoyz'; - } - return str; -}; - -/** - * A helper for the Soy directive |filterHtmlElementName - * @param {*} value Can be of any type but will be coerced to a string. - * @return {string} The escaped text. - */ -soy.esc.$$filterHtmlElementNameHelper = function(value) { - var str = String(value); - if (!soy.esc.$$FILTER_FOR_FILTER_HTML_ELEMENT_NAME_.test(str)) { - goog.asserts.fail('Bad value `%s` for |filterHtmlElementName', [str]); - return 'zSoyz'; - } - return str; -}; - -/** - * Matches all tags, HTML comments, and DOCTYPEs in tag soup HTML. - * By removing these, and replacing any '<' or '>' characters with - * entities we guarantee that the result can be embedded into a - * an attribute without introducing a tag boundary. - * - * @private {!RegExp} - */ -soy.esc.$$HTML_TAG_REGEX_ = /<(?:!|\/?([a-zA-Z][a-zA-Z0-9:\-]*))(?:[^>'"]|"[^"]*"|'[^']*')*>/g; - -/** - * Matches all occurrences of '<'. - * - * @private {!RegExp} - */ -soy.esc.$$LT_REGEX_ = /</g; - -/** - * Maps lower-case names of innocuous tags to true. - * - * @private {!Object<string, boolean>} - */ -soy.esc.$$SAFE_TAG_WHITELIST_ = {'b': true, 'br': true, 'em': true, 'i': true, 's': true, 'sub': true, 'sup': true, 'u': true}; - -/** - * Pattern for matching attribute name and value, where value is single-quoted - * or double-quoted. - * See http://www.w3.org/TR/2011/WD-html5-20110525/syntax.html#attributes-0 - * - * @private {!RegExp} - */ -soy.esc.$$HTML_ATTRIBUTE_REGEX_ = /([a-zA-Z][a-zA-Z0-9:\-]*)[\t\n\r\u0020]*=[\t\n\r\u0020]*("[^"]*"|'[^']*')/g; - -// END GENERATED CODE
diff --git a/third_party/ink/wireserializer.js b/third_party/ink/wireserializer.js deleted file mode 100644 index b88dcedf..0000000 --- a/third_party/ink/wireserializer.js +++ /dev/null
@@ -1,845 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -/** - * @fileoverview Protocol Buffer 2 Serializer which serializes and deserializes - * messages using the wire format. Note that this serializer requires protocol - * buffer reflection, which carries some overhead. - * @supported any browser with DataView implemented. For now Chrome9, FF15, IE10 - * - * @see https://developers.google.com/protocol-buffers/docs/encoding - * - * TODO(feinberg): Replace goog.math.Long with mutable long representation that - * permits in-place arithmetic to avoid allocations. - */ - - -goog.provide('net.proto2.contrib.WireSerializer'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.math.Long'); -goog.require('goog.proto2.Message'); -goog.require('goog.proto2.Serializer'); - - - -/** - * Wire format serializer. - * - * @constructor - * @extends {goog.proto2.Serializer} - */ -net.proto2.contrib.WireSerializer = function() { - /** - * This array is where proto bytes go during serialization. - * It must be reset for each serialization. - * @type {!Array.<number>} - * @private - */ - this.buffer_ = []; - - /** - * Scratch workspace to avoid allocations during serialization. - * @type {{value: number, length: number}} - * @private - */ - this.scratchTag32_ = {value: 0, length: 0}; - - /** - * Scratch workspace to avoid allocations during serialization. - * @type {{value: !goog.math.Long, length: number}} - * @private - */ - this.scratchTag64_ = {value: goog.math.Long.getZero(), length: 0}; - - /** - * Scratch data view for coding/decoding little-endian numbers. - * @type {!DataView} - * @private - */ - this.dataView_ = new DataView(new ArrayBuffer(8)); -}; -goog.inherits(net.proto2.contrib.WireSerializer, goog.proto2.Serializer); - - -/** - * @return {!Array.<number>} The serialized form of the message. - * @override - */ -net.proto2.contrib.WireSerializer.prototype.serialize = function(message) { - if (message == null) { - return []; - } - - this.buffer_ = []; - - var descriptor = message.getDescriptor(); - var fields = descriptor.getFields(); - - // Add the known fields. - for (var i = 0; i < fields.length; i++) { - var field = fields[i]; - - if (!message.has(field)) { - continue; - } - - if (field.isRepeated()) { - if (field.isPacked()) { - this.serializePackedField_(message, field); - } else { - for (var j = 0, n = message.countOf(field); j < n; j++) { - var val = message.get(field, j); - this.getSerializedValue(field, val); - } - } - } else { - this.getSerializedValue(field, message.get(field)); - } - } - - return this.buffer_; -}; - - -/** - * Append the serialized packed field to our serialization buffer. - * @param {!goog.proto2.Message} message The message containing the field - * to serialize. - * @param {!goog.proto2.FieldDescriptor} field The field to serialize. - * @return {boolean} Whether the field tag was serialized. - * @private - */ -net.proto2.contrib.WireSerializer.prototype.serializePackedField_ = - function(message, field) { - var buf = this.buffer_; - - var wireType = 2; // Per definition. - - // Tag. - this.serializeVarint_((field.getTag() << 3) | wireType); - - // Make note of the current buffer size. After serializing the repeated - // fields, splice the size header at the current position. - var savedBufferSize = buf.length; - for (var j = 0, n = message.countOf(field); j < n; j++) { - var val = message.get(field, j); - this.getSerializedValue(field, val, true /* omit tag */); - } - var serializedData = buf.splice( - savedBufferSize, buf.length - savedBufferSize); - this.serializeVarint_(serializedData.length); - - var args = [buf.length, 0].concat(serializedData); - buf.splice.apply(buf, args); - - return true; -}; - - -/** - * Append the serialized field tag to our serialization buffer. - * @param {goog.proto2.FieldDescriptor} field The field to serialize. - * @return {boolean} Whether the field tag was serialized. - * @private - */ -net.proto2.contrib.WireSerializer.prototype.serializeFieldTag_ = - function(field) { - var wireType = 0; - switch (field.getFieldType()) { - default: - return false; - case goog.proto2.Message.FieldType.SINT32: - case goog.proto2.Message.FieldType.SINT64: - case goog.proto2.Message.FieldType.BOOL: - case goog.proto2.Message.FieldType.INT64: - case goog.proto2.Message.FieldType.ENUM: - case goog.proto2.Message.FieldType.INT32: - case goog.proto2.Message.FieldType.UINT32: - case goog.proto2.Message.FieldType.UINT64: - wireType = 0; - break; - case goog.proto2.Message.FieldType.FIXED64: - case goog.proto2.Message.FieldType.SFIXED64: - case goog.proto2.Message.FieldType.DOUBLE: - wireType = 1; - break; - case goog.proto2.Message.FieldType.STRING: - case goog.proto2.Message.FieldType.BYTES: - case goog.proto2.Message.FieldType.MESSAGE: - wireType = 2; - break; - case goog.proto2.Message.FieldType.GROUP: - wireType = 3; - break; - case goog.proto2.Message.FieldType.FIXED32: - case goog.proto2.Message.FieldType.SFIXED32: - case goog.proto2.Message.FieldType.FLOAT: - wireType = 5; - break; - } - this.serializeVarint_((field.getTag() << 3) | wireType); - return true; -}; - - -/** - * Returns the serialized form of the given value for the given field if the - * field is a Message or Group and returns the value unchanged otherwise, except - * for Infinity, -Infinity and NaN numerical values which are converted to - * string representation. - * - * @param {goog.proto2.FieldDescriptor} field The field from which this - * value came. - * @param {*} value The value of the field. - * @param {boolean=} opt_omitTag If present and true, do not serialize a field - * tag. - * - * @return {*} The value. - * @protected - */ -net.proto2.contrib.WireSerializer.prototype.getSerializedValue = - function(field, value, opt_omitTag) { - if (!opt_omitTag) { - if (!this.serializeFieldTag_(field)) { - return false; - } - } - - switch (field.getFieldType()) { - default: - throw new Error('Unknown field type ' + field.getFieldType()); - case goog.proto2.Message.FieldType.SINT32: - this.serializeVarint_(this.zigZagEncode(/** @type {number} */ (value))); - break; - case goog.proto2.Message.FieldType.SINT64: - this.serializeVarint64_(this.zigZagEncode64_( - goog.math.Long.fromString(/** @type {string} */(value)))); - break; - case goog.proto2.Message.FieldType.BOOL: - this.serializeVarint_(value ? 1 : 0); - break; - case goog.proto2.Message.FieldType.INT32: - var numericValue = /** @type {number} */ (value); - if (numericValue > 0) { - this.serializeVarint_(numericValue); - } else { - // Negative 32 bit quantities are always 10 bytes long. - this.serializeVarint64_(goog.math.Long.fromInt(numericValue)); - } - break; - case goog.proto2.Message.FieldType.INT64: - case goog.proto2.Message.FieldType.UINT64: - this.serializeVarint64_( - goog.math.Long.fromString(/** @type {string} */(value))); - break; - case goog.proto2.Message.FieldType.ENUM: - case goog.proto2.Message.FieldType.UINT32: - this.serializeVarint_(/** @type {number} */ (value)); - break; - case goog.proto2.Message.FieldType.FIXED64: - case goog.proto2.Message.FieldType.SFIXED64: - this.serializeFixed_( - goog.math.Long.fromString(/** @type {string} */ (value)), 8); - break; - case goog.proto2.Message.FieldType.DOUBLE: - this.serializeDouble_(/** @type {number} */ (value)); - break; - case goog.proto2.Message.FieldType.STRING: - this.serializeString(value); - break; - case goog.proto2.Message.FieldType.BYTES: - this.serializeBytes(value); - break; - case goog.proto2.Message.FieldType.GROUP: - var serialized = new net.proto2.contrib.WireSerializer().serialize( - /** @type {goog.proto2.Message} */ (value)); - goog.array.extend(this.buffer_, serialized); - this.serializeVarint_((field.getTag() << 3) | 4); - break; - case goog.proto2.Message.FieldType.MESSAGE: - var serialized = new net.proto2.contrib.WireSerializer().serialize( - /** @type {goog.proto2.Message} */ (value)); - this.serializeVarint_(serialized.length); - goog.array.extend(this.buffer_, serialized); - break; - case goog.proto2.Message.FieldType.FIXED32: - this.serializeFixed_( - goog.math.Long.fromNumber(/** @type {number} */ (value)), 4); - break; - case goog.proto2.Message.FieldType.SFIXED32: - this.serializeFixed_( - goog.math.Long.fromInt(/** @type {number} */ (value)), 4); - break; - case goog.proto2.Message.FieldType.FLOAT: - this.serializeFloat_(/** @type {number} */ (value)); - break; - } - // To avoid allocations, this method serializes into a pre-existing buffer, - // rather than serializing into a new value object. - return null; -}; - - -/** @override */ -net.proto2.contrib.WireSerializer.prototype.deserializeTo = - function(message, buffer) { - if (buffer == null) { - // Since value double-equals null, it may be either null or undefined. - // Ensure we return the same one, since they have different meanings. - return buffer; - } - - if (buffer instanceof ArrayBuffer) { - buffer = new Uint8Array(buffer); - } - - var descriptor = message.getDescriptor(); - var offset = 0; - var size = buffer.length; - var view = function() { - return buffer.subarray(offset); - }; - // Because subarray is broken on ie10, we can't simply advance our view of the - // buffer. Instead, we keep track of an offset. - while (offset < buffer.length) { - var tag = this.parseUnsignedVarInt_(view()); - var tagValue = tag.value; - var tagLength = tag.length; - var index = tagValue >> 3; - var wireType = tagValue & 0x7; // Last 3 bits. - - // Advance. - offset += tagLength; - - var field = descriptor.findFieldByTag(index); - if (!field) { - // Unknown field; skip it. - offset += this.lengthForWireType_(wireType, view()); - continue; - } else if (field.isPacked()) { // Packed repeated. - // Read byte length. - var v = this.parseUnsignedVarInt_(view()); - var remaining = v.value; - offset += v.length; - while (remaining > 0 && offset < buffer.length) { - var packedValue = - this.getDeserializedValue(field, view()); - if (!packedValue) { - throw new Error('Expected ' + field.getFieldType()); - } - message.add(field, packedValue.value); - offset += packedValue.length; - remaining -= packedValue.length; - } - } else { - var value = this.getDeserializedValue(field, view()); - if (!value) { - throw new Error('Expected ' + field.getFieldType()); - } - offset += value.length; - if (field.isRepeated()) { - message.add(field, value.value); - } else { - message.set(field, value.value); - } - } - } -}; - - -/** - * @param {number} wireType - * @param {*} buffer The data of the message. - * @return {number} Default length to use for a given fieldType. - * @private - */ -net.proto2.contrib.WireSerializer.prototype.lengthForWireType_ = function( - wireType, buffer) { - var length = 0; - switch (wireType) { - case 0: // int32, int64, uint32, uint64, sint32, sint64, bool, enum. - length = this.parseVarInt64_(buffer).length; - break; - case 1: // fixed64, sfixed64, double. - length = 8; - break; - case 2: // Length-delimited: string, bytes, messages, repeated fields. - var bufferLength = this.parseVarInt64_(buffer); - length = bufferLength.length + bufferLength.value.toInt(); - break; - case 3: // "Start group". Not supported. - case 4: // "End group". Not supported. - goog.asserts.fail('Error deserializing group'); - break; - case 5: // fixed32, sfixed32, float. - length = 4; - break; - } - return length; -}; - - -/** - * Deserializes a message from the expected format and places the - * data in the message. The message must correspond to a group. Moreover - * the buffer must be positioned after the initial START_GROUP tag for the - * group. The message will be terminated by the first END_GROUP tag at the - * same nesting level. It is the responsibility of the caller to validate that - * its field index matches the one in the opening START_GROUP tag. Since groups - * are not length-delimited, this method returns the length of the parsed - * data excluding the END_GROUP tag. - * - * @param {goog.proto2.Message} message The message in which to - * place the information. - * @param {*} buffer The data of the message. - * @return {number} the length of the parsed message, excluding the closing tag. - * @protected - */ - net.proto2.contrib.WireSerializer.prototype.deserializeGroupTo = - function(message, buffer) { - var descriptor = message.getDescriptor(); - var parsedLength = 0; - - while (true) { - var tag = this.parseUnsignedVarInt_(buffer); - var tagValue = tag.value; - var tagLength = tag.length; - var index = tagValue >> 3; - var wiretype = tagValue & 7; - if (wiretype == 4) { - // Got an end group. - break; - } - parsedLength += tagLength; - var value = {value: undefined, length: 0}; - var field = descriptor.findFieldByTag(index); - if (field) { - value = this.getDeserializedValue(field, buffer.subarray(tagLength)); - if (value && value.value !== null) { - if (field.isRepeated()) { - message.add(field, value.value); - } else { - message.set(field, value.value); - } - } - } - parsedLength += value.length; - if (buffer.length < tagLength + value.length) { - break; - } - buffer = buffer.subarray(tagLength + value.length); - } - return parsedLength; -}; - - -/** - * @override - */ -net.proto2.contrib.WireSerializer.prototype.getDeserializedValue = - function(field, buffer) { - var value = null; - var t = field.getFieldType(); - var varInt = this.parseVarInt64_(buffer); - var length = varInt.length; - switch (t) { - case goog.proto2.Message.FieldType.SINT32: - value = this.zigZagDecode_(varInt.value.toInt()); - break; - case goog.proto2.Message.FieldType.SINT64: - value = this.zigZagDecode64_(varInt.value).toString(); - break; - case goog.proto2.Message.FieldType.BOOL: - value = varInt.value.equals(goog.math.Long.getOne()); - break; - case goog.proto2.Message.FieldType.INT64: - case goog.proto2.Message.FieldType.UINT64: - value = varInt.value.toString(); - break; - case goog.proto2.Message.FieldType.INT32: - value = varInt.value.toInt(); - break; - case goog.proto2.Message.FieldType.ENUM: - case goog.proto2.Message.FieldType.UINT32: - value = varInt.value.getLowBitsUnsigned(); - break; - case goog.proto2.Message.FieldType.FIXED64: - case goog.proto2.Message.FieldType.SFIXED64: - value = this.parseFixed64_(buffer.subarray(0, 8)).toString(); - length = 8; - break; - case goog.proto2.Message.FieldType.DOUBLE: - value = this.parseDouble_(buffer.subarray(0, 8)); - length = 8; - break; - case goog.proto2.Message.FieldType.STRING: - var strBuffer = - buffer.subarray(varInt.length, varInt.length + varInt.value.toInt()); - value = this.arrayBufferToUtf8String_(strBuffer); - length = varInt.length + varInt.value.toInt(); - break; - case goog.proto2.Message.FieldType.BYTES: - var strBuffer = - buffer.subarray(varInt.length, varInt.length + varInt.value.toInt()); - // Store the bytes using a String. - value = this.arrayBufferToString_(strBuffer); - length = varInt.length + varInt.value.toInt(); - break; - case goog.proto2.Message.FieldType.GROUP: - value = field.getFieldMessageType().createMessageInstance(); - var groupLength = this.deserializeGroupTo(value, buffer); - var next = buffer.subarray(groupLength); - var closingTag = this.parseVarInt64_(next); - var expected = (field.getTag() << 3) | 4; - goog.asserts.assert(closingTag.value.toInt() == expected, - 'Error deserializing group'); - length = groupLength + closingTag.length; - break; - case goog.proto2.Message.FieldType.MESSAGE: - length = varInt.length + varInt.value.toInt(); - var data = buffer.subarray(varInt.length, length); - value = field.getFieldMessageType().createMessageInstance(); - this.deserializeTo(value, data); - break; - case goog.proto2.Message.FieldType.FIXED32: - case goog.proto2.Message.FieldType.SFIXED32: - value = this.parseFixed32_( - buffer.subarray(0, 4), t == goog.proto2.Message.FieldType.SFIXED32); - length = 4; - break; - case goog.proto2.Message.FieldType.FLOAT: - value = this.parseFloat_(buffer.subarray(0, 4)); - length = 4; - break; - } - return {value: value, length: length}; -}; - - -/** - * @param {*} value Binary string that needs to be converted to bytes. - */ -net.proto2.contrib.WireSerializer.prototype.serializeBytes = function(value) { - if (goog.isDefAndNotNull(value)) { - var valueStr = /** @type {string} */ (value); - // Serialize the number of bytes, per spec of the wire format. - this.serializeVarint_(valueStr.length); - for (var i = 0; i < valueStr.length; i++) { - this.buffer_.push(valueStr.charCodeAt(i)); - } - } -}; - - -/** - * @param {*} value String (possibly utf-8) that needs to be converted to bytes. - */ -net.proto2.contrib.WireSerializer.prototype.serializeString = function(value) { - if (goog.isDefAndNotNull(value)) { - var valueStr = /** @type {string} */ (value); - // Inspired by: - // http://ecmanaut.blogspot.com/2006/07/encoding-decoding-utf8-in-javascript.html - var utf8 = unescape(encodeURIComponent(valueStr)); - // Serialize the length of the encoded string: what we want is the number - // of bytes, not the number of characters, per spec of the wire format. - this.serializeVarint_(utf8.length); - for (var i = 0; i < utf8.length; i++) { - this.buffer_.push(utf8.charCodeAt(i)); - } - } -}; - - -/** - * @param {*} buffer to parse as String. - * @return {{value: string, length: number}} - */ -net.proto2.contrib.WireSerializer.prototype.parseString = function(buffer) { - var length = this.parseUnsignedVarInt_(buffer); - var strBuffer = buffer.subarray(length.length, length.length + length.value); - return { - value: this.arrayBufferToUtf8String_(strBuffer), - length: length.length + length.value - }; -}; - - -/** - * @param {number} number signed number that needs to be converted to unsigned. - * @return {number} - */ -net.proto2.contrib.WireSerializer.prototype.zigZagEncode = - function(number) { - var sign = number >>> 31; - return (number << 1) ^ -sign; -}; - - -/** - * @param {number} number Unsigned number in zigzag format that needs - to be converted to signed. - * @return {number} signed. - * @private - */ -net.proto2.contrib.WireSerializer.prototype.zigZagDecode_ = - function(number) { - return (number >>> 1) ^ -(number & 1); -}; - - -/** - * @param {!goog.math.Long} number signed number that needs to be converted to - * unsigned. - * @return {!goog.math.Long} - * @private - */ -net.proto2.contrib.WireSerializer.prototype.zigZagEncode64_ = - function(number) { - var sign = number.shiftRightUnsigned(63); - return number.shiftLeft(1).xor(sign.negate()); -}; - - -/** - * @param {!goog.math.Long} number Unsigned number in zigzag format that needs - to be converted to signed. - * @return {!goog.math.Long} - * @private - */ -net.proto2.contrib.WireSerializer.prototype.zigZagDecode64_ = - function(number) { - return number.shiftRightUnsigned(1).xor( - number.and(goog.math.Long.getOne()).negate()); -}; - - -/** - * Serialize the given number as a varint into our buffer. - * @param {number} number that needs to be converted to varint. - * @private - */ -net.proto2.contrib.WireSerializer.prototype.serializeVarint_ = - function(number) { - do { - var chunk = number & 0x7F; - number = number >>> 7; - if (number > 0) { - chunk = chunk | 0x80; - } - this.buffer_.push(chunk); - } while (number > 0); -}; - - -/** - * Serialize the given 64-bit number as a varint into our buffer. - * @param {!goog.math.Long} number that needs to be encoded as varint. - * @private - */ -net.proto2.contrib.WireSerializer.prototype.serializeVarint64_ = - function(number) { - var mask = goog.math.Long.fromInt(0x7F); - do { - var chunk = number.and(mask).toInt(); - number = number.shiftRightUnsigned(7); - if (number.greaterThan(goog.math.Long.getZero())) { - chunk = chunk | 0x80; - } - this.buffer_.push(chunk); - } while (number.greaterThan(goog.math.Long.getZero())); -}; - - -/** - * @param {*} buffer from which field number and type needs to be extracted. - * @return {{value: !goog.math.Long, length: number}} - * @private - */ -net.proto2.contrib.WireSerializer.prototype.parseVarInt64_ = function(buffer) { - var valueInfo = this.scratchTag64_; - var number = goog.math.Long.fromNumber(0); - var i = 0; - for (; i < buffer.length; i++) { - var bits = goog.math.Long.fromInt(buffer[i] & 0x7F).shiftLeft(i * 7); - number = number.or(bits); - if ((buffer[i] & 0x80) == 0) { - break; - } - } - valueInfo.value = number; - valueInfo.length = i + 1; - return valueInfo; -}; - - -/** - * A special case parser for unsigned 32-bit varints, which can fit comfortably - * in 32 bits during decoding. - * @param {*} buffer from which field number and type needs to be extracted. - * @return {{value: number, length: number}} - * @private - */ -net.proto2.contrib.WireSerializer.prototype.parseUnsignedVarInt_ = - function(buffer) { - var valueInfo = this.scratchTag32_; - var result = 0; - var i = 0; - for (; i < buffer.length; i++) { - result = result | ((buffer[i] & 0x7F) << (i * 7)); - if ((buffer[i] & 0x80) == 0) { - break; - } - } - valueInfo.value = result; - valueInfo.length = i + 1; - return valueInfo; -}; - - -/** - * @param {goog.math.Long} number that needs to be converted to little endian - * order. - * @param {number} size of the result array (4 = 32bit, 8 = 64bit). - * @private - */ -net.proto2.contrib.WireSerializer.prototype.serializeFixed_ = - function(number, size) { - var mask = goog.math.Long.fromInt(0xFF); - for (var i = 0; i < size; i++) { - var chunk = number.and(mask).toInt(); - this.buffer_.push(chunk); - number = number.shiftRightUnsigned(8); - } -}; - - -/** - * @param {*} buffer from which the fixed32 value needs to be extracted. - * @param {boolean} signed if the fixed32 value represents a signed value - * (i.e. sfixed32). - * @return {number} - * @private - */ -net.proto2.contrib.WireSerializer.prototype.parseFixed32_ = function( - buffer, signed) { - var number = 0; - for (var i = 0; i < buffer.length; i++) { - number = number | (buffer[i] << (i * 8)); - } - if (!signed) { - // The bitwise operations above treat numbers as signed int32 values. - // Correct for this in the unsigned case by using >>> to coerce to unsigned. - number = number >>> 0; - } - return number; -}; - - -/** - * @param {*} buffer from which the fixed64 value needs to be extracted. - * @return {!goog.math.Long} - * @private - */ -net.proto2.contrib.WireSerializer.prototype.parseFixed64_ = function(buffer) { - // Javascript numbers are only accurate up to 51 bits as they are stored as - // 64-bit floating points. We store the result in a goog.math.Long object to - // preserve full precision. - return new goog.math.Long( - this.parseFixed32_(buffer.subarray(0, 4), true), - this.parseFixed32_(buffer.subarray(4, 8), true)); -}; - - -/** - * @param {*} buffer from which double needs to be extracted. - * @return {number} - * @private - */ -net.proto2.contrib.WireSerializer.prototype.parseDouble_ = function(buffer) { - for (var i = 0; i < 8; i++) { - this.dataView_.setUint8(i, buffer[i]); - } - return this.dataView_.getFloat64(0, true); // little-endian -}; - - -/** - * @param {*} buffer from which float needs to be extracted. - * @return {number} - * @private - */ -net.proto2.contrib.WireSerializer.prototype.parseFloat_ = function(buffer) { - for (var i = 0; i < 4; i++) { - this.dataView_.setUint8(i, buffer[i]); - } - return this.dataView_.getFloat32(0, true); // little-endian -}; - - -/** - * @param {number} number to be serialized to 8 bytes. - * @private - */ -net.proto2.contrib.WireSerializer.prototype.serializeDouble_ = - function(number) { - this.dataView_.setFloat64(0, number, true); // little-endian - for (var i = 0; i < 8; i++) { - this.buffer_.push(this.dataView_.getUint8(i)); - } -}; - - -/** - * @param {number} number to be serialized to 4 bytes. - * @private - */ -net.proto2.contrib.WireSerializer.prototype.serializeFloat_ = function(number) { - this.dataView_.setFloat32(0, number, true); // little-endian - for (var i = 0; i < 4; i++) { - this.buffer_.push(this.dataView_.getUint8(i)); - } -}; - - -/** - * This method converts an ArrayBuffer into a string (with utf8 encoding). - * - * @param {ArrayBuffer} buffer The buffer to convert to a string - * @return {string} - * @private - */ -net.proto2.contrib.WireSerializer.prototype.arrayBufferToUtf8String_ = function( - buffer) { - var str = this.arrayBufferToString_(buffer); - // Inspired by: - // http://ecmanaut.blogspot.com/2006/07/encoding-decoding-utf8-in-javascript.html - return decodeURIComponent(escape(str)); -}; - - -/** - * This method converts an ArrayBuffer into a string (each index is 1 byte). - * - * The maximum stack size in chrome is ~125k. This means that using - * String.fromCharCode.apply will fail for strings larger than the maximum stack - * size. This method breaks up the calls to fromCharCode into ~64k chunks to - * work around this limitation. - * - * @param {ArrayBuffer} buffer The buffer to convert to a string - * @return {string} - * @private - */ -net.proto2.contrib.WireSerializer.prototype.arrayBufferToString_ = function( - buffer) { - var CHUNK_SIZE = 65536; - var str = ''; - var view = new Uint16Array(buffer); - for (var offset = 0; offset < view.length; offset += CHUNK_SIZE) { - var len = Math.min(CHUNK_SIZE, view.length - offset); - var subview = view.subarray(offset, offset + len); - str += String.fromCharCode.apply(null, subview); - } - return str; -};
diff --git a/tools/binary_size/trybot_commit_size_checker.py b/tools/binary_size/trybot_commit_size_checker.py index 51895ce..f023a1b 100755 --- a/tools/binary_size/trybot_commit_size_checker.py +++ b/tools/binary_size/trybot_commit_size_checker.py
@@ -65,8 +65,8 @@ @property def explanation(self): - ret = '{}: expected max: {} {}, got {} {}'.format( - self.name, self.expected, self.units, self.actual, self.units) + ret = '{}: {} {} (max is {} {})'.format( + self.name, self.actual, self.units, self.expected, self.units) if self.details and not self.IsAllowable(): ret += '\n' + self.details return ret @@ -244,10 +244,11 @@ checks_text += _FAILURE_GUIDANCE status_code = 1 if failing_deltas and not is_roller else 0 - summary = """ -Normalized apk size delta: {} -Dex method count delta: {}\ -""".format(resource_sizes_delta.actual, dex_delta.actual) + summary = '<br>'.join([ + '', + 'Normalized apk size delta: {}'.format(resource_sizes_delta.actual), + 'Dex method count delta: {}'.format(dex_delta.actual), + ]) # TODO(agrieve): Remove once recipe is updated: details, normalized_apk_size results_json = { @@ -266,14 +267,14 @@ 'lines': resource_sizes_lines, }, { - 'name': '>>> SuperSize Text Diff <<<', - 'lines': supersize_diff_lines, - }, - { 'name': '>>> Dex Method Diff <<<', 'lines': dex_delta_lines, }, { + 'name': '>>> SuperSize Text Diff <<<', + 'lines': supersize_diff_lines, + }, + { 'name': '>>> Supersize HTML Diff <<<', 'url': _HTML_REPORT_BASE_URL + '{{' + _NDJSON_FILENAME + '}}', },
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b936e9d0..75851ae 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -1465,6 +1465,10 @@ <int value="1" label="Enter Background"/> <int value="2" label="Clear All"/> <int value="3" label="Initialize"/> + <int value="4" label="Sign In"/> + <int value="5" label="Sign Out"/> + <int value="6" label="History Deleted"/> + <int value="7" label="Cached Data Cleared"/> </enum> <enum name="AppListAppMovingType"> @@ -17585,6 +17589,7 @@ <int value="1303" label="AUTOTESTPRIVATE_CLOSEAPP"/> <int value="1304" label="ACCESSIBILITY_PRIVATE_SETSWITCHACCESSMENUSTATE"/> <int value="1305" label="AUTOTESTPRIVATE_SENDASSISTANTTEXTQUERY"/> + <int value="1306" label="AUTOTESTPRIVATE_SETCROSTINIAPPSCALED"/> </enum> <enum name="ExtensionIconState">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 06ba72c4..c1bf82249 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -2923,6 +2923,16 @@ </summary> </histogram> +<histogram name="AndroidSms.PWAUninstallationResult" enum="BooleanSuccess"> + <owner>azeemarshad@chromium.org</owner> + <owner>hansberry@chromium.org</owner> + <summary> + Records success/failure for when Android Messages for Web PWA is + uninstalled. The PWA is uninstalled when the messages URL changes, resulting + in the PWA being uninstalled at the old URL and reinstalled at the new URL. + </summary> +</histogram> + <histogram name="AndroidSms.ServiceWorkerLifetime" units="ms"> <owner>azeemarshad@chromium.org</owner> <summary> @@ -16443,6 +16453,18 @@ </summary> </histogram> +<histogram name="ContentSuggestions.Feed.AppLifecycle.NumRowsForDeletion" + enum="AppLifecycleEvent" expires_after="2019-10-01"> + <owner>skym@chromium.org</owner> + <owner>pnoland@chromium.org</owner> + <summary> + Android: number of rows present in a history deletion that's causing all + current suggestions to be deleted. Each row should correspond to a url that + is beign removed from history. Is not emitted when entire history is being + cleared. + </summary> +</histogram> + <histogram name="ContentSuggestions.Feed.AppLifecycleEvents" enum="AppLifecycleEvent" expires_after="2019-10-01"> <obsolete> @@ -27274,6 +27296,9 @@ <histogram name="Event.CompositorThreadEventQueue.CoalescedCount" units="events"> + <obsolete> + Deprecated 01/2019 due to lack of usage. + </obsolete> <owner>eirage@chromium.org</owner> <summary> Number of continuous gesture events (GestureScrollUpdate, @@ -27287,6 +27312,9 @@ <histogram name="Event.CompositorThreadEventQueue.Continuous.HeadQueueingTime" units="microseconds"> + <obsolete> + Deprecated 01/2019 due to lack of usage. + </obsolete> <owner>eirage@chromium.org</owner> <summary> Time between the first event in a coalesced continuous gesture events group @@ -27305,6 +27333,9 @@ <histogram name="Event.CompositorThreadEventQueue.Continuous.TailQueueingTime" units="microseconds"> + <obsolete> + Deprecated 01/2019 due to lack of usage. + </obsolete> <owner>eirage@chromium.org</owner> <summary> Time between the last event in a coalesced continuous gesture events group @@ -27323,6 +27354,9 @@ <histogram name="Event.CompositorThreadEventQueue.NonContinuous.QueueingTime" units="microseconds"> + <obsolete> + Deprecated 01/2019 due to lack of usage. + </obsolete> <owner>eirage@chromium.org</owner> <summary> Time between when a non-continuous gesture event (GestureScrollStart/End, @@ -69620,6 +69654,18 @@ </summary> </histogram> +<histogram name="NewTabPage.TimeToFirstDraw" units="ms"> + <owner>skym@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The time from when a new tab page is created until the first pre-draw call + on the main UI containing the search provider logo (if available), fake + search box, most visited tiles, etc. More specifically, this is the time + between NewTabPage's constructor and the first pre-draw pass on + NewTabPageLayout. + </summary> +</histogram> + <histogram name="NewTabPage.URLState" enum="NewTabURLState"> <owner>treib@chromium.org</owner> <summary> @@ -93498,27 +93544,27 @@ </summary> </histogram> -<histogram name="SafeBrowsing.FontSize.Default" units="pts" expires_after="M73"> +<histogram name="SafeBrowsing.FontSize.Default" units="pts" expires_after="M77"> <owner>drubery@chromium.org</owner> <owner>nparker@chromium.org</owner> <summary>Records the default font size on user startup.</summary> </histogram> <histogram name="SafeBrowsing.FontSize.DefaultFixed" units="pts" - expires_after="M73"> + expires_after="M77"> <owner>drubery@chromium.org</owner> <owner>nparker@chromium.org</owner> <summary>Records the default fixed font size on user startup.</summary> </histogram> -<histogram name="SafeBrowsing.FontSize.Minimum" units="pts" expires_after="M73"> +<histogram name="SafeBrowsing.FontSize.Minimum" units="pts" expires_after="M77"> <owner>drubery@chromium.org</owner> <owner>nparker@chromium.org</owner> <summary>Records the minimum font size on user startup.</summary> </histogram> <histogram name="SafeBrowsing.FontSize.MinimumLogical" units="pts" - expires_after="M73"> + expires_after="M77"> <owner>drubery@chromium.org</owner> <owner>nparker@chromium.org</owner> <summary>Records the minimum logical font size on user startup.</summary> @@ -94363,6 +94409,9 @@ </histogram> <histogram name="SafeBrowsing.V4UnusedStoreFileExists.V3" enum="BooleanExists"> + <obsolete> + Removed in M73. See https://crbug.com/916192 + </obsolete> <owner>vakh@chromium.org</owner> <summary> Track the presence of Safe Browsing list files used for PVer3, which has @@ -139329,6 +139378,9 @@ </histogram_suffixes> <histogram_suffixes name="SafeBrowsing.V4Store.V3.Metrics" separator="."> + <obsolete> + Removed in M73. See https://crbug.com/916192 + </obsolete> <suffix name="Bloom"/> <suffix name="BloomPrefixSet"/> <suffix name="CsdWhitelist"/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index d254e9e..94e0b3b 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -4034,6 +4034,18 @@ Set to 1 when a user is shown a lite page in page load. </summary> </metric> + <metric name="lite_page_redirect"> + <summary> + Set to 1 when a user is shown a lite page redirect in page load. + </summary> + </metric> + <metric name="navigation_restart_penalty"> + <summary> + Set to the number of milliseconds spent restarting navigations when a Lite + Page Redirect preview is attempted, whether or not it is committed, during + the page load. + </summary> + </metric> <metric name="noscript"> <summary> Set to 1 when a user is shown a NoScript preview on a page load.
diff --git a/tools/web_dev_style/js_checker.py b/tools/web_dev_style/js_checker.py index 117979ea..263867f 100644 --- a/tools/web_dev_style/js_checker.py +++ b/tools/web_dev_style/js_checker.py
@@ -59,17 +59,6 @@ """ os_path = self.input_api.os_path - try: - # Import ESLint. - _HERE_PATH = os_path.dirname(os_path.realpath(__file__)) - _SRC_PATH = os_path.normpath(os_path.join(_HERE_PATH, '..', '..')) - import sys - old_sys_path = sys.path[:] - sys.path.append(os_path.join(_SRC_PATH, 'third_party', 'node')) - import node, node_modules - finally: - sys.path = old_sys_path - # Extract paths to be passed to ESLint. affected_js_files_paths = [] presubmit_path = self.input_api.PresubmitLocalPath() @@ -77,12 +66,11 @@ affected_js_files_paths.append( os_path.relpath(f.AbsoluteLocalPath(), presubmit_path)) - output = node.RunNode([ - node_modules.PathToEsLint(), - '--color', - '--format', format, - '--ignore-pattern \'!.eslintrc.js\'', - ' '.join(affected_js_files_paths)]) + args = ['--color', '--format', format, '--ignore-pattern \'!.eslintrc.js\''] + args += affected_js_files_paths + + import eslint + output = eslint.Run(os_path=os_path, args=args) return [self.output_api.PresubmitError(output)] if output else []
diff --git a/ui/base/emoji/emoji_panel_helper_chromeos.cc b/ui/base/emoji/emoji_panel_helper_chromeos.cc index 84ec409..09ee96f4 100644 --- a/ui/base/emoji/emoji_panel_helper_chromeos.cc +++ b/ui/base/emoji/emoji_panel_helper_chromeos.cc
@@ -4,10 +4,8 @@ #include "ui/base/emoji/emoji_panel_helper.h" -#include "base/feature_list.h" #include "base/logging.h" #include "base/no_destructor.h" -#include "ui/base/ui_base_features.h" namespace ui { @@ -21,7 +19,7 @@ } // namespace bool IsEmojiPanelSupported() { - return base::FeatureList::IsEnabled(features::kEnableEmojiContextMenu); + return true; } void ShowEmojiPanel() {
diff --git a/ui/base/emoji/emoji_panel_helper_mac.mm b/ui/base/emoji/emoji_panel_helper_mac.mm index d322ea5..b743154 100644 --- a/ui/base/emoji/emoji_panel_helper_mac.mm +++ b/ui/base/emoji/emoji_panel_helper_mac.mm
@@ -7,12 +7,11 @@ #import <Cocoa/Cocoa.h> #include "base/feature_list.h" -#include "ui/base/ui_base_features.h" namespace ui { bool IsEmojiPanelSupported() { - return base::FeatureList::IsEnabled(features::kEnableEmojiContextMenu); + return true; } void ShowEmojiPanel() {
diff --git a/ui/base/emoji/emoji_panel_helper_win.cc b/ui/base/emoji/emoji_panel_helper_win.cc index 23124db1..a4b1eca7 100644 --- a/ui/base/emoji/emoji_panel_helper_win.cc +++ b/ui/base/emoji/emoji_panel_helper_win.cc
@@ -6,18 +6,15 @@ #include <windows.h> -#include "base/feature_list.h" #include "base/win/windows_version.h" -#include "ui/base/ui_base_features.h" #include "ui/events/keycodes/keyboard_code_conversion_win.h" namespace ui { bool IsEmojiPanelSupported() { - return base::FeatureList::IsEnabled(features::kEnableEmojiContextMenu) && - // Emoji picker is supported on Windows 10's Spring 2018 Update and - // above. - base::win::GetVersion() >= base::win::Version::VERSION_WIN10_RS4; + // Emoji picker is supported on Windows 10's Spring 2018 Update and + // above. + return base::win::GetVersion() >= base::win::Version::VERSION_WIN10_RS4; } void ShowEmojiPanel() {
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index 4d083be..500df822 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -17,16 +17,6 @@ const base::Feature kCalculateNativeWinOcclusion{ "CalculateNativeWinOcclusion", base::FEATURE_DISABLED_BY_DEFAULT}; #endif // OW_WIN -// If enabled, the emoji picker context menu item may be shown for editable -// text areas. -const base::Feature kEnableEmojiContextMenu { - "EnableEmojiContextMenu", -#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_CHROMEOS) - base::FEATURE_ENABLED_BY_DEFAULT -#else - base::FEATURE_DISABLED_BY_DEFAULT -#endif -}; // Enables the full screen handwriting virtual keyboard behavior. const base::Feature kEnableFullscreenHandwritingVirtualKeyboard = { @@ -159,7 +149,8 @@ } bool IsSingleProcessMash() { - return base::FeatureList::IsEnabled(features::kSingleProcessMash); + return base::FeatureList::IsEnabled(features::kSingleProcessMash) && + !base::FeatureList::IsEnabled(features::kMash); } bool IsAutomaticUiAdjustmentsForTouchEnabled() {
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index 0da6ef6d..f78fd18 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -13,7 +13,6 @@ namespace features { // Keep sorted! -UI_BASE_EXPORT extern const base::Feature kEnableEmojiContextMenu; UI_BASE_EXPORT extern const base::Feature kEnableFullscreenHandwritingVirtualKeyboard; UI_BASE_EXPORT extern const base::Feature kEnableStylusVirtualKeyboard; @@ -61,6 +60,8 @@ // make it the default kMash behavior. UI_BASE_EXPORT extern const base::Feature kMashOopViz; +// NOTE: Do not access directly outside of tests. Use IsSingleProcessMash() +// to avoid problems when Mash and SingleProcessMash are both enabled. UI_BASE_EXPORT extern const base::Feature kSingleProcessMash; // Returns true if Chrome's aura usage is backed by the WindowService.
diff --git a/ui/chromeos/search_box/search_box_constants.h b/ui/chromeos/search_box/search_box_constants.h index 462d491..544029d 100644 --- a/ui/chromeos/search_box/search_box_constants.h +++ b/ui/chromeos/search_box/search_box_constants.h
@@ -24,6 +24,9 @@ // The background border corner radius of the search box. SEARCH_BOX_EXPORT constexpr int kSearchBoxBorderCornerRadius = 24; +// The background border corner radius of the expanded search box. +SEARCH_BOX_EXPORT constexpr int kSearchBoxBorderCornerRadiusSearchResult = 20; + // Preferred height of search box. SEARCH_BOX_EXPORT constexpr int kSearchBoxPreferredHeight = 48;
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc index 97f093d..72fdfaf8 100644 --- a/ui/events/blink/input_handler_proxy.cc +++ b/ui/events/blink/input_handler_proxy.cc
@@ -43,8 +43,6 @@ const int32_t kEventDispositionUndefined = -1; -const size_t kTenSeconds = 10 * 1000 * 1000; - cc::ScrollState CreateScrollStateForGesture(const WebGestureEvent& event) { cc::ScrollStateData scroll_state_data; switch (event.GetType()) { @@ -253,32 +251,6 @@ void InputHandlerProxy::DispatchSingleInputEvent( std::unique_ptr<EventWithCallback> event_with_callback, const base::TimeTicks now) { - if (IsGestureScrollOrPinch(event_with_callback->event().GetType())) { - // Report the coalesced count only for continuous events to avoid the noise - // from non-continuous events. - if (IsContinuousGestureEvent(event_with_callback->event().GetType())) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Event.CompositorThreadEventQueue.Continuous.HeadQueueingTime", - (now - event_with_callback->creation_timestamp()).InMicroseconds(), 1, - kTenSeconds, 50); - - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Event.CompositorThreadEventQueue.Continuous.TailQueueingTime", - (now - event_with_callback->last_coalesced_timestamp()) - .InMicroseconds(), - 1, kTenSeconds, 50); - - UMA_HISTOGRAM_COUNTS_1000( - "Event.CompositorThreadEventQueue.CoalescedCount", - static_cast<int>(event_with_callback->coalesced_count())); - } else { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Event.CompositorThreadEventQueue.NonContinuous.QueueingTime", - (now - event_with_callback->creation_timestamp()).InMicroseconds(), 1, - kTenSeconds, 50); - } - } - ui::LatencyInfo monitored_latency_info = event_with_callback->latency_info(); std::unique_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor = input_handler_->CreateLatencyInfoSwapPromiseMonitor(
diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc index 7fb5408..2c81c8a 100644 --- a/ui/events/blink/input_handler_proxy_unittest.cc +++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -49,15 +49,6 @@ namespace { -const char* kCoalescedCountHistogram = - "Event.CompositorThreadEventQueue.CoalescedCount"; -const char* kContinuousHeadQueueingTimeHistogram = - "Event.CompositorThreadEventQueue.Continuous.HeadQueueingTime"; -const char* kContinuousTailQueueingTimeHistogram = - "Event.CompositorThreadEventQueue.Continuous.TailQueueingTime"; -const char* kNonContinuousQueueingTimeHistogram = - "Event.CompositorThreadEventQueue.NonContinuous.QueueingTime"; - enum InputHandlerProxyTestType { ROOT_SCROLL_NORMAL_HANDLER, ROOT_SCROLL_SYNCHRONOUS_HANDLER, @@ -1406,8 +1397,6 @@ } TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedGestureScroll) { - base::HistogramTester histogram_tester; - // Handle scroll on compositor. cc::InputHandlerScrollResult scroll_result_did_scroll_; scroll_result_did_scroll_.did_scroll = true; @@ -1465,12 +1454,9 @@ EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[2]); EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[3]); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); - histogram_tester.ExpectUniqueSample(kCoalescedCountHistogram, 2, 1); } TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedGestureScrollPinchScroll) { - base::HistogramTester histogram_tester; - // Handle scroll on compositor. cc::InputHandlerScrollResult scroll_result_did_scroll_; scroll_result_did_scroll_.did_scroll = true; @@ -1530,12 +1516,9 @@ EXPECT_EQ(0ul, event_queue().size()); EXPECT_EQ(12ul, event_disposition_recorder_.size()); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); - histogram_tester.ExpectBucketCount(kCoalescedCountHistogram, 1, 2); - histogram_tester.ExpectBucketCount(kCoalescedCountHistogram, 2, 2); } TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedQueueingTime) { - base::HistogramTester histogram_tester; base::SimpleTestTickClock tick_clock; tick_clock.SetNowTicks(base::TimeTicks::Now()); SetInputHandlerProxyTickClockForTesting(&tick_clock); @@ -1569,13 +1552,6 @@ EXPECT_EQ(0ul, event_queue().size()); EXPECT_EQ(5ul, event_disposition_recorder_.size()); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); - histogram_tester.ExpectUniqueSample(kContinuousHeadQueueingTimeHistogram, 140, - 1); - histogram_tester.ExpectUniqueSample(kContinuousTailQueueingTimeHistogram, 80, - 1); - histogram_tester.ExpectBucketCount(kNonContinuousQueueingTimeHistogram, 0, 1); - histogram_tester.ExpectBucketCount(kNonContinuousQueueingTimeHistogram, 70, - 1); } TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedCoalesceScrollAndPinch) {
diff --git a/ui/gfx/geometry/vector3d_f.cc b/ui/gfx/geometry/vector3d_f.cc index 749e330..d538a57 100644 --- a/ui/gfx/geometry/vector3d_f.cc +++ b/ui/gfx/geometry/vector3d_f.cc
@@ -86,8 +86,11 @@ float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base, const gfx::Vector3dF& other) { - return gfx::RadToDeg( - std::acos(gfx::DotProduct(base, other) / base.Length() / other.Length())); + // Clamp the resulting value to prevent potential NANs from floating point + // precision issues. + return gfx::RadToDeg(std::acos(fmax( + fmin(gfx::DotProduct(base, other) / base.Length() / other.Length(), 1.f), + -1.f))); } float ClockwiseAngleBetweenVectorsInDegrees(const gfx::Vector3dF& base,
diff --git a/ui/gfx/geometry/vector3d_unittest.cc b/ui/gfx/geometry/vector3d_unittest.cc index 02585c8..9a7e8b6 100644 --- a/ui/gfx/geometry/vector3d_unittest.cc +++ b/ui/gfx/geometry/vector3d_unittest.cc
@@ -270,14 +270,16 @@ float expected; gfx::Vector3dF input1; gfx::Vector3dF input2; - } tests[] = { - {0, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 1, 0)}, - {90, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 0, 1)}, - {45, - gfx::Vector3dF(0, 1, 0), - gfx::Vector3dF(0, 0.70710678188f, 0.70710678188f)}, - {180, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, -1, 0)}, - }; + } tests[] = {{0, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 1, 0)}, + {90, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 0, 1)}, + {45, gfx::Vector3dF(0, 1, 0), + gfx::Vector3dF(0, 0.70710678188f, 0.70710678188f)}, + {180, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, -1, 0)}, + // Two vectors that are sufficiently close enough together to + // trigger an issue that produces NANs if the value passed to + // acos is not clamped due to floating point precision. + {0, gfx::Vector3dF(0, -0.990842f, -0.003177f), + gfx::Vector3dF(0, -0.999995f, -0.003124f)}}; for (size_t i = 0; i < base::size(tests); ++i) { float actual =
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd index 6681177..4210d8a 100644 --- a/ui/strings/ui_strings.grd +++ b/ui/strings/ui_strings.grd
@@ -589,7 +589,7 @@ <message name="IDS_APP_COMMA_KEY" desc="Comma key"> Comma </message> - <message name="IDS_APP_PERIOD_KEY" desc="Period key"> + <message name="IDS_APP_PERIOD_KEY" desc="Period key, which is used to denote the end of a sentence (and not an interval of time)."> Period </message> <message name="IDS_APP_MEDIA_NEXT_TRACK_KEY" desc="Media next track key">
diff --git a/ui/views/bubble/footnote_container_view.cc b/ui/views/bubble/footnote_container_view.cc index 16aee1f7..58a32ea7 100644 --- a/ui/views/bubble/footnote_container_view.cc +++ b/ui/views/bubble/footnote_container_view.cc
@@ -54,7 +54,10 @@ SetLayoutManager( std::make_unique<BoxLayout>(BoxLayout::kVertical, margins, 0)); SetCornerRadius(corner_radius); - SetBorder(CreateSolidSidedBorder(1, 0, 0, 0, gfx::kGoogleGrey200)); + SetBorder(CreateSolidSidedBorder(1, 0, 0, 0, + GetNativeTheme()->SystemDarkModeEnabled() + ? gfx::kGoogleGrey900 + : gfx::kGoogleGrey200)); AddChildView(child_view); SetVisible(child_view->visible()); }
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc index e1c60d4e..f7490f2c 100644 --- a/ui/views/controls/textfield/textfield_unittest.cc +++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -20,7 +20,6 @@ #include "base/strings/string16.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "ui/accessibility/ax_node_data.h" #include "ui/aura/window.h" @@ -35,7 +34,6 @@ #include "ui/base/ime/text_edit_commands.h" #include "ui/base/ime/text_input_client.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches.h" #include "ui/base/ui_base_switches_util.h" #include "ui/events/event.h" @@ -1563,8 +1561,6 @@ TEST_F(TextfieldTest, ContextMenuDisplayTest) { InitTextfield(); - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kEnableEmojiContextMenu); EXPECT_TRUE(textfield_->context_menu_controller()); textfield_->SetText(ASCIIToUTF16("hello world")); @@ -3452,10 +3448,6 @@ InitTextfield(); EXPECT_TRUE(textfield_->context_menu_controller()); - // Enable the emoji feature. - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kEnableEmojiContextMenu); - // A normal empty field may show the Emoji option (if supported). ui::MenuModel* context_menu = GetContextMenuModel(); EXPECT_TRUE(context_menu); @@ -3470,10 +3462,6 @@ InitTextfield(); EXPECT_TRUE(textfield_->context_menu_controller()); - // Enable the emoji feature. - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kEnableEmojiContextMenu); - textfield_->SetReadOnly(true); // In no case is the emoji option showing on a read-only field. ui::MenuModel* context_menu = GetContextMenuModel(); @@ -3495,10 +3483,6 @@ constexpr int kExpectedEmojiIndex = 0; #endif - // Enable the emoji feature. - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kEnableEmojiContextMenu); - // A field with text may still show the Emoji option (if supported). textfield_->SetText(base::ASCIIToUTF16("some text")); textfield_->SelectAll(false); @@ -3549,10 +3533,6 @@ InitTextfield(); EXPECT_TRUE(textfield_->context_menu_controller()); - // Make sure the Emoji feature is disabled for this test. - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature(features::kEnableEmojiContextMenu); - const base::string16 kTextOne = ASCIIToUTF16("crake"); textfield_->SetText(kTextOne); textfield_->SelectAll(false);
diff --git a/ui/views_bridge_mac/BUILD.gn b/ui/views_bridge_mac/BUILD.gn index 3f249825..67f95555 100644 --- a/ui/views_bridge_mac/BUILD.gn +++ b/ui/views_bridge_mac/BUILD.gn
@@ -4,10 +4,20 @@ import("//mojo/public/tools/bindings/mojom.gni") +config("views_bridge_mac_warnings") { + if (is_mac) { + # TODO(thakis): Remove this once http://crbug.com/383820 is figured out + cflags = [ "-Wno-nonnull" ] + } +} + component("views_bridge_mac") { assert(is_mac) + configs += [ ":views_bridge_mac_warnings" ] sources = [ + "alert.h", + "alert.mm", "bridged_native_widget_host_helper.h", "cocoa_mouse_capture.h", "cocoa_mouse_capture.mm", @@ -17,7 +27,11 @@ ] defines = [ "VIEWS_BRIDGE_MAC_IMPLEMENTATION" ] deps = [ + ":mojo", "//base", + "//base:i18n", + "//mojo/public/cpp/bindings", + "//ui/accelerated_widget_mac", "//ui/base", "//ui/events", "//ui/gfx", @@ -29,6 +43,7 @@ assert(is_mac) sources = [ + "mojo/alert.mojom", "mojo/bridge_factory.mojom", "mojo/bridged_native_widget.mojom", "mojo/bridged_native_widget_host.mojom",
diff --git a/ui/views_bridge_mac/alert.h b/ui/views_bridge_mac/alert.h new file mode 100644 index 0000000..3a38554 --- /dev/null +++ b/ui/views_bridge_mac/alert.h
@@ -0,0 +1,65 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_VIEWS_BRIDGE_MAC_ALERT_H_ +#define UI_VIEWS_BRIDGE_MAC_ALERT_H_ + +#import <Cocoa/Cocoa.h> + +#include "base/mac/scoped_nsobject.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "ui/gfx/text_elider.h" +#include "ui/views_bridge_mac/mojo/alert.mojom.h" +#include "ui/views_bridge_mac/views_bridge_mac_export.h" + +@class AlertBridgeHelper; + +namespace views_bridge_mac { + +// Class that displays an NSAlert with associated UI as described by the mojo +// AlertBridge interface. +class VIEWS_BRIDGE_MAC_EXPORT AlertBridge + : public views_bridge_mac::mojom::AlertBridge { + public: + // Creates a new alert which controls its own lifetime. It will destroy itself + // once its NSAlert goes away. + AlertBridge(mojom::AlertBridgeRequest bridge_request); + + // Send the specified disposition via the Show callback, then destroy |this|. + void SendResultAndDestroy(mojom::AlertDisposition disposition); + + // Called by Cocoa to indicate when the NSAlert is visible (and can be + // programmatically updated by Accept, Cancel, and Close). + void SetAlertHasShown(); + + private: + // Private destructor is called only through SendResultAndDestroy. + ~AlertBridge() override; + + // Handle being disconnected (e.g, because the alert was programmatically + // dismissed). + void OnConnectionError(); + + // views_bridge_mac::mojom::Alert: + void Show(mojom::AlertBridgeInitParamsPtr params, + ShowCallback callback) override; + + // The NSAlert's owner and delegate. + base::scoped_nsobject<AlertBridgeHelper> helper_; + + // Set once the alert window is showing (needed because showing is done in a + // posted task). + bool alert_shown_ = false; + + // The callback to make when the dialog has finished running. + ShowCallback callback_; + + mojo::Binding<views_bridge_mac::mojom::AlertBridge> mojo_binding_; + base::WeakPtrFactory<AlertBridge> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(AlertBridge); +}; + +} // namespace views_bridge_mac + +#endif // UI_VIEWS_BRIDGE_MAC_ALERT_H_
diff --git a/ui/views_bridge_mac/alert.mm b/ui/views_bridge_mac/alert.mm new file mode 100644 index 0000000..328f51b --- /dev/null +++ b/ui/views_bridge_mac/alert.mm
@@ -0,0 +1,313 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/views_bridge_mac/alert.h" + +#include "base/i18n/rtl.h" +#import "base/mac/foundation_util.h" +#include "base/strings/sys_string_conversions.h" +#include "ui/accelerated_widget_mac/window_resize_helper_mac.h" +#include "ui/base/l10n/l10n_util_mac.h" + +using views_bridge_mac::mojom::AlertBridgeInitParams; +using views_bridge_mac::mojom::AlertDisposition; + +namespace { + +const int kSlotsPerLine = 50; +const int kMessageTextMaxSlots = 2000; + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// AlertBridgeHelper: + +// Helper object that receives the notification that the dialog/sheet is +// going away. Is responsible for cleaning itself up. +@interface AlertBridgeHelper : NSObject <NSAlertDelegate> { + @private + base::scoped_nsobject<NSAlert> alert_; + views_bridge_mac::AlertBridge* alertBridge_; // Weak. + base::scoped_nsobject<NSTextField> textField_; +} +@property(assign, nonatomic) views_bridge_mac::AlertBridge* alertBridge; + +// Returns the underlying alert. +- (NSAlert*)alert; + +// Set a blank icon for dialogs with text provided by the page. +- (void)setBlankIcon; + +// Add a text field to the alert. +- (void)addTextFieldWithPrompt:(NSString*)prompt; + +// Presents an AppKit blocking dialog. +- (void)showAlert; +@end + +@implementation AlertBridgeHelper +@synthesize alertBridge = alertBridge_; + +- (void)initAlert:(AlertBridgeInitParams*)params { + alert_.reset([[NSAlert alloc] init]); + [alert_ setDelegate:self]; + + if (params->hide_application_icon) + [self setBlankIcon]; + if (params->text_field_text) { + [self addTextFieldWithPrompt:base::SysUTF16ToNSString( + *params->text_field_text)]; + } + NSString* informative_text = base::SysUTF16ToNSString(params->message_text); + + // Truncate long JS alerts - crbug.com/331219 + NSCharacterSet* newline_char_set = [NSCharacterSet newlineCharacterSet]; + for (size_t index = 0, slots_count = 0; index < informative_text.length; + ++index) { + unichar current_char = [informative_text characterAtIndex:index]; + if ([newline_char_set characterIsMember:current_char]) + slots_count += kSlotsPerLine; + else + slots_count++; + if (slots_count > kMessageTextMaxSlots) { + base::string16 info_text = base::SysNSStringToUTF16(informative_text); + informative_text = base::SysUTF16ToNSString( + gfx::TruncateString(info_text, index, gfx::WORD_BREAK)); + break; + } + } + + [alert_ setInformativeText:informative_text]; + NSString* message_text = l10n_util::FixUpWindowsStyleLabel(params->title); + [alert_ setMessageText:message_text]; + [alert_ addButtonWithTitle:l10n_util::FixUpWindowsStyleLabel( + params->primary_button_text)]; + + if (params->secondary_button_text) { + NSButton* other = + [alert_ addButtonWithTitle:l10n_util::FixUpWindowsStyleLabel( + *params->secondary_button_text)]; + [other setKeyEquivalent:@"\e"]; + } + if (params->check_box_text) { + [alert_ setShowsSuppressionButton:YES]; + NSString* suppression_title = + l10n_util::FixUpWindowsStyleLabel(*params->check_box_text); + [[alert_ suppressionButton] setTitle:suppression_title]; + } + + // Fix RTL dialogs. + // + // Mac OS X will always display NSAlert strings as LTR. A workaround is to + // manually set the text as attributed strings in the implementing + // NSTextFields. This is a basic correctness issue. + // + // In addition, for readability, the overall alignment is set based on the + // directionality of the first strongly-directional character. + // + // If the dialog fields are selectable then they will scramble when clicked. + // Therefore, selectability is disabled. + // + // See http://crbug.com/70806 for more details. + + bool message_has_rtl = + base::i18n::StringContainsStrongRTLChars(params->title); + bool informative_has_rtl = + base::i18n::StringContainsStrongRTLChars(params->message_text); + + NSTextField* message_text_field = nil; + NSTextField* informative_text_field = nil; + if (message_has_rtl || informative_has_rtl) { + // Force layout of the dialog. NSAlert leaves its dialog alone once laid + // out; if this is not done then all the modifications that are to come will + // be un-done when the dialog is finally displayed. + [alert_ layout]; + + // Locate the NSTextFields that implement the text display. These are + // actually available as the ivars |_messageField| and |_informationField| + // of the NSAlert, but it is safer (and more forward-compatible) to search + // for them in the subviews. + for (NSView* view in [[[alert_ window] contentView] subviews]) { + NSTextField* text_field = base::mac::ObjCCast<NSTextField>(view); + if ([[text_field stringValue] isEqualTo:message_text]) + message_text_field = text_field; + else if ([[text_field stringValue] isEqualTo:informative_text]) + informative_text_field = text_field; + } + + // This may fail in future OS releases, but it will still work for shipped + // versions of Chromium. + DCHECK(message_text_field); + DCHECK(informative_text_field); + } + + if (message_has_rtl && message_text_field) { + base::scoped_nsobject<NSMutableParagraphStyle> alignment( + [[NSParagraphStyle defaultParagraphStyle] mutableCopy]); + [alignment setAlignment:NSRightTextAlignment]; + + NSDictionary* alignment_attributes = + @{NSParagraphStyleAttributeName : alignment}; + base::scoped_nsobject<NSAttributedString> attr_string( + [[NSAttributedString alloc] initWithString:message_text + attributes:alignment_attributes]); + + [message_text_field setAttributedStringValue:attr_string]; + [message_text_field setSelectable:NO]; + } + + if (informative_has_rtl && informative_text_field) { + base::i18n::TextDirection direction = + base::i18n::GetFirstStrongCharacterDirection(params->message_text); + base::scoped_nsobject<NSMutableParagraphStyle> alignment( + [[NSParagraphStyle defaultParagraphStyle] mutableCopy]); + [alignment setAlignment:(direction == base::i18n::RIGHT_TO_LEFT) + ? NSRightTextAlignment + : NSLeftTextAlignment]; + + NSDictionary* alignment_attributes = + @{NSParagraphStyleAttributeName : alignment}; + base::scoped_nsobject<NSAttributedString> attr_string( + [[NSAttributedString alloc] initWithString:informative_text + attributes:alignment_attributes]); + + [informative_text_field setAttributedStringValue:attr_string]; + [informative_text_field setSelectable:NO]; + } +} + +- (void)setBlankIcon { + NSImage* image = + [[[NSImage alloc] initWithSize:NSMakeSize(1, 1)] autorelease]; + [alert_ setIcon:image]; +} + +- (NSAlert*)alert { + return alert_; +} + +- (void)addTextFieldWithPrompt:(NSString*)prompt { + DCHECK(!textField_); + textField_.reset( + [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 22)]); + [[textField_ cell] setLineBreakMode:NSLineBreakByTruncatingTail]; + [[self alert] setAccessoryView:textField_]; + [[alert_ window] setInitialFirstResponder:textField_]; + + [textField_ setStringValue:prompt]; +} + +// |contextInfo| is the JavaScriptAppModalDialogCocoa that owns us. +- (void)alertDidEnd:(NSAlert*)alert + returnCode:(int)returnCode + contextInfo:(void*)contextInfo { + switch (returnCode) { + case NSAlertFirstButtonReturn: // OK + alertBridge_->SendResultAndDestroy(AlertDisposition::PRIMARY_BUTTON); + break; + case NSAlertSecondButtonReturn: // Cancel + alertBridge_->SendResultAndDestroy(AlertDisposition::SECONDARY_BUTTON); + break; + case NSRunStoppedResponse: // Window was closed underneath us + alertBridge_->SendResultAndDestroy(AlertDisposition::CLOSE); + break; + default: + NOTREACHED(); + } +} + +- (void)showAlert { + DCHECK(alertBridge_); + alertBridge_->SetAlertHasShown(); + NSAlert* alert = [self alert]; + [alert layout]; + [[alert window] recalculateKeyViewLoop]; + [alert beginSheetModalForWindow:nil // nil here makes it app-modal + modalDelegate:self + didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) + contextInfo:NULL]; +} + +- (void)closeWindow { + DCHECK(alertBridge_); + [NSApp endSheet:[[self alert] window]]; +} + +- (base::string16)input { + if (textField_) + return base::SysNSStringToUTF16([textField_ stringValue]); + return base::string16(); +} + +- (bool)shouldSuppress { + if ([[self alert] showsSuppressionButton]) + return [[[self alert] suppressionButton] state] == NSOnState; + return false; +} + +@end + +namespace views_bridge_mac { + +//////////////////////////////////////////////////////////////////////////////// +// AlertBridge: + +AlertBridge::AlertBridge(mojom::AlertBridgeRequest bridge_request) + : mojo_binding_(this), weak_factory_(this) { + mojo_binding_.Bind(std::move(bridge_request), + ui::WindowResizeHelperMac::Get()->task_runner()); + mojo_binding_.set_connection_error_handler(base::BindOnce( + &AlertBridge::OnConnectionError, weak_factory_.GetWeakPtr())); +} + +AlertBridge::~AlertBridge() { + [helper_ setAlertBridge:nil]; + [NSObject cancelPreviousPerformRequestsWithTarget:helper_.get()]; +} + +void AlertBridge::OnConnectionError() { + // If the alert has been shown, then close the window, and |this| will delete + // itself after the window is closed. Otherwise, just delete |this| + // immediately. + if (alert_shown_) + [helper_ closeWindow]; + else + delete this; +} + +void AlertBridge::SendResultAndDestroy(AlertDisposition disposition) { + DCHECK(callback_); + std::move(callback_).Run(disposition, [helper_ input], + [helper_ shouldSuppress]); + delete this; +} + +void AlertBridge::SetAlertHasShown() { + DCHECK(!alert_shown_); + alert_shown_ = true; +} + +//////////////////////////////////////////////////////////////////////////////// +// AlertBridge, mojo::AlertBridge: + +void AlertBridge::Show(mojom::AlertBridgeInitParamsPtr params, + ShowCallback callback) { + callback_ = std::move(callback); + + // Create a helper which will receive the sheet ended selector. It will + // delete itself when done. + helper_.reset([[AlertBridgeHelper alloc] init]); + [helper_ setAlertBridge:this]; + [helper_ initAlert:params.get()]; + + // Dispatch the method to show the alert back to the top of the CFRunLoop. + // This fixes an interaction bug with NSSavePanel. http://crbug.com/375785 + // When this object is destroyed, outstanding performSelector: requests + // should be cancelled. + [helper_.get() performSelector:@selector(showAlert) + withObject:nil + afterDelay:0]; +} + +} // namespace views_bridge_mac
diff --git a/ui/views_bridge_mac/bridge_factory_impl.h b/ui/views_bridge_mac/bridge_factory_impl.h index 5075e76bf..061be58 100644 --- a/ui/views_bridge_mac/bridge_factory_impl.h +++ b/ui/views_bridge_mac/bridge_factory_impl.h
@@ -7,6 +7,7 @@ #include "mojo/public/cpp/bindings/associated_binding.h" #include "ui/views/views_export.h" +#include "ui/views_bridge_mac/mojo/alert.mojom.h" #include "ui/views_bridge_mac/mojo/bridge_factory.mojom.h" #include "ui/views_bridge_mac/mojo/bridged_native_widget.mojom.h" #include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h" @@ -23,6 +24,7 @@ void BindRequest(mojom::BridgeFactoryAssociatedRequest request); // mojom::BridgeFactory: + void CreateAlert(mojom::AlertBridgeRequest bridge_request) override; void CreateBridgedNativeWidget( uint64_t bridge_id, mojom::BridgedNativeWidgetAssociatedRequest bridge_request,
diff --git a/ui/views_bridge_mac/bridge_factory_impl.mm b/ui/views_bridge_mac/bridge_factory_impl.mm index e4168c1..2d1f20e3 100644 --- a/ui/views_bridge_mac/bridge_factory_impl.mm +++ b/ui/views_bridge_mac/bridge_factory_impl.mm
@@ -7,6 +7,7 @@ #include "base/no_destructor.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/base/cocoa/remote_accessibility_api.h" +#include "ui/views_bridge_mac/alert.h" #include "ui/views_bridge_mac/bridged_native_widget_host_helper.h" #include "ui/views_bridge_mac/bridged_native_widget_impl.h" @@ -104,6 +105,11 @@ ui::WindowResizeHelperMac::Get()->task_runner()); } +void BridgeFactoryImpl::CreateAlert(mojom::AlertBridgeRequest bridge_request) { + // The resulting object manages its own lifetime. + ignore_result(new AlertBridge(std::move(bridge_request))); +} + void BridgeFactoryImpl::CreateBridgedNativeWidget( uint64_t bridge_id, mojom::BridgedNativeWidgetAssociatedRequest bridge_request,
diff --git a/ui/views_bridge_mac/mojo/alert.mojom b/ui/views_bridge_mac/mojo/alert.mojom new file mode 100644 index 0000000..7f49f42 --- /dev/null +++ b/ui/views_bridge_mac/mojo/alert.mojom
@@ -0,0 +1,51 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module views_bridge_mac.mojom; + +import "mojo/public/mojom/base/string16.mojom"; + +struct AlertBridgeInitParams { + // The dialog title and text. + mojo_base.mojom.String16 title; + mojo_base.mojom.String16 message_text; + + // Set if the application icon should be hidden. + bool hide_application_icon; + + // Text for the primary button (which is also the default button). + mojo_base.mojom.String16 primary_button_text; + + // Text for the secondary (non-default) button. If not set, then there is only + // one button for this alert. + mojo_base.mojom.String16? secondary_button_text; + + // Default text for the text field. If not set, then there is no text field + // for this alert. + mojo_base.mojom.String16? text_field_text; + + // The text for the checkbox. If not set, then there is no checkbox for this + // alert. + mojo_base.mojom.String16? check_box_text; +}; + +// Disposition of alert window. +enum AlertDisposition { + // Default button was pressed. + PRIMARY_BUTTON, + // Secondary button was pressed. + SECONDARY_BUTTON, + // The window was closed without a selection being made. + CLOSE, +}; + +interface AlertBridge { + // Initialize and show the alert. Return in |disposition| is how the window + // was dismissed. Return in |text_field_value| the value of the text field + // shown in the alert (if any). Return true in |check_box_value| only if the + // alert had a checkbox and it was checked. + Show(AlertBridgeInitParams params) => + (AlertDisposition disposition, mojo_base.mojom.String16 text_field_value, + bool check_box_value); +};
diff --git a/ui/views_bridge_mac/mojo/bridge_factory.mojom b/ui/views_bridge_mac/mojo/bridge_factory.mojom index 246ba5bb..d6a88f8 100644 --- a/ui/views_bridge_mac/mojo/bridge_factory.mojom +++ b/ui/views_bridge_mac/mojo/bridge_factory.mojom
@@ -4,11 +4,15 @@ module views_bridge_mac.mojom; +import "ui/views_bridge_mac/mojo/alert.mojom"; import "ui/views_bridge_mac/mojo/bridged_native_widget.mojom"; import "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom"; // The interface through which a bridge is created and connected to its host. interface BridgeFactory { + // Create a bridge for an NSAlert. The resulting object owns its own lifetime. + CreateAlert(AlertBridge& alert_bridge_request); + // Create a bridge for a native widget. The resulting object will be owned by // the connection for |host|. Closing that connection will result in deleting // the bridge.
diff --git a/url/BUILD.gn b/url/BUILD.gn index 725cff7c..9e1f5b46 100644 --- a/url/BUILD.gn +++ b/url/BUILD.gn
@@ -57,11 +57,6 @@ defines = [ "IS_URL_IMPL" ] - configs += [ - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - "//build/config/compiler:no_size_t_to_int_warning", - ] - deps = [ "//base", "//base/third_party/dynamic_annotations", @@ -164,9 +159,6 @@ deps += [ "//third_party/icu:icuuc" ] } - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - if (!is_ios) { deps += [ "//mojo/core/embedder",