diff --git a/BUILD.gn b/BUILD.gn index 1b299db..529d1fdb 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -401,7 +401,6 @@ "//base:base_junit_tests", "//base/android/linker:chromium_android_linker", "//build/android/gyp/test:hello_world", - "//build/android/rezip", "//chrome/android/webapk/shell_apk:webapk", "//components/invalidation/impl:components_invalidation_impl_junit_tests", "//components/policy/android:components_policy_junit_tests",
diff --git a/DEPS b/DEPS index c2f85f8..d4a0285 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,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': 'db52cf3b040d0360a70432d11d404712f0733c28', + 'skia_revision': 'a5494f117086d712855e4b6289c58c92d1549bcf', # 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': '8ba45f77c14f019f1d61565371a89e635db15151', + 'v8_revision': 'd1d93c3a0e8f6eb84756b5ad56b33e300e327bdc', # 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. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '44bc1f818dd791c2a5a81103be3853093fd934b3', + 'pdfium_revision': '8fa82794ffc2763e9fa1fc9d401c8e9a14d7c67f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -96,7 +96,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': '8b10e7828ad23b4aed04259a870ab11d2f323a23', + 'catapult_revision': '7863f77ca84edad4dc03fcb17c790e3c549c9f8e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -192,13 +192,13 @@ Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0', 'src/third_party/webgl/src': - Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '046d1f6892ba08de4b9f58d59a50794034f286e7', + Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '06ad9fd073271d958ae63fbc9ef924e5f824589f', 'src/third_party/webdriver/pylib': Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd', 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + 'f27276f44fa3a66c07a2a92a381f31aaf8371add', + Var('chromium_git') + '/webm/libvpx.git' + '@' + '5b1a8ca5e846f838062becaec9ed6b5ecef306e5', 'src/third_party/ffmpeg': Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'f309edd7828e3ea500c2891187d15926690ddd27',
diff --git a/android_webview/java/generated_src/org/chromium/base/library_loader/NativeLibraries.java b/android_webview/java/generated_src/org/chromium/base/library_loader/NativeLibraries.java deleted file mode 100644 index 6e360e29..0000000 --- a/android_webview/java/generated_src/org/chromium/base/library_loader/NativeLibraries.java +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.base.library_loader; - -/** - * This class defines the native libraries and loader options required by webview - */ -public class NativeLibraries { - // Set to true to use the chromium linker. Only useful to save memory - // on multi-process content-based projects. Always disabled for the Android Webview. - public static boolean sUseLinker = false; - - // Set to true to directly load the library from the zip file using the - // chromium linker. Always disabled for Android Webview. - public static boolean sUseLibraryInZipFile = false; - - // Set to true to enable chromium linker test support. NEVER enable this for the - // Android webview. - public static boolean sEnableLinkerTests = false; - - // This is the list of native libraries to load. In the normal chromium build, this would be - // automatically generated. - // TODO(torne, cjhopman): Use a generated file for this. - static final String[] LIBRARIES = { "webviewchromium" }; - // This should match the version name string returned by the native library. - // TODO(aberent) The Webview native library currently returns an empty string; change this - // to a string generated at compile time, and incorporate that string in a generated - // replacement for this file. - static String sVersionNumber = ""; -}
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni index 8b37716..90bdc7f5 100644 --- a/android_webview/system_webview_apk_tmpl.gni +++ b/android_webview/system_webview_apk_tmpl.gni
@@ -4,6 +4,7 @@ import("//build/config/android/config.gni") import("//build/config/android/rules.gni") +import("//build/config/locales.gni") template("system_webview_apk_tmpl") { android_apk(target_name) { @@ -27,6 +28,7 @@ if (build_apk_secondary_abi && android_64bit_target_cpu) { secondary_abi_shared_libraries = [ "//android_webview:libwebviewchromium($android_secondary_abi_toolchain)" ] } + aapt_locale_whitelist = locales if (!is_java_debug) { proguard_enabled = true
diff --git a/android_webview/tools/apk_merger.py b/android_webview/tools/apk_merger.py index 74eac37..713a58d 100755 --- a/android_webview/tools/apk_merger.py +++ b/android_webview/tools/apk_merger.py
@@ -135,8 +135,7 @@ def SignAndAlignApk(tmp_apk, signed_tmp_apk, new_apk, zipalign_path, - keystore_path, key_name, key_password, - page_align_shared_libraries): + keystore_path, key_name, key_password): try: finalize_apk.JarSigner( keystore_path, @@ -149,7 +148,6 @@ try: finalize_apk.AlignApk(zipalign_path, - page_align_shared_libraries, signed_tmp_apk, new_apk) except build_utils.CalledProcessError as e: @@ -224,7 +222,8 @@ parser.add_argument('--key_name', required=True) parser.add_argument('--key_password', required=True) parser.add_argument('--shared_library') - parser.add_argument('--page-align-shared-libraries', action='store_true') + parser.add_argument('--page-align-shared-libraries', action='store_true', + help='Obsolete, but remains for backwards compatibility') parser.add_argument('--uncompress-shared-libraries', action='store_true') parser.add_argument('--debug', action='store_true') # This option shall only used in debug build, see http://crbug.com/631494. @@ -250,8 +249,7 @@ MergeApk(args, tmp_apk, tmp_dir_32, tmp_dir_64) SignAndAlignApk(tmp_apk, signed_tmp_apk, new_apk, args.zipalign_path, - args.keystore_path, args.key_name, args.key_password, - args.page_align_shared_libraries) + args.keystore_path, args.key_name, args.key_password) except ApkMergeFailure as e: print e
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index e09087a..db31ff65 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1342,6 +1342,7 @@ "//ash/public/cpp", "//ash/public/interfaces", "//ash/resources", + "//ash/resources/vector_icons", "//ash/test:ash_with_aura_test_support", "//ash/test:test_support_without_content", "//ash/touch_hud",
diff --git a/ash/common/frame/caption_buttons/frame_caption_button.cc b/ash/common/frame/caption_buttons/frame_caption_button.cc index d496f1b..74f1ef9 100644 --- a/ash/common/frame/caption_buttons/frame_caption_button.cc +++ b/ash/common/frame/caption_buttons/frame_caption_button.cc
@@ -56,9 +56,10 @@ void FrameCaptionButton::SetImage(CaptionButtonIcon icon, Animate animate, - gfx::VectorIconId icon_image_id) { + const gfx::VectorIcon& icon_definition) { gfx::ImageSkia new_icon_image = gfx::CreateVectorIcon( - icon_image_id, use_light_images_ ? SK_ColorWHITE : gfx::kChromeIconGrey); + icon_definition, + use_light_images_ ? SK_ColorWHITE : gfx::kChromeIconGrey); // The early return is dependent on |animate| because callers use SetImage() // with ANIMATE_NO to progress the crossfade animation to the end. @@ -72,7 +73,7 @@ crossfade_icon_image_ = icon_image_; icon_ = icon; - icon_image_id_ = icon_image_id; + icon_definition_ = &icon_definition; icon_image_ = new_icon_image; if (animate == ANIMATE_YES) {
diff --git a/ash/common/frame/caption_buttons/frame_caption_button.h b/ash/common/frame/caption_buttons/frame_caption_button.h index 3f80862..8b6df285 100644 --- a/ash/common/frame/caption_buttons/frame_caption_button.h +++ b/ash/common/frame/caption_buttons/frame_caption_button.h
@@ -15,7 +15,7 @@ namespace gfx { class SlideAnimation; -enum class VectorIconId; +struct VectorIcon; } namespace ash { @@ -32,12 +32,12 @@ ~FrameCaptionButton() override; // Sets the image to use to paint the button. If |animate| is ANIMATE_YES, - // the button crossfades to the new visuals. If the image id matches the one + // the button crossfades to the new visuals. If the image matches the one // currently used by the button and |animate| is ANIMATE_NO, the crossfade // animation is progressed to the end. void SetImage(CaptionButtonIcon icon, Animate animate, - gfx::VectorIconId icon_image_id); + const gfx::VectorIcon& icon_image); // Returns true if the button is crossfading to new visuals set in // SetImage(). @@ -59,8 +59,6 @@ CaptionButtonIcon icon() const { return icon_; } - gfx::VectorIconId icon_image_id() const { return icon_image_id_; } - void set_size(const gfx::Size& size) { size_ = size; } protected: @@ -90,7 +88,7 @@ // The image id (kept for the purposes of testing) and image used to paint the // button's icon. - gfx::VectorIconId icon_image_id_; + const gfx::VectorIcon* icon_definition_ = nullptr; gfx::ImageSkia icon_image_; // The icon image to crossfade from.
diff --git a/ash/common/frame/caption_buttons/frame_caption_button_container_view.cc b/ash/common/frame/caption_buttons/frame_caption_button_container_view.cc index 77f8006..3539a04 100644 --- a/ash/common/frame/caption_buttons/frame_caption_button_container_view.cc +++ b/ash/common/frame/caption_buttons/frame_caption_button_container_view.cc
@@ -19,7 +19,7 @@ #include "ui/gfx/canvas.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/point.h" -#include "ui/gfx/vector_icons_public.h" +#include "ui/gfx/vector_icon_types.h" #include "ui/strings/grit/ui_strings.h" // Accessibility names #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -148,14 +148,15 @@ void FrameCaptionButtonContainerView::SetButtonImage( CaptionButtonIcon icon, - gfx::VectorIconId icon_image_id) { - button_icon_id_map_[icon] = icon_image_id; + const gfx::VectorIcon& icon_definition) { + button_icon_map_[icon] = &icon_definition; FrameCaptionButton* buttons[] = {minimize_button_, size_button_, close_button_}; for (size_t i = 0; i < arraysize(buttons); ++i) { if (buttons[i]->icon() == icon) - buttons[i]->SetImage(icon, FrameCaptionButton::ANIMATE_NO, icon_image_id); + buttons[i]->SetImage(icon, FrameCaptionButton::ANIMATE_NO, + icon_definition); } } @@ -299,9 +300,9 @@ FrameCaptionButton::Animate fcb_animate = (animate == ANIMATE_YES) ? FrameCaptionButton::ANIMATE_YES : FrameCaptionButton::ANIMATE_NO; - auto it = button_icon_id_map_.find(icon); - if (it != button_icon_id_map_.end()) - button->SetImage(icon, fcb_animate, it->second); + auto it = button_icon_map_.find(icon); + if (it != button_icon_map_.end()) + button->SetImage(icon, fcb_animate, *it->second); } bool FrameCaptionButtonContainerView::ShouldSizeButtonBeVisible() const {
diff --git a/ash/common/frame/caption_buttons/frame_caption_button_container_view.h b/ash/common/frame/caption_buttons/frame_caption_button_container_view.h index 55fd39c..014071a 100644 --- a/ash/common/frame/caption_buttons/frame_caption_button_container_view.h +++ b/ash/common/frame/caption_buttons/frame_caption_button_container_view.h
@@ -16,7 +16,7 @@ namespace gfx { class SlideAnimation; -enum class VectorIconId; +struct VectorIcon; } namespace views { @@ -68,7 +68,8 @@ // Sets the id of the vector image to paint the button for |icon|. The // FrameCaptionButtonContainerView will keep track of the image to use for // |icon| even if none of the buttons currently use |icon|. - void SetButtonImage(CaptionButtonIcon icon, gfx::VectorIconId icon_image_id); + void SetButtonImage(CaptionButtonIcon icon, + const gfx::VectorIcon& icon_definition); // Sets whether the buttons should be painted as active. Does not schedule // a repaint. @@ -141,9 +142,9 @@ FrameCaptionButton* size_button_; FrameCaptionButton* close_button_; - // Mapping of the image ID needed to paint a button for each of the values of + // Mapping of the image needed to paint a button for each of the values of // CaptionButtonIcon. - std::map<CaptionButtonIcon, gfx::VectorIconId> button_icon_id_map_; + std::map<CaptionButtonIcon, const gfx::VectorIcon*> button_icon_map_; // Animation that affects the position of |minimize_button_| and the // visibility of |size_button_|.
diff --git a/ash/common/frame/caption_buttons/frame_caption_button_container_view_unittest.cc b/ash/common/frame/caption_buttons/frame_caption_button_container_view_unittest.cc index 067e868..21fce7ca 100644 --- a/ash/common/frame/caption_buttons/frame_caption_button_container_view_unittest.cc +++ b/ash/common/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
@@ -8,10 +8,10 @@ #include "ash/common/frame/caption_buttons/frame_caption_button.h" #include "ash/common/wm/maximize_mode/maximize_mode_controller.h" #include "ash/common/wm_shell.h" +#include "ash/resources/vector_icons/vector_icons.h" #include "ash/test/ash_test_base.h" #include "grit/ash_resources.h" #include "ui/gfx/geometry/rect.h" -#include "ui/gfx/vector_icons_public.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -71,7 +71,7 @@ GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON)); for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) { container->SetButtonImage(static_cast<CaptionButtonIcon>(icon), - gfx::VectorIconId::WINDOW_CONTROL_CLOSE); + ash::kWindowControlCloseIcon); } }
diff --git a/ash/common/frame/default_header_painter.cc b/ash/common/frame/default_header_painter.cc index f333bf1..4856f7e9 100644 --- a/ash/common/frame/default_header_painter.cc +++ b/ash/common/frame/default_header_painter.cc
@@ -7,6 +7,7 @@ #include "ash/common/ash_layout_constants.h" #include "ash/common/frame/caption_buttons/frame_caption_button_container_view.h" #include "ash/common/frame/header_painter_util.h" +#include "ash/resources/vector_icons/vector_icons.h" #include "base/debug/leak_annotations.h" #include "base/logging.h" // DCHECK #include "grit/ash_resources.h" @@ -21,7 +22,6 @@ #include "ui/gfx/image/image.h" #include "ui/gfx/scoped_canvas.h" #include "ui/gfx/skia_util.h" -#include "ui/gfx/vector_icons_public.h" #include "ui/views/view.h" #include "ui/views/widget/native_widget_aura.h" #include "ui/views/widget/widget.h" @@ -283,29 +283,27 @@ void DefaultHeaderPainter::UpdateAllButtonImages() { caption_button_container_->SetUseLightImages(ShouldUseLightImages()); - caption_button_container_->SetButtonImage( - CAPTION_BUTTON_ICON_MINIMIZE, gfx::VectorIconId::WINDOW_CONTROL_MINIMIZE); + caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_MINIMIZE, + kWindowControlMinimizeIcon); UpdateSizeButtonImages(); - caption_button_container_->SetButtonImage( - CAPTION_BUTTON_ICON_CLOSE, gfx::VectorIconId::WINDOW_CONTROL_CLOSE); + caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_CLOSE, + kWindowControlCloseIcon); - caption_button_container_->SetButtonImage( - CAPTION_BUTTON_ICON_LEFT_SNAPPED, - gfx::VectorIconId::WINDOW_CONTROL_LEFT_SNAPPED); + caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_LEFT_SNAPPED, + kWindowControlLeftSnappedIcon); - caption_button_container_->SetButtonImage( - CAPTION_BUTTON_ICON_RIGHT_SNAPPED, - gfx::VectorIconId::WINDOW_CONTROL_RIGHT_SNAPPED); + caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, + kWindowControlRightSnappedIcon); } void DefaultHeaderPainter::UpdateSizeButtonImages() { - gfx::VectorIconId icon_id = frame_->IsMaximized() || frame_->IsFullscreen() - ? gfx::VectorIconId::WINDOW_CONTROL_RESTORE - : gfx::VectorIconId::WINDOW_CONTROL_MAXIMIZE; + const gfx::VectorIcon& icon = frame_->IsMaximized() || frame_->IsFullscreen() + ? kWindowControlRestoreIcon + : kWindowControlMaximizeIcon; caption_button_container_->SetButtonImage( - CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, icon_id); + CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, icon); } gfx::Rect DefaultHeaderPainter::GetLocalBounds() const {
diff --git a/ash/common/shelf/app_list_shelf_item_delegate.cc b/ash/common/shelf/app_list_shelf_item_delegate.cc index 53143be..af2dbb3 100644 --- a/ash/common/shelf/app_list_shelf_item_delegate.cc +++ b/ash/common/shelf/app_list_shelf_item_delegate.cc
@@ -14,19 +14,18 @@ namespace ash { // static -void AppListShelfItemDelegate::CreateAppListItemAndDelegate( - ShelfModel* shelf_model) { +void AppListShelfItemDelegate::CreateAppListItemAndDelegate(ShelfModel* model) { // Add the app list item to the shelf model. - ShelfItem app_list; - app_list.type = TYPE_APP_LIST; - int app_list_index = shelf_model->Add(app_list); - DCHECK_GE(app_list_index, 0); + ShelfItem item; + item.type = TYPE_APP_LIST; + item.title = l10n_util::GetStringUTF16(IDS_ASH_SHELF_APP_LIST_LAUNCHER_TITLE); + int index = model->Add(item); + DCHECK_GE(index, 0); // Create an AppListShelfItemDelegate for that item. - ShelfID app_list_id = shelf_model->items()[app_list_index].id; - DCHECK_GE(app_list_id, 0); - shelf_model->SetShelfItemDelegate( - app_list_id, base::MakeUnique<AppListShelfItemDelegate>()); + ShelfID id = model->items()[index].id; + DCHECK_GE(id, 0); + model->SetShelfItemDelegate(id, base::MakeUnique<AppListShelfItemDelegate>()); } AppListShelfItemDelegate::AppListShelfItemDelegate() {} @@ -39,16 +38,6 @@ return ShelfItemDelegate::kAppListMenuShown; } -base::string16 AppListShelfItemDelegate::GetTitle() { - ShelfModel* model = WmShell::Get()->shelf_model(); - DCHECK(model); - int title_id; - title_id = model->status() == ShelfModel::STATUS_LOADING - ? IDS_ASH_SHELF_APP_LIST_LAUNCHER_SYNCING_TITLE - : IDS_ASH_SHELF_APP_LIST_LAUNCHER_TITLE; - return l10n_util::GetStringUTF16(title_id); -} - ShelfMenuModel* AppListShelfItemDelegate::CreateApplicationMenu( int event_flags) { // AppList does not show an application menu.
diff --git a/ash/common/shelf/app_list_shelf_item_delegate.h b/ash/common/shelf/app_list_shelf_item_delegate.h index 3884052..82a122d 100644 --- a/ash/common/shelf/app_list_shelf_item_delegate.h +++ b/ash/common/shelf/app_list_shelf_item_delegate.h
@@ -15,8 +15,8 @@ class AppListShelfItemDelegate : public ShelfItemDelegate { public: // Initializes the app list item in the shelf data model and creates an - // AppListShelfItemDelegate which will be owned by |shelf_model|. - static void CreateAppListItemAndDelegate(ShelfModel* shelf_model); + // AppListShelfItemDelegate which will be owned by |model|. + static void CreateAppListItemAndDelegate(ShelfModel* model); AppListShelfItemDelegate(); ~AppListShelfItemDelegate() override; @@ -24,7 +24,6 @@ // ShelfItemDelegate: ShelfItemDelegate::PerformedAction ItemSelected( const ui::Event& event) override; - base::string16 GetTitle() override; ShelfMenuModel* CreateApplicationMenu(int event_flags) override; void Close() override;
diff --git a/ash/common/shelf/shelf_controller.cc b/ash/common/shelf/shelf_controller.cc index 78b0874..2cea707e4 100644 --- a/ash/common/shelf/shelf_controller.cc +++ b/ash/common/shelf/shelf_controller.cc
@@ -60,7 +60,7 @@ explicit ShelfMenuModelMus(ShelfItemDelegateMus* item_delegate) : ShelfMenuModel(this), item_delegate_(item_delegate) { AddSeparator(ui::SPACING_SEPARATOR); - AddItem(0, item_delegate_->GetTitle()); + AddItem(0, item_delegate_->title()); AddSeparator(ui::SPACING_SEPARATOR); for (const auto& window : item_delegate_->window_id_to_title()) AddItem(window.first, window.second); @@ -100,11 +100,6 @@ return kNoAction; } - base::string16 GetTitle() override { - return window_id_to_title_.empty() ? title_ - : window_id_to_title_.begin()->second; - } - ShelfMenuModel* CreateApplicationMenu(int event_flags) override { return new ShelfMenuModelMus(this); } @@ -232,13 +227,14 @@ shelf_item.type = TYPE_APP_SHORTCUT; shelf_item.status = STATUS_CLOSED; shelf_item.image = GetShelfIconFromBitmap(item->image); + shelf_item.title = base::UTF8ToUTF16(item->app_title); model_.Add(shelf_item); - std::unique_ptr<ShelfItemDelegateMus> item_delegate( - new ShelfItemDelegateMus()); + std::unique_ptr<ShelfItemDelegateMus> item_delegate = + base::MakeUnique<ShelfItemDelegateMus>(); item_delegate->SetDelegate(std::move(delegate)); item_delegate->set_pinned(true); - item_delegate->set_title(base::UTF8ToUTF16(item->app_title)); + item_delegate->set_title(shelf_item.title); model_.SetShelfItemDelegate(shelf_id, std::move(item_delegate)); }
diff --git a/ash/common/shelf/shelf_item_delegate.h b/ash/common/shelf/shelf_item_delegate.h index 868e856..fbf76ef 100644 --- a/ash/common/shelf/shelf_item_delegate.h +++ b/ash/common/shelf/shelf_item_delegate.h
@@ -44,9 +44,6 @@ // Returns the action performed by selecting the item. virtual PerformedAction ItemSelected(const ui::Event& event) = 0; - // Returns the title to display. - virtual base::string16 GetTitle() = 0; - // Returns the application menu model for the specified item. There are three // possible return values: // - A return of NULL indicates that no menu is wanted for this item.
diff --git a/ash/common/shelf/shelf_item_types.h b/ash/common/shelf/shelf_item_types.h index 998f33b..ea021bb 100644 --- a/ash/common/shelf/shelf_item_types.h +++ b/ash/common/shelf/shelf_item_types.h
@@ -10,6 +10,7 @@ #include "ash/ash_export.h" #include "ash/common/shelf/shelf_constants.h" +#include "base/strings/string16.h" #include "ui/gfx/image/image_skia.h" namespace ash { @@ -73,6 +74,9 @@ // The application id for this shelf item; only populated for some items. std::string app_id; + // The title to display for tooltips, etc. + base::string16 title; + // Whether the tooltip should be shown on hover; generally true. bool shows_tooltip = true;
diff --git a/ash/common/shelf/shelf_model.cc b/ash/common/shelf/shelf_model.cc index e5254194..a6844758 100644 --- a/ash/common/shelf/shelf_model.cc +++ b/ash/common/shelf/shelf_model.cc
@@ -43,7 +43,7 @@ } // namespace -ShelfModel::ShelfModel() : next_id_(1), status_(STATUS_NORMAL) {} +ShelfModel::ShelfModel() : next_id_(1) {} ShelfModel::~ShelfModel() {}
diff --git a/ash/common/shelf/shelf_model.h b/ash/common/shelf/shelf_model.h index 112f0b42..a5f61e80 100644 --- a/ash/common/shelf/shelf_model.h +++ b/ash/common/shelf/shelf_model.h
@@ -18,16 +18,9 @@ class ShelfItemDelegate; class ShelfModelObserver; -// Model used for shelf items. Owns ShelfItemDelegates, but does not create -// them. +// Model used for shelf items. Owns ShelfItemDelegates but does not create them. class ASH_EXPORT ShelfModel { public: - enum Status { - STATUS_NORMAL, - // A status that indicates apps are syncing/loading. - STATUS_LOADING, - }; - ShelfModel(); ~ShelfModel(); @@ -82,9 +75,6 @@ const ShelfItems& items() const { return items_; } int item_count() const { return static_cast<int>(items_.size()); } - void set_status(Status status) { status_ = status; } - Status status() const { return status_; } - // Set |item_delegate| for |id| and takes ownership. void SetShelfItemDelegate(ShelfID id, std::unique_ptr<ShelfItemDelegate> item_delegate); @@ -108,7 +98,6 @@ ShelfID next_id_; ShelfItems items_; - Status status_; base::ObserverList<ShelfModelObserver> observers_; std::map<ShelfID, std::unique_ptr<ShelfItemDelegate>>
diff --git a/ash/common/shelf/shelf_view.cc b/ash/common/shelf/shelf_view.cc index 5a6bfaa..48458db 100644 --- a/ash/common/shelf/shelf_view.cc +++ b/ash/common/shelf/shelf_view.cc
@@ -527,9 +527,7 @@ base::string16 ShelfView::GetTitleForView(const views::View* view) const { const ShelfItem* item = ShelfItemForView(view); - if (!item || !model_->GetShelfItemDelegate(item->id)) - return base::string16(); - return model_->GetShelfItemDelegate(item->id)->GetTitle(); + return item ? item->title : base::string16(); } gfx::Rect ShelfView::GetVisibleItemsBoundsInScreen() {
diff --git a/ash/common/shelf/shelf_window_watcher.cc b/ash/common/shelf/shelf_window_watcher.cc index 0fd654b..accb7ce 100644 --- a/ash/common/shelf/shelf_window_watcher.cc +++ b/ash/common/shelf/shelf_window_watcher.cc
@@ -39,6 +39,8 @@ if (item->image.isNull()) item->image = window->GetWindowIcon(); + item->title = window->GetTitle(); + // Do not show tooltips for visible attached app panel windows. item->shows_tooltip = item->type != TYPE_APP_PANEL || !window->IsVisible() || @@ -109,6 +111,11 @@ window_watcher_->OnUserWindowPropertyChanged(window); } +void ShelfWindowWatcher::UserWindowObserver::OnWindowTitleChanged( + WmWindow* window) { + window_watcher_->OnUserWindowPropertyChanged(window); +} + //////////////////////////////////////////////////////////////////////////////// ShelfWindowWatcher::ShelfWindowWatcher(ShelfModel* model)
diff --git a/ash/common/shelf/shelf_window_watcher.h b/ash/common/shelf/shelf_window_watcher.h index c523bf15..59564a1 100644 --- a/ash/common/shelf/shelf_window_watcher.h +++ b/ash/common/shelf/shelf_window_watcher.h
@@ -61,6 +61,7 @@ WmWindowProperty property) override; void OnWindowDestroying(WmWindow* window) override; void OnWindowVisibilityChanged(WmWindow* window, bool visible) override; + void OnWindowTitleChanged(WmWindow* window) override; ShelfWindowWatcher* window_watcher_;
diff --git a/ash/common/shelf/shelf_window_watcher_item_delegate.cc b/ash/common/shelf/shelf_window_watcher_item_delegate.cc index 0738ce5..303ef6a 100644 --- a/ash/common/shelf/shelf_window_watcher_item_delegate.cc +++ b/ash/common/shelf/shelf_window_watcher_item_delegate.cc
@@ -55,10 +55,6 @@ return kExistingWindowActivated; } -base::string16 ShelfWindowWatcherItemDelegate::GetTitle() { - return window_->GetTitle(); -} - ShelfMenuModel* ShelfWindowWatcherItemDelegate::CreateApplicationMenu( int event_flags) { return nullptr;
diff --git a/ash/common/shelf/shelf_window_watcher_item_delegate.h b/ash/common/shelf/shelf_window_watcher_item_delegate.h index 3dab83b3..0591a7dd 100644 --- a/ash/common/shelf/shelf_window_watcher_item_delegate.h +++ b/ash/common/shelf/shelf_window_watcher_item_delegate.h
@@ -23,7 +23,6 @@ // ShelfItemDelegate overrides: ShelfItemDelegate::PerformedAction ItemSelected( const ui::Event& event) override; - base::string16 GetTitle() override; ShelfMenuModel* CreateApplicationMenu(int event_flags) override; void Close() override;
diff --git a/ash/common/system/tray/tray_popup_header_button.cc b/ash/common/system/tray/tray_popup_header_button.cc index 804fcb8..576ec92e 100644 --- a/ash/common/system/tray/tray_popup_header_button.cc +++ b/ash/common/system/tray/tray_popup_header_button.cc
@@ -44,7 +44,7 @@ SetToggledImage(views::Button::STATE_NORMAL, bundle.GetImageNamed(disabled_resource_id).ToImageSkia()); SetImage(views::Button::STATE_HOVERED, - bundle.GetImageNamed(enabled_resource_id_hover).ToImageSkia()); + *bundle.GetImageNamed(enabled_resource_id_hover).ToImageSkia()); SetToggledImage( views::Button::STATE_HOVERED, bundle.GetImageNamed(disabled_resource_id_hover).ToImageSkia()); @@ -74,7 +74,7 @@ void TrayPopupHeaderButton::Initialize(const gfx::ImageSkia& icon, int accessible_name_id) { ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); - SetImage(views::Button::STATE_NORMAL, &icon); + SetImage(views::Button::STATE_NORMAL, icon); SetImageAlignment(views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE); SetAccessibleName(bundle.GetLocalizedString(accessible_name_id));
diff --git a/ash/common/test/test_shelf_item_delegate.cc b/ash/common/test/test_shelf_item_delegate.cc index f4ee11245..a9a6a96 100644 --- a/ash/common/test/test_shelf_item_delegate.cc +++ b/ash/common/test/test_shelf_item_delegate.cc
@@ -26,10 +26,6 @@ return kNoAction; } -base::string16 TestShelfItemDelegate::GetTitle() { - return window_ ? window_->GetTitle() : base::string16(); -} - ShelfMenuModel* TestShelfItemDelegate::CreateApplicationMenu(int event_flags) { return nullptr; }
diff --git a/ash/common/test/test_shelf_item_delegate.h b/ash/common/test/test_shelf_item_delegate.h index e5c88339..9336aa79 100644 --- a/ash/common/test/test_shelf_item_delegate.h +++ b/ash/common/test/test_shelf_item_delegate.h
@@ -24,7 +24,6 @@ // ShelfItemDelegate: ShelfItemDelegate::PerformedAction ItemSelected( const ui::Event& event) override; - base::string16 GetTitle() override; ShelfMenuModel* CreateApplicationMenu(int event_flags) override; void Close() override;
diff --git a/ash/common/wm/overview/window_selector_item.cc b/ash/common/wm/overview/window_selector_item.cc index 182beb5..647b739 100644 --- a/ash/common/wm/overview/window_selector_item.cc +++ b/ash/common/wm/overview/window_selector_item.cc
@@ -23,6 +23,7 @@ #include "ash/common/wm_window.h" #include "ash/common/wm_window_property.h" #include "ash/public/cpp/shell_window_ids.h" +#include "ash/resources/vector_icons/vector_icons.h" #include "base/auto_reset.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -37,7 +38,6 @@ #include "ui/gfx/geometry/safe_integer_conversions.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/transform_util.h" -#include "ui/gfx/vector_icons_public.h" #include "ui/strings/grit/ui_strings.h" #include "ui/views/background.h" #include "ui/views/border.h" @@ -130,9 +130,8 @@ WindowSelectorItem::OverviewCloseButton::OverviewCloseButton( views::ButtonListener* listener) : views::ImageButton(listener) { - icon_image_ = gfx::CreateVectorIcon(gfx::VectorIconId::WINDOW_CONTROL_CLOSE, - kCloseButtonColor); - SetImage(views::CustomButton::STATE_NORMAL, &icon_image_); + SetImage(views::CustomButton::STATE_NORMAL, + gfx::CreateVectorIcon(kWindowControlCloseIcon, kCloseButtonColor)); SetImageAlignment(views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE); SetMinimumImageSize(gfx::Size(kHeaderHeight, kHeaderHeight));
diff --git a/ash/common/wm/overview/window_selector_item.h b/ash/common/wm/overview/window_selector_item.h index f2ff9df..65b4293 100644 --- a/ash/common/wm/overview/window_selector_item.h +++ b/ash/common/wm/overview/window_selector_item.h
@@ -75,8 +75,6 @@ void ResetListener() { listener_ = nullptr; } private: - gfx::ImageSkia icon_image_; - DISALLOW_COPY_AND_ASSIGN(OverviewCloseButton); };
diff --git a/ash/frame/caption_buttons/frame_size_button_unittest.cc b/ash/frame/caption_buttons/frame_size_button_unittest.cc index 0de43d49..a14c83d6 100644 --- a/ash/frame/caption_buttons/frame_size_button_unittest.cc +++ b/ash/frame/caption_buttons/frame_size_button_unittest.cc
@@ -8,6 +8,7 @@ #include "ash/common/frame/caption_buttons/frame_caption_button.h" #include "ash/common/frame/caption_buttons/frame_caption_button_container_view.h" #include "ash/common/wm/window_state.h" +#include "ash/resources/vector_icons/vector_icons.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/wm/window_state_aura.h" @@ -18,7 +19,6 @@ #include "ui/display/screen.h" #include "ui/events/gesture_detection/gesture_configuration.h" #include "ui/events/test/event_generator.h" -#include "ui/gfx/vector_icons_public.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -65,8 +65,7 @@ GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON)); for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) { caption_button_container_->SetButtonImage( - static_cast<CaptionButtonIcon>(icon), - gfx::VectorIconId::WINDOW_CONTROL_CLOSE); + static_cast<CaptionButtonIcon>(icon), kWindowControlCloseIcon); } AddChildView(caption_button_container_);
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn index 9eddf84..14b065bb 100644 --- a/ash/resources/vector_icons/BUILD.gn +++ b/ash/resources/vector_icons/BUILD.gn
@@ -206,6 +206,20 @@ "system_tray_update.icon", "system_tray_volume_mute.1x.icon", "system_tray_volume_mute.icon", + "window_control_back.1x.icon", + "window_control_back.icon", + "window_control_close.1x.icon", + "window_control_close.icon", + "window_control_left_snapped.1x.icon", + "window_control_left_snapped.icon", + "window_control_maximize.1x.icon", + "window_control_maximize.icon", + "window_control_minimize.1x.icon", + "window_control_minimize.icon", + "window_control_restore.1x.icon", + "window_control_restore.icon", + "window_control_right_snapped.1x.icon", + "window_control_right_snapped.icon", ] output_cc = "$target_gen_dir/vector_icons.cc"
diff --git a/ui/gfx/vector_icons/window_control_back.1x.icon b/ash/resources/vector_icons/window_control_back.1x.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_back.1x.icon rename to ash/resources/vector_icons/window_control_back.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_back.icon b/ash/resources/vector_icons/window_control_back.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_back.icon rename to ash/resources/vector_icons/window_control_back.icon
diff --git a/ui/gfx/vector_icons/window_control_close.1x.icon b/ash/resources/vector_icons/window_control_close.1x.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_close.1x.icon rename to ash/resources/vector_icons/window_control_close.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_close.icon b/ash/resources/vector_icons/window_control_close.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_close.icon rename to ash/resources/vector_icons/window_control_close.icon
diff --git a/ui/gfx/vector_icons/window_control_left_snapped.1x.icon b/ash/resources/vector_icons/window_control_left_snapped.1x.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_left_snapped.1x.icon rename to ash/resources/vector_icons/window_control_left_snapped.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_left_snapped.icon b/ash/resources/vector_icons/window_control_left_snapped.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_left_snapped.icon rename to ash/resources/vector_icons/window_control_left_snapped.icon
diff --git a/ui/gfx/vector_icons/window_control_maximize.1x.icon b/ash/resources/vector_icons/window_control_maximize.1x.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_maximize.1x.icon rename to ash/resources/vector_icons/window_control_maximize.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_maximize.icon b/ash/resources/vector_icons/window_control_maximize.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_maximize.icon rename to ash/resources/vector_icons/window_control_maximize.icon
diff --git a/ui/gfx/vector_icons/window_control_minimize.1x.icon b/ash/resources/vector_icons/window_control_minimize.1x.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_minimize.1x.icon rename to ash/resources/vector_icons/window_control_minimize.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_minimize.icon b/ash/resources/vector_icons/window_control_minimize.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_minimize.icon rename to ash/resources/vector_icons/window_control_minimize.icon
diff --git a/ui/gfx/vector_icons/window_control_restore.1x.icon b/ash/resources/vector_icons/window_control_restore.1x.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_restore.1x.icon rename to ash/resources/vector_icons/window_control_restore.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_restore.icon b/ash/resources/vector_icons/window_control_restore.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_restore.icon rename to ash/resources/vector_icons/window_control_restore.icon
diff --git a/ui/gfx/vector_icons/window_control_right_snapped.1x.icon b/ash/resources/vector_icons/window_control_right_snapped.1x.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_right_snapped.1x.icon rename to ash/resources/vector_icons/window_control_right_snapped.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_right_snapped.icon b/ash/resources/vector_icons/window_control_right_snapped.icon similarity index 100% rename from ui/gfx/vector_icons/window_control_right_snapped.icon rename to ash/resources/vector_icons/window_control_right_snapped.icon
diff --git a/ash/shell/window_watcher.cc b/ash/shell/window_watcher.cc index 1ca47e1..99ed48b 100644 --- a/ash/shell/window_watcher.cc +++ b/ash/shell/window_watcher.cc
@@ -110,6 +110,7 @@ image_count == 1 ? 255 : 0, image_count == 2 ? 255 : 0); image_count = (image_count + 1) % 3; item.image = gfx::ImageSkia(gfx::ImageSkiaRep(icon_bitmap, 1.0f)); + item.title = new_window->GetTitle(); model->Add(item);
diff --git a/ash/shell/window_watcher_shelf_item_delegate.cc b/ash/shell/window_watcher_shelf_item_delegate.cc index 6c45e097..d50371bb 100644 --- a/ash/shell/window_watcher_shelf_item_delegate.cc +++ b/ash/shell/window_watcher_shelf_item_delegate.cc
@@ -31,10 +31,6 @@ return kExistingWindowActivated; } -base::string16 WindowWatcherShelfItemDelegate::GetTitle() { - return watcher_->GetWindowByID(id_)->GetTitle(); -} - ShelfMenuModel* WindowWatcherShelfItemDelegate::CreateApplicationMenu( int event_flags) { return nullptr;
diff --git a/ash/shell/window_watcher_shelf_item_delegate.h b/ash/shell/window_watcher_shelf_item_delegate.h index cff7ca2..51925b9 100644 --- a/ash/shell/window_watcher_shelf_item_delegate.h +++ b/ash/shell/window_watcher_shelf_item_delegate.h
@@ -24,7 +24,6 @@ // ShelfItemDelegate: ShelfItemDelegate::PerformedAction ItemSelected( const ui::Event& event) override; - base::string16 GetTitle() override; ShelfMenuModel* CreateApplicationMenu(int event_flags) override; void Close() override;
diff --git a/base/android/java/src/org/chromium/base/LocaleUtils.java b/base/android/java/src/org/chromium/base/LocaleUtils.java index e0af2e267..2f51455 100644 --- a/base/android/java/src/org/chromium/base/LocaleUtils.java +++ b/base/android/java/src/org/chromium/base/LocaleUtils.java
@@ -31,6 +31,8 @@ private static final Map<String, String> LANGUAGE_MAP_FOR_ANDROID; static { + // A variation of this mapping also exists in: + // build/android/gyp/package_resources.py HashMap<String, String> mapForChromium = new HashMap<>(); mapForChromium.put("iw", "he"); // Hebrew mapForChromium.put("ji", "yi"); // Yiddish
diff --git a/base/test/ios/wait_util.h b/base/test/ios/wait_util.h index d938bd9..99127930 100644 --- a/base/test/ios/wait_util.h +++ b/base/test/ios/wait_util.h
@@ -9,9 +9,6 @@ #include "base/time/time.h" namespace base { - -class MessageLoop; - namespace test { namespace ios { @@ -43,19 +40,6 @@ // elapsed. void SpinRunLoopWithMinDelay(TimeDelta min_delay); -// Deprecated. -// TODO(fdoray): Remove this once call have been removed from ios_internal. -TimeDelta TimeUntilCondition(ProceduralBlock action, - ConditionBlock condition, - MessageLoop* message_loop, - TimeDelta timeout); - -// Deprecated. -// TODO(fdoray): Remove this once call have been removed from ios_internal. -void WaitUntilCondition(ConditionBlock condition, - MessageLoop* message_loop, - TimeDelta timeout); - } // namespace ios } // namespace test } // namespace base
diff --git a/base/test/ios/wait_util.mm b/base/test/ios/wait_util.mm index 61bbb69..39a4115 100644 --- a/base/test/ios/wait_util.mm +++ b/base/test/ios/wait_util.mm
@@ -48,7 +48,7 @@ } void WaitUntilCondition(ConditionBlock condition) { - WaitUntilCondition(condition, nullptr, TimeDelta()); + WaitUntilCondition(condition, false, TimeDelta()); } void SpinRunLoopWithMaxDelay(TimeDelta max_delay) { @@ -65,20 +65,6 @@ } } -TimeDelta TimeUntilCondition(ProceduralBlock action, - ConditionBlock condition, - MessageLoop* message_loop, - TimeDelta timeout) { - return TimeUntilCondition(action, condition, message_loop != nullptr, - timeout); -} - -void WaitUntilCondition(ConditionBlock condition, - MessageLoop* message_loop, - TimeDelta timeout) { - WaitUntilCondition(condition, message_loop != nullptr, timeout); -} - } // namespace ios } // namespace test } // namespace base
diff --git a/blimp/client/app/linux/blimp_main.cc b/blimp/client/app/linux/blimp_main.cc index febfbb8..583db11 100644 --- a/blimp/client/app/linux/blimp_main.cc +++ b/blimp/client/app/linux/blimp_main.cc
@@ -63,7 +63,7 @@ return android_fonts_dir; } -SkFontMgr* CreateAndroidFontMgr(std::string android_fonts_dir) { +sk_sp<SkFontMgr> CreateAndroidFontMgr(std::string android_fonts_dir) { SkFontMgr_Android_CustomFonts custom; custom.fSystemFontUse = SkFontMgr_Android_CustomFonts::SystemFontUse::kOnlyCustom;
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py index 82ac496ed..162477c 100755 --- a/build/android/gyp/apkbuilder.py +++ b/build/android/gyp/apkbuilder.py
@@ -161,14 +161,20 @@ def _AddNativeLibraries(out_apk, native_libs, android_abi, uncompress): """Add native libraries to APK.""" + has_crazy_linker = any('android_linker' in os.path.basename(p) + for p in native_libs) for path in native_libs: basename = os.path.basename(path) - apk_path = 'lib/%s/%s' % (android_abi, basename) compress = None - if (uncompress and os.path.splitext(basename)[1] == '.so'): + if (uncompress and os.path.splitext(basename)[1] == '.so' + and 'android_linker' not in basename): compress = False + # Add prefix to prevent android install from extracting upon install. + if has_crazy_linker: + basename = 'crazy.' + basename + apk_path = 'lib/%s/%s' % (android_abi, basename) build_utils.AddToZipHermetic(out_apk, apk_path, src_path=path, @@ -265,8 +271,9 @@ options.uncompress_shared_libraries) for name in sorted(options.native_lib_placeholders): - # Empty libs files are ignored by md5check, but rezip requires them - # to be empty in order to identify them as placeholders. + # Note: Empty libs files are ignored by md5check (can cause issues + # with stale builds when the only change is adding/removing + # placeholders). apk_path = 'lib/%s/%s' % (options.android_abi, name) build_utils.AddToZipHermetic(out_apk, apk_path, data='')
diff --git a/build/android/gyp/finalize_apk.py b/build/android/gyp/finalize_apk.py index 532d001f..ecb5ebfe 100755 --- a/build/android/gyp/finalize_apk.py +++ b/build/android/gyp/finalize_apk.py
@@ -21,32 +21,6 @@ from util import build_utils -def RenameInflateAndAddPageAlignment( - rezip_apk_jar_path, in_zip_file, out_zip_file): - rezip_apk_cmd = [ - 'java', - '-classpath', - rezip_apk_jar_path, - 'RezipApk', - 'renamealign', - in_zip_file, - out_zip_file, - ] - build_utils.CheckOutput(rezip_apk_cmd) - - -def ReorderAndAlignApk(rezip_apk_jar_path, in_zip_file, out_zip_file): - rezip_apk_cmd = [ - 'java', - '-classpath', - rezip_apk_jar_path, - 'RezipApk', - 'reorder', - in_zip_file, - out_zip_file, - ] - build_utils.CheckOutput(rezip_apk_cmd) - def JarSigner(key_path, key_name, key_passwd, unsigned_path, signed_path): shutil.copy(unsigned_path, signed_path) @@ -62,14 +36,15 @@ build_utils.CheckOutput(sign_cmd) -def AlignApk(zipalign_path, package_align, unaligned_path, final_path): +def AlignApk(zipalign_path, unaligned_path, final_path): + # Note -p will page align native libraries (files ending with .so), but + # only those that are stored uncompressed. align_cmd = [ zipalign_path, - '-f' + '-p', + '-f', ] - if package_align: - align_cmd += ['-p'] align_cmd += [ '4', # 4 bytes @@ -85,23 +60,13 @@ parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) - parser.add_option('--rezip-apk-jar-path', - help='Path to the RezipApk jar file.') parser.add_option('--zipalign-path', help='Path to the zipalign tool.') - parser.add_option('--page-align-shared-libraries', - action='store_true', - help='Page align shared libraries.') parser.add_option('--unsigned-apk-path', help='Path to input unsigned APK.') parser.add_option('--final-apk-path', help='Path to output signed and aligned APK.') parser.add_option('--key-path', help='Path to keystore for signing.') parser.add_option('--key-passwd', help='Keystore password') parser.add_option('--key-name', help='Keystore name') - parser.add_option('--stamp', help='Path to touch on success.') - parser.add_option('--load-library-from-zip', type='int', - help='If non-zero, build the APK such that the library can be loaded ' + - 'directly from the zip file using the crazy linker. The library ' + - 'will be renamed, uncompressed and page aligned.') options, _ = parser.parse_args() @@ -110,14 +75,9 @@ options.key_path, ] - if options.load_library_from_zip: - input_paths.append(options.rezip_apk_jar_path) - input_strings = [ - options.load_library_from_zip, options.key_name, options.key_passwd, - options.page_align_shared_libraries, ] build_utils.CallAndWriteDepfileIfStale( @@ -129,57 +89,34 @@ output_paths=[options.final_apk_path]) +def _NormalizeZip(path): + with tempfile.NamedTemporaryFile(suffix='.zip') as hermetic_signed_apk: + with zipfile.ZipFile(path, 'r') as zi: + with zipfile.ZipFile(hermetic_signed_apk, 'w') as zo: + for info in zi.infolist(): + # Ignore 'extended local file headers'. Python doesn't write them + # properly (see https://bugs.python.org/issue1742205) which causes + # zipalign to miscalculate alignment. Since we don't use them except + # for alignment anyway, we write a stripped file here and let + # zipalign add them properly later. eLFHs are controlled by 'general + # purpose bit flag 03' (0x08) so we mask that out. + info.flag_bits = info.flag_bits & 0xF7 + + info.date_time = build_utils.HERMETIC_TIMESTAMP + zo.writestr(info, zi.read(info.filename)) + + shutil.copy(hermetic_signed_apk.name, path) + + def FinalizeApk(options): - with tempfile.NamedTemporaryFile() as signed_apk_path_tmp, \ - tempfile.NamedTemporaryFile() as apk_to_sign_tmp: - - if options.load_library_from_zip: - # We alter the name of the library so that the Android Package Manager - # does not extract it into a separate file. This must be done before - # signing, as the filename is part of the signed manifest. At the same - # time we uncompress the library, which is necessary so that it can be - # loaded directly from the APK. - # Move the library to a page boundary by adding a page alignment file. - apk_to_sign = apk_to_sign_tmp.name - RenameInflateAndAddPageAlignment( - options.rezip_apk_jar_path, options.unsigned_apk_path, apk_to_sign) - else: - apk_to_sign = options.unsigned_apk_path - + with tempfile.NamedTemporaryFile() as signed_apk_path_tmp: signed_apk_path = signed_apk_path_tmp.name JarSigner(options.key_path, options.key_name, options.key_passwd, - apk_to_sign, signed_apk_path) + options.unsigned_apk_path, signed_apk_path) + # Make the newly added signing files hermetic. + _NormalizeZip(signed_apk_path) - # Make the signing files hermetic. - with tempfile.NamedTemporaryFile(suffix='.zip') as hermetic_signed_apk: - with zipfile.ZipFile(signed_apk_path, 'r') as zi: - with zipfile.ZipFile(hermetic_signed_apk, 'w') as zo: - for info in zi.infolist(): - # Ignore 'extended local file headers'. Python doesn't write them - # properly (see https://bugs.python.org/issue1742205) which causes - # zipalign to miscalculate alignment. Since we don't use them except - # for alignment anyway, we write a stripped file here and let - # zipalign add them properly later. eLFHs are controlled by 'general - # purpose bit flag 03' (0x08) so we mask that out. - info.flag_bits = info.flag_bits & 0xF7 - - info.date_time = build_utils.HERMETIC_TIMESTAMP - zo.writestr(info, zi.read(info.filename)) - - shutil.copy(hermetic_signed_apk.name, signed_apk_path) - - if options.load_library_from_zip: - # Reorder the contents of the APK. This re-establishes the canonical - # order which means the library will be back at its page aligned location. - # This step also aligns uncompressed items to 4 bytes. - ReorderAndAlignApk( - options.rezip_apk_jar_path, signed_apk_path, options.final_apk_path) - else: - # Align uncompressed items to 4 bytes - AlignApk(options.zipalign_path, - options.page_align_shared_libraries, - signed_apk_path, - options.final_apk_path) + AlignApk(options.zipalign_path, signed_apk_path, options.final_apk_path) if __name__ == '__main__':
diff --git a/build/android/gyp/package_resources.py b/build/android/gyp/package_resources.py index 53ba92c..e5e91c9 100755 --- a/build/android/gyp/package_resources.py +++ b/build/android/gyp/package_resources.py
@@ -23,6 +23,22 @@ from util import build_utils +# A variation of this lists also exists in: +# //base/android/java/src/org/chromium/base/LocaleUtils.java +_CHROME_TO_ANDROID_LOCALE_MAP = { + 'en-GB': 'en-rGB', + 'en-US': 'en-rUS', + 'es-419': 'es-rUS', + 'fin': 'tl', + 'he': 'iw', + 'id': 'in', + 'pt-PT': 'pt-rPT', + 'pt-BR': 'pt-rBR', + 'yi': 'ji', + 'zh-CN': 'zh-rCN', + 'zh-TW': 'zh-rTW', +} + # List is generated from the chrome_apk.apk_intermediates.ap_ via: # unzip -l $FILE_AP_ | cut -c31- | grep res/draw | cut -d'/' -f 2 | sort \ # | uniq | grep -- -tvdpi- | cut -c10- @@ -113,7 +129,12 @@ help='Enables density splits') parser.add_option('--language-splits', default='[]', - help='GYP list of languages to create splits for') + help='GN list of languages to create splits for') + parser.add_option('--locale-whitelist', + default='[]', + help='GN list of languages to include. All other language ' + 'configs will be stripped out. List may include ' + 'a combination of Android locales or Chrome locales.') parser.add_option('--apk-path', help='Path to output (partial) apk.') @@ -132,9 +153,26 @@ options.resource_zips = build_utils.ParseGnList(options.resource_zips) options.language_splits = build_utils.ParseGnList(options.language_splits) + options.locale_whitelist = build_utils.ParseGnList(options.locale_whitelist) return options +def _ToAaptLocales(locale_whitelist): + """Converts the list of Chrome locales to aapt config locales.""" + ret = set() + for locale in locale_whitelist: + locale = _CHROME_TO_ANDROID_LOCALE_MAP.get(locale, locale) + if locale is None or ('-' in locale and '-r' not in locale): + raise Exception('_CHROME_TO_ANDROID_LOCALE_MAP needs updating.' + ' Found: %s' % locale) + ret.add(locale) + # Always keep non-regional fall-backs. + language = locale.split('-')[0] + ret.add(language) + + return sorted(ret) + + def MoveImagesToNonMdpiFolders(res_root): """Move images from drawable-*-mdpi-* folders to drawable-* folders. @@ -257,6 +295,10 @@ if 'Debug' in options.configuration_name: package_command += ['--debug-mode'] + if options.locale_whitelist: + aapt_locales = _ToAaptLocales(options.locale_whitelist) + package_command += ['-c', ','.join(aapt_locales)] + return package_command
diff --git a/build/android/rezip/BUILD.gn b/build/android/rezip/BUILD.gn deleted file mode 100644 index 1ace37c..0000000 --- a/build/android/rezip/BUILD.gn +++ /dev/null
@@ -1,10 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/android/rules.gni") - -java_library("rezip") { - jar_path = "$root_build_dir/lib.java/rezip_apk.jar" - java_files = [ "RezipApk.java" ] -}
diff --git a/build/android/rezip/RezipApk.java b/build/android/rezip/RezipApk.java deleted file mode 100644 index 43d75447..0000000 --- a/build/android/rezip/RezipApk.java +++ /dev/null
@@ -1,448 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Enumeration; -import java.util.List; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarOutputStream; -import java.util.regex.Pattern; -import java.util.zip.CRC32; - -/** - * Command line tool used to build APKs which support loading the native code library - * directly from the APK file. To construct the APK we rename the native library by - * adding the prefix "crazy." to the filename. This is done to prevent the Android - * Package Manager from extracting the library. The native code must be page aligned - * and uncompressed. The page alignment is implemented by adding a zero filled file - * in front of the the native code library. This tool is designed so that running - * SignApk and/or zipalign on the resulting APK does not break the page alignment. - * This is achieved by outputing the filenames in the same canonical order used - * by SignApk and adding the same alignment fields added by zipalign. - */ -class RezipApk { - // Alignment to use for non-compressed files (must match zipalign). - private static final int ALIGNMENT = 4; - - // Alignment to use for non-compressed *.so files - private static final int LIBRARY_ALIGNMENT = 4096; - - // Files matching this pattern are not copied to the output when adding alignment. - // When reordering and verifying the APK they are copied to the end of the file. - private static Pattern sMetaFilePattern = - Pattern.compile("^(META-INF/((.*)[.](SF|RSA|DSA)|com/android/otacert))|(" - + Pattern.quote(JarFile.MANIFEST_NAME) + ")$"); - - // Pattern for matching a shared library in the APK - private static Pattern sLibraryPattern = Pattern.compile("^lib/[^/]*/lib.*[.]so$"); - // Pattern for match the crazy linker in the APK - private static Pattern sCrazyLinkerPattern = - Pattern.compile("^lib/[^/]*/libchromium_android_linker.so$"); - // Pattern for matching a crazy loaded shared library in the APK - private static Pattern sCrazyLibraryPattern = Pattern.compile("^lib/[^/]*/crazy.lib.*[.]so$"); - - private static boolean isLibraryFilename(String filename) { - return sLibraryPattern.matcher(filename).matches() - && !sCrazyLinkerPattern.matcher(filename).matches(); - } - - private static boolean isCrazyLibraryFilename(String filename) { - return sCrazyLibraryPattern.matcher(filename).matches(); - } - - private static String renameLibraryForCrazyLinker(String filename) { - int lastSlash = filename.lastIndexOf('/'); - // We rename the library, so that the Android Package Manager - // no longer extracts the library. - return filename.substring(0, lastSlash + 1) + "crazy." + filename.substring(lastSlash + 1); - } - - /** - * Wraps another output stream, counting the number of bytes written. - */ - private static class CountingOutputStream extends OutputStream { - private long mCount = 0; - private OutputStream mOut; - - public CountingOutputStream(OutputStream out) { - this.mOut = out; - } - - /** Returns the number of bytes written. */ - public long getCount() { - return mCount; - } - - @Override public void write(byte[] b, int off, int len) throws IOException { - mOut.write(b, off, len); - mCount += len; - } - - @Override public void write(int b) throws IOException { - mOut.write(b); - mCount++; - } - - @Override public void close() throws IOException { - mOut.close(); - } - - @Override public void flush() throws IOException { - mOut.flush(); - } - } - - private static String outputName(JarEntry entry, boolean rename) { - String inName = entry.getName(); - if (rename && entry.getSize() > 0 && isLibraryFilename(inName)) { - return renameLibraryForCrazyLinker(inName); - } - return inName; - } - - /** - * Comparator used to sort jar entries from the input file. - * Sorting is done based on the output filename (which maybe renamed). - * Filenames are in natural string order, except that filenames matching - * the meta-file pattern are always after other files. This is so the manifest - * and signature are at the end of the file after any alignment file. - */ - private static class EntryComparator implements Comparator<JarEntry> { - private boolean mRename; - - public EntryComparator(boolean rename) { - mRename = rename; - } - - @Override - public int compare(JarEntry j1, JarEntry j2) { - String o1 = outputName(j1, mRename); - String o2 = outputName(j2, mRename); - boolean o1Matches = sMetaFilePattern.matcher(o1).matches(); - boolean o2Matches = sMetaFilePattern.matcher(o2).matches(); - if (o1Matches != o2Matches) { - return o1Matches ? 1 : -1; - } else { - return o1.compareTo(o2); - } - } - } - - // Build an ordered list of jar entries. The jar entries from the input are - // sorted based on the output filenames (which maybe renamed). If |omitMetaFiles| - // is true do not include the jar entries for the META-INF files. - // Entries are ordered in the deterministic order used by SignApk. - private static List<JarEntry> getOutputFileOrderEntries( - JarFile jar, boolean omitMetaFiles, boolean rename) { - List<JarEntry> entries = new ArrayList<JarEntry>(); - for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) { - JarEntry entry = e.nextElement(); - if (entry.isDirectory()) { - continue; - } - if (omitMetaFiles && sMetaFilePattern.matcher(entry.getName()).matches()) { - continue; - } - entries.add(entry); - } - - // We sort the input entries by name. When present META-INF files - // are sorted to the end. - Collections.sort(entries, new EntryComparator(rename)); - return entries; - } - - /** - * Add a zero filled alignment file at this point in the zip file, - * The added file will be added before |name| and after |prevName|. - * The size of the alignment file is such that the location of the - * file |name| will be on a LIBRARY_ALIGNMENT boundary. - * - * Note this arrangement is devised so that running SignApk and/or zipalign on the resulting - * file will not alter the alignment. - * - * @param offset number of bytes into the output file at this point. - * @param timestamp time in millis since the epoch to include in the header. - * @param name the name of the library filename. - * @param prevName the name of the previous file in the archive (or null). - * @param out jar output stream to write the alignment file to. - * - * @throws IOException if the output file can not be written. - */ - private static void addAlignmentFile( - long offset, long timestamp, String name, String prevName, - JarOutputStream out) throws IOException { - - // Compute the start and alignment of the library, as if it was next. - int headerSize = JarFile.LOCHDR + name.length(); - long libOffset = offset + headerSize; - int libNeeded = LIBRARY_ALIGNMENT - (int) (libOffset % LIBRARY_ALIGNMENT); - if (libNeeded == LIBRARY_ALIGNMENT) { - // Already aligned, no need to added alignment file. - return; - } - - // Check that there is not another file between the library and the - // alignment file. - String alignName = name.substring(0, name.length() - 2) + "align"; - if (prevName != null && prevName.compareTo(alignName) >= 0) { - throw new UnsupportedOperationException( - "Unable to insert alignment file, because there is " - + "another file in front of the file to be aligned. " - + "Other file: " + prevName + " Alignment file: " + alignName - + " file: " + name); - } - - // Compute the size of the alignment file header. - headerSize = JarFile.LOCHDR + alignName.length(); - // We are going to add an alignment file of type STORED. This file - // will itself induce a zipalign alignment adjustment. - int extraNeeded = - (ALIGNMENT - (int) ((offset + headerSize) % ALIGNMENT)) % ALIGNMENT; - headerSize += extraNeeded; - - if (libNeeded < headerSize + 1) { - // The header was bigger than the alignment that we need, add another page. - libNeeded += LIBRARY_ALIGNMENT; - } - // Compute the size of the alignment file. - libNeeded -= headerSize; - - // Build the header for the alignment file. - byte[] zeroBuffer = new byte[libNeeded]; - JarEntry alignEntry = new JarEntry(alignName); - alignEntry.setMethod(JarEntry.STORED); - alignEntry.setSize(libNeeded); - alignEntry.setTime(timestamp); - CRC32 crc = new CRC32(); - crc.update(zeroBuffer); - alignEntry.setCrc(crc.getValue()); - - if (extraNeeded != 0) { - alignEntry.setExtra(new byte[extraNeeded]); - } - - // Output the alignment file. - out.putNextEntry(alignEntry); - out.write(zeroBuffer); - out.closeEntry(); - out.flush(); - } - - // Make a JarEntry for the output file which corresponds to the input - // file. The output file will be called |name|. The output file will always - // be uncompressed (STORED). If the input is not STORED it is necessary to inflate - // it to compute the CRC and size of the output entry. - private static JarEntry makeStoredEntry(String name, JarEntry inEntry, JarFile in) - throws IOException { - JarEntry outEntry = new JarEntry(name); - outEntry.setMethod(JarEntry.STORED); - - if (inEntry.getMethod() == JarEntry.STORED) { - outEntry.setCrc(inEntry.getCrc()); - outEntry.setSize(inEntry.getSize()); - } else { - // We are inflating the file. We need to compute the CRC and size. - byte[] buffer = new byte[4096]; - CRC32 crc = new CRC32(); - int size = 0; - int num; - InputStream data = in.getInputStream(inEntry); - while ((num = data.read(buffer)) > 0) { - crc.update(buffer, 0, num); - size += num; - } - data.close(); - outEntry.setCrc(crc.getValue()); - outEntry.setSize(size); - } - return outEntry; - } - - /** - * Copy the contents of the input APK file to the output APK file. If |rename| is - * true then non-empty libraries (*.so) in the input will be renamed by prefixing - * "crazy.". This is done to prevent the Android Package Manager extracting the - * library. Note the crazy linker itself is not renamed, for bootstrapping reasons. - * Empty libraries are not renamed (they are in the APK to workaround a bug where - * the Android Package Manager fails to delete old versions when upgrading). - * There must be exactly one "crazy" library in the output stream. The "crazy" - * library will be uncompressed and page aligned in the output stream. Page - * alignment is implemented by adding a zero filled file, regular alignment is - * implemented by adding a zero filled extra field to the zip file header. If - * |addAlignment| is true a page alignment file is added, otherwise the "crazy" - * library must already be page aligned. Care is taken so that the output is generated - * in the same way as SignApk. This is important so that running SignApk and - * zipalign on the output does not break the page alignment. The archive may not - * contain a "*.apk" as SignApk has special nested signing logic that we do not - * support. - * - * @param in The input APK File. - * @param out The output APK stream. - * @param countOut Counting output stream (to measure the current offset). - * @param addAlignment Whether to add the alignment file or just check. - * @param rename Whether to rename libraries to be "crazy". - * - * @throws IOException if the output file can not be written. - */ - private static void rezip( - JarFile in, JarOutputStream out, CountingOutputStream countOut, - boolean addAlignment, boolean rename) throws IOException { - - List<JarEntry> entries = getOutputFileOrderEntries(in, addAlignment, rename); - long timestamp = System.currentTimeMillis(); - byte[] buffer = new byte[4096]; - boolean firstEntry = true; - String prevName = null; - int numCrazy = 0; - for (JarEntry inEntry : entries) { - // Rename files, if specied. - String name = outputName(inEntry, rename); - if (name.endsWith(".apk")) { - throw new UnsupportedOperationException( - "Nested APKs are not supported: " + name); - } - - // Build the header. - JarEntry outEntry = null; - boolean isCrazy = isCrazyLibraryFilename(name); - if (isCrazy) { - // "crazy" libraries are alway output uncompressed (STORED). - outEntry = makeStoredEntry(name, inEntry, in); - numCrazy++; - if (numCrazy > 1) { - throw new UnsupportedOperationException( - "Found more than one library\n" - + "Multiple libraries are not supported for APKs that use " - + "'load_library_from_zip'.\n" - + "See crbug/388223.\n" - + "Note, check that your build is clean.\n" - + "An unclean build can incorrectly incorporate old " - + "libraries in the APK."); - } - } else if (inEntry.getMethod() == JarEntry.STORED) { - // Preserve the STORED method of the input entry. - outEntry = new JarEntry(inEntry); - outEntry.setExtra(null); - } else { - // Create a new entry so that the compressed len is recomputed. - outEntry = new JarEntry(name); - } - outEntry.setTime(timestamp); - - // Compute and add alignment - long offset = countOut.getCount(); - if (firstEntry) { - // The first entry in a jar file has an extra field of - // four bytes that you can't get rid of; any extra - // data you specify in the JarEntry is appended to - // these forced four bytes. This is JAR_MAGIC in - // JarOutputStream; the bytes are 0xfeca0000. - firstEntry = false; - offset += 4; - } - if (outEntry.getMethod() == JarEntry.STORED) { - if (isCrazy) { - if (addAlignment) { - addAlignmentFile(offset, timestamp, name, prevName, out); - } - // We check that we did indeed get to a page boundary. - offset = countOut.getCount() + JarFile.LOCHDR + name.length(); - if ((offset % LIBRARY_ALIGNMENT) != 0) { - throw new AssertionError( - "Library was not page aligned when verifying page alignment. " - + "Library name: " + name + " Expected alignment: " - + LIBRARY_ALIGNMENT + "Offset: " + offset + " Error: " - + (offset % LIBRARY_ALIGNMENT)); - } - } else { - // This is equivalent to zipalign. - offset += JarFile.LOCHDR + name.length(); - int needed = (ALIGNMENT - (int) (offset % ALIGNMENT)) % ALIGNMENT; - if (needed != 0) { - outEntry.setExtra(new byte[needed]); - } - } - } - out.putNextEntry(outEntry); - - // Copy the data from the input to the output - int num; - InputStream data = in.getInputStream(inEntry); - while ((num = data.read(buffer)) > 0) { - out.write(buffer, 0, num); - } - data.close(); - out.closeEntry(); - out.flush(); - prevName = name; - } - if (numCrazy == 0) { - throw new AssertionError("There was no crazy library in the archive"); - } - } - - private static void usage() { - System.err.println("Usage: prealignapk (addalignment|reorder) input.apk output.apk"); - System.err.println("\"crazy\" libraries are always inflated in the output"); - System.err.println( - " renamealign - rename libraries with \"crazy.\" prefix and add alignment file"); - System.err.println(" align - add alignment file"); - System.err.println(" reorder - re-creates canonical ordering and checks alignment"); - System.exit(2); - } - - public static void main(String[] args) throws IOException { - if (args.length != 3) usage(); - - boolean addAlignment = false; - boolean rename = false; - if (args[0].equals("renamealign")) { - // Normal case. Before signing we rename the library and add an alignment file. - addAlignment = true; - rename = true; - } else if (args[0].equals("align")) { - // LGPL compliance case. Before signing, we add an alignment file to a - // reconstructed APK which already contains the "crazy" library. - addAlignment = true; - rename = false; - } else if (args[0].equals("reorder")) { - // Normal case. After jarsigning we write the file in the canonical order and check. - addAlignment = false; - } else { - usage(); - } - - String inputFilename = args[1]; - String outputFilename = args[2]; - - JarFile inputJar = null; - FileOutputStream outputFile = null; - - try { - inputJar = new JarFile(new File(inputFilename), true); - outputFile = new FileOutputStream(outputFilename); - - CountingOutputStream outCount = new CountingOutputStream(outputFile); - JarOutputStream outputJar = new JarOutputStream(outCount); - - // Match the compression level used by SignApk. - outputJar.setLevel(9); - - rezip(inputJar, outputJar, outCount, addAlignment, rename); - outputJar.close(); - } finally { - if (inputJar != null) inputJar.close(); - if (outputFile != null) outputFile.close(); - } - } -}
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index b7a42d3..9b50a705 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -32,7 +32,6 @@ # TODO(agrieve): Rename targets below to match above patterns. "*android_webview/glue:glue", - "//build/android/rezip:rezip", "//chrome/test/android/cast_emulator:cast_emulator", ] @@ -1393,7 +1392,6 @@ # keystore_path: Path to keystore to use for signing. # keystore_name: Key alias to use. # keystore_password: Keystore password. - # rezip_apk: Whether to add crazy-linker alignment. template("finalize_apk") { action(target_name) { deps = [] @@ -1436,20 +1434,6 @@ "--key-passwd", invoker.keystore_password, ] - if (defined(invoker.rezip_apk) && invoker.rezip_apk) { - deps += [ "//build/android/rezip" ] - _rezip_jar_path = "$root_build_dir/lib.java/rezip_apk.jar" - args += [ - "--load-library-from-zip=1", - "--rezip-apk-jar-path", - rebase_path(_rezip_jar_path, root_build_dir), - ] - } - - if (defined(invoker.page_align_shared_libraries) && - invoker.page_align_shared_libraries) { - args += [ "--page-align-shared-libraries" ] - } } } @@ -1608,6 +1592,9 @@ outputs += [ "${invoker.resource_packaged_apk_path}_${_language}" ] } } + if (defined(invoker.aapt_locale_whitelist)) { + args += [ "--locale-whitelist=${invoker.aapt_locale_whitelist}" ] + } if (defined(invoker.extensions_to_not_compress)) { args += [ "--no-compress", @@ -1621,6 +1608,7 @@ package_resources_helper(_package_resources_target_name) { forward_variables_from(invoker, [ + "aapt_locale_whitelist", "alternative_android_sdk_jar", "android_aapt_path", "extensions_to_not_compress", @@ -1669,6 +1657,7 @@ package_resources_helper(_incremental_package_resources_target_name) { forward_variables_from(invoker, [ + "aapt_locale_whitelist", "alternative_android_sdk_jar", "android_aapt_path", "extensions_to_not_compress", @@ -1692,6 +1681,9 @@ "uncompress_shared_libraries", "write_asset_list", ]) + if (!defined(uncompress_shared_libraries)) { + uncompress_shared_libraries = _load_library_from_apk + } deps = _deps + [ ":${_package_resources_target_name}" ] native_libs = _native_libs + _native_libs_even_when_incremental @@ -1712,6 +1704,9 @@ "secondary_native_libs", "uncompress_shared_libraries", ]) + if (!defined(uncompress_shared_libraries)) { + uncompress_shared_libraries = _load_library_from_apk + } _dex_target = "//build/android/incremental_install:bootstrap_java__dex" deps = _incremental_deps + [ ":${_incremental_package_resources_target_name}", @@ -1738,14 +1733,11 @@ _finalize_apk_rule_name = "${target_name}__finalize" finalize_apk(_finalize_apk_rule_name) { - forward_variables_from(invoker, [ "page_align_shared_libraries" ]) - input_apk_path = _packaged_apk_path output_apk_path = _final_apk_path keystore_path = _keystore_path keystore_name = _keystore_name keystore_password = _keystore_password - rezip_apk = _load_library_from_apk public_deps = [ # Generator of the _packaged_apk_path this target takes as input.
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 2a45db4..075c8a77 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1406,6 +1406,8 @@ # proguard_jar_path: The path to proguard.jar you wish to use. If undefined, # the proguard used will be the checked in one in //third_party/proguard. # never_incremental: If true, |incremental_apk_by_default| will be ignored. + # aapt_locale_whitelist: If set, all locales not in this list will be + # stripped from resources.arsc. # # Example # android_apk("foo_apk") { @@ -2007,15 +2009,7 @@ _extra_native_libs_deps = [] assert(_extra_native_libs_deps == []) # Mark as used. _extra_native_libs_even_when_incremental = [] - _extra_native_libs_even_when_incremental_deps = [] - assert(_extra_native_libs_even_when_incremental_deps == []) # Mark as used. if (_native_libs_deps != []) { - # zipalign can't align gdb_server, don't pack gdbserver temporarily. - if (is_debug && (!defined(invoker.page_align_shared_libraries) || - !invoker.page_align_shared_libraries)) { - _extra_native_libs_even_when_incremental = [ android_gdbserver ] - } - if (_use_chromium_linker) { _extra_native_libs = [ "$root_shlib_dir/libchromium_android_linker$shlib_extension" ] @@ -2031,13 +2025,13 @@ create_apk("${_template_name}__create") { forward_variables_from(invoker, [ + "aapt_locale_whitelist", "alternative_android_sdk_jar", "android_aapt_path", "app_as_shared_lib", "deps", "extensions_to_not_compress", "language_splits", - "page_align_shared_libraries", "public_deps", "secondary_native_libs", "shared_resources", @@ -2087,7 +2081,6 @@ _extra_native_libs_even_when_incremental != []) && !_create_abi_split) { deps += _native_libs_deps + _extra_native_libs_deps + - _extra_native_libs_even_when_incremental_deps + [ _native_libs_file_arg_dep ] native_libs_filearg = _native_libs_file_arg native_libs = _extra_native_libs @@ -2148,9 +2141,7 @@ "public_deps", ]) - incremental_deps = - deps + _extra_native_libs_even_when_incremental_deps + - [ ":$_manifest_rule" ] + incremental_deps = deps + [ ":$_manifest_rule" ] deps = [] deps = incremental_deps + _native_libs_deps + _extra_native_libs_deps + [ _native_libs_file_arg_dep ]
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni index 7dad6aa..8611e5a4 100644 --- a/build/config/ios/rules.gni +++ b/build/config/ios/rules.gni
@@ -997,15 +997,53 @@ _has_public_headers = defined(invoker.public_headers) && invoker.public_headers != [] + # Public configs are not propagated across toolchain (see crbug.com/675224) + # so some configs have to be defined for both default_toolchain and all others + # toolchains when performing a fat build. Use "get_label_info" to construct + # the path since they need to be relative to the default_toolchain. + + _default_toolchain_root_out_dir = + get_label_info("$_target_name($default_toolchain)", "root_out_dir") + _default_toolchain_target_gen_dir = + get_label_info("$_target_name($default_toolchain)", "target_gen_dir") + if (_has_public_headers) { _framework_headers_target = _target_name + "_framework_headers" _framework_headers_config = _target_name + "_framework_headers_config" + config(_framework_headers_config) { + # The link settings are inherited from the framework_bundle config. + cflags = [ + "-F", + rebase_path("$_default_toolchain_root_out_dir/.", root_build_dir), + ] + } + _headers_map_config = _target_name + "_headers_map" + _header_map_filename = + "$_default_toolchain_target_gen_dir/$_output_name.headers.hmap" + config(_headers_map_config) { + visibility = [ ":$_target_name" ] + include_dirs = [ _header_map_filename ] + } } _arch_shared_library_source = _target_name + "_arch_shared_library_sources" _arch_shared_library_target = _target_name + "_arch_shared_library" _lipo_shared_library_target = _target_name + "_shared_library" + _link_target_name = _target_name + "+link" + + _framework_public_config = _target_name + "_public_config" + config(_framework_public_config) { + # TODO(sdefresne): should we have a framework_dirs similar to lib_dirs + # and include_dirs to avoid duplicate values on the command-line. + visibility = [ ":$_target_name" ] + ldflags = [ + "-F", + rebase_path("$_default_toolchain_root_out_dir/.", root_build_dir), + ] + lib_dirs = [ root_out_dir ] + libs = [ "$_output_name.framework" ] + } source_set(_arch_shared_library_source) { forward_variables_from(invoker, @@ -1025,8 +1063,8 @@ if (_has_public_headers) { configs += [ - ":$_framework_headers_config($default_toolchain)", - ":$_headers_map_config($default_toolchain)", + ":$_framework_headers_config", + ":$_headers_map_config", ] if (!defined(deps)) { @@ -1097,15 +1135,24 @@ ] } - group(_target_name + "+link") { + group(_link_target_name) { forward_variables_from(invoker, [ + "public_configs", "visibility", "testonly", ]) public_deps = [ - ":$_target_name+link($default_toolchain)", + ":$_link_target_name($default_toolchain)", ] + + if (!defined(public_configs)) { + public_configs = [] + } + public_configs += [ ":$_framework_public_config" ] + if (_has_public_headers) { + public_configs += [ ":$_framework_headers_config" ] + } } if (defined(invoker.bundle_deps)) { @@ -1116,8 +1163,6 @@ _public_headers = invoker.public_headers _framework_root = "$root_out_dir/$_output_name.framework" - _header_map_filename = "$target_gen_dir/$_output_name.headers.hmap" - _compile_headers_map_target = _target_name + "_compile_headers_map" action(_compile_headers_map_target) { visibility = [ ":$_framework_headers_target" ] @@ -1165,11 +1210,6 @@ ] } - config(_headers_map_config) { - visibility = [ ":$_target_name" ] - include_dirs = [ _header_map_filename ] - } - group(_framework_headers_target) { deps = [ ":$_compile_headers_map_target", @@ -1177,14 +1217,6 @@ ":$_create_module_map_target", ] } - - config(_framework_headers_config) { - # The link settings are inherited from the framework_bundle config. - cflags = [ - "-F", - rebase_path("$root_out_dir/.", root_build_dir), - ] - } } lipo_binary(_lipo_shared_library_target) { @@ -1200,19 +1232,6 @@ arch_binary_output = _output_name } - _framework_public_config = _target_name + "_public_config" - config(_framework_public_config) { - # TODO(sdefresne): should we have a framework_dirs similar to lib_dirs - # and include_dirs to avoid duplicate values on the command-line. - visibility = [ ":$_target_name" ] - ldflags = [ - "-F", - rebase_path("$root_out_dir/.", root_build_dir), - ] - lib_dirs = [ root_out_dir ] - libs = [ "$_output_name.framework" ] - } - _info_plist_target = _target_name + "_info_plist" _info_plist_bundle = _target_name + "_info_plist_bundle" ios_info_plist(_info_plist_target) { @@ -1265,11 +1284,11 @@ deps += [ ":$_info_plist_bundle" ] } - group(_target_name + "+link") { + group(_link_target_name) { forward_variables_from(invoker, [ - "public_deps", "public_configs", + "public_deps", "testonly", "visibility", ]) @@ -1277,11 +1296,11 @@ public_deps = [] } public_deps += [ ":$_target_name" ] + if (!defined(public_configs)) { public_configs = [] } public_configs += [ ":$_framework_public_config" ] - if (_has_public_headers) { public_configs += [ ":$_framework_headers_config" ] }
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni index d964493..0252503c 100644 --- a/build/config/sanitizers/sanitizers.gni +++ b/build/config/sanitizers/sanitizers.gni
@@ -55,7 +55,7 @@ # # TODO(pcc): Remove this flag if/when CFI is enabled in all official builds. is_cfi = target_os == "linux" && !is_chromeos && target_cpu == "x64" && - is_chrome_branded && is_official_build && allow_posix_link_time_opt + is_official_build && allow_posix_link_time_opt # Enable checks for bad casts: derived cast and unrelated cast. # TODO(krasin): remove this, when we're ready to add these checks by default.
diff --git a/build/linux/sysroot_scripts/packagelist.precise.amd64 b/build/linux/sysroot_scripts/packagelist.precise.amd64 index ccb2973..9bf1deb 100644 --- a/build/linux/sysroot_scripts/packagelist.precise.amd64 +++ b/build/linux/sysroot_scripts/packagelist.precise.amd64
@@ -125,7 +125,7 @@ main/libx/libxtst/libxtst6_1.2.0-4ubuntu0.1_amd64.deb main/libx/libxtst/libxtst-dev_1.2.0-4ubuntu0.1_amd64.deb main/libx/libxxf86vm/libxxf86vm1_1.1.1-2ubuntu0.1_amd64.deb -main/l/linux/linux-libc-dev_3.2.0-119.162_amd64.deb +main/l/linux/linux-libc-dev_3.2.0-120.163_amd64.deb main/m/mesa/libegl1-mesa_8.0.4-0ubuntu0.7_amd64.deb main/m/mesa/libegl1-mesa-dev_8.0.4-0ubuntu0.7_amd64.deb main/m/mesa/libegl1-mesa-drivers_8.0.4-0ubuntu0.7_amd64.deb @@ -135,8 +135,8 @@ main/m/mesa/mesa-common-dev_8.0.4-0ubuntu0.7_amd64.deb main/n/nspr/libnspr4_4.12-0ubuntu0.12.04.1_amd64.deb main/n/nspr/libnspr4-dev_4.12-0ubuntu0.12.04.1_amd64.deb -main/n/nss/libnss3_3.23-0ubuntu0.12.04.1_amd64.deb -main/n/nss/libnss3-dev_3.23-0ubuntu0.12.04.1_amd64.deb +main/n/nss/libnss3_3.26.2-0ubuntu0.12.04.1_amd64.deb +main/n/nss/libnss3-dev_3.26.2-0ubuntu0.12.04.1_amd64.deb main/o/openssl/libssl1.0.0_1.0.1-4ubuntu5.38_amd64.deb main/o/openssl/libssl-dev_1.0.1-4ubuntu5.38_amd64.deb main/o/orbit2/liborbit2_2.14.19-0.1ubuntu1_amd64.deb
diff --git a/build/linux/sysroot_scripts/packagelist.trusty.arm b/build/linux/sysroot_scripts/packagelist.trusty.arm index 7cb20277..1f74a07 100644 --- a/build/linux/sysroot_scripts/packagelist.trusty.arm +++ b/build/linux/sysroot_scripts/packagelist.trusty.arm
@@ -113,15 +113,15 @@ main/libx/libxtst/libxtst6_1.2.2-1_armhf.deb main/libx/libxtst/libxtst-dev_1.2.2-1_armhf.deb main/libx/libxxf86vm/libxxf86vm1_1.1.3-1_armhf.deb -main/l/linux/linux-libc-dev_3.13.0-106.153_armhf.deb +main/l/linux/linux-libc-dev_3.13.0-107.154_armhf.deb main/m/mesa/libgl1-mesa-dev_10.1.3-0ubuntu0.6_armhf.deb main/m/mesa/libgl1-mesa-glx_10.1.3-0ubuntu0.6_armhf.deb main/m/mesa/libglapi-mesa_10.1.3-0ubuntu0.6_armhf.deb main/m/mesa/mesa-common-dev_10.1.3-0ubuntu0.6_armhf.deb main/n/nspr/libnspr4_4.12-0ubuntu0.14.04.1_armhf.deb main/n/nspr/libnspr4-dev_4.12-0ubuntu0.14.04.1_armhf.deb -main/n/nss/libnss3_3.23-0ubuntu0.14.04.1_armhf.deb -main/n/nss/libnss3-dev_3.23-0ubuntu0.14.04.1_armhf.deb +main/n/nss/libnss3_3.26.2-0ubuntu0.14.04.3_armhf.deb +main/n/nss/libnss3-dev_3.26.2-0ubuntu0.14.04.3_armhf.deb main/o/openssl/libssl1.0.0_1.0.1f-1ubuntu2.21_armhf.deb main/o/openssl/libssl-dev_1.0.1f-1ubuntu2.21_armhf.deb main/o/orbit2/liborbit2_2.14.19-0.3_armhf.deb
diff --git a/build/linux/sysroot_scripts/sysroots.json b/build/linux/sysroot_scripts/sysroots.json index 336fdca..71abb95 100644 --- a/build/linux/sysroot_scripts/sysroots.json +++ b/build/linux/sysroot_scripts/sysroots.json
@@ -1,67 +1,67 @@ { "jessie_amd64": { - "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd", - "Sha1Sum": "cc59aa719e061602e73a4868aad0ca160844b7fe", + "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928", + "Sha1Sum": "bae4459dbc24b86e92fba57b42e4ae9d540dd556", "SysrootDir": "debian_jessie_amd64-sysroot", "Tarball": "debian_jessie_amd64_sysroot.tgz" }, "jessie_arm": { - "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd", - "Sha1Sum": "96f6f81439955d0c9db49419ff5e4a38d1825b90", + "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928", + "Sha1Sum": "35a4b9eebbe6e495c1c10c668af091e3eded072f", "SysrootDir": "debian_jessie_arm-sysroot", "Tarball": "debian_jessie_arm_sysroot.tgz" }, "jessie_arm64": { - "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd", - "Sha1Sum": "4a9d0ea988e6d816d6abc59b2674f6769b535012", + "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928", + "Sha1Sum": "a28b37b47654cd02c07d0f47f1748c2b5b4b9586", "SysrootDir": "debian_jessie_arm64-sysroot", "Tarball": "debian_jessie_arm64_sysroot.tgz" }, "jessie_i386": { - "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd", - "Sha1Sum": "34b122c9ca411beb957d157d5a6696c9fa93e1db", + "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928", + "Sha1Sum": "c188bab82a303350e8182e289ea4f229f391a8b9", "SysrootDir": "debian_jessie_i386-sysroot", "Tarball": "debian_jessie_i386_sysroot.tgz" }, "jessie_mips": { - "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd", - "Sha1Sum": "25e8df7da22f97f900765094228f77cb72bebd87", + "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928", + "Sha1Sum": "70618d0f516f72ecc3b3eea2ae0a7151a519c0ff", "SysrootDir": "debian_jessie_mips-sysroot", "Tarball": "debian_jessie_mips_sysroot.tgz" }, "precise_amd64": { - "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd", - "Sha1Sum": "42223d9e127dda8d1512160ee96de312ec533556", + "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928", + "Sha1Sum": "6ea6b7f057c8a6d931ed12b1b37a4d5b4155c18e", "SysrootDir": "ubuntu_precise_amd64-sysroot", "Tarball": "ubuntu_precise_amd64_sysroot.tgz" }, "trusty_arm": { - "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd", - "Sha1Sum": "418e471ed3a90ad731ef4c1e7a1ef76518a0f8ac", + "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928", + "Sha1Sum": "0c18bacd8f629d0015dc3eba08509a81b35441d9", "SysrootDir": "ubuntu_trusty_arm-sysroot", "Tarball": "ubuntu_trusty_arm_sysroot.tgz" }, "wheezy_amd64": { - "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd", - "Sha1Sum": "762e8a060f3c3f9e14f76db5ce982a232b55bcbd", + "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928", + "Sha1Sum": "0c2fc59cc7d4dedc66e4467f1872ad3f54789bb6", "SysrootDir": "debian_wheezy_amd64-sysroot", "Tarball": "debian_wheezy_amd64_sysroot.tgz" }, "wheezy_arm": { - "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd", - "Sha1Sum": "2d356d060bf5017cc29d10bef4e09e4e9f65b0f0", + "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928", + "Sha1Sum": "e9e0f4b016ef2f662a0937ee8e3a877f34274d1b", "SysrootDir": "debian_wheezy_arm-sysroot", "Tarball": "debian_wheezy_arm_sysroot.tgz" }, "wheezy_i386": { - "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd", - "Sha1Sum": "9db92d45167d1b1cc78a338f49a84929ee3b1928", + "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928", + "Sha1Sum": "fd53c411577759949e28905fe9c6003458dcafa0", "SysrootDir": "debian_wheezy_i386-sysroot", "Tarball": "debian_wheezy_i386_sysroot.tgz" }, "wheezy_mips": { - "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd", - "Sha1Sum": "1ed22cdb5b560e8c1581ab2c2b4593b4bcb620f3", + "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928", + "Sha1Sum": "e6b283b52892cb8304394a49b6528d1d309880cc", "SysrootDir": "debian_wheezy_mips-sysroot", "Tarball": "debian_wheezy_mips_sysroot.tgz" }
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni index baa4387..b89733b1 100644 --- a/build/toolchain/toolchain.gni +++ b/build/toolchain/toolchain.gni
@@ -13,9 +13,8 @@ # faster, but linking is up to 5-20x slower). # Note: use target_os == "linux" rather than is_linux so that it does not # apply to host_toolchain when target_os="android". - allow_posix_link_time_opt = - target_os == "linux" && !is_chromeos && target_cpu == "x64" && - is_chrome_branded && is_official_build + allow_posix_link_time_opt = target_os == "linux" && !is_chromeos && + target_cpu == "x64" && is_official_build # Set to true to use lld, the LLVM linker. This flag may be used on Windows # with the shipped LLVM toolchain, or on Linux with a self-built top-of-tree
diff --git a/cc/resources/resource_pool.cc b/cc/resources/resource_pool.cc index 8041d8d..61a7ae3 100644 --- a/cc/resources/resource_pool.cc +++ b/cc/resources/resource_pool.cc
@@ -410,7 +410,10 @@ EvictResourcesNotUsedSince(current_time - resource_expiration_delay_); if (unused_resources_.empty() && busy_resources_.empty()) { - // Nothing is evictable. + // If nothing is evictable, we have deleted one (and possibly more) + // resources without any new activity. Flush to ensure these deletions are + // processed. + resource_provider_->FlushPendingDeletions(); return; }
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index 6547109d..6b057143 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc
@@ -847,6 +847,11 @@ resources_.erase(it); } +void ResourceProvider::FlushPendingDeletions() const { + if (auto* gl = ContextGL()) + gl->ShallowFlushCHROMIUM(); +} + ResourceProvider::ResourceType ResourceProvider::GetResourceType( ResourceId id) { return GetResource(id)->type;
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h index a9834cac..7f265b7 100644 --- a/cc/resources/resource_provider.h +++ b/cc/resources/resource_provider.h
@@ -150,6 +150,10 @@ bool read_lock_fences_enabled); void DeleteResource(ResourceId id); + // In the case of GPU resources, we may need to flush the GL context to ensure + // that texture deletions are seen in a timely fashion. This function should + // be called after texture deletions that may happen during an idle state. + void FlushPendingDeletions() const; // Update pixels from image, copying source_rect (in image) to dest_offset (in // the resource).
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 2758476..d7559a11 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -1448,8 +1448,10 @@ const ReturnedResourceArray& resources) { // TODO(piman): We may need to do some validation on this ack before // processing it. - if (resource_provider_) - resource_provider_->ReceiveReturnsFromParent(resources); + if (!resource_provider_) + return; + + resource_provider_->ReceiveReturnsFromParent(resources); // In OOM, we now might be able to release more resources that were held // because they were exported. @@ -1472,11 +1474,8 @@ // If we're not visible, we likely released resources, so we want to // aggressively flush here to make sure those DeleteTextures make it to the // GPU process to free up the memory. - if (compositor_frame_sink_->context_provider() && !visible_) { - compositor_frame_sink_->context_provider() - ->ContextGL() - ->ShallowFlushCHROMIUM(); - } + if (!visible_) + resource_provider_->FlushPendingDeletions(); } void LayerTreeHostImpl::OnDraw(const gfx::Transform& transform,
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 6646b59..01d5f66a 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -4,6 +4,7 @@ import("//base/android/linker/config.gni") import("//build/config/android/rules.gni") +import("//build/config/locales.gni") import("//chrome/common/features.gni") import("//third_party/leakcanary/config.gni") import("channel.gni") @@ -41,6 +42,9 @@ rebase_path("$root_gen_dir/CHROME_VERSION.json", root_out_dir) native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)" native_lib_version_rule = "//build/util:chrome_version_json" + if (!defined(aapt_locale_whitelist)) { + aapt_locale_whitelist = locales - android_chrome_omitted_locales + } if (is_java_debug) { enable_multidex = true @@ -99,12 +103,14 @@ enable_relocation_packing = true extensions_to_not_compress = ".lpak,.pak,.bin,.dat" + # Webview supports all locales (has no omitted ones). + aapt_locale_whitelist = locales + # Incremental install doesn't work for monochrome. See crbug.com/663492. never_incremental = true # Configrations to make android load shared library from APK. uncompress_shared_libraries = true - page_align_shared_libraries = true forward_variables_from(invoker, "*")
diff --git a/chrome/android/java/res/layout/fre_tosanduma.xml b/chrome/android/java/res/layout/fre_tosanduma.xml index 1067829..ba81160 100644 --- a/chrome/android/java/res/layout/fre_tosanduma.xml +++ b/chrome/android/java/res/layout/fre_tosanduma.xml
@@ -93,4 +93,13 @@ android:textSize="@dimen/fre_button_text_size" chrome:buttonColor="@color/light_active_color" chrome:buttonRaised="false"/> -</org.chromium.chrome.browser.firstrun.FirstRunView> \ No newline at end of file + + <!-- Same location as the button; marginButtom is adjusted for the different size. --> + <ProgressBar + android:id="@+id/progress_spinner" + style="@style/Widget.AppCompat.ProgressBar" + android:layout_marginBottom="22dp" + android:layout_gravity="bottom|center_horizontal" + android:layout_width="24dp" + android:layout_height="24dp" /> +</org.chromium.chrome.browser.firstrun.FirstRunView>
diff --git a/chrome/android/java/res/layout/multiline_spinner_item.xml b/chrome/android/java/res/layout/multiline_spinner_item.xml index 1fecc30..26801622 100644 --- a/chrome/android/java/res/layout/multiline_spinner_item.xml +++ b/chrome/android/java/res/layout/multiline_spinner_item.xml
@@ -10,5 +10,4 @@ android:singleLine="false" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingEnd="24dp" android:textAlignment="inherit" />
diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/res/menu/main_menu.xml index 9d87b740..963d4b4 100644 --- a/chrome/android/java/res/menu/main_menu.xml +++ b/chrome/android/java/res/menu/main_menu.xml
@@ -71,8 +71,7 @@ <item android:id="@+id/enter_vr_id" android:title="@string/enter_vr" /> <item android:id="@+id/content_suggestions_standalone_ui" - android:title="@null" - android:visible="false" /> + android:title="@null" /> </group> <!-- Items shown only in the tab switcher -->
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java index 6f574fce..1c1b9cbf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
@@ -192,11 +192,10 @@ // Only display the standalone content suggestions UI if the corresponding feature // is enabled. - if (ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_SUGGESTIONS_STANDALONE_UI)) { - MenuItem item = menu.findItem(R.id.content_suggestions_standalone_ui); - item.setTitle("🔰🆕👌"); - item.setVisible(true); - } + MenuItem item = menu.findItem(R.id.content_suggestions_standalone_ui); + item.setTitle("🔰🆕👌"); + item.setVisible( + ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_SUGGESTIONS_STANDALONE_UI)); } if (isOverviewMenu) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java index 3dbf0792..75fcea60 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
@@ -26,6 +26,7 @@ import org.chromium.content_public.browser.DownloadState; import java.util.List; +import java.util.Set; /** Bridges the user's download history and the UI used to display it. */ public class DownloadHistoryAdapter extends DateDividedAdapter implements DownloadUiObserver { @@ -248,12 +249,21 @@ DownloadHistoryItemWrapper existingWrapper = list.get(index); boolean isUpdated = existingWrapper.replaceItem(item); + // Re-add the file mapping once it finishes downloading. This accounts for the backend + // creating DownloadItems with a null file path, then updating it after the download starts. + // Doing it once after completion instead of at every update is a compromise that prevents + // us from rapidly and repeatedly updating the map with the same info. + if (item.getDownloadInfo().state() == DownloadState.COMPLETE) { + mFilePathsToItemsMap.addItem(existingWrapper); + } + if (item.getDownloadInfo().state() == DownloadState.CANCELLED) { // The old one is being removed. filter(mFilter); } else if (existingWrapper.isVisibleToUser(mFilter)) { if (existingWrapper.getPosition() == TimedItem.INVALID_POSITION) { filter(mFilter); + for (TestObserver observer : mObservers) observer.onDownloadItemUpdated(item); } else if (isUpdated) { notifyItemChanged(existingWrapper.getPosition()); for (TestObserver observer : mObservers) observer.onDownloadItemUpdated(item); @@ -307,7 +317,7 @@ * @param filePath The file path used to retrieve items. * @return DownloadHistoryItemWrappers associated with filePath. */ - List<DownloadHistoryItemWrapper> getItemsForFilePath(String filePath) { + Set<DownloadHistoryItemWrapper> getItemsForFilePath(String filePath) { return mFilePathsToItemsMap.getItemsForFilePath(filePath); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java index afb387ec..0821b57 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
@@ -428,7 +428,7 @@ for (DownloadHistoryItemWrapper item : selectedItems) { if (!filePathsToRemove.contains(item.getFilePath())) { - List<DownloadHistoryItemWrapper> itemsForFilePath = + Set<DownloadHistoryItemWrapper> itemsForFilePath = mHistoryAdapter.getItemsForFilePath(item.getFilePath()); if (itemsForFilePath != null) { itemsToRemove.addAll(itemsForFilePath);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilePathsToDownloadItemsMap.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilePathsToDownloadItemsMap.java index 31f755ebe..9c851ab3d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilePathsToDownloadItemsMap.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilePathsToDownloadItemsMap.java
@@ -4,10 +4,12 @@ package org.chromium.chrome.browser.download.ui; -import java.util.ArrayList; +import android.text.TextUtils; + import java.util.HashMap; -import java.util.List; +import java.util.HashSet; import java.util.Map; +import java.util.Set; /** * Multiple download items may reference the same location on disk. This class maintains a mapping @@ -15,16 +17,17 @@ * TODO(twellington): remove this class after the backend handles duplicate removal. */ class FilePathsToDownloadItemsMap { - private final Map<String, ArrayList<DownloadHistoryItemWrapper>> mMap = new HashMap<>(); + private final Map<String, Set<DownloadHistoryItemWrapper>> mMap = new HashMap<>(); /** - * Adds a DownloadHistoryItemWrapper to the map. This method does not check whether the item - * already exists in the map. + * Adds a DownloadHistoryItemWrapper to the map if it has a valid path. * @param wrapper The item to add to the map. */ void addItem(DownloadHistoryItemWrapper wrapper) { + if (TextUtils.isEmpty(wrapper.getFilePath())) return; + if (!mMap.containsKey(wrapper.getFilePath())) { - mMap.put(wrapper.getFilePath(), new ArrayList<DownloadHistoryItemWrapper>()); + mMap.put(wrapper.getFilePath(), new HashSet<DownloadHistoryItemWrapper>()); } mMap.get(wrapper.getFilePath()).add(wrapper); } @@ -35,21 +38,15 @@ * @param wrapper The item to remove from the map. */ void removeItem(DownloadHistoryItemWrapper wrapper) { - ArrayList<DownloadHistoryItemWrapper> matchingItems = mMap.get(wrapper.getFilePath()); - if (matchingItems == null) return; + Set<DownloadHistoryItemWrapper> matchingItems = mMap.get(wrapper.getFilePath()); + if (matchingItems == null || !matchingItems.contains(wrapper)) return; - for (int i = 0; i < matchingItems.size(); i++) { - if (!matchingItems.get(i).equals(wrapper)) continue; - + if (matchingItems.size() == 1) { // If this is the only DownloadHistoryItemWrapper that references the file path, // remove the file path from the map. - if (matchingItems.size() == 1) { - mMap.remove(wrapper.getFilePath()); - } else { - matchingItems.remove(i); - } - - return; + mMap.remove(wrapper.getFilePath()); + } else { + matchingItems.remove(wrapper); } } @@ -58,7 +55,7 @@ * @param filePath The file path used to retrieve items. * @return DownloadHistoryItemWrappers associated with filePath. */ - List<DownloadHistoryItemWrapper> getItemsForFilePath(String filePath) { + Set<DownloadHistoryItemWrapper> getItemsForFilePath(String filePath) { return mMap.get(filePath); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java index 96908cc..7a1c764 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
@@ -10,21 +10,18 @@ import android.app.PendingIntent.CanceledException; import android.content.Intent; import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import org.chromium.base.ApplicationStatus; import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; -import org.chromium.base.library_loader.ProcessInitException; import org.chromium.base.metrics.CachedMetrics.EnumeratedHistogramSample; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.customtabs.CustomTabsConnection; import org.chromium.chrome.browser.document.ChromeLauncherActivity; -import org.chromium.chrome.browser.init.ChromeBrowserInitializer; -import org.chromium.chrome.browser.init.EmptyBrowserParts; +import org.chromium.chrome.browser.init.AsyncInitializationActivity; import org.chromium.chrome.browser.metrics.UmaUtils; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; import org.chromium.chrome.browser.preferences.datareduction.DataReductionPromoUtils; @@ -35,7 +32,9 @@ import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.Callable; /** @@ -46,7 +45,7 @@ * [Sign-in page] * The activity might be run more than once, e.g. 1) for ToS and sign-in, and 2) for intro. */ -public class FirstRunActivity extends AppCompatActivity implements FirstRunPageDelegate { +public class FirstRunActivity extends AsyncInitializationActivity implements FirstRunPageDelegate { protected static final String TAG = "FirstRunActivity"; // Incoming parameters: @@ -103,6 +102,8 @@ private boolean mPostNativePageSequenceCreated; private boolean mNativeSideIsInitialized; + private Set<FirstRunPage> mPagesToNotifyOfNativeInit; + private boolean mDeferredCompleteFRE; private ProfileDataCache mProfileDataCache; private FirstRunViewPager mPager; @@ -131,12 +132,10 @@ if (mShowWelcomePage) { mPages.add(pageOf(ToSAndUMAFirstRunFragment.class)); mFreProgressStates.add(FRE_PROGRESS_WELCOME_SHOWN); - } else { - // Otherwise, if we're skipping past the welcome page, then init the - // native process and determine if data reduction proxy and signin - // pages should be shown - which both depend on native code. - createPostNativePageSequence(); } + + // Other pages will be created by createPostNativePageSequence() after + // native has been initialized. } private void createPostNativePageSequence() { @@ -144,7 +143,6 @@ // populates |mPages| which needs to be done even even if onNativeInitialized() was // performed in a previous session. if (mPostNativePageSequenceCreated) return; - ensureBrowserProcessInitialized(); mFirstRunFlowSequencer.onNativeInitialized(mFreProperties); boolean notifyAdapter = false; @@ -168,14 +166,11 @@ mPostNativePageSequenceCreated = true; } - // Activity: + // AsyncInitializationActivity: @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ChromeBrowserInitializer.getInstance(this).handlePreNativeStartup(new EmptyBrowserParts()); - + public void setContentView() { + Bundle savedInstanceState = getSavedInstanceState(); if (savedInstanceState != null) { mFreProperties = savedInstanceState; } else if (getIntent() != null) { @@ -225,8 +220,6 @@ mPager.setAdapter(mPagerAdapter); recordFreProgressHistogram(mFreProgressStates.get(0)); - - skipPagesIfNecessary(); } }; mFirstRunFlowSequencer.start(); @@ -235,13 +228,50 @@ } @Override + public void finishNativeInitialization() { + super.finishNativeInitialization(); + mNativeSideIsInitialized = true; + if (mDeferredCompleteFRE) { + completeFirstRunExperience(); + mDeferredCompleteFRE = false; + } else { + createPostNativePageSequence(); + if (mPagesToNotifyOfNativeInit != null) { + for (FirstRunPage page : mPagesToNotifyOfNativeInit) { + page.onNativeInitialized(); + } + } + mPagesToNotifyOfNativeInit = null; + skipPagesIfNecessary(); + } + } + + // Activity: + + @Override + public void onAttachFragment(Fragment fragment) { + if (!(fragment instanceof FirstRunPage)) return; + + FirstRunPage page = (FirstRunPage) fragment; + if (mNativeSideIsInitialized) { + page.onNativeInitialized(); + return; + } + + if (mPagesToNotifyOfNativeInit == null) { + mPagesToNotifyOfNativeInit = new HashSet<FirstRunPage>(); + } + mPagesToNotifyOfNativeInit.add(page); + } + + @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putAll(mFreProperties); } @Override - protected void onPause() { + public void onPause() { super.onPause(); flushPersistentData(); } @@ -253,7 +283,7 @@ } @Override - protected void onStart() { + public void onStart() { super.onStart(); // Since the FRE may be shown before any tab is shown, mark that this is the point at // which Chrome went to foreground. This is needed as otherwise an assert will be hit @@ -325,7 +355,10 @@ @Override public void completeFirstRunExperience() { - ensureBrowserProcessInitialized(); + if (!mNativeSideIsInitialized) { + mDeferredCompleteFRE = true; + return; + } if (!TextUtils.isEmpty(mResultSignInAccountName)) { boolean defaultAccountName = sGlue.isDefaultAccountName(getApplicationContext(), mResultSignInAccountName); @@ -396,13 +429,6 @@ @Override public void acceptTermsOfService(boolean allowCrashUpload) { - // At this point, we're advancing past the first page, which has no native - // dependencies to further pages in the sequence, if any. These require - // native to be initialized and will be added by the call below if needed. - // Additionally, the calls later in this function also require native - // to be initialized. - createPostNativePageSequence(); - // If default is true then it corresponds to opt-out and false corresponds to opt-in. UmaUtils.recordMetricsReportingDefaultOptIn(!DEFAULT_METRICS_AND_CRASH_REPORTING); sGlue.acceptTermsOfService(allowCrashUpload); @@ -504,28 +530,11 @@ while (currentPageIndex < mPagerAdapter.getCount()) { FirstRunPage currentPage = (FirstRunPage) mPagerAdapter.getItem(currentPageIndex); if (!currentPage.shouldSkipPageOnCreate(getApplicationContext())) return; - // If we're advancing to the next page, ensure to init the post native page - // sequence - as every page except the first requires that to be initialized. - // This is a no-op if it has already been done. - createPostNativePageSequence(); if (!jumpToPage(currentPageIndex + 1)) return; currentPageIndex = mPager.getCurrentItem(); } } - private void ensureBrowserProcessInitialized() { - if (mNativeSideIsInitialized) return; - try { - ChromeBrowserInitializer.getInstance(this).handlePostNativeStartup( - false, new EmptyBrowserParts()); - mNativeSideIsInitialized = true; - } catch (ProcessInitException e) { - Log.e(TAG, "Unable to load native library.", e); - abortFirstRunExperience(); - return; - } - } - private void recordFreProgressHistogram(int state) { if (mFreProperties.getBoolean(FirstRunActivity.EXTRA_COMING_FROM_CHROME_ICON)) { sMobileFreProgressMainIntentHistogram.record(state);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPage.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPage.java index 7221c6ff..032b286c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPage.java
@@ -49,6 +49,13 @@ } /** + * @return Whether the page should be re-created when notifyDataSetChanged() fires. + */ + public boolean shouldRecreatePageOnDataChange() { + return true; + } + + /** * @return Passed arguments if any, or saved instance state if any, or an empty bundle. */ protected Bundle getProperties() { @@ -68,4 +75,9 @@ protected void advanceToNextPage() { getPageDelegate().advanceToNextPage(); } -} \ No newline at end of file + + /** + * Notifies this page that native has been initialized. + */ + protected void onNativeInitialized() {} +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java index f42d039..d576c91 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
@@ -64,6 +64,7 @@ /** * Notifies all interested parties that the user has accepted Chrome Terms of Service. + * Must be called only after native has been initialized. * @param allowCrashUpload True if the user allows to upload crash dumps and collect stats. */ void acceptTermsOfService(boolean allowCrashUpload);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPagerAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPagerAdapter.java index 79cb9875..5de1eba4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPagerAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPagerAdapter.java
@@ -68,8 +68,11 @@ @Override public int getItemPosition(Object object) { - // We do not keep track of constructed objects, but we want the pages to be recreated - // on notifyDataSetChanged. Hence, tell the view that it needs to refresh the objects. + // Each page can specify whether it should be re-created or not on a notifyDataSetChanged. + if (object instanceof FirstRunPage) { + FirstRunPage page = (FirstRunPage) object; + return page.shouldRecreatePageOnDataChange() ? POSITION_NONE : POSITION_UNCHANGED; + } return POSITION_NONE; } -} \ No newline at end of file +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java index 889515c..1292e346 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java
@@ -6,7 +6,6 @@ import android.app.Activity; import android.content.Intent; -import android.os.Bundle; import android.text.method.LinkMovementMethod; import android.view.LayoutInflater; import android.view.View; @@ -27,9 +26,8 @@ */ public class LightweightFirstRunActivity extends FirstRunActivity { @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - + public void setContentView() { + super.setContentView(); if (CommandLine.getInstance().hasSwitch(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)) { completeFirstRunExperience(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java index 3c4c4f53..858c51b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java
@@ -31,6 +31,10 @@ private Button mAcceptButton; private CheckBox mSendReportCheckBox; private TextView mTosAndPrivacy; + private View mTitle; + private View mProgressSpinner; + private boolean mNativeInitialized; + private boolean mTriggerAcceptAfterNativeInit; @Override public View onCreateView( @@ -42,6 +46,9 @@ public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + mTitle = view.findViewById(R.id.title); + mProgressSpinner = view.findViewById(R.id.progress_spinner); + mProgressSpinner.setVisibility(View.GONE); mAcceptButton = (Button) view.findViewById(R.id.terms_accept); mSendReportCheckBox = (CheckBox) view.findViewById(R.id.send_report_checkbox); mTosAndPrivacy = (TextView) view.findViewById(R.id.tos_and_privacy); @@ -49,7 +56,7 @@ mAcceptButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - getPageDelegate().acceptTermsOfService(mSendReportCheckBox.isChecked()); + acceptTermsOfService(); } }); @@ -87,12 +94,22 @@ mTosAndPrivacy.setText(SpanApplier.applySpans(getString(R.string.fre_tos_and_privacy), new SpanInfo("<LINK1>", "</LINK1>", clickableTermsSpan), new SpanInfo("<LINK2>", "</LINK2>", clickablePrivacySpan))); + + // If this page should be skipped, hide all the UI elements except for the + // Chrome logo and the spinner. + if (FirstRunStatus.shouldSkipWelcomePage()) { + setSpinnerVisible(true); + } } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); - if (isVisibleToUser && mSendReportCheckBox != null) { + + if (!isVisibleToUser) { + // Restore original enabled & visibility states, in case the user returns to the page. + setSpinnerVisible(false); + } else if (mSendReportCheckBox != null) { // On certain versions of Android, the checkbox will appear unchecked upon revisiting // the page. Force it to the end state of the drawable animation as a work around. // crbug.com/666258 @@ -104,4 +121,42 @@ public boolean shouldSkipPageOnCreate(Context appContext) { return FirstRunStatus.shouldSkipWelcomePage(); } + + @Override + public boolean shouldRecreatePageOnDataChange() { + // Specify that this page shouldn't be re-created on notifyDataSetChanged(), so + // that state like mTriggerAcceptAfterNativeInit can be preserved on the instance + // when native is initialized. + return false; + } + + @Override + protected void onNativeInitialized() { + assert !mNativeInitialized; + + mNativeInitialized = true; + if (mTriggerAcceptAfterNativeInit) acceptTermsOfService(); + } + + private void acceptTermsOfService() { + if (!mNativeInitialized) { + mTriggerAcceptAfterNativeInit = true; + setSpinnerVisible(true); + return; + } + + mTriggerAcceptAfterNativeInit = false; + getPageDelegate().acceptTermsOfService(mSendReportCheckBox.isChecked()); + } + + private void setSpinnerVisible(boolean spinnerVisible) { + // When the progress spinner is visibile, we hide the other UI elements so that + // the user can't interact with them. + int otherElementsVisible = spinnerVisible ? View.INVISIBLE : View.VISIBLE; + mTitle.setVisibility(otherElementsVisible); + mAcceptButton.setVisibility(otherElementsVisible); + mTosAndPrivacy.setVisibility(otherElementsVisible); + mSendReportCheckBox.setVisibility(otherElementsVisible); + mProgressSpinner.setVisibility(spinnerVisible ? View.VISIBLE : View.GONE); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java index 0edbf902..e6af620a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java
@@ -154,11 +154,6 @@ public void onFinishDownloadImage(int id, int httpStatusCode, String imageUrl, List<Bitmap> bitmaps, List<Rect> originalImageSizes) { if (id != mRequestId) return; - if (httpStatusCode < 200 || httpStatusCode >= 300) { - mCallback.onImageDownloaded(null); - clearRequests(); - return; - } Iterator<Bitmap> iterBitmap = bitmaps.iterator(); Iterator<Rect> iterSize = originalImageSizes.iterator();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/BillingAddressAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/BillingAddressAdapter.java index 084e197..be4797f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/BillingAddressAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/BillingAddressAdapter.java
@@ -6,6 +6,7 @@ import android.content.Context; import android.content.res.Resources; +import android.graphics.Rect; import android.graphics.Typeface; import android.view.View; import android.view.ViewGroup; @@ -74,6 +75,19 @@ } @Override + public View getView(int position, View convertView, ViewGroup parent) { + View view = super.getView(position, convertView, parent); + + // Add the left and right padding of the parent's background to the selected item view to + // avoid overlaping the downward triangle. + Rect rect = new Rect(); + parent.getBackground().getPadding(rect); + view.setPadding(view.getPaddingLeft() + rect.left, view.getPaddingTop(), + view.getPaddingRight() + rect.right, view.getPaddingBottom()); + return view; + } + + @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { TextView textView = convertView == null ? null
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java index cd62bc1..792a0ca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java
@@ -226,13 +226,31 @@ } /** - * Refresh the list of available system accounts. + * Refresh the list of available system accounts asynchronously. This is a convenience method + * that will ignore whether the accounts updating was actually successful. */ private void updateAccounts() { - if (mSignedIn || mProfileData == null) return; + updateAccounts(new Callback<Boolean>() { + @Override + public void onResult(Boolean result) {} + }); + } + + /** + * Refresh the list of available system accounts asynchronously. + * + * @param callback Called once the accounts have been refreshed. Boolean indicates whether the + * accounts haven been successfully updated. + */ + private void updateAccounts(final Callback<Boolean> callback) { + if (mSignedIn || mProfileData == null) { + callback.onResult(false); + return; + } if (!checkGooglePlayServicesAvailable()) { setUpSigninButton(false); + callback.onResult(false); return; } @@ -256,6 +274,13 @@ updatingGmsDialog.dismiss(); } mIsGooglePlayServicesOutOfDate = false; + + if (mSignedIn) { + // If sign-in completed in the mean time, return in order to avoid showing the + // wrong state in the UI. + return; + } + mAccountNames = result; int accountToSelect = 0; @@ -263,6 +288,7 @@ accountToSelect = mAccountNames.indexOf(mForcedAccountName); if (accountToSelect < 0) { mListener.onFailedToSetForcedAccount(mForcedAccountName); + callback.onResult(false); return; } } else { @@ -275,6 +301,7 @@ mSigninChooseView.updateAccounts(mAccountNames, accountToSelect, mProfileData); if (mAccountNames.isEmpty()) { setUpSigninButton(false); + callback.onResult(true); return; } setUpSigninButton(true); @@ -283,7 +310,10 @@ // Determine how the accounts have changed. Each list should only have unique // elements. - if (oldAccountNames == null || oldAccountNames.isEmpty()) return; + if (oldAccountNames == null || oldAccountNames.isEmpty()) { + callback.onResult(true); + return; + } if (!mAccountNames.get(accountToSelect).equals( oldAccountNames.get(oldSelectedAccount))) { @@ -299,7 +329,7 @@ showConfirmSigninPageAccountTrackerServiceCheck(); } } - + callback.onResult(true); } }); } @@ -568,10 +598,15 @@ */ public void switchToForcedAccountMode(String forcedAccountName) { mForcedAccountName = forcedAccountName; - updateAccounts(); - assert TextUtils.equals(getSelectedAccountName(), mForcedAccountName); - switchToSignedMode(); - assert TextUtils.equals(getSelectedAccountName(), mForcedAccountName); + updateAccounts(new Callback<Boolean>() { + @Override + public void onResult(Boolean result) { + if (!result) return; + assert TextUtils.equals(getSelectedAccountName(), mForcedAccountName); + switchToSignedMode(); + assert TextUtils.equals(getSelectedAccountName(), mForcedAccountName); + } + }); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java index ee3b521b..5c20d1f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -21,6 +21,7 @@ import android.widget.TextView; import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; import org.chromium.chrome.browser.ShortcutHelper; @@ -418,8 +419,9 @@ waitUntilAppBannerInfoBarAppears(NATIVE_APP_TITLE); } - @MediumTest - @Feature({"AppBanners"}) + // @MediumTest + // @Feature({"AppBanners"}) + @DisabledTest public void testBannerAppearsThenDoesNotAppearAgainForCustomTime() throws Exception { AppBannerManager.setDaysAfterDismissAndIgnoreForTesting(7, 7); triggerWebAppBanner(mWebAppUrl, WEB_APP_TITLE, false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java index 2be9fd6..0a49cc4 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java
@@ -19,6 +19,8 @@ import org.chromium.content.browser.test.NativeLibraryTestBase; import org.chromium.content_public.browser.DownloadState; +import java.util.Set; + /** * Tests a DownloadHistoryAdapter that is isolated from the real bridges. */ @@ -194,7 +196,7 @@ // Add a third item with the same date as the second item. assertEquals(2, mObserver.onDownloadItemCreatedCallback.getCallCount()); DownloadItem item2 = StubbedProvider.createDownloadItem( - 2, "19840117 18:00", false, DownloadState.IN_PROGRESS); + 2, "19840117 18:00", false, DownloadState.IN_PROGRESS, 0); mAdapter.onDownloadItemCreated(item2); mObserver.onDownloadItemCreatedCallback.waitForCallback(2); assertEquals(mObserver.createdItem, item2); @@ -205,7 +207,7 @@ // but it should now be visible. int callCount = mObserver.onDownloadItemUpdatedCallback.getCallCount(); DownloadItem item3 = StubbedProvider.createDownloadItem( - 2, "19840117 18:00", false, DownloadState.COMPLETE); + 2, "19840117 18:00", false, DownloadState.COMPLETE, 100); mAdapter.onDownloadItemUpdated(item3); mObserver.onDownloadItemUpdatedCallback.waitForCallback(callCount); assertEquals(mObserver.updatedItem, item3); @@ -233,7 +235,7 @@ // Initialize the DownloadHistoryAdapter with three items in two date buckets. DownloadItem regularItem = StubbedProvider.createDownloadItem(0, "19840116 18:00"); DownloadItem offTheRecordItem = StubbedProvider.createDownloadItem( - 1, "19840116 12:00", true, DownloadState.COMPLETE); + 1, "19840116 12:00", true, DownloadState.COMPLETE, 100); OfflinePageDownloadItem offlineItem = StubbedProvider.createOfflineItem(2, "19840117 12:01"); mDownloadDelegate.regularItems.add(regularItem); @@ -334,6 +336,52 @@ assertEquals(0, mAdapter.getItemCount()); } + @SmallTest + public void testInProgress_FilePathMapAccurate() throws Exception { + Set<DownloadHistoryItemWrapper> toDelete; + + initializeAdapter(false); + assertEquals(0, mAdapter.getItemCount()); + assertEquals(0, mAdapter.getTotalDownloadSize()); + + // Simulate the creation of a new item by providing a DownloadItem without a path. + DownloadItem itemCreated = StubbedProvider.createDownloadItem( + 9, "19840118 12:01", false, DownloadState.IN_PROGRESS, 0); + mAdapter.onDownloadItemCreated(itemCreated); + mObserver.onDownloadItemCreatedCallback.waitForCallback(0); + assertEquals(mObserver.createdItem, itemCreated); + + checkAdapterContents(); + toDelete = mAdapter.getItemsForFilePath(itemCreated.getDownloadInfo().getFilePath()); + assertNull(toDelete); + + // Update the Adapter with new information about the item. + int callCount = mObserver.onDownloadItemUpdatedCallback.getCallCount(); + DownloadItem itemUpdated = StubbedProvider.createDownloadItem( + 10, "19840118 12:01", false, DownloadState.IN_PROGRESS, 50); + mAdapter.onDownloadItemUpdated(itemUpdated); + mObserver.onDownloadItemUpdatedCallback.waitForCallback(callCount); + assertEquals(mObserver.updatedItem, itemUpdated); + + checkAdapterContents(null, itemUpdated); + toDelete = mAdapter.getItemsForFilePath(itemUpdated.getDownloadInfo().getFilePath()); + assertNull(toDelete); + + // Tell the Adapter that the item has finished downloading. + callCount = mObserver.onDownloadItemUpdatedCallback.getCallCount(); + DownloadItem itemCompleted = StubbedProvider.createDownloadItem( + 10, "19840118 12:01", false, DownloadState.COMPLETE, 100); + mAdapter.onDownloadItemUpdated(itemCompleted); + mObserver.onDownloadItemUpdatedCallback.waitForCallback(callCount); + assertEquals(mObserver.updatedItem, itemCompleted); + checkAdapterContents(null, itemCompleted); + + // Confirm that the file now shows up when trying to delete it. + toDelete = mAdapter.getItemsForFilePath(itemCompleted.getDownloadInfo().getFilePath()); + assertEquals(1, toDelete.size()); + assertEquals(itemCompleted.getId(), toDelete.iterator().next().getId()); + } + /** Checks that the adapter has the correct items in the right places. */ private void checkAdapterContents(Object... expectedItems) { assertEquals(expectedItems.length, mAdapter.getItemCount());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/StubbedProvider.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/StubbedProvider.java index 44babce9..3846e681 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/StubbedProvider.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/StubbedProvider.java
@@ -199,118 +199,114 @@ @Override public void destroy() {} - /** See {@link #createDownloadItem(int, String, boolean)}. */ + /** See {@link #createDownloadItem(int, String, boolean, int, int)}. */ public static DownloadItem createDownloadItem(int which, String date) throws Exception { - return createDownloadItem(which, date, false, DownloadState.COMPLETE); + return createDownloadItem(which, date, false, DownloadState.COMPLETE, 100); } /** Creates a new DownloadItem with pre-defined values. */ public static DownloadItem createDownloadItem( - int which, String date, boolean isIncognito, int state) throws Exception { - DownloadItem item = null; + int which, String date, boolean isIncognito, int state, int percent) throws Exception { + DownloadInfo.Builder builder = null; if (which == 0) { - item = new DownloadItem(false, new DownloadInfo.Builder() + builder = new DownloadInfo.Builder() .setUrl("https://google.com") .setContentLength(1) .setFileName("first_file.jpg") .setFilePath("/storage/fake_path/Downloads/first_file.jpg") .setDownloadGuid("first_guid") - .setMimeType("image/jpeg") - .setState(state) - .setIsOffTheRecord(isIncognito) - .build()); + .setMimeType("image/jpeg"); } else if (which == 1) { - item = new DownloadItem(false, new DownloadInfo.Builder() + builder = new DownloadInfo.Builder() .setUrl("https://one.com") .setContentLength(10) .setFileName("second_file.gif") .setFilePath("/storage/fake_path/Downloads/second_file.gif") .setDownloadGuid("second_guid") - .setMimeType("image/gif") - .setState(state) - .setIsOffTheRecord(isIncognito) - .build()); + .setMimeType("image/gif"); } else if (which == 2) { - item = new DownloadItem(false, new DownloadInfo.Builder() + builder = new DownloadInfo.Builder() .setUrl("https://is.com") .setContentLength(100) .setFileName("third_file") .setFilePath("/storage/fake_path/Downloads/third_file") .setDownloadGuid("third_guid") - .setMimeType("text/plain") - .setState(state) - .setIsOffTheRecord(isIncognito) - .build()); + .setMimeType("text/plain"); } else if (which == 3) { - item = new DownloadItem(false, new DownloadInfo.Builder() + builder = new DownloadInfo.Builder() .setUrl("https://the.com") .setContentLength(5) .setFileName("four.webm") .setFilePath("/storage/fake_path/Downloads/four.webm") .setDownloadGuid("fourth_guid") - .setMimeType("video/webm") - .setState(state) - .setIsOffTheRecord(isIncognito) - .build()); + .setMimeType("video/webm"); } else if (which == 4) { - item = new DownloadItem(false, new DownloadInfo.Builder() + builder = new DownloadInfo.Builder() .setUrl("https://loneliest.com") .setContentLength(50) .setFileName("five.mp3") .setFilePath("/storage/fake_path/Downloads/five.mp3") .setDownloadGuid("fifth_guid") - .setMimeType("audio/mp3") - .setState(state) - .setIsOffTheRecord(isIncognito) - .build()); + .setMimeType("audio/mp3"); } else if (which == 5) { - item = new DownloadItem(false, new DownloadInfo.Builder() + builder = new DownloadInfo.Builder() .setUrl("https://number.com") .setContentLength(500) .setFileName("six.mp3") .setFilePath("/storage/fake_path/Downloads/six.mp3") .setDownloadGuid("sixth_guid") - .setMimeType("audio/mp3") - .setState(state) - .setIsOffTheRecord(isIncognito) - .build()); + .setMimeType("audio/mp3"); } else if (which == 6) { - item = new DownloadItem(false, new DownloadInfo.Builder() + builder = new DownloadInfo.Builder() .setUrl("https://sigh.com") .setContentLength(ONE_GIGABYTE) .setFileName("huge_image.png") .setFilePath("/storage/fake_path/Downloads/huge_image.png") .setDownloadGuid("seventh_guid") - .setMimeType("image/png") - .setState(state) - .build()); + .setMimeType("image/png"); } else if (which == 7) { - item = new DownloadItem(false, new DownloadInfo.Builder() + builder = new DownloadInfo.Builder() .setUrl("https://sleepy.com") .setContentLength(ONE_GIGABYTE / 2) .setFileName("sleep.pdf") .setFilePath("/storage/fake_path/Downloads/sleep.pdf") .setDownloadGuid("eighth_guid") - .setMimeType("application/pdf") - .setState(state) - .setIsOffTheRecord(isIncognito) - .build()); + .setMimeType("application/pdf"); } else if (which == 8) { - // This is a duplicate of item 7 above. - item = new DownloadItem(false, new DownloadInfo.Builder() + // This is a duplicate of item 7 above with a different GUID. + builder = new DownloadInfo.Builder() .setUrl("https://sleepy.com") .setContentLength(ONE_GIGABYTE / 2) .setFileName("sleep.pdf") .setFilePath("/storage/fake_path/Downloads/sleep.pdf") .setDownloadGuid("ninth_guid") - .setMimeType("application/pdf") - .setState(state) - .setIsOffTheRecord(isIncognito) - .build()); + .setMimeType("application/pdf"); + } else if (which == 9) { + builder = new DownloadInfo.Builder() + .setUrl("https://totallynew.com") + .setContentLength(ONE_GIGABYTE / 10) + .setFileName("forserious.jpg") + .setFilePath(null) + .setDownloadGuid("tenth_guid") + .setMimeType("image/jpg"); + } else if (which == 10) { + // Duplicate version of #9, but the file path has been set. + builder = new DownloadInfo.Builder() + .setUrl("https://totallynew.com") + .setContentLength(ONE_GIGABYTE / 10) + .setFileName("forserious.jpg") + .setFilePath("/storage/fake_path/Downloads/forserious.jpg") + .setDownloadGuid("tenth_guid") + .setMimeType("image/jpg"); } else { return null; } + builder.setIsOffTheRecord(isIncognito); + builder.setPercentCompleted(percent); + builder.setState(state); + + DownloadItem item = new DownloadItem(false, builder.build()); item.setStartTime(dateToEpoch(date)); return item; }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java index c82cca31..3496e02 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java
@@ -177,7 +177,7 @@ public void testDownloadImageFails() { mMediaImageManager.downloadImage(mImages, mCallback); mMediaImageManager.onFinishDownloadImage( - REQUEST_ID_1, 404, IMAGE_URL, mBitmaps, mOriginalImageSizes); + REQUEST_ID_1, 404, IMAGE_URL, new ArrayList<Bitmap>(), new ArrayList<Rect>()); verify(mCallback).onImageDownloaded(isNull(Bitmap.class)); verify(mCallback, times(0)).onImageDownloaded(isNotNull(Bitmap.class));
diff --git a/chrome/app/mash/mash_runner.cc b/chrome/app/mash/mash_runner.cc index 3ca96fa1..5d5d93d0 100644 --- a/chrome/app/mash/mash_runner.cc +++ b/chrome/app/mash/mash_runner.cc
@@ -19,6 +19,7 @@ #include "base/process/launch.h" #include "base/process/process.h" #include "base/run_loop.h" +#include "base/sys_info.h" #include "base/task_scheduler/task_scheduler.h" #include "base/threading/sequenced_worker_pool.h" #include "base/trace_event/trace_event.h" @@ -41,7 +42,6 @@ #include "services/service_manager/runner/common/client_util.h" #include "services/service_manager/runner/common/switches.h" #include "services/service_manager/runner/init.h" -#include "services/service_manager/standalone/context.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_paths.h" #include "ui/base/ui_base_switches.h" @@ -134,6 +134,9 @@ MashRunner::~MashRunner() {} int MashRunner::Run() { + base::TaskScheduler::CreateAndSetSimpleTaskScheduler( + base::SysInfo::NumberOfProcessors()); + if (IsChild()) return RunChild(); RunMain(); @@ -141,8 +144,6 @@ } void MashRunner::RunMain() { - base::TaskScheduler::CreateAndSetSimpleTaskScheduler( - service_manager::kThreadPoolMaxThreads); base::SequencedWorkerPool::EnableWithRedirectionToTaskSchedulerForProcess(); // TODO(sky): refactor BackgroundServiceManager so can supply own context, we @@ -193,11 +194,6 @@ } int MashRunner::RunChild() { - // TODO(fdoray): Add TaskScheduler initialization code in - // service_manager::ServiceRunner. TaskScheduler can't be initialized here - // because it wouldn't be visible to the service's dynamic library. - // https://crbug.com/664996 - service_manager::WaitForDebuggerIfNecessary(); base::i18n::InitializeICU();
diff --git a/chrome/browser/android/offline_pages/request_coordinator_factory_unittest.cc b/chrome/browser/android/offline_pages/request_coordinator_factory_unittest.cc index 2ff93c1..97766c4 100644 --- a/chrome/browser/android/offline_pages/request_coordinator_factory_unittest.cc +++ b/chrome/browser/android/offline_pages/request_coordinator_factory_unittest.cc
@@ -27,7 +27,8 @@ content::BrowserThread::GetBlockingPool()->FlushForTesting(); } -TEST_F(RequestCoordinatorFactoryTest, BuildRequestCoordinator) { +// Flaky on android_n5x_swarming_rel. https://crbug.com/679844 +TEST_F(RequestCoordinatorFactoryTest, DISABLED_BuildRequestCoordinator) { RequestCoordinatorFactory* factory = RequestCoordinatorFactory::GetInstance(); EXPECT_NE(nullptr, factory); RequestCoordinator* coordinator1 =
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index fbc1b1d..2698c53 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -95,12 +95,6 @@ #include "content/public/test/ppapi_test_utils.h" #endif -#if defined(OS_CHROMEOS) -#include "ash/common/accessibility_types.h" -#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" -#include "chrome/browser/chromeos/accessibility/speech_monitor.h" -#endif - using extensions::ContextMenuMatcher; using extensions::ExtensionsAPIClient; using extensions::MenuItem; @@ -2222,30 +2216,6 @@ << message_; } -#if defined(OS_CHROMEOS) -// Flaky, see http://crbug.com/611736. -IN_PROC_BROWSER_TEST_P(WebViewTest, DISABLED_ChromeVoxInjection) { - EXPECT_FALSE( - chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); - - chromeos::SpeechMonitor monitor; - chromeos::AccessibilityManager::Get()->EnableSpokenFeedback( - true, ash::A11Y_NOTIFICATION_NONE); - EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage()); - - ASSERT_TRUE(StartEmbeddedTestServer()); - content::WebContents* guest_web_contents = LoadGuest( - "/extensions/platform_apps/web_view/chromevox_injection/guest.html", - "web_view/chromevox_injection"); - ASSERT_TRUE(guest_web_contents); - - for (;;) { - if (monitor.GetNextUtterance() == "chrome vox test title") - break; - } -} -#endif - // Flaky on Windows. http://crbug.com/303966 #if defined(OS_WIN) #define MAYBE_TearDownTest DISABLED_TearDownTest
diff --git a/chrome/browser/chrome_browser_field_trials_desktop.cc b/chrome/browser/chrome_browser_field_trials_desktop.cc index 03dc966..5eb97f5 100644 --- a/chrome/browser/chrome_browser_field_trials_desktop.cc +++ b/chrome/browser/chrome_browser_field_trials_desktop.cc
@@ -29,10 +29,16 @@ #include "media/media_features.h" #if defined(OS_WIN) +#include "base/win/pe_image.h" #include "chrome/install_static/install_util.h" #include "components/browser_watcher/stability_data_names.h" #endif +#if defined(OS_WIN) +// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx +extern "C" IMAGE_DOS_HEADER __ImageBase; +#endif + namespace chrome { namespace { @@ -109,11 +115,11 @@ stability_file, kMemorySize, kAllocatorId, browser_watcher::kStabilityDebuggingFeature.name, kStackDepth); - // Record basic information: product, version, channel, special build and - // platform. + // Record basic information. base::debug::GlobalActivityTracker* global_tracker = base::debug::GlobalActivityTracker::Get(); if (global_tracker) { + // Record product, version, channel, special build and platform. wchar_t exe_file[MAX_PATH] = {}; CHECK(::GetModuleFileName(nullptr, exe_file, arraysize(exe_file))); @@ -136,6 +142,18 @@ #elif defined(ARCH_CPU_X86_64) global_data.SetString(browser_watcher::kStabilityPlatform, "Win64"); #endif + + // Record information about chrome's module. + global_data.SetUint(browser_watcher::kStabilityModuleAddress, + reinterpret_cast<uint64_t>(&__ImageBase)); + + base::win::PEImage pe(&__ImageBase); + PIMAGE_NT_HEADERS headers = pe.GetNTHeaders(); + CHECK(headers); + global_data.SetUint(browser_watcher::kStabilityModuleTimestamp, + headers->FileHeader.TimeDateStamp); + global_data.SetUint(browser_watcher::kStabilityModuleSize, + headers->OptionalHeader.SizeOfImage); } } #endif // defined(OS_WIN)
diff --git a/chrome/browser/chromeos/accessibility/accessibility_extension_loader.cc b/chrome/browser/chromeos/accessibility/accessibility_extension_loader.cc index 5f11a6d..15d618a 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_extension_loader.cc +++ b/chrome/browser/chromeos/accessibility/accessibility_extension_loader.cc
@@ -5,119 +5,14 @@ #include "chrome/browser/chromeos/accessibility/accessibility_extension_loader.h" #include "base/callback.h" -#include "base/callback_helpers.h" -#include "base/path_service.h" -#include "chrome/browser/chromeos/login/lock/screen_locker.h" -#include "chrome/browser/chromeos/login/lock/webui_screen_locker.h" -#include "chrome/browser/chromeos/login/ui/login_display_host.h" -#include "chrome/browser/chromeos/login/ui/webui_login_view.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/extensions/component_loader.h" #include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/extensions/extension_constants.h" -#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/web_contents.h" -#include "extensions/browser/extension_api_frame_id_map.h" -#include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" -#include "extensions/browser/file_reader.h" -#include "extensions/browser/script_executor.h" -#include "extensions/common/extension.h" -#include "extensions/common/extension_messages.h" -#include "extensions/common/extension_resource.h" namespace chromeos { -namespace { - -// Uses the ScriptExecutor associated with the given |render_view_host| to -// execute the given |code|. -void ExecuteScriptHelper(content::RenderViewHost* render_view_host, - const std::string& code, - const std::string& extension_id) { - content::WebContents* web_contents = - content::WebContents::FromRenderViewHost(render_view_host); - if (!web_contents) - return; - if (!extensions::TabHelper::FromWebContents(web_contents)) - extensions::TabHelper::CreateForWebContents(web_contents); - extensions::TabHelper::FromWebContents(web_contents) - ->script_executor() - ->ExecuteScript(HostID(HostID::EXTENSIONS, extension_id), - extensions::ScriptExecutor::JAVASCRIPT, code, - extensions::ScriptExecutor::INCLUDE_SUB_FRAMES, - extensions::ExtensionApiFrameIdMap::kTopFrameId, - extensions::ScriptExecutor::DONT_MATCH_ABOUT_BLANK, - extensions::UserScript::DOCUMENT_IDLE, - extensions::ScriptExecutor::ISOLATED_WORLD, - extensions::ScriptExecutor::DEFAULT_PROCESS, - GURL(), // No webview src. - GURL(), // No file url. - false, // Not user gesture. - extensions::ScriptExecutor::NO_RESULT, - extensions::ScriptExecutor::ExecuteScriptCallback()); -} - -// Helper class that directly loads an extension's content scripts into -// all of the frames corresponding to a given RenderViewHost. -class ContentScriptLoader { - public: - // Initialize the ContentScriptLoader with the ID of the extension - // and the RenderViewHost where the scripts should be loaded. - ContentScriptLoader(const std::string& extension_id, - int render_process_id, - int render_view_id) - : extension_id_(extension_id), - render_process_id_(render_process_id), - render_view_id_(render_view_id) {} - - // Call this once with the ExtensionResource corresponding to each - // content script to be loaded. - void AppendScript(extensions::ExtensionResource resource) { - resources_.push(resource); - } - - // Finally, call this method once to fetch all of the resources and - // load them. This method will delete this object when done. - void Run() { - if (resources_.empty()) { - delete this; - return; - } - - extensions::ExtensionResource resource = resources_.front(); - resources_.pop(); - scoped_refptr<FileReader> reader(new FileReader( - resource, - FileReader::OptionalFileThreadTaskCallback(), // null callback. - base::Bind(&ContentScriptLoader::OnFileLoaded, - base::Unretained(this)))); - reader->Start(); - } - - private: - void OnFileLoaded(bool success, std::unique_ptr<std::string> data) { - if (success) { - content::RenderViewHost* render_view_host = - content::RenderViewHost::FromID(render_process_id_, render_view_id_); - if (render_view_host) - ExecuteScriptHelper(render_view_host, *data, extension_id_); - } - Run(); - } - - std::string extension_id_; - int render_process_id_; - int render_view_id_; - std::queue<extensions::ExtensionResource> resources_; -}; - -} // namespace - AccessibilityExtensionLoader::AccessibilityExtensionLoader( const std::string& extension_id, const base::FilePath& extension_path, @@ -125,8 +20,7 @@ : profile_(nullptr), extension_id_(extension_id), extension_path_(extension_path), - loaded_on_lock_screen_(false), - loaded_on_user_screen_(false), + loaded_(false), unload_callback_(unload_callback), weak_ptr_factory_(this) {} @@ -137,7 +31,7 @@ const base::Closure& done_callback) { profile_ = profile; - if (!loaded_on_user_screen_ && !loaded_on_lock_screen_) + if (!loaded_) return; // If the extension was already enabled, but not for this profile, add it @@ -146,32 +40,25 @@ extensions::ExtensionSystem::Get(profile_)->extension_service(); auto* component_loader = extension_service->component_loader(); if (!component_loader->Exists(extension_id_)) - LoadExtension(profile_, nullptr, done_callback); + LoadExtension(profile_, done_callback); } void AccessibilityExtensionLoader::Load(Profile* profile, - const std::string& init_script_str, const base::Closure& done_cb) { profile_ = profile; - init_script_str_ = init_script_str; - ScreenLocker* screen_locker = ScreenLocker::default_screen_locker(); - if (screen_locker && screen_locker->locked()) { - // If on the lock screen, loads only to the lock screen as for - // now. On unlock, it will be loaded to the user screen. - // (see. AccessibilityExtensionLoader::Observe()) - LoadToLockScreen(done_cb); - } else { - LoadToUserScreen(done_cb); - } + + if (loaded_) + return; + + loaded_ = true; + LoadExtension(profile_, done_cb); } void AccessibilityExtensionLoader::Unload() { - if (loaded_on_lock_screen_) - UnloadFromLockScreen(); - - if (loaded_on_user_screen_) { + if (loaded_) { UnloadExtensionFromProfile(profile_); - loaded_on_user_screen_ = false; + UnloadExtensionFromProfile(ProfileHelper::GetSigninProfile()); + loaded_ = false; } profile_ = nullptr; @@ -180,53 +67,6 @@ unload_callback_.Run(); } -void AccessibilityExtensionLoader::LoadToUserScreen( - const base::Closure& done_cb) { - if (loaded_on_user_screen_) - return; - - // Determine whether an OOBE screen is currently being shown. If so, - // the extension will be injected directly into that screen. - content::WebUI* login_web_ui = nullptr; - - if (ProfileHelper::IsSigninProfile(profile_)) { - LoginDisplayHost* login_display_host = LoginDisplayHost::default_host(); - if (login_display_host) { - WebUILoginView* web_ui_login_view = - login_display_host->GetWebUILoginView(); - if (web_ui_login_view) - login_web_ui = web_ui_login_view->GetWebUI(); - } - - // Lock screen uses the signin progile. - loaded_on_lock_screen_ = true; - } - - loaded_on_user_screen_ = true; - LoadExtension(profile_, - login_web_ui - ? login_web_ui->GetWebContents()->GetRenderViewHost() - : nullptr, - done_cb); -} - -void AccessibilityExtensionLoader::LoadToLockScreen( - const base::Closure& done_cb) { - if (loaded_on_lock_screen_) - return; - - ScreenLocker* screen_locker = ScreenLocker::default_screen_locker(); - if (screen_locker && screen_locker->locked()) { - content::WebUI* lock_web_ui = screen_locker->web_ui()->GetWebUI(); - if (lock_web_ui) { - Profile* profile = Profile::FromWebUI(lock_web_ui); - loaded_on_lock_screen_ = true; - LoadExtension(profile, lock_web_ui->GetWebContents()->GetRenderViewHost(), - done_cb); - } - } -} - // // private // @@ -238,74 +78,11 @@ extension_service->component_loader()->Remove(extension_path_); } -void AccessibilityExtensionLoader::UnloadFromLockScreen() { - // Lock screen uses the signin progile. - Profile* signin_profile = ProfileHelper::GetSigninProfile(); - UnloadExtensionFromProfile(signin_profile); - loaded_on_lock_screen_ = false; -} - -void AccessibilityExtensionLoader::InjectContentScriptAndCallback( - ExtensionService* extension_service, - int render_process_id, - int render_view_id, - const base::Closure& done_cb) { - // Make sure to always run |done_cb|. The extension was loaded even - // if we end up not injecting into this particular render view. - base::ScopedClosureRunner done_runner(done_cb); - content::RenderViewHost* render_view_host = - content::RenderViewHost::FromID(render_process_id, render_view_id); - if (!render_view_host) - return; - const content::WebContents* web_contents = - content::WebContents::FromRenderViewHost(render_view_host); - GURL content_url; - if (web_contents) - content_url = web_contents->GetLastCommittedURL(); - const extensions::Extension* extension = - extensions::ExtensionRegistry::Get(extension_service->profile()) - ->enabled_extensions() - .GetByID(extension_id_); - - if (!init_script_str_.empty()) { - ExecuteScriptHelper(render_view_host, init_script_str_, extension->id()); - } - - // Inject the content scripts. - ContentScriptLoader* loader = new ContentScriptLoader( - extension->id(), render_view_host->GetProcess()->GetID(), - render_view_host->GetRoutingID()); - - const extensions::UserScriptList& content_scripts = - extensions::ContentScriptsInfo::GetContentScripts(extension); - for (const std::unique_ptr<extensions::UserScript>& script : - content_scripts) { - if (web_contents && !script->MatchesURL(content_url)) - continue; - for (const std::unique_ptr<extensions::UserScript::File>& file : - script->js_scripts()) { - extensions::ExtensionResource resource = - extension->GetResource(file->relative_path()); - loader->AppendScript(resource); - } - } - loader->Run(); // It cleans itself up when done. -} - void AccessibilityExtensionLoader::LoadExtension( Profile* profile, - content::RenderViewHost* render_view_host, base::Closure done_cb) { ExtensionService* extension_service = extensions::ExtensionSystem::Get(profile)->extension_service(); - if (render_view_host) { - // Wrap the passed in callback to inject the content script. - done_cb = base::Bind( - &AccessibilityExtensionLoader::InjectContentScriptAndCallback, - weak_ptr_factory_.GetWeakPtr(), extension_service, - render_view_host->GetProcess()->GetID(), - render_view_host->GetRoutingID(), done_cb); - } extension_service->component_loader()->AddComponentFromDir( extension_path_, extension_id_.c_str(), done_cb);
diff --git a/chrome/browser/chromeos/accessibility/accessibility_extension_loader.h b/chrome/browser/chromeos/accessibility/accessibility_extension_loader.h index 34d30ed..a8e983ad 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_extension_loader.h +++ b/chrome/browser/chromeos/accessibility/accessibility_extension_loader.h
@@ -9,11 +9,6 @@ #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" -namespace content { -class RenderViewHost; -} - -class ExtensionService; class Profile; namespace chromeos { @@ -26,35 +21,19 @@ ~AccessibilityExtensionLoader(); void SetProfile(Profile* profile, const base::Closure& done_callback); - void Load(Profile* profile, - const std::string& init_script_str, - const base::Closure& done_cb); + void Load(Profile* profile, const base::Closure& done_cb); void Unload(); - void LoadToUserScreen(const base::Closure& done_cb); - void LoadToLockScreen(const base::Closure& done_cb); void LoadExtension(Profile* profile, - content::RenderViewHost* render_view_host, base::Closure done_cb); - bool loaded_on_lock_screen() { return loaded_on_lock_screen_; } - private: - void InjectContentScriptAndCallback(ExtensionService* extension_service, - int render_process_id, - int render_view_id, - const base::Closure& done_cb); - void UnloadFromLockScreen(); void UnloadExtensionFromProfile(Profile* profile); Profile* profile_; std::string extension_id_; base::FilePath extension_path_; - std::string init_script_str_; - // Profile which the extension is currently loaded to. - // If nullptr, it is not loaded to any profile. - bool loaded_on_lock_screen_; - bool loaded_on_user_screen_; + bool loaded_; base::Closure unload_callback_;
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc index 1650a437..5597050 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -66,7 +66,6 @@ #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" -#include "content/public/browser/render_view_host.h" #include "content/public/browser/web_ui.h" #include "content/public/common/content_switches.h" #include "content/public/common/service_manager_connection.h" @@ -87,7 +86,6 @@ #include "ui/keyboard/keyboard_util.h" using content::BrowserThread; -using content::RenderViewHost; using extensions::api::braille_display_private::BrailleController; using extensions::api::braille_display_private::DisplayState; using extensions::api::braille_display_private::KeyEvent; @@ -261,7 +259,6 @@ select_to_speak_enabled_(false), switch_access_enabled_(false), spoken_feedback_notification_(ash::A11Y_NOTIFICATION_NONE), - should_speak_chrome_vox_announcements_on_user_screen_(true), system_sounds_enabled_(false), braille_display_connected_(false), scoped_braille_observer_(this), @@ -278,9 +275,6 @@ notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, content::NotificationService::AllSources()); - notification_registrar_.Add(this, - chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED, - content::NotificationService::AllSources()); input_method::InputMethodManager::Get()->AddObserver(this); @@ -483,7 +477,7 @@ NotifyAccessibilityStatusChanged(details); if (enabled) { - chromevox_loader_->Load(profile_, "window.INJECTED_AFTER_LOAD = true;", + chromevox_loader_->Load(profile_, base::Bind(&AccessibilityManager::PostLoadChromeVox, weak_ptr_factory_.GetWeakPtr())); } else { @@ -886,8 +880,7 @@ select_to_speak_enabled_ = enabled; if (enabled) { - select_to_speak_loader_->Load(profile_, "" /* init_script_str */, - base::Closure() /* done_cb */); + select_to_speak_loader_->Load(profile_, base::Closure() /* done_cb */); select_to_speak_event_handler_.reset( new chromeos::SelectToSpeakEventHandler()); } else { @@ -1163,10 +1156,6 @@ return media::SoundsManager::Get()->GetDuration(SOUND_SHUTDOWN); } -void AccessibilityManager::InjectChromeVox(RenderViewHost* render_view_host) { - chromevox_loader_->LoadExtension(profile_, render_view_host, base::Closure()); -} - std::unique_ptr<AccessibilityStatusSubscription> AccessibilityManager::RegisterCallback(const AccessibilityStatusCallback& cb) { return callback_list_.Add(cb); @@ -1245,9 +1234,6 @@ // Update |profile_| when entering a session. SetProfile(ProfileManager::GetActiveUserProfile()); - // Ensure ChromeVox makes announcements at the start of new sessions. - should_speak_chrome_vox_announcements_on_user_screen_ = true; - // Add a session state observer to be able to monitor session changes. if (!session_state_observer_.get() && ash::Shell::HasInstance()) session_state_observer_.reset( @@ -1260,19 +1246,6 @@ SetProfile(NULL); break; } - case chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED: { - bool is_screen_locked = *content::Details<bool>(details).ptr(); - if (spoken_feedback_enabled_) { - if (is_screen_locked) - chromevox_loader_->LoadToLockScreen(base::Closure()); - // If spoken feedback was enabled, make sure it is also enabled on - // the user screen. - // The status tray gets verbalized by user screen ChromeVox, so we need - // to load it on the user screen even if the screen is locked. - chromevox_loader_->LoadToUserScreen(base::Closure()); - } - break; - } } } @@ -1320,24 +1293,17 @@ // Do any setup work needed immediately after ChromeVox actually loads. PlayEarcon(SOUND_SPOKEN_FEEDBACK_ENABLED, PlaySoundOption::ALWAYS); - if (chromevox_loader_->loaded_on_lock_screen() || - should_speak_chrome_vox_announcements_on_user_screen_) { - extensions::EventRouter* event_router = - extensions::EventRouter::Get(profile_); - CHECK(event_router); + extensions::EventRouter* event_router = + extensions::EventRouter::Get(profile_); + CHECK(event_router); - std::unique_ptr<base::ListValue> event_args(new base::ListValue()); - std::unique_ptr<extensions::Event> event(new extensions::Event( - extensions::events::ACCESSIBILITY_PRIVATE_ON_INTRODUCE_CHROME_VOX, - extensions::api::accessibility_private::OnIntroduceChromeVox:: - kEventName, - std::move(event_args))); - event_router->DispatchEventWithLazyListener( - extension_misc::kChromeVoxExtensionId, std::move(event)); - } - - should_speak_chrome_vox_announcements_on_user_screen_ = - chromevox_loader_->loaded_on_lock_screen(); + std::unique_ptr<base::ListValue> event_args(new base::ListValue()); + std::unique_ptr<extensions::Event> event(new extensions::Event( + extensions::events::ACCESSIBILITY_PRIVATE_ON_INTRODUCE_CHROME_VOX, + extensions::api::accessibility_private::OnIntroduceChromeVox::kEventName, + std::move(event_args))); + event_router->DispatchEventWithLazyListener( + extension_misc::kChromeVoxExtensionId, std::move(event)); if (!chromevox_panel_) { chromevox_panel_ = new ChromeVoxPanel(profile_);
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h index 87684cb..3da064d05 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.h +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -26,10 +26,6 @@ #include "extensions/browser/extension_system.h" #include "ui/base/ime/chromeos/input_method_manager.h" -namespace content { -class RenderViewHost; -} - class Profile; namespace chromeos { @@ -235,9 +231,6 @@ // Initiates play of shutdown sound and returns it's duration. base::TimeDelta PlayShutdownSound(); - // Injects ChromeVox scripts into given |render_view_host|. - void InjectChromeVox(content::RenderViewHost* render_view_host); - // Register a callback to be notified when the status of an accessibility // option changes. std::unique_ptr<AccessibilityStatusSubscription> RegisterCallback( @@ -386,8 +379,6 @@ ash::AccessibilityNotificationVisibility spoken_feedback_notification_; - bool should_speak_chrome_vox_announcements_on_user_screen_; - bool system_sounds_enabled_; AccessibilityStatusCallbackList callback_list_;
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc index 876e24b..4858e18 100644 --- a/chrome/browser/chromeos/arc/arc_session_manager.cc +++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -163,6 +163,13 @@ return false; } + // IsPrimaryProfile can return true for an incognito profile corresponding + // to the primary profile, but ARC does not support it. + if (profile->IsOffTheRecord()) { + VLOG(1) << "Incognito profile is not supported in ARC."; + return false; + } + if (profile->IsLegacySupervised()) { VLOG(1) << "Supervised users are not supported in ARC."; return false;
diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc index 48ff949..84140764 100644 --- a/chrome/browser/chromeos/options/wifi_config_view.cc +++ b/chrome/browser/chromeos/options/wifi_config_view.cc
@@ -1119,12 +1119,12 @@ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE_HIDE)); passphrase_visible_button_->SetImage( views::ImageButton::STATE_NORMAL, - ResourceBundle::GetSharedInstance(). - GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD)); + *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( + IDR_NETWORK_SHOW_PASSWORD)); passphrase_visible_button_->SetImage( views::ImageButton::STATE_HOVERED, - ResourceBundle::GetSharedInstance(). - GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD_HOVER)); + *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( + IDR_NETWORK_SHOW_PASSWORD_HOVER)); passphrase_visible_button_->SetToggledImage( views::ImageButton::STATE_NORMAL, ResourceBundle::GetSharedInstance().
diff --git a/chrome/browser/chromeos/options/wimax_config_view.cc b/chrome/browser/chromeos/options/wimax_config_view.cc index 1236787f..92534666 100644 --- a/chrome/browser/chromeos/options/wimax_config_view.cc +++ b/chrome/browser/chromeos/options/wimax_config_view.cc
@@ -280,12 +280,12 @@ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE_HIDE)); passphrase_visible_button_->SetImage( views::ImageButton::STATE_NORMAL, - ResourceBundle::GetSharedInstance(). - GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD)); + *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( + IDR_NETWORK_SHOW_PASSWORD)); passphrase_visible_button_->SetImage( views::ImageButton::STATE_HOVERED, - ResourceBundle::GetSharedInstance(). - GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD_HOVER)); + *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( + IDR_NETWORK_SHOW_PASSWORD_HOVER)); passphrase_visible_button_->SetToggledImage( views::ImageButton::STATE_NORMAL, ResourceBundle::GetSharedInstance().
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc index fce4b86..ea33e64 100644 --- a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc +++ b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc
@@ -74,21 +74,6 @@ return true; } -void ChromeWebViewGuestDelegate::OnDidInitialize() { -#if defined(OS_CHROMEOS) - if (chrome::IsRunningInMash()) { - NOTIMPLEMENTED(); - return; - } - chromeos::AccessibilityManager* accessibility_manager = - chromeos::AccessibilityManager::Get(); - CHECK(accessibility_manager); - accessibility_subscription_ = accessibility_manager->RegisterCallback( - base::Bind(&ChromeWebViewGuestDelegate::OnAccessibilityStatusChanged, - weak_ptr_factory_.GetWeakPtr())); -#endif -} - // static std::unique_ptr<base::ListValue> ChromeWebViewGuestDelegate::MenuModelToValue( const ui::SimpleMenuModel& menu_model) { @@ -128,35 +113,6 @@ chrome::kChromeUIChromeSigninURL; } -void ChromeWebViewGuestDelegate::InjectChromeVoxIfNeeded( - content::RenderViewHost* render_view_host) { -#if defined(OS_CHROMEOS) - if (!chromevox_injected_) { - chromeos::AccessibilityManager* manager = - chromeos::AccessibilityManager::Get(); - if (manager && manager->IsSpokenFeedbackEnabled()) { - manager->InjectChromeVox(render_view_host); - chromevox_injected_ = true; - } - } -#endif -} - -#if defined(OS_CHROMEOS) -void ChromeWebViewGuestDelegate::OnAccessibilityStatusChanged( - const chromeos::AccessibilityStatusEventDetails& details) { - if (details.notification_type == chromeos::ACCESSIBILITY_MANAGER_SHUTDOWN) { - accessibility_subscription_.reset(); - } else if (details.notification_type == - chromeos::ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK) { - if (details.enabled) - InjectChromeVoxIfNeeded(guest_web_contents()->GetRenderViewHost()); - else - chromevox_injected_ = false; - } -} -#endif - void ChromeWebViewGuestDelegate::SetContextMenuPosition( const gfx::Point& position) { if (context_menu_position_ == nullptr)
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h index 682f4a23..f64e07c 100644 --- a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h +++ b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h
@@ -11,10 +11,6 @@ #include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "extensions/browser/guest_view/web_view/web_view_guest_delegate.h" -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" -#endif - class RenderViewContextMenuBase; namespace ui { @@ -30,7 +26,6 @@ // WebViewGuestDelegate implementation. bool HandleContextMenu(const content::ContextMenuParams& params) override; - void OnDidInitialize() override; void OnShowContextMenu(int request_id) override; bool ShouldHandleFindRequestsForEmbedder() const override; @@ -47,14 +42,6 @@ static std::unique_ptr<base::ListValue> MenuModelToValue( const ui::SimpleMenuModel& menu_model); - void InjectChromeVoxIfNeeded(content::RenderViewHost* render_view_host); - -#if defined(OS_CHROMEOS) - // Notification of a change in the state of an accessibility setting. - void OnAccessibilityStatusChanged( - const chromeos::AccessibilityStatusEventDetails& details); -#endif - // A counter to generate a unique request id for a context menu request. // We only need the ids to be unique for a given WebViewGuest. int pending_context_menu_request_id_; @@ -63,15 +50,6 @@ // shown. This is .reset() after ShowContextMenu(). std::unique_ptr<RenderViewContextMenuBase> pending_menu_; -#if defined(OS_CHROMEOS) - // Set to |true| if ChromeVox was already injected in main frame. - bool chromevox_injected_ = false; - - // Subscription to receive notifications on changes to a11y settings. - std::unique_ptr<chromeos::AccessibilityStatusSubscription> - accessibility_subscription_; -#endif - WebViewGuest* const web_view_guest_; std::unique_ptr<gfx::Point> context_menu_position_;
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index 21dbd851..b121fa6c1 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -3294,10 +3294,16 @@ base::SimpleTestTickClock* clock = OverridePrerenderManagerTimeTicks(); GURL url = embedded_test_server()->GetURL("/prerender/prerender_page.html"); + base::RunLoop hanging_request_waiter; + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(&CreateHangingFirstRequestInterceptorOnIO, + url, GetTestPath("prerender_page.html"), + hanging_request_waiter.QuitClosure())); // As this load will be canceled, it is not waited for, and hence no // javascript is executed. DisableJavascriptCalls(); PrerenderTestURL(url, FINAL_STATUS_CANCELLED, 0); + hanging_request_waiter.Run(); // This prerender cancels and reuses the first. clock->Advance(base::TimeDelta::FromSeconds(1));
diff --git a/chrome/browser/prerender/prerender_histograms.cc b/chrome/browser/prerender/prerender_histograms.cc index 60bf8349..d7ea7309 100644 --- a/chrome/browser/prerender/prerender_histograms.cc +++ b/chrome/browser/prerender/prerender_histograms.cc
@@ -468,10 +468,9 @@ if (!prefetch_age.is_zero()) { DCHECK_NE(origin, ORIGIN_NONE); - RecordHistogramTime( - GetHistogramName(origin, IsOriginWash(), "Prerender.PrefetchAge"), - base::TimeDelta::FromMilliseconds(10), base::TimeDelta::FromMinutes(30), - prefetch_age, 50); + RecordHistogramTime(GetHistogramName(origin, IsOriginWash(), "PrefetchAge"), + base::TimeDelta::FromMilliseconds(10), + base::TimeDelta::FromMinutes(30), prefetch_age, 50); } std::string histogram_base_name;
diff --git a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc index 522c0a4..69d7fb1 100644 --- a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc +++ b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
@@ -178,6 +178,7 @@ "Prerender.websame_PrefetchTTFCP.Warm.Cacheable.Visible", 1); histogram_tester().ExpectTotalCount( "Prerender.websame_NoStatePrefetchResponseTypes", 2); + histogram_tester().ExpectTotalCount("Prerender.websame_PrefetchAge", 1); } // Checks the prefetch of an img tag.
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js index b1f96568..8c0c9d50 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
@@ -88,12 +88,6 @@ */ this.currentRange_ = null; - /** - * @type {cursors.Range} - * @private - */ - this.savedRange_ = null; - // Manually bind all functions to |this|. for (var func in this) { if (typeof(this[func]) == 'function') @@ -156,9 +150,6 @@ /** @type {!LiveRegions} @private */ this.liveRegions_ = new LiveRegions(this); - /** @type {boolean} @private */ - this.inExcursion_ = false; - /** * Stores the mode as computed the last time a current range was set. * @type {?ChromeVoxMode} @@ -397,9 +388,6 @@ * @override */ setCurrentRange: function(newRange) { - if (!this.inExcursion_ && newRange) - this.savedRange_ = new cursors.Range(newRange.start, newRange.end); - if (newRange && !newRange.isValid()) return;
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/keyboard_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/keyboard_handler.js index 2f3505ff..fcc3b8c8 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/keyboard_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/keyboard_handler.js
@@ -23,6 +23,8 @@ document.addEventListener('keydown', this.onKeyDown.bind(this), false); document.addEventListener('keyup', this.onKeyUp.bind(this), false); + + chrome.accessibilityPrivate.setKeyboardListener(true, false); }; BackgroundKeyboardHandler.prototype = {
diff --git a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html index 3032f242..3ae34bf 100644 --- a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html +++ b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
@@ -1,6 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="/controls/settings_checkbox.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/i18n_setup.html"> <link rel="import" href="/route.html"> <link rel="import" href="/settings_shared_css.html"> @@ -36,30 +36,34 @@ <h2>$i18n{textToSpeechHeading}</h2> <div class="settings-box first" actionable> - <settings-checkbox class="start" pref="{{prefs.settings.accessibility}}" + <settings-toggle-button class="start" + pref="{{prefs.settings.accessibility}}" label="$i18n{chromeVoxLabel}"> - </settings-checkbox> - <button class="icon-external" is="paper-icon-button-light" - on-tap="onChromeVoxSettingsTap_" - hidden="[[!prefs.settings.accessibility.value]]"></button> + <button class="more-actions icon-external" is="paper-icon-button-light" + on-tap="onChromeVoxSettingsTap_" + hidden="[[!prefs.settings.accessibility.value]]"></button> + </settings-toggle-button> </div> <template is="dom-if" if="[[showExperimentalFeatures_]]"> <div class="settings-box block"> - <settings-checkbox pref="{{prefs.settings.a11y.select_to_speak}}" + <settings-toggle-button + pref="{{prefs.settings.a11y.select_to_speak}}" label="$i18n{selectToSpeakTitle}" sub-label="$i18n{selectToSpeakDescription}"> - </settings-checkbox> + </settings-toggle-button> </div> </template> <h2>$i18n{displayHeading}</h2> <div class="settings-box block first"> - <settings-checkbox label="$i18n{highContrastLabel}" - pref="{{prefs.settings.a11y.high_contrast_enabled}}"> - </settings-checkbox> - <settings-checkbox label="$i18n{screenMagnifierLabel}" - pref="{{prefs.settings.a11y.screen_magnifier}}"> - </settings-checkbox> + <settings-toggle-button + pref="{{prefs.settings.a11y.high_contrast_enabled}}" + label="$i18n{highContrastLabel}"> + </settings-toggle-button> + <settings-toggle-button + pref="{{prefs.settings.a11y.screen_magnifier}}" + label="$i18n{screenMagnifierLabel}"> + </settings-toggle-button> </div> <div class="settings-box two-line" on-tap="onDisplayTap_" actionable> <div class="start"> @@ -78,23 +82,27 @@ <h2>$i18n{keyboardHeading}</h2> <div class="settings-box block first"> - <settings-checkbox + <settings-toggle-button pref="{{prefs.settings.a11y.sticky_keys_enabled}}" label="$i18n{stickyKeysLabel}"> - </settings-checkbox> - <settings-checkbox pref="{{prefs.settings.a11y.virtual_keyboard}}" + </settings-toggle-button> + <settings-toggle-button + pref="{{prefs.settings.a11y.virtual_keyboard}}" label="$i18n{onScreenKeyboardLabel}"> - </settings-checkbox> - <settings-checkbox pref="{{prefs.settings.a11y.focus_highlight}}" + </settings-toggle-button> + <settings-toggle-button + pref="{{prefs.settings.a11y.focus_highlight}}" label="$i18n{focusHighlightLabel}"> - </settings-checkbox> - <settings-checkbox pref="{{prefs.settings.a11y.caret_highlight}}" + </settings-toggle-button> + <settings-toggle-button + pref="{{prefs.settings.a11y.caret_highlight}}" label="$i18n{caretHighlightLabel}"> - </settings-checkbox> + </settings-toggle-button> <template is="dom-if" if="[[showExperimentalFeatures_]]"> - <settings-checkbox pref="{{prefs.settings.a11y.switch_access}}" + <settings-toggle-button + pref="{{prefs.settings.a11y.switch_access}}" label="$i18n{switchAccessLabel}"> - </settings-checkbox> + </settings-toggle-button> </template> </div> <div class="settings-box two-line" on-tap="onKeyboardTap_" actionable> @@ -107,10 +115,11 @@ <h2>$i18n{mouseAndTouchpadHeading}</h2> <div class="settings-box block first"> - <settings-checkbox label="$i18n{clickOnStopLabel}" - pref="{{prefs.settings.a11y.autoclick}}"> - </settings-checkbox> - <div class="list-item settings-checkbox-spacer"> + <settings-toggle-button + pref="{{prefs.settings.a11y.autoclick}}" + label="$i18n{clickOnStopLabel}"> + </settings-toggle-button> + <div class="list-item settings-toggle-button-spacer"> <div>$i18n{delayBeforeClickLabel}</div> <settings-dropdown-menu pref="{{prefs.settings.a11y.autoclick_delay_ms}}" @@ -118,15 +127,18 @@ disabled="[[!prefs.settings.a11y.autoclick.value]]"> </settings-dropdown-menu> </div> - <settings-checkbox label="$i18n{tapDraggingLabel}" - pref="{{prefs.settings.touchpad.enable_tap_dragging}}"> - </settings-checkbox> - <settings-checkbox label="$i18n{largeMouseCursorLabel}" - pref="{{prefs.settings.a11y.large_cursor_enabled}}"> - </settings-checkbox> - <settings-checkbox pref="{{prefs.settings.a11y.cursor_highlight}}" + <settings-toggle-button + pref="{{prefs.settings.touchpad.enable_tap_dragging}}" + label="$i18n{tapDraggingLabel}"> + </settings-toggle-button> + <settings-toggle-button + pref="{{prefs.settings.a11y.large_cursor_enabled}}" + label="$i18n{largeMouseCursorLabel}"> + </settings-toggle-button> + <settings-toggle-button + pref="{{prefs.settings.a11y.cursor_highlight}}" label="$i18n{cursorHighlightLabel}"> - </settings-checkbox> + </settings-toggle-button> </div> <div class="settings-box two-line" on-tap="onMouseTap_" actionable> <div class="start"> @@ -138,9 +150,10 @@ <h2>$i18n{audioHeading}</h2> <div class="settings-box block first"> - <settings-checkbox pref="{{prefs.settings.a11y.mono_audio}}" + <settings-toggle-button + pref="{{prefs.settings.a11y.mono_audio}}" label="$i18n{monoAudioLabel}"> - </settings-checkbox> + </settings-toggle-button> </div> <div class="settings-box two-line" on-tap="onMoreFeaturesTap_" actionable>
diff --git a/chrome/browser/resources/settings/android_apps_page/android_apps_page.html b/chrome/browser/resources/settings/android_apps_page/android_apps_page.html index d0141e32..6843f2f 100644 --- a/chrome/browser/resources/settings/android_apps_page/android_apps_page.html +++ b/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
@@ -2,7 +2,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="/android_apps_page/android_apps_browser_proxy.html"> -<link rel="import" href="/controls/settings_checkbox.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/i18n_setup.html"> <link rel="import" href="/prefs/prefs_behavior.html"> <link rel="import" href="/settings_shared_css.html"> @@ -21,10 +21,12 @@ </style> <div class="settings-box first"> - <settings-checkbox id="enabledCheckbox" pref="{{prefs.arc.enabled}}" + <settings-toggle-button id="enabled" class="start" + pref="{{prefs.arc.enabled}}" label="$i18n{androidAppsEnabled}" - no-set-pref on-change="onArcEnabledChange_"> - </settings-checkbox> + on-change="onArcEnabledChange_" + no-set-pref> + </settings-toggle-button> <a href="$i18nRaw{androidAppsLearnMoreUrl}" target="_blank"> $i18n{androidAppsLearnMore} </a>
diff --git a/chrome/browser/resources/settings/android_apps_page/android_apps_page.js b/chrome/browser/resources/settings/android_apps_page/android_apps_page.js index 44ece83..9ac62e6 100644 --- a/chrome/browser/resources/settings/android_apps_page/android_apps_page.js +++ b/chrome/browser/resources/settings/android_apps_page/android_apps_page.js
@@ -87,8 +87,7 @@ * @private */ onConfirmDisableDialogConfirm_: function() { - /** @type {!SettingsCheckboxElement} */ (this.$.enabledCheckbox) - .sendPrefChange(); + /** @type {!SettingsCheckboxElement} */ (this.$.enabled).sendPrefChange(); this.$.confirmDisableDialog.close(); }, @@ -98,8 +97,7 @@ * @private */ onConfirmDisableDialogCancel_: function() { - /** @type {!SettingsCheckboxElement} */ (this.$.enabledCheckbox) - .resetToPrefValue(); + /** @type {!SettingsCheckboxElement} */ (this.$.enabled).resetToPrefValue(); this.$.confirmDisableDialog.close(); }, });
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html index 14179aa..b945c8f 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.html +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -11,6 +11,7 @@ <link rel="import" href="/controls/settings_dropdown_menu.html"> <link rel="import" href="/controls/settings_input.html"> <link rel="import" href="/controls/settings_radio_group.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/route.html"> <link rel="import" href="/settings_page/settings_animated_pages.html"> <link rel="import" href="/settings_page/settings_subpage.html"> @@ -90,11 +91,12 @@ </div> <div class="settings-box" hidden="[[!pageVisibility.homeButton]]"> - <settings-checkbox class="start" label="$i18n{showHomeButton}" + <settings-toggle-button class="start" + pref="{{prefs.browser.show_home_button}}" + label="$i18n{showHomeButton}" sub-label="[[getShowHomeSubLabel_( - prefs.homepage_is_newtabpage.value, prefs.homepage.value)]]" - pref="{{prefs.browser.show_home_button}}"> - </settings-checkbox> + prefs.homepage_is_newtabpage.value, prefs.homepage.value)]]"> + </settings-toggle-button> </div> <template is="dom-if" if="[[prefs.browser.show_home_button.value]]"> <div class="list-frame" @@ -130,15 +132,18 @@ </template> <div class="settings-box" hidden="[[!pageVisibility.bookmarksBar]]"> - <settings-checkbox class="start" label="$i18n{showBookmarksBar}" - pref="{{prefs.bookmark_bar.show_on_all_tabs}}"> - </settings-checkbox> + <settings-toggle-button class="start" + pref="{{prefs.bookmark_bar.show_on_all_tabs}}" + label="$i18n{showBookmarksBar}"> + </settings-toggle-button> </div> <div class$="settings-box [[getFirst_(pageVisibility.bookmarksBar)]]"> <if expr="is_linux and not chromeos"> - <settings-checkbox class="start" label="$i18n{showWindowDecorations}" - pref="{{prefs.browser.custom_chrome_frame}}" inverted> - </settings-checkbox> + <settings-toggle-button class="start" + pref="{{prefs.browser.custom_chrome_frame}}" + label="$i18n{showWindowDecorations}" + inverted> + </settings-toggle-button> </div> <div class="settings-box"> </if>
diff --git a/chrome/browser/resources/settings/controls/settings_toggle_button.html b/chrome/browser/resources/settings/controls/settings_toggle_button.html index c21d78c..624f41a 100644 --- a/chrome/browser/resources/settings/controls/settings_toggle_button.html +++ b/chrome/browser/resources/settings/controls/settings_toggle_button.html
@@ -21,8 +21,13 @@ @apply(--settings-secondary-unchecked); } + paper-toggle-button, cr-policy-pref-indicator { - -webkit-margin-end: var(--checkbox-spacing); + -webkit-margin-start: var(--checkbox-spacing); + } + + ::content .more-actions { + -webkit-margin-end: 10px; } </style> <div id="outerRow" noSubLabel$="[[!subLabel]]"> @@ -31,6 +36,7 @@ <div>[[label]]</div> <div class="secondary">[[subLabel]]</div> </div> + <content selector=".more-actions"></content> <template is="dom-if" if="[[pref.controlledBy]]"> <cr-policy-pref-indicator pref="[[pref]]"></cr-policy-pref-indicator> </template>
diff --git a/chrome/browser/resources/settings/date_time_page/date_time_page.html b/chrome/browser/resources/settings/date_time_page/date_time_page.html index 840d2606..185df7e 100644 --- a/chrome/browser/resources/settings/date_time_page/date_time_page.html +++ b/chrome/browser/resources/settings/date_time_page/date_time_page.html
@@ -1,10 +1,10 @@ <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="/controls/settings_checkbox.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="/controls/settings_dropdown_menu.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/i18n_setup.html"> <link rel="import" href="/prefs/prefs_behavior.html"> <link rel="import" href="/prefs/prefs_types.html"> @@ -28,22 +28,23 @@ </settings-dropdown-menu> </div> <div class="settings-box continuation"> - <paper-checkbox - id="timeZoneAutoDetectCheckbox" - checked="[[timeZoneAutoDetect_]]" - disabled="[[hasTimeZoneAutoDetectPolicy_]]" - on-change="onTimeZoneAutoDetectCheckboxChange_"> - $i18n{timeZoneGeolocation} - </paper-checkbox> + <div class="start">$i18n{timeZoneGeolocation}</div> <template is="dom-if" if="[[hasTimeZoneAutoDetectPolicy_]]"> <cr-policy-pref-indicator pref="[[timeZonePolicyPref_]]"> </cr-policy-pref-indicator> </template> + <paper-toggle-button + id="timeZoneAutoDetect" + checked="[[timeZoneAutoDetect_]]" + disabled="[[hasTimeZoneAutoDetectPolicy_]]" + on-change="onTimeZoneAutoDetectChange_"> + </paper-toggle-button> </div> <div class="settings-box continuation"> - <settings-checkbox pref="{{prefs.settings.clock.use_24hour_clock}}" + <settings-toggle-button class="start" + pref="{{prefs.settings.clock.use_24hour_clock}}" label="$i18n{use24HourClock}"> - </settings-checkbox> + </settings-toggle-button> </div> <div class="settings-box" id="setDateTime" actionable on-tap="onSetDateTimeTap_" hidden$="[[!canSetDateTime_]]">
diff --git a/chrome/browser/resources/settings/date_time_page/date_time_page.js b/chrome/browser/resources/settings/date_time_page/date_time_page.js index 3c7fb7d1..6e28f44 100644 --- a/chrome/browser/resources/settings/date_time_page/date_time_page.js +++ b/chrome/browser/resources/settings/date_time_page/date_time_page.js
@@ -151,7 +151,7 @@ * @param {!Event} e * @private */ - onTimeZoneAutoDetectCheckboxChange_: function(e) { + onTimeZoneAutoDetectChange_: function(e) { this.setPrefValue( 'settings.resolve_timezone_by_geolocation', e.target.checked); },
diff --git a/chrome/browser/resources/settings/device_page/display.html b/chrome/browser/resources/settings/device_page/display.html index e5c55c1..2337274 100644 --- a/chrome/browser/resources/settings/device_page/display.html +++ b/chrome/browser/resources/settings/device_page/display.html
@@ -4,7 +4,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-tabs/paper-tabs.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
diff --git a/chrome/browser/resources/settings/device_page/keyboard.html b/chrome/browser/resources/settings/device_page/keyboard.html index 5b6473a8..73dc9239 100644 --- a/chrome/browser/resources/settings/device_page/keyboard.html +++ b/chrome/browser/resources/settings/device_page/keyboard.html
@@ -3,8 +3,8 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="/controls/settings_checkbox.html"> <link rel="import" href="/controls/settings_dropdown_menu.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/i18n_setup.html"> <link rel="import" href="/route.html"> <link rel="import" href="/settings_shared_css.html"> @@ -66,17 +66,17 @@ </settings-dropdown-menu> </div> <div class="settings-box"> - <settings-checkbox + <settings-toggle-button class="start" pref="{{prefs.settings.language.send_function_keys}}" label="$i18n{keyboardSendFunctionKeys}" sub-label="$i18n{keyboardSendFunctionKeysDescription}"> - </settings-checkbox> + </settings-toggle-button> </div> <div class="settings-box"> - <settings-checkbox + <settings-toggle-button class="start" pref="{{prefs.settings.language.xkb_auto_repeat_enabled_r2}}" label="$i18n{keyboardEnableAutoRepeat}"> - </settings-checkbox> + </settings-toggle-button> </div> <iron-collapse opened="[[prefs.settings.language.xkb_auto_repeat_enabled_r2.value]]">
diff --git a/chrome/browser/resources/settings/device_page/pointers.html b/chrome/browser/resources/settings/device_page/pointers.html index 7c67f68..60a50fe 100644 --- a/chrome/browser/resources/settings/device_page/pointers.html +++ b/chrome/browser/resources/settings/device_page/pointers.html
@@ -1,8 +1,8 @@ <link rel="import" href="chrome://resources/cr_elements/cr_slider/cr_slider.html"> <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html"> -<link rel="import" href="/controls/settings_checkbox.html"> <link rel="import" href="/controls/settings_radio_group.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/device_page/device_page_browser_proxy.html"> <link rel="import" href="/settings_shared_css.html"> @@ -30,9 +30,10 @@ <!-- Subsection title only appears if both mouse and touchpad exist. --> <h2 hidden$="[[!hasTouchpad]]">$i18n{mouseTitle}</h2> <div class="settings-box first"> - <settings-checkbox pref="{{prefs.settings.mouse.primary_right}}" + <settings-toggle-button class="start" + pref="{{prefs.settings.mouse.primary_right}}" label="$i18n{mouseSwapButtons}"> - </settings-checkbox> + </settings-toggle-button> </div> <div class="settings-box"> <div class="start" id="mouseSpeedLabel">$i18n{mouseSpeed}</div> @@ -49,14 +50,14 @@ <!-- Subsection title only appears if both mouse and touchpad exist. --> <h2 hidden$="[[!hasMouse]]">$i18n{touchpadTitle}</h2> <div class="settings-box block first"> - <settings-checkbox id="enableTapToClick" + <settings-toggle-button id="enableTapToClick" pref="{{prefs.settings.touchpad.enable_tap_to_click}}" label="$i18n{touchpadTapToClickEnabledLabel}"> - </settings-checkbox> - <settings-checkbox id="enableTapDragging" + </settings-toggle-button> + <settings-toggle-button id="enableTapDragging" pref="{{prefs.settings.touchpad.enable_tap_dragging}}" label="$i18n{tapDraggingLabel}"> - </settings-checkbox> + </settings-toggle-button> </div> <div class="settings-box"> <div class="start" id="touchpadSpeedLabel">$i18n{touchpadSpeed}</div>
diff --git a/chrome/browser/resources/settings/device_page/stylus.html b/chrome/browser/resources/settings/device_page/stylus.html index 42fb14eb..2d4a473 100644 --- a/chrome/browser/resources/settings/device_page/stylus.html +++ b/chrome/browser/resources/settings/device_page/stylus.html
@@ -1,6 +1,6 @@ <link rel="import" href="chrome://resources/html/action_link.html"> <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="/controls/settings_checkbox.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/settings_shared_css.html"> <dom-module id="settings-stylus"> @@ -8,18 +8,18 @@ <style include="settings-shared"></style> <div class="settings-box"> - <settings-checkbox + <settings-toggle-button class="start" pref="{{prefs.settings.enable_stylus_tools}}" label="$i18n{stylusEnableStylusTools}"> - </settings-checkbox> + </settings-toggle-button> </div> <div class="settings-box continuation"> - <settings-checkbox - disabled="[[!prefs.settings.enable_stylus_tools.value]]" + <settings-toggle-button class="start" pref="{{prefs.settings.launch_palette_on_eject_event}}" - label="$i18n{stylusAutoOpenStylusTools}"> - </settings-checkbox> + label="$i18n{stylusAutoOpenStylusTools}" + disabled="[[!prefs.settings.enable_stylus_tools.value]]"> + </settings-toggle-button> </div> <div class="settings-box">
diff --git a/chrome/browser/resources/settings/downloads_page/downloads_page.html b/chrome/browser/resources/settings/downloads_page/downloads_page.html index ee334ebc..6c70bac9 100644 --- a/chrome/browser/resources/settings/downloads_page/downloads_page.html +++ b/chrome/browser/resources/settings/downloads_page/downloads_page.html
@@ -1,7 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html"> <link rel="import" href="/controls/controlled_button.html"> -<link rel="import" href="/controls/settings_checkbox.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/settings_shared_css.html"> <dom-module id="settings-downloads-page"> @@ -29,14 +29,16 @@ </div> </div> <div class="settings-box block"> - <settings-checkbox pref="{{prefs.download.prompt_for_download}}" + <settings-toggle-button + pref="{{prefs.download.prompt_for_download}}" label="$i18n{promptForDownload}"> - </settings-checkbox> + </settings-toggle-button> <if expr="chromeos"> - <settings-checkbox pref="{{prefs.gdata.disabled}}" + <settings-toggle-button + pref="{{prefs.gdata.disabled}}" label="$i18n{disconnectGoogleDriveAccount}" hidden="[[!pageVisibility.googleDrive]]"> - </settings-checkbox> + </settings-toggle-button> </if> </div> </template>
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.html b/chrome/browser/resources/settings/internet_page/internet_detail_page.html index 66e0f11e..dd271c2 100644 --- a/chrome/browser/resources/settings/internet_page/internet_detail_page.html +++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
@@ -8,7 +8,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="/prefs/prefs.html"> <link rel="import" href="/route.html"> <link rel="import" href="internet_shared_css.html"> @@ -154,27 +154,27 @@ <!-- Prefer this network. --> <template is="dom-if" if="[[showPreferNetwork_(networkProperties))]]"> <div class="settings-box"> - <paper-checkbox checked="{{preferNetwork_}}" - disabled="[[isNetworkPolicyEnforced( - networkProperties.Priority)]]"> - $i18n{networkPrefer} - </paper-checkbox> + <div class="start">$i18n{networkPrefer}</div> <cr-policy-network-indicator property="[[networkProperties.Priority]]"> </cr-policy-network-indicator> + <paper-toggle-button checked="{{preferNetwork_}}" + disabled="[[isNetworkPolicyEnforced( + networkProperties.Priority)]]"> + </paper-toggle-button> </div> </template> <!-- Autoconnect. --> <template is="dom-if" if="[[showAutoConnect_(networkProperties)]]"> <div class="settings-box"> - <paper-checkbox checked="{{autoConnect_}}" - disabled="[[isNetworkPolicyEnforced( - getManagedAutoConnect_(networkProperties))]]"> - $i18n{networkAutoConnect} - </paper-checkbox> + <div class="start">$i18n{networkAutoConnect}</div> <cr-policy-network-indicator property="[[getManagedAutoConnect_(networkProperties)]]"> </cr-policy-network-indicator> + <paper-toggle-button checked="{{autoConnect_}}" + disabled="[[isNetworkPolicyEnforced( + getManagedAutoConnect_(networkProperties))]]"> + </paper-toggle-button> </div> </template> <!-- SIM Info (Cellular only). -->
diff --git a/chrome/browser/resources/settings/internet_page/network_ip_config.html b/chrome/browser/resources/settings/internet_page/network_ip_config.html index d79a2bf..31565f7 100644 --- a/chrome/browser/resources/settings/internet_page/network_ip_config.html +++ b/chrome/browser/resources/settings/internet_page/network_ip_config.html
@@ -1,6 +1,6 @@ <link rel="import" href="chrome://resources/cr_elements/network/cr_onc_types.html"> <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="internet_shared_css.html"> <link rel="import" href="network_property_list.html"> @@ -8,9 +8,9 @@ <template> <style include="internet-shared"></style> <div class="settings-box first"> - <paper-checkbox checked="{{automatic_}}" disabled="[[!editable]]"> - $i18n{networkIPConfigAuto} - </paper-checkbox> + <div class="start">$i18n{networkIPConfigAuto}</div> + <paper-toggle-button checked="{{automatic_}}" disabled="[[!editable]]"> + </paper-toggle-button> </div> <div class="settings-box continuation" hidden$="[[!showIPEditFields_(editable, automatic_)]]">
diff --git a/chrome/browser/resources/settings/internet_page/network_proxy.html b/chrome/browser/resources/settings/internet_page/network_proxy.html index 8952fa51..ca1f90ce 100644 --- a/chrome/browser/resources/settings/internet_page/network_proxy.html +++ b/chrome/browser/resources/settings/internet_page/network_proxy.html
@@ -6,11 +6,11 @@ <link rel="import" href="chrome://resources/html/md_select_css.html"> <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="/controls/extension_controlled_indicator.html"> -<link rel="import" href="/controls/settings_checkbox.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/i18n_setup.html"> <link rel="import" href="/prefs/prefs_behavior.html"> <link rel="import" href="/settings_vars_css.html"> @@ -47,7 +47,7 @@ margin: 10px 0; } - #proxyDiv paper-checkbox { + #proxyDiv paper-toggle-button { padding: 10px 0; } </style> @@ -79,11 +79,12 @@ <div class="settings-box continuation" hidden$="[[!shouldShowAllowShared_( networkProperties.ProxySettings.Type)]]"> - <settings-checkbox id="allowShared" + <settings-toggle-button id="allowShared" class="start" pref="{{prefs.settings.use_shared_proxies}}" - no-set-pref label="$i18n{networkProxyAllowShared}" - on-change="onAllowSharedProxiesChange_"> - </settings-checkbox> + label="$i18n{networkProxyAllowShared}" + on-change="onAllowSharedProxiesChange_" + no-set-pref> + </settings-toggle-button> </div> <!-- Proxy type dropdown --> @@ -123,11 +124,13 @@ <!-- Manual --> <div id="proxyDiv" class="settings-box continuation single-column indent" hidden$="[[!matches_(proxy_.Type, ProxySettingsType_.MANUAL)]]"> - <paper-checkbox checked="{{useSameProxy_}}" - disabled="[[!isEditable_('Type', networkProperties, editable, - useSharedProxies_)]]"> - $i18n{networkProxyUseSame} - </paper-checkbox> + <div class="flex layout horizontal"> + <div class="flex">$i18n{networkProxyUseSame}</div> + <paper-toggle-button checked="{{useSameProxy_}}" + disabled="[[!isEditable_('Type', networkProperties, editable, + useSharedProxies_)]]"> + </paper-toggle-button> + </div> <div hidden$="[[!useSameProxy_]]" class="layout vertical"> <network-proxy-input on-proxy-change="onProxyInputChange_"
diff --git a/chrome/browser/resources/settings/internet_page/network_siminfo.html b/chrome/browser/resources/settings/internet_page/network_siminfo.html index f1db2d2..b3d5b589 100644 --- a/chrome/browser/resources/settings/internet_page/network_siminfo.html +++ b/chrome/browser/resources/settings/internet_page/network_siminfo.html
@@ -3,14 +3,14 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="/icons.html"> <link rel="import" href="internet_shared_css.html"> <dom-module id="network-siminfo"> <template> - <style include="internet-shared"> + <style include="settings-shared internet-shared"> iron-icon { -webkit-margin-end: 10px; } @@ -43,6 +43,10 @@ .settings-box:first-of-type { border-top: none; } + + paper-toggle-button { + -webkit-margin-start: var(--checkbox-spacing); + } </style> <!-- SIM missing UI --> @@ -71,14 +75,14 @@ <!-- SIM unlocked --> <div class="settings-box two-line" hidden$="[[!showSimUnlocked_(networkProperties)]]"> - <paper-checkbox class="start" on-change="onSimLockEnabledChange_" - checked="[[networkProperties.Cellular.SIMLockStatus.LockEnabled]]"> - $i18n{networkSimLockEnable} - </paper-checkbox> - <paper-button on-tap="onChangePinTap_" + <div class="start">$i18n{networkSimLockEnable}</div> + <paper-button on-tap="onChangePinTap_" hidden$="[[!networkProperties.Cellular.SIMLockStatus.LockEnabled]]"> $i18n{networkSimChangePin} </paper-button> + <paper-toggle-button on-change="onSimLockEnabledChange_" + checked="[[networkProperties.Cellular.SIMLockStatus.LockEnabled]]"> + </paper-toggle-button> </div> <!-- Enter PIN dialog -->
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html index b7ee06c..f3073fb 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html +++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
@@ -4,6 +4,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/global_scroll_target_behavior.html"> <link rel="import" href="/passwords_and_forms_page/password_edit_dialog.html"> <link rel="import" href="/passwords_and_forms_page/passwords_shared_css.html"> @@ -52,12 +53,12 @@ -webkit-user-select: text; } </style> - <div class="settings-box first two-line"> - <settings-checkbox id="autosigninCheckbox" + <div class="settings-box first"> + <settings-toggle-button id="autosigninCheckbox" class="start" pref="{{prefs.credentials_enable_autosignin}}" label="$i18n{passwordsAutosigninLabel}" sub-label="$i18n{passwordsAutosigninDescription}"> - </settings-checkbox> + </settings-toggle-button> </div> <div id="manageLink" class="settings-box first"> <!-- This span lays out the url correctly, relative to the label. -->
diff --git a/chrome/browser/resources/settings/people_page/lock_screen.html b/chrome/browser/resources/settings/people_page/lock_screen.html index be7d39f3..cf290e9 100644 --- a/chrome/browser/resources/settings/people_page/lock_screen.html +++ b/chrome/browser/resources/settings/people_page/lock_screen.html
@@ -2,6 +2,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-group/paper-radio-group.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/people_page/lock_screen_constants.html"> <link rel="import" href="/people_page/lock_state_behavior.html"> <link rel="import" href="/people_page/password_prompt_dialog.html"> @@ -33,7 +34,9 @@ $i18n{lockScreenPinOrPassword} </paper-radio-button> <div class="settings-box continuation radio-indent" - hidden$="[[!showConfigurePinButton_(selectedUnlockType)]]"> + hidden$="[[!showConfigurePinButton_(selectedUnlockType)]]"> + <!-- TODO(dbeam): I seriously doubt paper-button[is=action-link] is + a good idea. --> <paper-button is="action-link" on-tap="onConfigurePin_"> [[getSetupPinText_(hasPin)]] </paper-button> @@ -41,18 +44,18 @@ </paper-radio-group> </div> - <div class="settings-box single-column"> - <settings-checkbox pref="{{prefs.settings.enable_screen_lock}}" - label="$i18n{enableScreenlock}"> - </settings-checkbox> + <div class="settings-box"> + <settings-toggle-button class="start" + pref="{{prefs.settings.enable_screen_lock}}" + label="$i18n{enableScreenlock}"> + </settings-toggle-button> </div> <settings-password-prompt-dialog id="passwordPrompt" - on-close="onPasswordClosed_" - set-modes="{{setModes_}}"> + on-close="onPasswordClosed_" set-modes="{{setModes_}}"> </settings-password-prompt-dialog> <settings-setup-pin-dialog id="setupPin" on-done="onPinSetupDone_" - set-modes="[[setModes_]]"> + set-modes="[[setModes_]]"> </settings-setup-pin-dialog> </div> </template>
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html index d9b0d409..105745a 100644 --- a/chrome/browser/resources/settings/people_page/people_page.html +++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -10,7 +10,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="/controls/settings_checkbox.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/people_page/sync_page.html"> <link rel="import" href="/people_page/profile_info_browser_proxy.html"> <link rel="import" href="/people_page/sync_browser_proxy.html"> @@ -200,10 +200,11 @@ <if expr="chromeos"> <template is="dom-if" if="[[!quickUnlockEnabled_]]"> - <div class="settings-box single-column"> - <settings-checkbox pref="{{prefs.settings.enable_screen_lock}}" + <div class="settings-box"> + <settings-toggle-button class="start" + pref="{{prefs.settings.enable_screen_lock}}" label="$i18n{enableScreenlock}"> - </settings-checkbox> + </settings-toggle-button> </div> </template> @@ -235,13 +236,15 @@ <a target="_blank" href="$i18n{easyUnlockLearnMoreURL}"> $i18n{learnMore} </a> + <!-- TODO(dbeam): this should be 1 dom-if with a method instead + of 2 nested dom-ifs. --> <template is="dom-if" if="[[easyUnlockEnabled_]]"> <template is="dom-if" if="[[easyUnlockProximityDetectionAllowed_]]"> - <settings-checkbox + <settings-toggle-button pref="{{prefs.easy_unlock.proximity_required}}" label="$i18n{easyUnlockRequireProximityLabel}"> - </settings-checkbox> + </settings-toggle-button> </template> </template> </div>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html index b502be0c..6cd9f8aa 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.html +++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -2,7 +2,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-group/paper-radio-group.html"> @@ -44,15 +44,6 @@ padding: 0; }; } - - /** - * This is currently necessary because a link inside a disabled - * paper-checkbox inherits `pointer-events: none;` and will not work. - * See: https://github.com/PolymerElements/paper-checkbox/issues/166 - */ - #paymentLearnMore { - pointer-events: initial; - } </style> <div id="[[pages.SPINNER]]" class="settings-box first" hidden$="[[!isStatus_(pages.SPINNER, pageStatus_)]]"> @@ -65,96 +56,124 @@ <div id="[[pages.CONFIGURE]]" hidden$="[[!isStatus_(pages.CONFIGURE, pageStatus_)]]"> <div class="settings-box first"> - <paper-checkbox id="syncAllDataTypesCheckbox" + <div class="start">$i18n{syncEverythingCheckboxLabel}</div> + <paper-toggle-button id="syncAllDataTypesControl" checked="{{syncPrefs.syncAllDataTypes}}" on-change="onSyncAllDataTypesChanged_"> - $i18n{syncEverythingCheckboxLabel} - </paper-checkbox> + </paper-toggle-button> </div> <div class="list-frame"> - <paper-checkbox checked="{{syncPrefs.appsSynced}}" - on-change="onSingleSyncDataTypeChanged_" class="list-item" - hidden="[[!syncPrefs.appsRegistered]]" - disabled="[[shouldSyncCheckboxBeDisabled_( - syncPrefs.syncAllDataTypes, syncPrefs.appsEnforced)]]"> - $i18n{appCheckboxLabel} - </paper-checkbox> + <div class="layout horizontal list-item"> + <div class="flex">$i18n{appCheckboxLabel}</div> + <paper-toggle-button checked="{{syncPrefs.appsSynced}}" + on-change="onSingleSyncDataTypeChanged_" + hidden="[[!syncPrefs.appsRegistered]]" + disabled="[[shouldSyncCheckboxBeDisabled_( + syncPrefs.syncAllDataTypes, syncPrefs.appsEnforced)]]"> + </paper-toggle-button> + </div> - <!-- Autofill has a special on-change handler to deal with - Payments integriation. --> - <paper-checkbox checked="{{syncPrefs.autofillSynced}}" - on-change="onAutofillDataTypeChanged_" class="list-item" - hidden="[[!syncPrefs.autofillRegistered]]" - disabled="[[shouldSyncCheckboxBeDisabled_( - syncPrefs.syncAllDataTypes, syncPrefs.autofillEnforced)]]"> - $i18n{autofillCheckboxLabel} - </paper-checkbox> + <div class="layout horizontal list-item"> + <div class="flex">$i18n{autofillCheckboxLabel}</div> + <!-- Autofill has a special on-change handler to deal with + Payments integriation. --> + <paper-toggle-button checked="{{syncPrefs.autofillSynced}}" + on-change="onAutofillDataTypeChanged_" + hidden="[[!syncPrefs.autofillRegistered]]" + disabled="[[shouldSyncCheckboxBeDisabled_( + syncPrefs.syncAllDataTypes, syncPrefs.autofillEnforced)]]"> + </paper-toggle-button> + </div> - <paper-checkbox checked="{{syncPrefs.bookmarksSynced}}" - on-change="onSingleSyncDataTypeChanged_" class="list-item" - hidden="[[!syncPrefs.bookmarksRegistered]]" - disabled="[[shouldSyncCheckboxBeDisabled_( - syncPrefs.syncAllDataTypes, syncPrefs.bookmarksEnforced)]]"> - $i18n{bookmarksCheckboxLabel} - </paper-checkbox> - <paper-checkbox checked="{{syncPrefs.extensionsSynced}}" - on-change="onSingleSyncDataTypeChanged_" class="list-item" - hidden="[[!syncPrefs.extensionsRegistered]]" - disabled="[[shouldSyncCheckboxBeDisabled_( - syncPrefs.syncAllDataTypes, syncPrefs.extensionsEnforced)]]"> - $i18n{extensionsCheckboxLabel} - </paper-checkbox> - <paper-checkbox checked="{{syncPrefs.typedUrlsSynced}}" - on-change="onSingleSyncDataTypeChanged_" class="list-item" - hidden="[[!syncPrefs.typedUrlsRegistered]]" - disabled="[[shouldSyncCheckboxBeDisabled_( - syncPrefs.syncAllDataTypes, syncPrefs.typedUrlsEnforced)]]"> - $i18n{historyCheckboxLabel} - </paper-checkbox> - <paper-checkbox checked="{{syncPrefs.passwordsSynced}}" - on-change="onSingleSyncDataTypeChanged_" class="list-item" - hidden="[[!syncPrefs.passwordsRegistered]]" - disabled="[[shouldSyncCheckboxBeDisabled_( - syncPrefs.syncAllDataTypes, syncPrefs.passwordsEnforced)]]"> - $i18n{passwordsCheckboxLabel} - </paper-checkbox> - <paper-checkbox checked="{{syncPrefs.preferencesSynced}}" - on-change="onSingleSyncDataTypeChanged_" class="list-item" - hidden="[[!syncPrefs.preferencesRegistered]]" - disabled="[[shouldSyncCheckboxBeDisabled_( - syncPrefs.syncAllDataTypes, syncPrefs.preferencesEnforced)]]"> - $i18n{settingsCheckboxLabel} - </paper-checkbox> - <paper-checkbox checked="{{syncPrefs.themesSynced}}" - on-change="onSingleSyncDataTypeChanged_" class="list-item" - hidden="[[!syncPrefs.themesRegistered]]" - disabled="[[shouldSyncCheckboxBeDisabled_( - syncPrefs.syncAllDataTypes, syncPrefs.themesEnforced)]]"> - $i18n{themesAndWallpapersCheckboxLabel} - </paper-checkbox> - <paper-checkbox checked="{{syncPrefs.tabsSynced}}" - on-change="onSingleSyncDataTypeChanged_" class="list-item" - hidden="[[!syncPrefs.tabsRegistered]]" - disabled="[[shouldSyncCheckboxBeDisabled_( - syncPrefs.syncAllDataTypes, syncPrefs.tabsEnforced)]]"> - $i18n{openTabsCheckboxLabel} - </paper-checkbox> + <div class="layout horizontal list-item"> + <div class="flex">$i18n{bookmarksCheckboxLabel}</div> + <paper-toggle-button checked="{{syncPrefs.bookmarksSynced}}" + on-change="onSingleSyncDataTypeChanged_" + hidden="[[!syncPrefs.bookmarksRegistered]]" + disabled="[[shouldSyncCheckboxBeDisabled_( + syncPrefs.syncAllDataTypes, syncPrefs.bookmarksEnforced)]]"> + </paper-toggle-button> + </div> - <!-- The Payments integration checkbox is a special case in many ways. - It's visible only if autofill is registered. It's disabled and - unchecked if autofill is unchecked.--> - <paper-checkbox checked="{{syncPrefs.paymentsIntegrationEnabled}}" - on-change="onSingleSyncDataTypeChanged_" class="list-item" - hidden="[[!syncPrefs.autofillRegistered]]" - disabled="[[shouldPaymentsCheckboxBeDisabled_( - syncPrefs.syncAllDataTypes, syncPrefs.autofillSynced)]]"> - $i18n{enablePaymentsIntegrationCheckboxLabel} - <a href="$i18nRaw{autofillHelpURL}" target="_blank" - id="paymentLearnMore" on-tap="onLearnMoreTap_"> - $i18n{learnMore} - </a> - </paper-checkbox> + <div class="layout horizontal list-item"> + <div class="flex">$i18n{extensionsCheckboxLabel}</div> + <paper-toggle-button checked="{{syncPrefs.extensionsSynced}}" + on-change="onSingleSyncDataTypeChanged_" + hidden="[[!syncPrefs.extensionsRegistered]]" + disabled="[[shouldSyncCheckboxBeDisabled_( + syncPrefs.syncAllDataTypes, syncPrefs.extensionsEnforced)]]"> + </paper-toggle-button> + </div> + + <div class="layout horizontal list-item"> + <div class="flex">$i18n{historyCheckboxLabel}</div> + <paper-toggle-button checked="{{syncPrefs.typedUrlsSynced}}" + on-change="onSingleSyncDataTypeChanged_" + hidden="[[!syncPrefs.typedUrlsRegistered]]" + disabled="[[shouldSyncCheckboxBeDisabled_( + syncPrefs.syncAllDataTypes, syncPrefs.typedUrlsEnforced)]]"> + </paper-toggle-button> + </div> + + <div class="layout horizontal list-item"> + <div class="flex">$i18n{passwordsCheckboxLabel}</div> + <paper-toggle-button checked="{{syncPrefs.passwordsSynced}}" + on-change="onSingleSyncDataTypeChanged_" + hidden="[[!syncPrefs.passwordsRegistered]]" + disabled="[[shouldSyncCheckboxBeDisabled_( + syncPrefs.syncAllDataTypes, syncPrefs.passwordsEnforced)]]"> + </paper-toggle-button> + </div> + + <div class="layout horizontal list-item"> + <div class="flex">$i18n{settingsCheckboxLabel}</div> + <paper-toggle-button checked="{{syncPrefs.preferencesSynced}}" + on-change="onSingleSyncDataTypeChanged_" + hidden="[[!syncPrefs.preferencesRegistered]]" + disabled="[[shouldSyncCheckboxBeDisabled_( + syncPrefs.syncAllDataTypes, syncPrefs.preferencesEnforced)]]"> + </paper-toggle-button> + </div> + + <div class="layout horizontal list-item"> + <div class="flex">$i18n{themesAndWallpapersCheckboxLabel}</div> + <paper-toggle-button checked="{{syncPrefs.themesSynced}}" + on-change="onSingleSyncDataTypeChanged_" + hidden="[[!syncPrefs.themesRegistered]]" + disabled="[[shouldSyncCheckboxBeDisabled_( + syncPrefs.syncAllDataTypes, syncPrefs.themesEnforced)]]"> + </paper-toggle-button> + </div> + + <div class="layout horizontal list-item"> + <div class="flex">$i18n{openTabsCheckboxLabel}</div> + <paper-toggle-button checked="{{syncPrefs.tabsSynced}}" + on-change="onSingleSyncDataTypeChanged_" + hidden="[[!syncPrefs.tabsRegistered]]" + disabled="[[shouldSyncCheckboxBeDisabled_( + syncPrefs.syncAllDataTypes, syncPrefs.tabsEnforced)]]"> + </paper-toggle-button> + </div> + + <div class="layout horizontal list-item"> + <!-- The Payments integration checkbox is a special case in many ways. + It's visible only if autofill is registered. It's disabled and + unchecked if autofill is unchecked.--> + <div class="flex"> + $i18n{enablePaymentsIntegrationCheckboxLabel} + <a href="$i18nRaw{autofillHelpURL}" target="_blank"> + $i18n{learnMore} + </a> + </div> + <paper-toggle-button + checked="{{syncPrefs.paymentsIntegrationEnabled}}" + on-change="onSingleSyncDataTypeChanged_" + hidden="[[!syncPrefs.autofillRegistered]]" + disabled="[[shouldPaymentsCheckboxBeDisabled_( + syncPrefs.syncAllDataTypes, syncPrefs.autofillSynced)]]"> + </paper-toggle-button> + </div> </div> <div class="settings-box two-line" actionable
diff --git a/chrome/browser/resources/settings/people_page/users_page.html b/chrome/browser/resources/settings/people_page/users_page.html index 9fd6801..f0ddb52 100644 --- a/chrome/browser/resources/settings/people_page/users_page.html +++ b/chrome/browser/resources/settings/people_page/users_page.html
@@ -1,7 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="/controls/settings_checkbox.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/settings_shared_css.html"> <link rel="import" href="user_list.html"> <link rel="import" href="users_add_user_dialog.html"> @@ -32,28 +32,28 @@ </template> </template> <div class="settings-box block"> - <settings-checkbox + <settings-toggle-button pref="{{prefs.cros.accounts.allowBWSI}}" label="$i18n{guestBrowsingLabel}" disabled="[[isEditingDisabled_(isOwner_, isWhitelistManaged_)]]"> - </settings-checkbox> - <settings-checkbox + </settings-toggle-button> + <settings-toggle-button pref="{{prefs.cros.accounts.supervisedUsersEnabled}}" label="$i18n{supervisedUsersLabel}" disabled="[[isEditingDisabled_(isOwner_, isWhitelistManaged_)]]"> - </settings-checkbox> - <settings-checkbox + </settings-toggle-button> + <settings-toggle-button pref="{{prefs.cros.accounts.showUserNamesOnSignIn}}" label="$i18n{showOnSigninLabel}" disabled="[[isEditingDisabled_(isOwner_, isWhitelistManaged_)]]"> - </settings-checkbox> - <settings-checkbox + </settings-toggle-button> + <settings-toggle-button pref="{{prefs.cros.accounts.allowGuest}}" id="restrictSignIn" label="$i18n{restrictSigninLabel}" disabled="[[isEditingDisabled_(isOwner_, isWhitelistManaged_)]]" inverted> - </settings-checkbox> + </settings-toggle-button> <div class="users"> <settings-user-list prefs="[[prefs]]" disabled="[[isEditingUsersDisabled_(isOwner_, isWhitelistManaged_,
diff --git a/chrome/browser/resources/settings/printing_page/cloud_printers.html b/chrome/browser/resources/settings/printing_page/cloud_printers.html index fe3c6f69..157c346 100644 --- a/chrome/browser/resources/settings/printing_page/cloud_printers.html +++ b/chrome/browser/resources/settings/printing_page/cloud_printers.html
@@ -1,6 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="/controls/settings_checkbox.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/settings_shared_css.html"> <dom-module id="settings-cloud-printers"> @@ -15,8 +15,10 @@ </span> </div> <div class="settings-box"> - <settings-checkbox pref="{{prefs.local_discovery.notifications_enabled}}" - label="$i18n{printingNotificationsLabel}"></settings-checkbox> + <settings-toggle-button class="start" + pref="{{prefs.local_discovery.notifications_enabled}}" + label="$i18n{printingNotificationsLabel}"> + </settings-toggle-button> </div> <div class="settings-box two-line" on-tap="onManageTap_" actionable> <div class="start">
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html index d315b07..c789f6c 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -6,7 +6,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="/clear_browsing_data_dialog/clear_browsing_data_dialog.html"> -<link rel="import" href="/controls/settings_checkbox.html"> <link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/lifetime_browser_proxy.html"> <link rel="import" href="/route.html"> @@ -42,16 +41,6 @@ min-height: var(--settings-row-min-height); } - #metricsReportingCheckbox, - #safeBrowsingExtendedReportingCheckbox { - display: inline-block; - } - - #metricsReportingCheckbox, - #safeBrowsingExtendedReportingCheckbox { - width: 100%; - } - #metricsReporting paper-tooltip { --paper-tooltip: var(--cr-policy-tooltip); } @@ -73,48 +62,41 @@ <neon-animatable route-path="default"> <div class="settings-box block first"> <p class="privacy-explanation">$i18nRaw{improveBrowsingExperience}</p> - <settings-checkbox pref="{{prefs.alternate_error_pages.enabled}}" + <settings-toggle-button + pref="{{prefs.alternate_error_pages.enabled}}" label="$i18n{linkDoctorPref}"> - </settings-checkbox> - <settings-checkbox pref="{{prefs.search.suggest_enabled}}" + </settings-toggle-button> + <settings-toggle-button + pref="{{prefs.search.suggest_enabled}}" label="$i18n{searchSuggestPref}" hidden="[[!pageVisibility.searchPrediction]]"> - </settings-checkbox> - <settings-checkbox pref="{{prefs.net.network_prediction_options}}" + </settings-toggle-button> + <settings-toggle-button + pref="{{prefs.net.network_prediction_options}}" label="$i18n{networkPredictionEnabled}" hidden="[[!pageVisibility.networkPrediction]]"> - </settings-checkbox> + </settings-toggle-button> <div class="layout horizontal center settings-row-min-height"> - <paper-checkbox id="safeBrowsingExtendedReportingCheckbox" - on-tap="onSafeBrowsingExtendedReportingCheckboxTap_" + <div class="flex">$i18n{safeBrowsingEnableExtendedReporting}</div> + <paper-toggle-button id="safeBrowsingExtendedReportingControl" + on-tap="onSafeBrowsingExtendedReportingControlTap_" checked="[[safeBrowsingExtendedReportingEnabled_]]"> - $i18n{safeBrowsingEnableExtendedReporting} - </paper-checkbox> + </paper-toggle-button> </div> - <settings-checkbox pref="{{prefs.safebrowsing.enabled}}" + <settings-toggle-button + pref="{{prefs.safebrowsing.enabled}}" label="$i18n{safeBrowsingEnableProtection}"> - </settings-checkbox> + </settings-toggle-button> <if expr="_google_chrome"> <if expr="chromeos"> - <settings-checkbox pref="{{prefs.cros.metrics.reportingEnabled}}" + <settings-toggle-button + pref="{{prefs.cros.metrics.reportingEnabled}}" label="$i18n{enableLogging}"> - </settings-checkbox> + </settings-toggle-button> </if><!-- chromeos --> <if expr="not chromeos"> <div class="layout horizontal center settings-row-min-height"> - <paper-checkbox id="metricsReportingCheckbox" - on-tap="onMetricsReportingCheckboxTap_" - checked="[[metricsReporting_.enabled]]" - disabled="[[metricsReporting_.managed]]"> - $i18n{enableLogging} - </paper-checkbox> - <template is="dom-if" if="[[metricsReporting_.managed]]" restamp> - <iron-icon id="indicator" tabindex=0 icon="cr:domain"></iron-icon> - <paper-tooltip for="indicator" position="top" - fit-to-visible-bounds> - $i18n{controlledSettingPolicy} - </paper-tooltip> - </template> + <div class="flex">$i18n{enableLogging}</div> <template is="dom-if" if="[[showRestart_]]" restamp> <div id="restart" class="flex"> <paper-button on-tap="onRestartTap_"> @@ -122,21 +104,34 @@ </paper-button> </div> </template> + <template is="dom-if" if="[[metricsReporting_.managed]]" restamp> + <iron-icon id="indicator" tabindex=0 icon="cr:domain"></iron-icon> + <paper-tooltip for="indicator" position="top" + fit-to-visible-bounds> + $i18n{controlledSettingPolicy} + </paper-tooltip> + </template> + <paper-toggle-button id="metricsReportingControl" + on-tap="onMetricsReportingControlTap_" + checked="[[metricsReporting_.enabled]]" + disabled="[[metricsReporting_.managed]]"> + </paper-toggle-button> </div> </if><!-- not chromeos --> </if><!-- _google_chrome --> - <settings-checkbox pref="{{prefs.enable_do_not_track}}" + <settings-toggle-button + pref="{{prefs.enable_do_not_track}}" label="$i18n{doNotTrack}"> - </settings-checkbox> + </settings-toggle-button> <if expr="chromeos"> - <settings-checkbox + <settings-toggle-button pref="{{prefs.cros.device.attestation_for_content_protection_enabled}}" label="$i18n{enableContentProtectionAttestation}"> - </settings-checkbox> - <settings-checkbox + </settings-toggle-button> + <settings-toggle-button pref="{{prefs.settings.internet.wake_on_wifi_darkconnect}}" label="$i18n{wakeOnWifi}"> - </settings-checkbox> + </settings-toggle-button> </if> </div> <if expr="_google_chrome"> @@ -251,9 +246,9 @@ </category-default-setting> <div class="settings-box"> <settings-toggle-button class="start" + pref="{{prefs.profile.block_third_party_cookies}}" label="$i18n{thirdPartyCookie}" - sub-label="$i18n{thirdPartyCookieSublabel}" - pref="{{prefs.profile.block_third_party_cookies}}"> + sub-label="$i18n{thirdPartyCookieSublabel}"> </settings-toggle-button> </div> <category-setting-exceptions
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.js b/chrome/browser/resources/settings/privacy_page/privacy_page.js index ae72e25..faf61cd 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.js +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.js
@@ -113,9 +113,9 @@ // <if expr="_google_chrome and not chromeos"> /** @private */ - onMetricsReportingCheckboxTap_: function() { + onMetricsReportingControlTap_: function() { var browserProxy = settings.PrivacyPageBrowserProxyImpl.getInstance(); - var enabled = this.$.metricsReportingCheckbox.checked; + var enabled = this.$.metricsReportingControl.checked; browserProxy.setMetricsReportingEnabled(enabled); }, @@ -142,9 +142,9 @@ // </if> /** @private */ - onSafeBrowsingExtendedReportingCheckboxTap_: function() { + onSafeBrowsingExtendedReportingControlTap_: function() { var browserProxy = settings.PrivacyPageBrowserProxyImpl.getInstance(); - var enabled = this.$.safeBrowsingExtendedReportingCheckbox.checked; + var enabled = this.$.safeBrowsingExtendedReportingControl.checked; browserProxy.setSafeBrowsingExtendedReportingEnabled(enabled); },
diff --git a/chrome/browser/resources/settings/search_page/search_page.html b/chrome/browser/resources/settings/search_page/search_page.html index 0320f0f..96b4ba01 100644 --- a/chrome/browser/resources/settings/search_page/search_page.html +++ b/chrome/browser/resources/settings/search_page/search_page.html
@@ -5,7 +5,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="/controls/extension_controlled_indicator.html"> -<link rel="import" href="/controls/settings_checkbox.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/icons.html"> <link rel="import" href="/i18n_setup.html"> <link rel="import" href="/route.html"> @@ -67,27 +67,27 @@ <template is="dom-if" if="[[googleNowAvailable_]]"> <!-- Google Now cards in the launcher --> <div class="settings-box continuation"> - <settings-checkbox id="googleNowEnable" - label="$i18n{searchEnableGoogleNowLabel}" - pref="{{prefs.google_now_launcher.enabled}}"> - </settings-checkbox> + <settings-toggle-button id="googleNowEnable" class="start" + pref="{{prefs.google_now_launcher.enabled}}" + label="$i18n{searchEnableGoogleNowLabel}"> + </settings-toggle-button> </div> </template> <template is="dom-if" if="[[hotwordInfo_.allowed]]"> <!-- Hotword (OK Google) --> <div class="settings-box two-line continuation"> - <settings-checkbox id="hotwordSearchEnable" class="start" + <settings-toggle-button id="hotwordSearchEnable" class="start" + pref="{{hotwordSearchEnablePref_}}" label="$i18n{searchOkGoogleLabel}" sub-label="[[getHotwordSearchEnableSubLabel_( hotwordInfo_.alwaysOn)]]" - pref="{{hotwordSearchEnablePref_}}" on-change="onHotwordSearchEnableChange_"> <a href="$i18nRaw{hotwordLearnMoreUrl}" target="_blank" on-tap="doNothing_"> $i18n{searchOkGoogleLearnMore} </a> - </settings-checkbox> + </settings-toggle-button> <div class="secondary-action" hidden$="[[!getShowHotwordSearchRetrain_(hotwordInfo_.*)]]"> <paper-button on-tap="onRetrainTap_" class="secondary-button">
diff --git a/chrome/browser/resources/settings/system_page/system_page.html b/chrome/browser/resources/settings/system_page/system_page.html index 9a264d6..db416e60 100644 --- a/chrome/browser/resources/settings/system_page/system_page.html +++ b/chrome/browser/resources/settings/system_page/system_page.html
@@ -3,7 +3,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="/controls/controlled_button.html"> <link rel="import" href="/controls/extension_controlled_indicator.html"> -<link rel="import" href="/controls/settings_checkbox.html"> +<link rel="import" href="/controls/settings_toggle_button.html"> <link rel="import" href="/lifetime_browser_proxy.html"> <link rel="import" href="/prefs/prefs.html"> <link rel="import" href="/settings_shared_css.html"> @@ -14,19 +14,21 @@ <style include="settings-shared"></style> <div class="settings-box block first"> <if expr="not is_macosx"> - <settings-checkbox label="$i18n{backgroundAppsLabel}" - pref="{{prefs.background_mode.enabled}}"> - </settings-checkbox> + <settings-toggle-button + pref="{{prefs.background_mode.enabled}}" + label="$i18n{backgroundAppsLabel}"> + </settings-toggle-button> </if> - <div id="hardware-acceleration" class="layout horizontal center"> - <settings-checkbox class="flex" label="$i18n{hardwareAccelerationLabel}" - pref="{{prefs.hardware_acceleration_mode.enabled}}"> - </settings-checkbox> + <settings-toggle-button class="flex" id="hardwareAcceleration" + pref="{{prefs.hardware_acceleration_mode.enabled}}" + label="$i18n{hardwareAccelerationLabel}"> <template is="dom-if" if="[[shouldShowRestart_( prefs.hardware_acceleration_mode.enabled.value)]]"> - <paper-button on-tap="onRestartTap_">$i18n{restart}</paper-button> + <paper-button on-tap="onRestartTap_" class="more-actions"> + $i18n{restart} + </paper-button> </template> - </div> + </settings-toggle-button> </div> <div class="settings-box"> <controlled-button class="primary-button" pref="[[prefs.proxy]]"
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui.css b/chrome/browser/resources/vr_shell/vr_shell_ui.css index af1f1ed..534047c 100644 --- a/chrome/browser/resources/vr_shell/vr_shell_ui.css +++ b/chrome/browser/resources/vr_shell/vr_shell_ui.css
@@ -126,6 +126,8 @@ } #omnibox-border { + --fadeTimeMs: 500; + --fadeYOffset: -0.1; --statusBarColor: rgb(66, 133, 244); background-color: #ececec; border-radius: 200px;
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui.js b/chrome/browser/resources/vr_shell/vr_shell_ui.js index 93ad0b05..6f0802e 100644 --- a/chrome/browser/resources/vr_shell/vr_shell_ui.js +++ b/chrome/browser/resources/vr_shell/vr_shell_ui.js
@@ -5,8 +5,8 @@ var vrShellUi = (function() { 'use strict'; - let scene = new ui.Scene(); - let sceneManager; + let ui = new scene.Scene(); + let uiManager; let uiRootElement = document.querySelector('#ui'); let uiStyle = window.getComputedStyle(uiRootElement); @@ -38,13 +38,13 @@ element.setSize( this.SCREEN_HEIGHT * this.SCREEN_RATIO, this.SCREEN_HEIGHT); element.setTranslation(0, 0, -this.BROWSING_SCREEN_DISTANCE); - this.elementId = scene.addElement(element); + this.elementId = ui.addElement(element); } setEnabled(enabled) { let update = new api.UiElementUpdate(); update.setVisible(enabled); - scene.updateElement(this.elementId, update); + ui.updateElement(this.elementId, update); } setFullscreen(enabled) { @@ -54,7 +54,7 @@ } else { anim.setTranslation(0, 0, -this.BROWSING_SCREEN_DISTANCE); } - scene.addAnimation(anim); + ui.addAnimation(anim); } // TODO(crbug/643815): Add a method setting aspect ratio (and possible @@ -81,11 +81,13 @@ // Pull additional custom properties from CSS. let style = window.getComputedStyle(domElement); + this.translationX = getStyleFloat(style, '--tranX'); + this.translationY = getStyleFloat(style, '--tranY'); + this.translationZ = getStyleFloat(style, '--tranZ'); element.setTranslation( - getStyleFloat(style, '--tranX'), getStyleFloat(style, '--tranY'), - getStyleFloat(style, '--tranZ')); + this.translationX, this.translationY, this.translationZ); - this.uiElementId = scene.addElement(element); + this.uiElementId = ui.addElement(element); this.uiAnimationId = -1; this.domElement = domElement; } @@ -109,10 +111,10 @@ let anim = new api.Animation(this.uiElementId, ANIM_DURATION); anim.setTranslation(0, 0, distanceForward); if (this.uiAnimationId >= 0) { - scene.removeAnimation(this.uiAnimationId); + ui.removeAnimation(this.uiAnimationId); } - this.uiAnimationId = scene.addAnimation(anim); - scene.flush(); + this.uiAnimationId = ui.addAnimation(anim); + ui.flush(); } onMouseEnter() { @@ -159,7 +161,7 @@ let position = new api.UiElement(0, 0, 0, 0); position.setVisible(false); position.setTranslation(startPosition + i * BUTTON_SPACING, -0.68, -1); - let id = scene.addElement(position); + let id = ui.addElement(position); let domId = descriptors[i][0]; let callback = descriptors[i][1]; @@ -169,12 +171,12 @@ let update = new api.UiElementUpdate(); update.setParentId(id); update.setVisible(false); - scene.updateElement(element.uiElementId, update); + ui.updateElement(element.uiElementId, update); } this.reloadUiButton = new DomUiElement('#reload-ui-button'); this.reloadUiButton.domElement.addEventListener('click', function() { - scene.purge(); + ui.purge(); api.doAction(api.Action.RELOAD_UI); }); @@ -184,7 +186,7 @@ update.setScale(2.2, 2.2, 1); update.setTranslation(0, -0.6, 0.3); update.setAnchoring(api.XAnchoring.XNONE, api.YAnchoring.YBOTTOM); - scene.updateElement(this.reloadUiButton.uiElementId, update); + ui.updateElement(this.reloadUiButton.uiElementId, update); } setEnabled(enabled) { @@ -201,11 +203,11 @@ for (let i = 0; i < this.buttons.length; i++) { let update = new api.UiElementUpdate(); update.setVisible(this.enabled); - scene.updateElement(this.buttons[i].uiElementId, update); + ui.updateElement(this.buttons[i].uiElementId, update); } let update = new api.UiElementUpdate(); update.setVisible(this.enabled && this.reloadUiEnabled); - scene.updateElement(this.reloadUiButton.uiElementId, update); + ui.updateElement(this.reloadUiButton.uiElementId, update); } }; @@ -229,7 +231,7 @@ update.setHitTestable(false); update.setVisible(false); update.setLockToFieldOfView(true); - scene.updateElement(this.webVrSecureWarning.uiElementId, update); + ui.updateElement(this.webVrSecureWarning.uiElementId, update); // Temporary WebVR security warning. This warning is shown in the center // of the field of view, for a limited period of time. @@ -240,7 +242,7 @@ update.setHitTestable(false); update.setVisible(false); update.setLockToFieldOfView(true); - scene.updateElement(this.transientWarning.uiElementId, update); + ui.updateElement(this.transientWarning.uiElementId, update); } setEnabled(enabled) { @@ -271,46 +273,48 @@ showOrHideWarnings(visible) { let update = new api.UiElementUpdate(); update.setVisible(visible); - scene.updateElement(this.webVrSecureWarning.uiElementId, update); + ui.updateElement(this.webVrSecureWarning.uiElementId, update); update = new api.UiElementUpdate(); update.setVisible(visible); - scene.updateElement(this.transientWarning.uiElementId, update); + ui.updateElement(this.transientWarning.uiElementId, update); } onTransientTimer() { let update = new api.UiElementUpdate(); update.setVisible(false); - scene.updateElement(this.transientWarning.uiElementId, update); + ui.updateElement(this.transientWarning.uiElementId, update); this.secureOriginTimer = null; - scene.flush(); + ui.flush(); } }; class Omnibox { - constructor(contentQuadId) { + constructor() { this.domUiElement = new DomUiElement('#omnibox-container'); this.enabled = false; + this.hidden = false; this.loading = false; this.loadingProgress = 0; this.level = 0; this.visibilityTimeout = 0; this.visibilityTimer = null; - this.visibleAfterTransition = false; this.nativeState = {}; // Initially invisible. let update = new api.UiElementUpdate(); update.setVisible(false); - scene.updateElement(this.domUiElement.uiElementId, update); + ui.updateElement(this.domUiElement.uiElementId, update); this.nativeState.visible = false; - // Pull colors from CSS so that Javascript can set the progress indicator - // gradient programmatically. + // Pull some CSS properties so that Javascript can reconfigure the omnibox + // programmatically. let border = this.domUiElement.domElement.querySelector('#omnibox-border'); let style = window.getComputedStyle(border); this.statusBarColor = getStyleString(style, '--statusBarColor'); this.backgroundColor = style.backgroundColor; + this.fadeTimeMs = getStyleFloat(style, '--fadeTimeMs'); + this.fadeYOffset = getStyleFloat(style, '--fadeYOffset'); // Listen to the end of transitions, so that the box can be natively // hidden after it finishes hiding itself. @@ -395,7 +399,7 @@ } onAnimationDone(e) { - if (e.propertyName == 'opacity' && !this.visibleAfterTransition) { + if (e.propertyName == 'opacity' && this.hidden) { this.setNativeVisibility(false); } } @@ -420,14 +424,24 @@ indicator.style.background = this.backgroundColor; } - // Make the box fade away if it's disappearing. - if (!this.loading && this.visibilityTimeout > 0 && - !this.visibilityTimer) { - document.querySelector('#omnibox-border').className = 'hidden'; - this.visibleAfterTransition = false; - } else { - document.querySelector('#omnibox-border').className = ''; - this.visibleAfterTransition = true; + let shouldBeHidden = + !this.loading && this.visibilityTimeout > 0 && !this.visibilityTimer; + if (shouldBeHidden != this.hidden) { + // Make the box fade away if it's disappearing. + this.hidden = shouldBeHidden; + document.querySelector('#omnibox-border').className = + this.hidden ? 'hidden' : ''; + + // Drop the position as it fades, or raise the position if appearing. + let yOffset = this.hidden ? this.fadeYOffset : 0; + let animation = + new api.Animation(this.domUiElement.uiElementId, this.fadeTimeMs); + animation.setTranslation( + this.domUiElement.translationX, + this.domUiElement.translationY + yOffset, + this.domUiElement.translationZ); + ui.addAnimation(animation); + ui.flush(); } this.setNativeVisibility(true); @@ -440,12 +454,12 @@ this.nativeState.visible = visible; let update = new api.UiElementUpdate(); update.setVisible(visible); - scene.updateElement(this.domUiElement.uiElementId, update); - scene.flush(); + ui.updateElement(this.domUiElement.uiElementId, update); + ui.flush(); } }; - class SceneManager { + class UiManager { constructor() { this.mode = api.Mode.UNKNOWN; this.menuMode = false; @@ -456,7 +470,7 @@ this.controls = new Controls(contentId); this.secureOriginWarnings = new SecureOriginWarnings(); - this.omnibox = new Omnibox(contentId); + this.omnibox = new Omnibox(); } setMode(mode, menuMode, fullscreen) { @@ -497,36 +511,36 @@ }; function initialize() { - sceneManager = new SceneManager(); - scene.flush(); + uiManager = new UiManager(); + ui.flush(); api.domLoaded(); } function command(dict) { if ('mode' in dict) { - sceneManager.setMode(dict['mode'], dict['menuMode'], dict['fullscreen']); + uiManager.setMode(dict['mode'], dict['menuMode'], dict['fullscreen']); } if ('securityLevel' in dict) { - sceneManager.setSecurityLevel(dict['securityLevel']); + uiManager.setSecurityLevel(dict['securityLevel']); } if ('webVRSecureOrigin' in dict) { - sceneManager.setWebVRSecureOrigin(dict['webVRSecureOrigin']); + uiManager.setWebVRSecureOrigin(dict['webVRSecureOrigin']); } if ('enableReloadUi' in dict) { - sceneManager.setReloadUiEnabled(dict['enableReloadUi']); + uiManager.setReloadUiEnabled(dict['enableReloadUi']); } if ('url' in dict) { let url = dict['url']; - sceneManager.omnibox.setURL(url['host'], url['path']); + uiManager.omnibox.setURL(url['host'], url['path']); } if ('loading' in dict) { - sceneManager.omnibox.setLoading(dict['loading']); + uiManager.omnibox.setLoading(dict['loading']); } if ('loadingProgress' in dict) { - sceneManager.omnibox.setLoadingProgress(dict['loadingProgress']); + uiManager.omnibox.setLoadingProgress(dict['loadingProgress']); } - scene.flush(); + ui.flush(); } return {
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui_api.js b/chrome/browser/resources/vr_shell/vr_shell_ui_api.js index 877a8ea5..967de17 100644 --- a/chrome/browser/resources/vr_shell/vr_shell_ui_api.js +++ b/chrome/browser/resources/vr_shell/vr_shell_ui_api.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var api = new Object(); +var api = {}; /** * Enumeration of scene update commands.
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js b/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js index d3a1f905..00182e1 100644 --- a/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js +++ b/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js
@@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var ui = new Object(); +var scene = {}; /** - * The scene class assists in managing element and animations in the scene. - * It allows scene update commands to be queued in batches, and manages - * allocation of element and animation IDs. + * The scene class assists in managing element and animations in the UI. It + * allows UI update API commands to be queued in batches, and manages allocation + * of element and animation IDs. * * Examples: * - * var scene = new ui.Scene(); + * var ui = new scene.Scene(); * * // Add an element. * var el = new api.UiElement(100, 200, 50, 50); @@ -24,25 +24,25 @@ * // Place it just below the content quad edge. * el.setTranslation(0, -0.2, 0.0); * - * // Add it to the scene. - * var buttonId = scene.addElement(el); - * scene.flush(); + * // Add it to the ui. + * var buttonId = ui.addElement(el); + * ui.flush(); * * // Make the button twice as big. * var update = new api.UiElementUpdate(); * update.setSize(bunttonWidth * 2, buttonHeight * 2); - * scene.updateElement(buttonId, update); - * scene.flush(); + * ui.updateElement(buttonId, update); + * ui.flush(); * * // Animate the button size back to its original size, over 250 ms. * var resize = new api.Animation(buttonId, 250); * resize.setSize(buttonWidth, buttonHeight); - * scene.addAnimation(resize); - * scene.flush(); + * ui.addAnimation(resize); + * ui.flush(); * * @struct */ -ui.Scene = class { +scene.Scene = class { constructor() { /** @private {number} */ this.idIndex = 1;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 570b6d31..7d361a70 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1417,6 +1417,7 @@ "//ash/common/strings", "//ash/public/cpp", "//ash/public/interfaces", + "//ash/resources/vector_icons", "//components/session_manager/core", "//components/user_manager", "//services/ui/public/cpp",
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc index cda8e1d..8788a45 100644 --- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
@@ -156,8 +156,10 @@ AppShortcutLauncherItemController::GetApplicationList(int event_flags) { ChromeLauncherAppMenuItems items; // Add the application name to the menu. + base::string16 app_title = LauncherControllerHelper::GetAppTitle( + launcher_controller()->profile(), app_id()); items.push_back( - base::MakeUnique<ChromeLauncherAppMenuItem>(GetTitle(), nullptr, false)); + base::MakeUnique<ChromeLauncherAppMenuItem>(app_title, nullptr, false)); std::vector<content::WebContents*> content_list = GetRunningApplications(); @@ -216,11 +218,6 @@ return Activate(ash::LAUNCH_FROM_UNKNOWN); } -base::string16 AppShortcutLauncherItemController::GetTitle() { - return LauncherControllerHelper::GetAppTitle(launcher_controller()->profile(), - app_id()); -} - ash::ShelfMenuModel* AppShortcutLauncherItemController::CreateApplicationMenu( int event_flags) { return new LauncherApplicationMenuItemModel(GetApplicationList(event_flags));
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h index 5bbccc6..7ba7958c 100644 --- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h +++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
@@ -48,7 +48,6 @@ ChromeLauncherAppMenuItems GetApplicationList(int event_flags) override; ash::ShelfItemDelegate::PerformedAction ItemSelected( const ui::Event& event) override; - base::string16 GetTitle() override; ash::ShelfMenuModel* CreateApplicationMenu(int event_flags) override; void Close() override;
diff --git a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc index 82ee61f76..fa22849f 100644 --- a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc
@@ -110,8 +110,11 @@ ChromeLauncherAppMenuItems AppWindowLauncherItemController::GetApplicationList( int event_flags) { ChromeLauncherAppMenuItems items; + // Add the application name to the menu. + base::string16 app_title = LauncherControllerHelper::GetAppTitle( + launcher_controller()->profile(), app_id()); items.push_back( - base::MakeUnique<ChromeLauncherAppMenuItem>(GetTitle(), nullptr, false)); + base::MakeUnique<ChromeLauncherAppMenuItem>(app_title, nullptr, false)); return items; } @@ -132,11 +135,6 @@ } } -base::string16 AppWindowLauncherItemController::GetTitle() { - return LauncherControllerHelper::GetAppTitle(launcher_controller()->profile(), - app_id()); -} - void AppWindowLauncherItemController::OnWindowPropertyChanged( aura::Window* window, const void* key,
diff --git a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h index 106539f3..6f2b7df 100644 --- a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h +++ b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h
@@ -50,7 +50,6 @@ ChromeLauncherAppMenuItems GetApplicationList(int event_flags) override; ash::ShelfItemDelegate::PerformedAction ItemSelected( const ui::Event& event) override; - base::string16 GetTitle() override; void Close() override; // aura::WindowObserver overrides:
diff --git a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc index 7cb1bd8..2890ada 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc
@@ -37,20 +37,6 @@ return ash::ShelfItemDelegate::kNoAction; } -base::string16 ArcAppDeferredLauncherItemController::GetTitle() { - ArcAppListPrefs* arc_prefs = - ArcAppListPrefs::Get(launcher_controller()->profile()); - DCHECK(arc_prefs); - std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = arc_prefs->GetApp( - ArcAppWindowLauncherController::GetArcAppIdFromShelfAppId(app_id())); - if (!app_info) { - NOTREACHED(); - return base::string16(); - } - - return base::UTF8ToUTF16(app_info->name); -} - ash::ShelfMenuModel* ArcAppDeferredLauncherItemController::CreateApplicationMenu(int event_flags) { return nullptr;
diff --git a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h index f8530fe..ea33aa1 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h +++ b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h
@@ -35,7 +35,6 @@ // ash::ShelfItemDelegate ash::ShelfItemDelegate::PerformedAction ItemSelected( const ui::Event& event) override; - base::string16 GetTitle() override; ash::ShelfMenuModel* CreateApplicationMenu(int event_flags) override; void Close() override;
diff --git a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc index 422d2383..580bf05 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc +++ b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/ui/app_list/app_list_service.h" #include "chrome/browser/ui/app_list/app_list_syncable_service.h" @@ -305,7 +306,10 @@ const std::string app_id = GetTestApp1Id(kTestAppPackage); if (is_pinned()) { shelf_delegate()->PinAppWithID(app_id); - EXPECT_TRUE(shelf_delegate()->GetShelfIDForAppID(app_id)); + const ash::ShelfID shelf_id = shelf_delegate()->GetShelfIDForAppID(app_id); + EXPECT_TRUE(shelf_id); + const ash::ShelfItem* item = chrome_controller()->GetItem(shelf_id); + EXPECT_EQ(base::UTF8ToUTF16(kTestAppName), item->title); } else { EXPECT_FALSE(shelf_delegate()->GetShelfIDForAppID(app_id)); } @@ -328,7 +332,10 @@ // Launching non-ready Arc app creates item on shelf and spinning animation. arc::LaunchApp(profile(), app_id, ui::EF_LEFT_MOUSE_BUTTON); - EXPECT_TRUE(shelf_delegate()->GetShelfIDForAppID(app_id)); + const ash::ShelfID shelf_id = shelf_delegate()->GetShelfIDForAppID(app_id); + EXPECT_TRUE(shelf_id); + const ash::ShelfItem* item = chrome_controller()->GetItem(shelf_id); + EXPECT_EQ(base::UTF8ToUTF16(kTestAppName), item->title); AppAnimatedWaiter(app_id).Wait(); switch (test_action()) {
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc index 88cf6a5..6e3d940 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_v2app.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h" +#include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h" #include "ui/aura/window.h" #include "ui/base/base_window.h" @@ -49,20 +50,6 @@ } } -base::string16 ArcAppWindowLauncherItemController::GetTitle() { - ArcAppListPrefs* arc_prefs = - ArcAppListPrefs::Get(launcher_controller()->profile()); - DCHECK(arc_prefs); - std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = arc_prefs->GetApp( - ArcAppWindowLauncherController::GetArcAppIdFromShelfAppId(app_id())); - if (!app_info) { - NOTREACHED(); - return base::string16(); - } - - return base::UTF8ToUTF16(app_info->name); -} - ash::ShelfMenuModel* ArcAppWindowLauncherItemController::CreateApplicationMenu( int event_flags) { return new LauncherApplicationMenuItemModel(GetApplicationList(event_flags)); @@ -72,6 +59,8 @@ ArcAppWindowLauncherItemController::GetApplicationList(int event_flags) { ChromeLauncherAppMenuItems items = AppWindowLauncherItemController::GetApplicationList(event_flags); + base::string16 app_title = LauncherControllerHelper::GetAppTitle( + launcher_controller()->profile(), app_id()); for (auto it = windows().begin(); it != windows().end(); ++it) { // TODO(khmel): resolve correct icon here. size_t i = std::distance(windows().begin(), it); @@ -79,7 +68,7 @@ aura::Window* window = (*it)->GetNativeWindow(); items.push_back(base::MakeUnique<ChromeLauncherAppMenuItemV2App>( ((window && !window->GetTitle().empty()) ? window->GetTitle() - : GetTitle()), + : app_title), &image, app_id(), launcher_controller(), i, i == 0 /* has_leading_separator */)); }
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.h index c81ebc5..61bb3774e 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.h +++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.h
@@ -22,7 +22,6 @@ ~ArcAppWindowLauncherItemController() override; // LauncherItemController overrides: - base::string16 GetTitle() override; ash::ShelfItemDelegate::PerformedAction ItemSelected( const ui::Event& event) override; ash::ShelfMenuModel* CreateApplicationMenu(int event_flags) override;
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc index d8a7f541..8f541ef 100644 --- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
@@ -170,8 +170,9 @@ ChromeLauncherAppMenuItems items; bool found_tabbed_browser = false; // Add the application name to the menu. + base::string16 app_title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); items.push_back( - base::MakeUnique<ChromeLauncherAppMenuItem>(GetTitle(), nullptr, false)); + base::MakeUnique<ChromeLauncherAppMenuItem>(app_title, nullptr, false)); for (auto* browser : GetListOfActiveBrowsers()) { TabStripModel* tab_strip = browser->tab_strip_model(); if (tab_strip->active_index() == -1) @@ -223,10 +224,6 @@ return Activate(ash::LAUNCH_FROM_UNKNOWN); } -base::string16 BrowserShortcutLauncherItemController::GetTitle() { - return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); -} - ash::ShelfMenuModel* BrowserShortcutLauncherItemController::CreateApplicationMenu(int event_flags) { return new LauncherApplicationMenuItemModel(GetApplicationList(event_flags));
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h index f281de66..2b77cd06 100644 --- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h +++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
@@ -50,7 +50,6 @@ ChromeLauncherAppMenuItems GetApplicationList(int event_flags) override; ash::ShelfItemDelegate::PerformedAction ItemSelected( const ui::Event& event) override; - base::string16 GetTitle() override; ash::ShelfMenuModel* CreateApplicationMenu(int event_flags) override; void Close() override;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc index 045b01a9..a010ecdc 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
@@ -11,6 +11,7 @@ #include "ash/common/multi_profile_uma.h" #include "ash/common/shelf/shelf_model.h" #include "ash/common/shelf/wm_shelf.h" +#include "ash/common/strings/grit/ash_strings.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/wm_shell.h" #include "ash/common/wm_window.h" @@ -67,6 +68,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" +#include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" #include "components/favicon/content/content_favicon_driver.h" @@ -1279,6 +1281,7 @@ item.type = shelf_item_type; item.app_id = app_id; item.image = extensions::util::GetDefaultAppIcon(); + item.title = LauncherControllerHelper::GetAppTitle(profile(), app_id); ash::ShelfItemStatus new_state = GetAppState(app_id); if (new_state != ash::STATUS_CLOSED) @@ -1303,6 +1306,7 @@ browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT; ResourceBundle& rb = ResourceBundle::GetSharedInstance(); browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32); + browser_shortcut.title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); ash::ShelfID id = model_->next_id(); model_->AddAt(0, browser_shortcut); id_to_item_controller_map_[id] = @@ -1445,10 +1449,19 @@ // AppSyncUIStateObserver: void ChromeLauncherControllerImpl::OnAppSyncUIStatusChanged() { - if (app_sync_ui_state_->status() == AppSyncUIState::STATUS_SYNCING) - model_->set_status(ash::ShelfModel::STATUS_LOADING); - else - model_->set_status(ash::ShelfModel::STATUS_NORMAL); + // Update the app list button title to reflect the syncing status. + base::string16 title = l10n_util::GetStringUTF16( + app_sync_ui_state_->status() == AppSyncUIState::STATUS_SYNCING + ? IDS_ASH_SHELF_APP_LIST_LAUNCHER_SYNCING_TITLE + : IDS_ASH_SHELF_APP_LIST_LAUNCHER_TITLE); + + const int app_list_index = model_->GetItemIndexForType(ash::TYPE_APP_LIST); + DCHECK_GE(app_list_index, 0); + ash::ShelfItem item = model_->items()[app_list_index]; + if (item.title != title) { + item.title = title; + model_->Set(app_list_index, item); + } } ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc index c24ec796..c0920ce6 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
@@ -267,7 +267,6 @@ const ui::Event& event) override { return kExistingWindowActivated; } - base::string16 GetTitle() override { return base::string16(); } ChromeLauncherAppMenuItems GetApplicationList(int event_flags) override { ChromeLauncherAppMenuItems items; items.push_back(base::MakeUnique<ChromeLauncherAppMenuItem>(
diff --git a/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc b/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc index 06423c8c..6efa7f3 100644 --- a/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc +++ b/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" +#include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/extensions/app_launch_params.h" #include "chrome/browser/ui/extensions/application_launch.h" @@ -103,25 +104,25 @@ base::string16 LauncherControllerHelper::GetAppTitle( Profile* profile, const std::string& app_id) { - base::string16 title; if (app_id.empty()) - return title; + return base::string16(); - // Get title if the app is an Arc app. + // Get the title if the app is an Arc app. ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile); - if (arc_prefs && arc_prefs->IsRegistered(app_id)) { + const std::string arc_app_id = + ArcAppWindowLauncherController::GetArcAppIdFromShelfAppId(app_id); + if (arc_prefs && arc_prefs->IsRegistered(arc_app_id)) { std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = - arc_prefs->GetApp(app_id); + arc_prefs->GetApp(arc_app_id); DCHECK(app_info.get()); if (app_info) - title = base::UTF8ToUTF16(app_info->name); - return title; + return base::UTF8ToUTF16(app_info->name); } const extensions::Extension* extension = GetExtensionByID(profile, app_id); if (extension) - title = base::UTF8ToUTF16(extension->name()); - return title; + return base::UTF8ToUTF16(extension->name()); + return base::string16(); } std::string LauncherControllerHelper::GetAppID(content::WebContents* tab) {
diff --git a/chrome/browser/ui/startup/startup_tab_provider.cc b/chrome/browser/ui/startup/startup_tab_provider.cc index c3aaac70..a069c99 100644 --- a/chrome/browser/ui/startup/startup_tab_provider.cc +++ b/chrome/browser/ui/startup/startup_tab_provider.cc
@@ -50,12 +50,23 @@ PrefService* local_state = g_browser_process->local_state(); bool has_seen_win10_promo = local_state && local_state->GetBoolean(prefs::kHasSeenWin10PromoPage); + // The set default browser operation can be disabled by the browser + // distribution (e.g. SxS Canary), or by enterprise policy. In these cases, + // the Win 10 promo page should not be displayed. + bool disabled_by_enterprise_policy = + local_state && + local_state->IsManagedPreference( + prefs::kDefaultBrowserSettingEnabled) && + !local_state->GetBoolean(prefs::kDefaultBrowserSettingEnabled); + bool set_default_browser_allowed = + !disabled_by_enterprise_policy && + shell_integration::CanSetAsDefaultBrowser(); bool is_default_browser = g_browser_process->CachedDefaultWebClientState() == shell_integration::IS_DEFAULT; - return CheckWin10OnboardingTabPolicy(is_first_run, has_seen_welcome_page, - has_seen_win10_promo, is_signed_in, - is_default_browser); + return CheckWin10OnboardingTabPolicy( + is_first_run, has_seen_welcome_page, has_seen_win10_promo, is_signed_in, + set_default_browser_allowed, is_default_browser); } #endif // defined(OS_WIN) @@ -135,12 +146,15 @@ bool has_seen_welcome_page, bool has_seen_win10_promo, bool is_signed_in, + bool set_default_browser_allowed, bool is_default_browser) { StartupTabs tabs; - if (!has_seen_win10_promo && !is_default_browser) + if (set_default_browser_allowed && !has_seen_win10_promo && + !is_default_browser) { tabs.emplace_back(GetWin10WelcomePageUrl(!is_first_run), false); - else if (!has_seen_welcome_page && !is_signed_in) + } else if (!has_seen_welcome_page && !is_signed_in) { tabs.emplace_back(GetWelcomePageUrl(!is_first_run), false); + } return tabs; } #endif
diff --git a/chrome/browser/ui/startup/startup_tab_provider.h b/chrome/browser/ui/startup/startup_tab_provider.h index 633ee02..96004fea 100644 --- a/chrome/browser/ui/startup/startup_tab_provider.h +++ b/chrome/browser/ui/startup/startup_tab_provider.h
@@ -68,11 +68,13 @@ #if defined(OS_WIN) // Determines which tabs should be shown according to onboarding/first run // policy, including promo content specific to Windows 10. - static StartupTabs CheckWin10OnboardingTabPolicy(bool is_first_run, - bool has_seen_welcome_page, - bool has_seen_win10_promo, - bool is_signed_in, - bool is_default_browser); + static StartupTabs CheckWin10OnboardingTabPolicy( + bool is_first_run, + bool has_seen_welcome_page, + bool has_seen_win10_promo, + bool is_signed_in, + bool set_default_browser_allowed, + bool is_default_browser); #endif // Processes first run URLs specified in Master Preferences file, replacing
diff --git a/chrome/browser/ui/startup/startup_tab_provider_unittest.cc b/chrome/browser/ui/startup/startup_tab_provider_unittest.cc index 226f0b79b..abd61979 100644 --- a/chrome/browser/ui/startup/startup_tab_provider_unittest.cc +++ b/chrome/browser/ui/startup/startup_tab_provider_unittest.cc
@@ -46,7 +46,7 @@ // Show Win 10 Welcome page if it has not been seen, but the standard page // has. StartupTabs output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy( - true, true, false, false, false); + true, true, false, false, true, false); ASSERT_EQ(1U, output.size()); EXPECT_EQ(StartupTabProviderImpl::GetWin10WelcomePageUrl(false), @@ -56,7 +56,7 @@ // Show standard Welcome page if the Win 10 Welcome page has been seen, but // the standard page has not. output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy( - true, false, true, false, false); + true, false, true, false, true, false); ASSERT_EQ(1U, output.size()); EXPECT_EQ(StartupTabProviderImpl::GetWelcomePageUrl(false), output[0].url); @@ -65,7 +65,7 @@ // If neither page has been seen, the Win 10 Welcome page takes precedence // this launch. output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy( - true, false, false, false, false); + true, false, false, false, true, false); ASSERT_EQ(1U, output.size()); EXPECT_EQ(StartupTabProviderImpl::GetWin10WelcomePageUrl(false), @@ -77,7 +77,7 @@ // Show a variant of the Win 10 Welcome page after first run, if it has not // been seen. StartupTabs output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy( - false, false, false, false, false); + false, false, false, false, true, false); ASSERT_EQ(1U, output.size()); EXPECT_EQ(StartupTabProviderImpl::GetWin10WelcomePageUrl(true), @@ -87,7 +87,7 @@ // Show a variant of the standard Welcome page after first run, if the Win 10 // Welcome page has already been seen but the standard has not. output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy( - false, false, true, false, false); + false, false, true, false, true, false); ASSERT_EQ(1U, output.size()); EXPECT_EQ(StartupTabProviderImpl::GetWelcomePageUrl(true), output[0].url); @@ -97,14 +97,14 @@ TEST(StartupTabProviderTest, CheckWin10OnboardingTabPolicy_Negative) { // Do not show either page if it has already been shown. StartupTabs output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy( - true, true, true, false, false); + true, true, true, false, true, false); EXPECT_TRUE(output.empty()); // If Chrome is already the default browser, don't show the Win 10 Welcome // page, and don't preempt the standard Welcome page. output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy( - true, false, false, false, true); + true, false, false, false, true, true); ASSERT_EQ(1U, output.size()); EXPECT_EQ(StartupTabProviderImpl::GetWelcomePageUrl(false), output[0].url); @@ -112,10 +112,28 @@ // If the user is signed in, block showing the standard Welcome page. output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy( - true, false, true, true, false); + true, false, true, true, true, false); EXPECT_TRUE(output.empty()); } + +TEST(StartupTabProviderTest, + CheckWin10OnboardingTabPolicy_SetDefaultBrowserNotAllowed) { + // Skip the Win 10 promo if setting the default browser is not allowed. + StartupTabs output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy( + true, false, false, false, false, false); + + ASSERT_EQ(1U, output.size()); + EXPECT_EQ(StartupTabProviderImpl::GetWelcomePageUrl(false), output[0].url); + + // After first run, no onboarding content is displayed when setting the + // default browser is not allowed. + output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy( + true, true, false, false, false, false); + + EXPECT_TRUE(output.empty()); +} + #endif TEST(StartupTabProviderTest, CheckMasterPrefsTabPolicy) {
diff --git a/chrome/browser/ui/views/frame/browser_header_painter_ash.cc b/chrome/browser/ui/views/frame/browser_header_painter_ash.cc index 45d2a559..c61cb3f 100644 --- a/chrome/browser/ui/views/frame/browser_header_painter_ash.cc +++ b/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
@@ -7,6 +7,7 @@ #include "ash/common/ash_layout_constants.h" #include "ash/common/frame/caption_buttons/frame_caption_button_container_view.h" #include "ash/common/frame/header_painter_util.h" +#include "ash/resources/vector_icons/vector_icons.h" #include "base/logging.h" // DCHECK #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/browser.h" @@ -22,7 +23,6 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/skia_util.h" -#include "ui/gfx/vector_icons_public.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -285,29 +285,27 @@ } void BrowserHeaderPainterAsh::UpdateCaptionButtons() { - caption_button_container_->SetButtonImage( - ash::CAPTION_BUTTON_ICON_MINIMIZE, - gfx::VectorIconId::WINDOW_CONTROL_MINIMIZE); - caption_button_container_->SetButtonImage( - ash::CAPTION_BUTTON_ICON_CLOSE, gfx::VectorIconId::WINDOW_CONTROL_CLOSE); + caption_button_container_->SetButtonImage(ash::CAPTION_BUTTON_ICON_MINIMIZE, + ash::kWindowControlMinimizeIcon); + caption_button_container_->SetButtonImage(ash::CAPTION_BUTTON_ICON_CLOSE, + ash::kWindowControlCloseIcon); caption_button_container_->SetButtonImage( ash::CAPTION_BUTTON_ICON_LEFT_SNAPPED, - gfx::VectorIconId::WINDOW_CONTROL_LEFT_SNAPPED); + ash::kWindowControlLeftSnappedIcon); caption_button_container_->SetButtonImage( ash::CAPTION_BUTTON_ICON_RIGHT_SNAPPED, - gfx::VectorIconId::WINDOW_CONTROL_RIGHT_SNAPPED); + ash::kWindowControlRightSnappedIcon); - gfx::VectorIconId size_icon_id = gfx::VectorIconId::WINDOW_CONTROL_MAXIMIZE; + const gfx::VectorIcon* size_icon = &ash::kWindowControlMaximizeIcon; gfx::Size button_size( GetAshLayoutSize(AshLayoutSize::BROWSER_RESTORED_CAPTION_BUTTON)); if (frame_->IsMaximized() || frame_->IsFullscreen()) { - size_icon_id = gfx::VectorIconId::WINDOW_CONTROL_RESTORE; + size_icon = &ash::kWindowControlRestoreIcon; button_size = GetAshLayoutSize(AshLayoutSize::BROWSER_MAXIMIZED_CAPTION_BUTTON); } caption_button_container_->SetButtonImage( - ash::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, - size_icon_id); + ash::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, *size_icon); caption_button_container_->SetButtonSize(button_size); }
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc index 871efc0..3e5cd88a 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc
@@ -16,7 +16,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/ref_counted_memory.h" #include "base/strings/string_split.h" -#include "base/task_runner_util.h" +#include "base/task_scheduler/post_task.h" #include "chrome/browser/printing/pwg_raster_converter.h" #include "components/cloud_devices/common/cloud_device_description.h" #include "components/cloud_devices/common/printer_description.h" @@ -69,10 +69,9 @@ // Callback to PWG raster conversion. // Posts a task to update print job with info about file containing converted -// PWG raster data. The task is posted to |slow_task_runner|. +// PWG raster data. void UpdateJobFileInfo( std::unique_ptr<extensions::PrinterProviderPrintJob> job, - const scoped_refptr<base::TaskRunner>& slow_task_runner, const ExtensionPrinterHandler::PrintJobCallback& callback, bool success, const base::FilePath& pwg_file_path) { @@ -81,8 +80,11 @@ return; } - base::PostTaskAndReplyWithResult( - slow_task_runner.get(), FROM_HERE, + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, base::TaskTraits() + .WithShutdownBehavior( + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) + .MayBlock(), base::Bind(&UpdateJobFileInfoOnWorkerThread, pwg_file_path, base::Passed(&job)), callback); @@ -122,12 +124,8 @@ } // namespace ExtensionPrinterHandler::ExtensionPrinterHandler( - content::BrowserContext* browser_context, - const scoped_refptr<base::TaskRunner>& slow_task_runner) - : browser_context_(browser_context), - slow_task_runner_(slow_task_runner), - weak_ptr_factory_(this) { -} + content::BrowserContext* browser_context) + : browser_context_(browser_context), weak_ptr_factory_(this) {} ExtensionPrinterHandler::~ExtensionPrinterHandler() { } @@ -274,8 +272,7 @@ data.get(), PWGRasterConverter::GetConversionSettings(printer_description, page_size), PWGRasterConverter::GetBitmapSettings(printer_description, ticket), - base::Bind(&UpdateJobFileInfo, base::Passed(&job), slow_task_runner_, - callback)); + base::Bind(&UpdateJobFileInfo, base::Passed(&job), callback)); } void ExtensionPrinterHandler::DispatchPrintJob(
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler.h b/chrome/browser/ui/webui/print_preview/extension_printer_handler.h index 3a0c9f5..183d172 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.h +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.h
@@ -19,7 +19,6 @@ class DictionaryValue; class ListValue; class RefCountedMemory; -class TaskRunner; } namespace content { @@ -49,9 +48,7 @@ using PrintJobCallback = base::Callback<void( std::unique_ptr<extensions::PrinterProviderPrintJob>)>; - ExtensionPrinterHandler( - content::BrowserContext* browser_context, - const scoped_refptr<base::TaskRunner>& slow_task_runner); + explicit ExtensionPrinterHandler(content::BrowserContext* browser_context); ~ExtensionPrinterHandler() override; @@ -122,8 +119,6 @@ std::unique_ptr<printing::PWGRasterConverter> pwg_raster_converter_; int pending_enumeration_count_ = 0; - scoped_refptr<base::TaskRunner> slow_task_runner_; - base::WeakPtrFactory<ExtensionPrinterHandler> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ExtensionPrinterHandler);
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc index 64a80c50..56c50d1 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
@@ -22,7 +22,6 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/test/values_test_util.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "chrome/browser/extensions/test_extension_environment.h" #include "chrome/browser/printing/pwg_raster_converter.h" @@ -462,8 +461,8 @@ void SetUp() override { extensions::PrinterProviderAPIFactory::GetInstance()->SetTestingFactory( env_.profile(), &BuildTestingPrinterProviderAPI); - extension_printer_handler_.reset(new ExtensionPrinterHandler( - env_.profile(), base::ThreadTaskRunnerHandle::Get())); + extension_printer_handler_.reset( + new ExtensionPrinterHandler(env_.profile())); pwg_raster_converter_ = new FakePWGRasterConverter(); extension_printer_handler_->SetPWGRasterConverterForTesting(
diff --git a/chrome/browser/ui/webui/print_preview/printer_handler.cc b/chrome/browser/ui/webui/print_preview/printer_handler.cc index 9e6f3dac..14dad12 100644 --- a/chrome/browser/ui/webui/print_preview/printer_handler.cc +++ b/chrome/browser/ui/webui/print_preview/printer_handler.cc
@@ -4,12 +4,11 @@ #include "chrome/browser/ui/webui/print_preview/printer_handler.h" -#include "base/threading/worker_pool.h" #include "chrome/browser/ui/webui/print_preview/extension_printer_handler.h" // static std::unique_ptr<PrinterHandler> PrinterHandler::CreateForExtensionPrinters( content::BrowserContext* browser_context) { - return std::unique_ptr<ExtensionPrinterHandler>(new ExtensionPrinterHandler( - browser_context, base::WorkerPool::GetTaskRunner(true))); + return std::unique_ptr<ExtensionPrinterHandler>( + new ExtensionPrinterHandler(browser_context)); }
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc index 17f7a10..dbaaf2b 100644 --- a/chrome/installer/util/install_util.cc +++ b/chrome/installer/util/install_util.cc
@@ -319,11 +319,6 @@ env->UnSetVar(kEnvProgramFilesPath); } -bool InstallUtil::IsMultiInstall(bool system_install) { - ProductState state; - return state.Initialize(system_install) && state.is_multi_install(); -} - bool CheckIsChromeSxSProcess() { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); CHECK(command_line);
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h index fb8d7a84..198d3385 100644 --- a/chrome/installer/util/install_util.h +++ b/chrome/installer/util/install_util.h
@@ -92,9 +92,6 @@ // with fresh data. static void ResetIsPerUserInstallForTest(); - // Returns true if Chrome at |system_level| is a multi install. - static bool IsMultiInstall(bool system_install); - // Returns true if this is running setup process for Chrome SxS (as // indicated by the presence of --chrome-sxs on the command line) or if this // is running Chrome process from the Chrome SxS installation (as indicated
diff --git a/chrome/installer/util/installation_state.cc b/chrome/installer/util/installation_state.cc index 271f513..68e548f 100644 --- a/chrome/installer/util/installation_state.cc +++ b/chrome/installer/util/installation_state.cc
@@ -12,6 +12,7 @@ #include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/google_update_constants.h" #include "chrome/installer/util/install_util.h" +#include "chrome/installer/util/util_constants.h" namespace installer { @@ -117,7 +118,7 @@ &dw_value) == ERROR_SUCCESS) && (dw_value != 0); // Multi-install is a legacy option that is read for the sole purpose of // migrating clients away from it. - multi_install_ = uninstall_command_.HasSwitch(switches::kMultiInstall); + multi_install_ = uninstall_command_.HasSwitch("multi-install"); } // Read from the ClientStateMedium key. Values here override those in
diff --git a/chrome/installer/util/master_preferences.cc b/chrome/installer/util/master_preferences.cc index ef58f813..2f7ccb6 100644 --- a/chrome/installer/util/master_preferences.cc +++ b/chrome/installer/util/master_preferences.cc
@@ -163,12 +163,10 @@ } // Strip multi-install from the dictionary, if present. This ensures that any - // code that probes the dictionary directly to check for multi-install (rather - // than calling is_multi_install()) receives false. The updated dictionary is - // not written back to disk. - master_dictionary_->Remove(std::string(master_preferences::kDistroDict) + - '.' + master_preferences::kMultiInstall, - nullptr); + // code that probes the dictionary directly to check for multi-install + // receives false. The updated dictionary is not written back to disk. + master_dictionary_->Remove( + std::string(master_preferences::kDistroDict) + ".multi_install", nullptr); // Cache a pointer to the distribution dictionary. Ignore errors if any. master_dictionary_->GetDictionary(installer::master_preferences::kDistroDict,
diff --git a/chrome/installer/util/master_preferences.h b/chrome/installer/util/master_preferences.h index 9f1a569..4c570486 100644 --- a/chrome/installer/util/master_preferences.h +++ b/chrome/installer/util/master_preferences.h
@@ -170,8 +170,6 @@ return preferences_read_from_file_; } - bool is_multi_install() const { return false; } - // Returns a reference to this MasterPreferences' root dictionary of values. const base::DictionaryValue& master_dictionary() const { return *master_dictionary_.get();
diff --git a/chrome/installer/util/master_preferences_constants.cc b/chrome/installer/util/master_preferences_constants.cc index e65450b..0af4ab94 100644 --- a/chrome/installer/util/master_preferences_constants.cc +++ b/chrome/installer/util/master_preferences_constants.cc
@@ -36,7 +36,6 @@ "suppress_first_run_default_browser_prompt"; const char kMsi[] = "msi"; const char kMsiProductId[] = "msi_product_id"; - const char kMultiInstall[] = "multi_install"; const char kRequireEula[] = "require_eula"; const char kSystemLevel[] = "system_level"; const char kVerboseLogging[] = "verbose_logging";
diff --git a/chrome/installer/util/master_preferences_constants.h b/chrome/installer/util/master_preferences_constants.h index cb394167..92bbe4b 100644 --- a/chrome/installer/util/master_preferences_constants.h +++ b/chrome/installer/util/master_preferences_constants.h
@@ -75,8 +75,6 @@ // String. The MSI Product ID under which the MSI stores its information. This // is used to update the DisplayVersion to match Chrome's version number. extern const char kMsiProductId[]; -// Boolean. Support installing multiple products at once. -extern const char kMultiInstall[]; // Boolean. Show EULA dialog before install. extern const char kRequireEula[]; // Boolean. Indicates that the first-run 'set-as-default' dialog should not be
diff --git a/chrome/installer/util/master_preferences_unittest.cc b/chrome/installer/util/master_preferences_unittest.cc index 8a5a3f8..019ac57 100644 --- a/chrome/installer/util/master_preferences_unittest.cc +++ b/chrome/installer/util/master_preferences_unittest.cc
@@ -321,23 +321,6 @@ base::CommandLine::FromString(chrome_cmd.str())); installer::MasterPreferences pref_chrome(chrome_install); - - EXPECT_FALSE(pref_chrome.is_multi_install()); -} - -TEST_F(MasterPreferencesTest, TestMultiInstallIgnoredConfig) { - using installer::switches::kMultiInstall; - using installer::switches::kChrome; - - std::wstringstream chrome_cmd, cf_cmd, chrome_cf_cmd; - chrome_cmd << "setup.exe --" << kMultiInstall << " --" << kChrome; - - base::CommandLine chrome_install( - base::CommandLine::FromString(chrome_cmd.str())); - - installer::MasterPreferences pref_chrome(chrome_install); - - EXPECT_FALSE(pref_chrome.is_multi_install()); } TEST_F(MasterPreferencesTest, EnforceLegacyCreateAllShortcutsFalse) {
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc index e768bf0d2..22a5465 100644 --- a/chrome/installer/util/util_constants.cc +++ b/chrome/installer/util/util_constants.cc
@@ -8,10 +8,6 @@ namespace switches { -// Install Chrome. -// Currently this is only required when used in combination with kMultiInstall. -const char kChrome[] = "chrome"; - // Run the installer for Chrome SxS. const char kChromeSxS[] = "chrome-sxs"; @@ -83,10 +79,6 @@ // Tells installer to expect to be run as a subsidiary to an MSI. const char kMsi[] = "msi"; -// Tells installer to install multiple products specified on the command line. -// (e.g. Chrome Frame, Chrome) -const char kMultiInstall[] = "multi-install"; - // Useful only when used with --update-setup-exe, otherwise ignored. It // specifies the full path where updated setup.exe will be stored. const char kNewSetupExe[] = "new-setup-exe";
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h index 4e9e5da..4d8e4521 100644 --- a/chrome/installer/util/util_constants.h +++ b/chrome/installer/util/util_constants.h
@@ -144,7 +144,6 @@ namespace switches { -extern const char kChrome[]; extern const char kChromeSxS[]; extern const char kConfigureUserSettings[]; extern const char kCriticalUpdateVersion[]; @@ -162,7 +161,6 @@ extern const char kLogFile[]; extern const char kMakeChromeDefault[]; extern const char kMsi[]; -extern const char kMultiInstall[]; extern const char kNewSetupExe[]; extern const char kOnOsUpgrade[]; extern const char kPreviousVersion[];
diff --git a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/guest.html b/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/guest.html deleted file mode 100644 index 39c42a3..0000000 --- a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/guest.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!doctype html> -<!-- - * Copyright (c) 2014 The Chromium Authors. All rights reserved. Use of this - * source code is governed by a BSD-style license that can be found in the - * LICENSE file. ---> -<html> -<head> - <title>ChromeVox test title</title> -</head> -<body> - <div>Some text</div> -</body> -</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/main.html b/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/main.html deleted file mode 100644 index c4da227..0000000 --- a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/main.html +++ /dev/null
@@ -1,12 +0,0 @@ -<!doctype html> -<!-- - * Copyright (c) 2014 The Chromium Authors. All rights reserved. Use of this - * source code is governed by a BSD-style license that can be found in the - * LICENSE file. ---> -<html> -<body> - <div id="webview-tag-container"></div> - <script src="main.js"></script> -</body> -</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/main.js b/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/main.js deleted file mode 100644 index de92c73b..0000000 --- a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/main.js +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var startTest = function() { - chrome.test.sendMessage('guest-loaded'); -}; - -chrome.test.getConfig(function(config) { - var guestURL = 'http://localhost:' + config.testServer.port + - '/extensions/platform_apps/web_view/chromevox_injection/guest.html'; - document.querySelector('#webview-tag-container').innerHTML = - '<webview style="width: 10px; height: 10px; margin: 0; padding: 0;"' + - ' src="' + guestURL + '"' + - '></webview>'; - startTest(); -});
diff --git a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/manifest.json b/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/manifest.json deleted file mode 100644 index fdbcce1f..0000000 --- a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/manifest.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "name": "<webview> ChromeVox injection test.", - "version": "1", - "permissions": [ - "webview" - ], - "app": { - "background": { - "scripts": ["test.js"] - } - } -}
diff --git a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/test.js b/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/test.js deleted file mode 100644 index a80d274..0000000 --- a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/test.js +++ /dev/null
@@ -1,7 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -chrome.app.runtime.onLaunched.addListener(function() { - chrome.app.window.create('main.html', {}, function () {}); -});
diff --git a/chrome/test/data/webui/settings/android_apps_page_test.js b/chrome/test/data/webui/settings/android_apps_page_test.js index 52d8bc41..95a80c2 100644 --- a/chrome/test/data/webui/settings/android_apps_page_test.js +++ b/chrome/test/data/webui/settings/android_apps_page_test.js
@@ -61,17 +61,17 @@ cr.webUIListenerCallback( 'android-apps-info-update', {appReady: false}); Polymer.dom.flush(); - var checkbox = androidAppsPage.$$('#enabledCheckbox'); - assertTrue(!!checkbox); - assertFalse(checkbox.disabled); - assertFalse(checkbox.checked); + var control = androidAppsPage.$$('#enabled'); + assertTrue(!!control); + assertFalse(control.disabled); + assertFalse(control.checked); var managed = androidAppsPage.$$('#manageApps'); assertTrue(!!managed); assertTrue(managed.hidden); - MockInteractions.tap(checkbox.$.checkbox); + MockInteractions.tap(control.$.control); Polymer.dom.flush(); - assertTrue(checkbox.checked); + assertTrue(control.checked); }); }); @@ -88,15 +88,15 @@ cr.webUIListenerCallback( 'android-apps-info-update', {appReady: true}); Polymer.dom.flush(); - var checkbox = androidAppsPage.$$('#enabledCheckbox'); - assertTrue(!!checkbox); - assertFalse(checkbox.disabled); - assertTrue(checkbox.checked); + var control = androidAppsPage.$$('#enabled'); + assertTrue(!!control); + assertFalse(control.disabled); + assertTrue(control.checked); var managed = androidAppsPage.$$('#manageApps'); assertTrue(!!managed); assertFalse(managed.hidden); - MockInteractions.tap(checkbox.$.checkbox); + MockInteractions.tap(control.$.control); cr.webUIListenerCallback( 'android-apps-info-update', {appReady: false}); Polymer.dom.flush(); @@ -108,7 +108,7 @@ assertTrue(!!actionButton); MockInteractions.tap(actionButton); Polymer.dom.flush(); - assertFalse(checkbox.checked); + assertFalse(control.checked); assertTrue(managed.hidden); }); });
diff --git a/chrome/test/data/webui/settings/date_time_page_tests.js b/chrome/test/data/webui/settings/date_time_page_tests.js index c88bc51..7cf96a7 100644 --- a/chrome/test/data/webui/settings/date_time_page_tests.js +++ b/chrome/test/data/webui/settings/date_time_page_tests.js
@@ -112,7 +112,7 @@ function verifyAutoDetectSetting(autoDetect) { assertEquals(autoDetect, dateTime.$$('settings-dropdown-menu').disabled); - assertEquals(autoDetect, dateTime.$.timeZoneAutoDetectCheckbox.checked); + assertEquals(autoDetect, dateTime.$.timeZoneAutoDetect.checked); } function verifyPolicy(policy) { @@ -128,7 +128,7 @@ assertEquals(0, indicator.clientHeight); } - assertEquals(policy, dateTime.$.timeZoneAutoDetectCheckbox.disabled); + assertEquals(policy, dateTime.$.timeZoneAutoDetect.disabled); } function verifyTimeZonesPopulated(populated) { @@ -151,7 +151,7 @@ verifyPolicy(false); // Disable auto-detect. - MockInteractions.tap(dateTime.$.timeZoneAutoDetectCheckbox); + MockInteractions.tap(dateTime.$.timeZoneAutoDetect); verifyAutoDetectSetting(false); assertTrue(getTimeZonesCalled); @@ -176,7 +176,7 @@ verifyTimeZonesPopulated(true); // Enable auto-detect. - MockInteractions.tap(dateTime.$.timeZoneAutoDetectCheckbox); + MockInteractions.tap(dateTime.$.timeZoneAutoDetect); verifyAutoDetectSetting(true); done(); }); @@ -195,7 +195,7 @@ verifyPolicy(true); // Cannot disable auto-detect. - MockInteractions.tap(dateTime.$.timeZoneAutoDetectCheckbox); + MockInteractions.tap(dateTime.$.timeZoneAutoDetect); verifyAutoDetectSetting(true); assertFalse(getTimeZonesCalled); @@ -230,7 +230,7 @@ verifyPolicy(false); // User can disable auto-detect. - MockInteractions.tap(dateTime.$.timeZoneAutoDetectCheckbox); + MockInteractions.tap(dateTime.$.timeZoneAutoDetect); verifyAutoDetectSetting(false); done(); });
diff --git a/chrome/test/data/webui/settings/device_page_tests.js b/chrome/test/data/webui/settings/device_page_tests.js index c6b6a9b..477d274 100644 --- a/chrome/test/data/webui/settings/device_page_tests.js +++ b/chrome/test/data/webui/settings/device_page_tests.js
@@ -274,7 +274,7 @@ test('mouse', function() { expectLT(0, pointersPage.$.mouse.offsetHeight); - expectFalse(pointersPage.$$('#mouse settings-checkbox').checked); + expectFalse(pointersPage.$$('#mouse settings-toggle-button').checked); var slider = assert(pointersPage.$$('#mouse cr-slider')); expectEquals(4, slider.value);
diff --git a/chrome/test/data/webui/settings/metrics_reporting_tests.js b/chrome/test/data/webui/settings/metrics_reporting_tests.js index 37ff7d68..de2f12c 100644 --- a/chrome/test/data/webui/settings/metrics_reporting_tests.js +++ b/chrome/test/data/webui/settings/metrics_reporting_tests.js
@@ -22,8 +22,8 @@ return testBrowserProxy.whenCalled('getMetricsReporting').then(function() { Polymer.dom.flush(); - var checkbox = page.$.metricsReportingCheckbox; - assertEquals(testBrowserProxy.metricsReporting.enabled, checkbox.checked); + var control = page.$.metricsReportingControl; + assertEquals(testBrowserProxy.metricsReporting.enabled, control.checked); var indicatorVisible = !!page.$$('#indicator'); assertEquals(testBrowserProxy.metricsReporting.managed, indicatorVisible); @@ -34,13 +34,13 @@ cr.webUIListenerCallback('metrics-reporting-change', changedMetrics); Polymer.dom.flush(); - assertEquals(changedMetrics.enabled, checkbox.checked); + assertEquals(changedMetrics.enabled, control.checked); indicatorVisible = !!page.$$('#indicator'); assertEquals(changedMetrics.managed, indicatorVisible); var toggled = !changedMetrics.enabled; - MockInteractions.tap(checkbox); + MockInteractions.tap(control); return testBrowserProxy.whenCalled('setMetricsReportingEnabled', toggled); }); });
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_test.js b/chrome/test/data/webui/settings/people_page_sync_page_test.js index c4a0e808..b8cd5c4 100644 --- a/chrome/test/data/webui/settings/people_page_sync_page_test.js +++ b/chrome/test/data/webui/settings/people_page_sync_page_test.js
@@ -196,21 +196,21 @@ }); test('SettingIndividualDatatypes', function() { - var syncAllDataTypesCheckbox = syncPage.$.syncAllDataTypesCheckbox; - assertFalse(syncAllDataTypesCheckbox.disabled); - assertTrue(syncAllDataTypesCheckbox.checked); + var syncAllDataTypesControl = syncPage.$.syncAllDataTypesControl; + assertFalse(syncAllDataTypesControl.disabled); + assertTrue(syncAllDataTypesControl.checked); - // Assert that all the individual datatype checkboxes are disabled. - var datatypeCheckboxes = syncPage + // Assert that all the individual datatype controls are disabled. + var datatypeControls = syncPage .$$('#configure') - .querySelectorAll('paper-checkbox.list-item'); - for (var box of datatypeCheckboxes) { - assertTrue(box.disabled); - assertTrue(box.checked); + .querySelectorAll('.list-item paper-toggle-button'); + for (var control of datatypeControls) { + assertTrue(control.disabled); + assertTrue(control.checked); } - // Uncheck the Sync All checkbox. - MockInteractions.tap(syncAllDataTypesCheckbox); + // Uncheck the Sync All control. + MockInteractions.tap(syncAllDataTypesControl); function verifyPrefs(prefs) { var expected = getSyncAllPrefs(); @@ -219,16 +219,16 @@ cr.webUIListenerCallback('sync-prefs-changed', expected); - // Assert that all the individual datatype checkboxes are enabled. - for (var box of datatypeCheckboxes) { - assertFalse(box.disabled); - assertTrue(box.checked); + // Assert that all the individual datatype controls are enabled. + for (var control of datatypeControls) { + assertFalse(control.disabled); + assertTrue(control.checked); } browserProxy.resetResolver('setSyncDatatypes'); - // Test an arbitrarily-selected checkbox (extensions synced checkbox). - MockInteractions.tap(datatypeCheckboxes[3]); + // Test an arbitrarily-selected control (extensions synced control). + MockInteractions.tap(datatypeControls[3]); return browserProxy.whenCalled('setSyncDatatypes').then( function(prefs) { var expected = getSyncAllPrefs(); @@ -240,30 +240,6 @@ return browserProxy.whenCalled('setSyncDatatypes').then(verifyPrefs); }); - test('ClickingLinkDoesNotChangeCheckboxValue', function() { - var syncAllDataTypesCheckbox = syncPage.$.syncAllDataTypesCheckbox; - - // Uncheck the Sync All checkbox. - MockInteractions.tap(syncAllDataTypesCheckbox); - - // Make sure the checkbox is enabled and checked. - var link = syncPage.$.paymentLearnMore; - - // Suppress opening a new tab, since then the test will continue running - // on a background tab (which has throttled timers) and will timeout. - link.target = ''; - link.href = '#'; - - assertEquals('PAPER-CHECKBOX', link.parentNode.nodeName); - assertFalse(link.parentNode.disabled); - assertTrue(link.parentNode.checked); - - MockInteractions.tap(link); - - // The checkbox value should be unchanged after clicking on the link. - assertTrue(link.parentNode.checked); - }); - test('RadioBoxesEnabledWhenUnencrypted', function() { // Verify that the encryption radio boxes are enabled. assertFalse(encryptWithGoogle.disabled);
diff --git a/chrome/test/data/webui/settings/privacy_page_test.js b/chrome/test/data/webui/settings/privacy_page_test.js index f16097d..5a2f2362 100644 --- a/chrome/test/data/webui/settings/privacy_page_test.js +++ b/chrome/test/data/webui/settings/privacy_page_test.js
@@ -260,18 +260,18 @@ 'getSafeBrowsingExtendedReporting').then(function() { Polymer.dom.flush(); - // Checkbox starts checked by default - var checkbox = page.$.safeBrowsingExtendedReportingCheckbox; - assertEquals(true, checkbox.checked); + // Control starts checked by default + var control = page.$.safeBrowsingExtendedReportingControl; + assertEquals(true, control.checked); // Notification from browser can uncheck the box cr.webUIListenerCallback('safe-browsing-extended-reporting-change', false); Polymer.dom.flush(); - assertEquals(false, checkbox.checked); + assertEquals(false, control.checked); // Tapping on the box will check it again. - MockInteractions.tap(checkbox); + MockInteractions.tap(control); return testBrowserProxy.whenCalled('getSafeBrowsingExtendedReporting', true); });
diff --git a/chrome/test/data/webui/settings/search_page_test.js b/chrome/test/data/webui/settings/search_page_test.js index c8efd1b5..a8394f17 100644 --- a/chrome/test/data/webui/settings/search_page_test.js +++ b/chrome/test/data/webui/settings/search_page_test.js
@@ -109,11 +109,11 @@ assertFalse(browserProxy.hotwordSearchEnabled); assertFalse(page.hotwordSearchEnablePref_.value); - var checkbox = page.$$('#hotwordSearchEnable'); - assertTrue(!!checkbox); - assertFalse(checkbox.disabled); - assertFalse(checkbox.checked); - MockInteractions.tap(checkbox.$.checkbox); + var control = page.$$('#hotwordSearchEnable'); + assertTrue(!!control); + assertFalse(control.disabled); + assertFalse(control.checked); + MockInteractions.tap(control.$.control); Polymer.dom.flush(); return browserProxy.whenCalled('setHotwordSearchEnabled'); }).then(function() { @@ -137,11 +137,11 @@ assertFalse(page.hotwordInfo_.alwaysOn); assertFalse(page.hotwordInfo_.enabled); - var checkbox = page.$$('#hotwordSearchEnable'); - assertTrue(!!checkbox); - assertFalse(checkbox.disabled); - assertFalse(checkbox.checked); - MockInteractions.tap(checkbox.$.checkbox); + var control = page.$$('#hotwordSearchEnable'); + assertTrue(!!control); + assertFalse(control.disabled); + assertFalse(control.checked); + MockInteractions.tap(control.$.control); Polymer.dom.flush(); return browserProxy.whenCalled('setHotwordSearchEnabled'); }).then(function() { @@ -155,10 +155,10 @@ Polymer.dom.flush(); assertTrue(page.googleNowAvailable_); - var checkbox = page.$$('#googleNowEnable'); - assertTrue(!!checkbox); - assertFalse(checkbox.disabled); - assertFalse(checkbox.checked); + var control = page.$$('#googleNowEnable'); + assertTrue(!!control); + assertFalse(control.disabled); + assertFalse(control.checked); page.prefs = { google_now_launcher: { @@ -169,8 +169,8 @@ } }; Polymer.dom.flush(); - assertFalse(checkbox.disabled); - assertTrue(checkbox.checked); + assertFalse(control.disabled); + assertTrue(control.checked); }); }); });
diff --git a/chrome/test/data/webui/settings/system_page_tests.js b/chrome/test/data/webui/settings/system_page_tests.js index a9f2e219..7de7af1 100644 --- a/chrome/test/data/webui/settings/system_page_tests.js +++ b/chrome/test/data/webui/settings/system_page_tests.js
@@ -66,18 +66,18 @@ teardown(function() { systemPage.remove(); }); test('restart button', function() { - var checkbox = systemPage.$$('#hardware-acceleration settings-checkbox'); - expectEquals(checkbox.checked, HARDWARE_ACCELERATION_AT_STARTUP); + var control = systemPage.$.hardwareAcceleration; + expectEquals(control.checked, HARDWARE_ACCELERATION_AT_STARTUP); // Restart button should be hidden by default. - expectFalse(!!systemPage.$$('#hardware-acceleration paper-button')); + expectFalse(!!control.querySelector('paper-button')); systemPage.set('prefs.hardware_acceleration_mode.enabled.value', !HARDWARE_ACCELERATION_AT_STARTUP); Polymer.dom.flush(); - expectNotEquals(checkbox.checked, HARDWARE_ACCELERATION_AT_STARTUP); + expectNotEquals(control.checked, HARDWARE_ACCELERATION_AT_STARTUP); - var restart = systemPage.$$('#hardware-acceleration paper-button'); + var restart = control.querySelector('paper-button'); expectTrue(!!restart); // The "RESTART" button should be showing now. MockInteractions.tap(restart);
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn index 6b997da6..0423c4b 100644 --- a/components/arc/BUILD.gn +++ b/components/arc/BUILD.gn
@@ -193,6 +193,7 @@ source_set("unit_tests") { testonly = true sources = [ + "arc_service_manager_unittest.cc", "arc_session_runner_unittest.cc", "bluetooth/arc_bluetooth_bridge_unittest.cc", "bluetooth/bluetooth_struct_traits_unittest.cc",
diff --git a/components/arc/arc_service_manager.cc b/components/arc/arc_service_manager.cc index 73ea36e..f2a81d15 100644 --- a/components/arc/arc_service_manager.cc +++ b/components/arc/arc_service_manager.cc
@@ -4,8 +4,6 @@ #include "components/arc/arc_service_manager.h" -#include <utility> - #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/task_runner.h" @@ -83,9 +81,32 @@ return arc_bridge_service_.get(); } -void ArcServiceManager::AddService(std::unique_ptr<ArcService> service) { +bool ArcServiceManager::AddServiceInternal( + const std::string& name, + std::unique_ptr<ArcService> service) { DCHECK(thread_checker_.CalledOnValidThread()); - services_.emplace_back(std::move(service)); + if (!name.empty() && services_.count(name) != 0) { + LOG(ERROR) << "Ignoring registration of service with duplicate name: " + << name; + return false; + } + services_.insert(std::make_pair(name, std::move(service))); + return true; +} + +ArcService* ArcServiceManager::GetNamedServiceInternal( + const std::string& name) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (name.empty()) { + LOG(ERROR) << "kArcServiceName[] should be a fully-qualified class name."; + return nullptr; + } + auto service = services_.find(name); + if (service == services_.end()) { + LOG(ERROR) << "Named service " << name << " not found"; + return nullptr; + } + return service->second.get(); } void ArcServiceManager::AddObserver(Observer* observer) {
diff --git a/components/arc/arc_service_manager.h b/components/arc/arc_service_manager.h index cf37287..7db5fe7 100644 --- a/components/arc/arc_service_manager.h +++ b/components/arc/arc_service_manager.h
@@ -6,6 +6,10 @@ #define COMPONENTS_ARC_ARC_SERVICE_MANAGER_H_ #include <memory> +#include <string> +#include <type_traits> +#include <unordered_map> +#include <utility> #include <vector> #include "base/macros.h" @@ -22,6 +26,40 @@ class ArcIntentHelperObserver; class ArcService; +namespace internal { + +// If an ArcService is declared with a name, e.g.: +// +// class MyArcService : public ArcService { +// public: +// static const char kArcServiceName[]; +// ... +// }; +// +// it can then be retrieved from ArcServiceManager in a type-safe way using +// GetService<T>(). This two functions allow AddService() to get the name only +// if it was provided, or use an empty string otherwise. +// +// Although the typename is always specified explicitly by the caller, the +// parameter is required in order for SFINAE to work correctly. It is not used +// and can be nullptr, though. +// +// In order to avoid collisions, kArcServiceName should be the fully-qualified +// name of the class. +template <typename T> +decltype(T::kArcServiceName, std::string()) GetArcServiceName(T* unused) { + if (strlen(T::kArcServiceName) == 0) + LOG(ERROR) << "kArcServiceName[] should be a fully-qualified class name."; + return T::kArcServiceName; +} + +template <typename T> +std::string GetArcServiceName(...) { + return std::string(); +} + +} // namespace internal + // Manages creation and destruction of services that communicate with the ARC // instance via the ArcBridgeService. class ArcServiceManager { @@ -43,8 +81,22 @@ // class was created on. ArcBridgeService* arc_bridge_service(); - // Adds a service to the managed services list. - void AddService(std::unique_ptr<ArcService> service); + // Adds a service to the managed services list. Returns false if another + // named service with that name had already been added. + template <typename T> + bool AddService(std::unique_ptr<T> service) { + return AddServiceInternal(internal::GetArcServiceName<T>(nullptr), + std::move(service)); + } + + // Gets the named service from the managed services list. This uses SFINAE, so + // you can only call this function if the service specified by T provides a + // static member variable called kArcServiceName[] (otherwise this will not + // compile). + template <typename T> + T* GetService() { + return static_cast<T*>(GetNamedServiceInternal(T::kArcServiceName)); + } // Gets the global instance of the ARC Service Manager. This can only be // called on the thread that this class was created on. @@ -82,6 +134,11 @@ private: class IntentHelperObserverImpl; // implemented in arc_service_manager.cc. + // Helper methods for AddService and GetService. + bool AddServiceInternal(const std::string& name, + std::unique_ptr<ArcService> service); + ArcService* GetNamedServiceInternal(const std::string& name); + base::ThreadChecker thread_checker_; scoped_refptr<base::TaskRunner> blocking_task_runner_; @@ -89,7 +146,7 @@ std::unique_ptr<ArcIntentHelperObserver> intent_helper_observer_; std::unique_ptr<ArcBridgeService> arc_bridge_service_; - std::vector<std::unique_ptr<ArcService>> services_; + std::unordered_multimap<std::string, std::unique_ptr<ArcService>> services_; scoped_refptr<ActivityIconLoader> icon_loader_; scoped_refptr<LocalActivityResolver> activity_resolver_;
diff --git a/components/arc/arc_service_manager_unittest.cc b/components/arc/arc_service_manager_unittest.cc new file mode 100644 index 0000000..98c4db8 --- /dev/null +++ b/components/arc/arc_service_manager_unittest.cc
@@ -0,0 +1,182 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> +#include <utility> + +#include "base/auto_reset.h" +#include "base/memory/ptr_util.h" +#include "components/arc/arc_bridge_service.h" +#include "components/arc/arc_service_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace arc { + +namespace { + +class AnonymousService : public ArcService { + public: + AnonymousService(ArcBridgeService* arc_bridge_service, bool* alive) + : ArcService(arc_bridge_service), alive_(alive, true) {} + ~AnonymousService() override = default; + + private: + base::AutoReset<bool> alive_; +}; + +class NamedService : public ArcService { + public: + static const char kArcServiceName[]; + NamedService(ArcBridgeService* arc_bridge_service, bool* alive) + : ArcService(arc_bridge_service), alive_(alive, true) {} + ~NamedService() override = default; + + private: + base::AutoReset<bool> alive_; +}; + +class DifferentNamedService : public ArcService { + public: + static const char kArcServiceName[]; + DifferentNamedService(ArcBridgeService* arc_bridge_service, bool* alive) + : ArcService(arc_bridge_service), alive_(alive, true) {} + ~DifferentNamedService() override = default; + + private: + base::AutoReset<bool> alive_; +}; + +class EmptyNamedService : public ArcService { + public: + static const char kArcServiceName[]; + EmptyNamedService(ArcBridgeService* arc_bridge_service, bool* alive) + : ArcService(arc_bridge_service), alive_(alive, true) {} + ~EmptyNamedService() override = default; + + private: + base::AutoReset<bool> alive_; +}; + +const char NamedService::kArcServiceName[] = + "arc::(anonymous namespace)::NamedService"; + +const char DifferentNamedService::kArcServiceName[] = + "arc::(anonymous namespace)::DifferentNamedService"; + +const char EmptyNamedService::kArcServiceName[] = ""; + +} // namespace + +class ArcServiceManagerTest : public testing::Test { + public: + ArcServiceManagerTest() = default; + + void SetUp() override { + arc_bridge_service_ = base::MakeUnique<ArcBridgeService>(); + } + + void TearDown() override { arc_bridge_service_.reset(); } + + ArcBridgeService* arc_bridge_service() { return arc_bridge_service_.get(); } + + private: + std::unique_ptr<ArcBridgeService> arc_bridge_service_; + + DISALLOW_COPY_AND_ASSIGN(ArcServiceManagerTest); +}; + +// Exercises the basic getter functionality of ArcServiceManager. +TEST_F(ArcServiceManagerTest, BasicGetter) { + bool named_service_alive = false; + + // ArcServiceManager is empty, GetService() should return nullptr. + auto manager = base::MakeUnique<ArcServiceManager>(nullptr); + EXPECT_EQ(nullptr, manager->GetService<NamedService>()); + + EXPECT_TRUE(manager->AddService(base::MakeUnique<NamedService>( + arc_bridge_service(), &named_service_alive))); + EXPECT_TRUE(named_service_alive); + EXPECT_NE(nullptr, manager->GetService<NamedService>()); + + // Finally, the service should not be alive anymore. + manager.reset(); + EXPECT_FALSE(named_service_alive); +} + +// There is no way to distinguish between anonymous services, so it should be +// possible to add them twice (not that it's recommended). +TEST_F(ArcServiceManagerTest, MultipleAnonymousServices) { + bool anonymous_service_alive = false; + bool second_anonymous_service_alive = false; + + auto manager = base::MakeUnique<ArcServiceManager>(nullptr); + + EXPECT_TRUE(manager->AddService(base::MakeUnique<AnonymousService>( + arc_bridge_service(), &anonymous_service_alive))); + EXPECT_TRUE(anonymous_service_alive); + EXPECT_TRUE(manager->AddService(base::MakeUnique<AnonymousService>( + arc_bridge_service(), &second_anonymous_service_alive))); + EXPECT_TRUE(second_anonymous_service_alive); + + // Finally, the individual services should not be alive anymore. + manager.reset(); + EXPECT_FALSE(anonymous_service_alive); + EXPECT_FALSE(second_anonymous_service_alive); +} + +// Named services can only be added once, but can still be retrieved. +TEST_F(ArcServiceManagerTest, MultipleNamedServices) { + bool named_service_alive = false; + bool second_named_service_alive = false; + bool different_named_service_alive = false; + + auto manager = base::MakeUnique<ArcServiceManager>(nullptr); + + auto named_service = base::MakeUnique<NamedService>(arc_bridge_service(), + &named_service_alive); + NamedService* raw_named_service = named_service.get(); + EXPECT_TRUE(named_service_alive); + EXPECT_TRUE(manager->AddService(std::move(named_service))); + auto second_named_service = base::MakeUnique<NamedService>( + arc_bridge_service(), &second_named_service_alive); + EXPECT_TRUE(second_named_service_alive); + // This will fail and immediately destroy the service. + EXPECT_FALSE(manager->AddService(std::move(second_named_service))); + EXPECT_FALSE(second_named_service_alive); + + // We should still be able to add a different-named service. + auto different_named_service = base::MakeUnique<DifferentNamedService>( + arc_bridge_service(), &different_named_service_alive); + DifferentNamedService* raw_different_named_service = + different_named_service.get(); + EXPECT_TRUE(different_named_service_alive); + EXPECT_TRUE(manager->AddService(std::move(different_named_service))); + + // And find both. + EXPECT_EQ(raw_named_service, manager->GetService<NamedService>()); + EXPECT_EQ(raw_different_named_service, + manager->GetService<DifferentNamedService>()); + + manager.reset(); + EXPECT_FALSE(named_service_alive); + EXPECT_FALSE(different_named_service_alive); +} + +// Named services with an empty name are treated as anonymous services. +// Developers shouldn't do that, though, and will trigger an error log. +TEST_F(ArcServiceManagerTest, EmptyNamedServices) { + bool empty_named_service_alive = false; + + auto manager = base::MakeUnique<ArcServiceManager>(nullptr); + + EXPECT_TRUE(manager->AddService(base::MakeUnique<EmptyNamedService>( + arc_bridge_service(), &empty_named_service_alive))); + EXPECT_TRUE(empty_named_service_alive); + EXPECT_EQ(nullptr, manager->GetService<EmptyNamedService>()); + + manager.reset(); + EXPECT_FALSE(empty_named_service_alive); +} + +} // namespace arc
diff --git a/components/browser_watcher/stability_data_names.cc b/components/browser_watcher/stability_data_names.cc index 27be25b..03cb921 100644 --- a/components/browser_watcher/stability_data_names.cc +++ b/components/browser_watcher/stability_data_names.cc
@@ -8,6 +8,9 @@ const char kStabilityChannel[] = "channel"; const char kStabilityExecutionPhase[] = "stability-execution-phase"; +const char kStabilityModuleAddress[] = "module-address"; +const char kStabilityModuleSize[] = "module-size"; +const char kStabilityModuleTimestamp[] = "module-timestamp"; const char kStabilityPlatform[] = "platform"; const char kStabilityProduct[] = "product"; const char kStabilitySpecialBuild[] = "special-build";
diff --git a/components/browser_watcher/stability_data_names.h b/components/browser_watcher/stability_data_names.h index 9143811..32fb640 100644 --- a/components/browser_watcher/stability_data_names.h +++ b/components/browser_watcher/stability_data_names.h
@@ -10,6 +10,9 @@ // Alphabetical list of stability data names. extern const char kStabilityChannel[]; extern const char kStabilityExecutionPhase[]; +extern const char kStabilityModuleAddress[]; +extern const char kStabilityModuleSize[]; +extern const char kStabilityModuleTimestamp[]; extern const char kStabilityPlatform[]; extern const char kStabilityProduct[]; extern const char kStabilitySpecialBuild[];
diff --git a/components/cronet/ios/cronet_environment.mm b/components/cronet/ios/cronet_environment.mm index 65a59172..03f36dd 100644 --- a/components/cronet/ios/cronet_environment.mm +++ b/components/cronet/ios/cronet_environment.mm
@@ -272,28 +272,18 @@ return; cache_path = cache_path.Append(FILE_PATH_LITERAL("cronet")); - std::unique_ptr<URLRequestContextConfig> config(new URLRequestContextConfig( - quic_enabled_, // Enable QUIC. - quic_enabled_ && quic_user_agent_id_.empty() - ? getDefaultQuicUserAgentId() - : quic_user_agent_id_, // QUIC User Agent ID. - http2_enabled_, // Enable SPDY. - false, // Enable SDCH - URLRequestContextConfig::DISK, // Type of http cache. - 0, // Max size of http cache in bytes. - false, // Disable caching for HTTP responses. - cache_path.value(), // Storage path for http cache and cookie storage. - user_agent_, // User-Agent request header field. - "{}", // JSON encoded experimental options. - "", // Data reduction proxy key. - "", // Data reduction proxy. - "", // Fallback data reduction proxy. - "", // Data reduction proxy secure proxy check URL. - std::move(mock_cert_verifier_), // MockCertVerifier to use for testing - // purposes. - false, // Enable network quality estimator. - true, // Enable bypassing of public key pinning for local trust anchors - "")); // Certificate verifier cache data. + URLRequestContextConfigBuilder context_config_builder; + context_config_builder.enable_quic = quic_enabled_; // Enable QUIC. + context_config_builder.enable_spdy = http2_enabled_; // Enable HTTP/2. + context_config_builder.http_cache = URLRequestContextConfig::DISK; + context_config_builder.storage_path = + cache_path.value(); // Storage path for http cache and cookie storage. + context_config_builder.user_agent = + user_agent_; // User-Agent request header field. + context_config_builder.mock_cert_verifier = std::move( + mock_cert_verifier_); // MockCertVerifier to use for testing purposes. + std::unique_ptr<URLRequestContextConfig> config = + context_config_builder.Build(); net::URLRequestContextBuilder context_builder;
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc index b93bf3d..5e1bc35 100644 --- a/components/cronet/url_request_context_config.cc +++ b/components/cronet/url_request_context_config.cc
@@ -392,4 +392,19 @@ // TODO(mef): Use |config| to set cookies. } +URLRequestContextConfigBuilder::URLRequestContextConfigBuilder() {} +URLRequestContextConfigBuilder::~URLRequestContextConfigBuilder() {} + +std::unique_ptr<URLRequestContextConfig> +URLRequestContextConfigBuilder::Build() { + return base::MakeUnique<URLRequestContextConfig>( + enable_quic, quic_user_agent_id, enable_spdy, enable_sdch, http_cache, + http_cache_max_size, load_disable_cache, storage_path, user_agent, + experimental_options, data_reduction_proxy_key, + data_reduction_primary_proxy, data_reduction_fallback_proxy, + data_reduction_secure_proxy_check_url, std::move(mock_cert_verifier), + enable_network_quality_estimator, + bypass_public_key_pinning_for_local_trust_anchors, cert_verifier_data); +} + } // namespace cronet
diff --git a/components/cronet/url_request_context_config.h b/components/cronet/url_request_context_config.h index f01564e..3ef5159a 100644 --- a/components/cronet/url_request_context_config.h +++ b/components/cronet/url_request_context_config.h
@@ -13,6 +13,7 @@ #include "base/memory/scoped_vector.h" #include "base/time/time.h" #include "net/base/hash_value.h" +#include "net/cert/cert_verifier.h" namespace base { class SequencedTaskRunner; @@ -176,6 +177,67 @@ DISALLOW_COPY_AND_ASSIGN(URLRequestContextConfig); }; +// Stores intermediate state for URLRequestContextConfig. Initializes with +// (mostly) sane defaults, then the appropriate member variables can be +// modified, and it can be finalized with Build(). +struct URLRequestContextConfigBuilder { + URLRequestContextConfigBuilder(); + ~URLRequestContextConfigBuilder(); + + // Finalize state into a URLRequestContextConfig. Must only be called once, + // as once |mock_cert_verifier| is moved into a URLRequestContextConfig, it + // cannot be used again. + std::unique_ptr<URLRequestContextConfig> Build(); + + // Enable QUIC. + bool enable_quic = false; + // QUIC User Agent ID. + std::string quic_user_agent_id = ""; + // Enable SPDY. + bool enable_spdy = true; + // Enable SDCH. + bool enable_sdch = false; + // Type of http cache. + URLRequestContextConfig::HttpCacheType http_cache = + URLRequestContextConfig::DISABLED; + // Max size of http cache in bytes. + int http_cache_max_size = 0; + // Disable caching for HTTP responses. Other information may be stored in + // the cache. + bool load_disable_cache = false; + // Storage path for http cache and cookie storage. + std::string storage_path = ""; + // User-Agent request header field. + std::string user_agent = ""; + // Experimental options encoded as a string in a JSON format containing + // experiments and their corresponding configuration options. The format + // is a JSON object with the name of the experiment as the key, and the + // configuration options as the value. An example: + // {"experiment1": {"option1": "option_value1", "option2": "option_value2", + // ...}, "experiment2: {"option3", "option_value3", ...}, ...} + std::string experimental_options = "{}"; + // Enable Data Reduction Proxy with authentication key. + std::string data_reduction_proxy_key = ""; + std::string data_reduction_primary_proxy = ""; + std::string data_reduction_fallback_proxy = ""; + std::string data_reduction_secure_proxy_check_url = ""; + + // Certificate verifier for testing. + std::unique_ptr<net::CertVerifier> mock_cert_verifier = nullptr; + + // Enable network quality estimator. + bool enable_network_quality_estimator = false; + + // Enable public key pinning bypass for local trust anchors. + bool bypass_public_key_pinning_for_local_trust_anchors = true; + + // Data to populate CertVerifierCache. + std::string cert_verifier_data = ""; + + private: + DISALLOW_COPY_AND_ASSIGN(URLRequestContextConfigBuilder); +}; + } // namespace cronet #endif // COMPONENTS_CRONET_URL_REQUEST_CONTEXT_CONFIG_H_
diff --git a/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedService.java b/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedService.java index f6e5c7f..2e57753 100644 --- a/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedService.java +++ b/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedService.java
@@ -33,8 +33,8 @@ private static final String VARIATIONS_SERVER_URL = "https://clientservices.googleapis.com/chrome-variations/seed?osname=android"; private static final int BUFFER_SIZE = 4096; - private static final int READ_TIMEOUT = 10000; // time in ms - private static final int REQUEST_TIMEOUT = 15000; // time in ms + private static final int READ_TIMEOUT = 3000; // time in ms + private static final int REQUEST_TIMEOUT = 1000; // time in ms // Values for the "Variations.FirstRun.SeedFetchResult" sparse histogram, which also logs // HTTP result codes. These are negative so that they don't conflict with the HTTP codes.
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 727e71e..0cf393c8 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1499,17 +1499,10 @@ "//third_party/webrtc/media:rtc_media_base", "//third_party/webrtc/modules/desktop_capture:primitives", ] - - if (is_linux || is_mac || is_win) { - sources += [ - "media/capture/desktop_capture_device.cc", - "media/capture/desktop_capture_device.h", - ] - deps += [ "//third_party/webrtc/modules/desktop_capture" ] - } } - # Desktop screen capture implementations that are not dependent on WebRTC. + # Desktop screen capture implementations, conditionally built depending on + # the available implementations for each platform. if (is_linux || is_mac || is_win) { defines += [ "ENABLE_SCREEN_CAPTURE=1" ] sources += [ @@ -1540,6 +1533,13 @@ "media/capture/window_activity_tracker_mac.mm", ] } + if (enable_webrtc) { + sources += [ + "media/capture/desktop_capture_device.cc", + "media/capture/desktop_capture_device.h", + ] + deps += [ "//third_party/webrtc/modules/desktop_capture" ] + } } if (is_win) {
diff --git a/content/browser/DEPS b/content/browser/DEPS index 21eafb20..71effe5c95 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS
@@ -66,6 +66,7 @@ "+third_party/WebKit/public/platform/WebGestureEvent.h", "+third_party/WebKit/public/platform/WebInputEvent.h", "+third_party/WebKit/public/platform/WebInsecureRequestPolicy.h", + "+third_party/WebKit/public/platform/WebMixedContentContextType.h", "+third_party/WebKit/public/platform/WebMouseEvent.h", "+third_party/WebKit/public/platform/WebMouseWheelEvent.h", "+third_party/WebKit/public/platform/WebNavigationHintType.h", @@ -80,9 +81,9 @@ "+third_party/WebKit/public/platform/modules/broadcastchannel/broadcast_channel.mojom.h", "+third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h", "+third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h", + "+third_party/WebKit/public/platform/modules/mediasession/media_session.mojom.h", "+third_party/WebKit/public/platform/modules/notifications/WebNotificationConstants.h", "+third_party/WebKit/public/platform/modules/notifications/notification.mojom.h", - "+third_party/WebKit/public/platform/modules/mediasession/media_session.mojom.h", "+third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom.h", "+third_party/WebKit/public/platform/modules/permissions/permission.mojom.h", "+third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h",
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index a4654300..4f55898 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -92,6 +92,16 @@ return rfh->IsCrossProcessSubframe() || !rfh->GetParent(); } +bool ShouldCreateDevToolsForNode(FrameTreeNode* ftn) { + return ShouldCreateDevToolsFor(ftn->current_frame_host()); +} + +static RenderFrameDevToolsAgentHost* GetAgentHostFor(FrameTreeNode* ftn) { + while (ftn && !ShouldCreateDevToolsForNode(ftn)) + ftn = ftn->parent(); + return FindAgentHost(ftn); +} + } // namespace // RenderFrameDevToolsAgentHost::FrameHostHolder ------------------------------- @@ -395,7 +405,7 @@ // static bool RenderFrameDevToolsAgentHost::IsNetworkHandlerEnabled( FrameTreeNode* frame_tree_node) { - RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node); + RenderFrameDevToolsAgentHost* agent_host = GetAgentHostFor(frame_tree_node); if (!agent_host || !agent_host->session()) return false; return protocol::NetworkHandler::FromSession(agent_host->session()) @@ -405,7 +415,7 @@ // static std::string RenderFrameDevToolsAgentHost::UserAgentOverride( FrameTreeNode* frame_tree_node) { - RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node); + RenderFrameDevToolsAgentHost* agent_host = GetAgentHostFor(frame_tree_node); if (!agent_host || !agent_host->session()) return std::string(); return protocol::NetworkHandler::FromSession(agent_host->session())
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc index eba07da5..8ed60813 100644 --- a/content/browser/frame_host/navigation_handle_impl.cc +++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -30,6 +30,7 @@ #include "content/public/common/url_constants.h" #include "net/base/net_errors.h" #include "net/url_request/redirect_info.h" +#include "third_party/WebKit/public/platform/WebMixedContentContextType.h" #include "url/gurl.h" #include "url/url_constants.h" @@ -92,6 +93,7 @@ navigation_start_(navigation_start), pending_nav_entry_id_(pending_nav_entry_id), request_context_type_(REQUEST_CONTEXT_TYPE_UNSPECIFIED), + mixed_content_context_type_(blink::WebMixedContentContextType::Blockable), should_replace_current_entry_(false), is_download_(false), is_stream_(false), @@ -315,6 +317,7 @@ WillStartRequest(method, resource_request_body, sanitized_referrer, has_user_gesture, transition, is_external_protocol, REQUEST_CONTEXT_TYPE_LOCATION, + blink::WebMixedContentContextType::Blockable, base::Bind(&UpdateThrottleCheckResult, &result)); // Reset the callback to ensure it will not be called later. @@ -422,6 +425,7 @@ ui::PageTransition transition, bool is_external_protocol, RequestContextType request_context_type, + blink::WebMixedContentContextType mixed_content_context_type, const ThrottleChecksFinishedCallback& callback) { if (method != "POST") DCHECK(!resource_request_body); @@ -435,6 +439,7 @@ transition_ = transition; is_external_protocol_ = is_external_protocol; request_context_type_ = request_context_type; + mixed_content_context_type_ = mixed_content_context_type; state_ = WILL_SEND_REQUEST; complete_callback_ = callback;
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h index 20a159a..cc02ac4 100644 --- a/content/browser/frame_host/navigation_handle_impl.h +++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -26,6 +26,7 @@ #include "content/public/browser/navigation_throttle.h" #include "content/public/browser/ssl_status.h" #include "content/public/common/request_context_type.h" +#include "third_party/WebKit/public/platform/WebMixedContentContextType.h" #include "url/gurl.h" struct FrameHostMsg_DidCommitProvisionalLoad_Params; @@ -155,6 +156,11 @@ return request_context_type_; } + blink::WebMixedContentContextType mixed_content_context_type() const { + DCHECK_GE(state_, WILL_SEND_REQUEST); + return mixed_content_context_type_; + } + // Get the unique id from the NavigationEntry associated with this // NavigationHandle. Note that a synchronous, renderer-initiated navigation // will not have a NavigationEntry associated with it, and this will return 0. @@ -221,6 +227,7 @@ ui::PageTransition transition, bool is_external_protocol, RequestContextType request_context_type, + blink::WebMixedContentContextType mixed_content_context_type, const ThrottleChecksFinishedCallback& callback); // Called when the URLRequest will be redirected in the network stack. @@ -398,6 +405,9 @@ // The fetch request context type. RequestContextType request_context_type_; + // The mixed content context type for potential mixed content checks. + blink::WebMixedContentContextType mixed_content_context_type_; + // This callback will be run when all throttle checks have been performed. ThrottleChecksFinishedCallback complete_callback_;
diff --git a/content/browser/frame_host/navigation_handle_impl_unittest.cc b/content/browser/frame_host/navigation_handle_impl_unittest.cc index 0a1ec53..8c9ef716 100644 --- a/content/browser/frame_host/navigation_handle_impl_unittest.cc +++ b/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -113,6 +113,7 @@ test_handle_->WillStartRequest( "GET", nullptr, Referrer(), false, ui::PAGE_TRANSITION_LINK, false, REQUEST_CONTEXT_TYPE_LOCATION, + blink::WebMixedContentContextType::Blockable, base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult, base::Unretained(this))); }
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 8a1007d..9f676eb 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -43,6 +43,7 @@ #include "net/base/url_util.h" #include "net/http/http_request_headers.h" #include "net/url_request/redirect_info.h" +#include "third_party/WebKit/public/platform/WebMixedContentContextType.h" #include "third_party/WebKit/public/web/WebSandboxFlags.h" namespace content { @@ -228,7 +229,9 @@ BeginNavigationParams(entry.extra_headers(), net::LOAD_NORMAL, false, // has_user_gestures false, // skip_service_worker - REQUEST_CONTEXT_TYPE_LOCATION, initiator), + REQUEST_CONTEXT_TYPE_LOCATION, + blink::WebMixedContentContextType::Blockable, + initiator), entry.ConstructRequestNavigationParams( frame_entry, is_same_document_history_load, is_history_navigation_in_new_child, @@ -239,7 +242,7 @@ controller->GetLastCommittedEntryIndex(), controller->GetEntryCount()), browser_initiated, - true, // may_transfer + true, // may_transfer &frame_entry, &entry)); return navigation_request; } @@ -357,6 +360,7 @@ common_params_.referrer), begin_params_.has_user_gesture, common_params_.transition, false, begin_params_.request_context_type, + begin_params_.mixed_content_context_type, base::Bind(&NavigationRequest::OnStartChecksComplete, base::Unretained(this))); return;
diff --git a/content/browser/loader/navigation_resource_throttle.cc b/content/browser/loader/navigation_resource_throttle.cc index 5ce1654f..6a7f6b6 100644 --- a/content/browser/loader/navigation_resource_throttle.cc +++ b/content/browser/loader/navigation_resource_throttle.cc
@@ -99,7 +99,8 @@ bool has_user_gesture, ui::PageTransition transition, bool is_external_protocol, - RequestContextType request_context_type) { + RequestContextType request_context_type, + blink::WebMixedContentContextType mixed_content_context_type) { DCHECK_CURRENTLY_ON(BrowserThread::UI); NavigationHandleImpl* navigation_handle = FindNavigationHandle(render_process_id, render_frame_host_id, callback); @@ -109,6 +110,7 @@ navigation_handle->WillStartRequest( method, resource_request_body, sanitized_referrer, has_user_gesture, transition, is_external_protocol, request_context_type, + mixed_content_context_type, base::Bind(&SendCheckResultToIOThread, callback)); } @@ -178,10 +180,12 @@ NavigationResourceThrottle::NavigationResourceThrottle( net::URLRequest* request, ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate, - RequestContextType request_context_type) + RequestContextType request_context_type, + blink::WebMixedContentContextType mixed_content_context_type) : request_(request), resource_dispatcher_host_delegate_(resource_dispatcher_host_delegate), request_context_type_(request_context_type), + mixed_content_context_type_(mixed_content_context_type), in_cross_site_transition_(false), on_transfer_done_result_(NavigationThrottle::DEFER), weak_ptr_factory_(this) {} @@ -214,7 +218,8 @@ request_->url(), Referrer(GURL(request_->referrer()), info->GetReferrerPolicy())), info->HasUserGesture(), info->GetPageTransition(), - is_external_protocol, request_context_type_)); + is_external_protocol, request_context_type_, + mixed_content_context_type_)); *defer = true; }
diff --git a/content/browser/loader/navigation_resource_throttle.h b/content/browser/loader/navigation_resource_throttle.h index a9685e3..62db169 100644 --- a/content/browser/loader/navigation_resource_throttle.h +++ b/content/browser/loader/navigation_resource_throttle.h
@@ -11,6 +11,7 @@ #include "content/public/browser/navigation_throttle.h" #include "content/public/browser/resource_throttle.h" #include "content/public/common/request_context_type.h" +#include "third_party/WebKit/public/platform/WebMixedContentContextType.h" namespace net { class URLRequest; @@ -27,7 +28,8 @@ NavigationResourceThrottle( net::URLRequest* request, ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate, - RequestContextType request_context_type); + RequestContextType request_context_type, + blink::WebMixedContentContextType mixed_content_context_type); ~NavigationResourceThrottle() override; // ResourceThrottle overrides: @@ -56,6 +58,7 @@ net::URLRequest* request_; ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate_; RequestContextType request_context_type_; + blink::WebMixedContentContextType mixed_content_context_type_; bool in_cross_site_transition_; NavigationThrottle::ThrottleCheckResult on_transfer_done_result_;
diff --git a/content/browser/loader/navigation_url_loader_unittest.cc b/content/browser/loader/navigation_url_loader_unittest.cc index 2b60f650..29fed3e 100644 --- a/content/browser/loader/navigation_url_loader_unittest.cc +++ b/content/browser/loader/navigation_url_loader_unittest.cc
@@ -106,9 +106,10 @@ std::unique_ptr<NavigationURLLoader> MakeTestLoader( const GURL& url, NavigationURLLoaderDelegate* delegate) { - BeginNavigationParams begin_params(std::string(), net::LOAD_NORMAL, false, - false, REQUEST_CONTEXT_TYPE_LOCATION, - url::Origin(url)); + BeginNavigationParams begin_params( + std::string(), net::LOAD_NORMAL, false, false, + REQUEST_CONTEXT_TYPE_LOCATION, + blink::WebMixedContentContextType::Blockable, url::Origin(url)); CommonNavigationParams common_params; common_params.url = url; std::unique_ptr<NavigationRequestInfo> request_info(
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index 6cd99e8f..c8351429 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -1684,6 +1684,7 @@ return AddStandardHandlers(request, request_data.resource_type, resource_context, request_data.fetch_request_context_type, + request_data.fetch_mixed_content_context_type, requester_info->appcache_service(), child_id, route_id, std::move(handler)); } @@ -1694,6 +1695,7 @@ ResourceType resource_type, ResourceContext* resource_context, RequestContextType fetch_request_context_type, + blink::WebMixedContentContextType fetch_mixed_content_context_type, AppCacheService* appcache_service, int child_id, int route_id, @@ -1712,7 +1714,8 @@ // thread is handled by the NavigationURLloader. if (!IsBrowserSideNavigationEnabled() && IsResourceTypeFrame(resource_type)) { throttles.push_back(base::MakeUnique<NavigationResourceThrottle>( - request, delegate_, fetch_request_context_type)); + request, delegate_, fetch_request_context_type, + fetch_mixed_content_context_type)); } if (delegate_) { @@ -2286,6 +2289,7 @@ handler = AddStandardHandlers( new_request.get(), resource_type, resource_context, info.begin_params.request_context_type, + info.begin_params.mixed_content_context_type, appcache_handle_core ? appcache_handle_core->GetAppCacheService() : nullptr, -1, // child_id
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h index 90a0112..3089f6a 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.h +++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -37,6 +37,7 @@ #include "ipc/ipc_message.h" #include "net/base/load_states.h" #include "net/base/request_priority.h" +#include "third_party/WebKit/public/platform/WebMixedContentContextType.h" #include "url/gurl.h" namespace base { @@ -618,6 +619,7 @@ ResourceType resource_type, ResourceContext* resource_context, RequestContextType fetch_request_context_type, + blink::WebMixedContentContextType fetch_mixed_content_context_type, AppCacheService* appcache_service, int child_id, int route_id,
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc index 9f3361f..f7706e9 100644 --- a/content/browser/loader/resource_dispatcher_host_unittest.cc +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -1083,9 +1083,10 @@ // Make a navigation request. TestNavigationURLLoaderDelegate delegate; - BeginNavigationParams begin_params(std::string(), net::LOAD_NORMAL, false, - false, REQUEST_CONTEXT_TYPE_LOCATION, - url::Origin(url)); + BeginNavigationParams begin_params( + std::string(), net::LOAD_NORMAL, false, false, + REQUEST_CONTEXT_TYPE_LOCATION, + blink::WebMixedContentContextType::Blockable, url::Origin(url)); CommonNavigationParams common_params; common_params.url = url; std::unique_ptr<NavigationRequestInfo> request_info( @@ -2641,9 +2642,11 @@ if (IsBrowserSideNavigationEnabled()) { // Create a NavigationRequest. TestNavigationURLLoaderDelegate delegate; - BeginNavigationParams begin_params(std::string(), net::LOAD_NORMAL, false, - false, REQUEST_CONTEXT_TYPE_LOCATION, - url::Origin(download_url)); + BeginNavigationParams begin_params( + std::string(), net::LOAD_NORMAL, false, false, + REQUEST_CONTEXT_TYPE_LOCATION, + blink::WebMixedContentContextType::Blockable, + url::Origin(download_url)); CommonNavigationParams common_params; common_params.url = download_url; std::unique_ptr<NavigationRequestInfo> request_info(
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc index 6af09c0..24880a57 100644 --- a/content/browser/renderer_host/media/video_capture_manager.cc +++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -40,17 +40,22 @@ #include "media/capture/video/video_capture_device_client.h" #include "media/capture/video/video_capture_device_factory.h" -#if defined(ENABLE_SCREEN_CAPTURE) && !defined(OS_ANDROID) +#if defined(ENABLE_SCREEN_CAPTURE) + +#if BUILDFLAG(ENABLE_WEBRTC) && !defined(OS_ANDROID) #include "content/browser/media/capture/desktop_capture_device.h" +#endif + #if defined(USE_AURA) #include "content/browser/media/capture/desktop_capture_device_aura.h" #endif -#endif -#if defined(ENABLE_SCREEN_CAPTURE) && defined(OS_ANDROID) +#if defined(OS_ANDROID) #include "content/browser/media/capture/screen_capture_device_android.h" #endif +#endif // defined(ENABLE_SCREEN_CAPTURE) + namespace { class VideoFrameConsumerFeedbackObserverOnTaskRunner @@ -707,8 +712,10 @@ #if defined(USE_AURA) video_capture_device = DesktopCaptureDeviceAura::Create(desktop_id); #endif // defined(USE_AURA) - if (!video_capture_device) - video_capture_device = DesktopCaptureDevice::Create(desktop_id); +#if BUILDFLAG(ENABLE_WEBRTC) + if (!video_capture_device) + video_capture_device = DesktopCaptureDevice::Create(desktop_id); +#endif // BUILDFLAG(ENABLE_WEBRTC) #endif // defined (OS_ANDROID) } #endif // defined(ENABLE_SCREEN_CAPTURE) @@ -1227,7 +1234,7 @@ media::VideoCaptureDevice* device, gfx::NativeViewId window_id) { DCHECK(IsOnDeviceThread()); -#if defined(ENABLE_SCREEN_CAPTURE) && !defined(OS_ANDROID) +#if defined(ENABLE_SCREEN_CAPTURE) && BUILDFLAG(ENABLE_WEBRTC) && !defined(OS_ANDROID) DesktopCaptureDevice* desktop_device = static_cast<DesktopCaptureDevice*>(device); desktop_device->SetNotificationWindowId(window_id);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 4fb8c88..4113b7d5 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1669,6 +1669,7 @@ switches::kDisable3DAPIs, switches::kDisableAcceleratedJpegDecoding, switches::kDisableAcceleratedVideoDecode, + switches::kDisableBackgroundTimerThrottling, switches::kDisableBlinkFeatures, switches::kDisableBreakpad, switches::kDisablePreferCompositingToLCDText,
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index bcb9a6fa..976b7fc 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -1174,10 +1174,12 @@ }; void DownloadImageTestInternal(Shell* shell, - const GURL &image_url, - int expected_http_status) { + const GURL& image_url, + int expected_http_status, + int expected_number_of_images) { using ::testing::_; using ::testing::InvokeWithoutArgs; + using ::testing::SizeIs; // Set up everything. DownloadImageObserver download_image_observer; @@ -1186,7 +1188,8 @@ // Set up expectation and stub. EXPECT_CALL(download_image_observer, - OnFinishDownloadImage(_, expected_http_status, _, _, _)); + OnFinishDownloadImage(_, expected_http_status, _, + SizeIs(expected_number_of_images), _)); ON_CALL(download_image_observer, OnFinishDownloadImage(_, _, _, _, _)) .WillByDefault( InvokeWithoutArgs(loop_runner.get(), &MessageLoopRunner::Quit)); @@ -1218,16 +1221,26 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DownloadImage_HttpImage) { ASSERT_TRUE(embedded_test_server()->Start()); - const GURL kImageUrl = - embedded_test_server()->GetURL("/image.jpg"); - DownloadImageTestInternal(shell(), kImageUrl, 200); + const GURL kImageUrl = embedded_test_server()->GetURL("/single_face.jpg"); + DownloadImageTestInternal(shell(), kImageUrl, 200, 1); } IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DownloadImage_Deny_FileImage) { + ASSERT_TRUE(embedded_test_server()->Start()); + shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html")); + + const GURL kImageUrl = GetTestUrl("", "single_face.jpg"); + DownloadImageTestInternal(shell(), kImageUrl, 0, 0); +} + +IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, + DownloadImage_Allow_FileImage) { + shell()->LoadURL(GetTestUrl("", "simple_page.html")); + const GURL kImageUrl = GetTestUrl("", "image.jpg"); - DownloadImageTestInternal(shell(), kImageUrl, 0); + DownloadImageTestInternal(shell(), kImageUrl, 0, 0); } IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DownloadImage_NoValidImage) { @@ -1242,6 +1255,19 @@ run_loop.Run(); } +IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DownloadImage_DataImage) { + const GURL kImageUrl = GURL( + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHE" + "lEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="); + DownloadImageTestInternal(shell(), kImageUrl, 0, 1); +} + +IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, + DownloadImage_InvalidDataImage) { + const GURL kImageUrl = GURL("data:image/png;invalid"); + DownloadImageTestInternal(shell(), kImageUrl, 0, 0); +} + class MouseLockDelegate : public WebContentsDelegate { public: // WebContentsDelegate:
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc index fd4e3167..88785e4 100644 --- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc +++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -1003,8 +1003,8 @@ } // Test that vertical overscroll updates are sent only when a user overscrolls -// vertically. -#if defined(OS_WIN) +// vertically. Flaky on several platforms. https://crbug.com/679420 +#if defined(OS_WIN) || defined(OS_CHROMEOS) #define MAYBE_VerticalOverscroll DISABLED_VerticalOverscroll #else #define MAYBE_VerticalOverscroll VerticalOverscroll
diff --git a/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc b/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc index 5708d60..9ac9311d 100644 --- a/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc +++ b/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc
@@ -70,14 +70,11 @@ &font_fallback, g_font_collection.Get(), sender); } - sk_sp<SkFontMgr> skia_font_manager(SkFontMgr_New_DirectWrite( - factory.Get(), g_font_collection.Get(), font_fallback.Get())); - blink::WebFontRendering::setSkiaFontManager(skia_font_manager.get()); + sk_sp<SkFontMgr> skia_font_manager = SkFontMgr_New_DirectWrite( + factory.Get(), g_font_collection.Get(), font_fallback.Get()); + blink::WebFontRendering::setSkiaFontManager(skia_font_manager); - // Add an extra ref for SetDefaultSkiaFactory, which keeps a ref but doesn't - // addref. - skia_font_manager->ref(); - SetDefaultSkiaFactory(skia_font_manager.get()); + SetDefaultSkiaFactory(std::move(skia_font_manager)); // When IDWriteFontFallback is not available (prior to Win8.1) Skia will // still attempt to use DirectWrite to determine fallback fonts (in
diff --git a/content/child/font_warmup_win.cc b/content/child/font_warmup_win.cc index 739246b..99d0139 100644 --- a/content/child/font_warmup_win.cc +++ b/content/child/font_warmup_win.cc
@@ -416,7 +416,7 @@ GdiFontPatchData* PatchGdiFontEnumeration(const base::FilePath& path) { if (!g_warmup_fontmgr) - g_warmup_fontmgr = SkFontMgr_New_DirectWrite(); + g_warmup_fontmgr = SkFontMgr_New_DirectWrite().release(); DCHECK(g_warmup_fontmgr); return new GdiFontPatchDataImpl(path); } @@ -429,8 +429,9 @@ g_fake_gdi_object_factory.Get().ResetObjectHandles(); } -void SetPreSandboxWarmupFontMgrForTesting(SkFontMgr* fontmgr) { - g_warmup_fontmgr = fontmgr; +void SetPreSandboxWarmupFontMgrForTesting(sk_sp<SkFontMgr> fontmgr) { + SkSafeUnref(g_warmup_fontmgr); + g_warmup_fontmgr = fontmgr.release(); } } // namespace content
diff --git a/content/child/font_warmup_win.h b/content/child/font_warmup_win.h index 3a89ef2..d62ce5f 100644 --- a/content/child/font_warmup_win.h +++ b/content/child/font_warmup_win.h
@@ -12,6 +12,7 @@ #include "content/common/content_export.h" class SkFontMgr; +template <typename T> class sk_sp; namespace content { @@ -39,7 +40,8 @@ // Sets the pre-sandbox warmup font manager directly. This should only be used // for testing the implementation. -CONTENT_EXPORT void SetPreSandboxWarmupFontMgrForTesting(SkFontMgr* fontmgr); +CONTENT_EXPORT void SetPreSandboxWarmupFontMgrForTesting( + sk_sp<SkFontMgr> fontmgr); // Directwrite connects to the font cache service to retrieve information about // fonts installed on the system etc. This works well outside the sandbox and
diff --git a/content/child/font_warmup_win_unittest.cc b/content/child/font_warmup_win_unittest.cc index 21ba20d..9494655b 100644 --- a/content/child/font_warmup_win_unittest.cc +++ b/content/child/font_warmup_win_unittest.cc
@@ -16,6 +16,7 @@ #include "base/sys_byteorder.h" #include "base/win/windows_version.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkString.h" #include "third_party/skia/include/core/SkTypeface.h" #include "third_party/skia/include/ports/SkFontMgr.h" @@ -130,7 +131,9 @@ class TestSkFontMgr : public SkFontMgr { public: - TestSkFontMgr() { content::SetPreSandboxWarmupFontMgrForTesting(this); } + TestSkFontMgr() { + content::SetPreSandboxWarmupFontMgrForTesting(sk_ref_sp(this)); + } ~TestSkFontMgr() override { content::SetPreSandboxWarmupFontMgrForTesting(nullptr); }
diff --git a/content/child/request_extra_data.cc b/content/child/request_extra_data.cc index 1b5ea2e..2d26828 100644 --- a/content/child/request_extra_data.cc +++ b/content/child/request_extra_data.cc
@@ -27,7 +27,8 @@ originated_from_service_worker_(false), initiated_in_secure_context_(false), is_prefetch_(false), - download_to_network_cache_only_(false) {} + download_to_network_cache_only_(false), + block_mixed_plugin_content_(false) {} RequestExtraData::~RequestExtraData() { }
diff --git a/content/child/request_extra_data.h b/content/child/request_extra_data.h index 553469e..d544989 100644 --- a/content/child/request_extra_data.h +++ b/content/child/request_extra_data.h
@@ -149,6 +149,15 @@ download_to_network_cache_only_ = download_to_cache; } + // Copy of the settings value determining if mixed plugin content should be + // blocked. + bool block_mixed_plugin_content() const { + return block_mixed_plugin_content_; + } + void set_block_mixed_plugin_content(bool block_mixed_plugin_content) { + block_mixed_plugin_content_ = block_mixed_plugin_content; + } + void CopyToResourceRequest(ResourceRequest* request) const; private: @@ -171,6 +180,7 @@ bool initiated_in_secure_context_; bool is_prefetch_; bool download_to_network_cache_only_; + bool block_mixed_plugin_content_; DISALLOW_COPY_AND_ASSIGN(RequestExtraData); };
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc index de9efa92..9c444531 100644 --- a/content/child/web_url_loader_impl.cc +++ b/content/child/web_url_loader_impl.cc
@@ -586,6 +586,9 @@ GetFetchRedirectModeForWebURLRequest(request); resource_request->fetch_request_context_type = GetRequestContextTypeForWebURLRequest(request); + resource_request->fetch_mixed_content_context_type = + GetMixedContentContextTypeForWebURLRequest(request); + resource_request->fetch_frame_type = GetRequestContextFrameTypeForWebURLRequest(request); resource_request->request_body =
diff --git a/content/child/web_url_loader_impl_unittest.cc b/content/child/web_url_loader_impl_unittest.cc index 01c19d4e..eb3c606c 100644 --- a/content/child/web_url_loader_impl_unittest.cc +++ b/content/child/web_url_loader_impl_unittest.cc
@@ -269,6 +269,7 @@ void DoStartAsyncRequest() { blink::WebURLRequest request{GURL(kTestURL)}; + request.setRequestContext(blink::WebURLRequest::RequestContextInternal); client()->loader()->loadAsynchronously(request, client()); ASSERT_TRUE(peer()); } @@ -276,6 +277,7 @@ void DoStartAsyncRequestWithPriority( blink::WebURLRequest::Priority priority) { blink::WebURLRequest request{GURL(kTestURL)}; + request.setRequestContext(blink::WebURLRequest::RequestContextInternal); request.setPriority(priority); client()->loader()->loadAsynchronously(request, client()); ASSERT_TRUE(peer()); @@ -668,6 +670,7 @@ const int kEncodedDataLength = 130; const GURL url(kTestURL); blink::WebURLRequest request(url); + request.setRequestContext(blink::WebURLRequest::RequestContextInternal); // Prepare a mock response SyncLoadResponse sync_load_response;
diff --git a/content/child/web_url_request_util.cc b/content/child/web_url_request_util.cc index 6065831..51faca13 100644 --- a/content/child/web_url_request_util.cc +++ b/content/child/web_url_request_util.cc
@@ -18,6 +18,7 @@ #include "third_party/WebKit/public/platform/WebCachePolicy.h" #include "third_party/WebKit/public/platform/WebData.h" #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" +#include "third_party/WebKit/public/platform/WebMixedContent.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/platform/WebURLError.h" @@ -471,6 +472,19 @@ return static_cast<RequestContextType>(request.getRequestContext()); } +blink::WebMixedContentContextType GetMixedContentContextTypeForWebURLRequest( + const blink::WebURLRequest& request) { + bool block_mixed_plugin_content = false; + if (request.getExtraData()) { + RequestExtraData* extra_data = + static_cast<RequestExtraData*>(request.getExtraData()); + block_mixed_plugin_content = extra_data->block_mixed_plugin_content(); + } + + return blink::WebMixedContent::contextTypeFromRequestContext( + request.getRequestContext(), block_mixed_plugin_content); +} + STATIC_ASSERT_ENUM(SkipServiceWorker::NONE, WebURLRequest::SkipServiceWorker::None); STATIC_ASSERT_ENUM(SkipServiceWorker::CONTROLLING,
diff --git a/content/child/web_url_request_util.h b/content/child/web_url_request_util.h index 6763af8..857a9c3 100644 --- a/content/child/web_url_request_util.h +++ b/content/child/web_url_request_util.h
@@ -13,6 +13,7 @@ #include "content/public/common/request_context_frame_type.h" #include "content/public/common/request_context_type.h" #include "content/public/common/resource_type.h" +#include "third_party/WebKit/public/platform/WebMixedContentContextType.h" namespace blink { class WebHTTPBody; @@ -56,6 +57,8 @@ const blink::WebURLRequest& request); RequestContextType GetRequestContextTypeForWebURLRequest( const blink::WebURLRequest& request); +blink::WebMixedContentContextType GetMixedContentContextTypeForWebURLRequest( + const blink::WebURLRequest& request); SkipServiceWorker GetSkipServiceWorkerForWebURLRequest( const blink::WebURLRequest& request);
diff --git a/content/common/DEPS b/content/common/DEPS index 1053daf..caee767d 100644 --- a/content/common/DEPS +++ b/content/common/DEPS
@@ -24,6 +24,7 @@ "+third_party/WebKit/public/platform/WebHistoryScrollRestorationType.h", "+third_party/WebKit/public/platform/WebInputEvent.h", "+third_party/WebKit/public/platform/WebInsecureRequestPolicy.h", + "+third_party/WebKit/public/platform/WebMixedContentContextType.h", "+third_party/WebKit/public/platform/WebMouseWheelEvent.h", "+third_party/WebKit/public/platform/WebOriginTrialTokenStatus.h", "+third_party/WebKit/public/platform/WebPageVisibilityState.h", @@ -38,8 +39,8 @@ "+third_party/WebKit/public/platform/modules/device_orientation/WebDeviceOrientationData.h", "+third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h", "+third_party/WebKit/public/platform/modules/mediasession/media_session.mojom.h", - "+third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h", "+third_party/WebKit/public/platform/modules/permissions/WebPermissionType.h", + "+third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h", "+third_party/WebKit/public/platform/modules/push_messaging/WebPushError.h", "+third_party/WebKit/public/platform/modules/push_messaging/WebPushPermissionStatus.h", "+third_party/WebKit/public/platform/modules/remoteplayback/WebRemotePlaybackAvailability.h",
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 9f65e60..cc85b72 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -347,6 +347,7 @@ IPC_STRUCT_TRAITS_MEMBER(has_user_gesture) IPC_STRUCT_TRAITS_MEMBER(skip_service_worker) IPC_STRUCT_TRAITS_MEMBER(request_context_type) + IPC_STRUCT_TRAITS_MEMBER(mixed_content_context_type) IPC_STRUCT_TRAITS_MEMBER(searchable_form_url) IPC_STRUCT_TRAITS_MEMBER(searchable_form_encoding) IPC_STRUCT_TRAITS_MEMBER(initiator_origin)
diff --git a/content/common/navigation_params.cc b/content/common/navigation_params.cc index 51220c0..cf75598 100644 --- a/content/common/navigation_params.cc +++ b/content/common/navigation_params.cc
@@ -84,7 +84,9 @@ : load_flags(0), has_user_gesture(false), skip_service_worker(false), - request_context_type(REQUEST_CONTEXT_TYPE_LOCATION) {} + request_context_type(REQUEST_CONTEXT_TYPE_LOCATION), + mixed_content_context_type(blink::WebMixedContentContextType::Blockable) { +} BeginNavigationParams::BeginNavigationParams( std::string headers, @@ -92,12 +94,14 @@ bool has_user_gesture, bool skip_service_worker, RequestContextType request_context_type, + blink::WebMixedContentContextType mixed_content_context_type, const base::Optional<url::Origin>& initiator_origin) : headers(headers), load_flags(load_flags), has_user_gesture(has_user_gesture), skip_service_worker(skip_service_worker), request_context_type(request_context_type), + mixed_content_context_type(mixed_content_context_type), initiator_origin(initiator_origin) {} BeginNavigationParams::BeginNavigationParams(
diff --git a/content/common/navigation_params.h b/content/common/navigation_params.h index 86a5e7e..81e3229c 100644 --- a/content/common/navigation_params.h +++ b/content/common/navigation_params.h
@@ -21,6 +21,7 @@ #include "content/public/common/referrer.h" #include "content/public/common/request_context_type.h" #include "content/public/common/resource_response.h" +#include "third_party/WebKit/public/platform/WebMixedContentContextType.h" #include "ui/base/page_transition_types.h" #include "url/gurl.h" #include "url/origin.h" @@ -144,12 +145,14 @@ // TODO(clamy): See if it is possible to reuse this in // ResourceMsg_Request_Params. BeginNavigationParams(); - BeginNavigationParams(std::string headers, - int load_flags, - bool has_user_gesture, - bool skip_service_worker, - RequestContextType request_context_type, - const base::Optional<url::Origin>& initiator_origin); + BeginNavigationParams( + std::string headers, + int load_flags, + bool has_user_gesture, + bool skip_service_worker, + RequestContextType request_context_type, + blink::WebMixedContentContextType mixed_content_context_type, + const base::Optional<url::Origin>& initiator_origin); BeginNavigationParams(const BeginNavigationParams& other); ~BeginNavigationParams(); @@ -168,6 +171,9 @@ // Indicates the request context type. RequestContextType request_context_type; + // The mixed content context type for potential mixed content checks. + blink::WebMixedContentContextType mixed_content_context_type; + // See WebSearchableFormData for a description of these. GURL searchable_form_url; std::string searchable_form_encoding;
diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h index e806755..31d4ebdb7 100644 --- a/content/common/resource_messages.h +++ b/content/common/resource_messages.h
@@ -27,6 +27,7 @@ #include "net/http/http_response_info.h" #include "net/nqe/effective_connection_type.h" #include "net/url_request/redirect_info.h" +#include "third_party/WebKit/public/platform/WebMixedContentContextType.h" #ifndef CONTENT_COMMON_RESOURCE_MESSAGES_H_ #define CONTENT_COMMON_RESOURCE_MESSAGES_H_ @@ -135,6 +136,9 @@ IPC_ENUM_TRAITS_MAX_VALUE(net::EffectiveConnectionType, net::EFFECTIVE_CONNECTION_TYPE_LAST - 1) +IPC_ENUM_TRAITS_MAX_VALUE(blink::WebMixedContentContextType, + blink::WebMixedContentContextType::Last) + IPC_STRUCT_TRAITS_BEGIN(content::ResourceResponseHead) IPC_STRUCT_TRAITS_PARENT(content::ResourceResponseInfo) IPC_STRUCT_TRAITS_MEMBER(request_start) @@ -230,6 +234,7 @@ IPC_STRUCT_TRAITS_MEMBER(fetch_credentials_mode) IPC_STRUCT_TRAITS_MEMBER(fetch_redirect_mode) IPC_STRUCT_TRAITS_MEMBER(fetch_request_context_type) + IPC_STRUCT_TRAITS_MEMBER(fetch_mixed_content_context_type) IPC_STRUCT_TRAITS_MEMBER(fetch_frame_type) IPC_STRUCT_TRAITS_MEMBER(request_body) IPC_STRUCT_TRAITS_MEMBER(download_to_file)
diff --git a/content/common/resource_request.h b/content/common/resource_request.h index 0f5651f..a19d912 100644 --- a/content/common/resource_request.h +++ b/content/common/resource_request.h
@@ -19,6 +19,7 @@ #include "content/public/common/request_context_type.h" #include "content/public/common/resource_type.h" #include "net/base/request_priority.h" +#include "third_party/WebKit/public/platform/WebMixedContentContextType.h" #include "third_party/WebKit/public/platform/WebPageVisibilityState.h" #include "third_party/WebKit/public/platform/WebReferrerPolicy.h" #include "ui/base/page_transition_types.h" @@ -116,6 +117,10 @@ RequestContextType fetch_request_context_type = REQUEST_CONTEXT_TYPE_UNSPECIFIED; + // The mixed content context type to be used for mixed content checks. + blink::WebMixedContentContextType fetch_mixed_content_context_type = + blink::WebMixedContentContextType::Blockable; + // The frame type passed to the ServiceWorker. RequestContextFrameType fetch_frame_type = REQUEST_CONTEXT_FRAME_TYPE_AUXILIARY;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 120d558..3291804 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -141,6 +141,7 @@ #include "content/renderer/web_frame_utils.h" #include "content/renderer/web_ui_extension.h" #include "crypto/sha2.h" +#include "gin/modules/console.h" #include "gin/modules/module_registry.h" #include "media/audio/audio_output_device.h" #include "media/base/audio_renderer_mixer_input.h" @@ -2621,6 +2622,9 @@ return; v8::HandleScope handle_scope(isolate); + + registry->AddBuiltinModule(isolate, gin::Console::kModuleName, + gin::Console::GetModule(isolate)); registry->AddBuiltinModule(isolate, mojo::edk::js::Core::kModuleName, mojo::edk::js::Core::GetModule(isolate)); registry->AddBuiltinModule(isolate, mojo::edk::js::Support::kModuleName, @@ -6228,7 +6232,9 @@ info.urlRequest.hasUserGesture(), info.urlRequest.skipServiceWorker() != blink::WebURLRequest::SkipServiceWorker::None, - GetRequestContextTypeForWebURLRequest(info.urlRequest), initiator_origin); + GetRequestContextTypeForWebURLRequest(info.urlRequest), + GetMixedContentContextTypeForWebURLRequest(info.urlRequest), + initiator_origin); if (!info.form.isNull()) { WebSearchableFormData web_searchable_form_data(info.form);
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 5b6afa6c..7186122 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -684,6 +684,7 @@ blink::WebURLRequest::FetchCredentialsModeInclude); request.setFetchRedirectMode(blink::WebURLRequest::FetchRedirectModeManual); request.setFrameType(blink::WebURLRequest::FrameTypeTopLevel); + request.setRequestContext(blink::WebURLRequest::RequestContextInternal); blink::WebFrameClient::NavigationPolicyInfo policy_info(request); policy_info.navigationType = blink::WebNavigationTypeLinkClicked; policy_info.defaultPolicy = blink::WebNavigationPolicyCurrentTab;
diff --git a/content/shell/app/blink_test_platform_support_android.cc b/content/shell/app/blink_test_platform_support_android.cc index 2a5867c..fb6dadc 100644 --- a/content/shell/app/blink_test_platform_support_android.cc +++ b/content/shell/app/blink_test_platform_support_android.cc
@@ -5,6 +5,7 @@ #include "content/shell/app/blink_test_platform_support.h" #include "skia/ext/fontmgr_default_android.h" +#include "third_party/skia/include/ports/SkFontMgr.h" #include "third_party/skia/include/ports/SkFontMgr_android.h" namespace {
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 0b41550..cf9a43eb 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -41,6 +41,14 @@ self.Skip('deqp/functional/gles3/builtinprecision/*.html', bug=619403) # All platforms. + self.Fail('conformance/more/functions/vertexAttribPointerBadArgs.html', + bug=678850) + self.Fail('conformance/attribs/gl-vertexattribpointer.html', bug=678850) + self.Fail('conformance2/attribs/gl-vertexattribipointer.html', bug=678850) + + self.Fail('conformance/extensions/webgl-compressed-texture-etc.html', + bug=679678) + self.Flaky('conformance2/query/occlusion-query.html', bug=603168) self.Fail('conformance2/glsl3/tricky-loop-conditions.html', bug=483282) @@ -159,6 +167,14 @@ self.Fail('conformance2/reading/format-r11f-g11f-b10f.html', ['mac'], bug=1832) # khronos WebGL issue + self.Fail('deqp/functional/gles3/fborender/recreate_color_02.html', + ['mac'], bug=679682) + self.Fail('deqp/functional/gles3/fborender/resize_01.html', + ['mac'], bug=679682) + self.Fail('deqp/functional/gles3/fragmentoutput/basic.float.html', + ['mac'], bug=679684) + self.Fail('deqp/functional/gles3/fragmentoutput/array.float.html', + ['mac'], bug=679684) # Mac Retina NVIDIA self.Fail('deqp/functional/gles3/fbomultisample*', @@ -304,6 +320,16 @@ ['mac', ('nvidia', 0xfe9)], bug=483282) # Mac AMD + self.Fail('deqp/functional/gles3/fbomultisample.8_samples.html', + ['mac', 'amd'], bug=679686) + self.Fail('deqp/functional/gles3/fbomultisample.4_samples.html', + ['mac', 'amd'], bug=679686) + self.Fail('deqp/functional/gles3/fbomultisample.2_samples.html', + ['mac', 'amd'], bug=679686) + self.Fail('deqp/functional/gles3/pixelbufferobject.html', + ['mac', 'amd'], bug=679687) + self.Fail('deqp/functional/gles3/instancedrendering.html', + ['mac', 'amd'], bug=679689) self.Fail('conformance/glsl/bugs/bool-type-cast-bug-int-float.html', ['mac', 'amd'], bug=643866) self.Fail('conformance2/glsl3/bool-type-cast-bug-uint-ivec-uvec.html', @@ -429,6 +455,14 @@ self.Fail('deqp/functional/gles3/shaderoperator/common_functions.html', ['mac', ('amd', 0x679e)], bug=483282) + # Mac Multi-vendor failures. + self.Fail('deqp/functional/gles3/fragmentoutput/random_00.html', + ['mac', 'amd', 'intel'], bug=679690) + self.Fail('deqp/functional/gles3/fragmentoutput/random_02.html', + ['mac', 'amd', 'intel'], bug=679690) + self.Fail('deqp/functional/gles3/fbocolorbuffer/clear.html', + ['mac', 'amd', 'intel'], bug=679691) + # Mac Intel self.Fail( @@ -456,6 +490,8 @@ 'conformance2/textures/webgl_canvas/tex-3d-rgb9_e5-rgb-half_float.html', ['sierra', 'intel'], bug=663188) + self.Fail('conformance2/textures/misc/angle-stuck-depth-textures.html', + ['mac', 'intel'], bug=679692) self.Fail('deqp/functional/gles3/fbomultisample*', ['mac', 'intel'], bug=641209) self.Fail('deqp/functional/gles3/texturefiltering/2d_combinations_01.html', @@ -571,6 +607,8 @@ ['linux'], bug=627525) self.Fail('conformance2/glsl3/vector-dynamic-indexing-nv-driver-bug.html', ['linux'], bug=483282) + self.Fail('conformance2/textures/image_bitmap_from_image/' + + 'tex-3d-r16f-red-float.html', ['linux'], bug=679695) # Linux Multi-vendor failures. self.Skip('deqp/data/gles3/shaders/qualification_order.html', @@ -588,6 +626,9 @@ ['linux', 'nvidia'], bug=618447) self.Fail('conformance/glsl/bugs/unary-minus-operator-float-bug.html', ['linux', 'nvidia'], bug=672380) + self.Fail('conformance2/textures/image_bitmap_from_canvas/' + + 'tex-3d-srgb8_alpha8-rgba-unsigned_byte.html', + ['linux', 'nvidia'], bug=679677) # Linux Intel self.Fail('conformance2/extensions/ext-color-buffer-float.html',
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 6d8b16b..c7393aea0 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -110,6 +110,10 @@ # ======================== # Fails on all platforms + self.Fail('conformance/more/functions/vertexAttribPointerBadArgs.html', + bug=678850) + self.Fail('conformance/attribs/gl-vertexattribpointer.html', bug=678850) + # Need to add detection of feedback loops with multiple render targets. self.Fail('conformance/extensions/webgl-draw-buffers-feedback-loop.html', bug=1619) # angle bug ID @@ -136,6 +140,8 @@ ['win', 'nvidia'], bug=630860) self.Fail('conformance/glsl/bugs/unary-minus-operator-float-bug.html', ['win', 'nvidia'], bug=672380) + self.Fail('conformance/extensions/ext-sRGB.html', + ['win', 'nvidia', 'no_passthrough'], bug=679696) # Win7 / Intel failures self.Fail('conformance/textures/misc/' + @@ -225,8 +231,8 @@ ['win10', 'intel', 'opengl'], bug=1007) # angle bug ID # Win / Passthrough command decoder - self.Fail('conformance/attribs/gl-vertexattribpointer.html', - ['win', 'passthrough', 'd3d11'], bug=1523) # angle bug ID + self.Fail('conformance/extensions/ext-sRGB.html', + ['win', 'passthrough', 'd3d11'], bug=679696) self.Fail('conformance/extensions/angle-instanced-arrays.html', ['win', 'passthrough', 'd3d11'], bug=1523) # angle bug ID self.Fail('conformance/extensions/ext-disjoint-timer-query.html', @@ -287,8 +293,6 @@ ['win', 'passthrough', 'd3d11'], bug=1639) # angle bug ID self.Fail('conformance/more/functions/texSubImage2DHTMLBadArgs.html', ['win', 'passthrough', 'd3d11'], bug=1639) # angle bug ID - self.Fail('conformance/more/functions/vertexAttribPointerBadArgs.html', - ['win', 'passthrough', 'd3d11'], bug=1639) # angle bug ID self.Fail('conformance/reading/read-pixels-test.html', ['win', 'passthrough', 'd3d11'], bug=1639) # angle bug ID self.Fail('conformance/renderbuffers/feedback-loop.html', @@ -369,6 +373,8 @@ self.Flaky('conformance/textures/video/' + 'tex-2d-rgb-rgb-unsigned_short_5_6_5.html', ['linux'], bug=627525) + self.Fail('conformance/extensions/webgl-compressed-texture-etc.html', + bug=679678) # NVIDIA self.Flaky('conformance/extensions/oes-element-index-uint.html', @@ -436,6 +442,10 @@ # The following tests timed out on android, so skip them for now. self.Skip('conformance/textures/image_bitmap_from_video/*', ['android'], bug=585108) + + self.Fail('conformance/textures/misc/' + + 'copytexsubimage2d-large-partial-copy-corruption.html', + ['android'], bug=679697) # The following WebView crashes are causing problems with further # tests in the suite, so skip them for now. self.Skip('conformance/textures/video/' + @@ -554,9 +564,6 @@ ['android', ('qualcomm', 'Adreno (TM) 418')], bug=610951) self.Fail('conformance/textures/image_data/*', ['android', ('qualcomm', 'Adreno (TM) 418')], bug=610951) - self.Fail('conformance/textures/misc/' + - 'copy-tex-sub-image-2d-partial-texture.html', - ['android', ('qualcomm', 'Adreno (TM) 418')], bug=643361) self.Fail('conformance/textures/svg_image/*', ['android', ('qualcomm', 'Adreno (TM) 418')], bug=610951) self.Fail('conformance/textures/video/*', @@ -669,11 +676,6 @@ 'copy-tex-image-and-sub-image-2d.html', ['android', ('qualcomm', 'Adreno (TM) 420')], bug=499555) self.Fail('conformance/textures/misc/' + - 'copy-tex-sub-image-2d-partial-texture.html', - ['android', - ('qualcomm', 'Adreno (TM) 420'), - ('qualcomm', 'Adreno (TM) 430')], bug=643361) - self.Fail('conformance/textures/misc/' + 'tex-image-and-sub-image-2d-with-array-buffer-view.html', ['android', ('qualcomm', 'Adreno (TM) 420'),
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc index c23f1a1..764125ce 100644 --- a/content/test/layouttest_support.cc +++ b/content/test/layouttest_support.cc
@@ -61,6 +61,7 @@ #elif defined(OS_WIN) #include "content/child/font_warmup_win.h" #include "third_party/WebKit/public/web/win/WebFontRendering.h" +#include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/ports/SkFontMgr.h" #include "third_party/skia/include/ports/SkTypeface_win.h" #include "ui/gfx/win/direct_write.h" @@ -438,7 +439,7 @@ base::MakeUnique<LayoutTestDependenciesImpl>()); #if defined(OS_WIN) - RegisterSideloadedTypefaces(SkFontMgr_New_DirectWrite()); + RegisterSideloadedTypefaces(SkFontMgr_New_DirectWrite().get()); #endif }
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc index 02b50aed..c50f745 100644 --- a/content/test/test_render_frame_host.cc +++ b/content/test/test_render_frame_host.cc
@@ -24,6 +24,7 @@ #include "content/test/test_render_view_host.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "net/base/load_flags.h" +#include "third_party/WebKit/public/platform/WebMixedContentContextType.h" #include "third_party/WebKit/public/platform/WebPageVisibilityState.h" #include "third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h" #include "third_party/WebKit/public/web/WebSandboxFlags.h" @@ -412,7 +413,8 @@ // TODO(mkwst): The initiator origin here is incorrect. BeginNavigationParams begin_params( std::string(), net::LOAD_NORMAL, has_user_gesture, false, - REQUEST_CONTEXT_TYPE_HYPERLINK, url::Origin()); + REQUEST_CONTEXT_TYPE_HYPERLINK, + blink::WebMixedContentContextType::Blockable, url::Origin()); CommonNavigationParams common_params; common_params.url = url; common_params.referrer = Referrer(GURL(), blink::WebReferrerPolicyDefault);
diff --git a/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc index 707b5a4..779e9b70 100644 --- a/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc +++ b/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc
@@ -7,8 +7,8 @@ #include <memory> #include "base/bind.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_scheduler.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_uuid.h" @@ -150,7 +150,7 @@ } protected: - base::MessageLoop message_loop_; + base::test::ScopedTaskScheduler scoped_task_scheduler_; scoped_refptr<BluetoothAdapter> adapter_;
diff --git a/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc index ee4d814..74ac10a 100644 --- a/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc +++ b/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc
@@ -10,6 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_async_task_scheduler.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_device.h" @@ -175,6 +176,7 @@ protected: base::MessageLoop message_loop_; + base::test::ScopedAsyncTaskScheduler scoped_async_task_scheduler_; scoped_refptr<BluetoothAdapter> adapter_;
diff --git a/device/bluetooth/dbus/fake_bluetooth_device_client.cc b/device/bluetooth/dbus/fake_bluetooth_device_client.cc index 5aaaf08..cd588b54 100644 --- a/device/bluetooth/dbus/fake_bluetooth_device_client.cc +++ b/device/bluetooth/dbus/fake_bluetooth_device_client.cc
@@ -23,8 +23,8 @@ #include "base/rand_util.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/thread_task_runner_handle.h" -#include "base/threading/worker_pool.h" #include "base/time/time.h" #include "device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h" #include "device/bluetooth/dbus/bluez_dbus_manager.h" @@ -515,8 +515,12 @@ return; } - base::WorkerPool::GetTaskRunner(false) - ->PostTask(FROM_HERE, base::Bind(&SimulatedProfileSocket, fds[0])); + base::PostTaskWithTraits( + FROM_HERE, base::TaskTraits() + .WithShutdownBehavior( + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) + .MayBlock(), + base::Bind(&SimulatedProfileSocket, fds[0])); base::ScopedFD fd(fds[1]);
diff --git a/docs/chromoting_android_hacking.md b/docs/chromoting_android_hacking.md index 5eebdfea..1c3c8df 100644 --- a/docs/chromoting_android_hacking.md +++ b/docs/chromoting_android_hacking.md
@@ -95,7 +95,6 @@ <classpathentry kind="src" path="third_party/libjingle/source/talk/app/webrtc/javatests/src"/> <classpathentry kind="src" path="third_party/libjingle/source/talk/examples/android/src"/> <classpathentry kind="src" path="android_webview/java/src"/> -<classpathentry kind="src" path="android_webview/java/generated_src"/> <classpathentry kind="src" path="android_webview/test/shell/src"/> <classpathentry kind="src" path="android_webview/unittestjava/src"/> <classpathentry kind="src" path="android_webview/javatests/src"/>
diff --git a/docs/memory-infra/README.md b/docs/memory-infra/README.md index 5066a650..eb3252b 100644 --- a/docs/memory-infra/README.md +++ b/docs/memory-infra/README.md
@@ -93,7 +93,7 @@ * **UI**: Android only. Memory used by Android java bitmaps for the UI. * **V8**: Memory used by V8 Javascript engine. * **Web Cache**: Memory used by resources downloaded from the Web, like images - and scipts. + and scripts. The **tracing column in gray** reports memory that is used to collect all of the above information. This memory would not be used if tracing were not enabled, @@ -107,6 +107,19 @@ [gpu-memory]: probe-gpu.md [partalloc]: /base/allocator/partition_allocator/PartitionAlloc.md +## 'effective\_size' vs. 'size' + +This is a little like the difference between 'self time' and 'cumulative time' +in a profiling tool. Size is the total amount of memory allocated/requested +by a subsystem whereas effective size is the total amount of memory +used/consumed by a subsystem. If Skia allocates 10mb via partition_alloc +that memory would show up in the size of both Skia and partition_alloc +but only in the effective size of Skia since although partition_alloc +allocates the 10mb it does so on behalf of Skia which is responsible +for the memory. Summing all effective sizes gives the total amount of +memory used whereas summing size would give a number larger than the total +amount of memory used. + ## Related Pages * [Adding MemoryInfra Tracing to a Component](adding_memory_infra_tracing.md)
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc index 47f4a6ee..de1fbd6 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.cc +++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -401,8 +401,6 @@ content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, content::Source<WebContents>(web_contents())); - if (web_view_guest_delegate_) - web_view_guest_delegate_->OnDidInitialize(); ExtensionsAPIClient::Get()->AttachWebContentsHelpers(web_contents()); web_view_permission_helper_.reset(new WebViewPermissionHelper(this));
diff --git a/extensions/browser/guest_view/web_view/web_view_guest_delegate.h b/extensions/browser/guest_view/web_view/web_view_guest_delegate.h index 373ff34..8abb15f 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest_delegate.h +++ b/extensions/browser/guest_view/web_view/web_view_guest_delegate.h
@@ -18,9 +18,6 @@ // Called when context menu operation was handled. virtual bool HandleContextMenu(const content::ContextMenuParams& params) = 0; - // Called just after additional initialization is performed. - virtual void OnDidInitialize() = 0; - // Shows the context menu for the guest. virtual void OnShowContextMenu(int request_id) = 0;
diff --git a/extensions/renderer/api_test_base.cc b/extensions/renderer/api_test_base.cc index 8a2baba..8e534acb 100644 --- a/extensions/renderer/api_test_base.cc +++ b/extensions/renderer/api_test_base.cc
@@ -16,6 +16,7 @@ #include "extensions/renderer/process_info_native_handler.h" #include "gin/converter.h" #include "gin/dictionary.h" +#include "gin/modules/console.h" #include "mojo/edk/js/core.h" #include "mojo/edk/js/handle.h" #include "mojo/edk/js/support.h" @@ -154,6 +155,9 @@ "exports.$set('MatchAgainstEventFilter', function() { return [] });"); gin::ModuleRegistry::From(env()->context()->v8_context()) + ->AddBuiltinModule(env()->isolate(), gin::Console::kModuleName, + gin::Console::GetModule(env()->isolate())); + gin::ModuleRegistry::From(env()->context()->v8_context()) ->AddBuiltinModule(env()->isolate(), mojo::edk::js::Core::kModuleName, mojo::edk::js::Core::GetModule(env()->isolate())); gin::ModuleRegistry::From(env()->context()->v8_context())
diff --git a/gin/per_isolate_data.cc b/gin/per_isolate_data.cc index dd4ce9d..029b93d 100644 --- a/gin/per_isolate_data.cc +++ b/gin/per_isolate_data.cc
@@ -29,7 +29,8 @@ : isolate_(isolate), allocator_(allocator), access_mode_(access_mode), - task_runner_(task_runner) { + task_runner_( + task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get()) { isolate_->SetData(kEmbedderNativeGin, this); }
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc index 42a331fb..6c28e708 100644 --- a/headless/app/headless_shell.cc +++ b/headless/app/headless_shell.cc
@@ -106,16 +106,23 @@ // TODO(alexclarke): Should we navigate to about:blank first if using // virtual time? - if (!args.empty() && !args[0].empty()) - builder.SetInitialURL(GURL(args[0])); - - web_contents_ = builder.Build(); - if (!web_contents_) { - LOG(ERROR) << "Navigation failed"; - browser_->Shutdown(); - return; + if (args.empty()) + args.push_back("about:blank"); + for (auto it = args.rbegin(); it != args.rend(); ++it) { + GURL url(*it); + HeadlessWebContents* web_contents = builder.SetInitialURL(url).Build(); + if (!web_contents) { + LOG(ERROR) << "Navigation to " << url << " failed"; + browser_->Shutdown(); + return; + } + if (!web_contents_ && !RemoteDebuggingEnabled()) { + // TODO(jzfeng): Support observing multiple targets. + url_ = url; + web_contents_ = web_contents; + web_contents_->AddObserver(this); + } } - web_contents_->AddObserver(this); } void Shutdown() { @@ -138,8 +145,6 @@ // HeadlessWebContents::Observer implementation: void DevToolsTargetReady() override { - if (RemoteDebuggingEnabled()) - return; web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get()); devtools_client_->GetInspector()->GetExperimental()->AddObserver(this); devtools_client_->GetPage()->AddObserver(this); @@ -400,6 +405,41 @@ DISALLOW_COPY_AND_ASSIGN(HeadlessShell); }; +bool ValidateCommandLine(const base::CommandLine& command_line) { + if (!command_line.HasSwitch(::switches::kRemoteDebuggingPort)) { + if (command_line.GetArgs().size() <= 1) + return true; + LOG(ERROR) << "Open multiple tabs is only supported when the " + << "remote debug port is set."; + return false; + } + if (command_line.HasSwitch(switches::kDumpDom)) { + LOG(ERROR) << "Dump DOM is disabled when remote debugging is enabled."; + return false; + } + if (command_line.HasSwitch(switches::kRepl)) { + LOG(ERROR) << "Evaluate Javascript is disabled " + << "when remote debugging is enabled."; + return false; + } + if (command_line.HasSwitch(switches::kScreenshot)) { + LOG(ERROR) << "Capture screenshot is disabled " + << "when remote debugging is enabled."; + return false; + } + if (command_line.HasSwitch(switches::kTimeout)) { + LOG(ERROR) << "Navigation timeout is disabled " + << "when remote debugging is enabled."; + return false; + } + if (command_line.HasSwitch(switches::kVirtualTimeBudget)) { + LOG(ERROR) << "Virtual time budget is disabled " + << "when remote debugging is enabled."; + return false; + } + return true; +} + int HeadlessShellMain(int argc, const char** argv) { RunChildProcessIfNeeded(argc, argv); HeadlessShell shell; @@ -407,6 +447,9 @@ // Enable devtools if requested. base::CommandLine command_line(argc, argv); + if (!ValidateCommandLine(command_line)) + return EXIT_FAILURE; + if (command_line.HasSwitch(::switches::kRemoteDebuggingPort)) { std::string address = kDevToolsHttpServerAddress; if (command_line.HasSwitch(switches::kRemoteDebuggingAddress)) {
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn index 15f57eb..4a2edda 100644 --- a/ios/chrome/browser/tabs/BUILD.gn +++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -8,6 +8,7 @@ "tab_delegate.h", "tab_dialog_delegate.h", "tab_model.h", + "tab_model_list.h", "tab_model_observer.h", "tab_model_order_controller.h", "tab_model_synced_window_delegate.h", @@ -36,6 +37,7 @@ ] deps = [ ":tabs", + ":tabs_internal_arc", "//base", "//components/content_settings/core/browser", "//components/favicon/core", @@ -106,12 +108,26 @@ "//ui/base", "//url", ] + allow_circular_includes_from = [ ":tabs_internal_arc" ] libs = [ "CoreLocation.framework", "UIKit.framework", ] } +source_set("tabs_internal_arc") { + sources = [ + "tab_model_list.mm", + ] + deps = [ + ":tabs", + "//base", + "//ios/chrome/browser/browser_state", + ] + libs = [ "Foundation.framework" ] + configs += [ "//build/config/compiler:enable_arc" ] +} + source_set("unit_tests") { testonly = true sources = [ @@ -122,6 +138,7 @@ deps = [ ":tabs", ":tabs_internal", + ":unit_tests_arc", "//base", "//components/bookmarks/test", "//components/history/core/browser", @@ -147,3 +164,20 @@ "//third_party/ocmock", ] } + +source_set("unit_tests_arc") { + testonly = true + sources = [ + "tab_model_list_unittest.mm", + ] + deps = [ + ":tabs", + ":tabs_internal", + "//base", + "//ios/chrome/browser/browser_state:test_support", + "//ios/chrome/browser/sessions:test_support", + "//ios/web:test_support", + "//testing/gtest", + ] + configs += [ "//build/config/compiler:enable_arc" ] +}
diff --git a/ios/chrome/browser/tabs/tab_model.mm b/ios/chrome/browser/tabs/tab_model.mm index 8bfb11f..aa4cd9a 100644 --- a/ios/chrome/browser/tabs/tab_model.mm +++ b/ios/chrome/browser/tabs/tab_model.mm
@@ -30,6 +30,7 @@ #import "ios/chrome/browser/snapshots/snapshot_cache.h" #include "ios/chrome/browser/tab_parenting_global_observer.h" #import "ios/chrome/browser/tabs/tab.h" +#import "ios/chrome/browser/tabs/tab_model_list.h" #import "ios/chrome/browser/tabs/tab_model_observer.h" #import "ios/chrome/browser/tabs/tab_model_order_controller.h" #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" @@ -299,6 +300,9 @@ selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; + + // Associate with ios::ChromeBrowserState. + RegisterTabModelWithChromeBrowserState(_browserState, self); } return self; } @@ -732,6 +736,9 @@ // NOTE: This can be called multiple times, so must be robust against that. - (void)browserStateDestroyed { [[NSNotificationCenter defaultCenter] removeObserver:self]; + if (_browserState) { + UnregisterTabModelFromChromeBrowserState(_browserState, self); + } _browserState = nullptr; }
diff --git a/ios/chrome/browser/tabs/tab_model_list.h b/ios/chrome/browser/tabs/tab_model_list.h new file mode 100644 index 0000000..bbba490 --- /dev/null +++ b/ios/chrome/browser/tabs/tab_model_list.h
@@ -0,0 +1,37 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_TABS_TAB_MODEL_LIST_H_ +#define IOS_CHROME_BROWSER_TABS_TAB_MODEL_LIST_H_ + +#import <Foundation/Foundation.h> + +// This file contains free functions to help maintain a 1:N relationship +// between an ios::ChromeBrowserState and multiple TabModels. + +@class TabModel; + +namespace ios { +class ChromeBrowserState; +} + +// Registers |tab_model| as associated to |browser_state|. The object will +// be retained until |UnregisterTabModelFromChromeBrowserState| is called. +// It is an error if |tab_model is already registered as associated to +// |browser_state|. +void RegisterTabModelWithChromeBrowserState( + ios::ChromeBrowserState* browser_state, + TabModel* tab_model); + +// Unregisters the association between |tab_model| and |browser_state|. +// It is an error if no such association exists. +void UnregisterTabModelFromChromeBrowserState( + ios::ChromeBrowserState* browser_state, + TabModel* tab_model); + +// Returns the list of all TabModels associated with |browser_state|. +NSArray<TabModel*>* GetTabModelsForChromeBrowserState( + ios::ChromeBrowserState* browser_state); + +#endif // IOS_CHROME_BROWSER_TABS_TAB_MODEL_LIST_H_
diff --git a/ios/chrome/browser/tabs/tab_model_list.mm b/ios/chrome/browser/tabs/tab_model_list.mm new file mode 100644 index 0000000..b9562232 --- /dev/null +++ b/ios/chrome/browser/tabs/tab_model_list.mm
@@ -0,0 +1,87 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/tabs/tab_model_list.h" + +#include "base/logging.h" +#include "base/macros.h" +#include "base/supports_user_data.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/tabs/tab_model.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +// Wrapper around a NSMutableArray<TabModel> allowing to bind it to a +// base::SupportsUserData. Any base::SupportsUserData that owns this +// wrapper will owns the reference to the TabModels. +class TabModelList : public base::SupportsUserData::Data { + public: + TabModelList(); + ~TabModelList() override; + + static TabModelList* GetForBrowserState( + ios::ChromeBrowserState* browser_state, + bool create); + + NSMutableSet<TabModel*>* tab_models() const { return tab_models_; } + + private: + NSMutableSet<TabModel*>* tab_models_; + + DISALLOW_COPY_AND_ASSIGN(TabModelList); +}; + +const char kTabModelListKey = 0; + +TabModelList::TabModelList() : tab_models_([[NSMutableSet alloc] init]) {} + +TabModelList::~TabModelList() { + // TabModelList is destroyed during base::SupportsUserData destruction. At + // that point, all TabModels must have been unregistered already. + DCHECK_EQ([tab_models_ count], 0u); +} + +// static +TabModelList* TabModelList::GetForBrowserState( + ios::ChromeBrowserState* browser_state, + bool create) { + TabModelList* tab_model_list = + static_cast<TabModelList*>(browser_state->GetUserData(&kTabModelListKey)); + if (!tab_model_list && create) { + // The ownership of TabModelList is transfered to base::SupportsUserData + // via the SetUserData call (should take a std::unique_ptr<>). + tab_model_list = new TabModelList; + browser_state->SetUserData(&kTabModelListKey, tab_model_list); + } + return tab_model_list; +} +} // namespace + +void RegisterTabModelWithChromeBrowserState( + ios::ChromeBrowserState* browser_state, + TabModel* tab_model) { + NSMutableSet<TabModel*>* tab_models = + TabModelList::GetForBrowserState(browser_state, true)->tab_models(); + DCHECK(![tab_models containsObject:tab_model]); + [tab_models addObject:tab_model]; +} + +void UnregisterTabModelFromChromeBrowserState( + ios::ChromeBrowserState* browser_state, + TabModel* tab_model) { + NSMutableSet<TabModel*>* tab_models = + TabModelList::GetForBrowserState(browser_state, false)->tab_models(); + DCHECK([tab_models containsObject:tab_model]); + [tab_models removeObject:tab_model]; +} + +NSArray<TabModel*>* GetTabModelsForChromeBrowserState( + ios::ChromeBrowserState* browser_state) { + TabModelList* tab_model_list = + TabModelList::GetForBrowserState(browser_state, false); + return tab_model_list ? [tab_model_list->tab_models() allObjects] : nil; +}
diff --git a/ios/chrome/browser/tabs/tab_model_list_unittest.mm b/ios/chrome/browser/tabs/tab_model_list_unittest.mm new file mode 100644 index 0000000..d8d6730 --- /dev/null +++ b/ios/chrome/browser/tabs/tab_model_list_unittest.mm
@@ -0,0 +1,75 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/tabs/tab_model_list.h" + +#import "base/mac/scoped_nsobject.h" +#include "base/memory/ptr_util.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#import "ios/chrome/browser/sessions/test_session_service.h" +#import "ios/chrome/browser/tabs/tab_model.h" +#include "ios/web/public/test/test_web_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +class TabModelListTest : public PlatformTest { + public: + TabModelListTest() { + TestChromeBrowserState::Builder test_cbs_builder; + chrome_browser_state_ = test_cbs_builder.Build(); + } + + TabModel* CreateTabModel() { + return [[TabModel alloc] + initWithSessionWindow:nil + sessionService:[[TestSessionService alloc] init] + browserState:chrome_browser_state_.get()]; + } + + NSArray<TabModel*>* RegisteredTabModels() { + return GetTabModelsForChromeBrowserState(chrome_browser_state_.get()); + } + + private: + web::TestWebThreadBundle thread_bundle_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; + + DISALLOW_COPY_AND_ASSIGN(TabModelListTest); +}; + +TEST_F(TabModelListTest, RegisterAndUnregister) { + EXPECT_EQ([RegisteredTabModels() count], 0u); + + TabModel* tab_model = CreateTabModel(); + EXPECT_EQ([RegisteredTabModels() count], 1u); + EXPECT_NE([RegisteredTabModels() indexOfObject:tab_model], + static_cast<NSUInteger>(NSNotFound)); + + [tab_model browserStateDestroyed]; + + EXPECT_EQ([RegisteredTabModels() count], 0u); +} + +TEST_F(TabModelListTest, SupportsMultipleTabModel) { + EXPECT_EQ([RegisteredTabModels() count], 0u); + + TabModel* tab_model1 = CreateTabModel(); + EXPECT_EQ([RegisteredTabModels() count], 1u); + EXPECT_NE([RegisteredTabModels() indexOfObject:tab_model1], + static_cast<NSUInteger>(NSNotFound)); + + TabModel* tab_model2 = CreateTabModel(); + EXPECT_EQ([RegisteredTabModels() count], 2u); + EXPECT_NE([RegisteredTabModels() indexOfObject:tab_model2], + static_cast<NSUInteger>(NSNotFound)); + + [tab_model1 browserStateDestroyed]; + [tab_model2 browserStateDestroyed]; + + EXPECT_EQ([RegisteredTabModels() count], 0u); +}
diff --git a/ios/chrome/browser/tabs/tab_model_unittest.mm b/ios/chrome/browser/tabs/tab_model_unittest.mm index d99a886..4d2e9068 100644 --- a/ios/chrome/browser/tabs/tab_model_unittest.mm +++ b/ios/chrome/browser/tabs/tab_model_unittest.mm
@@ -147,7 +147,7 @@ TestChromeBrowserState::Builder test_cbs_builder; chrome_browser_state_ = test_cbs_builder.Build(); - sessionWindow_.reset([[SessionWindowIOS new] retain]); + sessionWindow_.reset([[SessionWindowIOS alloc] init]); // Create tab model with just a dummy session service so the async state // saving doesn't trigger unless actually wanted. base::scoped_nsobject<TestSessionService> test_service(
diff --git a/ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm b/ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm index 73bee7c..c9389ec 100644 --- a/ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm +++ b/ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm
@@ -363,7 +363,7 @@ ^bool(void) { return [audience updated]; }, - nullptr, delay); + false, delay); EXPECT_TRUE([audience updated]); // Reset |audience|. [audience setUpdated:NO]; @@ -410,7 +410,7 @@ ^bool(void) { return [audience updated]; }, - nullptr, delay); + false, delay); EXPECT_TRUE([audience updated]); // Reset |audience|. [audience setUpdated:NO]; @@ -443,7 +443,7 @@ ^bool(void) { return [audience2 updated]; }, - nullptr, delay); + false, delay); EXPECT_TRUE([audience2 updated]); }
diff --git a/ios/chrome/browser/ui/fullscreen_controller.mm b/ios/chrome/browser/ui/fullscreen_controller.mm index f964931..cf4902f 100644 --- a/ios/chrome/browser/ui/fullscreen_controller.mm +++ b/ios/chrome/browser/ui/fullscreen_controller.mm
@@ -144,8 +144,6 @@ - (void)decrementFullScreenLock; // Called when the application is about to be the foreground application. - (void)applicationWillEnterForeground:(NSNotification*)notification; -// TODO(shreyasv): Make the following methods act on a WebViewScrollView proxy -// instead of taking in a UIScrollView directly. // Called from -webViewScrollViewDidScroll: Returns YES if the scroll should be // ignored. - (BOOL)shouldIgnoreScroll:(CRWWebViewScrollViewProxy*)webViewScrollViewProxy; @@ -294,8 +292,8 @@ selector:@selector(decrementFullScreenLock) name:ios_internal::kSideSwipeDidStopNotification object:nil]; - // TODO(jbbegue): Evaluate using a listener instead of a notification - // crbug/451373. + // TODO(crbug.com/451373): Evaluate using listeners instead of + // notifications. [center addObserver:self selector:@selector(overscrollActionsWillStart) name:kOverscrollActionsWillStart
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_perftest.mm b/ios/chrome/browser/ui/ntp/new_tab_page_perftest.mm index eabe37d..a94c646 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_perftest.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_perftest.mm
@@ -38,7 +38,7 @@ } void SettleUI() { base::test::ios::WaitUntilCondition( - nil, nullptr, base::TimeDelta::FromSecondsD(kMaxUICatchupDelay)); + nil, false, base::TimeDelta::FromSecondsD(kMaxUICatchupDelay)); } };
diff --git a/ios/chrome/browser/ui/omnibox_perftest.mm b/ios/chrome/browser/ui/omnibox_perftest.mm index e4e24f8..0c59ec7a 100644 --- a/ios/chrome/browser/ui/omnibox_perftest.mm +++ b/ios/chrome/browser/ui/omnibox_perftest.mm
@@ -159,7 +159,7 @@ ^bool() { return [keyboard_listener_ isKeyboardVisible]; }, - nullptr, base::TimeDelta()); + false, base::TimeDelta()); base::test::ios::TimeUntilCondition( ^{ [textField resignFirstResponder]; @@ -167,7 +167,7 @@ ^bool() { return ![keyboard_listener_ isKeyboardVisible]; }, - nullptr, base::TimeDelta()); + false, base::TimeDelta()); [textField removeFromSuperview]; return elapsed; } @@ -182,7 +182,7 @@ ^bool() { return [keyboard_listener_ isKeyboardVisible]; }, - nullptr, base::TimeDelta()); + false, base::TimeDelta()); } // Performs necessary cleanup (so next pass of unit test can start from @@ -197,7 +197,7 @@ ^bool() { return ![keyboard_listener_ isKeyboardVisible]; }, - nullptr, base::TimeDelta()); + false, base::TimeDelta()); } std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
diff --git a/ios/chrome/browser/ui/stack_view/stack_view_controller_perftest.mm b/ios/chrome/browser/ui/stack_view/stack_view_controller_perftest.mm index 5b93233..cb5dbce 100644 --- a/ios/chrome/browser/ui/stack_view/stack_view_controller_perftest.mm +++ b/ios/chrome/browser/ui/stack_view/stack_view_controller_perftest.mm
@@ -257,9 +257,9 @@ ^bool() { return !tab.webState->IsLoading(); }, - nullptr, base::TimeDelta::FromSecondsD(kMaxPageLoadDelay)); + false, base::TimeDelta::FromSecondsD(kMaxPageLoadDelay)); base::test::ios::WaitUntilCondition( - nil, nullptr, base::TimeDelta::FromSecondsD(kMaxUICatchupDelay)); + nil, false, base::TimeDelta::FromSecondsD(kMaxUICatchupDelay)); } base::TimeDelta StackViewControllerPerfTest::OpenStackView() { @@ -271,7 +271,7 @@ ^bool() { return [delegate_ showAnimationEnded]; }, - nullptr, base::TimeDelta::FromSecondsD(kTotalSpinDelay)); + false, base::TimeDelta::FromSecondsD(kTotalSpinDelay)); } void StackViewControllerPerfTest::MainControllerShowTabSwitcher() { @@ -326,7 +326,7 @@ ^bool() { return [delegate_ dismissAnimationEnded]; }, - nullptr, base::TimeDelta::FromSecondsD(kTotalSpinDelay)); + false, base::TimeDelta::FromSecondsD(kTotalSpinDelay)); [view_controller_ dismissViewControllerAnimated:NO completion:nil]; if (!reuse_svc_) @@ -338,7 +338,7 @@ // in the OS during view teardown to resolve, so that the view gets its // dismissal callbacks. base::test::ios::WaitUntilCondition( - nil, nullptr, base::TimeDelta::FromSecondsD(kSpinDelay)); + nil, false, base::TimeDelta::FromSecondsD(kSpinDelay)); return closeTime; }
diff --git a/ios/chrome/test/block_cleanup_test.h b/ios/chrome/test/block_cleanup_test.h index 61ec9f5..09b4c288 100644 --- a/ios/chrome/test/block_cleanup_test.h +++ b/ios/chrome/test/block_cleanup_test.h
@@ -22,7 +22,7 @@ void SpinRunLoop(NSTimeInterval cleanup_time); private: - NSAutoreleasePool* block_cleanup_pool_; + id block_cleanup_pool_; }; #endif // IOS_CHROME_TEST_BLOCK_CLEANUP_TEST_H_
diff --git a/ios/chrome/test/block_cleanup_test.mm b/ios/chrome/test/block_cleanup_test.mm index 06ac9e4c..5b35057 100644 --- a/ios/chrome/test/block_cleanup_test.mm +++ b/ios/chrome/test/block_cleanup_test.mm
@@ -8,6 +8,7 @@ #include "base/logging.h" #import "base/mac/scoped_nsobject.h" +#import "base/mac/foundation_util.h" void BlockCleanupTest::SetUp() { block_cleanup_pool_ = [[NSAutoreleasePool alloc] init]; @@ -22,7 +23,7 @@ // Drain the autorelease pool to finish cleaning up after blocks. // TODO(rohitrao): Can this be an EXPECT, so as to not crash the whole suite? DCHECK(block_cleanup_pool_); - [block_cleanup_pool_ release]; + [base::mac::ObjCCastStrict<NSAutoreleasePool>(block_cleanup_pool_) release]; block_cleanup_pool_ = nil; PlatformTest::TearDown();
diff --git a/ios/web/ios_web_resources.grd b/ios/web/ios_web_resources.grd index 763a3f8c..193d0c6 100644 --- a/ios/web/ios_web_resources.grd +++ b/ios/web/ios_web_resources.grd
@@ -18,6 +18,7 @@ <include name="IDR_MOJO_UNICODE_JS" file="../../mojo/public/js/unicode.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_MOJO_VALIDATOR_JS" file="../../mojo/public/js/validator.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_IOS_MOJO_SUPPORT_JS" file="webui/resources/support.js" flattenhtml="true" type="BINDATA" /> + <include name="IDR_IOS_CONSOLE_JS" file="webui/resources/console.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_IOS_MOJO_SYNC_MESSAGE_CHANNEL_JS" file="webui/resources/sync_message_channel.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_IOS_MOJO_HANDLE_UTIL_JS" file="webui/resources/handle_util.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_IOS_MOJO_CORE_JS" file="webui/resources/core.js" flattenhtml="true" type="BINDATA" />
diff --git a/ios/web/public/test/web_test_with_web_state.mm b/ios/web/public/test/web_test_with_web_state.mm index 6ad0beb3..1b868c9d 100644 --- a/ios/web/public/test/web_test_with_web_state.mm +++ b/ios/web/public/test/web_test_with_web_state.mm
@@ -113,9 +113,7 @@ } void WebTestWithWebState::WaitForCondition(ConditionBlock condition) { - base::MessageLoop* messageLoop = base::MessageLoop::current(); - DCHECK(messageLoop); - base::test::ios::WaitUntilCondition(condition, messageLoop, + base::test::ios::WaitUntilCondition(condition, true, base::TimeDelta::FromSeconds(10)); }
diff --git a/ios/web/webui/crw_web_ui_manager.mm b/ios/web/webui/crw_web_ui_manager.mm index 298066ad..2efc12b7 100644 --- a/ios/web/webui/crw_web_ui_manager.mm +++ b/ios/web/webui/crw_web_ui_manager.mm
@@ -226,6 +226,7 @@ {mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS}, {mojo::kUnicodeModuleName, IDR_MOJO_UNICODE_JS}, {mojo::kValidatorModuleName, IDR_MOJO_VALIDATOR_JS}, + {web::kConsoleModuleName, IDR_IOS_CONSOLE_JS}, {web::kSyncMessageChannelModuleName, IDR_IOS_MOJO_SYNC_MESSAGE_CHANNEL_JS}, {web::kHandleUtilModuleName, IDR_IOS_MOJO_HANDLE_UTIL_JS},
diff --git a/ios/web/webui/mojo_js_constants.cc b/ios/web/webui/mojo_js_constants.cc index 5df3b6f0..ac6227f 100644 --- a/ios/web/webui/mojo_js_constants.cc +++ b/ios/web/webui/mojo_js_constants.cc
@@ -6,6 +6,7 @@ namespace web { +const char kConsoleModuleName[] = "console"; const char kSyncMessageChannelModuleName[] = "ios/mojo/public/js/sync_message_channel"; const char kHandleUtilModuleName[] = "ios/mojo/public/js/handle_util";
diff --git a/ios/web/webui/mojo_js_constants.h b/ios/web/webui/mojo_js_constants.h index e940a8516..3e08244 100644 --- a/ios/web/webui/mojo_js_constants.h +++ b/ios/web/webui/mojo_js_constants.h
@@ -7,6 +7,7 @@ namespace web { +extern const char kConsoleModuleName[]; extern const char kSyncMessageChannelModuleName[]; extern const char kHandleUtilModuleName[]; extern const char kSupportModuleName[];
diff --git a/ios/web/webui/resources/console.js b/ios/web/webui/resources/console.js new file mode 100644 index 0000000..4368b00 --- /dev/null +++ b/ios/web/webui/resources/console.js
@@ -0,0 +1,25 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Module "console" +// +// This module provides basic logging support. The reason to define this module +// to forward calls to the |console| object exposed by the browser, instead of +// using that object directly: mojo JS bindings are currently loaded using gin +// and the |console| object is not always available. When the Mojo JS bindings +// move away from gin, this module could be removed. + +define("console", [], function() { + /** + * Logs a message to the console. + * @param {string} message to log. + */ + function log(message) { + console.log(message); + } + + var exports = {}; + exports.log = log; + return exports; +});
diff --git a/media/gpu/video_decode_accelerator_unittest.cc b/media/gpu/video_decode_accelerator_unittest.cc index 96e5d0b0..6723474 100644 --- a/media/gpu/video_decode_accelerator_unittest.cc +++ b/media/gpu/video_decode_accelerator_unittest.cc
@@ -50,6 +50,7 @@ #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "base/test/launcher/unit_test_launcher.h" +#include "base/test/scoped_task_scheduler.h" #include "base/test/test_suite.h" #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" @@ -1765,6 +1766,13 @@ base::MessageLoop main_loop; #endif // OS_WIN || USE_OZONE + base::test::ScopedTaskScheduler scoped_task_scheduler(&main_loop); + + media::g_env = + reinterpret_cast<media::VideoDecodeAcceleratorTestEnvironment*>( + testing::AddGlobalTestEnvironment( + new media::VideoDecodeAcceleratorTestEnvironment())); + #if defined(USE_OZONE) ui::OzonePlatform::InitializeForUI(); #endif @@ -1847,11 +1855,6 @@ base::ShadowingAtExitManager at_exit_manager; - media::g_env = - reinterpret_cast<media::VideoDecodeAcceleratorTestEnvironment*>( - testing::AddGlobalTestEnvironment( - new media::VideoDecodeAcceleratorTestEnvironment())); - return base::LaunchUnitTestsSerially( argc, argv, base::Bind(&media::VDATestSuite::Run, base::Unretained(&test_suite)));
diff --git a/mojo/public/js/router.js b/mojo/public/js/router.js index 3f0d96b..9db1220 100644 --- a/mojo/public/js/router.js +++ b/mojo/public/js/router.js
@@ -3,11 +3,12 @@ // found in the LICENSE file. define("mojo/public/js/router", [ + "console", "mojo/public/js/codec", "mojo/public/js/core", "mojo/public/js/connector", "mojo/public/js/validator", -], function(codec, core, connector, validator) { +], function(console, codec, core, connector, validator) { var Connector = connector.Connector; var MessageReader = codec.MessageReader; @@ -117,8 +118,12 @@ var reader = new MessageReader(message); var requestID = reader.requestID; var completer = this.completers_.get(requestID); - this.completers_.delete(requestID); - completer.resolve(message); + if (completer) { + this.completers_.delete(requestID); + completer.resolve(message); + } else { + console.log("Unexpected response with request ID: " + requestID); + } } else { if (this.incomingReceiver_) this.incomingReceiver_.accept(message); @@ -127,10 +132,12 @@ Router.prototype.handleInvalidIncomingMessage_ = function(message, error) { if (!this.testingController_) { - // TODO(yzshen): Consider logging and notifying the embedder. + // TODO(yzshen): Consider notifying the embedder. // TODO(yzshen): This should also trigger connection error handler. // Consider making accept() return a boolean and let the connector deal // with this, as the C++ code does. + console.log("Invalid message: " + validator.validationError[error]); + this.close(); return; }
diff --git a/net/base/arena.cc b/net/base/arena.cc index eeb28633..3bf29a7 100644 --- a/net/base/arena.cc +++ b/net/base/arena.cc
@@ -68,6 +68,7 @@ void UnsafeArena::Reset() { blocks_.clear(); + status_.bytes_allocated_ = 0; } void UnsafeArena::Reserve(size_t additional_space) { @@ -83,6 +84,7 @@ void UnsafeArena::AllocBlock(size_t size) { blocks_.push_back(Block(size)); + status_.bytes_allocated_ += size; } UnsafeArena::Block::Block(size_t s) : data(new char[s]), size(s), used(0) {}
diff --git a/net/base/arena.h b/net/base/arena.h index 223517d..f9a31ac 100644 --- a/net/base/arena.h +++ b/net/base/arena.h
@@ -16,6 +16,16 @@ // Not thread-safe. class NET_EXPORT_PRIVATE UnsafeArena { public: + class Status { + private: + friend class UnsafeArena; + size_t bytes_allocated_; + + public: + Status() : bytes_allocated_(0) {} + size_t bytes_allocated() const { return bytes_allocated_; } + }; + // Blocks allocated by this arena will be at least |block_size| bytes. explicit UnsafeArena(size_t block_size); ~UnsafeArena(); @@ -39,6 +49,8 @@ void Reset(); + Status status() const { return status_; } + private: struct Block { std::unique_ptr<char[]> data; @@ -57,6 +69,7 @@ size_t block_size_; std::vector<Block> blocks_; + Status status_; }; } // namespace net
diff --git a/net/disk_cache/blockfile/file_ios.cc b/net/disk_cache/blockfile/file_ios.cc index 5c9a6fad..47ff7f8 100644 --- a/net/disk_cache/blockfile/file_ios.cc +++ b/net/disk_cache/blockfile/file_ios.cc
@@ -14,7 +14,7 @@ #include "base/location.h" #include "base/logging.h" #include "base/macros.h" -#include "base/threading/worker_pool.h" +#include "base/task_scheduler/post_task.h" #include "net/base/net_errors.h" #include "net/disk_cache/blockfile/in_flight_io.h" #include "net/disk_cache/disk_cache.h" @@ -121,8 +121,12 @@ new FileBackgroundIO(file, buf, buf_len, offset, callback, this)); file->AddRef(); // Balanced on OnOperationComplete() - base::WorkerPool::PostTask(FROM_HERE, - base::Bind(&FileBackgroundIO::Read, operation.get()), true); + base::PostTaskWithTraits( + FROM_HERE, base::TaskTraits() + .WithShutdownBehavior( + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) + .MayBlock(), + base::Bind(&FileBackgroundIO::Read, operation.get())); OnOperationPosted(operation.get()); } @@ -133,8 +137,12 @@ new FileBackgroundIO(file, buf, buf_len, offset, callback, this)); file->AddRef(); // Balanced on OnOperationComplete() - base::WorkerPool::PostTask(FROM_HERE, - base::Bind(&FileBackgroundIO::Write, operation.get()), true); + base::PostTaskWithTraits( + FROM_HERE, base::TaskTraits() + .WithShutdownBehavior( + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) + .MayBlock(), + base::Bind(&FileBackgroundIO::Write, operation.get())); OnOperationPosted(operation.get()); }
diff --git a/net/disk_cache/disk_cache_perftest.cc b/net/disk_cache/disk_cache_perftest.cc index b4ad47d..eeef3b7 100644 --- a/net/disk_cache/disk_cache_perftest.cc +++ b/net/disk_cache/disk_cache_perftest.cc
@@ -62,7 +62,7 @@ ~DiskCachePerfTest() override { if (saved_fd_limit_ < kFdLimitForCacheTests) - MaybeSetFdLimit(kFdLimitForCacheTests); + MaybeSetFdLimit(saved_fd_limit_); } protected:
diff --git a/net/disk_cache/disk_cache_test_base.h b/net/disk_cache/disk_cache_test_base.h index c94f5ac8..9dde5bf 100644 --- a/net/disk_cache/disk_cache_test_base.h +++ b/net/disk_cache/disk_cache_test_base.h
@@ -12,6 +12,7 @@ #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/macros.h" +#include "base/test/scoped_async_task_scheduler.h" #include "base/threading/thread.h" #include "net/base/cache_type.h" #include "net/disk_cache/disk_cache.h" @@ -56,6 +57,12 @@ private: base::ScopedTempDir temp_dir_; std::unique_ptr<base::MessageLoop> message_loop_; + + // Use a ScopedAsyncTaskScheduler instead of a ScopedTaskScheduler to allow + // disk_cache::InFlightIO::WaitForPendingIO to wait for TaskScheduler tasks + // from the main thread using WaitableEvents (this wouldn't work if + // TaskScheduler tasks ran on the main thread). + base::test::ScopedAsyncTaskScheduler scoped_async_task_scheduler_; }; // Provides basic support for cache related tests.
diff --git a/net/http/http_util.cc b/net/http/http_util.cc index bb980bd0d..62bed8c 100644 --- a/net/http/http_util.cc +++ b/net/http/http_util.cc
@@ -312,30 +312,8 @@ return true; } -// static -bool HttpUtil::HasHeader(const std::string& headers, const char* name) { - size_t name_len = strlen(name); - std::string::const_iterator it = - std::search(headers.begin(), - headers.end(), - name, - name + name_len, - base::CaseInsensitiveCompareASCII<char>()); - if (it == headers.end()) - return false; - - // ensure match is prefixed by newline - if (it != headers.begin() && it[-1] != '\n') - return false; - - // ensure match is suffixed by colon - if (it + name_len >= headers.end() || it[name_len] != ':') - return false; - - return true; -} - namespace { + // A header string containing any of the following fields will cause // an error. The list comes from the XMLHttpRequest standard. // http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method @@ -362,7 +340,8 @@ "user-agent", "via", }; -} // anonymous namespace + +} // namespace // static bool HttpUtil::IsSafeHeader(const std::string& name) { @@ -781,16 +760,6 @@ return lang_list_with_q; } -void HttpUtil::AppendHeaderIfMissing(const char* header_name, - const std::string& header_value, - std::string* headers) { - if (header_value.empty()) - return; - if (HttpUtil::HasHeader(*headers, header_name)) - return; - *headers += std::string(header_name) + ": " + header_value + "\r\n"; -} - bool HttpUtil::HasStrongValidators(HttpVersion version, const std::string& etag_header, const std::string& last_modified_header,
diff --git a/net/http/http_util.h b/net/http/http_util.h index 1ccf9cc..267b96400 100644 --- a/net/http/http_util.h +++ b/net/http/http_util.h
@@ -74,11 +74,6 @@ base::Time now, base::TimeDelta* retry_after); - // Scans the '\r\n'-delimited headers for the given header name. Returns - // true if a match is found. Input is assumed to be well-formed. - // TODO(darin): kill this - static bool HasHeader(const std::string& headers, const char* name); - // Returns true if it is safe to allow users and scripts to specify the header // named |name|. static bool IsSafeHeader(const std::string& name); @@ -210,12 +205,6 @@ static std::string GenerateAcceptLanguageHeader( const std::string& raw_language_list); - // Helper. If |*headers| already contains |header_name| do nothing, - // otherwise add <header_name> ": " <header_value> to the end of the list. - static void AppendHeaderIfMissing(const char* header_name, - const std::string& header_value, - std::string* headers); - // Returns true if the parameters describe a response with a strong etag or // last-modified header. See section 13.3.3 of RFC 2616. // An empty string should be passed for missing headers.
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc index 34c98483..3560e2f4 100644 --- a/net/http/http_util_unittest.cc +++ b/net/http/http_util_unittest.cc
@@ -100,26 +100,6 @@ } } -TEST(HttpUtilTest, HasHeader) { - static const struct { - const char* const headers; - const char* const name; - bool expected_result; - } tests[] = { - { "", "foo", false }, - { "foo\r\nbar", "foo", false }, - { "ffoo: 1", "foo", false }, - { "foo: 1", "foo", true }, - { "foo: 1\r\nbar: 2", "foo", true }, - { "fOO: 1\r\nbar: 2", "foo", true }, - { "g: 0\r\nfoo: 1\r\nbar: 2", "foo", true }, - }; - for (size_t i = 0; i < arraysize(tests); ++i) { - bool result = HttpUtil::HasHeader(tests[i].headers, tests[i].name); - EXPECT_EQ(tests[i].expected_result, result); - } -} - TEST(HttpUtilTest, HeadersIterator) { std::string headers = "foo: 1\t\r\nbar: hello world\r\nbaz: 3 \r\n";
diff --git a/net/http2/decoder/decode_buffer_test.cc b/net/http2/decoder/decode_buffer_test.cc index 35a9fbb..a4d10d7c 100644 --- a/net/http2/decoder/decode_buffer_test.cc +++ b/net/http2/decoder/decode_buffer_test.cc
@@ -6,9 +6,6 @@ #include <string> -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" #include "base/logging.h" #include "base/strings/string_piece.h" #include "net/http2/tools/http2_random.h" @@ -68,7 +65,7 @@ bool SlowDecodeField(DecodeBuffer* b, size_t field_size, size_t field_offset, - const base::Callback<bool(DecodeBuffer*)>& fn, + std::function<bool(DecodeBuffer*)> fn, T* f) { VLOG(2) << "Remaining: " << b->Remaining(); VLOG(2) << "field_size: " << field_size; @@ -80,7 +77,7 @@ uint32_t old = static_cast<uint32_t>(*f); VLOG(2) << "old: " << old; size_t old_decode_offset = decode_offset_; - bool done = fn.Run(b); + bool done = fn(b); VLOG(2) << "done: " << done; if (old_decode_offset == decode_offset_) { // Didn't do any decoding (may have no input, or may have already @@ -106,35 +103,35 @@ return done; } - bool decode_f1(TestStruct* p, DecodeBuffer* db) { - return db->SlowDecodeUInt8(kF1Offset, &decode_offset_, &p->f1); - } - bool decode_f2(TestStruct* p, DecodeBuffer* db) { - return db->SlowDecodeUInt16(kF2Offset, &decode_offset_, &p->f2); - } - bool decode_f3(TestStruct* p, DecodeBuffer* db) { - return db->SlowDecodeUInt24(kF3Offset, &decode_offset_, &p->f3); - } - bool decode_f4(TestStruct* p, DecodeBuffer* db) { - return db->SlowDecodeUInt32(kF4Offset, &decode_offset_, &p->f4); - } - bool decode_f5(TestStruct* p, DecodeBuffer* db) { - return db->SlowDecodeUInt31(kF5Offset, &decode_offset_, &p->f5); - } - bool decode_f6(TestStruct* p, DecodeBuffer* db) { - return db->SlowDecodeEnum(4, kF6Offset, &decode_offset_, &p->f6); - } - bool decode_f7(TestStruct* p, DecodeBuffer* db) { - return db->SlowDecodeEnum(1, kF7Offset, &decode_offset_, &p->f7); - } - bool decode_f8(TestStruct* p, DecodeBuffer* db) { - return db->SlowDecodeEnum(1, kF8Offset, &decode_offset_, &p->f8); - } void SlowDecodeTestStruct(StringPiece input, TestStruct* p) { VLOG(2) << "############################################################"; EXPECT_LE(10u, input.size()); decode_offset_ = 0; + auto decode_f1 = [this, p](DecodeBuffer* db) { + return db->SlowDecodeUInt8(kF1Offset, &decode_offset_, &p->f1); + }; + auto decode_f2 = [this, p](DecodeBuffer* db) { + return db->SlowDecodeUInt16(kF2Offset, &decode_offset_, &p->f2); + }; + auto decode_f3 = [this, p](DecodeBuffer* db) { + return db->SlowDecodeUInt24(kF3Offset, &decode_offset_, &p->f3); + }; + auto decode_f4 = [this, p](DecodeBuffer* db) { + return db->SlowDecodeUInt32(kF4Offset, &decode_offset_, &p->f4); + }; + auto decode_f5 = [this, p](DecodeBuffer* db) { + return db->SlowDecodeUInt31(kF5Offset, &decode_offset_, &p->f5); + }; + auto decode_f6 = [this, p](DecodeBuffer* db) { + return db->SlowDecodeEnum(4, kF6Offset, &decode_offset_, &p->f6); + }; + auto decode_f7 = [this, p](DecodeBuffer* db) { + return db->SlowDecodeEnum(1, kF7Offset, &decode_offset_, &p->f7); + }; + auto decode_f8 = [this, p](DecodeBuffer* db) { + return db->SlowDecodeEnum(1, kF8Offset, &decode_offset_, &p->f8); + }; while (input.size() > 0) { size_t size = input.size(); // Sometimes check that zero length input is OK. @@ -148,38 +145,14 @@ VLOG(2) << "================= input size " << size; DecodeBuffer b(input.data(), size); size_t old_decode_offset = decode_offset_; - if (SlowDecodeField(&b, 1, kF1Offset, - base::Bind(&DecodeBufferTest::decode_f1, - base::Unretained(this), p), - &p->f1) && - SlowDecodeField(&b, 2, kF2Offset, - base::Bind(&DecodeBufferTest::decode_f2, - base::Unretained(this), p), - &p->f2) && - SlowDecodeField(&b, 3, kF3Offset, - base::Bind(&DecodeBufferTest::decode_f3, - base::Unretained(this), p), - &p->f3) && - SlowDecodeField(&b, 4, kF4Offset, - base::Bind(&DecodeBufferTest::decode_f4, - base::Unretained(this), p), - &p->f4) && - SlowDecodeField(&b, 4, kF5Offset, - base::Bind(&DecodeBufferTest::decode_f5, - base::Unretained(this), p), - &p->f5) && - SlowDecodeField(&b, 4, kF6Offset, - base::Bind(&DecodeBufferTest::decode_f6, - base::Unretained(this), p), - &p->f6) && - SlowDecodeField(&b, 1, kF7Offset, - base::Bind(&DecodeBufferTest::decode_f7, - base::Unretained(this), p), - &p->f7) && - SlowDecodeField(&b, 1, kF8Offset, - base::Bind(&DecodeBufferTest::decode_f8, - base::Unretained(this), p), - &p->f8)) { + if (SlowDecodeField(&b, 1, kF1Offset, decode_f1, &p->f1) && + SlowDecodeField(&b, 2, kF2Offset, decode_f2, &p->f2) && + SlowDecodeField(&b, 3, kF3Offset, decode_f3, &p->f3) && + SlowDecodeField(&b, 4, kF4Offset, decode_f4, &p->f4) && + SlowDecodeField(&b, 4, kF5Offset, decode_f5, &p->f5) && + SlowDecodeField(&b, 4, kF6Offset, decode_f6, &p->f6) && + SlowDecodeField(&b, 1, kF7Offset, decode_f7, &p->f7) && + SlowDecodeField(&b, 1, kF8Offset, decode_f8, &p->f8)) { EXPECT_TRUE(b.Empty()); EXPECT_EQ(size, input.size()); EXPECT_EQ(input.size(), b.Offset()); // All input consumed. @@ -245,7 +218,6 @@ ts.f2 = random_.Rand16(); ts.f3 = random_.Rand32(); ts.f4 = random_.Rand32(); - // Ensure high-bit is set. ts.f5 = 0x80000000 | random_.Rand32(); // Ensure high-bit is set. ts.f6 = static_cast<TestEnumClass32>(random_.Rand32()); ts.f7 = static_cast<TestEnumClass8>(random_.Rand8());
diff --git a/net/http2/decoder/decode_http2_structures_test.cc b/net/http2/decoder/decode_http2_structures_test.cc index 4b09e7a..0a76bdc 100644 --- a/net/http2/decoder/decode_http2_structures_test.cc +++ b/net/http2/decoder/decode_http2_structures_test.cc
@@ -14,8 +14,6 @@ #include <stddef.h> #include <string> -#include "base/bind.h" -#include "base/bind_helpers.h" #include "base/logging.h" #include "base/strings/string_piece.h" #include "net/http2/decoder/decode_buffer.h" @@ -110,17 +108,6 @@ // Set the fields of |*p| to random values. void Randomize(S* p) { ::net::test::Randomize(p, RandomPtr()); } - AssertionResult ValidatorForDecodeLeadingStructure(const S* expected, - const DecodeBuffer& db, - DecodeStatus status) { - if (expected != nullptr && *expected != structure_) { - return AssertionFailure() - << "Expected structs to be equal\nExpected: " << *expected - << "\n Actual: " << structure_; - } - return AssertionSuccess(); - } - // Fully decodes the Structure at the start of data, and confirms it matches // *expected (if provided). void DecodeLeadingStructure(const S* expected, StringPiece data) { @@ -130,20 +117,25 @@ // The validator is called after each of the several times that the input // DecodeBuffer is decoded, each with a different segmentation of the input. // Validate that structure_ matches the expected value, if provided. - Validator validator = - base::Bind(&StructureDecoderTest::ValidatorForDecodeLeadingStructure, - base::Unretained(this), expected); + Validator validator = [expected, this]( + const DecodeBuffer& db, DecodeStatus status) -> AssertionResult { + if (expected != nullptr && *expected != structure_) { + return AssertionFailure() + << "Expected structs to be equal\nExpected: " << *expected + << "\n Actual: " << structure_; + } + return AssertionSuccess(); + }; // First validate that decoding is done and that we've advanced the cursor // the expected amount. - Validator wrapped_validator = - ValidateDoneAndOffset(S::EncodedSize(), validator); + validator = ValidateDoneAndOffset(S::EncodedSize(), validator); // Decode several times, with several segmentations of the input buffer. fast_decode_count_ = 0; slow_decode_count_ = 0; EXPECT_TRUE(DecodeAndValidateSeveralWays( - &original, false /*return_non_zero_on_first*/, wrapped_validator)); + &original, false /*return_non_zero_on_first*/, validator)); if (!HasFailure()) { EXPECT_EQ(S::EncodedSize(), decode_offset_);
diff --git a/net/http2/decoder/http2_frame_decoder_test.cc b/net/http2/decoder/http2_frame_decoder_test.cc index ee1e9e49..0d1d278 100644 --- a/net/http2/decoder/http2_frame_decoder_test.cc +++ b/net/http2/decoder/http2_frame_decoder_test.cc
@@ -10,8 +10,6 @@ #include <string> #include <vector> -#include "base/bind.h" -#include "base/bind_helpers.h" #include "base/logging.h" #include "net/http2/decoder/frame_parts.h" #include "net/http2/decoder/frame_parts_collector_listener.h" @@ -38,24 +36,6 @@ namespace { class Http2FrameDecoderTest : public RandomDecoderTest { - public: - AssertionResult ValidatorForDecodePayloadExpectingError( - const FrameParts& expected, - const DecodeBuffer& input, - DecodeStatus status) { - VERIFY_EQ(status, DecodeStatus::kDecodeError); - VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected)); - } - - AssertionResult ValidatorForBeyondMaximum(const FrameParts& expected, - const DecodeBuffer& input, - DecodeStatus status) { - VERIFY_EQ(status, DecodeStatus::kDecodeError); - // The decoder detects this error after decoding the header, and without - // trying to decode the payload. - VERIFY_EQ(input.Offset(), Http2FrameHeader::EncodedSize()); - VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected)); - } protected: void SetUp() override { @@ -152,13 +132,6 @@ validator); } - AssertionResult ValidatorForDecodePayloadAndValidateSeveralWays( - const FrameParts& expected, - const DecodeBuffer& input, - DecodeStatus status) { - VERIFY_EQ(status, DecodeStatus::kDecodeDone); - VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected)); - } // Decode one frame's payload and confirm that the listener recorded the // expected FrameParts instance, and only one FrameParts instance. The @@ -167,9 +140,11 @@ AssertionResult DecodePayloadAndValidateSeveralWays( StringPiece payload, const FrameParts& expected) { - Validator validator = base::Bind( - &Http2FrameDecoderTest::ValidatorForDecodePayloadAndValidateSeveralWays, - base::Unretained(this), base::ConstRef(expected)); + Validator validator = [&expected, this]( + const DecodeBuffer& input, DecodeStatus status) -> AssertionResult { + VERIFY_EQ(status, DecodeStatus::kDecodeDone); + VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected)); + }; ResetDecodeSpeedCounters(); VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays( payload, ValidateDoneAndEmpty(validator))); @@ -209,12 +184,14 @@ template <size_t N> AssertionResult DecodePayloadExpectingError(const char (&buf)[N], const FrameParts& expected) { + auto validator = [&expected, this](const DecodeBuffer& input, + DecodeStatus status) -> AssertionResult { + VERIFY_EQ(status, DecodeStatus::kDecodeError); + VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected)); + }; ResetDecodeSpeedCounters(); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays( - ToStringPiece(buf), - base::Bind( - &Http2FrameDecoderTest::ValidatorForDecodePayloadExpectingError, - base::Unretained(this), expected))); + EXPECT_TRUE( + DecodePayloadAndValidateSeveralWays(ToStringPiece(buf), validator)); EXPECT_GT(fast_decode_count_, 0u); EXPECT_GT(slow_decode_count_, 0u); return AssertionSuccess(); @@ -865,11 +842,17 @@ Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_PADDED, 2); FrameParts expected(header); expected.has_frame_size_error = true; + auto validator = [&expected, this](const DecodeBuffer& input, + DecodeStatus status) -> AssertionResult { + VERIFY_EQ(status, DecodeStatus::kDecodeError); + // The decoder detects this error after decoding the header, and without + // trying to decode the payload. + VERIFY_EQ(input.Offset(), Http2FrameHeader::EncodedSize()); + VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected)); + }; ResetDecodeSpeedCounters(); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays( - ToStringPiece(kFrameData), - base::Bind(&Http2FrameDecoderTest::ValidatorForBeyondMaximum, - base::Unretained(this), expected))); + EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(ToStringPiece(kFrameData), + validator)); EXPECT_GT(fast_decode_count_, 0u); EXPECT_GT(slow_decode_count_, 0u); }
diff --git a/net/http2/decoder/http2_structure_decoder_test.cc b/net/http2/decoder/http2_structure_decoder_test.cc index 68479a1..3ff2f98 100644 --- a/net/http2/decoder/http2_structure_decoder_test.cc +++ b/net/http2/decoder/http2_structure_decoder_test.cc
@@ -21,8 +21,6 @@ #include <stddef.h> #include <string> -#include "base/bind.h" -#include "base/bind_helpers.h" #include "base/logging.h" #include "base/strings/string_piece.h" #include "net/http2/decoder/decode_buffer.h" @@ -102,12 +100,6 @@ } } - AssertionResult ValidatorForDecodeLeadingStructure(const S* expected, - const DecodeBuffer& db, - DecodeStatus status) { - VERIFY_EQ(*expected, structure_); - return AssertionSuccess(); - } // Fully decodes the Structure at the start of data, and confirms it matches // *expected (if provided). @@ -118,17 +110,18 @@ // The validator is called after each of the several times that the input // DecodeBuffer is decoded, each with a different segmentation of the input. // Validate that structure_ matches the expected value, if provided. - Validator validator = - (expected == nullptr) - ? base::Bind(&SucceedingValidator) - : base::Bind(&Http2StructureDecoderTest:: - ValidatorForDecodeLeadingStructure, - base::Unretained(this), expected); + Validator validator; + if (expected != nullptr) { + validator = [expected, this](const DecodeBuffer& db, + DecodeStatus status) -> AssertionResult { + VERIFY_EQ(*expected, structure_); + return AssertionSuccess(); + }; + } // Before that, validate that decoding is done and that we've advanced // the cursor the expected amount. - Validator wrapped_validator = - ValidateDoneAndOffset(S::EncodedSize(), validator); + validator = ValidateDoneAndOffset(S::EncodedSize(), validator); // Decode several times, with several segmentations of the input buffer. fast_decode_count_ = 0; @@ -136,7 +129,7 @@ incomplete_start_count_ = 0; incomplete_resume_count_ = 0; VERIFY_SUCCESS(DecodeAndValidateSeveralWays( - &original, kMayReturnZeroOnFirst, wrapped_validator)); + &original, kMayReturnZeroOnFirst, validator)); VERIFY_FALSE(HasFailure()); VERIFY_EQ(S::EncodedSize(), structure_decoder_.offset()); VERIFY_EQ(S::EncodedSize(), original.Offset());
diff --git a/net/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc index e10fc50..5fa62d61 100644 --- a/net/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc +++ b/net/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc
@@ -8,7 +8,6 @@ #include <string> -#include "base/bind.h" #include "base/logging.h" #include "net/http2/decoder/frame_parts.h" #include "net/http2/decoder/frame_parts_collector.h" @@ -88,9 +87,8 @@ Http2FrameBuilder fb; fb.Append(Http2AltSvcFields{0xffff}); // The longest possible origin length. fb.Append("Too little origin!"); - EXPECT_TRUE(VerifyDetectsFrameSizeError( - 0, fb.buffer(), - base::Bind(&AbstractPayloadDecoderTest::SucceedingApproveSize))); + EXPECT_TRUE( + VerifyDetectsFrameSizeError(0, fb.buffer(), /*approve_size*/ nullptr)); } class AltSvcPayloadLengthTests : public AltSvcPayloadDecoderTest,
diff --git a/net/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc index 248ac0d..cddda79 100644 --- a/net/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc +++ b/net/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc
@@ -8,7 +8,6 @@ #include <string> -#include "base/bind.h" #include "base/logging.h" #include "net/http2/decoder/frame_parts.h" #include "net/http2/decoder/frame_parts_collector.h" @@ -70,21 +69,17 @@ class GoAwayPayloadDecoderTest : public AbstractPayloadDecoderTest<GoAwayPayloadDecoder, GoAwayPayloadDecoderPeer, - Listener> { - public: - static bool ApproveSizeForTruncated(size_t size) { - return size != Http2GoAwayFields::EncodedSize(); - } -}; + Listener> {}; // Confirm we get an error if the payload is not long enough to hold // Http2GoAwayFields. TEST_F(GoAwayPayloadDecoderTest, Truncated) { + auto approve_size = [](size_t size) { + return size != Http2GoAwayFields::EncodedSize(); + }; Http2FrameBuilder fb; fb.Append(Http2GoAwayFields(123, Http2ErrorCode::ENHANCE_YOUR_CALM)); - EXPECT_TRUE(VerifyDetectsFrameSizeError( - 0, fb.buffer(), - base::Bind(&GoAwayPayloadDecoderTest::ApproveSizeForTruncated))); + EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); } class GoAwayOpaqueDataLengthTests
diff --git a/net/http2/decoder/payload_decoders/headers_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/headers_payload_decoder_test.cc index 89bd29f..69bf56f 100644 --- a/net/http2/decoder/payload_decoders/headers_payload_decoder_test.cc +++ b/net/http2/decoder/payload_decoders/headers_payload_decoder_test.cc
@@ -8,7 +8,6 @@ #include <string> -#include "base/bind.h" #include "base/logging.h" #include "net/http2/decoder/frame_parts.h" #include "net/http2/decoder/frame_parts_collector.h" @@ -103,12 +102,7 @@ class HeadersPayloadDecoderTest : public AbstractPaddablePayloadDecoderTest<HeadersPayloadDecoder, HeadersPayloadDecoderPeer, - Listener> { - public: - static bool ApproveSizeForTruncated(size_t size) { - return size != Http2PriorityFields::EncodedSize(); - } -}; + Listener> {}; INSTANTIATE_TEST_CASE_P(VariousPadLengths, HeadersPayloadDecoderTest, @@ -153,12 +147,14 @@ // Confirm we get an error if the PRIORITY flag is set but the payload is // not long enough, regardless of the amount of (valid) padding. TEST_P(HeadersPayloadDecoderTest, Truncated) { + auto approve_size = [](size_t size) { + return size != Http2PriorityFields::EncodedSize(); + }; Http2FrameBuilder fb; fb.Append(Http2PriorityFields(RandStreamId(), 1 + Random().Rand8(), Random().OneIn(2))); EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors( - Http2FrameFlag::FLAG_PRIORITY, fb.buffer(), - base::Bind(&HeadersPayloadDecoderTest::ApproveSizeForTruncated), + Http2FrameFlag::FLAG_PRIORITY, fb.buffer(), approve_size, total_pad_length_)); }
diff --git a/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h b/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h index b49b15ef..5f998e4 100644 --- a/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h +++ b/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h
@@ -11,9 +11,6 @@ #include <string> -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" #include "base/logging.h" #include "base/strings/string_piece.h" #include "net/http2/decoder/decode_buffer.h" @@ -123,15 +120,13 @@ class Listener, bool SupportedFrameType = true> class AbstractPayloadDecoderTest : public PayloadDecoderBaseTest { - public: - static bool SucceedingApproveSize(size_t size) { return true; } protected: // An ApproveSize function returns true to approve decoding the specified // size of payload, else false to skip that size. Typically used for negative // tests; for example, decoding a SETTINGS frame at all sizes except for // multiples of 6. - typedef base::Callback<bool(size_t size)> ApproveSize; + typedef std::function<bool(size_t size)> ApproveSize; AbstractPayloadDecoderTest() {} @@ -196,14 +191,6 @@ return payload_decoder_.ResumeDecodingPayload(mutable_state(), db); } - // Wrap |validator| in another one which will check that we've reached the - // expected state of kDecodeError with OnFrameSizeError having been called by - AssertionResult ValidatorForDecodePayloadAndValidateSeveralWays( - const FrameParts& expected) { - VERIFY_FALSE(listener_.IsInProgress()); - VERIFY_EQ(1u, listener_.size()); - VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*listener_.frame(0))); - } // Decode one frame's payload and confirm that the listener recorded the // expected FrameParts instance, and only FrameParts instance. The payload @@ -212,33 +199,13 @@ AssertionResult DecodePayloadAndValidateSeveralWays( base::StringPiece payload, const FrameParts& expected) { + NoArgValidator validator = [&expected, this]() -> AssertionResult { + VERIFY_FALSE(listener_.IsInProgress()); + VERIFY_EQ(1u, listener_.size()); + VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*listener_.frame(0))); + }; return PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays( - payload, this->ValidateDoneAndEmpty(base::Bind( - &AbstractPayloadDecoderTest:: - ValidatorForDecodePayloadAndValidateSeveralWays, - base::Unretained(this), base::ConstRef(expected)))); - } - - // Wrap |validator| in another one which will check that we've reached the - // expected state of kDecodeError with OnFrameSizeError having been called by - // the payload decoder. - AssertionResult ValidatorForVerifyDetectsFrameSizeError( - const Http2FrameHeader& header, - const Validator& validator, - const DecodeBuffer& input, - DecodeStatus status) { - DVLOG(2) << "VerifyDetectsFrameSizeError validator; status=" << status - << "; input.Remaining=" << input.Remaining(); - VERIFY_EQ(DecodeStatus::kDecodeError, status); - VERIFY_FALSE(listener_.IsInProgress()); - VERIFY_EQ(1u, listener_.size()); - const FrameParts* frame = listener_.frame(0); - VERIFY_EQ(header, frame->frame_header); - VERIFY_TRUE(frame->has_frame_size_error); - // Verify did not get OnPaddingTooLong, as we should only ever produce - // one of these two errors for a single frame. - VERIFY_FALSE(frame->opt_missing_length); - return validator.Run(input, status); + payload, ValidateDoneAndEmpty(validator)); } // Decode one frame's payload, expecting that the final status will be @@ -254,13 +221,29 @@ WrappedValidator wrapped_validator) { set_frame_header(header); // If wrapped_validator is not a RandomDecoderTest::Validator, make it so. - Validator validator = this->ToValidator(wrapped_validator); + Validator validator = ToValidator(wrapped_validator); + // And wrap that validator in another which will check that we've reached + // the expected state of kDecodeError with OnFrameSizeError having been + // called by the payload decoder. + validator = [header, validator, this]( + const DecodeBuffer& input, + DecodeStatus status) -> ::testing::AssertionResult { + DVLOG(2) << "VerifyDetectsFrameSizeError validator; status=" << status + << "; input.Remaining=" << input.Remaining(); + VERIFY_EQ(DecodeStatus::kDecodeError, status); + VERIFY_FALSE(listener_.IsInProgress()); + VERIFY_EQ(1u, listener_.size()); + const FrameParts* frame = listener_.frame(0); + VERIFY_EQ(header, frame->frame_header); + VERIFY_TRUE(frame->has_frame_size_error); + // Verify did not get OnPaddingTooLong, as we should only ever produce + // one of these two errors for a single frame. + VERIFY_FALSE(frame->opt_missing_length); + return validator(input, status); + }; VERIFY_AND_RETURN_SUCCESS( - PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays( - payload, base::Bind(&AbstractPayloadDecoderTest:: - ValidatorForVerifyDetectsFrameSizeError, - base::Unretained(this), base::ConstRef(header), - base::ConstRef(validator)))); + PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(payload, + validator)); } // Confirm that we get OnFrameSizeError when trying to decode unpadded_payload @@ -299,7 +282,7 @@ bool validated = false; for (size_t real_payload_size = 0; real_payload_size <= unpadded_payload.size(); ++real_payload_size) { - if (!approve_size.Run(real_payload_size)) { + if (approve_size != nullptr && !approve_size(real_payload_size)) { continue; } VLOG(1) << "real_payload_size=" << real_payload_size; @@ -320,8 +303,7 @@ // checking stream ids. uint32_t stream_id = RandStreamId(); Http2FrameHeader header(fb.size(), frame_type, flags, stream_id); - VERIFY_SUCCESS(VerifyDetectsFrameSizeError( - fb.buffer(), header, base::Bind(&SucceedingValidator))); + VERIFY_SUCCESS(VerifyDetectsFrameSizeError(fb.buffer(), header, nullptr)); validated = true; } VERIFY_TRUE(validated); @@ -406,23 +388,6 @@ return flags; } - static ::testing::AssertionResult ValidatorForVerifyDetectsPaddingTooLong( - const Http2FrameHeader& header, - int expected_missing_length, - const Listener& listener, - const DecodeBuffer& input, - DecodeStatus status) { - VERIFY_EQ(DecodeStatus::kDecodeError, status); - VERIFY_FALSE(listener.IsInProgress()); - VERIFY_EQ(1u, listener.size()); - const FrameParts* frame = listener.frame(0); - VERIFY_EQ(header, frame->frame_header); - VERIFY_TRUE(frame->opt_missing_length); - VERIFY_EQ(expected_missing_length, frame->opt_missing_length.value()); - // Verify did not get OnFrameSizeError. - VERIFY_FALSE(frame->has_frame_size_error); - return ::testing::AssertionSuccess(); - } // Verify that we get OnPaddingTooLong when decoding payload, and that the // amount of missing padding is as specified. header.IsPadded must be true, @@ -433,12 +398,23 @@ int expected_missing_length) { set_frame_header(header); auto& listener = listener_; + Validator validator = [header, expected_missing_length, &listener]( + const DecodeBuffer& input, + DecodeStatus status) -> ::testing::AssertionResult { + VERIFY_EQ(DecodeStatus::kDecodeError, status); + VERIFY_FALSE(listener.IsInProgress()); + VERIFY_EQ(1u, listener.size()); + const FrameParts* frame = listener.frame(0); + VERIFY_EQ(header, frame->frame_header); + VERIFY_TRUE(frame->opt_missing_length); + VERIFY_EQ(expected_missing_length, frame->opt_missing_length.value()); + // Verify did not get OnFrameSizeError. + VERIFY_FALSE(frame->has_frame_size_error); + return ::testing::AssertionSuccess(); + }; VERIFY_AND_RETURN_SUCCESS( - PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays( - payload, base::Bind(&AbstractPaddablePayloadDecoderTest:: - ValidatorForVerifyDetectsPaddingTooLong, - header, expected_missing_length, - base::ConstRef(listener)))); + PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(payload, + validator)); } // Verifies that we get OnPaddingTooLong for a padded frame payload whose
diff --git a/net/http2/decoder/payload_decoders/ping_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/ping_payload_decoder_test.cc index c3696f7c..5733411 100644 --- a/net/http2/decoder/payload_decoders/ping_payload_decoder_test.cc +++ b/net/http2/decoder/payload_decoders/ping_payload_decoder_test.cc
@@ -6,7 +6,6 @@ #include <stddef.h> -#include "base/bind.h" #include "base/logging.h" #include "net/http2/decoder/frame_parts.h" #include "net/http2/decoder/frame_parts_collector.h" @@ -61,11 +60,6 @@ : public AbstractPayloadDecoderTest<PingPayloadDecoder, PingPayloadDecoderPeer, Listener> { - public: - static bool ApproveSizeForWrongSize(size_t size) { - return size != Http2PingFields::EncodedSize(); - } - protected: Http2PingFields RandPingFields() { Http2PingFields fields; @@ -77,13 +71,14 @@ // Confirm we get an error if the payload is not the correct size to hold // exactly one Http2PingFields. TEST_F(PingPayloadDecoderTest, WrongSize) { + auto approve_size = [](size_t size) { + return size != Http2PingFields::EncodedSize(); + }; Http2FrameBuilder fb; fb.Append(RandPingFields()); fb.Append(RandPingFields()); fb.Append(RandPingFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError( - 0, fb.buffer(), - base::Bind(&PingPayloadDecoderTest::ApproveSizeForWrongSize))); + EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); } TEST_F(PingPayloadDecoderTest, Ping) {
diff --git a/net/http2/decoder/payload_decoders/priority_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/priority_payload_decoder_test.cc index dabcba5..d40b07c 100644 --- a/net/http2/decoder/payload_decoders/priority_payload_decoder_test.cc +++ b/net/http2/decoder/payload_decoders/priority_payload_decoder_test.cc
@@ -6,7 +6,6 @@ #include <stddef.h> -#include "base/bind.h" #include "base/logging.h" #include "net/http2/decoder/frame_parts.h" #include "net/http2/decoder/frame_parts_collector.h" @@ -57,11 +56,6 @@ : public AbstractPayloadDecoderTest<PriorityPayloadDecoder, PriorityPayloadDecoderPeer, Listener> { - public: - static bool ApproveSizeForWrongSize(size_t size) { - return size != Http2PriorityFields::EncodedSize(); - } - protected: Http2PriorityFields RandPriorityFields() { Http2PriorityFields fields; @@ -73,12 +67,13 @@ // Confirm we get an error if the payload is not the correct size to hold // exactly one Http2PriorityFields. TEST_F(PriorityPayloadDecoderTest, WrongSize) { + auto approve_size = [](size_t size) { + return size != Http2PriorityFields::EncodedSize(); + }; Http2FrameBuilder fb; fb.Append(RandPriorityFields()); fb.Append(RandPriorityFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError( - 0, fb.buffer(), - base::Bind(&PriorityPayloadDecoderTest::ApproveSizeForWrongSize))); + EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); } TEST_F(PriorityPayloadDecoderTest, VariousPayloads) {
diff --git a/net/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc index ba1a815..f7d83836 100644 --- a/net/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc +++ b/net/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc
@@ -8,7 +8,6 @@ #include <string> -#include "base/bind.h" #include "base/logging.h" #include "net/http2/decoder/frame_parts.h" #include "net/http2/decoder/frame_parts_collector.h" @@ -96,10 +95,6 @@ : public AbstractPaddablePayloadDecoderTest<PushPromisePayloadDecoder, PushPromisePayloadDecoderPeer, Listener> { - public: - static bool ApproveSizeForTruncated(size_t size) { - return size != Http2PushPromiseFields::EncodedSize(); - } }; INSTANTIATE_TEST_CASE_P(VariousPadLengths, @@ -131,13 +126,14 @@ // Confirm we get an error if the payload is not long enough for the required // portion of the payload, regardless of the amount of (valid) padding. TEST_P(PushPromisePayloadDecoderTest, Truncated) { + auto approve_size = [](size_t size) { + return size != Http2PushPromiseFields::EncodedSize(); + }; Http2PushPromiseFields push_promise{RandStreamId()}; Http2FrameBuilder fb; fb.Append(push_promise); - EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors( - 0, fb.buffer(), - base::Bind(&PushPromisePayloadDecoderTest::ApproveSizeForTruncated), - total_pad_length_)); + EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(0, fb.buffer(), approve_size, + total_pad_length_)); } // Confirm we get an error if the PADDED flag is set but the payload is not
diff --git a/net/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc index 703d98ff..88bd803 100644 --- a/net/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc +++ b/net/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc
@@ -6,7 +6,6 @@ #include <stddef.h> -#include "base/bind.h" #include "base/logging.h" #include "net/http2/decoder/frame_parts.h" #include "net/http2/decoder/frame_parts_collector.h" @@ -58,11 +57,6 @@ : public AbstractPayloadDecoderTest<RstStreamPayloadDecoder, RstStreamPayloadDecoderPeer, Listener> { - public: - static bool ApproveSizeForWrongSize(size_t size) { - return size != Http2RstStreamFields::EncodedSize(); - } - protected: Http2RstStreamFields RandRstStreamFields() { Http2RstStreamFields fields; @@ -74,13 +68,14 @@ // Confirm we get an error if the payload is not the correct size to hold // exactly one Http2RstStreamFields. TEST_F(RstStreamPayloadDecoderTest, WrongSize) { + auto approve_size = [](size_t size) { + return size != Http2RstStreamFields::EncodedSize(); + }; Http2FrameBuilder fb; fb.Append(RandRstStreamFields()); fb.Append(RandRstStreamFields()); fb.Append(RandRstStreamFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError( - 0, fb.buffer(), - base::Bind(&RstStreamPayloadDecoderTest::ApproveSizeForWrongSize))); + EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); } TEST_F(RstStreamPayloadDecoderTest, AllErrors) {
diff --git a/net/http2/decoder/payload_decoders/settings_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/settings_payload_decoder_test.cc index 7a53797..4d26e1b 100644 --- a/net/http2/decoder/payload_decoders/settings_payload_decoder_test.cc +++ b/net/http2/decoder/payload_decoders/settings_payload_decoder_test.cc
@@ -8,7 +8,6 @@ #include <vector> -#include "base/bind.h" #include "base/logging.h" #include "net/http2/decoder/frame_parts.h" #include "net/http2/decoder/frame_parts_collector.h" @@ -78,17 +77,6 @@ : public AbstractPayloadDecoderTest<SettingsPayloadDecoder, SettingsPayloadDecoderPeer, Listener> { - public: - static bool ApproveSizeForSettingsWrongSize(size_t size) { - // Should get an error if size is not an integral multiple of the size - // of one setting. - return 0 != (size % Http2SettingFields::EncodedSize()); - } - - static bool ApproveSizeForSettingsAkcWrongSize(size_t size) { - return size != 0; - } - protected: Http2SettingFields RandSettingsFields() { Http2SettingFields fields; @@ -100,26 +88,27 @@ // Confirm we get an error if the SETTINGS payload is not the correct size // to hold exactly zero or more whole Http2SettingFields. TEST_F(SettingsPayloadDecoderTest, SettingsWrongSize) { + auto approve_size = [](size_t size) { + // Should get an error if size is not an integral multiple of the size + // of one setting. + return 0 != (size % Http2SettingFields::EncodedSize()); + }; Http2FrameBuilder fb; fb.Append(RandSettingsFields()); fb.Append(RandSettingsFields()); fb.Append(RandSettingsFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError( - 0, fb.buffer(), - base::Bind( - &SettingsPayloadDecoderTest::ApproveSizeForSettingsWrongSize))); + EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); } // Confirm we get an error if the SETTINGS ACK payload is not empty. TEST_F(SettingsPayloadDecoderTest, SettingsAkcWrongSize) { + auto approve_size = [](size_t size) { return size != 0; }; Http2FrameBuilder fb; fb.Append(RandSettingsFields()); fb.Append(RandSettingsFields()); fb.Append(RandSettingsFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError( - Http2FrameFlag::FLAG_ACK, fb.buffer(), - base::Bind( - &SettingsPayloadDecoderTest::ApproveSizeForSettingsAkcWrongSize))); + EXPECT_TRUE(VerifyDetectsFrameSizeError(Http2FrameFlag::FLAG_ACK, fb.buffer(), + approve_size)); } // SETTINGS must have stream_id==0, but the payload decoder doesn't check that.
diff --git a/net/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc index 5517dab..5914b8166 100644 --- a/net/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc +++ b/net/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc
@@ -6,7 +6,6 @@ #include <stddef.h> -#include "base/bind.h" #include "base/logging.h" #include "net/http2/decoder/frame_parts.h" #include "net/http2/decoder/frame_parts_collector.h" @@ -60,10 +59,6 @@ : public AbstractPayloadDecoderTest<WindowUpdatePayloadDecoder, WindowUpdatePayloadDecoderPeer, Listener> { - public: - static bool ApproveSizeForWrongSize(size_t size) { - return size != Http2WindowUpdateFields::EncodedSize(); - } protected: Http2WindowUpdateFields RandWindowUpdateFields() { @@ -77,13 +72,14 @@ // Confirm we get an error if the payload is not the correct size to hold // exactly one Http2WindowUpdateFields. TEST_F(WindowUpdatePayloadDecoderTest, WrongSize) { + auto approve_size = [](size_t size) { + return size != Http2WindowUpdateFields::EncodedSize(); + }; Http2FrameBuilder fb; fb.Append(RandWindowUpdateFields()); fb.Append(RandWindowUpdateFields()); fb.Append(RandWindowUpdateFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError( - 0, fb.buffer(), - base::Bind(&WindowUpdatePayloadDecoderTest::ApproveSizeForWrongSize))); + EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); } TEST_F(WindowUpdatePayloadDecoderTest, VariousPayloads) {
diff --git a/net/http2/hpack/decoder/hpack_block_decoder_test.cc b/net/http2/hpack/decoder/hpack_block_decoder_test.cc index 421f0fc5..566963d 100644 --- a/net/http2/hpack/decoder/hpack_block_decoder_test.cc +++ b/net/http2/hpack/decoder/hpack_block_decoder_test.cc
@@ -8,8 +8,6 @@ #include <sstream> -#include "base/bind.h" -#include "base/bind_helpers.h" #include "net/http2/decoder/decode_buffer.h" #include "net/http2/hpack/decoder/hpack_block_collector.h" #include "net/http2/hpack/http2_hpack_constants.h" @@ -29,31 +27,6 @@ namespace { class HpackBlockDecoderTest : public RandomDecoderTest { - public: - AssertionResult VerifyExpected(const HpackBlockCollector& expected) { - VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected)); - } - - AssertionResult ValidateForSpecExample_C_2_1() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader( - HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false, - "custom-header")); - } - - AssertionResult ValidateForSpecExample_C_2_2() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralValueHeader( - HpackEntryType::kUnindexedLiteralHeader, 4, false, "/sample/path")); - } - - AssertionResult ValidateForSpecExample_C_2_3() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader( - HpackEntryType::kNeverIndexedLiteralHeader, false, "password", false, - "secret")); - } - - AssertionResult ValidateForSpecExample_C_2_4() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleIndexedHeader(2)); - } protected: HpackBlockDecoderTest() : listener_(&collector_), decoder_(&listener_) { @@ -112,9 +85,11 @@ // http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.1 TEST_F(HpackBlockDecoderTest, SpecExample_C_2_1) { - NoArgValidator do_check = - base::Bind(&HpackBlockDecoderTest::ValidateForSpecExample_C_2_1, - base::Unretained(this)); + NoArgValidator do_check = [this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader( + HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false, + "custom-header")); + }; EXPECT_TRUE( DecodeHpackExampleAndValidateSeveralWays(R"( 40 | == Literal indexed == @@ -126,14 +101,15 @@ | custom-header )", ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } // http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.2 TEST_F(HpackBlockDecoderTest, SpecExample_C_2_2) { - NoArgValidator do_check = - base::Bind(&HpackBlockDecoderTest::ValidateForSpecExample_C_2_2, - base::Unretained(this)); + NoArgValidator do_check = [this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralValueHeader( + HpackEntryType::kUnindexedLiteralHeader, 4, false, "/sample/path")); + }; EXPECT_TRUE( DecodeHpackExampleAndValidateSeveralWays(R"( 04 | == Literal not indexed == @@ -144,14 +120,16 @@ | -> :path: /sample/path )", ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } // http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.3 TEST_F(HpackBlockDecoderTest, SpecExample_C_2_3) { - NoArgValidator do_check = - base::Bind(&HpackBlockDecoderTest::ValidateForSpecExample_C_2_3, - base::Unretained(this)); + NoArgValidator do_check = [this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader( + HpackEntryType::kNeverIndexedLiteralHeader, false, "password", false, + "secret")); + }; EXPECT_TRUE( DecodeHpackExampleAndValidateSeveralWays(R"( 10 | == Literal never indexed == @@ -162,14 +140,14 @@ | -> password: secret )", ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } // http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.4 TEST_F(HpackBlockDecoderTest, SpecExample_C_2_4) { - NoArgValidator do_check = - base::Bind(&HpackBlockDecoderTest::ValidateForSpecExample_C_2_4, - base::Unretained(this)); + NoArgValidator do_check = [this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleIndexedHeader(2)); + }; EXPECT_TRUE( DecodeHpackExampleAndValidateSeveralWays(R"( 82 | == Indexed - Add == @@ -177,7 +155,7 @@ | -> :method: GET )", ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } // http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1 TEST_F(HpackBlockDecoderTest, SpecExample_C_3_1) { @@ -205,11 +183,12 @@ expected.ExpectIndexedHeader(4); expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 1, false, "www.example.com"); - NoArgValidator do_check = base::Bind(&HpackBlockDecoderTest::VerifyExpected, - base::Unretained(this), expected); + NoArgValidator do_check = [expected, this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected)); + }; EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } // http://httpwg.org/specs/rfc7541.html#rfc.section.C.5.1 @@ -254,11 +233,12 @@ "Mon, 21 Oct 2013 20:13:21 GMT"); expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 46, false, "https://www.example.com"); - NoArgValidator do_check = base::Bind(&HpackBlockDecoderTest::VerifyExpected, - base::Unretained(this), expected); + NoArgValidator do_check = [expected, this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected)); + }; EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } // Generate a bunch of HPACK block entries to expect, use those expectations @@ -303,11 +283,12 @@ HpackBlockBuilder hbb; expected.AppendToHpackBlockBuilder(&hbb); - NoArgValidator do_check = base::Bind(&HpackBlockDecoderTest::VerifyExpected, - base::Unretained(this), expected); + NoArgValidator do_check = [expected, this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected)); + }; EXPECT_TRUE( DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } } // namespace
diff --git a/net/http2/hpack/decoder/hpack_entry_decoder_test.cc b/net/http2/hpack/decoder/hpack_entry_decoder_test.cc index 34581fa..6a1c293f 100644 --- a/net/http2/hpack/decoder/hpack_entry_decoder_test.cc +++ b/net/http2/hpack/decoder/hpack_entry_decoder_test.cc
@@ -6,8 +6,6 @@ // Tests of HpackEntryDecoder. -#include "base/bind.h" -#include "base/bind_helpers.h" #include "net/http2/hpack/decoder/hpack_entry_collector.h" #include "net/http2/hpack/tools/hpack_block_builder.h" #include "net/http2/tools/failure.h" @@ -23,25 +21,6 @@ namespace { class HpackEntryDecoderTest : public RandomDecoderTest { - public: - AssertionResult ValidateIndexedHeader(uint32_t ndx) { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(ndx)); - } - - AssertionResult ValidateForIndexedLiteralValue_Literal() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader( - HpackEntryType::kIndexedLiteralHeader, 0x40, false, "custom-header")); - } - - AssertionResult ValidateForIndexedLiteralNameValue_Literal() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader( - HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false, - "custom-header")); - } - - AssertionResult ValidateForDynamicTableSizeUpdate_Literal() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateDynamicTableSizeUpdate(31)); - } protected: HpackEntryDecoderTest() : listener_(&collector_) {} @@ -79,34 +58,34 @@ { const char input[] = {0x82u}; // == Index 2 == DecodeBuffer b(input); - NoArgValidator do_check = - base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader, - base::Unretained(this), 2); + NoArgValidator do_check = [this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(2)); + }; EXPECT_TRUE( DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } collector_.Clear(); { const char input[] = {0xfeu}; // == Index 126 == DecodeBuffer b(input); - NoArgValidator do_check = - base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader, - base::Unretained(this), 126); + NoArgValidator do_check = [this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(126)); + }; EXPECT_TRUE( DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } collector_.Clear(); { const char input[] = {0xffu, 0x00}; // == Index 127 == DecodeBuffer b(input); - NoArgValidator do_check = - base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader, - base::Unretained(this), 127); + NoArgValidator do_check = [this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(127)); + }; EXPECT_TRUE( DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } } @@ -116,12 +95,12 @@ HpackBlockBuilder hbb; hbb.AppendIndexedHeader(ndx); - NoArgValidator do_check = - base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader, - base::Unretained(this), ndx); + NoArgValidator do_check = [this, ndx]() { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(ndx)); + }; EXPECT_TRUE( DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } } @@ -132,11 +111,12 @@ "\x0d" // Value length (13) "custom-header"; // Value DecodeBuffer b(input, sizeof input - 1); - NoArgValidator do_check = - base::Bind(&HpackEntryDecoderTest::ValidateForIndexedLiteralValue_Literal, - base::Unretained(this)); + NoArgValidator do_check = [this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader( + HpackEntryType::kIndexedLiteralHeader, 0x40, false, "custom-header")); + }; EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } TEST_F(HpackEntryDecoderTest, IndexedLiteralNameValue_Literal) { @@ -148,45 +128,29 @@ "custom-header"; // Value DecodeBuffer b(input, sizeof input - 1); - NoArgValidator do_check = base::Bind( - &HpackEntryDecoderTest::ValidateForIndexedLiteralNameValue_Literal, - base::Unretained(this)); + NoArgValidator do_check = [this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader( + HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false, + "custom-header")); + }; EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } TEST_F(HpackEntryDecoderTest, DynamicTableSizeUpdate_Literal) { // Size update, length 31. const char input[] = "\x3f\x00"; DecodeBuffer b(input, 2); - NoArgValidator do_check = base::Bind( - &HpackEntryDecoderTest::ValidateForDynamicTableSizeUpdate_Literal, - base::Unretained(this)); + NoArgValidator do_check = [this]() { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateDynamicTableSizeUpdate(31)); + }; EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } class HpackLiteralEntryDecoderTest : public HpackEntryDecoderTest, public ::testing::WithParamInterface<HpackEntryType> { - public: - AssertionResult ValidateForRandNameIndexAndLiteralValue( - uint32_t ndx, - bool value_is_huffman_encoded, - const string& value) { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader( - entry_type_, ndx, value_is_huffman_encoded, value)); - } - - AssertionResult ValidateForRandLiteralNameAndValue( - bool name_is_huffman_encoded, - const string& name, - bool value_is_huffman_encoded, - const string& value) { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader( - entry_type_, name_is_huffman_encoded, name, value_is_huffman_encoded, - value)); - } protected: HpackLiteralEntryDecoderTest() : entry_type_(GetParam()) {} @@ -209,12 +173,14 @@ HpackBlockBuilder hbb; hbb.AppendNameIndexAndLiteralValue(entry_type_, ndx, value_is_huffman_encoded, value); - NoArgValidator do_check = base::Bind( - &HpackLiteralEntryDecoderTest::ValidateForRandNameIndexAndLiteralValue, - base::Unretained(this), ndx, value_is_huffman_encoded, value); + NoArgValidator do_check = [this, ndx, value_is_huffman_encoded, + value]() -> AssertionResult { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader( + entry_type_, ndx, value_is_huffman_encoded, value)); + }; EXPECT_TRUE( DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } } @@ -229,13 +195,16 @@ HpackBlockBuilder hbb; hbb.AppendLiteralNameAndValue(entry_type_, name_is_huffman_encoded, name, value_is_huffman_encoded, value); - NoArgValidator do_check = base::Bind( - &HpackLiteralEntryDecoderTest::ValidateForRandLiteralNameAndValue, - base::Unretained(this), name_is_huffman_encoded, name, - value_is_huffman_encoded, value); + NoArgValidator do_check = [this, name_is_huffman_encoded, name, + value_is_huffman_encoded, + value]() -> AssertionResult { + VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader( + entry_type_, name_is_huffman_encoded, name, value_is_huffman_encoded, + value)); + }; EXPECT_TRUE( DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check.Run()); + EXPECT_TRUE(do_check()); } }
diff --git a/net/http2/hpack/decoder/hpack_entry_type_decoder_test.cc b/net/http2/hpack/decoder/hpack_entry_type_decoder_test.cc index 0abf0c9..9f72eb6 100644 --- a/net/http2/hpack/decoder/hpack_entry_type_decoder_test.cc +++ b/net/http2/hpack/decoder/hpack_entry_type_decoder_test.cc
@@ -6,8 +6,6 @@ #include <vector> -#include "base/bind.h" -#include "base/bind_helpers.h" #include "base/logging.h" #include "net/http2/hpack/tools/hpack_block_builder.h" #include "net/http2/tools/failure.h" @@ -24,19 +22,6 @@ const bool kReturnNonZeroOnFirst = true; class HpackEntryTypeDecoderTest : public RandomDecoderTest { - public: - AssertionResult ValidatorForDynamicTableSizeUpdate(uint32_t size) { - VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, decoder_.entry_type()); - VERIFY_EQ(size, decoder_.varint()); - return AssertionSuccess(); - } - - AssertionResult ValidatorForHeaderWithIndex(const HpackEntryType entry_type, - uint32_t index) { - VERIFY_EQ(entry_type, decoder_.entry_type()); - VERIFY_EQ(index, decoder_.varint()); - return AssertionSuccess(); - } protected: DecodeStatus StartDecoding(DecodeBuffer* b) override { @@ -56,15 +41,17 @@ HpackBlockBuilder bb; bb.AppendDynamicTableSizeUpdate(size); DecodeBuffer db(bb.buffer()); - NoArgValidator validator = base::Bind( - &HpackEntryTypeDecoderTest::ValidatorForDynamicTableSizeUpdate, - base::Unretained(this), size); + NoArgValidator validator = [size, this]() -> AssertionResult { + VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, decoder_.entry_type()); + VERIFY_EQ(size, decoder_.varint()); + return AssertionSuccess(); + }; EXPECT_TRUE(DecodeAndValidateSeveralWays(&db, kReturnNonZeroOnFirst, ValidateDoneAndEmpty(validator))) << "\nentry_type=kDynamicTableSizeUpdate, size=" << size; // Run the validator again to make sure that DecodeAndValidateSeveralWays // did the right thing. - EXPECT_TRUE(validator.Run()); + EXPECT_TRUE(validator()); } } @@ -80,15 +67,18 @@ HpackBlockBuilder bb; bb.AppendEntryTypeAndVarint(entry_type, index); DecodeBuffer db(bb.buffer()); - NoArgValidator validator = - base::Bind(&HpackEntryTypeDecoderTest::ValidatorForHeaderWithIndex, - base::Unretained(this), entry_type, index); + NoArgValidator validator = [entry_type, index, + this]() -> AssertionResult { + VERIFY_EQ(entry_type, decoder_.entry_type()); + VERIFY_EQ(index, decoder_.varint()); + return AssertionSuccess(); + }; EXPECT_TRUE(DecodeAndValidateSeveralWays(&db, kReturnNonZeroOnFirst, ValidateDoneAndEmpty(validator))) << "\nentry_type=" << entry_type << ", index=" << index; // Run the validator again to make sure that DecodeAndValidateSeveralWays // did the right thing. - EXPECT_TRUE(validator.Run()); + EXPECT_TRUE(validator()); } } }
diff --git a/net/http2/hpack/decoder/hpack_string_decoder_test.cc b/net/http2/hpack/decoder/hpack_string_decoder_test.cc index e4afc61..614fa0d 100644 --- a/net/http2/hpack/decoder/hpack_string_decoder_test.cc +++ b/net/http2/hpack/decoder/hpack_string_decoder_test.cc
@@ -6,8 +6,6 @@ // Tests of HpackStringDecoder. -#include "base/bind.h" -#include "base/bind_helpers.h" #include "base/strings/string_piece.h" #include "net/http2/hpack/decoder/hpack_string_collector.h" #include "net/http2/hpack/decoder/hpack_string_decoder_listener.h" @@ -74,32 +72,27 @@ return collector_.Collected(s, huffman_encoded); } - // Note that base::Bind() makes a copy of |expected_str| even though it is - // taken as a constant reference, so even if MakeValidator is called with a - // C-style string that is cast to a temporary std::string that gets destroyed - // after the call to MakeValidator, |expected_str| is still valid later when - // the Validator is run. - AssertionResult StringValidator(const string& expected_str, - bool expected_huffman, - const DecodeBuffer& input, - DecodeStatus status) { - AssertionResult result = Collected(expected_str, expected_huffman); - if (result) { - VERIFY_EQ(collector_, - HpackStringCollector(expected_str, expected_huffman)); - } else { - VERIFY_NE(collector_, - HpackStringCollector(expected_str, expected_huffman)); - } - VLOG(2) << collector_.ToString(); - collector_.Clear(); - VLOG(2) << collector_; - return result; - } + // expected_str is a string rather than a const string& or StringPiece so that + // the lambda makes a copy of the string, and thus the string to be passed to + // Collected outlives the call to MakeValidator. Validator MakeValidator(const string& expected_str, bool expected_huffman) { - return base::Bind(&HpackStringDecoderTest::StringValidator, - base::Unretained(this), expected_str, expected_huffman); + return + [expected_str, expected_huffman, this]( + const DecodeBuffer& input, DecodeStatus status) -> AssertionResult { + AssertionResult result = Collected(expected_str, expected_huffman); + if (result) { + VERIFY_EQ(collector_, + HpackStringCollector(expected_str, expected_huffman)); + } else { + VERIFY_NE(collector_, + HpackStringCollector(expected_str, expected_huffman)); + } + VLOG(2) << collector_.ToString(); + collector_.Clear(); + VLOG(2) << collector_; + return result; + }; } const StartMethod start_method_;
diff --git a/net/http2/hpack/decoder/hpack_varint_decoder_test.cc b/net/http2/hpack/decoder/hpack_varint_decoder_test.cc index e63e9f0..7cdc872 100644 --- a/net/http2/hpack/decoder/hpack_varint_decoder_test.cc +++ b/net/http2/hpack/decoder/hpack_varint_decoder_test.cc
@@ -15,8 +15,6 @@ #include <sstream> #include <vector> -#include "base/bind.h" -#include "base/bind_helpers.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" @@ -38,16 +36,6 @@ namespace { class HpackVarintDecoderTest : public RandomDecoderTest { - public: - AssertionResult ValidatorForValueTooLarge(bool* validated, - uint32_t expected_offset, - const DecodeBuffer& db, - DecodeStatus status) { - *validated = true; - VERIFY_EQ(DecodeStatus::kDecodeError, status); - VERIFY_EQ(expected_offset, db.Offset()); - return AssertionSuccess(); - } protected: DecodeStatus StartDecoding(DecodeBuffer* b) override { @@ -61,24 +49,19 @@ return decoder_.Resume(b); } - AssertionResult ValidatorForDecodeSeveralWays(uint32_t expected_value, - const DecodeBuffer& db, - DecodeStatus status) { - if (decoder_.value() != expected_value) { - return AssertionFailure() - << "Value doesn't match expected: " << decoder_.value() - << " != " << expected_value; - } - return AssertionSuccess(); - } - void DecodeSeveralWays(uint32_t expected_value, uint32_t expected_offset) { // The validator is called after each of the several times that the input // DecodeBuffer is decoded, each with a different segmentation of the input. // Validate that decoder_.value() matches the expected value. - Validator validator = - base::Bind(&HpackVarintDecoderTest::ValidatorForDecodeSeveralWays, - base::Unretained(this), expected_value); + Validator validator = [expected_value, this]( + const DecodeBuffer& db, DecodeStatus status) -> AssertionResult { + if (decoder_.value() != expected_value) { + return AssertionFailure() + << "Value doesn't match expected: " << decoder_.value() + << " != " << expected_value; + } + return AssertionSuccess(); + }; // First validate that decoding is done and that we've advanced the cursor // the expected amount. @@ -375,9 +358,13 @@ // DecodeBuffer is decoded, each with a different segmentation of the input. // Validate that decoder_.value() matches the expected value. bool validated = false; - Validator validator = - base::Bind(&HpackVarintDecoderTest::ValidatorForValueTooLarge, - base::Unretained(this), &validated, expected_offset); + Validator validator = [&validated, expected_offset]( + const DecodeBuffer& db, DecodeStatus status) -> AssertionResult { + validated = true; + VERIFY_EQ(DecodeStatus::kDecodeError, status); + VERIFY_EQ(expected_offset, db.Offset()); + return AssertionSuccess(); + }; // StartDecoding, above, requires the DecodeBuffer be non-empty so that it // can call Start with the prefix byte.
diff --git a/net/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc b/net/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc index e062046..0b5564f 100644 --- a/net/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc +++ b/net/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc
@@ -7,6 +7,8 @@ // Tests of HpackWholeEntryBuffer: does it buffer correctly, and does it // detect Huffman decoding errors and oversize string errors? +#include "net/test/gtest_util.h" +#include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -15,7 +17,6 @@ using ::testing::HasSubstr; using ::testing::InSequence; using ::testing::Property; -using ::testing::SaveArg; using ::testing::StrictMock; using ::testing::_; @@ -25,6 +26,15 @@ constexpr size_t kMaxStringSize = 20; +// Define HasSubstr() for base::StringPiece arguments. +// This shadows ::testing::HasSubstr(), which only works on argument types +// that can be implicilty converted to a std::string. +inline ::testing::PolymorphicMatcher<StringPieceHasSubstrMatcher> HasSubstr( + const std::string& substring) { + return ::testing::MakePolymorphicMatcher( + StringPieceHasSubstrMatcher(substring)); +} + class MockHpackWholeEntryListener : public HpackWholeEntryListener { public: ~MockHpackWholeEntryListener() override {} @@ -157,21 +167,15 @@ // Verify that a name longer than the allowed size generates an error. TEST_F(HpackWholeEntryBufferTest, NameTooLong) { entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 0); - StringPiece error_message; - EXPECT_CALL(listener_, OnHpackDecodeError(_)) - .WillOnce(SaveArg<0>(&error_message)); + EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry name"))); entry_buffer_.OnNameStart(false, kMaxStringSize + 1); - EXPECT_THAT(error_message.as_string(), HasSubstr("HPACK entry name")); } // Verify that a name longer than the allowed size generates an error. TEST_F(HpackWholeEntryBufferTest, ValueTooLong) { entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 1); - StringPiece error_message; - EXPECT_CALL(listener_, OnHpackDecodeError(_)) - .WillOnce(SaveArg<0>(&error_message)); + EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry value"))); entry_buffer_.OnValueStart(false, kMaxStringSize + 1); - EXPECT_THAT(error_message.as_string(), HasSubstr("HPACK entry value")); } // Verify that a Huffman encoded name with an explicit EOS generates an error @@ -183,12 +187,9 @@ entry_buffer_.OnNameStart(true, 4); entry_buffer_.OnNameData(data, 3); - StringPiece error_message; - EXPECT_CALL(listener_, OnHpackDecodeError(_)) - .WillOnce(SaveArg<0>(&error_message)); + EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry name"))); entry_buffer_.OnNameData(data, 1); - EXPECT_THAT(error_message.as_string(), HasSubstr("HPACK entry name")); // After an error is reported, the listener is not called again. EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(8096)).Times(0); @@ -204,12 +205,9 @@ entry_buffer_.OnValueStart(true, 3); entry_buffer_.OnValueData(data, 3); - StringPiece error_message; - EXPECT_CALL(listener_, OnHpackDecodeError(_)) - .WillOnce(SaveArg<0>(&error_message)); + EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry value"))); entry_buffer_.OnValueEnd(); - EXPECT_THAT(error_message.as_string(), HasSubstr("HPACK entry value")); // After an error is reported, the listener is not called again. EXPECT_CALL(listener_, OnIndexedHeader(17)).Times(0);
diff --git a/net/http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc b/net/http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc index 3ad47351..3eb52adc 100644 --- a/net/http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc +++ b/net/http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc
@@ -9,8 +9,6 @@ #include <iostream> #include <string> -#include "base/bind.h" -#include "base/bind_helpers.h" #include "base/macros.h" #include "base/strings/string_piece.h" #include "net/http2/decoder/decode_buffer.h" @@ -202,25 +200,19 @@ return false; } - AssertionResult ValidatorForHuffmanDecodeAndValidateSeveralWays( - StringPiece expected_plain) { - VERIFY_EQ(output_buffer_.size(), expected_plain.size()); - VERIFY_EQ(output_buffer_, expected_plain); - return AssertionSuccess(); - } - AssertionResult HuffmanDecodeAndValidateSeveralWays( StringPiece encoded, StringPiece expected_plain) { input_bytes_expected_ = encoded.size(); + NoArgValidator validator = [expected_plain, this]() -> AssertionResult { + VERIFY_EQ(output_buffer_.size(), expected_plain.size()); + VERIFY_EQ(output_buffer_, expected_plain); + return AssertionSuccess(); + }; DecodeBuffer db(encoded); bool return_non_zero_on_first = false; - return DecodeAndValidateSeveralWays( - &db, return_non_zero_on_first, - ValidateDoneAndEmpty( - base::Bind(&HpackHuffmanDecoderTest:: - ValidatorForHuffmanDecodeAndValidateSeveralWays, - base::Unretained(this), expected_plain))); + return DecodeAndValidateSeveralWays(&db, return_non_zero_on_first, + ValidateDoneAndEmpty(validator)); } HpackHuffmanDecoder decoder_;
diff --git a/net/http2/tools/random_decoder_test.cc b/net/http2/tools/random_decoder_test.cc index 9a646e3..224a825 100644 --- a/net/http2/tools/random_decoder_test.cc +++ b/net/http2/tools/random_decoder_test.cc
@@ -127,8 +127,7 @@ DecodeBuffer input(original->cursor(), original_remaining); VLOG(2) << "DecodeSegmentsAndValidate with SelectRandom"; VERIFY_SUCCESS(DecodeSegmentsAndValidate( - &input, RandomDecoderTest::SelectRandom(return_non_zero_on_first), - validator)) + &input, SelectRandom(return_non_zero_on_first), validator)) << "\nFailed with SelectRandom; input.Offset=" << input.Offset() << "; input.Remaining=" << input.Remaining(); VERIFY_EQ(first_consumed, input.Offset()) << "\nFailed with SelectRandom";
diff --git a/net/http2/tools/random_decoder_test.h b/net/http2/tools/random_decoder_test.h index 7402173..5cb10f6 100644 --- a/net/http2/tools/random_decoder_test.h +++ b/net/http2/tools/random_decoder_test.h
@@ -12,12 +12,11 @@ #include <stddef.h> +#include <functional> #include <memory> #include <string> #include <type_traits> -#include "base/bind.h" -#include "base/callback.h" #include "base/logging.h" #include "base/strings/string_piece.h" #include "base/template_util.h" @@ -71,10 +70,10 @@ // Validator returns an AssertionResult so test can do: // EXPECT_THAT(DecodeAndValidate(..., validator)); typedef ::testing::AssertionResult AssertionResult; - typedef base::Callback<AssertionResult(const DecodeBuffer& input, - DecodeStatus status)> + typedef std::function<AssertionResult(const DecodeBuffer& input, + DecodeStatus status)> Validator; - typedef base::Callback<AssertionResult()> NoArgValidator; + typedef std::function<AssertionResult()> NoArgValidator; RandomDecoderTest(); @@ -120,7 +119,7 @@ const SelectSize& select_size, const Validator& validator) { DecodeStatus status = DecodeSegments(original, select_size); - VERIFY_AND_RETURN_SUCCESS(validator.Run(*original, status)); + VERIFY_AND_RETURN_SUCCESS(validator(*original, status)); } // Returns a SelectSize function for fast decoding, i.e. passing all that @@ -152,21 +151,26 @@ bool return_non_zero_on_first, const Validator& validator); - static AssertionResult SucceedingValidator(const DecodeBuffer& input, - DecodeStatus status) { - return ::testing::AssertionSuccess(); + static Validator ToValidator(std::nullptr_t) { + return [](const DecodeBuffer& input, DecodeStatus status) { + return ::testing::AssertionSuccess(); + }; } - static Validator ToValidator(const Validator& validator) { return validator; } - - static AssertionResult RunNoArgValidator(const NoArgValidator& validator, - const DecodeBuffer& input, - DecodeStatus status) { - return validator.Run(); + static Validator ToValidator(const Validator& validator) { + if (validator == nullptr) { + return ToValidator(nullptr); + } + return validator; } static Validator ToValidator(const NoArgValidator& validator) { - return base::Bind(&RunNoArgValidator, validator); + if (validator == nullptr) { + return ToValidator(nullptr); + } + return [validator](const DecodeBuffer& input, DecodeStatus status) { + return validator(); + }; } // Wraps a validator with another validator @@ -175,29 +179,31 @@ // TODO(jamessynge): Replace this overload with the next, as using this method // usually means that the wrapped function doesn't need to be passed the // DecodeBuffer nor the DecodeStatus. - static AssertionResult ValidateDoneAndEmptyImpl(const Validator& wrapped, - const DecodeBuffer& input, - DecodeStatus status) { - VERIFY_EQ(status, DecodeStatus::kDecodeDone); - VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset(); - return wrapped.Run(input, status); - } static Validator ValidateDoneAndEmpty(const Validator& wrapped) { - return base::Bind(&ValidateDoneAndEmptyImpl, wrapped); + return [wrapped](const DecodeBuffer& input, + DecodeStatus status) -> AssertionResult { + VERIFY_EQ(status, DecodeStatus::kDecodeDone); + VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset(); + if (wrapped) { + return wrapped(input, status); + } + return ::testing::AssertionSuccess(); + }; } - static AssertionResult ValidateDoneAndEmptyNoArgImpl( - const NoArgValidator& wrapped, - const DecodeBuffer& input, - DecodeStatus status) { - VERIFY_EQ(status, DecodeStatus::kDecodeDone); - VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset(); - return wrapped.Run(); - } - static Validator ValidateDoneAndEmpty(const NoArgValidator& wrapped) { - return base::Bind(&ValidateDoneAndEmptyNoArgImpl, wrapped); + static Validator ValidateDoneAndEmpty(NoArgValidator wrapped) { + return [wrapped](const DecodeBuffer& input, + DecodeStatus status) -> AssertionResult { + VERIFY_EQ(status, DecodeStatus::kDecodeDone); + VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset(); + if (wrapped) { + return wrapped(); + } + return ::testing::AssertionSuccess(); + }; } static Validator ValidateDoneAndEmpty() { - return ValidateDoneAndEmpty(base::Bind(&SucceedingValidator)); + NoArgValidator validator; + return ValidateDoneAndEmpty(validator); } // Wraps a validator with another validator @@ -206,39 +212,32 @@ // TODO(jamessynge): Replace this overload with the next, as using this method // usually means that the wrapped function doesn't need to be passed the // DecodeBuffer nor the DecodeStatus. - static AssertionResult ValidateDoneAndOffsetImpl(uint32_t offset, - const Validator& wrapped, - const DecodeBuffer& input, - DecodeStatus status) { - VERIFY_EQ(status, DecodeStatus::kDecodeDone); - VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining(); - return wrapped.Run(input, status); + static Validator ValidateDoneAndOffset(uint32_t offset, Validator wrapped) { + return [wrapped, offset](const DecodeBuffer& input, + DecodeStatus status) -> AssertionResult { + VERIFY_EQ(status, DecodeStatus::kDecodeDone); + VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining(); + if (wrapped) { + return wrapped(input, status); + } + return ::testing::AssertionSuccess(); + }; } static Validator ValidateDoneAndOffset(uint32_t offset, - const Validator& wrapped) { - // Make a copy of |wrapped| (by not using base::ConstRef) to avoid lifetime - // issues if this method is called with a temporary Validator. - return base::Bind(&ValidateDoneAndOffsetImpl, offset, wrapped); - } - static AssertionResult ValidateDoneAndOffsetNoArgImpl( - uint32_t offset, - const NoArgValidator& wrapped, - const DecodeBuffer& input, - DecodeStatus status) { - VERIFY_EQ(status, DecodeStatus::kDecodeDone); - VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining(); - return wrapped.Run(); - } - static Validator ValidateDoneAndOffset(uint32_t offset, - const NoArgValidator& wrapped) { - // Make a copy of |wrapped| (by not using base::ConstRef) to avoid lifetime - // issues if this method is called with a temporary Validator. - return base::Bind(&ValidateDoneAndOffsetNoArgImpl, offset, wrapped); + NoArgValidator wrapped) { + return [wrapped, offset](const DecodeBuffer& input, + DecodeStatus status) -> AssertionResult { + VERIFY_EQ(status, DecodeStatus::kDecodeDone); + VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining(); + if (wrapped) { + return wrapped(); + } + return ::testing::AssertionSuccess(); + }; } static Validator ValidateDoneAndOffset(uint32_t offset) { - // Make a copy of |wrapped| (by not using base::ConstRef) to avoid lifetime - // issues if this method is called with a temporary Validator. - return ValidateDoneAndOffset(offset, base::Bind(&SucceedingValidator)); + NoArgValidator validator; + return ValidateDoneAndOffset(offset, validator); } // Expose |random_| as RandomBase so callers do not have to care about which
diff --git a/net/spdy/spdy_flags.cc b/net/spdy/spdy_flags.cc index c3a7f8e..fa380d4 100644 --- a/net/spdy/spdy_flags.cc +++ b/net/spdy/spdy_flags.cc
@@ -9,6 +9,9 @@ // Log compressed size of HTTP/2 requests. bool FLAGS_chromium_http2_flag_log_compressed_size = true; +// If true, remove use of SpdyFrameBuilder::OverwriteLength(). +bool FLAGS_chromium_http2_flag_remove_rewritelength = true; + // Use //net/http2/hpack/decoder as HPACK decoder. bool FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
diff --git a/net/spdy/spdy_flags.h b/net/spdy/spdy_flags.h index 9c90639..d44cb9de 100644 --- a/net/spdy/spdy_flags.h +++ b/net/spdy/spdy_flags.h
@@ -10,6 +10,7 @@ namespace net { NET_EXPORT_PRIVATE extern bool FLAGS_chromium_http2_flag_log_compressed_size; +NET_EXPORT_PRIVATE extern bool FLAGS_chromium_http2_flag_remove_rewritelength; NET_EXPORT_PRIVATE extern bool FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2; NET_EXPORT_PRIVATE extern bool
diff --git a/net/spdy/spdy_frame_builder.cc b/net/spdy/spdy_frame_builder.cc index 5f14f78..39f0c296 100644 --- a/net/spdy/spdy_frame_builder.cc +++ b/net/spdy/spdy_frame_builder.cc
@@ -65,6 +65,29 @@ return success; } +bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer, + SpdyFrameType type, + uint8_t flags, + SpdyStreamId stream_id, + size_t length) { + DCHECK(IsValidFrameType(SerializeFrameType(type))); + DCHECK_EQ(0u, stream_id & ~kStreamIdMask); + bool success = true; + SPDY_BUG_IF(framer.GetFrameMaximumSize() < length_) + << "Frame length " << length_ + << " is longer than the maximum allowed length."; + + offset_ += length_; + length_ = 0; + + success &= WriteUInt24(length); + success &= WriteUInt8(SerializeFrameType(type)); + success &= WriteUInt8(flags); + success &= WriteUInt32(stream_id); + DCHECK_EQ(framer.GetDataFrameMinimumSize(), length_); + return success; +} + bool SpdyFrameBuilder::WriteStringPiece16(const base::StringPiece& value) { if (value.size() > 0xffff) { DCHECK(false) << "Tried to write string with length > 16bit.";
diff --git a/net/spdy/spdy_frame_builder.h b/net/spdy/spdy_frame_builder.h index 743e0f3..b48ef20 100644 --- a/net/spdy/spdy_frame_builder.h +++ b/net/spdy/spdy_frame_builder.h
@@ -58,6 +58,14 @@ uint8_t flags, SpdyStreamId stream_id); + // Populates this frame with a HTTP2 frame prefix with length information. + // The given type must be a control frame type. + bool BeginNewFrame(const SpdyFramer& framer, + SpdyFrameType type, + uint8_t flags, + SpdyStreamId stream_id, + size_t length); + // Takes the buffer from the SpdyFrameBuilder. SpdySerializedFrame take() { SPDY_BUG_IF(kMaxFrameSizeLimit < length_)
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc index b5cd187..38861b3f 100644 --- a/net/spdy/spdy_framer.cc +++ b/net/spdy/spdy_framer.cc
@@ -159,6 +159,7 @@ if (adapter_factory != nullptr) { decoder_adapter_ = adapter_factory(this); } + skip_rewritelength_ = FLAGS_chromium_http2_flag_remove_rewritelength; } SpdyFramer::SpdyFramer(CompressionOption option) @@ -1860,12 +1861,21 @@ } SpdyFrameBuilder builder(frame_size); - builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id()); - if (data_ir.padded()) { - builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); + if (!skip_rewritelength_) { + builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id()); + if (data_ir.padded()) { + builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); + } + builder.OverwriteLength(*this, num_padding_fields + data_ir.data_len() + + data_ir.padding_payload_len()); + } else { + builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id(), + num_padding_fields + data_ir.data_len() + + data_ir.padding_payload_len()); + if (data_ir.padded()) { + builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); + } } - builder.OverwriteLength(*this, num_padding_fields + data_ir.data_len() + - data_ir.padding_payload_len()); DCHECK_EQ(frame_size, builder.length()); return builder.take(); } @@ -1993,7 +2003,29 @@ } SpdyFrameBuilder builder(size); - builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id()); + + if (!skip_rewritelength_) { + builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id()); + } else { + // Compute frame length field. + size_t length_field = 0; + if (headers.padded()) { + length_field += 1; // Padding length field. + } + if (headers.has_priority()) { + length_field += 4; // Dependency field. + length_field += 1; // Weight field. + } + length_field += headers.padding_payload_len(); + length_field += hpack_encoding.size(); + // If the HEADERS frame with payload would exceed the max frame size, then + // WritePayloadWithContinuation() will serialize CONTINUATION frames as + // necessary. + length_field = + std::min(length_field, kMaxControlFrameSize - GetFrameHeaderSize()); + builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id(), + length_field); + } DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); int padding_payload_len = 0; @@ -2066,10 +2098,13 @@ } SpdyFrameBuilder builder(size); - builder.BeginNewFrame(*this, - PUSH_PROMISE, - flags, - push_promise.stream_id()); + if (!skip_rewritelength_) { + builder.BeginNewFrame(*this, PUSH_PROMISE, flags, push_promise.stream_id()); + } else { + size_t length = std::min(size, kMaxControlFrameSize) - GetFrameHeaderSize(); + builder.BeginNewFrame(*this, PUSH_PROMISE, flags, push_promise.stream_id(), + length); + } int padding_payload_len = 0; if (push_promise.padded()) { builder.WriteUInt8(push_promise.padding_payload_len()); @@ -2399,7 +2434,7 @@ string padding = string(padding_payload_len, 0); builder->WriteBytes(padding.data(), padding.length()); } - if (bytes_remaining > 0) { + if (bytes_remaining > 0 && !skip_rewritelength_) { builder->OverwriteLength(*this, kMaxControlFrameSize - GetFrameHeaderSize()); } @@ -2412,7 +2447,12 @@ if (bytes_remaining == bytes_to_write) { flags |= end_flag; } - builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id); + if (!skip_rewritelength_) { + builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id); + } else { + builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id, + bytes_to_write); + } // Write payload fragment. builder->WriteBytes( &hpack_encoding[hpack_encoding.size() - bytes_remaining],
diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h index fff856a30..b686746 100644 --- a/net/spdy/spdy_framer.h +++ b/net/spdy/spdy_framer.h
@@ -765,6 +765,9 @@ // If true, then ProcessInput returns after processing a full frame, // rather than reading all available input. bool process_single_input_frame_ = false; + + // Latched value of FLAGS_chromium_http2_flag_remove_rewritelength. + bool skip_rewritelength_ = false; }; } // namespace net
diff --git a/net/spdy/spdy_header_block.cc b/net/spdy/spdy_header_block.cc index 4e36b89..6cbd6ba6 100644 --- a/net/spdy/spdy_header_block.cc +++ b/net/spdy/spdy_header_block.cc
@@ -19,6 +19,7 @@ using base::StringPiece; using std::dec; using std::hex; +using std::make_pair; using std::max; using std::min; using std::string; @@ -30,6 +31,16 @@ const size_t kDefaultStorageBlockSize = 2048; const char kCookieKey[] = "cookie"; +const char kNullSeparator = 0; + +StringPiece SeparatorForKey(StringPiece key) { + if (key == kCookieKey) { + static StringPiece cookie_separator = "; "; + return cookie_separator; + } else { + return StringPiece(&kNullSeparator, 1); + } +} } // namespace @@ -50,24 +61,6 @@ return StringPiece(arena_.Memdup(s.data(), s.size()), s.size()); } - // Given value, a string already in the arena, perform a realloc and append - // separator and more to the end of the value's new location. If value is the - // most recently added string (via Write), then UnsafeArena will not copy the - // existing value but instead will increase the space reserved for value. - StringPiece Realloc(StringPiece value, - StringPiece separator, - StringPiece more) { - size_t total_length = value.size() + separator.size() + more.size(); - char* ptr = const_cast<char*>(value.data()); - ptr = arena_.Realloc(ptr, value.size(), total_length); - StringPiece result(ptr, total_length); - ptr += value.size(); - memcpy(ptr, separator.data(), separator.size()); - ptr += separator.size(); - memcpy(ptr, more.data(), more.size()); - return result; - } - // If |s| points to the most recent allocation from arena_, the arena will // reclaim the memory. Otherwise, this method is a no-op. void Rewind(const StringPiece s) { @@ -76,10 +69,77 @@ void Clear() { arena_.Reset(); } + // Given a list of fragments and a separator, writes the fragments joined by + // the separator to a contiguous region of memory. Returns a StringPiece + // pointing to the region of memory. + StringPiece WriteFragments(const std::vector<StringPiece>& fragments, + StringPiece separator) { + if (fragments.empty()) { + return StringPiece(); + } + size_t total_size = separator.size() * (fragments.size() - 1); + for (const auto fragment : fragments) { + total_size += fragment.size(); + } + char* dst = arena_.Alloc(total_size); + size_t written = Join(dst, fragments, separator); + DCHECK_EQ(written, total_size); + return StringPiece(dst, total_size); + } + + size_t bytes_allocated() const { return arena_.status().bytes_allocated(); } + private: UnsafeArena arena_; }; +SpdyHeaderBlock::HeaderValue::HeaderValue(Storage* storage, + StringPiece key, + StringPiece initial_value) + : storage_(storage), fragments_({initial_value}), pair_({key, {}}) {} + +SpdyHeaderBlock::HeaderValue::HeaderValue(HeaderValue&& other) + : storage_(other.storage_), + fragments_(std::move(other.fragments_)), + pair_(std::move(other.pair_)) {} + +SpdyHeaderBlock::HeaderValue& SpdyHeaderBlock::HeaderValue::operator=( + HeaderValue&& other) { + storage_ = other.storage_; + fragments_ = std::move(other.fragments_); + pair_ = std::move(other.pair_); + return *this; +} + +SpdyHeaderBlock::HeaderValue::~HeaderValue() {} + +StringPiece SpdyHeaderBlock::HeaderValue::ConsolidatedValue() const { + if (fragments_.empty()) { + return StringPiece(); + } + if (fragments_.size() > 1) { + fragments_ = { + storage_->WriteFragments(fragments_, SeparatorForKey(pair_.first))}; + } + return fragments_[0]; +} + +void SpdyHeaderBlock::HeaderValue::Append(StringPiece fragment) { + fragments_.push_back(fragment); +} + +const std::pair<StringPiece, StringPiece>& +SpdyHeaderBlock::HeaderValue::as_pair() const { + pair_.second = ConsolidatedValue(); + return pair_; +} + +SpdyHeaderBlock::iterator::iterator(MapType::const_iterator it) : it_(it) {} + +SpdyHeaderBlock::iterator::iterator(const iterator& other) : it_(other.it_) {} + +SpdyHeaderBlock::iterator::~iterator() {} + SpdyHeaderBlock::ValueProxy::ValueProxy( SpdyHeaderBlock::MapType* block, SpdyHeaderBlock::Storage* storage, @@ -89,8 +149,7 @@ storage_(storage), lookup_result_(lookup_result), key_(key), - valid_(true) { -} + valid_(true) {} SpdyHeaderBlock::ValueProxy::ValueProxy(ValueProxy&& other) : block_(other.block_), @@ -127,10 +186,14 @@ if (lookup_result_ == block_->end()) { DVLOG(1) << "Inserting: (" << key_ << ", " << value << ")"; lookup_result_ = - block_->insert(std::make_pair(key_, storage_->Write(value))).first; + block_ + ->emplace(make_pair( + key_, HeaderValue(storage_, key_, storage_->Write(value)))) + .first; } else { DVLOG(1) << "Updating key: " << key_ << " with value: " << value; - lookup_result_->second = storage_->Write(value); + lookup_result_->second = + HeaderValue(storage_, key_, storage_->Write(value)); } return *this; } @@ -139,7 +202,7 @@ if (lookup_result_ == block_->end()) { return ""; } else { - return lookup_result_->second.as_string(); + return lookup_result_->second.value().as_string(); } } @@ -160,8 +223,8 @@ SpdyHeaderBlock SpdyHeaderBlock::Clone() const { SpdyHeaderBlock copy; - for (auto iter : *this) { - copy.AppendHeader(iter.first, iter.second); + for (const auto& p : *this) { + copy.AppendHeader(p.first, p.second); } return copy; } @@ -181,7 +244,7 @@ string output = "\n{\n"; for (auto it = begin(); it != end(); ++it) { output += - " " + it->first.as_string() + ":" + it->second.as_string() + "\n"; + " " + it->first.as_string() + " " + it->second.as_string() + "\n"; } output.append("}\n"); return output; @@ -192,8 +255,7 @@ storage_.reset(); } -void SpdyHeaderBlock::insert( - const SpdyHeaderBlock::MapType::value_type& value) { +void SpdyHeaderBlock::insert(const SpdyHeaderBlock::value_type& value) { // TODO(birenroy): Write new value in place of old value, if it fits. auto iter = block_.find(value.first); if (iter == block_.end()) { @@ -202,7 +264,9 @@ } else { DVLOG(1) << "Updating key: " << iter->first << " with value: " << value.second; - iter->second = GetStorage()->Write(value.second); + auto storage = GetStorage(); + iter->second = + HeaderValue(storage, iter->first, storage->Write(value.second)); } } @@ -232,16 +296,15 @@ return; } DVLOG(1) << "Updating key: " << iter->first << "; appending value: " << value; - StringPiece separator("", 1); - if (key == kCookieKey) { - separator = "; "; - } - iter->second = GetStorage()->Realloc(iter->second, separator, value); + iter->second.Append(GetStorage()->Write(value)); } void SpdyHeaderBlock::AppendHeader(const StringPiece key, const StringPiece value) { - block_.emplace(GetStorage()->Write(key), GetStorage()->Write(value)); + auto storage = GetStorage(); + auto backed_key = storage->Write(key); + block_.emplace(make_pair( + backed_key, HeaderValue(storage, backed_key, storage->Write(value)))); } SpdyHeaderBlock::Storage* SpdyHeaderBlock::GetStorage() { @@ -293,4 +356,31 @@ return true; } +size_t SpdyHeaderBlock::bytes_allocated() const { + if (storage_ == nullptr) { + return 0; + } else { + return storage_->bytes_allocated(); + } +} + +size_t Join(char* dst, + const std::vector<StringPiece>& fragments, + StringPiece separator) { + if (fragments.empty()) { + return 0; + } + auto original_dst = dst; + auto it = fragments.begin(); + memcpy(dst, it->data(), it->size()); + dst += it->size(); + for (++it; it != fragments.end(); ++it) { + memcpy(dst, separator.data(), separator.size()); + dst += separator.size(); + memcpy(dst, it->data(), it->size()); + dst += it->size(); + } + return dst - original_dst; +} + } // namespace net
diff --git a/net/spdy/spdy_header_block.h b/net/spdy/spdy_header_block.h index fef27e8f..fe8827f5 100644 --- a/net/spdy/spdy_header_block.h +++ b/net/spdy/spdy_header_block.h
@@ -11,6 +11,7 @@ #include <map> #include <memory> #include <string> +#include <vector> #include "base/macros.h" #include "base/strings/string_piece.h" @@ -27,6 +28,7 @@ class NetLogCaptureMode; namespace test { +class SpdyHeaderBlockPeer; class ValueProxyPeer; } @@ -43,16 +45,93 @@ // It's expected that keys are rarely deleted from a SpdyHeaderBlock. class NET_EXPORT SpdyHeaderBlock { private: - using MapType = linked_hash_map<base::StringPiece, - base::StringPiece, - base::StringPieceHash>; class Storage; + // Stores a list of value fragments that can be joined later with a + // key-dependent separator. + class NET_EXPORT HeaderValue { + public: + HeaderValue(Storage* storage, + base::StringPiece key, + base::StringPiece initial_value); + + // Moves are allowed. + HeaderValue(HeaderValue&& other); + HeaderValue& operator=(HeaderValue&& other); + + // Copies are not. + HeaderValue(const HeaderValue& other) = delete; + HeaderValue& operator=(const HeaderValue& other) = delete; + + ~HeaderValue(); + + // Consumes at most |fragment.size()| bytes of memory. + void Append(base::StringPiece fragment); + + base::StringPiece value() const { return as_pair().second; } + const std::pair<base::StringPiece, base::StringPiece>& as_pair() const; + + private: + // May allocate a large contiguous region of memory to hold the concatenated + // fragments and separators. + base::StringPiece ConsolidatedValue() const; + + mutable Storage* storage_; + mutable std::vector<base::StringPiece> fragments_; + // The first element is the key; the second is the consolidated value. + mutable std::pair<base::StringPiece, base::StringPiece> pair_; + }; + + typedef linked_hash_map<base::StringPiece, HeaderValue, base::StringPieceHash> + MapType; + public: - using iterator = MapType::iterator; - using const_iterator = MapType::const_iterator; - using value_type = MapType::value_type; - using reverse_iterator = MapType::reverse_iterator; + typedef std::pair<base::StringPiece, base::StringPiece> value_type; + + // Provides iteration over a sequence of std::pair<StringPiece, StringPiece>, + // even though the underlying MapType::value_type is different. Dereferencing + // the iterator will result in memory allocation for multi-value headers. + class NET_EXPORT iterator { + public: + // The following type definitions fulfill the requirements for iterator + // implementations. + typedef std::pair<base::StringPiece, base::StringPiece> value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef MapType::iterator::difference_type difference_type; + + // In practice, this iterator only offers access to const value_type. + typedef const value_type& const_reference; + typedef const value_type* const_pointer; + + explicit iterator(MapType::const_iterator it); + iterator(const iterator& other); + ~iterator(); + + // This will result in memory allocation if the value consists of multiple + // fragments. + const_reference operator*() const { return it_->second.as_pair(); } + + const_pointer operator->() const { return &(this->operator*()); } + bool operator==(const iterator& it) const { return it_ == it.it_; } + bool operator!=(const iterator& it) const { return !(*this == it); } + + iterator& operator++() { + it_++; + return *this; + } + + iterator operator++(int) { + auto ret = *this; + this->operator++(); + return ret; + } + + private: + MapType::const_iterator it_; + }; + typedef iterator const_iterator; class ValueProxy; @@ -72,16 +151,16 @@ // keys and values. std::string DebugString() const; - // These methods delegate to our MapType member. - iterator begin() { return block_.begin(); } - iterator end() { return block_.end(); } - const_iterator begin() const { return block_.begin(); } - const_iterator end() const { return block_.end(); } + iterator begin() { return iterator(block_.begin()); } + iterator end() { return iterator(block_.end()); } + const_iterator begin() const { return const_iterator(block_.begin()); } + const_iterator end() const { return const_iterator(block_.end()); } bool empty() const { return block_.empty(); } size_t size() const { return block_.size(); } - iterator find(base::StringPiece key) { return block_.find(key); } - const_iterator find(base::StringPiece key) const { return block_.find(key); } - reverse_iterator rbegin() { return block_.rbegin(); } + iterator find(base::StringPiece key) { return iterator(block_.find(key)); } + const_iterator find(base::StringPiece key) const { + return const_iterator(block_.find(key)); + } void erase(base::StringPiece key) { block_.erase(key); } // Clears both our MapType member and the memory used to hold headers. @@ -91,7 +170,7 @@ // If key already exists in the block, replaces the value of that key. Else // adds a new header to the end of the block. - void insert(const MapType::value_type& value); + void insert(const value_type& value); // If a header with the key is already present, then append the value to the // existing header value, NUL ("\0") separated unless the key is cookie, in @@ -140,8 +219,11 @@ }; private: + friend class test::SpdyHeaderBlockPeer; + void AppendHeader(const base::StringPiece key, const base::StringPiece value); Storage* GetStorage(); + size_t bytes_allocated() const; // StringPieces held by |block_| point to memory owned by |*storage_|. // |storage_| might be nullptr as long as |block_| is empty. @@ -149,6 +231,12 @@ std::unique_ptr<Storage> storage_; }; +// Writes |fragments| to |dst|, joined by |separator|. |dst| must be large +// enough to hold the result. Returns the number of bytes written. +NET_EXPORT size_t Join(char* dst, + const std::vector<base::StringPiece>& fragments, + base::StringPiece separator); + // Converts a SpdyHeaderBlock into NetLog event parameters. NET_EXPORT std::unique_ptr<base::Value> SpdyHeaderBlockNetLogCallback( const SpdyHeaderBlock* headers,
diff --git a/net/spdy/spdy_header_block_test.cc b/net/spdy/spdy_header_block_test.cc index 5f4429d..c2c4a8f 100644 --- a/net/spdy/spdy_header_block_test.cc +++ b/net/spdy/spdy_header_block_test.cc
@@ -13,8 +13,10 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using base::StringPiece; using std::make_pair; using std::string; +using std::vector; using ::testing::ElementsAre; namespace net { @@ -22,13 +24,10 @@ class ValueProxyPeer { public: - static base::StringPiece key(SpdyHeaderBlock::ValueProxy* p) { - return p->key_; - } + static StringPiece key(SpdyHeaderBlock::ValueProxy* p) { return p->key_; } }; -std::pair<base::StringPiece, base::StringPiece> Pair(base::StringPiece k, - base::StringPiece v) { +std::pair<StringPiece, StringPiece> Pair(StringPiece k, StringPiece v) { return make_pair(k, v); } @@ -46,12 +45,12 @@ TEST(SpdyHeaderBlockTest, KeyMemoryReclaimedOnLookup) { SpdyHeaderBlock block; - base::StringPiece copied_key1; + StringPiece copied_key1; { auto proxy1 = block["some key name"]; copied_key1 = ValueProxyPeer::key(&proxy1); } - base::StringPiece copied_key2; + StringPiece copied_key2; { auto proxy2 = block["some other key name"]; copied_key2 = ValueProxyPeer::key(&proxy2); @@ -187,12 +186,40 @@ block.AppendValueOrAddHeader("h1", "h1v3"); block.AppendValueOrAddHeader("h2", "h2v3"); block.AppendValueOrAddHeader("h3", "h3v3"); + block.AppendValueOrAddHeader("h4", "singleton"); EXPECT_EQ("key1=value1; key2=value2; key3=value3", block["cookie"]); EXPECT_EQ("baz", block["foo"]); EXPECT_EQ(string("h1v1\0h1v2\0h1v3", 14), block["h1"]); EXPECT_EQ(string("h2v1\0h2v2\0h2v3", 14), block["h2"]); EXPECT_EQ(string("h3v2\0h3v3", 9), block["h3"]); + EXPECT_EQ("singleton", block["h4"]); +} + +TEST(JoinTest, JoinEmpty) { + vector<StringPiece> empty; + StringPiece separator = ", "; + char buf[10] = ""; + size_t written = Join(buf, empty, separator); + EXPECT_EQ(0u, written); +} + +TEST(JoinTest, JoinOne) { + vector<StringPiece> v = {"one"}; + StringPiece separator = ", "; + char buf[15]; + size_t written = Join(buf, v, separator); + EXPECT_EQ(3u, written); + EXPECT_EQ("one", StringPiece(buf, written)); +} + +TEST(JoinTest, JoinMultiple) { + vector<StringPiece> v = {"one", "two", "three"}; + StringPiece separator = ", "; + char buf[15]; + size_t written = Join(buf, v, separator); + EXPECT_EQ(15u, written); + EXPECT_EQ("one, two, three", StringPiece(buf, written)); } } // namespace test
diff --git a/net/spdy/spdy_protocol.cc b/net/spdy/spdy_protocol.cc index adf76ef..1c9254e30 100644 --- a/net/spdy/spdy_protocol.cc +++ b/net/spdy/spdy_protocol.cc
@@ -46,54 +46,13 @@ } bool IsValidFrameType(int frame_type_field) { - // Check for recognized extensions. - if (frame_type_field == SerializeFrameType(ALTSVC) || - frame_type_field == SerializeFrameType(BLOCKED)) { - return true; - } - - // DATA is the first valid frame. - if (frame_type_field < SerializeFrameType(DATA)) { - return false; - } - - // CONTINUATION is the last valid frame. - if (frame_type_field > SerializeFrameType(CONTINUATION)) { - return false; - } - - return true; + return frame_type_field >= MIN_FRAME_TYPE && + frame_type_field <= MAX_FRAME_TYPE; } SpdyFrameType ParseFrameType(int frame_type_field) { - switch (frame_type_field) { - case 0: - return DATA; - case 1: - return HEADERS; - case 2: - return PRIORITY; - case 3: - return RST_STREAM; - case 4: - return SETTINGS; - case 5: - return PUSH_PROMISE; - case 6: - return PING; - case 7: - return GOAWAY; - case 8: - return WINDOW_UPDATE; - case 9: - return CONTINUATION; - case 10: - return ALTSVC; - case 11: - return BLOCKED; - } - SPDY_BUG << "Unhandled frame type " << frame_type_field; - return DATA; + SPDY_BUG_IF(!IsValidFrameType(frame_type_field)) << "Invalid frame type."; + return static_cast<SpdyFrameType>(frame_type_field); } int SerializeFrameType(SpdyFrameType frame_type) {
diff --git a/net/spdy/spdy_protocol.h b/net/spdy/spdy_protocol.h index 62b08b80..c5ab564 100644 --- a/net/spdy/spdy_protocol.h +++ b/net/spdy/spdy_protocol.h
@@ -74,19 +74,21 @@ // Types of HTTP2 frames. enum SpdyFrameType { - DATA, - RST_STREAM, - SETTINGS, - PING, - GOAWAY, - HEADERS, - WINDOW_UPDATE, - PUSH_PROMISE, - CONTINUATION, - PRIORITY, - // BLOCKED and ALTSVC are recognized extensions. - BLOCKED, - ALTSVC, + DATA = 0x00, + MIN_FRAME_TYPE = DATA, + HEADERS = 0x01, + PRIORITY = 0x02, + RST_STREAM = 0x03, + SETTINGS = 0x04, + PUSH_PROMISE = 0x05, + PING = 0x06, + GOAWAY = 0x07, + WINDOW_UPDATE = 0x08, + CONTINUATION = 0x09, + // ALTSVC and BLOCKED are recognized extensions. + ALTSVC = 0x0a, + BLOCKED = 0x0b, + MAX_FRAME_TYPE = BLOCKED }; // Flags on data packets.
diff --git a/net/test/gtest_util.h b/net/test/gtest_util.h index 22d82b0..dec0bb9 100644 --- a/net/test/gtest_util.h +++ b/net/test/gtest_util.h
@@ -7,9 +7,14 @@ #ifndef NET_TEST_GTEST_UTIL_H_ #define NET_TEST_GTEST_UTIL_H_ +#include <string> + +#include "base/macros.h" +#include "base/strings/string_piece.h" #include "base/test/mock_log.h" #include "net/base/net_errors.h" #include "net/test/scoped_disable_exit_on_dfatal.h" +#include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -36,6 +41,34 @@ return arg == net::OK; } +// A gMock matcher for base::StringPiece arguments. +// gMock's built-in HasSubstrMatcher does not work, +// because base::StringPiece cannot be implicitly converted to std::string. +class StringPieceHasSubstrMatcher { + public: + explicit StringPieceHasSubstrMatcher(const std::string& substring) + : substring_(substring) {} + + bool MatchAndExplain(base::StringPiece s, + ::testing::MatchResultListener* listener) const { + return s.as_string().find(substring_) != std::string::npos; + } + + // Describe what this matcher matches. + void DescribeTo(std::ostream* os) const { + *os << "has substring " << substring_; + } + + void DescribeNegationTo(std::ostream* os) const { + *os << "has no substring " << substring_; + } + + private: + const std::string substring_; + + DISALLOW_ASSIGN(StringPieceHasSubstrMatcher); +}; + // Internal implementation for the EXPECT_DFATAL and ASSERT_DFATAL // macros. Do not use this directly. #define GTEST_DFATAL_(statement, severity, matcher, fail) \
diff --git a/net/tools/testserver/testserver.pydeps b/net/tools/testserver/testserver.pydeps index 8deef4a..b3b97fa0 100644 --- a/net/tools/testserver/testserver.pydeps +++ b/net/tools/testserver/testserver.pydeps
@@ -1,5 +1,5 @@ # Generated by running: -# build/print_python_deps.py --root net/tools/testserver --output net/tools/testserver/testserver.pydeps net/tools/testserver/testserver.py +# build/print_python_deps.py --root net/tools/testserver --output net/tools/testserver/testserver.pydeps --whitelist third_party/tlslite/tlslite/utils net/tools/testserver/testserver.py ../../../third_party/pyftpdlib/src/pyftpdlib/__init__.py ../../../third_party/pyftpdlib/src/pyftpdlib/ftpserver.py ../../../third_party/pywebsocket/src/mod_pywebsocket/__init__.py @@ -53,7 +53,12 @@ ../../../third_party/tlslite/tlslite/utils/codec.py ../../../third_party/tlslite/tlslite/utils/compat.py ../../../third_party/tlslite/tlslite/utils/cryptomath.py +../../../third_party/tlslite/tlslite/utils/datefuncs.py ../../../third_party/tlslite/tlslite/utils/keyfactory.py +../../../third_party/tlslite/tlslite/utils/openssl_aes.py +../../../third_party/tlslite/tlslite/utils/openssl_rc4.py +../../../third_party/tlslite/tlslite/utils/openssl_rsakey.py +../../../third_party/tlslite/tlslite/utils/openssl_tripledes.py ../../../third_party/tlslite/tlslite/utils/p256.py ../../../third_party/tlslite/tlslite/utils/pem.py ../../../third_party/tlslite/tlslite/utils/pycrypto_aes.py
diff --git a/remoting/client/plugin/pepper_video_renderer_2d.cc b/remoting/client/plugin/pepper_video_renderer_2d.cc index 96fc9cf..4a605cb 100644 --- a/remoting/client/plugin/pepper_video_renderer_2d.cc +++ b/remoting/client/plugin/pepper_video_renderer_2d.cc
@@ -176,7 +176,7 @@ if (!done.is_null()) { pending_frames_done_callbacks_.push_back( - new base::ScopedClosureRunner(done)); + base::MakeUnique<base::ScopedClosureRunner>(done)); } need_flush_ = true;
diff --git a/remoting/client/plugin/pepper_video_renderer_2d.h b/remoting/client/plugin/pepper_video_renderer_2d.h index 74fa15f..4663cdd6 100644 --- a/remoting/client/plugin/pepper_video_renderer_2d.h +++ b/remoting/client/plugin/pepper_video_renderer_2d.h
@@ -6,11 +6,12 @@ #define REMOTING_CLIENT_PLUGIN_PEPPER_VIDEO_RENDERER_2D_H_ #include <list> +#include <memory> +#include <vector> #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "ppapi/cpp/graphics_2d.h" @@ -84,10 +85,12 @@ webrtc::DesktopSize source_size_; // Done callbacks for the frames that have been painted but not flushed. - ScopedVector<base::ScopedClosureRunner> pending_frames_done_callbacks_; + std::vector<std::unique_ptr<base::ScopedClosureRunner>> + pending_frames_done_callbacks_; // Done callbacks for the frames that are currently being flushed. - ScopedVector<base::ScopedClosureRunner> flushing_frames_done_callbacks_; + std::vector<std::unique_ptr<base::ScopedClosureRunner>> + flushing_frames_done_callbacks_; // True if there paint operations that need to be flushed. bool need_flush_ = false;
diff --git a/remoting/client/software_video_renderer_unittest.cc b/remoting/client/software_video_renderer_unittest.cc index 7aa113c..b9541a97 100644 --- a/remoting/client/software_video_renderer_unittest.cc +++ b/remoting/client/software_video_renderer_unittest.cc
@@ -6,12 +6,12 @@ #include <stdint.h> +#include <memory> #include <utility> #include <vector> #include "base/bind.h" #include "base/memory/ptr_util.h" -#include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/threading/thread.h" @@ -156,7 +156,7 @@ TEST_F(SoftwareVideoRendererTest, DecodeFrame) { const int kFrameCount = 5; - ScopedVector<DesktopFrame> test_frames; + std::vector<std::unique_ptr<DesktopFrame>> test_frames; // std::vector<bool> doesn't allow to get pointer to individual values, so // int needs to be used instead.
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index 6572713..238b618c 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc
@@ -125,7 +125,7 @@ } void ChromotingHost::AddExtension(std::unique_ptr<HostExtension> extension) { - extensions_.push_back(extension.release()); + extensions_.push_back(std::move(extension)); } void ChromotingHost::SetAuthenticatorFactory( @@ -259,9 +259,12 @@ DesktopEnvironmentOptions options = desktop_environment_options_; // TODO(zijiehe): Apply HostSessionOptions to options. // Create a ClientSession object. + std::vector<HostExtension*> extension_ptrs; + for (const auto& extension : extensions_) + extension_ptrs.push_back(extension.get()); clients_.push_back(base::MakeUnique<ClientSession>( this, std::move(connection), desktop_environment_factory_, options, - max_session_duration_, pairing_registry_, extensions_.get())); + max_session_duration_, pairing_registry_, extension_ptrs)); } } // namespace remoting
diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h index 7009f6e..d9d34ea 100644 --- a/remoting/host/chromoting_host.h +++ b/remoting/host/chromoting_host.h
@@ -11,7 +11,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/threading/non_thread_safe.h" @@ -142,8 +141,6 @@ private: friend class ChromotingHostTest; - typedef ScopedVector<HostExtension> HostExtensionList; - // Unless specified otherwise all members of this class must be // used on the network thread only. @@ -176,7 +173,7 @@ scoped_refptr<protocol::PairingRegistry> pairing_registry_; // List of host extensions. - HostExtensionList extensions_; + std::vector<std::unique_ptr<HostExtension>> extensions_; base::WeakPtrFactory<ChromotingHost> weak_factory_;
diff --git a/remoting/host/host_extension_session_manager.cc b/remoting/host/host_extension_session_manager.cc index 8940cb66b..ac06b4f 100644 --- a/remoting/host/host_extension_session_manager.cc +++ b/remoting/host/host_extension_session_manager.cc
@@ -4,6 +4,7 @@ #include "remoting/host/host_extension_session_manager.h" +#include "base/logging.h" #include "remoting/base/capabilities.h" #include "remoting/host/client_session_details.h" #include "remoting/host/host_extension.h" @@ -12,7 +13,7 @@ namespace remoting { HostExtensionSessionManager::HostExtensionSessionManager( - const std::vector<HostExtension*>& extensions, + const HostExtensions& extensions, ClientSessionDetails* client_session_details) : client_session_details_(client_session_details), client_stub_(nullptr), @@ -22,9 +23,8 @@ std::string HostExtensionSessionManager::GetCapabilities() const { std::string capabilities; - for (HostExtensions::const_iterator extension = extensions_.begin(); - extension != extensions_.end(); ++extension) { - const std::string& capability = (*extension)->capability(); + for (const auto& extension : extensions_) { + const std::string& capability = extension->capability(); if (capability.empty()) { continue; } @@ -44,30 +44,28 @@ client_stub_ = client_stub; - for (HostExtensions::const_iterator extension = extensions_.begin(); - extension != extensions_.end(); ++extension) { + for (const auto& extension : extensions_) { // If the extension requires a capability that was not negotiated then do // not instantiate it. - if (!(*extension)->capability().empty() && - !HasCapability(capabilities, (*extension)->capability())) { + if (!extension->capability().empty() && + !HasCapability(capabilities, extension->capability())) { continue; } std::unique_ptr<HostExtensionSession> extension_session = - (*extension) - ->CreateExtensionSession(client_session_details_, client_stub_); + extension->CreateExtensionSession(client_session_details_, + client_stub_); DCHECK(extension_session); - extension_sessions_.push_back(extension_session.release()); + extension_sessions_.push_back(std::move(extension_session)); } } bool HostExtensionSessionManager::OnExtensionMessage( const protocol::ExtensionMessage& message) { - for(HostExtensionSessions::const_iterator it = extension_sessions_.begin(); - it != extension_sessions_.end(); ++it) { - if ((*it)->OnExtensionMessage(client_session_details_, client_stub_, - message)) { + for (const auto& session : extension_sessions_) { + if (session->OnExtensionMessage(client_session_details_, client_stub_, + message)) { return true; } }
diff --git a/remoting/host/host_extension_session_manager.h b/remoting/host/host_extension_session_manager.h index 6925b8df..e26ec08f 100644 --- a/remoting/host/host_extension_session_manager.h +++ b/remoting/host/host_extension_session_manager.h
@@ -5,11 +5,11 @@ #ifndef REMOTING_HOST_HOST_EXTENSION_SESSION_MANAGER_H_ #define REMOTING_HOST_HOST_EXTENSION_SESSION_MANAGER_H_ +#include <memory> #include <string> #include <vector> #include "base/macros.h" -#include "base/memory/scoped_vector.h" namespace remoting { @@ -27,7 +27,7 @@ // set of capabilities negotiated between client and host. class HostExtensionSessionManager { public: - typedef std::vector<HostExtension*> HostExtensions; + using HostExtensions = std::vector<HostExtension*>; // Creates an extension manager for the specified |extensions|. HostExtensionSessionManager(const HostExtensions& extensions, @@ -48,7 +48,8 @@ bool OnExtensionMessage(const protocol::ExtensionMessage& message); private: - typedef ScopedVector<HostExtensionSession> HostExtensionSessions; + using HostExtensionSessions = + std::vector<std::unique_ptr<HostExtensionSession>>; // Passed to HostExtensionSessions to allow them to send messages, // disconnect the session, etc.
diff --git a/remoting/protocol/audio_pump_unittest.cc b/remoting/protocol/audio_pump_unittest.cc index 67ce2ac..806cd0a 100644 --- a/remoting/protocol/audio_pump_unittest.cc +++ b/remoting/protocol/audio_pump_unittest.cc
@@ -6,11 +6,12 @@ #include <stddef.h> +#include <memory> #include <utility> +#include <vector> #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "remoting/codec/audio_encoder.h" @@ -69,7 +70,7 @@ std::unique_ptr<AudioPump> pump_; - ScopedVector<AudioPacket> sent_packets_; + std::vector<std::unique_ptr<AudioPacket>> sent_packets_; std::vector<base::Closure> done_closures_; private:
diff --git a/remoting/protocol/client_video_dispatcher_unittest.cc b/remoting/protocol/client_video_dispatcher_unittest.cc index e26ca45..d4722f4 100644 --- a/remoting/protocol/client_video_dispatcher_unittest.cc +++ b/remoting/protocol/client_video_dispatcher_unittest.cc
@@ -4,8 +4,10 @@ #include "remoting/protocol/client_video_dispatcher.h" +#include <memory> +#include <vector> + #include "base/bind.h" -#include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "remoting/base/buffered_socket_writer.h" @@ -58,10 +60,10 @@ MessageReader reader_; BufferedSocketWriter writer_; - ScopedVector<VideoPacket> video_packets_; + std::vector<std::unique_ptr<VideoPacket>> video_packets_; std::vector<base::Closure> packet_done_callbacks_; - ScopedVector<VideoAck> ack_messages_; + std::vector<std::unique_ptr<VideoAck>> ack_messages_; }; ClientVideoDispatcherTest::ClientVideoDispatcherTest() @@ -88,7 +90,7 @@ void ClientVideoDispatcherTest::ProcessVideoPacket( std::unique_ptr<VideoPacket> video_packet, const base::Closure& done) { - video_packets_.push_back(video_packet.release()); + video_packets_.push_back(std::move(video_packet)); packet_done_callbacks_.push_back(done); } @@ -112,7 +114,7 @@ std::unique_ptr<CompoundBuffer> buffer) { std::unique_ptr<VideoAck> ack = ParseMessage<VideoAck>(buffer.get()); EXPECT_TRUE(ack); - ack_messages_.push_back(ack.release()); + ack_messages_.push_back(std::move(ack)); } void ClientVideoDispatcherTest::OnReadError(int error) {
diff --git a/remoting/protocol/video_frame_pump.cc b/remoting/protocol/video_frame_pump.cc index 8cb30e4..68324ec 100644 --- a/remoting/protocol/video_frame_pump.cc +++ b/remoting/protocol/video_frame_pump.cc
@@ -238,8 +238,9 @@ // Send next packet if any. if (!pending_packets_.empty()) { - std::unique_ptr<PacketWithTimestamps> next(pending_packets_.front()); - pending_packets_.weak_erase(pending_packets_.begin()); + std::unique_ptr<PacketWithTimestamps> next = + std::move(pending_packets_.front()); + pending_packets_.erase(pending_packets_.begin()); SendPacket(std::move(next)); } }
diff --git a/remoting/protocol/video_frame_pump.h b/remoting/protocol/video_frame_pump.h index 6fe57e8..925b9bc5 100644 --- a/remoting/protocol/video_frame_pump.h +++ b/remoting/protocol/video_frame_pump.h
@@ -9,9 +9,9 @@ #include <stdint.h> #include <memory> +#include <vector> #include "base/macros.h" -#include "base/memory/scoped_vector.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "base/timer/timer.h" @@ -179,7 +179,7 @@ bool send_pending_ = false; - ScopedVector<PacketWithTimestamps> pending_packets_; + std::vector<std::unique_ptr<PacketWithTimestamps>> pending_packets_; base::ThreadChecker thread_checker_;
diff --git a/remoting/protocol/webrtc_transport.cc b/remoting/protocol/webrtc_transport.cc index e4ce98ae..c9c88c4e 100644 --- a/remoting/protocol/webrtc_transport.cc +++ b/remoting/protocol/webrtc_transport.cc
@@ -680,8 +680,8 @@ if (peer_connection()->signaling_state() == webrtc::PeerConnectionInterface::kStable) { - for (auto* candidate : pending_incoming_candidates_) { - if (!peer_connection()->AddIceCandidate(candidate)) { + for (const auto& candidate : pending_incoming_candidates_) { + if (!peer_connection()->AddIceCandidate(candidate.get())) { LOG(ERROR) << "Failed to add incoming candidate"; Close(INCOMPATIBLE_PROTOCOL); return;
diff --git a/remoting/protocol/webrtc_transport.h b/remoting/protocol/webrtc_transport.h index 8e5fb1b..faf72be 100644 --- a/remoting/protocol/webrtc_transport.h +++ b/remoting/protocol/webrtc_transport.h
@@ -7,10 +7,10 @@ #include <memory> #include <string> +#include <vector> #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "base/timer/timer.h" @@ -141,7 +141,8 @@ std::unique_ptr<buzz::XmlElement> pending_transport_info_message_; base::OneShotTimer transport_info_timer_; - ScopedVector<webrtc::IceCandidateInterface> pending_incoming_candidates_; + std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> + pending_incoming_candidates_; base::WeakPtrFactory<WebrtcTransport> weak_factory_;
diff --git a/remoting/signaling/xmpp_signal_strategy_unittest.cc b/remoting/signaling/xmpp_signal_strategy_unittest.cc index 53147bc..99d8f84d5 100644 --- a/remoting/signaling/xmpp_signal_strategy_unittest.cc +++ b/remoting/signaling/xmpp_signal_strategy_unittest.cc
@@ -4,7 +4,9 @@ #include "remoting/signaling/xmpp_signal_strategy.h" +#include <memory> #include <utility> +#include <vector> #include "base/base64.h" #include "base/memory/ptr_util.h" @@ -160,7 +162,7 @@ std::unique_ptr<XmppSignalStrategy> signal_strategy_; std::vector<SignalStrategy::State> state_history_; - ScopedVector<buzz::XmlElement> received_messages_; + std::vector<std::unique_ptr<buzz::XmlElement>> received_messages_; }; void XmppSignalStrategyTest::Connect(bool success) {
diff --git a/remoting/signaling/xmpp_stream_parser_unittest.cc b/remoting/signaling/xmpp_stream_parser_unittest.cc index 299d9f7..22e341f9 100644 --- a/remoting/signaling/xmpp_stream_parser_unittest.cc +++ b/remoting/signaling/xmpp_stream_parser_unittest.cc
@@ -4,10 +4,11 @@ #include "remoting/signaling/xmpp_stream_parser.h" +#include <memory> #include <utility> +#include <vector> #include "base/bind.h" -#include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "testing/gtest/include/gtest/gtest.h" @@ -43,7 +44,7 @@ base::MessageLoop message_loop_; std::unique_ptr<XmppStreamParser> parser_; - ScopedVector<buzz::XmlElement> received_stanzas_; + std::vector<std::unique_ptr<buzz::XmlElement>> received_stanzas_; bool error_; };
diff --git a/remoting/test/test_video_renderer_unittest.cc b/remoting/test/test_video_renderer_unittest.cc index 30ab30c..0d6f53e 100644 --- a/remoting/test/test_video_renderer_unittest.cc +++ b/remoting/test/test_video_renderer_unittest.cc
@@ -7,11 +7,12 @@ #include <stdint.h> #include <cmath> +#include <memory> #include <utility> +#include <vector> #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" @@ -399,7 +400,7 @@ // more than one task on the video decode thread, while not too large to wait // for too long for the unit test to complete. const int task_num = 20; - ScopedVector<VideoPacket> video_packets; + std::vector<std::unique_ptr<VideoPacket>> video_packets; for (int i = 0; i < task_num; ++i) { std::unique_ptr<webrtc::DesktopFrame> original_frame = CreateDesktopFrameWithGradient(kDefaultScreenWidthPx, @@ -407,11 +408,8 @@ video_packets.push_back(encoder_->Encode(*original_frame.get())); } - for (int i = 0; i < task_num; ++i) { - // Transfer ownership of video packet. - VideoPacket* packet = video_packets[i]; - video_packets[i] = nullptr; - test_video_renderer_->ProcessVideoPacket(base::WrapUnique(packet), + for (auto& packet : video_packets) { + test_video_renderer_->ProcessVideoPacket(std::move(packet), base::Bind(&base::DoNothing)); } }
diff --git a/services/ui/gpu/gpu_main.cc b/services/ui/gpu/gpu_main.cc index 660c471..a87c7cbe 100644 --- a/services/ui/gpu/gpu_main.cc +++ b/services/ui/gpu/gpu_main.cc
@@ -14,6 +14,10 @@ #include "services/ui/common/server_gpu_memory_buffer_manager.h" #include "services/ui/gpu/gpu_service.h" +#if defined(OS_MACOSX) +#include "base/message_loop/message_pump_mac.h" +#endif + namespace { #if defined(USE_X11) @@ -104,14 +108,15 @@ } void GpuMain::CreateGpuService(mojom::GpuServiceRequest request, - mojom::GpuHostPtr gpu_host) { + mojom::GpuHostPtr gpu_host, + const gpu::GpuPreferences& preferences) { // |this| will outlive the gpu thread and so it's safe to use // base::Unretained here. gpu_thread_.task_runner()->PostTask( FROM_HERE, base::Bind(&GpuMain::CreateGpuServiceOnGpuThread, base::Unretained(this), base::Passed(std::move(request)), - base::Passed(gpu_host.PassInterface()))); + base::Passed(gpu_host.PassInterface()), preferences)); } void GpuMain::CreateDisplayCompositor( @@ -211,10 +216,11 @@ void GpuMain::CreateGpuServiceOnGpuThread( mojom::GpuServiceRequest request, - mojom::GpuHostPtrInfo gpu_host_info) { + mojom::GpuHostPtrInfo gpu_host_info, + const gpu::GpuPreferences& preferences) { mojom::GpuHostPtr gpu_host; gpu_host.Bind(std::move(gpu_host_info)); - gpu_service_->InitializeWithHost(std::move(gpu_host)); + gpu_service_->InitializeWithHost(std::move(gpu_host), preferences); gpu_service_->Bind(std::move(request)); if (pending_display_compositor_request_.is_pending()) {
diff --git a/services/ui/gpu/gpu_main.h b/services/ui/gpu/gpu_main.h index 031b5b9d..a5c859d 100644 --- a/services/ui/gpu/gpu_main.h +++ b/services/ui/gpu/gpu_main.h
@@ -28,7 +28,8 @@ // mojom::GpuMain implementation: void CreateGpuService(mojom::GpuServiceRequest request, - mojom::GpuHostPtr gpu_host) override; + mojom::GpuHostPtr gpu_host, + const gpu::GpuPreferences& preferences) override; void CreateDisplayCompositor( cc::mojom::DisplayCompositorRequest request, cc::mojom::DisplayCompositorClientPtr client) override; @@ -51,7 +52,8 @@ cc::mojom::DisplayCompositorRequest request, cc::mojom::DisplayCompositorClientPtrInfo client_info); void CreateGpuServiceOnGpuThread(mojom::GpuServiceRequest request, - mojom::GpuHostPtrInfo gpu_host_info); + mojom::GpuHostPtrInfo gpu_host_info, + const gpu::GpuPreferences& preferences); void BindGpuInternalOnGpuThread(mojom::GpuServiceRequest request); void TearDownOnCompositorThread();
diff --git a/services/ui/gpu/gpu_service.cc b/services/ui/gpu/gpu_service.cc index ac657e8..af091f3 100644 --- a/services/ui/gpu/gpu_service.cc +++ b/services/ui/gpu/gpu_service.cc
@@ -60,10 +60,12 @@ shutdown_event_.Signal(); } -void GpuService::InitializeWithHost(mojom::GpuHostPtr gpu_host) { +void GpuService::InitializeWithHost(mojom::GpuHostPtr gpu_host, + const gpu::GpuPreferences& preferences) { DCHECK(CalledOnValidThread()); DCHECK(!gpu_host_); gpu_host_ = std::move(gpu_host); + gpu_preferences_ = preferences; gpu_info_.video_decode_accelerator_capabilities = media::GpuVideoDecodeAccelerator::GetCapabilities(gpu_preferences_); gpu_info_.video_encode_accelerator_supported_profiles =
diff --git a/services/ui/gpu/gpu_service.h b/services/ui/gpu/gpu_service.h index f2978fe..ae45e55 100644 --- a/services/ui/gpu/gpu_service.h +++ b/services/ui/gpu/gpu_service.h
@@ -19,7 +19,6 @@ #include "gpu/ipc/service/gpu_channel_manager_delegate.h" #include "gpu/ipc/service/gpu_config.h" #include "gpu/ipc/service/x_util.h" -#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/ui/gpu/interfaces/gpu_host.mojom.h" #include "services/ui/gpu/interfaces/gpu_service.mojom.h" @@ -53,9 +52,18 @@ ~GpuService() override; - void InitializeWithHost(mojom::GpuHostPtr gpu_host); + void InitializeWithHost(mojom::GpuHostPtr gpu_host, + const gpu::GpuPreferences& preferences); void Bind(mojom::GpuServiceRequest request); + media::MediaGpuChannelManager* media_gpu_channel_manager() { + return media_gpu_channel_manager_.get(); + } + + gpu::GpuChannelManager* gpu_channel_manager() { + return gpu_channel_manager_.get(); + } + private: friend class GpuMain;
diff --git a/services/ui/gpu/interfaces/gpu_host.mojom b/services/ui/gpu/interfaces/gpu_host.mojom index b4baab5..1d2b8fb 100644 --- a/services/ui/gpu/interfaces/gpu_host.mojom +++ b/services/ui/gpu/interfaces/gpu_host.mojom
@@ -9,6 +9,8 @@ import "services/ui/gpu/interfaces/context_lost_reason.mojom"; import "url/mojo/url.mojom"; +// Communication channel from the gpu process to the gpu host. This interface +// should never have any sync function calls. interface GpuHost { DidInitialize(gpu.mojom.GpuInfo gpu_info); DidCreateOffscreenContext(url.mojom.Url url);
diff --git a/services/ui/gpu/interfaces/gpu_main.mojom b/services/ui/gpu/interfaces/gpu_main.mojom index 9b932746..985b823 100644 --- a/services/ui/gpu/interfaces/gpu_main.mojom +++ b/services/ui/gpu/interfaces/gpu_main.mojom
@@ -5,6 +5,7 @@ module ui.mojom; import "cc/ipc/display_compositor.mojom"; +import "gpu/ipc/common/gpu_preferences.mojom"; import "services/ui/gpu/interfaces/gpu_host.mojom"; import "services/ui/gpu/interfaces/gpu_service.mojom"; @@ -16,5 +17,6 @@ cc.mojom.DisplayCompositorClient display_compositor_client); CreateGpuService(GpuService& gpu_service, - GpuHost gpu_host); + GpuHost gpu_host, + gpu.mojom.GpuPreferences preferences); };
diff --git a/services/ui/ws/gpu_host.cc b/services/ui/ws/gpu_host.cc index 78304942..bfa771d 100644 --- a/services/ui/ws/gpu_host.cc +++ b/services/ui/ws/gpu_host.cc
@@ -107,8 +107,13 @@ // connector->BindInterface("gpu", &gpu_main_); gpu_main_impl_ = base::MakeUnique<GpuMain>(MakeRequest(&gpu_main_)); gpu_main_impl_->OnStart(); + + // TODO(sad): Correctly initialize gpu::GpuPreferences (like it is initialized + // in GpuProcessHost::Init()). + gpu::GpuPreferences preferences; gpu_main_->CreateGpuService(MakeRequest(&gpu_service_), - gpu_host_binding_.CreateInterfacePtrAndBind()); + gpu_host_binding_.CreateInterfacePtrAndBind(), + preferences); gpu_memory_buffer_manager_ = base::MakeUnique<ServerGpuMemoryBufferManager>( gpu_service_.get(), next_client_id_++); }
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index 1306231c..25530a5c 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -41,10 +41,7 @@ "//third_party/skia/include/utils", ] - defines = [ - "SK_IGNORE_DW_GRAY_FIX", - "SK_LEGACY_FONTMGR_FACTORY", - ] + defines = [ "SK_IGNORE_DW_GRAY_FIX" ] defines += skia_for_chromium_defines defines += []
diff --git a/skia/ext/fontmgr_default_android.cc b/skia/ext/fontmgr_default_android.cc index 668cb56..1bbd9d1d 100644 --- a/skia/ext/fontmgr_default_android.cc +++ b/skia/ext/fontmgr_default_android.cc
@@ -8,14 +8,15 @@ #include "third_party/skia/include/ports/SkFontMgr_android.h" namespace { +// An owning leaky bare pointer. SkFontMgr* g_default_fontmgr; } // namespace -SK_API void SetDefaultSkiaFactory(SkFontMgr* fontmgr) { - g_default_fontmgr = fontmgr; +SK_API void SetDefaultSkiaFactory(sk_sp<SkFontMgr> fontmgr) { + g_default_fontmgr = fontmgr.release(); } -SK_API SkFontMgr* SkFontMgr::Factory() { - return g_default_fontmgr ? SkRef(g_default_fontmgr) +SK_API sk_sp<SkFontMgr> SkFontMgr::Factory() { + return g_default_fontmgr ? sk_ref_sp(g_default_fontmgr) : SkFontMgr_New_Android(nullptr); }
diff --git a/skia/ext/fontmgr_default_android.h b/skia/ext/fontmgr_default_android.h index b774050..1dda9c6 100644 --- a/skia/ext/fontmgr_default_android.h +++ b/skia/ext/fontmgr_default_android.h
@@ -8,7 +8,8 @@ #include "third_party/skia/include/core/SkTypes.h" class SkFontMgr; +template <typename T> class sk_sp; -SK_API void SetDefaultSkiaFactory(SkFontMgr* fontmgr); +SK_API void SetDefaultSkiaFactory(sk_sp<SkFontMgr> fontmgr); #endif // SKIA_EXT_FONTMGR_DEFAULT_ANDROID_H_
diff --git a/skia/ext/fontmgr_default_linux.cc b/skia/ext/fontmgr_default_linux.cc index abb0dbe..22430e4 100644 --- a/skia/ext/fontmgr_default_linux.cc +++ b/skia/ext/fontmgr_default_linux.cc
@@ -13,13 +13,14 @@ SkFontMgr* g_default_fontmgr; } // namespace -void SetDefaultSkiaFactory(SkFontMgr* fontmgr) { - g_default_fontmgr = fontmgr; +void SetDefaultSkiaFactory(sk_sp<SkFontMgr> fontmgr) { + SkASSERT(g_default_fontmgr == nullptr); + g_default_fontmgr = fontmgr.release(); } -SK_API SkFontMgr* SkFontMgr::Factory() { +SK_API sk_sp<SkFontMgr> SkFontMgr::Factory() { if (g_default_fontmgr) { - return SkRef(g_default_fontmgr); + return sk_ref_sp(g_default_fontmgr); } sk_sp<SkFontConfigInterface> fci(SkFontConfigInterface::RefGlobal()); return fci ? SkFontMgr_New_FCI(std::move(fci)) : nullptr;
diff --git a/skia/ext/fontmgr_default_linux.h b/skia/ext/fontmgr_default_linux.h index b0ab6e78..29420074 100644 --- a/skia/ext/fontmgr_default_linux.h +++ b/skia/ext/fontmgr_default_linux.h
@@ -8,7 +8,8 @@ #include "third_party/skia/include/core/SkTypes.h" class SkFontMgr; +template <typename T> class sk_sp; -void SK_API SetDefaultSkiaFactory(SkFontMgr* fontmgr); +void SK_API SetDefaultSkiaFactory(sk_sp<SkFontMgr> fontmgr); #endif // SKIA_EXT_FONTMGR_DEFAULT_LINUX_H_
diff --git a/skia/ext/fontmgr_default_win.cc b/skia/ext/fontmgr_default_win.cc index 3b1031f..6c451fa 100644 --- a/skia/ext/fontmgr_default_win.cc +++ b/skia/ext/fontmgr_default_win.cc
@@ -9,19 +9,21 @@ namespace { +// This is a leaky bare owning pointer. SkFontMgr* g_default_fontmgr; } // namespace -void SetDefaultSkiaFactory(SkFontMgr* fontmgr) { - g_default_fontmgr = fontmgr; +void SetDefaultSkiaFactory(sk_sp<SkFontMgr> fontmgr) { + SkASSERT(g_default_fontmgr == nullptr); + g_default_fontmgr = fontmgr.release(); } -SK_API SkFontMgr* SkFontMgr::Factory() { +SK_API sk_sp<SkFontMgr> SkFontMgr::Factory() { // This will be set when DirectWrite is in use, and an SkFontMgr has been // created with the pre-sandbox warmed up one. Otherwise, we fallback to a // GDI SkFontMgr which is used in the browser. if (g_default_fontmgr) - return SkRef(g_default_fontmgr); + return sk_ref_sp(g_default_fontmgr); return SkFontMgr_New_GDI(); }
diff --git a/skia/ext/fontmgr_default_win.h b/skia/ext/fontmgr_default_win.h index cea72c1b..a41d94ad 100644 --- a/skia/ext/fontmgr_default_win.h +++ b/skia/ext/fontmgr_default_win.h
@@ -8,7 +8,8 @@ #include "third_party/skia/include/core/SkTypes.h" class SkFontMgr; +template <typename T> class sk_sp; -void SK_API SetDefaultSkiaFactory(SkFontMgr* fontmgr); +void SK_API SetDefaultSkiaFactory(sk_sp<SkFontMgr> fontmgr); #endif // SKIA_EXT_FONTMGR_DEFAULT_WIN_H_
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index af896f0..2cfec2b 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -98243,6 +98243,25 @@ "Win 7 Intel GPU Perf": { "isolated_scripts": [ { + "args": [], + "isolate_name": "angle_perftests", + "name": "angle_perftests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:041a", + "id": "build166-m1", + "os": "Windows-2008ServerR2-SP1", + "pool": "Chrome-perf" + } + ], + "expiration": 21600, + "hard_timeout": 7200, + "io_timeout": 3600 + } + }, + { "args": [ "battor.power_cases", "-v", @@ -100979,6 +100998,25 @@ } }, { + "args": [], + "isolate_name": "load_library_perf_tests", + "name": "load_library_perf_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:041a", + "id": "build166-m1", + "os": "Windows-2008ServerR2-SP1", + "pool": "Chrome-perf" + } + ], + "expiration": 21600, + "hard_timeout": 7200, + "io_timeout": 3600 + } + }, + { "args": [ "loading.cluster_telemetry", "-v", @@ -102860,6 +102898,25 @@ } }, { + "args": [], + "isolate_name": "performance_browser_tests", + "name": "performance_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:041a", + "id": "build166-m1", + "os": "Windows-2008ServerR2-SP1", + "pool": "Chrome-perf" + } + ], + "expiration": 21600, + "hard_timeout": 7200, + "io_timeout": 3600 + } + }, + { "args": [ "power.android_acceptance", "-v",
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation index fd45f85e..eaa5322 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
@@ -41,9 +41,6 @@ crbug.com/551000 http/tests/inspector/network/network-initiator.html [ Failure ] crbug.com/551000 virtual/mojo-loading/http/tests/inspector/network/network-document-initiator.html [ Failure ] crbug.com/551000 virtual/mojo-loading/http/tests/inspector/network/network-initiator.html [ Failure ] -# We are missing several parameters in network har reports. -crbug.com/551000 http/tests/inspector/resource-parameters.html [ Failure ] -crbug.com/551000 virtual/mojo-loading/http/tests/inspector/resource-parameters.html [ Failure ] # Duplicate started loading output. crbug.com/551000 inspector-protocol/page/frameAttachedDetached.html [ Failure ] crbug.com/551000 inspector-protocol/page/frameStartedLoading.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests index 673f204..cd0c1216 100644 --- a/third_party/WebKit/LayoutTests/SlowTests +++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -114,8 +114,8 @@ webkit.org/b/90488 [ Debug ] virtual/mojo-loading/http/tests/inspector-enabled/ [ Slow ] webkit.org/b/90488 [ Debug ] inspector-protocol/ [ Slow ] crbug.com/451577 inspector/console [ Slow ] -crbug.com/451577 [ Win ] http/tests/inspector/network/network-datareceived.html [ Slow ] -crbug.com/451577 [ Win ] virtual/mojo-loading/http/tests/inspector/network/network-datareceived.html [ Slow ] +crbug.com/679833 http/tests/inspector/network/network-datareceived.html [ Slow ] +crbug.com/679833 virtual/mojo-loading/http/tests/inspector/network/network-datareceived.html [ Slow ] # Debugger and profiler tests are slow in Release as well. crbug.com/450493 inspector/sources/ [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-constructor.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-constructor.html new file mode 100644 index 0000000..3ec49e4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-constructor.html
@@ -0,0 +1,6 @@ +<!DOCTYPE html> +<body> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="resources/canvas-Float32ImageData.js"></script> +</body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-workers.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-workers.html new file mode 100644 index 0000000..b3c97567 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-workers.html
@@ -0,0 +1,6 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script> +fetch_tests_from_worker(new Worker("resources/canvas-Float32ImageData-workers.js")); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-constructor-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-constructor-expected.txt index f1b473d..77d93449 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-constructor-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-constructor-expected.txt
@@ -18,16 +18,16 @@ PASS new ImageData(1 << 31, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range.. PASS new ImageData(new Uint8ClampedArray(0)) threw exception TypeError: Failed to construct 'ImageData': 2 arguments required, but only 1 present.. PASS new ImageData(new Uint8Array(100), 25) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number.. -PASS new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of 4.. -PASS new ImageData(new Uint8ClampedArray(28), 7, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not equal to (4 * width * height).. -PASS new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width).. +PASS new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of 4.. +PASS new ImageData(new Uint8ClampedArray(28), 7, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source height is zero or not a number.. +PASS new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of (4 * width).. PASS new ImageData(self, 4, 4) threw exception TypeError: Failed to construct 'ImageData': parameter 1 is not of type 'Uint8ClampedArray'.. PASS new ImageData(null, 4, 4) threw exception TypeError: Failed to construct 'ImageData': parameter 1 is not of type 'Uint8ClampedArray'.. PASS new ImageData(imageData.data, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number.. -PASS new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width).. -PASS new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width).. +PASS new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of (4 * width).. +PASS new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range.. PASS new ImageData(imageData.data, 'biggish') threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number.. -PASS new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width).. +PASS new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range.. PASS (new ImageData(new Uint8ClampedArray(28), 7)).height is 1 PASS imageDataFromData.width is 100 PASS imageDataFromData.height is 50
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-workers-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-workers-expected.txt index 51185d7..8f444dd 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-workers-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-workers-expected.txt
@@ -19,16 +19,16 @@ PASS [Worker] new ImageData(1 << 31, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range.. PASS [Worker] new ImageData(new Uint8ClampedArray(0)) threw exception TypeError: Failed to construct 'ImageData': 2 arguments required, but only 1 present.. PASS [Worker] new ImageData(new Uint8Array(100), 25) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number.. -PASS [Worker] new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of 4.. -PASS [Worker] new ImageData(new Uint8ClampedArray(28), 7, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not equal to (4 * width * height).. -PASS [Worker] new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width).. +PASS [Worker] new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of 4.. +PASS [Worker] new ImageData(new Uint8ClampedArray(28), 7, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source height is zero or not a number.. +PASS [Worker] new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of (4 * width).. PASS [Worker] new ImageData(self, 4, 4) threw exception TypeError: Failed to construct 'ImageData': parameter 1 is not of type 'Uint8ClampedArray'.. PASS [Worker] new ImageData(null, 4, 4) threw exception TypeError: Failed to construct 'ImageData': parameter 1 is not of type 'Uint8ClampedArray'.. PASS [Worker] new ImageData(imageData.data, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number.. -PASS [Worker] new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width).. -PASS [Worker] new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width).. +PASS [Worker] new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of (4 * width).. +PASS [Worker] new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range.. PASS [Worker] new ImageData(imageData.data, 'biggish') threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number.. -PASS [Worker] new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width).. +PASS [Worker] new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range.. PASS [Worker] (new ImageData(new Uint8ClampedArray(28), 7)).height is 1 PASS [Worker] imageDataFromData.width is 100 PASS [Worker] imageDataFromData.height is 50
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/color-space/float32ImageData-colorSpace.html b/third_party/WebKit/LayoutTests/fast/canvas/color-space/float32ImageData-colorSpace.html new file mode 100644 index 0000000..5731c30 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/color-space/float32ImageData-colorSpace.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<body> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script> + +// RGBA(255,0,0,255) -> LinearRGB(0x3c00, 0x0, 0x0, 0x3c00) +var data = new Float32Array([0x00003c00, 0x0, 0x0, 0x00003c00]); + +test(function() { + + assert_equals((new Float32ImageData(1, 1)).colorSpace, "linear-rgb", "The default color space for Float32ImageData is linear-rgb."); + assert_equals((new Float32ImageData(1, 1, "linear-rgb")).colorSpace, "linear-rgb", "The color space read from Float32ImageData is the one that was set."); + assert_throws("NotSupportedError", function() {fImageData = new Float32ImageData(1, 1, "legacy-srgb");}, "Legacy SRGB is not supported in Float32ImageData."); + assert_throws("NotSupportedError", function() {fImageData = new Float32ImageData(1, 1, "srgb");}, "SRGB is not supported in Float32ImageData."); + assert_throws(null, function() {fImageData = new Float32ImageData(1, 1, "undefined");}, "Only members of ImageDataColorSpace enum are processed in Float32ImageData constructor."); + + assert_equals((new Float32ImageData(data, 1, 1)).colorSpace, "linear-rgb", "The default color space for Float32ImageData is linear-rgb."); + assert_equals((new Float32ImageData(data, 1, 1, "linear-rgb")).colorSpace, "linear-rgb", "The color space read from Float32ImageData is the one that was set."); + assert_throws("NotSupportedError", function() {fImageData = new Float32ImageData(data, 1, 1, "legacy-srgb");}, "Legacy SRGB is not supported in Float32ImageData."); + assert_throws("NotSupportedError", function() {fImageData = new Float32ImageData(data, 1, 1, "srgb");}, "SRGB is not supported in Float32ImageData."); + assert_throws(null, function() {fImageData = new Float32ImageData(data, 1, 1, "undefined");}, "Only members of ImageDataColorSpace enum are processed in Float32ImageData constructor."); + +}, 'This test examines the correct behavior of Float32ImageData API in setting and getting ImageDataColorSpace.'); + +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/color-space/imageData-colorSpace.html b/third_party/WebKit/LayoutTests/fast/canvas/color-space/imageData-colorSpace.html new file mode 100644 index 0000000..a170bc6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/color-space/imageData-colorSpace.html
@@ -0,0 +1,49 @@ +<!DOCTYPE html> +<body> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script> + +var data = new Uint8ClampedArray([255, 0, 0, 255]); + +function createImageDataAndGetColorSpace(colorSpace) { + experimental = new ImageData(1,1); + imageData = experimental.createImageData(1, 1, colorSpace) + return imageData.colorSpace; +} + +function createWithDataAndGetColorSpaceW(colorSpace) { + experimental = new ImageData(1,1); + imageData = experimental.createImageData(data, 1, colorSpace) + return imageData.colorSpace; +} + +function createWithDataAndGetColorSpaceWH(colorSpace) { + experimental = new ImageData(1,1); + imageData = experimental.createImageData(data, 1, 1, colorSpace) + return imageData.colorSpace; +} + +test(function() { + assert_equals((new ImageData(1,1)).colorSpace, "legacy-srgb", "The default color space for ImageData is legacy-srgb."); + assert_equals(createImageDataAndGetColorSpace("legacy-srgb"), "legacy-srgb", "The color space read from ImageData is the one that was set."); + assert_equals(createImageDataAndGetColorSpace("srgb"), "srgb", "The color space read from ImageData is the one that was set."); + assert_throws("NotSupportedError", function() {createImageDataAndGetColorSpace("linear-rgb");}, "Linear RGB is not supported in ImageData."); + assert_throws(null, function() {createImageDataAndGetColorSpace("undefined");}, "Only members of ImageDataColorSpace enum are processed in ImageData constructor."); + + assert_equals((new ImageData(data,1)).colorSpace, "legacy-srgb", "The default color space for ImageData is legacy-srgb."); + assert_equals(createWithDataAndGetColorSpaceW("legacy-srgb"), "legacy-srgb", "The color space read from ImageData is the one that was set."); + assert_equals(createWithDataAndGetColorSpaceW("srgb"), "srgb", "The color space read from ImageData is the one that was set."); + assert_throws("NotSupportedError", function() {createWithDataAndGetColorSpaceW("linear-rgb");}, "Linear RGB is not supported in ImageData."); + assert_throws(null, function() {createWithDataAndGetColorSpaceW("undefined");}, "Only members of ImageDataColorSpace enum are processed in ImageData constructor."); + + assert_equals((new ImageData(data,1, 1)).colorSpace, "legacy-srgb", "The default color space for ImageData is legacy-srgb."); + assert_equals(createWithDataAndGetColorSpaceWH("legacy-srgb"), "legacy-srgb", "The color space read from ImageData is the one that was set."); + assert_equals(createWithDataAndGetColorSpaceWH("srgb"), "srgb", "The color space read from ImageData is the one that was set."); + assert_throws("NotSupportedError", function() {createWithDataAndGetColorSpaceWH("linear-rgb");}, "Linear RGB is not supported in ImageData."); + assert_throws(null, function() {createWithDataAndGetColorSpaceWH("undefined");}, "Only members of ImageDataColorSpace enum are processed in ImageData constructor."); + +}, 'This test examines the correct behavior of createImageData API in setting and getting ImageData.colorSpace.'); + +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData-workers.js b/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData-workers.js new file mode 100644 index 0000000..7c872b55 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData-workers.js
@@ -0,0 +1,2 @@ +importScripts('../../../resources/testharness.js', 'canvas-Float32ImageData.js'); +done();
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData.js b/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData.js new file mode 100644 index 0000000..838297b0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData.js
@@ -0,0 +1,121 @@ +function setF16Color(float32ImageData, i, f16Color) { + var s = i * 4; + float32ImageData[s] = f16Color[0]; + float32ImageData[s + 1] = f16Color[1]; + float32ImageData[s + 2] = f16Color[2]; + float32ImageData[s + 3] = f16Color[3]; +} + +function getF16Color(float32ImageData, i) { + var result = []; + var s = i * 4; + for (var j = 0; j < 4; j++) { + result[j] = float32ImageData[s + j]; + } + return result; +} + +function compareF16Colors(f16Color1, f16Color2) { + for (var j = 0; j < 4; j++) + if (f16Color1[j] != f16Color2[j]) + return false; + return true; +} + +test(function() { + + float32ImageData = new Float32ImageData(100, 50); + assert_equals(float32ImageData.width, 100, + "The width of the float32ImageData should be the width we passed to the constructor."); + assert_equals(float32ImageData.height, 50, + "The height of the float32ImageData should be the height we passed to the constructor."); + + var f16ColorData = getF16Color(float32ImageData.data, 4); + assert_equals(f16ColorData[0], 0, + "The default ImageData color is transparent black."); + assert_equals(f16ColorData[1], 0, + "The default ImageData color is transparent black."); + assert_equals(f16ColorData[2], 0, + "The default ImageData color is transparent black."); + assert_equals(f16ColorData[3], 0, + "The default ImageData color is transparent black."); + + var testColor = new Float32Array([0x00003c00, 0x00003c01, 0x00003c02, 0x00003c03]); + setF16Color(float32ImageData.data, 4, testColor); + f16ColorData = getF16Color(float32ImageData.data, 4); + assert_equals(f16ColorData[0], 0x00003c00, + "The red component of f16 color is the value we set."); + assert_equals(f16ColorData[1], 0x00003c01, + "The green component of f16 color is the value we set."); + assert_equals(f16ColorData[2], 0x00003c02, + "The blue component of f16 color is the value we set."); + assert_equals(f16ColorData[3], 0x00003c03, + "The alpha component of f16 color is the value we set."); + + assert_throws(null, function() {new Float32ImageData(10);}, + "Float32ImageData constructor requires both width and height."); + assert_throws("IndexSizeError", function() {new Float32ImageData(0,10);}, + "Float32ImageData width must be greater than zero."); + assert_throws("IndexSizeError", function() {new Float32ImageData(10,0);}, + "Float32ImageData height must be greater than zero."); + assert_throws("IndexSizeError", function() {new Float32ImageData('width', 'height');}, + "Float32ImageData width and height must be numbers."); + assert_throws("IndexSizeError", function() {new Float32ImageData(1 << 31, 1 << 31);}, + "Float32ImageData width multiplied by height must be less than 2^30 to avoid buffer size overflow."); + + assert_throws(null, function() {new Float32ImageData(new Float32Array(0));}, + "The Float32Array passed to the constructor cannot have a length of zero."); + assert_throws("IndexSizeError", function() {new Float32ImageData(new Float32Array(27), 2);}, + "The size of Float32Array passed to the constructor must be divisible by 4 * width."); + assert_throws("IndexSizeError", function() {new Float32ImageData(new Float32Array(28), 7, 0);}, + "The size of Float32Array passed to the constructor must be equal to 4 * width * height."); + assert_throws(null, function() {new Float32ImageData(self, 4, 4);}, + "The object passed to the constructor as data array should be of type Float32Array."); + assert_throws(null, function() {new Float32ImageData(null, 4, 4);}, + "The object passed to the constructor as data array should be of type Float32Array."); + assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 0);}, + "The size of Float32Array passed to the constructor must be divisible by 4 * width."); + assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 13);}, + "The size of Float32Array passed to the constructor must be divisible by 4 * width."); + assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 1 << 31);}, + "The size of Float32Array passed to the constructor must be divisible by 4 * width."); + assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 'biggish');}, + "The width parameter must be a number."); + assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 1 << 24, 1 << 31);}, + "Float32ImageData width multiplied by height must be less than 2^30 to avoid buffer size overflow."); + assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 1 << 31, 1 << 24);}, + "Float32ImageData width multiplied by height must be less than 2^30 to avoid buffer size overflow."); + assert_equals((new Float32ImageData(new Float32Array(28), 7)).height, 1, + "The height must be equal to size of the data array divided by 4 * width."); + + float32ImageDataFromData = new Float32ImageData(float32ImageData.data, 100); + assert_equals(float32ImageDataFromData.width, 100, + "The width of the float32ImageDataFromData should be the same as that of float32ImageData."); + assert_equals(float32ImageDataFromData.height, 50, + "The height of the float32ImageDataFromData should be the same as that of float32ImageData."); + assert_true(float32ImageDataFromData.data == float32ImageData.data, + "The pixel data buffer of float32ImageDataFromData should be the same as that of float32ImageData."); + assert_true(compareF16Colors(getF16Color(float32ImageDataFromData.data, 10), + getF16Color(float32ImageData.data, 10)), + "The color of a pixel from float32ImageDataFromData should be the same as that of float32ImageData."); + setF16Color(float32ImageData.data, 10, testColor); + assert_true(compareF16Colors(getF16Color(float32ImageDataFromData.data, 10), + getF16Color(float32ImageData.data, 10)), + "Setting the color of a pixel from float32ImageData must cascade to the same pixel of float32ImageDataFromData."); + + var data = new Float32Array(400); + data[22] = 129; + float32ImageDataFromData = new Float32ImageData(data, 20, 5); + assert_equals(float32ImageDataFromData.width, 20, + "The width of the float32ImageData should be the width we passed to the constructor."); + assert_equals(float32ImageDataFromData.height, 5, + "The height of the Float32ImageData must be equal to size of the Float32Array divided by 4 * width."); + assert_true(float32ImageDataFromData.data == data, + "The pixel data buffer of float32ImageDataFromData should be the same buffer passed to the constructor."); + assert_true(compareF16Colors(getF16Color(float32ImageDataFromData.data, 2), getF16Color(data, 2)), + "The pixel data of float32ImageDataFromData should be the same as that of the buffer passed to the constructor."); + setF16Color(float32ImageDataFromData.data, 2, testColor); + assert_true(compareF16Colors(getF16Color(float32ImageDataFromData.data, 2), getF16Color(data, 2)), + "Setting the color of a pixel from float32ImageDataFromData must cascade to the same pixel of the buffer passed to the constructor."); + +}, 'This test examines the correct behavior of Float32ImageData API.');
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 27de9fc2..bfb9fb2 100644 --- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -240,6 +240,12 @@ method readAsBinaryString method readAsDataURL method readAsText +interface Float32ImageData + getter colorSpace + getter data + getter height + getter width + method constructor interface ForeignFetchEvent : ExtendableEvent getter origin getter request @@ -406,9 +412,12 @@ method close method constructor interface ImageData + getter colorSpace + getter data getter height getter width method constructor + method createImageData interface InstallEvent : ExtendableEvent method constructor method registerForeignFetch
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-exceptions-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-exceptions-expected.txt index db19d841..2712ad3 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-exceptions-expected.txt +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-exceptions-expected.txt
@@ -10,7 +10,7 @@ FAIL [[Delete]] Should throw on cross-origin objects assert_throws: Can't delete cross-origin indexed property function "function () { delete C[0]; }" did not throw FAIL [[DefineOwnProperty]] Should throw for cross-origin objects assert_throws: Can't define cross-origin value property length function "function () { Object.defineProperty(obj, prop, valueDesc); }" did not throw FAIL [[Enumerate]] should return an empty iterator assert_unreached: Shouldn't have been able to enumerate stop on cross-origin Window Reached unreachable code -FAIL [[OwnPropertyKeys]] should return all properties from cross-origin objects assert_array_equals: Object.getOwnPropertyNames() gives the right answer for cross-origin Window lengths differ, expected 873 got 13 +FAIL [[OwnPropertyKeys]] should return all properties from cross-origin objects assert_array_equals: Object.getOwnPropertyNames() gives the right answer for cross-origin Window lengths differ, expected 874 got 13 PASS A and B jointly observe the same identity for cross-origin Window and Location PASS Cross-origin functions get local Function.prototype FAIL Cross-origin Window accessors get local Function.prototype Cannot read property 'name' of undefined
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt index ff2e741..f7d6294 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -149,6 +149,7 @@ getter minValue getter value method cancelScheduledValues + method cancelValuesAndHoldAtTime method constructor method exponentialRampToValueAtTime method linearRampToValueAtTime @@ -3016,6 +3017,8 @@ method transferFromImageBitmap interface ImageData attribute @@toStringTag + getter colorSpace + getter data getter height getter width method constructor
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.png index e6cdd360..df18a23 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.txt index 916eb419..66f7e2f 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.txt
@@ -54,11 +54,11 @@ layer at (0,0) size 295x295 LayoutSVGRoot {svg} at (0,0) size 295x295 LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 - LayoutSVGRect {rect} at (0,0) size 295x295 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00] - LayoutSVGEllipse {circle} at (0,0) size 295x295 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00] - LayoutSVGContainer {g} at (44,92) size 207x119 - LayoutSVGText {text} at (29,62) size 141x81 contains 1 chunk(s) - LayoutSVGInlineText {#text} at (0,0) size 141x80 + LayoutSVGRect {rect} at (-3000,-1000) size 6200x2200 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00] + LayoutSVGEllipse {circle} at (0,0) size 200x200 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00] + LayoutSVGContainer {g} at (29.97,62.64) size 140.03x80 + LayoutSVGText {text} at (29.97,62.64) size 140.03x80 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (29.97,62.64) size 140.03x80 chunk 1 (middle anchor) text run 1 at (29.98,125.00) startOffset 0 endOffset 3 width 140.03: "SVG" layer at (347,242) size 147x148 LayoutEmbeddedObject {object} at (299.59,147) size 147.58x147.58 [bgcolor=#FF0000] @@ -67,11 +67,11 @@ layer at (0,0) size 148x148 LayoutSVGRoot {svg} at (0,0) size 148x148 LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 - LayoutSVGRect {rect} at (0,0) size 148x148 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00] - LayoutSVGEllipse {circle} at (0,0) size 148x148 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00] - LayoutSVGContainer {g} at (22,45) size 104x61 - LayoutSVGText {text} at (29,61) size 141x82 contains 1 chunk(s) - LayoutSVGInlineText {#text} at (0,0) size 141x82 + LayoutSVGRect {rect} at (-3000,-1000) size 6200x2200 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00] + LayoutSVGEllipse {circle} at (0,0) size 200x200 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00] + LayoutSVGContainer {g} at (29.97,61.50) size 140.03x81.08 + LayoutSVGText {text} at (29.97,61.50) size 140.03x81.08 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (29.97,61.50) size 140.03x81.08 chunk 1 (middle anchor) text run 1 at (29.98,125.00) startOffset 0 endOffset 3 width 140.03: "SVG" layer at (499,316) size 73x74 LayoutEmbeddedObject {object} at (451.61,221) size 73.78x73.78 [bgcolor=#FF0000] @@ -80,11 +80,11 @@ layer at (0,0) size 74x74 LayoutSVGRoot {svg} at (0,0) size 74x74 LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 - LayoutSVGRect {rect} at (0,0) size 74x74 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00] - LayoutSVGEllipse {circle} at (0,0) size 74x74 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00] - LayoutSVGContainer {g} at (11,23) size 52x30 - LayoutSVGText {text} at (29,62) size 141x80 contains 1 chunk(s) - LayoutSVGInlineText {#text} at (0,0) size 141x79 + LayoutSVGRect {rect} at (-3000,-1000) size 6200x2200 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00] + LayoutSVGEllipse {circle} at (0,0) size 200x200 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00] + LayoutSVGContainer {g} at (29.97,62.84) size 140.03x78.38 + LayoutSVGText {text} at (29.97,62.84) size 140.03x78.38 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (29.97,62.84) size 140.03x78.38 chunk 1 (middle anchor) text run 1 at (29.98,125.00) startOffset 0 endOffset 3 width 140.03: "SVG" layer at (577,353) size 37x37 LayoutEmbeddedObject {object} at (529.83,258) size 36.89x36.89 [bgcolor=#FF0000] @@ -93,9 +93,9 @@ layer at (0,0) size 37x37 LayoutSVGRoot {svg} at (0,0) size 37x37 LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 - LayoutSVGRect {rect} at (0,0) size 37x37 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00] - LayoutSVGEllipse {circle} at (0,0) size 37x37 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00] - LayoutSVGContainer {g} at (5,11) size 27x16 - LayoutSVGText {text} at (29,60) size 141x82 contains 1 chunk(s) - LayoutSVGInlineText {#text} at (0,0) size 141x82 + LayoutSVGRect {rect} at (-3000,-1000) size 6200x2200 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00] + LayoutSVGEllipse {circle} at (0,0) size 200x200 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00] + LayoutSVGContainer {g} at (29.97,60.14) size 140.03x81.08 + LayoutSVGText {text} at (29.97,60.14) size 140.03x81.08 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (29.97,60.14) size 140.03x81.08 chunk 1 (middle anchor) text run 1 at (29.98,125.00) startOffset 0 endOffset 3 width 140.03: "SVG"
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt index ff2e741..f7d6294 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -149,6 +149,7 @@ getter minValue getter value method cancelScheduledValues + method cancelValuesAndHoldAtTime method constructor method exponentialRampToValueAtTime method linearRampToValueAtTime @@ -3016,6 +3017,8 @@ method transferFromImageBitmap interface ImageData attribute @@toStringTag + getter colorSpace + getter data getter height getter width method constructor
diff --git a/third_party/WebKit/LayoutTests/svg/animations/resources/set-foo.js b/third_party/WebKit/LayoutTests/svg/animations/resources/set-foo.js new file mode 100644 index 0000000..131d881 --- /dev/null +++ b/third_party/WebKit/LayoutTests/svg/animations/resources/set-foo.js
@@ -0,0 +1 @@ +foo = 1337;
diff --git a/third_party/WebKit/LayoutTests/svg/animations/script-href-no-animate.html b/third_party/WebKit/LayoutTests/svg/animations/script-href-no-animate.html new file mode 100644 index 0000000..483cdfd1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/svg/animations/script-href-no-animate.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>SVGScriptElement.href should not be animatable</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script> +var foo = 42; + +async_test(t => { + window.onload = () => { + var s = document.createElementNS('http://www.w3.org/2000/svg', 'script'); + s.onload = t.unreached_func('Should not get a load event'); + s.id = 'x'; + document.querySelector('svg').appendChild(s); + requestAnimationFrame(_ => { + requestAnimationFrame(t.step_func_done(_ => { + assert_equals(foo, 42); + })); + }); + }; +}); +</script> +<svg xmlns:xlink="http://www.w3.org/1999/xlink"> + <set href="#x" attributeName="href" to="resources/set-foo.js"/> + <set href="#x" attributeName="xlink:href" to="resources/set-foo.js"/> + <animate href="#x" attributeName="href" to="resources/set-foo.js" dur="0.01s"/> + <animate href="#x" attributeName="xlink:href" to="resources/set-foo.js" dur="0.01s"/> +</svg>
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index f7ca39b..eae06c6 100644 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -241,6 +241,12 @@ method readAsBinaryString method readAsDataURL method readAsText +interface Float32ImageData + getter colorSpace + getter data + getter height + getter width + method constructor interface ForeignFetchEvent : ExtendableEvent getter origin getter request @@ -407,9 +413,12 @@ method close method constructor interface ImageData + getter colorSpace + getter data getter height getter width method constructor + method createImageData interface InstallEvent : ExtendableEvent method constructor method registerForeignFetch
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 2452562e..179caa5 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -368,6 +368,8 @@ method close method constructor interface ImageData + getter colorSpace + getter data getter height getter width method constructor
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt index 02dde09..d859f5d 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -387,6 +387,8 @@ [Worker] method constructor [Worker] interface ImageData [Worker] attribute @@toStringTag +[Worker] getter colorSpace +[Worker] getter data [Worker] getter height [Worker] getter width [Worker] method constructor
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt index 88ea189..8487d96 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -149,6 +149,7 @@ getter minValue getter value method cancelScheduledValues + method cancelValuesAndHoldAtTime method constructor method exponentialRampToValueAtTime method linearRampToValueAtTime @@ -3077,6 +3078,8 @@ method transferFromImageBitmap interface ImageData attribute @@toStringTag + getter colorSpace + getter data getter height getter width method constructor
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt index ebb785d..c644e8f 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -382,6 +382,8 @@ [Worker] method constructor [Worker] interface ImageData [Worker] attribute @@toStringTag +[Worker] getter colorSpace +[Worker] getter data [Worker] getter height [Worker] getter width [Worker] method constructor
diff --git a/third_party/WebKit/LayoutTests/webaudio/AudioParam/audioparam-cancel-and-hold.html b/third_party/WebKit/LayoutTests/webaudio/AudioParam/audioparam-cancel-and-hold.html new file mode 100644 index 0000000..2e64ed08 --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/AudioParam/audioparam-cancel-and-hold.html
@@ -0,0 +1,516 @@ +<!doctype html> +<html> + <head> + <script src="../../resources/testharness.js"></script> + <script src="../../resources/testharnessreport.js"></script> + <script src="../resources/audit-util.js"></script> + <script src="../resources/audit.js"></script> + <title>Test CancelValuesAndHoldAtTime</title> + </head> + + <body> + <script> + let sampleRate = 48000; + let renderDuration = 0.5; + + let audit = Audit.createTaskRunner(); + + // The first few tasks test the cancellation of each relevant automation + // function. For the test, a simple linear ramp from 0 to 1 is used to + // start things off. Then the automation to be tested is scheduled and + // cancelled. + + audit.define("linear", function (task, should) { + task.describe("Cancel linearRampToValueAtTime"); + cancelTest(should, linearRampTest("linearRampToValueAtTime"), { + valueThreshold: 8.3998e-5, + curveThreshold: 0 + }).then(task.done.bind(task)); + }); + + audit.define("exponential", function (task, should) { + task.describe("Cancel exponentialRampAtTime"); + // Cancel an exponential ramp. The thresholds are experimentally + // determined. + cancelTest(should, function (g, v0, t0, cancelTime) { + // Initialize values to 0. + g[0].gain.setValueAtTime(0, 0); + g[1].gain.setValueAtTime(0, 0); + // Schedule a short linear ramp to start things off. + g[0].gain.linearRampToValueAtTime(v0, t0); + g[1].gain.linearRampToValueAtTime(v0, t0); + + // After the linear ramp, schedule an exponential ramp to the end. + // (This is the event that will be be cancelled.) + let v1 = 0.001; + let t1 = renderDuration; + + g[0].gain.exponentialRampToValueAtTime(v1, t1); + g[1].gain.exponentialRampToValueAtTime(v1, t1); + + expectedConstant = Math.fround(v0 * Math.pow(v1 / v0, ( + cancelTime - + t0) / (t1 - t0))); + return { + expectedConstant: expectedConstant, + autoMessage: "exponentialRampToValue(" + v1 + ", " + t1 + ")", + summary: "exponentialRampToValueAtTime", + }; + }, { + valueThreshold: 1.8664e-6, + curveThreshold: 5.9605e-8 + }).then(task.done.bind(task)); + }); + + audit.define("setTarget", function (task, should) { + task.describe("Cancel setTargetAtTime"); + // Cancel a setTarget event. + cancelTest(should, function (g, v0, t0, cancelTime) { + // Initialize values to 0. + g[0].gain.setValueAtTime(0, 0); + g[1].gain.setValueAtTime(0, 0); + // Schedule a short linear ramp to start things off. + g[0].gain.linearRampToValueAtTime(v0, t0); + g[1].gain.linearRampToValueAtTime(v0, t0); + + // At the end of the linear ramp, schedule a setTarget. (This is the + // event that will be cancelled.) + let v1 = 0; + let t1 = t0; + let timeConstant = 0.05; + + g[0].gain.setTargetAtTime(v1, t1, timeConstant); + g[1].gain.setTargetAtTime(v1, t1, timeConstant); + + expectedConstant = Math.fround(v1 + (v0 - v1) * Math.exp(-( + cancelTime - t0) / timeConstant)); + return { + expectedConstant: expectedConstant, + autoMessage: "setTargetAtTime(" + v1 + ", " + t1 + ", " + + timeConstant + ")", + summary: "setTargetAtTime", + }; + }, { + valueThreshold: 4.5267e-7, //1.1317e-7, + curveThreshold: 0 + }).then(task.done.bind(task)); + }); + + audit.define("setValueCurve", function (task, should) { + task.describe("Cancel setValueCurveAtTime"); + // Cancel a setValueCurve event. + cancelTest(should, function (g, v0, t0, cancelTime) { + // Initialize values to 0. + g[0].gain.setValueAtTime(0, 0); + g[1].gain.setValueAtTime(0, 0); + // Schedule a short linear ramp to start things off. + g[0].gain.linearRampToValueAtTime(v0, t0); + g[1].gain.linearRampToValueAtTime(v0, t0); + + // After the linear ramp, schedule a setValuesCurve. (This is the + // event that will be cancelled.) + let v1 = 0; + let duration = renderDuration - t0; + + // For simplicity, a 2-point curve so we get a linear interpolated result. + let curve = Float32Array.from([v0, 0]); + + g[0].gain.setValueCurveAtTime(curve, t0, duration); + g[1].gain.setValueCurveAtTime(curve, t0, duration); + + let index = Math.floor((curve.length - 1) / duration * ( + cancelTime - t0)); + + let curvePointsPerFrame = (curve.length - 1) / duration / + sampleRate; + let virtualIndex = (cancelTime - t0) * sampleRate * + curvePointsPerFrame; + + let delta = virtualIndex - index; + expectedConstant = curve[0] + (curve[1] - curve[0]) * delta; + return { + expectedConstant: expectedConstant, + autoMessage: "setValueCurveAtTime([" + curve + "], " + t0 + + ", " + duration + + ")", + summary: "setValueCurveAtTime", + }; + }, { + valueThreshold: 9.5368e-9, + curveThreshold: 0 + }).then(task.done.bind(task)); + }); + + audit.define("setValueCurve after end", function (task, should) { + task.describe("Cancel setValueCurveAtTime after the end"); + cancelTest(should, function (g, v0, t0, cancelTime) { + // Initialize values to 0. + g[0].gain.setValueAtTime(0, 0); + g[1].gain.setValueAtTime(0, 0); + // Schedule a short linear ramp to start things off. + g[0].gain.linearRampToValueAtTime(v0, t0); + g[1].gain.linearRampToValueAtTime(v0, t0); + + // After the linear ramp, schedule a setValuesCurve. (This is the + // event that will be cancelled.) Make sure the curve ends before the + // cancellation time. + let v1 = 0; + let duration = cancelTime - t0 - 0.125; + + // For simplicity, a 2-point curve so we get a linear interpolated + // result. + let curve = Float32Array.from([v0, 0]); + + g[0].gain.setValueCurveAtTime(curve, t0, duration); + g[1].gain.setValueCurveAtTime(curve, t0, duration); + + expectedConstant = curve[1]; + return { + expectedConstant: expectedConstant, + autoMessage: "setValueCurveAtTime([" + curve + "], " + t0 + + ", " + duration + + ")", + summary: "setValueCurveAtTime", + }; + }, { + valueThreshold: 0, + curveThreshold: 0 + }).then(task.done.bind(task)); + }); + + // Special case where we schedule a setTarget and there is no earlier + // automation event. This tests that we pick up the starting point + // correctly from the last setting of the AudioParam value attribute. + + + audit.define("initial setTarget", function (task, should) { + task.describe("Cancel with initial setTargetAtTime"); + cancelTest(should, function (g, v0, t0, cancelTime) { + let v1 = 0; + let timeConstant = 0.1; + g[0].gain.value = 1; + g[0].gain.setTargetAtTime(v1, t0, timeConstant); + g[1].gain.value = 1; + g[1].gain.setTargetAtTime(v1, t0, timeConstant); + + let expectedConstant = Math.fround(v1 + (v0 - v1) * Math.exp(- + (cancelTime - t0) / + timeConstant)); + + return { + expectedConstant: expectedConstant, + autoMessage: "setTargetAtTime(" + v1 + ", " + t0 + ", " + + timeConstant + ")", + summary: "Initial setTargetAtTime", + }; + }, { + valueThreshold: 1.2320e-6, + curveThreshold: 0 + }).then(task.done.bind(task)); + }); + + // Test automations scheduled after the call to cancelValuesAndHoldAtTime. + // Very similar to the above tests, but we also schedule an event after + // cancelValuesAndHoldAtTime and verify that curve after cancellation has + // the correct values. + + audit.define("post cancel: Linear", function (task, should) { + // Run the cancel test using a linearRamp as the event to be cancelled. + // Then schedule another linear ramp after the cancellation. + task.describe("LinearRamp after cancelling"); + cancelTest(should, linearRampTest( + "Post cancellation linearRampToValueAtTime"), { + valueThreshold: 8.3998e-5, + curveThreshold: 0 + }, function (g, cancelTime, expectedConstant) { + // Schedule the linear ramp on g[0], and do the same for g[2], using the starting point + // given by expectedConstant. + let v2 = 2; + let t2 = cancelTime + 0.125; + g[0].gain.linearRampToValueAtTime(v2, t2); + g[2].gain.setValueAtTime(expectedConstant, cancelTime); + g[2].gain.linearRampToValueAtTime(v2, t2); + return { + constantEndTime: cancelTime, + message: "Post linearRamp(" + v2 + ", " + t2 + ")" + }; + }).then(task.done.bind(task)); + }); + + audit.define("post cancel: Exponential", function (task, should) { + task.describe("ExponentialRamp after cancelling"); + // Run the cancel test using a linearRamp as the event to be cancelled. + // Then schedule an exponential ramp after the cancellation. + cancelTest(should, linearRampTest( + "Post cancel exponentialRampToValueAtTime"), { + valueThreshold: 8.3998e-5, + curveThreshold: 0 + }, function (g, cancelTime, expectedConstant) { + // Schedule the exponential ramp on g[0], and do the same for g[2], + // using the starting point given by expectedConstant. + let v2 = 2; + let t2 = cancelTime + 0.125; + g[0].gain.exponentialRampToValueAtTime(v2, t2); + g[2].gain.setValueAtTime(expectedConstant, cancelTime); + g[2].gain.exponentialRampToValueAtTime(v2, t2); + return { + constantEndTime: cancelTime, + message: "Post exponentialRamp(" + v2 + ", " + t2 + ")" + }; + }).then(task.done.bind(task)); + }); + + audit.define("post cancel: ValueCurve", function (task, should) { + // Run the cancel test using a linearRamp as the event to be cancelled. + // Then schedule a setValueCurve after the cancellation. + cancelTest(should, linearRampTest("Post cancel setValueCurveAtTime"), { + valueThreshold: 8.3998e-5, + curveThreshold: 0 + }, function (g, cancelTime, expectedConstant) { + // Schedule the exponential ramp on g[0], and do the same for g[2], + // using the starting point given by expectedConstant. + let t2 = cancelTime + 0.125; + let duration = 0.125; + let curve = Float32Array.from([.125, 2]); + g[0].gain.setValueCurveAtTime(curve, t2, duration); + g[2].gain.setValueAtTime(expectedConstant, cancelTime); + g[2].gain.setValueCurveAtTime(curve, t2, duration); + return { + constantEndTime: cancelTime, + message: "Post setValueCurve([" + curve + "], " + t2 + ", " + + duration + ")", + errorThreshold: 8.3998e-5 + }; + }).then(task.done.bind(task)); + }); + + audit.define("post cancel: setTarget", function (task, should) { + // Run the cancel test using a linearRamp as the event to be cancelled. + // Then schedule a setTarget after the cancellation. + cancelTest(should, linearRampTest("Post cancel setTargetAtTime"), { + valueThreshold: 8.3998e-5, + curveThreshold: 0 + }, function (g, cancelTime, expectedConstant) { + // Schedule the exponential ramp on g[0], and do the same for g[2], + // using the starting point given by expectedConstant. + let v2 = 0.125; + let t2 = cancelTime + 0.125; + let timeConstant = 0.1; + g[0].gain.setTargetAtTime(v2, t2, timeConstant); + g[2].gain.setValueAtTime(expectedConstant, cancelTime); + g[2].gain.setTargetAtTime(v2, t2, timeConstant); + return { + constantEndTime: cancelTime + 0.125, + message: "Post setTargetAtTime(" + v2 + ", " + t2 + ", " + + timeConstant + ")", + errorThreshold: 8.4037e-5 + }; + }).then(task.done.bind(task)); + }); + + audit.define("post cancel: setValue", function (task, should) { + // Run the cancel test using a linearRamp as the event to be cancelled. + // Then schedule a setTarget after the cancellation. + cancelTest(should, linearRampTest("Post cancel setValueAtTime"), { + valueThreshold: 8.3998e-5, + curveThreshold: 0 + }, function (g, cancelTime, expectedConstant) { + // Schedule the exponential ramp on g[0], and do the same for g[2], + // using the starting point given by expectedConstant. + let v2 = 0.125; + let t2 = cancelTime + 0.125; + g[0].gain.setValueAtTime(v2, t2); + g[2].gain.setValueAtTime(expectedConstant, cancelTime); + g[2].gain.setValueAtTime(v2, t2); + return { + constantEndTime: cancelTime + 0.125, + message: "Post setValueAtTime(" + v2 + ", " + t2 + ")" + }; + }).then(task.done.bind(task)); + }); + + audit.run(); + + // Common function for doing a linearRamp test. This just does a linear + // ramp from 0 to v0 at from time 0 to t0. Then another linear ramp is + // scheduled from v0 to 0 from time t0 to t1. This is the ramp that is to + // be cancelled. + function linearRampTest(message) { + return function (g, v0, t0, cancelTime) { + g[0].gain.setValueAtTime(0, 0); + g[1].gain.setValueAtTime(0, 0); + g[0].gain.linearRampToValueAtTime(v0, t0); + g[1].gain.linearRampToValueAtTime(v0, t0); + + let v1 = 0; + let t1 = renderDuration; + g[0].gain.linearRampToValueAtTime(v1, t1); + g[1].gain.linearRampToValueAtTime(v1, t1); + + expectedConstant = Math.fround(v0 + (v1 - v0) * (cancelTime - t0) / + (t1 - t0)); + + return { + expectedConstant: expectedConstant, + autoMessage: "linearRampToValue(" + v1 + ", " + t1 + ")", + summary: message, + }; + } + } + + // Run the cancellation test. A set of automations is created and + // canceled. + // + // |testFunction| is a function that generates the automation to be + // tested. It is given an array of 3 gain nodes, the value and time of an + // initial linear ramp, and the time where the cancellation should occur. + // The function must do the automations for the first two gain nodes. It + // must return a dictionary with |expectedConstant| being the value at the + // cancellation time, |autoMessage| for message to describe the test, and + // |summary| for general summary message to be printed at the end of the + // test. + // + // |thresholdOptions| is a property bag that specifies the error threshold + // to use. |thresholdOptions.valueThreshold| is the error threshold for + // comparing the actual constant output after cancelling to the expected + // value. |thresholdOptions.curveThreshold| is the error threshold for + // comparing the actual and expected automation curves before the + // cancelation point. + // + // For cancellation tests, |postCancelTest| is a function that schedules + // some automation after the cancellation. It takes 3 arguments: an array + // of the gain nodes, the cancellation time, and the expected value at the + // cancellation time. This function must return a dictionary consisting + // of |constantEndtime| indicating when the held constant from + // cancellation stops being constant, |message| giving a summary of what + // automation is being used, and |errorThreshold| that is the error + // threshold between the expected curve and the actual curve. + // + function cancelTest(should, testerFunction, thresholdOptions, + postCancelTest) { + // Create a context with three channels. Channel 0 is the test channel + // containing the actual output that includes the cancellation of + // events. Channel 1 is the expected data upto the cancellation so we + // can verify the cancellation produced the correct result. Channel 2 + // is for verifying events inserted after the cancellation so we can + // verify that automations are correctly generated after the + // cancellation point. + let context = new OfflineAudioContext(3, renderDuration * sampleRate, + sampleRate); + + // Test source is a constant signal + let src = context.createBufferSource(); + src.buffer = createConstantBuffer(context, 1, 1); + src.loop = true; + + // We'll do the automation tests with three gain nodes. One (g0) will + // have cancelValuesAndHoldAtTime and the other (g1) will not. g1 is + // used as the expected result for that automation up to the + // cancellation point. They should be the same. The third node (g2) is + // used for testing automations inserted after the cancellation point, + // if any. g2 is the expected result from the cancellation point to the + // end of the test. + + let g0 = context.createGain(); + let g1 = context.createGain(); + let g2 = context.createGain(); + let v0 = 1; + let t0 = 0.01; + + let cancelTime = renderDuration / 2; + + // Test automation here. The tester function is responsible for setting + // up the gain nodes with the desired automation for testing. + autoResult = testerFunction([g0, g1, g2], v0, t0, cancelTime); + let expectedConstant = autoResult.expectedConstant; + let autoMessage = autoResult.autoMessage; + let summaryMessage = autoResult.summary; + + // Cancel scheduled events somewhere in the middle of the test + // automation. + g0.gain.cancelValuesAndHoldAtTime(cancelTime); + + let constantEndTime; + if (postCancelTest) { + postResult = postCancelTest([g0, g1, g2], cancelTime, + expectedConstant); + constantEndTime = postResult.constantEndTime; + } + + // Connect everything together (with a merger to make a two-channel + // result). Channel 0 is the test (with cancelValuesAndHoldAtTime) and + // channel 1 is the reference (without cancelValuesAndHoldAtTime). + // Channel 1 is used to verify that everything up to the cancellation + // has the correct values. + src.connect(g0); + src.connect(g1); + src.connect(g2); + let merger = context.createChannelMerger(3); + g0.connect(merger, 0, 0); + g1.connect(merger, 0, 1); + g2.connect(merger, 0, 2); + merger.connect(context.destination); + + // Go! + src.start(); + + return context.startRendering().then(function (buffer) { + let actual = buffer.getChannelData(0); + let expected = buffer.getChannelData(1); + + // The actual output should be a constant from the cancel time to the + // end. We use the last value of the actual output as the constant, + // but we also want to compare that with what we thought it should + // really be. + + let cancelFrame = Math.ceil(cancelTime * sampleRate); + + // Verify that the curves up to the cancel time are "identical". The + // should be but round-off may make them differ slightly due to the + // way cancelling is done. + let endFrame = Math.floor(cancelTime * sampleRate); + should(actual.slice(0, endFrame), + autoMessage + " up to time " + cancelTime) + .beCloseToArray(expected.slice(0, endFrame), { + absoluteThreshold: thresholdOptions.curveThreshold + }); + + // Verify the output after the cancellation is a constant. + let actualTail; + let constantEndFrame; + + if (postCancelTest) { + constantEndFrame = Math.ceil(constantEndTime * sampleRate); + actualTail = actual.slice(cancelFrame, constantEndFrame); + } else { + actualTail = actual.slice(cancelFrame); + } + + let actualConstant = actual[cancelFrame]; + + should(actualTail, "Cancelling " + autoMessage + " at time " + + cancelTime) + .beConstantValueOf(actualConstant); + + // Verify that the constant is the value we expect. + should(actualConstant, "Expected value for cancelling " + + autoMessage + " at time " + + cancelTime) + .beCloseTo(expectedConstant, { + threshold: thresholdOptions.valueThreshold + }); + + // Verify the curve after the constantEndTime matches our + // expectations. + if (postCancelTest) { + let c2 = buffer.getChannelData(2); + should(actual.slice(constantEndFrame), postResult.message) + .beCloseToArray(c2.slice(constantEndFrame), { + absoluteThreshold: postResult.errorThreshold || 0 + }); + } + }); + } + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt index a71964a..90cea8fa 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -248,6 +248,13 @@ [Worker] method readAsBinaryString [Worker] method readAsDataURL [Worker] method readAsText +[Worker] interface Float32ImageData +[Worker] attribute @@toStringTag +[Worker] getter colorSpace +[Worker] getter data +[Worker] getter height +[Worker] getter width +[Worker] method constructor [Worker] interface FormData [Worker] attribute @@toStringTag [Worker] method @@iterator @@ -428,9 +435,12 @@ [Worker] method constructor [Worker] interface ImageData [Worker] attribute @@toStringTag +[Worker] getter colorSpace +[Worker] getter data [Worker] getter height [Worker] getter width [Worker] method constructor +[Worker] method createImageData [Worker] interface MessageChannel [Worker] attribute @@toStringTag [Worker] getter port1
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index 1886d67..ecad6fe 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -214,6 +214,7 @@ getter minValue getter value method cancelScheduledValues + method cancelValuesAndHoldAtTime method constructor method exponentialRampToValueAtTime method linearRampToValueAtTime @@ -1837,6 +1838,13 @@ setter onloadend setter onloadstart setter onprogress +interface Float32ImageData + attribute @@toStringTag + getter colorSpace + getter data + getter height + getter width + method constructor interface FocusEvent : UIEvent attribute @@toStringTag getter relatedTarget @@ -3657,9 +3665,12 @@ method takePhoto interface ImageData attribute @@toStringTag + getter colorSpace + getter data getter height getter width method constructor + method createImageData interface InputDeviceCapabilities attribute @@toStringTag getter firesTouchEvents
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt index 0e9045a..5214a44 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -243,6 +243,13 @@ [Worker] method readAsBinaryString [Worker] method readAsDataURL [Worker] method readAsText +[Worker] interface Float32ImageData +[Worker] attribute @@toStringTag +[Worker] getter colorSpace +[Worker] getter data +[Worker] getter height +[Worker] getter width +[Worker] method constructor [Worker] interface FormData [Worker] attribute @@toStringTag [Worker] method @@iterator @@ -423,9 +430,12 @@ [Worker] method constructor [Worker] interface ImageData [Worker] attribute @@toStringTag +[Worker] getter colorSpace +[Worker] getter data [Worker] getter height [Worker] getter width [Worker] method constructor +[Worker] method createImageData [Worker] interface MessageChannel [Worker] attribute @@toStringTag [Worker] getter port1
diff --git a/third_party/WebKit/Source/bindings/bindings.gni b/third_party/WebKit/Source/bindings/bindings.gni index b65c97c..0b930966 100644 --- a/third_party/WebKit/Source/bindings/bindings.gni +++ b/third_party/WebKit/Source/bindings/bindings.gni
@@ -65,6 +65,8 @@ "core/v8/IDLDictionaryBase.cpp", "core/v8/IDLDictionaryBase.h", "core/v8/Iterable.h", + "core/v8/LocalWindowProxy.cpp", + "core/v8/LocalWindowProxy.h", "core/v8/Maplike.h", "core/v8/Microtask.cpp", "core/v8/Microtask.h", @@ -72,6 +74,8 @@ "core/v8/Nullable.h", "core/v8/RejectedPromises.cpp", "core/v8/RejectedPromises.h", + "core/v8/RemoteWindowProxy.cpp", + "core/v8/RemoteWindowProxy.h", "core/v8/RetainedDOMInfo.cpp", "core/v8/RetainedDOMInfo.h", "core/v8/RetainedObjectInfo.h",
diff --git a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp new file mode 100644 index 0000000..a0d7e39 --- /dev/null +++ b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
@@ -0,0 +1,370 @@ +/* + * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bindings/core/v8/LocalWindowProxy.h" + +#include "bindings/core/v8/ConditionalFeatures.h" +#include "bindings/core/v8/DOMWrapperWorld.h" +#include "bindings/core/v8/ScriptController.h" +#include "bindings/core/v8/ToV8.h" +#include "bindings/core/v8/V8Binding.h" +#include "bindings/core/v8/V8DOMActivityLogger.h" +#include "bindings/core/v8/V8HTMLDocument.h" +#include "bindings/core/v8/V8HiddenValue.h" +#include "bindings/core/v8/V8Initializer.h" +#include "bindings/core/v8/V8PrivateProperty.h" +#include "bindings/core/v8/V8Window.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/csp/ContentSecurityPolicy.h" +#include "core/html/DocumentNameCollection.h" +#include "core/html/HTMLIFrameElement.h" +#include "core/inspector/MainThreadDebugger.h" +#include "core/loader/FrameLoader.h" +#include "core/loader/FrameLoaderClient.h" +#include "core/origin_trials/OriginTrialContext.h" +#include "platform/Histogram.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "platform/ScriptForbiddenScope.h" +#include "platform/heap/Handle.h" +#include "platform/instrumentation/tracing/TraceEvent.h" +#include "platform/weborigin/SecurityOrigin.h" +#include "wtf/Assertions.h" +#include <v8.h> + +namespace blink { + +void LocalWindowProxy::disposeContext(GlobalDetachmentBehavior behavior) { + if (m_lifecycle != Lifecycle::ContextInitialized) + return; + + ScriptState::Scope scope(m_scriptState.get()); + v8::Local<v8::Context> context = m_scriptState->context(); + // The embedder could run arbitrary code in response to the + // willReleaseScriptContext callback, so all disposing should happen after + // it returns. + frame()->loader().client()->willReleaseScriptContext(context, + m_world->worldId()); + MainThreadDebugger::instance()->contextWillBeDestroyed(m_scriptState.get()); + + WindowProxy::disposeContext(behavior); +} + +void LocalWindowProxy::initialize() { + TRACE_EVENT1("v8", "LocalWindowProxy::initialize", "isMainWindow", + frame()->isMainFrame()); + SCOPED_BLINK_UMA_HISTOGRAM_TIMER( + frame()->isMainFrame() ? "Blink.Binding.InitializeMainWindowProxy" + : "Blink.Binding.InitializeNonMainWindowProxy"); + + ScriptForbiddenScope::AllowUserAgentScript allowScript; + + v8::HandleScope handleScope(isolate()); + + createContext(); + + ScriptState::Scope scope(m_scriptState.get()); + v8::Local<v8::Context> context = m_scriptState->context(); + if (m_globalProxy.isEmpty()) { + m_globalProxy.set(isolate(), context->Global()); + CHECK(!m_globalProxy.isEmpty()); + } + + setupWindowPrototypeChain(); + + SecurityOrigin* origin = 0; + if (m_world->isMainWorld()) { + // ActivityLogger for main world is updated within updateDocument(). + updateDocument(); + origin = frame()->document()->getSecurityOrigin(); + // FIXME: Can this be removed when CSP moves to browser? + ContentSecurityPolicy* csp = frame()->document()->contentSecurityPolicy(); + context->AllowCodeGenerationFromStrings( + csp->allowEval(0, ContentSecurityPolicy::SuppressReport)); + context->SetErrorMessageForCodeGenerationFromStrings( + v8String(isolate(), csp->evalDisabledErrorMessage())); + } else { + updateActivityLogger(); + origin = m_world->isolatedWorldSecurityOrigin(); + setSecurityToken(origin); + } + + MainThreadDebugger::instance()->contextCreated(m_scriptState.get(), frame(), + origin); + frame()->loader().client()->didCreateScriptContext( + context, m_world->extensionGroup(), m_world->worldId()); + // If conditional features for window have been queued before the V8 context + // was ready, then inject them into the context now + if (m_world->isMainWorld()) { + installPendingConditionalFeaturesOnWindow(m_scriptState.get()); + } + + if (m_world->isMainWorld()) + frame()->loader().dispatchDidClearWindowObjectInMainWorld(); +} + +void LocalWindowProxy::createContext() { + // Create a new v8::Context with the window object as the global object + // (aka the inner global). Reuse the global proxy object (aka the outer + // global) if it already exists. See the comments in + // setupWindowPrototypeChain for the structure of the prototype chain of + // the global object. + v8::Local<v8::ObjectTemplate> globalTemplate = + V8Window::domTemplate(isolate(), *m_world)->InstanceTemplate(); + CHECK(!globalTemplate.IsEmpty()); + + // FIXME: It's not clear what the right thing to do for remote frames is. + // The extensions registered don't generally seem to make sense for remote + // frames, so skip it for now. + Vector<const char*> extensionNames; + // Dynamically tell v8 about our extensions now. + const V8Extensions& extensions = ScriptController::registeredExtensions(); + extensionNames.reserveInitialCapacity(extensions.size()); + int extensionGroup = m_world->extensionGroup(); + int worldId = m_world->worldId(); + for (const auto* extension : extensions) { + if (!frame()->loader().client()->allowScriptExtension( + extension->name(), extensionGroup, worldId)) + continue; + + extensionNames.push_back(extension->name()); + } + v8::ExtensionConfiguration extensionConfiguration(extensionNames.size(), + extensionNames.data()); + + v8::Local<v8::Context> context; + { + V8PerIsolateData::UseCounterDisabledScope useCounterDisabled( + V8PerIsolateData::from(isolate())); + context = + v8::Context::New(isolate(), &extensionConfiguration, globalTemplate, + m_globalProxy.newLocal(isolate())); + } + CHECK(!context.IsEmpty()); + + m_scriptState = ScriptState::create(context, m_world); + + // TODO(haraken): Currently we cannot enable the following DCHECK because + // an already detached window proxy can be re-initialized. This is wrong. + // DCHECK(m_lifecycle == Lifecycle::ContextUninitialized); + m_lifecycle = Lifecycle::ContextInitialized; + DCHECK(m_scriptState->contextIsValid()); +} + +void LocalWindowProxy::updateDocumentProperty() { + DCHECK(m_world->isMainWorld()); + + ScriptState::Scope scope(m_scriptState.get()); + v8::Local<v8::Context> context = m_scriptState->context(); + v8::Local<v8::Value> documentWrapper = + ToV8(frame()->document(), context->Global(), isolate()); + DCHECK(documentWrapper->IsObject()); + // Update the cached accessor for window.document. + CHECK(V8PrivateProperty::getWindowDocumentCachedAccessor(isolate()).set( + context, context->Global(), documentWrapper)); +} + +void LocalWindowProxy::updateActivityLogger() { + m_scriptState->perContextData()->setActivityLogger( + V8DOMActivityLogger::activityLogger( + m_world->worldId(), + frame()->document() ? frame()->document()->baseURI() : KURL())); +} + +void LocalWindowProxy::setSecurityToken(SecurityOrigin* origin) { + // If two tokens are equal, then the SecurityOrigins canAccess each other. + // If two tokens are not equal, then we have to call canAccess. + // Note: we can't use the HTTPOrigin if it was set from the DOM. + String token; + // If document.domain is modified, v8 needs to do a full canAccess check, + // so always use an empty security token in that case. + bool delaySet = m_world->isMainWorld() && origin->domainWasSetInDOM(); + if (origin && !delaySet) + token = origin->toString(); + + // An empty or "null" token means we always have to call + // canAccess. The toString method on securityOrigins returns the + // string "null" for empty security origins and for security + // origins that should only allow access to themselves. In this + // case, we use the global object as the security token to avoid + // calling canAccess when a script accesses its own objects. + v8::HandleScope handleScope(isolate()); + v8::Local<v8::Context> context = m_scriptState->context(); + if (token.isEmpty() || token == "null") { + context->UseDefaultSecurityToken(); + return; + } + + if (m_world->isIsolatedWorld()) { + SecurityOrigin* frameSecurityOrigin = + frame()->document()->getSecurityOrigin(); + String frameSecurityToken = frameSecurityOrigin->toString(); + // We need to check the return value of domainWasSetInDOM() on the + // frame's SecurityOrigin because, if that's the case, only + // SecurityOrigin::m_domain would have been modified. + // m_domain is not used by SecurityOrigin::toString(), so we would end + // up generating the same token that was already set. + if (frameSecurityOrigin->domainWasSetInDOM() || + frameSecurityToken.isEmpty() || frameSecurityToken == "null") { + context->UseDefaultSecurityToken(); + return; + } + token = frameSecurityToken + token; + } + + // NOTE: V8 does identity comparison in fast path, must use a symbol + // as the security token. + context->SetSecurityToken(v8AtomicString(isolate(), token)); +} + +void LocalWindowProxy::updateDocument() { + DCHECK(m_world->isMainWorld()); + // For an uninitialized main window proxy, there's nothing we need + // to update. The update is done when the window proxy gets initialized later. + if (m_lifecycle == Lifecycle::ContextUninitialized) + return; + // TODO(yukishiino): Is it okay to not update document when the context + // is detached? It's not trivial to fix this because udpateDocumentProperty + // requires a not-yet-detached context to instantiate a document wrapper. + if (m_lifecycle == Lifecycle::ContextDetached) + return; + + updateActivityLogger(); + updateDocumentProperty(); + updateSecurityOrigin(frame()->document()->getSecurityOrigin()); +} + +static v8::Local<v8::Value> getNamedProperty( + HTMLDocument* htmlDocument, + const AtomicString& key, + v8::Local<v8::Object> creationContext, + v8::Isolate* isolate) { + if (!htmlDocument->hasNamedItem(key) && !htmlDocument->hasExtraNamedItem(key)) + return v8Undefined(); + + DocumentNameCollection* items = htmlDocument->documentNamedItems(key); + if (items->isEmpty()) + return v8Undefined(); + + if (items->hasExactlyOneItem()) { + HTMLElement* element = items->item(0); + DCHECK(element); + Frame* frame = isHTMLIFrameElement(*element) + ? toHTMLIFrameElement(*element).contentFrame() + : 0; + if (frame) + return ToV8(frame->domWindow(), creationContext, isolate); + return ToV8(element, creationContext, isolate); + } + return ToV8(items, creationContext, isolate); +} + +static void getter(v8::Local<v8::Name> property, + const v8::PropertyCallbackInfo<v8::Value>& info) { + if (!property->IsString()) + return; + // FIXME: Consider passing StringImpl directly. + AtomicString name = toCoreAtomicString(property.As<v8::String>()); + HTMLDocument* htmlDocument = V8HTMLDocument::toImpl(info.Holder()); + DCHECK(htmlDocument); + v8::Local<v8::Value> result = + getNamedProperty(htmlDocument, name, info.Holder(), info.GetIsolate()); + if (!result.IsEmpty()) { + v8SetReturnValue(info, result); + return; + } + v8::Local<v8::Value> value; + if (info.Holder() + ->GetRealNamedPropertyInPrototypeChain( + info.GetIsolate()->GetCurrentContext(), property.As<v8::String>()) + .ToLocal(&value)) + v8SetReturnValue(info, value); +} + +void LocalWindowProxy::namedItemAdded(HTMLDocument* document, + const AtomicString& name) { + DCHECK(m_world->isMainWorld()); + + // Context must be initialized before this point. + DCHECK(m_lifecycle >= Lifecycle::ContextInitialized); + // TODO(yukishiino): Is it okay to not update named properties + // after the context gets detached? + if (m_lifecycle == Lifecycle::ContextDetached) + return; + + ScriptState::Scope scope(m_scriptState.get()); + v8::Local<v8::Object> documentWrapper = + m_world->domDataStore().get(document, isolate()); + // TODO(yukishiino,peria): We should check if the own property with the same + // name already exists or not, and if it exists, we shouldn't define a new + // accessor property (it fails). + documentWrapper->SetAccessor(isolate()->GetCurrentContext(), + v8String(isolate(), name), getter); +} + +void LocalWindowProxy::namedItemRemoved(HTMLDocument* document, + const AtomicString& name) { + DCHECK(m_world->isMainWorld()); + + // Context must be initialized before this point. + DCHECK(m_lifecycle >= Lifecycle::ContextInitialized); + // TODO(yukishiino): Is it okay to not update named properties + // after the context gets detached? + if (m_lifecycle == Lifecycle::ContextDetached) + return; + + if (document->hasNamedItem(name) || document->hasExtraNamedItem(name)) + return; + ScriptState::Scope scope(m_scriptState.get()); + v8::Local<v8::Object> documentWrapper = + m_world->domDataStore().get(document, isolate()); + documentWrapper + ->Delete(isolate()->GetCurrentContext(), v8String(isolate(), name)) + .ToChecked(); +} + +void LocalWindowProxy::updateSecurityOrigin(SecurityOrigin* origin) { + // For an uninitialized main window proxy, there's nothing we need + // to update. The update is done when the window proxy gets initialized later. + if (m_lifecycle == Lifecycle::ContextUninitialized) + return; + // TODO(yukishiino): Is it okay to not update security origin when the context + // is detached? + if (m_lifecycle == Lifecycle::ContextDetached) + return; + + setSecurityToken(origin); +} + +LocalWindowProxy::LocalWindowProxy(v8::Isolate* isolate, + LocalFrame& frame, + RefPtr<DOMWrapperWorld> world) + : WindowProxy(isolate, frame, std::move(world)) {} + +} // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.h b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.h new file mode 100644 index 0000000..e92aea2 --- /dev/null +++ b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.h
@@ -0,0 +1,92 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LocalWindowProxy_h +#define LocalWindowProxy_h + +#include "bindings/core/v8/DOMWrapperWorld.h" +#include "bindings/core/v8/WindowProxy.h" +#include "core/frame/LocalFrame.h" +#include "wtf/RefPtr.h" +#include "wtf/text/AtomicString.h" +#include <v8.h> + +namespace blink { + +class HTMLDocument; +class SecurityOrigin; + +// Subclass of WindowProxy that only handles LocalFrame. +class LocalWindowProxy final : public WindowProxy { + public: + static LocalWindowProxy* create(v8::Isolate* isolate, + LocalFrame& frame, + RefPtr<DOMWrapperWorld> world) { + return new LocalWindowProxy(isolate, frame, std::move(world)); + } + + // Update document object of the frame. + void updateDocument(); + + void namedItemAdded(HTMLDocument*, const AtomicString&); + void namedItemRemoved(HTMLDocument*, const AtomicString&); + + // Update the security origin of a document + // (e.g., after setting docoument.domain). + void updateSecurityOrigin(SecurityOrigin*); + + private: + LocalWindowProxy(v8::Isolate*, LocalFrame&, RefPtr<DOMWrapperWorld>); + + void initialize() override; + void disposeContext(GlobalDetachmentBehavior) override; + + // Creates a new v8::Context with the window wrapper object as the global + // object (aka the inner global). Note that the window wrapper and its + // prototype chain do not get fully initialized yet, e.g. the window + // wrapper is not yet associated with the native DOMWindow object. + void createContext(); + + void setSecurityToken(SecurityOrigin*); + + // The JavaScript wrapper for the document object is cached on the global + // object for fast access. UpdateDocumentProperty sets the wrapper + // for the current document on the global object. + void updateDocumentProperty(); + + // Updates Activity Logger for the current context. + void updateActivityLogger(); + + LocalFrame* frame() const { return toLocalFrame(WindowProxy::frame()); } +}; + +} // namespace blink + +#endif // LocalWindowProxy_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp new file mode 100644 index 0000000..2bbdba3 --- /dev/null +++ b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp
@@ -0,0 +1,143 @@ +/* + * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bindings/core/v8/WindowProxy.h" + +#include "bindings/core/v8/ConditionalFeatures.h" +#include "bindings/core/v8/DOMWrapperWorld.h" +#include "bindings/core/v8/ScriptController.h" +#include "bindings/core/v8/ToV8.h" +#include "bindings/core/v8/V8Binding.h" +#include "bindings/core/v8/V8DOMActivityLogger.h" +#include "bindings/core/v8/V8Document.h" +#include "bindings/core/v8/V8GCForContextDispose.h" +#include "bindings/core/v8/V8HTMLCollection.h" +#include "bindings/core/v8/V8HTMLDocument.h" +#include "bindings/core/v8/V8HiddenValue.h" +#include "bindings/core/v8/V8Initializer.h" +#include "bindings/core/v8/V8ObjectConstructor.h" +#include "bindings/core/v8/V8PagePopupControllerBinding.h" +#include "bindings/core/v8/V8PrivateProperty.h" +#include "bindings/core/v8/V8Window.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/csp/ContentSecurityPolicy.h" +#include "core/html/DocumentNameCollection.h" +#include "core/html/HTMLCollection.h" +#include "core/html/HTMLIFrameElement.h" +#include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/MainThreadDebugger.h" +#include "core/loader/DocumentLoader.h" +#include "core/loader/FrameLoader.h" +#include "core/loader/FrameLoaderClient.h" +#include "core/origin_trials/OriginTrialContext.h" +#include "platform/Histogram.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "platform/ScriptForbiddenScope.h" +#include "platform/heap/Handle.h" +#include "platform/instrumentation/tracing/TraceEvent.h" +#include "platform/weborigin/SecurityOrigin.h" +#include "public/platform/Platform.h" +#include "wtf/Assertions.h" +#include "wtf/StringExtras.h" +#include "wtf/text/CString.h" +#include <algorithm> +#include <utility> +#include <v8-debug.h> +#include <v8.h> + +namespace blink { + +RemoteWindowProxy::RemoteWindowProxy(v8::Isolate* isolate, + RemoteFrame& frame, + RefPtr<DOMWrapperWorld> world) + : WindowProxy(isolate, frame, std::move(world)) {} + +void RemoteWindowProxy::disposeContext(GlobalDetachmentBehavior behavior) { + if (m_lifecycle != Lifecycle::ContextInitialized) + return; + + WindowProxy::disposeContext(behavior); +} + +void RemoteWindowProxy::initialize() { + TRACE_EVENT1("v8", "RemoteWindowProxy::initialize", "isMainWindow", + frame()->isMainFrame()); + SCOPED_BLINK_UMA_HISTOGRAM_TIMER( + frame()->isMainFrame() ? "Blink.Binding.InitializeMainWindowProxy" + : "Blink.Binding.InitializeNonMainWindowProxy"); + + ScriptForbiddenScope::AllowUserAgentScript allowScript; + + v8::HandleScope handleScope(isolate()); + + createContext(); + + ScriptState::Scope scope(m_scriptState.get()); + v8::Local<v8::Context> context = m_scriptState->context(); + if (m_globalProxy.isEmpty()) { + m_globalProxy.set(isolate(), context->Global()); + CHECK(!m_globalProxy.isEmpty()); + } + + setupWindowPrototypeChain(); + + // Remote frames always require a full canAccess() check. + context->UseDefaultSecurityToken(); +} + +void RemoteWindowProxy::createContext() { + // Create a new v8::Context with the window object as the global object + // (aka the inner global). Reuse the global proxy object (aka the outer + // global) if it already exists. See the comments in + // setupWindowPrototypeChain for the structure of the prototype chain of + // the global object. + v8::Local<v8::ObjectTemplate> globalTemplate = + V8Window::domTemplate(isolate(), *m_world)->InstanceTemplate(); + CHECK(!globalTemplate.IsEmpty()); + + v8::Local<v8::Context> context; + { + V8PerIsolateData::UseCounterDisabledScope useCounterDisabled( + V8PerIsolateData::from(isolate())); + context = v8::Context::New(isolate(), nullptr, globalTemplate, + m_globalProxy.newLocal(isolate())); + } + CHECK(!context.IsEmpty()); + + m_scriptState = ScriptState::create(context, m_world); + + // TODO(haraken): Currently we cannot enable the following DCHECK because + // an already detached window proxy can be re-initialized. This is wrong. + // DCHECK(m_lifecycle == Lifecycle::ContextUninitialized); + m_lifecycle = Lifecycle::ContextInitialized; + DCHECK(m_scriptState->contextIsValid()); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.h b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.h new file mode 100644 index 0000000..d85780f --- /dev/null +++ b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.h
@@ -0,0 +1,65 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RemoteWindowProxy_h +#define RemoteWindowProxy_h + +#include "bindings/core/v8/DOMWrapperWorld.h" +#include "core/frame/RemoteFrame.h" +#include <v8.h> + +namespace blink { + +// Subclass of WindowProxy that only handles RemoteFrame. +class RemoteWindowProxy final : public WindowProxy { + public: + static RemoteWindowProxy* create(v8::Isolate* isolate, + RemoteFrame& frame, + + RefPtr<DOMWrapperWorld> world) { + return new RemoteWindowProxy(isolate, frame, std::move(world)); + } + + private: + RemoteWindowProxy(v8::Isolate*, RemoteFrame&, RefPtr<DOMWrapperWorld>); + + void initialize() override; + void disposeContext(GlobalDetachmentBehavior) override; + + // Creates a new v8::Context with the window wrapper object as the global + // object (aka the inner global). Note that the window wrapper and its + // prototype chain do not get fully initialized yet, e.g. the window + // wrapper is not yet associated with the native DOMWindow object. + void createContext(); +}; + +} // namespace blink + +#endif // RemoteWindowProxy_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp index e204731d..1f94c6f 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
@@ -79,7 +79,7 @@ namespace blink { ScriptController::ScriptController(LocalFrame* frame) - : m_windowProxyManager(WindowProxyManager::create(*frame)) {} + : m_windowProxyManager(LocalWindowProxyManager::create(*frame)) {} DEFINE_TRACE(ScriptController) { visitor->trace(m_windowProxyManager); @@ -209,8 +209,8 @@ InspectorUpdateCountersEvent::data()); } -WindowProxy* ScriptController::windowProxy(DOMWrapperWorld& world) { - WindowProxy* windowProxy = m_windowProxyManager->windowProxy(world); +LocalWindowProxy* ScriptController::windowProxy(DOMWrapperWorld& world) { + LocalWindowProxy* windowProxy = m_windowProxyManager->windowProxy(world); windowProxy->initializeIfNeeded(); return windowProxy; } @@ -441,7 +441,7 @@ RefPtr<DOMWrapperWorld> world = DOMWrapperWorld::ensureIsolatedWorld(isolate(), worldID, extensionGroup); - WindowProxy* isolatedWorldWindowProxy = windowProxy(*world); + LocalWindowProxy* isolatedWorldWindowProxy = windowProxy(*world); ScriptState* scriptState = isolatedWorldWindowProxy->getScriptState(); if (!scriptState->contextIsValid()) return;
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptController.h b/third_party/WebKit/Source/bindings/core/v8/ScriptController.h index 83a4cc9..747bea0 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptController.h +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptController.h
@@ -52,7 +52,6 @@ class KURL; class ScriptSourceCode; class SecurityOrigin; -class WindowProxy; class Widget; typedef WTF::Vector<v8::Extension*> V8Extensions; @@ -80,7 +79,7 @@ // This returns an initialized window proxy. (If the window proxy is not // yet initialized, it's implicitly initialized at the first access.) - WindowProxy* windowProxy(DOMWrapperWorld&); + LocalWindowProxy* windowProxy(DOMWrapperWorld&); // Evaluate JavaScript in the main world. void executeScriptInMainWorld( @@ -148,22 +147,20 @@ v8::Isolate* isolate() const { return m_windowProxyManager->isolate(); } - WindowProxyManager* getWindowProxyManager() const { + LocalWindowProxyManager* getWindowProxyManager() const { return m_windowProxyManager.get(); } private: explicit ScriptController(LocalFrame*); - LocalFrame* frame() const { - return toLocalFrame(m_windowProxyManager->frame()); - } + LocalFrame* frame() const { return m_windowProxyManager->frame(); } v8::Local<v8::Value> evaluateScriptInMainWorld(const ScriptSourceCode&, AccessControlStatus, ExecuteScriptPolicy); - Member<WindowProxyManager> m_windowProxyManager; + Member<LocalWindowProxyManager> m_windowProxyManager; }; } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp index b49db8f4..347c27bc8 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
@@ -392,9 +392,11 @@ gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode, v8ExtrasMode, &arrayBufferAllocator); + // NOTE: Some threads (namely utility threads) don't have a scheduler. WebScheduler* scheduler = Platform::current()->currentThread()->scheduler(); - v8::Isolate* isolate = - V8PerIsolateData::initialize(scheduler->timerTaskRunner()); + v8::Isolate* isolate = V8PerIsolateData::initialize( + scheduler ? scheduler->timerTaskRunner() + : Platform::current()->currentThread()->getWebTaskRunner()); initializeV8Common(isolate);
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp index e6e7ce8..a5d8814 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
@@ -55,7 +55,7 @@ V8PerIsolateData::V8PerIsolateData(WebTaskRunner* taskRunner) : m_isolateHolder(WTF::makeUnique<gin::IsolateHolder>( - taskRunner->toSingleThreadTaskRunner())), + taskRunner ? taskRunner->toSingleThreadTaskRunner() : nullptr)), m_stringCache(WTF::wrapUnique(new StringCache(isolate()))), m_hiddenValue(V8HiddenValue::create()), m_privateProperty(V8PrivateProperty::create()),
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp index 61471d3..b750f26 100644 --- a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
@@ -30,64 +30,18 @@ #include "bindings/core/v8/WindowProxy.h" -#include "bindings/core/v8/ConditionalFeatures.h" -#include "bindings/core/v8/DOMWrapperWorld.h" -#include "bindings/core/v8/ScriptController.h" -#include "bindings/core/v8/ToV8.h" #include "bindings/core/v8/V8Binding.h" -#include "bindings/core/v8/V8DOMActivityLogger.h" -#include "bindings/core/v8/V8Document.h" +#include "bindings/core/v8/V8DOMWrapper.h" #include "bindings/core/v8/V8GCForContextDispose.h" -#include "bindings/core/v8/V8HTMLCollection.h" -#include "bindings/core/v8/V8HTMLDocument.h" -#include "bindings/core/v8/V8HiddenValue.h" -#include "bindings/core/v8/V8Initializer.h" -#include "bindings/core/v8/V8ObjectConstructor.h" #include "bindings/core/v8/V8PagePopupControllerBinding.h" -#include "bindings/core/v8/V8PrivateProperty.h" -#include "bindings/core/v8/V8Window.h" -#include "core/frame/LocalFrame.h" -#include "core/frame/csp/ContentSecurityPolicy.h" -#include "core/html/DocumentNameCollection.h" -#include "core/html/HTMLCollection.h" -#include "core/html/HTMLIFrameElement.h" -#include "core/inspector/InspectorInstrumentation.h" -#include "core/inspector/MainThreadDebugger.h" -#include "core/loader/DocumentLoader.h" -#include "core/loader/FrameLoader.h" -#include "core/loader/FrameLoaderClient.h" -#include "core/origin_trials/OriginTrialContext.h" -#include "platform/Histogram.h" -#include "platform/RuntimeEnabledFeatures.h" -#include "platform/ScriptForbiddenScope.h" -#include "platform/heap/Handle.h" -#include "platform/instrumentation/tracing/TraceEvent.h" -#include "platform/weborigin/SecurityOrigin.h" -#include "public/platform/Platform.h" +#include "core/frame/DOMWindow.h" +#include "core/frame/Frame.h" #include "wtf/Assertions.h" -#include "wtf/StringExtras.h" -#include "wtf/text/CString.h" -#include <algorithm> #include <utility> -#include <v8-debug.h> #include <v8.h> namespace blink { -WindowProxy* WindowProxy::create(v8::Isolate* isolate, - Frame* frame, - DOMWrapperWorld& world) { - return new WindowProxy(frame, &world, isolate); -} - -WindowProxy::WindowProxy(Frame* frame, - PassRefPtr<DOMWrapperWorld> world, - v8::Isolate* isolate) - : m_frame(frame), - m_isolate(isolate), - m_world(world), - m_lifecycle(Lifecycle::ContextUninitialized) {} - WindowProxy::~WindowProxy() { // clearForClose() or clearForNavigation() must be invoked before destruction // starts. @@ -98,23 +52,20 @@ visitor->trace(m_frame); } -void WindowProxy::disposeContext(GlobalDetachmentBehavior behavior) { - if (m_lifecycle != Lifecycle::ContextInitialized) - return; +WindowProxy::WindowProxy(v8::Isolate* isolate, + Frame& frame, + RefPtr<DOMWrapperWorld> world) + : m_isolate(isolate), + m_frame(frame), - ScriptState::Scope scope(m_scriptState.get()); - v8::Local<v8::Context> context = m_scriptState->context(); - if (m_frame->isLocalFrame()) { - LocalFrame* frame = toLocalFrame(m_frame); - // The embedder could run arbitrary code in response to the - // willReleaseScriptContext callback, so all disposing should happen after - // it returns. - frame->loader().client()->willReleaseScriptContext(context, - m_world->worldId()); - MainThreadDebugger::instance()->contextWillBeDestroyed(m_scriptState.get()); - } + m_world(std::move(world)), + m_lifecycle(Lifecycle::ContextUninitialized) {} + +void WindowProxy::disposeContext(GlobalDetachmentBehavior behavior) { + DCHECK(m_lifecycle == Lifecycle::ContextInitialized); if (behavior == DetachGlobal) { + v8::Local<v8::Context> context = m_scriptState->context(); // Clean up state on the global proxy, which will be reused. if (!m_globalProxy.isEmpty()) { // TODO(yukishiino): This DCHECK failed on Canary (M57) and Dev (M56). @@ -222,116 +173,9 @@ // proxy. This must be 'if(m_lifecycle == Lifecycle::ContextUninitialized)'. if (m_lifecycle != Lifecycle::ContextInitialized) { initialize(); - if (m_world->isMainWorld() && m_frame->isLocalFrame()) - toLocalFrame(m_frame)->loader().dispatchDidClearWindowObjectInMainWorld(); } } -void WindowProxy::initialize() { - TRACE_EVENT1("v8", "WindowProxy::initialize", "isMainWindow", - m_frame->isMainFrame()); - SCOPED_BLINK_UMA_HISTOGRAM_TIMER( - m_frame->isMainFrame() ? "Blink.Binding.InitializeMainWindowProxy" - : "Blink.Binding.InitializeNonMainWindowProxy"); - - ScriptForbiddenScope::AllowUserAgentScript allowScript; - - v8::HandleScope handleScope(m_isolate); - - createContext(); - - ScriptState::Scope scope(m_scriptState.get()); - v8::Local<v8::Context> context = m_scriptState->context(); - if (m_globalProxy.isEmpty()) { - m_globalProxy.set(m_isolate, context->Global()); - CHECK(!m_globalProxy.isEmpty()); - } - - setupWindowPrototypeChain(); - - SecurityOrigin* origin = 0; - if (m_world->isMainWorld()) { - // ActivityLogger for main world is updated within updateDocument(). - updateDocument(); - origin = m_frame->securityContext()->getSecurityOrigin(); - // FIXME: Can this be removed when CSP moves to browser? - ContentSecurityPolicy* csp = - m_frame->securityContext()->contentSecurityPolicy(); - context->AllowCodeGenerationFromStrings( - csp->allowEval(0, ContentSecurityPolicy::SuppressReport)); - context->SetErrorMessageForCodeGenerationFromStrings( - v8String(m_isolate, csp->evalDisabledErrorMessage())); - } else { - updateActivityLogger(); - origin = m_world->isolatedWorldSecurityOrigin(); - setSecurityToken(origin); - } - - if (m_frame->isLocalFrame()) { - LocalFrame* frame = toLocalFrame(m_frame); - MainThreadDebugger::instance()->contextCreated(m_scriptState.get(), frame, - origin); - frame->loader().client()->didCreateScriptContext( - context, m_world->extensionGroup(), m_world->worldId()); - } - // If conditional features for window have been queued before the V8 context - // was ready, then inject them into the context now - if (m_world->isMainWorld()) { - installPendingConditionalFeaturesOnWindow(m_scriptState.get()); - } -} - -void WindowProxy::createContext() { - // Create a new v8::Context with the window object as the global object - // (aka the inner global). Reuse the global proxy object (aka the outer - // global) if it already exists. See the comments in - // setupWindowPrototypeChain for the structure of the prototype chain of - // the global object. - v8::Local<v8::ObjectTemplate> globalTemplate = - V8Window::domTemplate(m_isolate, *m_world)->InstanceTemplate(); - CHECK(!globalTemplate.IsEmpty()); - - // FIXME: It's not clear what the right thing to do for remote frames is. - // The extensions registered don't generally seem to make sense for remote - // frames, so skip it for now. - Vector<const char*> extensionNames; - if (m_frame->isLocalFrame()) { - LocalFrame* frame = toLocalFrame(m_frame); - // Dynamically tell v8 about our extensions now. - const V8Extensions& extensions = ScriptController::registeredExtensions(); - extensionNames.reserveInitialCapacity(extensions.size()); - int extensionGroup = m_world->extensionGroup(); - int worldId = m_world->worldId(); - for (const auto* extension : extensions) { - if (!frame->loader().client()->allowScriptExtension( - extension->name(), extensionGroup, worldId)) - continue; - - extensionNames.push_back(extension->name()); - } - } - v8::ExtensionConfiguration extensionConfiguration(extensionNames.size(), - extensionNames.data()); - - v8::Local<v8::Context> context; - { - V8PerIsolateData::UseCounterDisabledScope useCounterDisabled( - V8PerIsolateData::from(m_isolate)); - context = - v8::Context::New(m_isolate, &extensionConfiguration, globalTemplate, - m_globalProxy.newLocal(m_isolate)); - } - CHECK(!context.IsEmpty()); - - m_scriptState = ScriptState::create(context, m_world); - - // TODO(haraken): Currently we cannot enable the following DCHECK because - // an already detached window proxy can be re-initialized. This is wrong. - // DCHECK(m_lifecycle == Lifecycle::ContextUninitialized); - m_lifecycle = Lifecycle::ContextInitialized; - DCHECK(m_scriptState->contextIsValid()); -} - void WindowProxy::setupWindowPrototypeChain() { // Associate the window wrapper object and its prototype chain with the // corresponding native DOMWindow object. @@ -399,198 +243,4 @@ windowWrapper); } -void WindowProxy::updateDocumentProperty() { - DCHECK(m_world->isMainWorld()); - - if (m_frame->isRemoteFrame()) - return; - - ScriptState::Scope scope(m_scriptState.get()); - v8::Local<v8::Context> context = m_scriptState->context(); - LocalFrame* frame = toLocalFrame(m_frame); - v8::Local<v8::Value> documentWrapper = - ToV8(frame->document(), context->Global(), m_isolate); - DCHECK(documentWrapper->IsObject()); - // Update the cached accessor for window.document. - CHECK(V8PrivateProperty::getWindowDocumentCachedAccessor(m_isolate).set( - context, context->Global(), documentWrapper)); -} - -void WindowProxy::updateActivityLogger() { - m_scriptState->perContextData()->setActivityLogger( - V8DOMActivityLogger::activityLogger( - m_world->worldId(), - m_frame->isLocalFrame() && toLocalFrame(m_frame)->document() - ? toLocalFrame(m_frame)->document()->baseURI() - : KURL())); -} - -void WindowProxy::setSecurityToken(SecurityOrigin* origin) { - // If two tokens are equal, then the SecurityOrigins canAccess each other. - // If two tokens are not equal, then we have to call canAccess. - // Note: we can't use the HTTPOrigin if it was set from the DOM. - String token; - // There are two situations where v8 needs to do a full canAccess check, - // so set an empty security token instead: - // - document.domain was modified - // - the frame is remote - bool delaySet = m_frame->isRemoteFrame() || - (m_world->isMainWorld() && origin->domainWasSetInDOM()); - if (origin && !delaySet) - token = origin->toString(); - - // An empty or "null" token means we always have to call - // canAccess. The toString method on securityOrigins returns the - // string "null" for empty security origins and for security - // origins that should only allow access to themselves. In this - // case, we use the global object as the security token to avoid - // calling canAccess when a script accesses its own objects. - v8::HandleScope handleScope(m_isolate); - v8::Local<v8::Context> context = m_scriptState->context(); - if (token.isEmpty() || token == "null") { - context->UseDefaultSecurityToken(); - return; - } - - if (m_world->isIsolatedWorld()) { - SecurityOrigin* frameSecurityOrigin = - m_frame->securityContext()->getSecurityOrigin(); - String frameSecurityToken = frameSecurityOrigin->toString(); - // We need to check the return value of domainWasSetInDOM() on the - // frame's SecurityOrigin because, if that's the case, only - // SecurityOrigin::m_domain would have been modified. - // m_domain is not used by SecurityOrigin::toString(), so we would end - // up generating the same token that was already set. - if (frameSecurityOrigin->domainWasSetInDOM() || - frameSecurityToken.isEmpty() || frameSecurityToken == "null") { - context->UseDefaultSecurityToken(); - return; - } - token = frameSecurityToken + token; - } - - // NOTE: V8 does identity comparison in fast path, must use a symbol - // as the security token. - context->SetSecurityToken(v8AtomicString(m_isolate, token)); -} - -void WindowProxy::updateDocument() { - DCHECK(m_world->isMainWorld()); - // For an uninitialized main window proxy, there's nothing we need - // to update. The update is done when the window proxy gets initialized later. - if (m_lifecycle == Lifecycle::ContextUninitialized) - return; - // TODO(yukishiino): Is it okay to not update document when the context - // is detached? It's not trivial to fix this because udpateDocumentProperty - // requires a not-yet-detached context to instantiate a document wrapper. - if (m_lifecycle == Lifecycle::ContextDetached) - return; - - updateActivityLogger(); - updateDocumentProperty(); - updateSecurityOrigin(m_frame->securityContext()->getSecurityOrigin()); -} - -static v8::Local<v8::Value> getNamedProperty( - HTMLDocument* htmlDocument, - const AtomicString& key, - v8::Local<v8::Object> creationContext, - v8::Isolate* isolate) { - if (!htmlDocument->hasNamedItem(key) && !htmlDocument->hasExtraNamedItem(key)) - return v8Undefined(); - - DocumentNameCollection* items = htmlDocument->documentNamedItems(key); - if (items->isEmpty()) - return v8Undefined(); - - if (items->hasExactlyOneItem()) { - HTMLElement* element = items->item(0); - ASSERT(element); - Frame* frame = isHTMLIFrameElement(*element) - ? toHTMLIFrameElement(*element).contentFrame() - : 0; - if (frame) - return ToV8(frame->domWindow(), creationContext, isolate); - return ToV8(element, creationContext, isolate); - } - return ToV8(items, creationContext, isolate); -} - -static void getter(v8::Local<v8::Name> property, - const v8::PropertyCallbackInfo<v8::Value>& info) { - if (!property->IsString()) - return; - // FIXME: Consider passing StringImpl directly. - AtomicString name = toCoreAtomicString(property.As<v8::String>()); - HTMLDocument* htmlDocument = V8HTMLDocument::toImpl(info.Holder()); - ASSERT(htmlDocument); - v8::Local<v8::Value> result = - getNamedProperty(htmlDocument, name, info.Holder(), info.GetIsolate()); - if (!result.IsEmpty()) { - v8SetReturnValue(info, result); - return; - } - v8::Local<v8::Value> value; - if (info.Holder() - ->GetRealNamedPropertyInPrototypeChain( - info.GetIsolate()->GetCurrentContext(), property.As<v8::String>()) - .ToLocal(&value)) - v8SetReturnValue(info, value); -} - -void WindowProxy::namedItemAdded(HTMLDocument* document, - const AtomicString& name) { - DCHECK(m_world->isMainWorld()); - - // Context must be initialized before this point. - DCHECK(m_lifecycle >= Lifecycle::ContextInitialized); - // TODO(yukishiino): Is it okay to not update named properties - // after the context gets detached? - if (m_lifecycle == Lifecycle::ContextDetached) - return; - - ScriptState::Scope scope(m_scriptState.get()); - v8::Local<v8::Object> documentWrapper = - m_world->domDataStore().get(document, m_isolate); - // TODO(yukishiino,peria): We should check if the own property with the same - // name already exists or not, and if it exists, we shouldn't define a new - // accessor property (it fails). - documentWrapper->SetAccessor(m_isolate->GetCurrentContext(), - v8String(m_isolate, name), getter); -} - -void WindowProxy::namedItemRemoved(HTMLDocument* document, - const AtomicString& name) { - DCHECK(m_world->isMainWorld()); - - // Context must be initialized before this point. - DCHECK(m_lifecycle >= Lifecycle::ContextInitialized); - // TODO(yukishiino): Is it okay to not update named properties - // after the context gets detached? - if (m_lifecycle == Lifecycle::ContextDetached) - return; - - if (document->hasNamedItem(name) || document->hasExtraNamedItem(name)) - return; - ScriptState::Scope scope(m_scriptState.get()); - v8::Local<v8::Object> documentWrapper = - m_world->domDataStore().get(document, m_isolate); - documentWrapper - ->Delete(m_isolate->GetCurrentContext(), v8String(m_isolate, name)) - .ToChecked(); -} - -void WindowProxy::updateSecurityOrigin(SecurityOrigin* origin) { - // For an uninitialized main window proxy, there's nothing we need - // to update. The update is done when the window proxy gets initialized later. - if (m_lifecycle == Lifecycle::ContextUninitialized) - return; - // TODO(yukishiino): Is it okay to not update security origin when the context - // is detached? - if (m_lifecycle == Lifecycle::ContextDetached) - return; - - setSecurityToken(origin); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h index 9f074f2b..9089f01 100644 --- a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h +++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h
@@ -35,55 +35,43 @@ #include "bindings/core/v8/ScopedPersistent.h" #include "bindings/core/v8/ScriptState.h" #include "platform/heap/Handle.h" -#include "platform/weborigin/SecurityOrigin.h" -#include "wtf/HashMap.h" -#include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" -#include "wtf/text/AtomicString.h" #include <v8.h> namespace blink { class Frame; -class HTMLDocument; -class SecurityOrigin; +class ScriptController; // WindowProxy represents all the per-global object state for a Frame that // persist between navigations. -class WindowProxy final : public GarbageCollectedFinalized<WindowProxy> { +class WindowProxy : public GarbageCollectedFinalized<WindowProxy> { public: - static WindowProxy* create(v8::Isolate*, Frame*, DOMWrapperWorld&); + virtual ~WindowProxy(); - ~WindowProxy(); DECLARE_TRACE(); v8::Local<v8::Context> contextIfInitialized() const { return m_scriptState ? m_scriptState->context() : v8::Local<v8::Context>(); } - ScriptState* getScriptState() const { return m_scriptState.get(); } - - // Update document object of the frame. - void updateDocument(); - - void namedItemAdded(HTMLDocument*, const AtomicString&); - void namedItemRemoved(HTMLDocument*, const AtomicString&); - - // Update the security origin of a document - // (e.g., after setting docoument.domain). - void updateSecurityOrigin(SecurityOrigin*); - void initializeIfNeeded(); - void clearForNavigation(); void clearForClose(); + void clearForNavigation(); v8::Local<v8::Object> globalIfNotDetached(); v8::Local<v8::Object> releaseGlobal(); void setGlobal(v8::Local<v8::Object>); + // TODO(dcheng): Temporarily exposed to avoid include cycles. Remove the need + // for this and remove this getter. DOMWrapperWorld& world() { return *m_world; } - private: + protected: + // TODO(dcheng): Remove this friend declaration once LocalWindowProxyManager + // and ScriptController are merged. + friend class ScriptController; + // A valid transition is from ContextUninitialized to ContextInitialized, // and then ContextDetached. Other transitions are forbidden. enum class Lifecycle { @@ -92,36 +80,31 @@ ContextDetached, }; - WindowProxy(Frame*, PassRefPtr<DOMWrapperWorld>, v8::Isolate*); - void initialize(); + WindowProxy(v8::Isolate*, Frame&, RefPtr<DOMWrapperWorld>); + + virtual void initialize() = 0; enum GlobalDetachmentBehavior { DoNotDetachGlobal, DetachGlobal }; - void disposeContext(GlobalDetachmentBehavior); - - void setSecurityToken(SecurityOrigin*); - - // The JavaScript wrapper for the document object is cached on the global - // object for fast access. UpdateDocumentProperty sets the wrapper - // for the current document on the global object. - void updateDocumentProperty(); - - // Updates Activity Logger for the current context. - void updateActivityLogger(); - - // Creates a new v8::Context with the window wrapper object as the global - // object (aka the inner global). Note that the window wrapper and its - // prototype chain do not get fully initialized yet, e.g. the window - // wrapper is not yet associated with the native DOMWindow object. - void createContext(); + virtual void disposeContext(GlobalDetachmentBehavior); // Associates the window wrapper and its prototype chain with the native // DOMWindow object. Also does some more Window-specific initialization. void setupWindowPrototypeChain(); - Member<Frame> m_frame; - v8::Isolate* m_isolate; + v8::Isolate* isolate() const { return m_isolate; } + Frame* frame() const { return m_frame.get(); } + ScriptState* getScriptState() const { return m_scriptState.get(); } + + private: + v8::Isolate* const m_isolate; + const Member<Frame> m_frame; + + protected: + // TODO(dcheng): Move this to LocalWindowProxy once RemoteWindowProxy uses + // remote contexts. RefPtr<ScriptState> m_scriptState; - RefPtr<DOMWrapperWorld> m_world; + // TODO(dcheng): Consider making these private and using getters. + const RefPtr<DOMWrapperWorld> m_world; ScopedPersistent<v8::Object> m_globalProxy; Lifecycle m_lifecycle; };
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp index d73a8213..8e7a752 100644 --- a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp
@@ -5,22 +5,31 @@ #include "bindings/core/v8/WindowProxyManager.h" #include "bindings/core/v8/DOMWrapperWorld.h" -#include "bindings/core/v8/WindowProxy.h" -#include "core/frame/Frame.h" namespace blink { -WindowProxyManager* WindowProxyManager::create(Frame& frame) { - return new WindowProxyManager(frame); +namespace { + +WindowProxy* createWindowProxyForFrame(v8::Isolate* isolate, + Frame& frame, + + RefPtr<DOMWrapperWorld> world) { + if (frame.isLocalFrame()) { + return LocalWindowProxy::create(isolate, toLocalFrame(frame), + std::move(world)); + } + return RemoteWindowProxy::create(isolate, toRemoteFrame(frame), + std::move(world)); +} } -DEFINE_TRACE(WindowProxyManager) { +DEFINE_TRACE(WindowProxyManagerBase) { visitor->trace(m_frame); visitor->trace(m_windowProxy); visitor->trace(m_isolatedWorlds); } -WindowProxy* WindowProxyManager::windowProxy(DOMWrapperWorld& world) { +WindowProxy* WindowProxyManagerBase::windowProxy(DOMWrapperWorld& world) { WindowProxy* windowProxy = nullptr; if (world.isMainWorld()) { windowProxy = m_windowProxy.get(); @@ -29,36 +38,26 @@ if (iter != m_isolatedWorlds.end()) { windowProxy = iter->value.get(); } else { - windowProxy = WindowProxy::create(m_isolate, m_frame, world); + windowProxy = createWindowProxyForFrame(m_isolate, *m_frame, &world); m_isolatedWorlds.set(world.worldId(), windowProxy); } } return windowProxy; } -void WindowProxyManager::clearForClose() { +void WindowProxyManagerBase::clearForClose() { m_windowProxy->clearForClose(); for (auto& entry : m_isolatedWorlds) entry.value->clearForClose(); } -void WindowProxyManager::clearForNavigation() { +void WindowProxyManagerBase::clearForNavigation() { m_windowProxy->clearForNavigation(); for (auto& entry : m_isolatedWorlds) entry.value->clearForNavigation(); } -void WindowProxyManager::updateSecurityOrigin(SecurityOrigin* securityOrigin) { - m_windowProxy->updateSecurityOrigin(securityOrigin); - for (auto& entry : m_isolatedWorlds) { - WindowProxy* isolatedWindowProxy = entry.value.get(); - SecurityOrigin* isolatedSecurityOrigin = - isolatedWindowProxy->world().isolatedWorldSecurityOrigin(); - isolatedWindowProxy->updateSecurityOrigin(isolatedSecurityOrigin); - } -} - -void WindowProxyManager::releaseGlobals( +void WindowProxyManagerBase::releaseGlobals( HashMap<DOMWrapperWorld*, v8::Local<v8::Object>>& map) { map.add(&m_windowProxy->world(), m_windowProxy->releaseGlobal()); for (auto& entry : m_isolatedWorlds) @@ -66,17 +65,30 @@ windowProxy(entry.value->world())->releaseGlobal()); } -void WindowProxyManager::setGlobals( +void WindowProxyManagerBase::setGlobals( const HashMap<DOMWrapperWorld*, v8::Local<v8::Object>>& map) { for (auto& entry : map) windowProxy(*entry.key)->setGlobal(entry.value); } -WindowProxyManager::WindowProxyManager(Frame& frame) - : m_frame(&frame), - m_isolate(v8::Isolate::GetCurrent()), - m_windowProxy(WindowProxy::create(m_isolate, - &frame, - DOMWrapperWorld::mainWorld())) {} +WindowProxyManagerBase::WindowProxyManagerBase(Frame& frame) + : m_isolate(v8::Isolate::GetCurrent()), + m_frame(&frame), + m_windowProxy(createWindowProxyForFrame(m_isolate, + frame, + &DOMWrapperWorld::mainWorld())) {} + +void LocalWindowProxyManager::updateSecurityOrigin( + SecurityOrigin* securityOrigin) { + static_cast<LocalWindowProxy*>(mainWorldProxy()) + ->updateSecurityOrigin(securityOrigin); + for (auto& entry : isolatedWorlds()) { + auto* isolatedWindowProxy = + static_cast<LocalWindowProxy*>(entry.value.get()); + SecurityOrigin* isolatedSecurityOrigin = + isolatedWindowProxy->world().isolatedWorldSecurityOrigin(); + isolatedWindowProxy->updateSecurityOrigin(isolatedSecurityOrigin); + } +} } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h index e785aff..a70c384d 100644 --- a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h +++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h
@@ -5,52 +5,101 @@ #ifndef WindowProxyManager_h #define WindowProxyManager_h +#include "bindings/core/v8/LocalWindowProxy.h" +#include "bindings/core/v8/RemoteWindowProxy.h" #include "core/CoreExport.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/RemoteFrame.h" #include "platform/heap/Handle.h" -#include "wtf/Vector.h" #include <utility> #include <v8.h> namespace blink { class DOMWrapperWorld; -class Frame; class SecurityOrigin; -class WindowProxy; +class ScriptController; -class CORE_EXPORT WindowProxyManager final - : public GarbageCollected<WindowProxyManager> { +class WindowProxyManagerBase : public GarbageCollected<WindowProxyManagerBase> { public: - static WindowProxyManager* create(Frame&); - DECLARE_TRACE(); - Frame* frame() const { return m_frame.get(); } v8::Isolate* isolate() const { return m_isolate; } - WindowProxy* mainWorldProxy() const { return m_windowProxy.get(); } - - WindowProxy* windowProxy(DOMWrapperWorld&); void clearForClose(); - void clearForNavigation(); + void CORE_EXPORT clearForNavigation(); + + void CORE_EXPORT + releaseGlobals(HashMap<DOMWrapperWorld*, v8::Local<v8::Object>>&); + void CORE_EXPORT + setGlobals(const HashMap<DOMWrapperWorld*, v8::Local<v8::Object>>&); + + protected: + using IsolatedWorldMap = HeapHashMap<int, Member<WindowProxy>>; + + explicit WindowProxyManagerBase(Frame&); + + Frame* frame() const { return m_frame; } + WindowProxy* mainWorldProxy() const { return m_windowProxy.get(); } + WindowProxy* windowProxy(DOMWrapperWorld&); + + IsolatedWorldMap& isolatedWorlds() { return m_isolatedWorlds; } + + private: + v8::Isolate* const m_isolate; + const Member<Frame> m_frame; + const Member<WindowProxy> m_windowProxy; + IsolatedWorldMap m_isolatedWorlds; +}; + +template <typename FrameType, typename ProxyType> +class WindowProxyManagerImplHelper : public WindowProxyManagerBase { + private: + using Base = WindowProxyManagerBase; + + public: + FrameType* frame() const { return static_cast<FrameType*>(Base::frame()); } + ProxyType* mainWorldProxy() const { + return static_cast<ProxyType*>(Base::mainWorldProxy()); + } + ProxyType* windowProxy(DOMWrapperWorld& world) { + return static_cast<ProxyType*>(Base::windowProxy(world)); + } + + protected: + explicit WindowProxyManagerImplHelper(Frame& frame) + : WindowProxyManagerBase(frame) {} +}; + +class LocalWindowProxyManager + : public WindowProxyManagerImplHelper<LocalFrame, LocalWindowProxy> { + public: + static LocalWindowProxyManager* create(LocalFrame& frame) { + return new LocalWindowProxyManager(frame); + } // Sets the given security origin to the main world's context. Also updates // the security origin of the context for each isolated world. void updateSecurityOrigin(SecurityOrigin*); - void releaseGlobals(HashMap<DOMWrapperWorld*, v8::Local<v8::Object>>&); - void setGlobals(const HashMap<DOMWrapperWorld*, v8::Local<v8::Object>>&); + private: + // TODO(dcheng): Merge LocalWindowProxyManager and ScriptController? + friend class ScriptController; + + explicit LocalWindowProxyManager(LocalFrame& frame) + : WindowProxyManagerImplHelper<LocalFrame, LocalWindowProxy>(frame) {} +}; + +class RemoteWindowProxyManager + : public WindowProxyManagerImplHelper<RemoteFrame, RemoteWindowProxy> { + public: + static RemoteWindowProxyManager* create(RemoteFrame& frame) { + return new RemoteWindowProxyManager(frame); + } private: - typedef HeapHashMap<int, Member<WindowProxy>> IsolatedWorldMap; - - explicit WindowProxyManager(Frame&); - - Member<Frame> m_frame; - v8::Isolate* const m_isolate; - - const Member<WindowProxy> m_windowProxy; - IsolatedWorldMap m_isolatedWorlds; + explicit RemoteWindowProxyManager(RemoteFrame& frame) + : WindowProxyManagerImplHelper<RemoteFrame, RemoteWindowProxy>(frame) {} }; } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_interface.py b/third_party/WebKit/Source/bindings/scripts/v8_interface.py index c8aeceb6..c72c8e2 100644 --- a/third_party/WebKit/Source/bindings/scripts/v8_interface.py +++ b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
@@ -254,6 +254,10 @@ cpp_class_name_or_partial = cpp_name_or_partial(interface) v8_class_name_or_partial = v8_utilities.v8_class_name_or_partial(interface) + # TODO(peria): Generate the target list from 'Window' and 'HTMLDocument'. + needs_runtime_enabled_installer = v8_class_name in [ + 'V8Window', 'V8HTMLDocument', 'V8Document', 'V8Node', 'V8EventTarget'] + context = { 'cpp_class': cpp_class_name, 'cpp_class_or_partial': cpp_class_name_or_partial, @@ -279,6 +283,7 @@ 'is_typed_array_type': is_typed_array_type, 'lifetime': 'Dependent' if (has_visit_dom_wrapper or is_dependent_lifetime) else 'Independent', 'measure_as': v8_utilities.measure_as(interface, None), # [MeasureAs] + 'needs_runtime_enabled_installer': needs_runtime_enabled_installer, 'origin_trial_enabled_function': v8_utilities.origin_trial_enabled_function_name(interface), 'parent_interface': parent_interface, 'pass_cpp_type': cpp_name(interface) + '*',
diff --git a/third_party/WebKit/Source/bindings/templates/interface.h.tmpl b/third_party/WebKit/Source/bindings/templates/interface.h.tmpl index 5fd5568..8f6e6d6 100644 --- a/third_party/WebKit/Source/bindings/templates/interface.h.tmpl +++ b/third_party/WebKit/Source/bindings/templates/interface.h.tmpl
@@ -150,6 +150,15 @@ {% endfor %} {% endif %} + {% if needs_runtime_enabled_installer %} + {{exported}}static void installRuntimeEnabledFeatures( + v8::Isolate* isolate, + const DOMWrapperWorld& world, + v8::Local<v8::Object> instance, + v8::Local<v8::Object> prototype, + v8::Local<v8::Function> interface); + {% endif %} + {% for feature in origin_trial_features %} static void install{{feature.name}}(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, v8::Local<v8::Function> interface);
diff --git a/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl index 9c1cabcd..4f5907c 100644 --- a/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl +++ b/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
@@ -527,6 +527,71 @@ {% endif %}{# not is_array_buffer_or_view #} {% endblock %} {##############################################################################} +{% block install_runtime_enabled %} +{% if needs_runtime_enabled_installer %} +{% from 'attributes.cpp.tmpl' import attribute_configuration with context %} +{% from 'methods.cpp.tmpl' import install_custom_signature with context %} +void {{v8_class_or_partial}}::installRuntimeEnabledFeatures(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, v8::Local<v8::Function> interface) { + {% if runtime_enabled_feature_name %} +#error "We don't expect a runtime enabled interface {{v8_class_or_partial}} to have installRuntimeEnabledFeatures()." + {% endif %} + + {% if is_partial %} + {{v8_class}}::installRuntimeEnabledFeatures(isolate, world, instance, prototype, interface); + {% endif %} + + v8::Local<v8::FunctionTemplate> interfaceTemplate = {{v8_class}}::wrapperTypeInfo.domTemplate(isolate, world); + v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate); + ALLOW_UNUSED_LOCAL(signature); + + {# TODO(peria): Generate code to install constants. It depends on runtime_enabled_feaure of this interface. #} + + {% for feature_name, attrs in runtime_enabled_attributes | groupby('runtime_enabled_feature_name') %} + {% filter runtime_enabled(feature_name) %} + {% for attribute in attrs | unique_by('name') | sort %} + {% if attribute.is_data_type_property %} + const V8DOMConfiguration::AttributeConfiguration attribute{{attribute.name}}Configuration = {{attribute_configuration(attribute)}}; + V8DOMConfiguration::installAttribute(isolate, world, instance, prototype, attribute{{attribute.name}}Configuration); + {% else %} + const V8DOMConfiguration::AccessorConfiguration accessor{{attribute.name}}Configuration = {{attribute_configuration(attribute)}}; + V8DOMConfiguration::installAccessor(isolate, world, instance, prototype, interface, signature, accessor{{attribute.name}}Configuration); + {% endif %} + {% endfor %} + {% endfilter %} + {% endfor %} + + {% if iterator_method and iterator_method.runtime_enabled_feature_name %} + {% filter exposed(iterator_method.exposed_test) %} + {% filter runtime_enabled(iterator_method.runtime_enabled_feature_name) %} + // Runtime enabled iterator (@@iterator) +#error "{{v8_class_or_partial}} should not have runtime enabled iterators." + {% endfilter %} + {% endfilter %} + {% endif %} + + {% if methods | custom_registration(is_partial) %} + {% for method in methods | custom_registration(is_partial) %} + {% filter exposed(method.overloads.exposed_test_all + if method.overloads else method.exposed_test) %} + {% set feature_name = (method.overloads.runtime_enabled_all + if method.overloads else method.runtime_enabled_feature_name) %} + {% if feature_name %} + {% filter runtime_enabled(feature_name) %} + {% if method.is_cross_origin %} +#error "{{v8_class_or_partial}} should not have runtime enabled and cross origin methods." + {% else %} + {{install_custom_signature(method, 'instance', 'prototype', 'interface', 'signature') | indent(2)}} + {% endif %} + {% endfilter %} + {% endif %} + {% endfilter %} + {% endfor %} + {% endif %} +} + +{% endif %}{# needs_runtime_enabled_installer #} +{% endblock %} +{##############################################################################} {% block origin_trials %} {% from 'attributes.cpp.tmpl' import attribute_configuration with context %} {% from 'constants.cpp.tmpl' import constant_configuration with context %}
diff --git a/third_party/WebKit/Source/bindings/templates/partial_interface.h.tmpl b/third_party/WebKit/Source/bindings/templates/partial_interface.h.tmpl index 1359c46..0af2797 100644 --- a/third_party/WebKit/Source/bindings/templates/partial_interface.h.tmpl +++ b/third_party/WebKit/Source/bindings/templates/partial_interface.h.tmpl
@@ -42,6 +42,15 @@ {% endif %} {% endfor %} + {% if needs_runtime_enabled_installer %} + static void installRuntimeEnabledFeatures( + v8::Isolate* isolate, + const DOMWrapperWorld& world, + v8::Local<v8::Object> instance, + v8::Local<v8::Object> prototype, + v8::Local<v8::Function> interface); + {% endif %} + private: static void install{{v8_class}}Template(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::FunctionTemplate> interfaceTemplate); };
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni index 0a8ab8ee..8dfad6f 100644 --- a/third_party/WebKit/Source/core/core_idl_files.gni +++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -191,6 +191,7 @@ "frame/ImageBitmap.idl", "frame/Location.idl", "frame/VisualViewport.idl", + "html/Float32ImageData.idl", "html/FormData.idl", "html/HTMLAllCollection.idl", "html/HTMLAnchorElement.idl",
diff --git a/third_party/WebKit/Source/core/dom/DOMTypedArray.h b/third_party/WebKit/Source/core/dom/DOMTypedArray.h index 292003a..f4b6893 100644 --- a/third_party/WebKit/Source/core/dom/DOMTypedArray.h +++ b/third_party/WebKit/Source/core/dom/DOMTypedArray.h
@@ -54,7 +54,8 @@ } static ThisType* createOrNull(unsigned length) { - RefPtr<WTF::ArrayBuffer> buffer = WTF::ArrayBuffer::createOrNull(length, 1); + RefPtr<WTF::ArrayBuffer> buffer = + WTF::ArrayBuffer::createOrNull(length, sizeof(ThisType)); return buffer ? create(buffer.release(), 0, length) : nullptr; }
diff --git a/third_party/WebKit/Source/core/frame/Frame.h b/third_party/WebKit/Source/core/frame/Frame.h index 5f0aec9..ba5e83e 100644 --- a/third_party/WebKit/Source/core/frame/Frame.h +++ b/third_party/WebKit/Source/core/frame/Frame.h
@@ -54,7 +54,7 @@ class SecurityContext; class Settings; class WindowProxy; -class WindowProxyManager; +class WindowProxyManagerBase; struct FrameLoadRequest; enum class FrameDetachType { Remove, Swap }; @@ -143,7 +143,7 @@ void setIsLoading(bool isLoading) { m_isLoading = isLoading; } bool isLoading() const { return m_isLoading; } - virtual WindowProxyManager* getWindowProxyManager() const = 0; + virtual WindowProxyManagerBase* getWindowProxyManager() const = 0; virtual void didChangeVisibilityState();
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp index f6ba656..858f4d3 100644 --- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp +++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
@@ -4,6 +4,7 @@ #include "core/frame/ImageBitmap.h" +#include "core/html/Float32ImageData.h" #include "core/html/HTMLCanvasElement.h" #include "core/html/HTMLVideoElement.h" #include "core/html/ImageData.h" @@ -757,6 +758,8 @@ resizedPixels.release().leakRef()); } +// TODO(zakerinasab): Fix this and the constructor from Float32ImageData +// when the CL for Float32ImageData landed. ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const ImageBitmapOptions& options) { @@ -905,6 +908,10 @@ m_image = StaticBitmapImage::create(std::move(skImage)); } +ImageBitmap::ImageBitmap(Float32ImageData* data, + Optional<IntRect> cropRect, + const ImageBitmapOptions& options) {} + ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const ImageBitmapOptions& options) { @@ -989,6 +996,12 @@ return new ImageBitmap(data, cropRect, options); } +ImageBitmap* ImageBitmap::create(Float32ImageData* data, + Optional<IntRect> cropRect, + const ImageBitmapOptions& options) { + return new ImageBitmap(data, cropRect, options); +} + ImageBitmap* ImageBitmap::create(ImageBitmap* bitmap, Optional<IntRect> cropRect, const ImageBitmapOptions& options) {
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.h b/third_party/WebKit/Source/core/frame/ImageBitmap.h index 99fd4d5..eab4930 100644 --- a/third_party/WebKit/Source/core/frame/ImageBitmap.h +++ b/third_party/WebKit/Source/core/frame/ImageBitmap.h
@@ -21,6 +21,7 @@ #include <memory> namespace blink { +class Float32ImageData; class HTMLCanvasElement; class HTMLVideoElement; class ImageData; @@ -65,6 +66,9 @@ static ImageBitmap* create(ImageData*, Optional<IntRect>, const ImageBitmapOptions& = ImageBitmapOptions()); + static ImageBitmap* create(Float32ImageData*, + Optional<IntRect>, + const ImageBitmapOptions& = ImageBitmapOptions()); static ImageBitmap* create(ImageBitmap*, Optional<IntRect>, const ImageBitmapOptions& = ImageBitmapOptions()); @@ -150,6 +154,7 @@ ImageBitmap(HTMLCanvasElement*, Optional<IntRect>, const ImageBitmapOptions&); ImageBitmap(OffscreenCanvas*, Optional<IntRect>, const ImageBitmapOptions&); ImageBitmap(ImageData*, Optional<IntRect>, const ImageBitmapOptions&); + ImageBitmap(Float32ImageData*, Optional<IntRect>, const ImageBitmapOptions&); ImageBitmap(ImageBitmap*, Optional<IntRect>, const ImageBitmapOptions&); ImageBitmap(PassRefPtr<StaticBitmapImage>); ImageBitmap(PassRefPtr<StaticBitmapImage>,
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp index f866542c..1d711cb 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -494,7 +494,7 @@ ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); } -WindowProxyManager* LocalFrame::getWindowProxyManager() const { +WindowProxyManagerBase* LocalFrame::getWindowProxyManager() const { return m_script->getWindowProxyManager(); }
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.h b/third_party/WebKit/Source/core/frame/LocalFrame.h index da62177a..2b8671e 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.h +++ b/third_party/WebKit/Source/core/frame/LocalFrame.h
@@ -236,7 +236,7 @@ InterfaceRegistry*); // Internal Frame helper overrides: - WindowProxyManager* getWindowProxyManager() const override; + WindowProxyManagerBase* getWindowProxyManager() const override; // Intentionally private to prevent redundant checks when the type is // already LocalFrame. bool isLocalFrame() const override { return true; }
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp index 558aed7e..c9c83df3 100644 --- a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp +++ b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
@@ -30,7 +30,7 @@ FrameOwner* owner) : Frame(client, host, owner), m_securityContext(RemoteSecurityContext::create()), - m_windowProxyManager(WindowProxyManager::create(*this)) { + m_windowProxyManager(RemoteWindowProxyManager::create(*this)) { m_domWindow = RemoteDOMWindow::create(*this); } @@ -187,6 +187,10 @@ client()->advanceFocus(type, source); } +WindowProxyManagerBase* RemoteFrame::getWindowProxyManager() const { + return m_windowProxyManager.get(); +} + void RemoteFrame::detachChildren() { using FrameVector = HeapVector<Member<Frame>>; FrameVector childrenToDetach;
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.h b/third_party/WebKit/Source/core/frame/RemoteFrame.h index 777c92d9..412ec72e8 100644 --- a/third_party/WebKit/Source/core/frame/RemoteFrame.h +++ b/third_party/WebKit/Source/core/frame/RemoteFrame.h
@@ -17,8 +17,8 @@ class LocalFrame; class RemoteFrameClient; class RemoteFrameView; +class RemoteWindowProxyManager; class WebLayer; -class WindowProxyManager; struct FrameLoadRequest; class CORE_EXPORT RemoteFrame final : public Frame { @@ -68,9 +68,8 @@ RemoteFrame(RemoteFrameClient*, FrameHost*, FrameOwner*); // Internal Frame helper overrides: - WindowProxyManager* getWindowProxyManager() const override { - return m_windowProxyManager.get(); - } + WindowProxyManagerBase* getWindowProxyManager() const override; + // Intentionally private to prevent redundant checks when the type is // already RemoteFrame. bool isLocalFrame() const override { return false; } @@ -80,7 +79,7 @@ Member<RemoteFrameView> m_view; Member<RemoteSecurityContext> m_securityContext; - Member<WindowProxyManager> m_windowProxyManager; + Member<RemoteWindowProxyManager> m_windowProxyManager; WebLayer* m_webLayer = nullptr; };
diff --git a/third_party/WebKit/Source/core/frame/ScreenOrientationController.cpp b/third_party/WebKit/Source/core/frame/ScreenOrientationController.cpp index e8104123..9e35cec 100644 --- a/third_party/WebKit/Source/core/frame/ScreenOrientationController.cpp +++ b/third_party/WebKit/Source/core/frame/ScreenOrientationController.cpp
@@ -6,6 +6,9 @@ namespace blink { +ScreenOrientationController::ScreenOrientationController(LocalFrame& frame) + : Supplement<LocalFrame>(frame) {} + // static ScreenOrientationController* ScreenOrientationController::from( LocalFrame& frame) {
diff --git a/third_party/WebKit/Source/core/frame/ScreenOrientationController.h b/third_party/WebKit/Source/core/frame/ScreenOrientationController.h index 7c80e30..fbe0e274 100644 --- a/third_party/WebKit/Source/core/frame/ScreenOrientationController.h +++ b/third_party/WebKit/Source/core/frame/ScreenOrientationController.h
@@ -19,7 +19,11 @@ // module will implement and add a provider for. // Callers of ScreenOrientationController::from() should always assume the // returned pointer can be nullptr. -class CORE_EXPORT ScreenOrientationController : public Supplement<LocalFrame> { +class CORE_EXPORT ScreenOrientationController + : public GarbageCollectedFinalized<ScreenOrientationController>, + public Supplement<LocalFrame> { + USING_GARBAGE_COLLECTED_MIXIN(ScreenOrientationController); + public: virtual ~ScreenOrientationController() = default; @@ -38,6 +42,7 @@ DECLARE_VIRTUAL_TRACE(); protected: + explicit ScreenOrientationController(LocalFrame&); // To be called by an ScreenOrientationController to register its // implementation. static void provideTo(LocalFrame&, ScreenOrientationController*);
diff --git a/third_party/WebKit/Source/core/html/BUILD.gn b/third_party/WebKit/Source/core/html/BUILD.gn index 63cfdfcb..0fab038 100644 --- a/third_party/WebKit/Source/core/html/BUILD.gn +++ b/third_party/WebKit/Source/core/html/BUILD.gn
@@ -17,6 +17,8 @@ "CrossOriginAttribute.h", "DocumentNameCollection.cpp", "DocumentNameCollection.h", + "Float32ImageData.cpp", + "Float32ImageData.h", "FormAssociated.h", "FormData.cpp", "FormData.h",
diff --git a/third_party/WebKit/Source/core/html/Float32ImageData.cpp b/third_party/WebKit/Source/core/html/Float32ImageData.cpp new file mode 100644 index 0000000..665a265 --- /dev/null +++ b/third_party/WebKit/Source/core/html/Float32ImageData.cpp
@@ -0,0 +1,197 @@ +/* + * Copyright (C) 2016 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core/html/Float32ImageData.h" + +#include "bindings/core/v8/ExceptionState.h" +#include "bindings/core/v8/V8Float32Array.h" +#include "core/dom/ExceptionCode.h" +#include "core/frame/ImageBitmap.h" +#include "core/imagebitmap/ImageBitmapOptions.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "wtf/CheckedNumeric.h" + +namespace blink { + +bool Float32ImageData::validateConstructorArguments( + const unsigned& paramFlags, + const IntSize* size, + const unsigned& width, + const unsigned& height, + const DOMFloat32Array* data, + const String* colorSpace, + ExceptionState* exceptionState) { + return ImageData::validateConstructorArguments( + paramFlags, size, width, height, data, colorSpace, exceptionState, + kFloat32ImageData); +} + +DOMFloat32Array* Float32ImageData::allocateAndValidateFloat32Array( + const unsigned& length, + ExceptionState* exceptionState) { + if (!length) + return nullptr; + DOMFloat32Array* dataArray = DOMFloat32Array::createOrNull(length); + if (!dataArray || length != dataArray->length()) { + if (exceptionState) { + exceptionState->throwDOMException( + V8RangeError, "Out of memory at Float32ImageData creation"); + } + return nullptr; + } + return dataArray; +} + +Float32ImageData* Float32ImageData::create(const IntSize& size) { + if (!Float32ImageData::validateConstructorArguments(kParamSize, &size)) + return nullptr; + DOMFloat32Array* dataArray = + Float32ImageData::allocateAndValidateFloat32Array(4 * size.width() * + size.height()); + return dataArray ? new Float32ImageData(size, dataArray) : nullptr; +} + +Float32ImageData* Float32ImageData::create(const IntSize& size, + DOMFloat32Array* dataArray) { + if (!Float32ImageData::validateConstructorArguments(kParamSize | kParamData, + &size, 0, 0, dataArray)) + return nullptr; + return new Float32ImageData(size, dataArray); +} + +Float32ImageData* Float32ImageData::create(unsigned width, + unsigned height, + ExceptionState& exceptionState) { + if (!Float32ImageData::validateConstructorArguments( + kParamWidth | kParamHeight, nullptr, width, height, nullptr, nullptr, + &exceptionState)) + return nullptr; + DOMFloat32Array* dataArray = + Float32ImageData::allocateAndValidateFloat32Array(4 * width * height, + &exceptionState); + return dataArray ? new Float32ImageData(IntSize(width, height), dataArray) + : nullptr; +} + +Float32ImageData* Float32ImageData::create(DOMFloat32Array* data, + unsigned width, + ExceptionState& exceptionState) { + if (!Float32ImageData::validateConstructorArguments(kParamData | kParamWidth, + nullptr, width, 0, data, + nullptr, &exceptionState)) + return nullptr; + unsigned height = data->length() / (width * 4); + return new Float32ImageData(IntSize(width, height), data); +} + +Float32ImageData* Float32ImageData::create(DOMFloat32Array* data, + unsigned width, + unsigned height, + ExceptionState& exceptionState) { + if (!Float32ImageData::validateConstructorArguments( + kParamData | kParamWidth | kParamHeight, nullptr, width, height, data, + nullptr, &exceptionState)) + return nullptr; + return new Float32ImageData(IntSize(width, height), data); +} + +Float32ImageData* Float32ImageData::create(unsigned width, + unsigned height, + String colorSpace, + ExceptionState& exceptionState) { + if (!Float32ImageData::validateConstructorArguments( + kParamWidth | kParamHeight | kParamColorSpace, nullptr, width, height, + nullptr, &colorSpace, &exceptionState)) + return nullptr; + + DOMFloat32Array* dataArray = + Float32ImageData::allocateAndValidateFloat32Array(4 * width * height, + &exceptionState); + return dataArray ? new Float32ImageData(IntSize(width, height), dataArray, + colorSpace) + : nullptr; +} + +Float32ImageData* Float32ImageData::create(DOMFloat32Array* data, + unsigned width, + String colorSpace, + ExceptionState& exceptionState) { + if (!Float32ImageData::validateConstructorArguments( + kParamData | kParamWidth | kParamColorSpace, nullptr, width, 0, data, + &colorSpace, &exceptionState)) + return nullptr; + unsigned height = data->length() / (width * 4); + return new Float32ImageData(IntSize(width, height), data, colorSpace); +} + +Float32ImageData* Float32ImageData::create(DOMFloat32Array* data, + unsigned width, + unsigned height, + String colorSpace, + ExceptionState& exceptionState) { + if (!Float32ImageData::validateConstructorArguments( + kParamData | kParamWidth | kParamHeight | kParamColorSpace, nullptr, + width, height, data, &colorSpace, &exceptionState)) + return nullptr; + return new Float32ImageData(IntSize(width, height), data, colorSpace); +} + +v8::Local<v8::Object> Float32ImageData::associateWithWrapper( + v8::Isolate* isolate, + const WrapperTypeInfo* wrapperType, + v8::Local<v8::Object> wrapper) { + wrapper = + ScriptWrappable::associateWithWrapper(isolate, wrapperType, wrapper); + + if (!wrapper.IsEmpty() && m_data.get()) { + // Create a V8 Float32Array object and set the "data" property + // of the Float32ImageData object to the created v8 object, eliminating the + // C++ callback when accessing the "data" property. + v8::Local<v8::Value> pixelArray = ToV8(m_data.get(), wrapper, isolate); + if (pixelArray.IsEmpty() || + !v8CallBoolean(wrapper->DefineOwnProperty( + isolate->GetCurrentContext(), v8AtomicString(isolate, "data"), + pixelArray, v8::ReadOnly))) + return v8::Local<v8::Object>(); + } + return wrapper; +} + +Float32ImageData::Float32ImageData(const IntSize& size, + DOMFloat32Array* dataArray, + String colorSpaceName) + : m_size(size), + m_colorSpace(ImageData::getImageDataColorSpace(colorSpaceName)), + m_data(dataArray) { + DCHECK_GE(size.width(), 0); + DCHECK_GE(size.height(), 0); + SECURITY_CHECK(static_cast<unsigned>(size.width() * size.height() * 4) <= + m_data->length()); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/html/Float32ImageData.h b/third_party/WebKit/Source/core/html/Float32ImageData.h new file mode 100644 index 0000000..361fb1d --- /dev/null +++ b/third_party/WebKit/Source/core/html/Float32ImageData.h
@@ -0,0 +1,120 @@ +/* + * Copyright (C) 2016 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Float32ImageData_h +#define Float32ImageData_h + +#include "bindings/core/v8/ScriptWrappable.h" +#include "core/CoreExport.h" +#include "core/dom/DOMTypedArray.h" +#include "core/html/ImageData.h" +#include "core/imagebitmap/ImageBitmapSource.h" +#include "platform/geometry/IntRect.h" +#include "platform/geometry/IntSize.h" +#include "platform/heap/Handle.h" +#include "wtf/Compiler.h" +#include "wtf/text/WTFString.h" + +namespace blink { + +class ExceptionState; + +class CORE_EXPORT Float32ImageData final + : public GarbageCollectedFinalized<Float32ImageData>, + public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); + + public: + static Float32ImageData* create(const IntSize&); + static Float32ImageData* create(const IntSize&, DOMFloat32Array*); + static Float32ImageData* create(unsigned width, + unsigned height, + ExceptionState&); + static Float32ImageData* create(unsigned width, + unsigned height, + String colorSpace, + ExceptionState&); + static Float32ImageData* create(DOMFloat32Array*, + unsigned width, + ExceptionState&); + static Float32ImageData* create(DOMFloat32Array*, + unsigned width, + String colorSpace, + ExceptionState&); + static Float32ImageData* create(DOMFloat32Array*, + unsigned width, + unsigned height, + ExceptionState&); + static Float32ImageData* create(DOMFloat32Array*, + unsigned width, + unsigned height, + String colorSpace, + ExceptionState&); + + IntSize size() const { return m_size; } + int width() const { return m_size.width(); } + int height() const { return m_size.height(); } + String colorSpace() const { + return ImageData::getImageDataColorSpaceName(m_colorSpace); + } + ImageDataColorSpace imageDataColorSpace() { return m_colorSpace; } + const DOMFloat32Array* data() const { return m_data.get(); } + DOMFloat32Array* data() { return m_data.get(); } + + DEFINE_INLINE_TRACE() { visitor->trace(m_data); } + + WARN_UNUSED_RESULT v8::Local<v8::Object> associateWithWrapper( + v8::Isolate*, + const WrapperTypeInfo*, + v8::Local<v8::Object> wrapper) override; + + private: + Float32ImageData(const IntSize&, + DOMFloat32Array*, + String = kLinearRGBImageDataColorSpaceName); + + IntSize m_size; + ImageDataColorSpace m_colorSpace; + Member<DOMFloat32Array> m_data; + + static bool validateConstructorArguments(const unsigned&, + const IntSize* = nullptr, + const unsigned& = 0, + const unsigned& = 0, + const DOMFloat32Array* = nullptr, + const String* = nullptr, + ExceptionState* = nullptr); + + static DOMFloat32Array* allocateAndValidateFloat32Array( + const unsigned&, + ExceptionState* = nullptr); +}; + +} // namespace blink + +#endif // Float32ImageData_h
diff --git a/third_party/WebKit/Source/core/html/Float32ImageData.idl b/third_party/WebKit/Source/core/html/Float32ImageData.idl new file mode 100644 index 0000000..555e366 --- /dev/null +++ b/third_party/WebKit/Source/core/html/Float32ImageData.idl
@@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// https://github.com/junov/CanvasColorSpace/blob/master/CanvasColorSpaceProposal.md#imagedata + +[ + Constructor(unsigned long sw, unsigned long sh), + Constructor(unsigned long sw, unsigned long sh, ImageDataColorSpace colorSpace), + Constructor(Float32Array data, unsigned long sw), + Constructor(Float32Array data, unsigned long sw, unsigned long sh), + Constructor(Float32Array data, unsigned long sw, unsigned long sh, ImageDataColorSpace colorSpace), + + Exposed=(Window,Worker), + RaisesException=Constructor, + RuntimeEnabled=ExperimentalCanvasFeatures, +] interface Float32ImageData { + readonly attribute unsigned long width; + readonly attribute unsigned long height; + readonly attribute Float32Array data; + readonly attribute ImageDataColorSpace colorSpace; +};
diff --git a/third_party/WebKit/Source/core/html/ImageData.cpp b/third_party/WebKit/Source/core/html/ImageData.cpp index 355814b..1bc6d27f 100644 --- a/third_party/WebKit/Source/core/html/ImageData.cpp +++ b/third_party/WebKit/Source/core/html/ImageData.cpp
@@ -34,11 +34,161 @@ #include "core/frame/ImageBitmap.h" #include "core/imagebitmap/ImageBitmapOptions.h" #include "platform/RuntimeEnabledFeatures.h" -#include "wtf/CheckedNumeric.h" namespace blink { +bool ImageData::validateConstructorArguments(const unsigned& paramFlags, + const IntSize* size, + const unsigned& width, + const unsigned& height, + const DOMArrayBufferView* data, + const String* colorSpace, + ExceptionState* exceptionState, + ImageDataType imageDataType) { + if (paramFlags & kParamData) { + if (data->type() != DOMArrayBufferView::ViewType::TypeUint8Clamped && + data->type() != DOMArrayBufferView::ViewType::TypeFloat32) + return false; + if (data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped && + imageDataType != kUint8ClampedImageData) + imageDataType = kFloat32ImageData; + } + + // ImageData::create parameters without ExceptionState + if (paramFlags & kParamSize) { + if (!size->width() || !size->height()) + return false; + if (paramFlags & kParamData) { + DCHECK(data); + CheckedNumeric<unsigned> dataSize = 4; + dataSize *= size->width(); + dataSize *= size->height(); + unsigned length = + data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped + ? (const_cast<DOMUint8ClampedArray*>( + static_cast<const DOMUint8ClampedArray*>(data))) + ->length() + : (const_cast<DOMFloat32Array*>( + static_cast<const DOMFloat32Array*>(data))) + ->length(); + if (!dataSize.IsValid() || dataSize.ValueOrDie() > length) + return false; + } + return true; + } + + // ImageData::create parameters with ExceptionState + if ((paramFlags & kParamWidth) && !width) { + exceptionState->throwDOMException( + IndexSizeError, "The source width is zero or not a number."); + return false; + } + if ((paramFlags & kParamHeight) && !height) { + exceptionState->throwDOMException( + IndexSizeError, "The source height is zero or not a number."); + return false; + } + if (paramFlags & (kParamWidth | kParamHeight)) { + CheckedNumeric<unsigned> dataSize = 4; + dataSize *= width; + dataSize *= height; + if (!dataSize.IsValid()) { + exceptionState->throwDOMException( + IndexSizeError, + "The requested image size exceeds the supported range."); + return false; + } + } + if (paramFlags & kParamData) { + DCHECK(data); + unsigned length = + data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped + ? (const_cast<DOMUint8ClampedArray*>( + static_cast<const DOMUint8ClampedArray*>(data))) + ->length() + : (const_cast<DOMFloat32Array*>( + static_cast<const DOMFloat32Array*>(data))) + ->length(); + if (!length) { + exceptionState->throwDOMException(IndexSizeError, + "The input data has zero elements."); + return false; + } + if (length % 4) { + exceptionState->throwDOMException( + IndexSizeError, "The input data length is not a multiple of 4."); + return false; + } + length /= 4; + if (length % width) { + exceptionState->throwDOMException( + IndexSizeError, + "The input data length is not a multiple of (4 * width)."); + return false; + } + if ((paramFlags & kParamHeight) && height != length / width) { + exceptionState->throwDOMException( + IndexSizeError, + "The input data length is not equal to (4 * width * height)."); + return false; + } + } + if (paramFlags & kParamColorSpace) { + if (!colorSpace || colorSpace->length() == 0) { + exceptionState->throwDOMException( + NotSupportedError, "The source color space is not defined."); + return false; + } + if (imageDataType == kUint8ClampedImageData && + *colorSpace != kLegacyImageDataColorSpaceName && + *colorSpace != kSRGBImageDataColorSpaceName) { + exceptionState->throwDOMException(NotSupportedError, + "The input color space is not " + "supported in " + "Uint8ClampedArray-backed ImageData."); + return false; + } + if (imageDataType == kFloat32ImageData && + *colorSpace != kLinearRGBImageDataColorSpaceName) { + exceptionState->throwDOMException(NotSupportedError, + "The input color space is not " + "supported in " + "Float32Array-backed ImageData."); + return false; + } + } + return true; +} + +DOMUint8ClampedArray* ImageData::allocateAndValidateUint8ClampedArray( + const unsigned& length, + ExceptionState* exceptionState) { + if (!length) + return nullptr; + DOMUint8ClampedArray* dataArray = DOMUint8ClampedArray::createOrNull(length); + if (!dataArray || length != dataArray->length()) { + if (exceptionState) { + exceptionState->throwDOMException(V8RangeError, + "Out of memory at ImageData creation"); + } + return nullptr; + } + return dataArray; +} + ImageData* ImageData::create(const IntSize& size) { + if (!ImageData::validateConstructorArguments(kParamSize, &size)) + return nullptr; + DOMUint8ClampedArray* byteArray = + ImageData::allocateAndValidateUint8ClampedArray(4 * size.width() * + size.height()); + if (!byteArray) + return nullptr; + return new ImageData(size, byteArray); +} + +// This function accepts size (0, 0). +ImageData* ImageData::createForTest(const IntSize& size) { CheckedNumeric<unsigned> dataSize = 4; dataSize *= size.width(); dataSize *= size.height(); @@ -55,94 +205,33 @@ ImageData* ImageData::create(const IntSize& size, DOMUint8ClampedArray* byteArray) { - CheckedNumeric<unsigned> dataSize = 4; - dataSize *= size.width(); - dataSize *= size.height(); - if (!dataSize.IsValid()) + if (!ImageData::validateConstructorArguments(kParamSize | kParamData, &size, + 0, 0, byteArray)) return nullptr; - - if (!dataSize.IsValid() || dataSize.ValueOrDie() > byteArray->length()) - return nullptr; - return new ImageData(size, byteArray); } ImageData* ImageData::create(unsigned width, unsigned height, ExceptionState& exceptionState) { - if (!width || !height) { - exceptionState.throwDOMException( - IndexSizeError, String::format("The source %s is zero or not a number.", - width ? "height" : "width")); + if (!ImageData::validateConstructorArguments(kParamWidth | kParamHeight, + nullptr, width, height, nullptr, + nullptr, &exceptionState)) return nullptr; - } - - CheckedNumeric<unsigned> dataSize = 4; - dataSize *= width; - dataSize *= height; - if (!dataSize.IsValid() || static_cast<int>(width) < 0 || - static_cast<int>(height) < 0) { - exceptionState.throwDOMException( - IndexSizeError, - "The requested image size exceeds the supported range."); - return nullptr; - } - DOMUint8ClampedArray* byteArray = - DOMUint8ClampedArray::createOrNull(dataSize.ValueOrDie()); - if (!byteArray) { - exceptionState.throwDOMException(V8Error, - "Out of memory at ImageData creation"); - return nullptr; - } - - return new ImageData(IntSize(width, height), byteArray); -} - -bool ImageData::validateConstructorArguments(DOMUint8ClampedArray* data, - unsigned width, - unsigned& lengthInPixels, - ExceptionState& exceptionState) { - if (!width) { - exceptionState.throwDOMException( - IndexSizeError, "The source width is zero or not a number."); - return false; - } - DCHECK(data); - unsigned length = data->length(); - if (!length) { - exceptionState.throwDOMException(IndexSizeError, - "The input data has a zero byte length."); - return false; - } - if (length % 4) { - exceptionState.throwDOMException( - IndexSizeError, "The input data byte length is not a multiple of 4."); - return false; - } - length /= 4; - if (length % width) { - exceptionState.throwDOMException( - IndexSizeError, - "The input data byte length is not a multiple of (4 * width)."); - return false; - } - lengthInPixels = length; - return true; + ImageData::allocateAndValidateUint8ClampedArray(4 * width * height, + &exceptionState); + return byteArray ? new ImageData(IntSize(width, height), byteArray) : nullptr; } ImageData* ImageData::create(DOMUint8ClampedArray* data, unsigned width, ExceptionState& exceptionState) { - unsigned lengthInPixels = 0; - if (!validateConstructorArguments(data, width, lengthInPixels, - exceptionState)) { - DCHECK(exceptionState.hadException()); + if (!ImageData::validateConstructorArguments(kParamData | kParamWidth, + nullptr, width, 0, data, nullptr, + &exceptionState)) return nullptr; - } - DCHECK_GT(lengthInPixels, 0u); - DCHECK_GT(width, 0u); - unsigned height = lengthInPixels / width; + unsigned height = data->length() / (width * 4); return new ImageData(IntSize(width, height), data); } @@ -150,23 +239,81 @@ unsigned width, unsigned height, ExceptionState& exceptionState) { - unsigned lengthInPixels = 0; - if (!validateConstructorArguments(data, width, lengthInPixels, - exceptionState)) { - DCHECK(exceptionState.hadException()); + if (!ImageData::validateConstructorArguments( + kParamData | kParamWidth | kParamHeight, nullptr, width, height, data, + nullptr, &exceptionState)) return nullptr; - } - DCHECK_GT(lengthInPixels, 0u); - DCHECK_GT(width, 0u); - if (height != lengthInPixels / width) { - exceptionState.throwDOMException( - IndexSizeError, - "The input data byte length is not equal to (4 * width * height)."); - return nullptr; - } return new ImageData(IntSize(width, height), data); } +ImageDataColorSpace ImageData::getImageDataColorSpace(String colorSpaceName) { + if (colorSpaceName == kLegacyImageDataColorSpaceName) + return kLegacyImageDataColorSpace; + if (colorSpaceName == kSRGBImageDataColorSpaceName) + return kSRGBImageDataColorSpace; + if (colorSpaceName == kLinearRGBImageDataColorSpaceName) + return kLinearRGBImageDataColorSpace; + NOTREACHED(); + return kLegacyImageDataColorSpace; +} + +String ImageData::getImageDataColorSpaceName(ImageDataColorSpace colorSpace) { + switch (colorSpace) { + case kLegacyImageDataColorSpace: + return kLegacyImageDataColorSpaceName; + case kSRGBImageDataColorSpace: + return kSRGBImageDataColorSpaceName; + case kLinearRGBImageDataColorSpace: + return kLinearRGBImageDataColorSpaceName; + } + NOTREACHED(); + return String(); +} + +ImageData* ImageData::createImageData(unsigned width, + unsigned height, + String colorSpace, + ExceptionState& exceptionState) { + if (!ImageData::validateConstructorArguments( + kParamWidth | kParamHeight | kParamColorSpace, nullptr, width, height, + nullptr, &colorSpace, &exceptionState)) + return nullptr; + + DOMUint8ClampedArray* byteArray = + ImageData::allocateAndValidateUint8ClampedArray(4 * width * height, + &exceptionState); + return byteArray + ? new ImageData(IntSize(width, height), byteArray, colorSpace) + : nullptr; +} + +ImageData* ImageData::createImageData(DOMUint8ClampedArray* data, + unsigned width, + String colorSpace, + ExceptionState& exceptionState) { + if (!ImageData::validateConstructorArguments( + kParamData | kParamWidth | kParamColorSpace, nullptr, width, 0, data, + &colorSpace, &exceptionState)) + return nullptr; + unsigned height = data->length() / (width * 4); + return new ImageData(IntSize(width, height), data, colorSpace); +} + +ImageData* ImageData::createImageData(DOMUint8ClampedArray* data, + unsigned width, + unsigned height, + String colorSpace, + ExceptionState& exceptionState) { + if (!ImageData::validateConstructorArguments( + kParamData | kParamWidth | kParamHeight | kParamColorSpace, nullptr, + width, height, data, &colorSpace, &exceptionState)) + return nullptr; + return new ImageData(IntSize(width, height), data, colorSpace); +} + +// TODO(zakerinasab): Fix this when ImageBitmap color correction code is landed. +// Tip: If the source Image Data has a color space, createImageBitmap must +// respect this color space even when no color space tag is passed to it. ScriptPromise ImageData::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, Optional<IntRect> cropRect, @@ -211,8 +358,12 @@ return wrapper; } -ImageData::ImageData(const IntSize& size, DOMUint8ClampedArray* byteArray) - : m_size(size), m_data(byteArray) { +ImageData::ImageData(const IntSize& size, + DOMUint8ClampedArray* byteArray, + String colorSpaceName) + : m_size(size), + m_colorSpace(getImageDataColorSpace(colorSpaceName)), + m_data(byteArray) { DCHECK_GE(size.width(), 0); DCHECK_GE(size.height(), 0); SECURITY_CHECK(static_cast<unsigned>(size.width() * size.height() * 4) <=
diff --git a/third_party/WebKit/Source/core/html/ImageData.h b/third_party/WebKit/Source/core/html/ImageData.h index 206671a..286092d 100644 --- a/third_party/WebKit/Source/core/html/ImageData.h +++ b/third_party/WebKit/Source/core/html/ImageData.h
@@ -31,18 +31,44 @@ #include "bindings/core/v8/ScriptWrappable.h" #include "core/CoreExport.h" +#include "core/dom/DOMArrayBufferView.h" #include "core/dom/DOMTypedArray.h" #include "core/imagebitmap/ImageBitmapSource.h" #include "platform/geometry/IntRect.h" #include "platform/geometry/IntSize.h" #include "platform/heap/Handle.h" +#include "wtf/CheckedNumeric.h" #include "wtf/Compiler.h" +#include "wtf/text/WTFString.h" namespace blink { class ExceptionState; class ImageBitmapOptions; +enum ConstructorParams { + kParamSize = 1, + kParamWidth = 1 << 1, + kParamHeight = 1 << 2, + kParamData = 1 << 3, + kParamColorSpace = 1 << 4, +}; + +enum ImageDataType { + kUint8ClampedImageData, + kFloat32ImageData, +}; + +enum ImageDataColorSpace { + kLegacyImageDataColorSpace, + kSRGBImageDataColorSpace, + kLinearRGBImageDataColorSpace, +}; + +const char* const kLinearRGBImageDataColorSpaceName = "linear-rgb"; +const char* const kSRGBImageDataColorSpaceName = "srgb"; +const char* const kLegacyImageDataColorSpaceName = "legacy-srgb"; + class CORE_EXPORT ImageData final : public GarbageCollectedFinalized<ImageData>, public ScriptWrappable, public ImageBitmapSource { @@ -60,9 +86,30 @@ unsigned height, ExceptionState&); + static ImageData* createForTest(const IntSize&); + + ImageData* createImageData(unsigned width, + unsigned height, + String colorSpace, + ExceptionState&); + ImageData* createImageData(DOMUint8ClampedArray*, + unsigned width, + String colorSpace, + ExceptionState&); + ImageData* createImageData(DOMUint8ClampedArray*, + unsigned width, + unsigned height, + String colorSpace, + ExceptionState&); + + static ImageDataColorSpace getImageDataColorSpace(String); + static String getImageDataColorSpaceName(ImageDataColorSpace); + IntSize size() const { return m_size; } int width() const { return m_size.width(); } int height() const { return m_size.height(); } + String colorSpace() const { return getImageDataColorSpaceName(m_colorSpace); } + ImageDataColorSpace imageDataColorSpace() { return m_colorSpace; } const DOMUint8ClampedArray* data() const { return m_data.get(); } DOMUint8ClampedArray* data() { return m_data.get(); } @@ -81,16 +128,28 @@ const WrapperTypeInfo*, v8::Local<v8::Object> wrapper) override; - private: - ImageData(const IntSize&, DOMUint8ClampedArray*); + static bool validateConstructorArguments( + const unsigned&, + const IntSize* = nullptr, + const unsigned& = 0, + const unsigned& = 0, + const DOMArrayBufferView* = nullptr, + const String* = nullptr, + ExceptionState* = nullptr, + ImageDataType = kUint8ClampedImageData); - static bool validateConstructorArguments(DOMUint8ClampedArray*, - unsigned width, - unsigned&, - ExceptionState&); + private: + ImageData(const IntSize&, + DOMUint8ClampedArray*, + String = kLegacyImageDataColorSpaceName); IntSize m_size; + ImageDataColorSpace m_colorSpace; Member<DOMUint8ClampedArray> m_data; + + static DOMUint8ClampedArray* allocateAndValidateUint8ClampedArray( + const unsigned&, + ExceptionState* = nullptr); }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/ImageData.idl b/third_party/WebKit/Source/core/html/ImageData.idl index d52d253..38051b0 100644 --- a/third_party/WebKit/Source/core/html/ImageData.idl +++ b/third_party/WebKit/Source/core/html/ImageData.idl
@@ -27,6 +27,9 @@ */ // https://html.spec.whatwg.org/#dom-imagedata +// https://github.com/junov/CanvasColorSpace/blob/master/CanvasColorSpaceProposal.md#imagedata + +enum ImageDataColorSpace { "legacy-srgb", "srgb", "linear-rgb" }; [ Constructor(unsigned long sw, unsigned long sh), @@ -34,8 +37,13 @@ Exposed=(Window,Worker), RaisesException=Constructor, ] interface ImageData { + + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(unsigned long sw, unsigned long sh, ImageDataColorSpace colorSpace); + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(Uint8ClampedArray data, unsigned long sw, ImageDataColorSpace colorSpace); + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(Uint8ClampedArray data, unsigned long sw, unsigned long sh, ImageDataColorSpace colorSpace); + readonly attribute unsigned long width; readonly attribute unsigned long height; - // TODO(foolip): Expose data. - // readonly attribute Uint8ClampedArray data; + readonly attribute Uint8ClampedArray data; + readonly attribute ImageDataColorSpace colorSpace; };
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp index 6a771c1..c5a39da 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp +++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp
@@ -200,7 +200,7 @@ void CanvasAsyncBlobCreatorTest::prepareMockCanvasAsyncBlobCreatorFailPng() { IntSize testSize(0, 0); - ImageData* imageData = ImageData::create(testSize); + ImageData* imageData = ImageData::createForTest(testSize); // We reuse the class MockCanvasAsyncBlobCreatorWithoutCompletePng because // this test case is expected to fail at initialization step before @@ -229,7 +229,7 @@ void CanvasAsyncBlobCreatorTest::prepareMockCanvasAsyncBlobCreatorFailJpeg() { IntSize testSize(0, 0); - ImageData* imageData = ImageData::create(testSize); + ImageData* imageData = ImageData::createForTest(testSize); // We reuse the class MockCanvasAsyncBlobCreatorWithoutCompleteJpeg because // this test case is expected to fail at initialization step before
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp index 6a80ef90..ad490be 100644 --- a/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp +++ b/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp
@@ -92,15 +92,13 @@ }; class MockScreenOrientationController final - : public GarbageCollectedFinalized<MockScreenOrientationController>, - public ScreenOrientationController { - USING_GARBAGE_COLLECTED_MIXIN(MockScreenOrientationController); + : public ScreenOrientationController { WTF_MAKE_NONCOPYABLE(MockScreenOrientationController); public: static MockScreenOrientationController* provideTo(LocalFrame& frame) { MockScreenOrientationController* controller = - new MockScreenOrientationController(); + new MockScreenOrientationController(frame); ScreenOrientationController::provideTo(frame, controller); return controller; } @@ -108,10 +106,11 @@ MOCK_METHOD1(lock, void(WebScreenOrientationLockType)); MOCK_METHOD0(mockUnlock, void()); - DEFINE_INLINE_VIRTUAL_TRACE() { Supplement<LocalFrame>::trace(visitor); } + DEFINE_INLINE_VIRTUAL_TRACE() { ScreenOrientationController::trace(visitor); } private: - MockScreenOrientationController() = default; + explicit MockScreenOrientationController(LocalFrame& frame) + : ScreenOrientationController(frame) {} void lock(WebScreenOrientationLockType type, std::unique_ptr<WebLockOrientationCallback>) override {
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp index 4fd0a6e6..93b7ec5 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
@@ -71,7 +71,7 @@ #include "platform/weborigin/ReferrerPolicy.h" #include "platform/weborigin/SecurityOrigin.h" #include "public/platform/WebCachePolicy.h" -#include "public/platform/WebMixedContent.h" +#include "public/platform/WebMixedContentContextType.h" #include "public/platform/WebURLLoaderClient.h" #include "public/platform/WebURLRequest.h" #include "wtf/CurrentTime.h" @@ -211,15 +211,14 @@ return result; } -String mixedContentTypeForContextType( - WebMixedContent::ContextType contextType) { +String mixedContentTypeForContextType(WebMixedContentContextType contextType) { switch (contextType) { - case WebMixedContent::ContextType::NotMixedContent: + case WebMixedContentContextType::NotMixedContent: return protocol::Network::Request::MixedContentTypeEnum::None; - case WebMixedContent::ContextType::Blockable: + case WebMixedContentContextType::Blockable: return protocol::Network::Request::MixedContentTypeEnum::Blockable; - case WebMixedContent::ContextType::OptionallyBlockable: - case WebMixedContent::ContextType::ShouldBeBlockable: + case WebMixedContentContextType::OptionallyBlockable: + case WebMixedContentContextType::ShouldBeBlockable: return protocol::Network::Request::MixedContentTypeEnum:: OptionallyBlockable; }
diff --git a/third_party/WebKit/Source/core/loader/MixedContentChecker.cpp b/third_party/WebKit/Source/core/loader/MixedContentChecker.cpp index 21c313b2..51dfb21 100644 --- a/third_party/WebKit/Source/core/loader/MixedContentChecker.cpp +++ b/third_party/WebKit/Source/core/loader/MixedContentChecker.cpp
@@ -43,6 +43,7 @@ #include "platform/weborigin/SecurityOrigin.h" #include "public/platform/WebAddressSpace.h" #include "public/platform/WebInsecureRequestPolicy.h" +#include "public/platform/WebMixedContent.h" #include "wtf/text/StringBuilder.h" namespace blink { @@ -61,6 +62,81 @@ return toLocalFrame(frame)->document()->url(); } +const char* requestContextName(WebURLRequest::RequestContext context) { + switch (context) { + case WebURLRequest::RequestContextAudio: + return "audio file"; + case WebURLRequest::RequestContextBeacon: + return "Beacon endpoint"; + case WebURLRequest::RequestContextCSPReport: + return "Content Security Policy reporting endpoint"; + case WebURLRequest::RequestContextDownload: + return "download"; + case WebURLRequest::RequestContextEmbed: + return "plugin resource"; + case WebURLRequest::RequestContextEventSource: + return "EventSource endpoint"; + case WebURLRequest::RequestContextFavicon: + return "favicon"; + case WebURLRequest::RequestContextFetch: + return "resource"; + case WebURLRequest::RequestContextFont: + return "font"; + case WebURLRequest::RequestContextForm: + return "form action"; + case WebURLRequest::RequestContextFrame: + return "frame"; + case WebURLRequest::RequestContextHyperlink: + return "resource"; + case WebURLRequest::RequestContextIframe: + return "frame"; + case WebURLRequest::RequestContextImage: + return "image"; + case WebURLRequest::RequestContextImageSet: + return "image"; + case WebURLRequest::RequestContextImport: + return "HTML Import"; + case WebURLRequest::RequestContextInternal: + return "resource"; + case WebURLRequest::RequestContextLocation: + return "resource"; + case WebURLRequest::RequestContextManifest: + return "manifest"; + case WebURLRequest::RequestContextObject: + return "plugin resource"; + case WebURLRequest::RequestContextPing: + return "hyperlink auditing endpoint"; + case WebURLRequest::RequestContextPlugin: + return "plugin data"; + case WebURLRequest::RequestContextPrefetch: + return "prefetch resource"; + case WebURLRequest::RequestContextScript: + return "script"; + case WebURLRequest::RequestContextServiceWorker: + return "Service Worker script"; + case WebURLRequest::RequestContextSharedWorker: + return "Shared Worker script"; + case WebURLRequest::RequestContextStyle: + return "stylesheet"; + case WebURLRequest::RequestContextSubresource: + return "resource"; + case WebURLRequest::RequestContextTrack: + return "Text Track"; + case WebURLRequest::RequestContextUnspecified: + return "resource"; + case WebURLRequest::RequestContextVideo: + return "video"; + case WebURLRequest::RequestContextWorker: + return "Worker script"; + case WebURLRequest::RequestContextXMLHttpRequest: + return "XMLHttpRequest endpoint"; + case WebURLRequest::RequestContextXSLT: + return "XSLT"; + } + NOTREACHED(); + return "resource"; +} + } // namespace static void measureStricterVersionOfIsMixedContent(Frame* frame, @@ -150,8 +226,7 @@ "Mixed Content: The page at '%s' was loaded over HTTPS, but requested an " "insecure %s '%s'. %s", mainResourceUrl.elidedString().utf8().data(), - WebMixedContent::requestContextName(requestContext), - url.elidedString().utf8().data(), + requestContextName(requestContext), url.elidedString().utf8().data(), allowed ? "This content should also be served over HTTPS." : "This request has been blocked; the content must be served " "over HTTPS."); @@ -168,11 +243,11 @@ // Roll blockable content up into a single counter, count unblocked types // individually so we can determine when they can be safely moved to the // blockable category: - WebMixedContent::ContextType contextType = + WebMixedContentContextType contextType = WebMixedContent::contextTypeFromRequestContext( requestContext, frame->settings()->getStrictMixedContentCheckingForPlugin()); - if (contextType == WebMixedContent::ContextType::Blockable) { + if (contextType == WebMixedContentContextType::Blockable) { UseCounter::count(frame, UseCounter::MixedContentBlockable); return; } @@ -245,7 +320,7 @@ kBlockAllMixedContent || settings->getStrictMixedContentChecking(); - WebMixedContent::ContextType contextType = + WebMixedContentContextType contextType = WebMixedContent::contextTypeFromRequestContext( requestContext, settings->getStrictMixedContentCheckingForPlugin()); @@ -259,10 +334,10 @@ // https://crbug.com/393481 if (frameType == WebURLRequest::FrameTypeNested && !SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(url.protocol())) - contextType = WebMixedContent::ContextType::OptionallyBlockable; + contextType = WebMixedContentContextType::OptionallyBlockable; switch (contextType) { - case WebMixedContent::ContextType::OptionallyBlockable: + case WebMixedContentContextType::OptionallyBlockable: allowed = !strictMode; if (allowed) { client->passiveInsecureContentFound(url); @@ -270,7 +345,7 @@ } break; - case WebMixedContent::ContextType::Blockable: { + case WebMixedContentContextType::Blockable: { // Strictly block subresources that are mixed with respect to their // subframes, unless all insecure content is allowed. This is to avoid the // following situation: https://a.com embeds https://b.com, which loads a @@ -302,12 +377,12 @@ break; } - case WebMixedContent::ContextType::ShouldBeBlockable: + case WebMixedContentContextType::ShouldBeBlockable: allowed = !strictMode; if (allowed) client->didDisplayInsecureContent(); break; - case WebMixedContent::ContextType::NotMixedContent: + case WebMixedContentContextType::NotMixedContent: NOTREACHED(); break; }; @@ -475,20 +550,20 @@ bool strictMixedContentCheckingForPlugin = effectiveFrame->settings() && effectiveFrame->settings()->getStrictMixedContentCheckingForPlugin(); - WebMixedContent::ContextType contextType = + WebMixedContentContextType contextType = WebMixedContent::contextTypeFromRequestContext( requestContext, strictMixedContentCheckingForPlugin); - if (contextType == WebMixedContent::ContextType::Blockable) { + if (contextType == WebMixedContentContextType::Blockable) { client->didRunContentWithCertificateErrors(response.url()); } else { // contextTypeFromRequestContext() never returns NotMixedContent (it // computes the type of mixed content, given that the content is mixed). - DCHECK_NE(contextType, WebMixedContent::ContextType::NotMixedContent); + DCHECK_NE(contextType, WebMixedContentContextType::NotMixedContent); client->didDisplayContentWithCertificateErrors(response.url()); } } -WebMixedContent::ContextType MixedContentChecker::contextTypeForInspector( +WebMixedContentContextType MixedContentChecker::contextTypeForInspector( LocalFrame* frame, const ResourceRequest& request) { Frame* effectiveFrame = @@ -497,14 +572,14 @@ Frame* mixedFrame = inWhichFrameIsContentMixed( effectiveFrame, request.frameType(), request.url()); if (!mixedFrame) - return WebMixedContent::ContextType::NotMixedContent; + return WebMixedContentContextType::NotMixedContent; // See comment in shouldBlockFetch() about loading the main resource of a // subframe. if (request.frameType() == WebURLRequest::FrameTypeNested && !SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled( request.url().protocol())) { - return WebMixedContent::ContextType::OptionallyBlockable; + return WebMixedContentContextType::OptionallyBlockable; } bool strictMixedContentCheckingForPlugin =
diff --git a/third_party/WebKit/Source/core/loader/MixedContentChecker.h b/third_party/WebKit/Source/core/loader/MixedContentChecker.h index b1100e79..33e8a1a8 100644 --- a/third_party/WebKit/Source/core/loader/MixedContentChecker.h +++ b/third_party/WebKit/Source/core/loader/MixedContentChecker.h
@@ -35,7 +35,7 @@ #include "core/CoreExport.h" #include "platform/heap/Handle.h" #include "platform/network/ResourceRequest.h" -#include "public/platform/WebMixedContent.h" +#include "public/platform/WebMixedContentContextType.h" #include "public/platform/WebURLRequest.h" #include "wtf/text/WTFString.h" @@ -80,7 +80,7 @@ static void checkMixedPrivatePublic(LocalFrame*, const AtomicString& resourceIPAddress); - static WebMixedContent::ContextType contextTypeForInspector( + static WebMixedContentContextType contextTypeForInspector( LocalFrame*, const ResourceRequest&);
diff --git a/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp b/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp index 3323b62..831dfa1 100644 --- a/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp +++ b/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp
@@ -10,6 +10,8 @@ #include "platform/network/ResourceResponse.h" #include "platform/weborigin/KURL.h" #include "platform/weborigin/SecurityOrigin.h" +#include "public/platform/WebMixedContent.h" +#include "public/platform/WebMixedContentContextType.h" #include "testing/gmock/include/gmock/gmock-generated-function-mockers.h" #include "testing/gtest/include/gtest/gtest.h" #include "wtf/RefPtr.h" @@ -68,20 +70,20 @@ ResourceRequest notMixedContent("https://example.test/foo.jpg"); notMixedContent.setFrameType(WebURLRequest::FrameTypeAuxiliary); notMixedContent.setRequestContext(WebURLRequest::RequestContextScript); - EXPECT_EQ(WebMixedContent::ContextType::NotMixedContent, + EXPECT_EQ(WebMixedContentContextType::NotMixedContent, MixedContentChecker::contextTypeForInspector( &dummyPageHolder->frame(), notMixedContent)); dummyPageHolder->frame().document()->setSecurityOrigin( SecurityOrigin::createFromString("https://example.test")); - EXPECT_EQ(WebMixedContent::ContextType::NotMixedContent, + EXPECT_EQ(WebMixedContentContextType::NotMixedContent, MixedContentChecker::contextTypeForInspector( &dummyPageHolder->frame(), notMixedContent)); ResourceRequest blockableMixedContent("http://example.test/foo.jpg"); blockableMixedContent.setFrameType(WebURLRequest::FrameTypeAuxiliary); blockableMixedContent.setRequestContext(WebURLRequest::RequestContextScript); - EXPECT_EQ(WebMixedContent::ContextType::Blockable, + EXPECT_EQ(WebMixedContentContextType::Blockable, MixedContentChecker::contextTypeForInspector( &dummyPageHolder->frame(), blockableMixedContent)); @@ -89,7 +91,7 @@ "http://example.test/foo.jpg"); blockableMixedContent.setFrameType(WebURLRequest::FrameTypeAuxiliary); blockableMixedContent.setRequestContext(WebURLRequest::RequestContextImage); - EXPECT_EQ(WebMixedContent::ContextType::OptionallyBlockable, + EXPECT_EQ(WebMixedContentContextType::OptionallyBlockable, MixedContentChecker::contextTypeForInspector( &dummyPageHolder->frame(), blockableMixedContent)); } @@ -126,7 +128,7 @@ WebURLRequest::RequestContext requestContext = WebURLRequest::RequestContextImage; ASSERT_EQ( - WebMixedContent::ContextType::OptionallyBlockable, + WebMixedContentContextType::OptionallyBlockable, WebMixedContent::contextTypeFromRequestContext( requestContext, dummyPageHolder->frame() .settings()
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp b/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp index a1028420..848d763 100644 --- a/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
@@ -192,6 +192,14 @@ ? cssPropertyID(attributeName().localName()) : CSSPropertyInvalid; } + // Blacklist <script> targets here for now to prevent unpleasantries. This + // also disallows the perfectly "valid" animation of 'className' on said + // element. If SVGScriptElement.href is transitioned off of SVGAnimatedHref, + // this can be removed. + if (isSVGScriptElement(*targetElement())) { + m_type = AnimatedUnknown; + m_cssPropertyId = CSSPropertyInvalid; + } DCHECK(m_type != AnimatedPoint && m_type != AnimatedStringList && m_type != AnimatedTransform && m_type != AnimatedTransformList); }
diff --git a/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp b/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp index 25dbc97..936f08e6 100644 --- a/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp
@@ -22,6 +22,7 @@ #include "bindings/core/v8/ScriptEventListener.h" #include "core/HTMLNames.h" +#include "core/XLinkNames.h" #include "core/dom/Attribute.h" #include "core/dom/ScriptLoader.h" #include "core/dom/ScriptRunner.h" @@ -146,9 +147,9 @@ #if DCHECK_IS_ON() bool SVGScriptElement::isAnimatableAttribute(const QualifiedName& name) const { - if (name == SVGNames::typeAttr) + if (name == SVGNames::typeAttr || name == SVGNames::hrefAttr || + name == XLinkNames::hrefAttr) return false; - return SVGElement::isAnimatableAttribute(name); } #endif
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp index 65b3bdc..337e37c 100644 --- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp +++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -1041,7 +1041,9 @@ if (m_upload) request.setReportUploadProgress(true); - DCHECK(!m_loader); + // TODO(yhirano): Turn this CHECK into DCHECK once https://crbug.com/667254 + // is fixed. + CHECK(!m_loader); DCHECK(m_sendFlag); m_loader = ThreadableLoader::create(executionContext, this, options, resourceLoaderOptions); @@ -1050,6 +1052,8 @@ return; } + // TODO(yhirano): Remove this CHECK once https://crbug.com/667254 is fixed. + CHECK(!m_loader); // Use count for XHR synchronous requests. UseCounter::count(&executionContext, UseCounter::XMLHttpRequestSynchronous); ThreadableLoader::loadResourceSynchronously(executionContext, request, *this,
diff --git a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.cpp b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.cpp index 064a51a..ad9c003 100644 --- a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.cpp +++ b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.cpp
@@ -40,7 +40,8 @@ ScreenOrientationControllerImpl::ScreenOrientationControllerImpl( LocalFrame& frame, WebScreenOrientationClient* client) - : ContextLifecycleObserver(frame.document()), + : ScreenOrientationController(frame), + ContextLifecycleObserver(frame.document()), PlatformEventController(frame.page()), m_client(client), m_dispatchEventTimer(
diff --git a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.h b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.h index 7fa4373..8863622b 100644 --- a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.h +++ b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.h
@@ -21,8 +21,7 @@ class WebScreenOrientationClient; class MODULES_EXPORT ScreenOrientationControllerImpl final - : public GarbageCollectedFinalized<ScreenOrientationControllerImpl>, - public ScreenOrientationController, + : public ScreenOrientationController, public ContextLifecycleObserver, public PlatformEventController { USING_GARBAGE_COLLECTED_MIXIN(ScreenOrientationControllerImpl);
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp b/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp index ab72ab8..4ae77b7 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp
@@ -517,4 +517,11 @@ return this; } +AudioParam* AudioParam::cancelValuesAndHoldAtTime( + double startTime, + ExceptionState& exceptionState) { + handler().timeline().cancelValuesAndHoldAtTime(startTime, exceptionState); + return this; +} + } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParam.h b/third_party/WebKit/Source/modules/webaudio/AudioParam.h index f52ed1f..cf2f761 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioParam.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioParam.h
@@ -251,6 +251,7 @@ double duration, ExceptionState&); AudioParam* cancelScheduledValues(double startTime, ExceptionState&); + AudioParam* cancelValuesAndHoldAtTime(double startTime, ExceptionState&); private: AudioParam(BaseAudioContext&,
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParam.idl b/third_party/WebKit/Source/modules/webaudio/AudioParam.idl index 1fa7537..1cc12ba 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioParam.idl +++ b/third_party/WebKit/Source/modules/webaudio/AudioParam.idl
@@ -50,4 +50,7 @@ // Cancels all scheduled parameter changes with times greater than or equal to startTime. [RaisesException, MeasureAs=AudioParamCancelScheduledValues] AudioParam cancelScheduledValues(double startTime); + // Cancel scheduled parameter changes and hold the last value + [RaisesException] AudioParam cancelValuesAndHoldAtTime(double startTime); + };
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp index 5a5448d9..dbb6a1b8 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp
@@ -29,6 +29,7 @@ #include "platform/audio/AudioUtilities.h" #include "wtf/CPU.h" #include "wtf/MathExtras.h" +#include "wtf/PtrUtil.h" #include <algorithm> #if CPU(X86) || CPU(X86_64) @@ -106,6 +107,9 @@ args = "..., " + String::number(event.time(), 16) + ", " + String::number(event.duration(), 16); break; + case ParamEvent::CancelValues: + // Fall through; we should never have to print out the internal + // CancelValues event. case ParamEvent::LastType: ASSERT_NOT_REACHED(); break; @@ -114,54 +118,77 @@ return s + "(" + args + ")"; } -AudioParamTimeline::ParamEvent::ParamEvent(Type type, - float value, - double time, - double timeConstant, +// Computes the value of a linear ramp event at time t with the given event +// parameters. +float AudioParamTimeline::linearRampAtTime(double t, + float value1, + double time1, + float value2, + double time2) { + return value1 + (value2 - value1) * (t - time1) / (time2 - time1); +} + +// Computes the value of an exponential ramp event at time t with the given +// event parameters. +float AudioParamTimeline::exponentialRampAtTime(double t, + float value1, + double time1, + float value2, + double time2) { + return value1 * pow(value2 / value1, (t - time1) / (time2 - time1)); +} + +// Compute the value of a set target event at time t with the given event +// parameters. +float AudioParamTimeline::targetValueAtTime(double t, + float value1, + double time1, + float value2, + float timeConstant) { + return value2 + (value1 - value2) * exp(-(t - time1) / timeConstant); +} + +// Compute the value of a set curve event at time t with the given event +// parameters. +float AudioParamTimeline::valueCurveAtTime(double t, + double time1, double duration, - const DOMFloat32Array* curve, - float initialValue, - double callTime) - : m_type(type), - m_value(value), - m_time(time), - m_timeConstant(timeConstant), - m_duration(duration), - m_initialValue(initialValue), - m_callTime(callTime), - m_needsTimeClampCheck(true) { - if (curve) { - // Copy the curve data - unsigned curveLength = curve->length(); - m_curve.resize(curveLength); - memcpy(m_curve.data(), curve->data(), curveLength * sizeof(float)); - } + const float* curveData, + unsigned curveLength) { + double curveIndex = (curveLength - 1) / duration * (t - time1); + unsigned k = std::min(static_cast<unsigned>(curveIndex), curveLength - 1); + unsigned k1 = std::min(k + 1, curveLength - 1); + float c0 = curveData[k]; + float c1 = curveData[k1]; + float delta = std::min(curveIndex - k, 1.0); + + return c0 + (c1 - c0) * delta; } -AudioParamTimeline::ParamEvent +std::unique_ptr<AudioParamTimeline::ParamEvent> AudioParamTimeline::ParamEvent::createSetValueEvent(float value, double time) { - return ParamEvent(ParamEvent::SetValue, value, time, 0, 0, nullptr); + return WTF::wrapUnique(new ParamEvent(ParamEvent::SetValue, value, time)); } -AudioParamTimeline::ParamEvent +std::unique_ptr<AudioParamTimeline::ParamEvent> AudioParamTimeline::ParamEvent::createLinearRampEvent(float value, double time, float initialValue, double callTime) { - return ParamEvent(ParamEvent::LinearRampToValue, value, time, 0, 0, nullptr, - initialValue, callTime); + return WTF::wrapUnique(new ParamEvent(ParamEvent::LinearRampToValue, value, + time, initialValue, callTime)); } -AudioParamTimeline::ParamEvent +std::unique_ptr<AudioParamTimeline::ParamEvent> AudioParamTimeline::ParamEvent::createExponentialRampEvent(float value, double time, float initialValue, double callTime) { - return ParamEvent(ParamEvent::ExponentialRampToValue, value, time, 0, 0, - nullptr, initialValue, callTime); + return WTF::wrapUnique(new ParamEvent(ParamEvent::ExponentialRampToValue, + value, time, initialValue, callTime)); } -AudioParamTimeline::ParamEvent +std::unique_ptr<AudioParamTimeline::ParamEvent> AudioParamTimeline::ParamEvent::createSetTargetEvent(float value, double time, double timeConstant) { @@ -169,16 +196,211 @@ // returns NaN or Infinity due to division by zero. The caller // should have converted this to a SetValueEvent. DCHECK_NE(timeConstant, 0); - return ParamEvent(ParamEvent::SetTarget, value, time, timeConstant, 0, - nullptr); + return WTF::wrapUnique( + new ParamEvent(ParamEvent::SetTarget, value, time, timeConstant)); } -AudioParamTimeline::ParamEvent +std::unique_ptr<AudioParamTimeline::ParamEvent> AudioParamTimeline::ParamEvent::createSetValueCurveEvent( const DOMFloat32Array* curve, double time, double duration) { - return ParamEvent(ParamEvent::SetValueCurve, 0, time, 0, duration, curve); + double curvePoints = (curve->length() - 1) / duration; + float endValue = curve->data()[curve->length() - 1]; + + return WTF::wrapUnique(new ParamEvent( + ParamEvent::SetValueCurve, time, duration, curve, curvePoints, endValue)); +} + +std::unique_ptr<AudioParamTimeline::ParamEvent> +AudioParamTimeline::ParamEvent::createCancelValuesEvent( + double time, + std::unique_ptr<ParamEvent> savedEvent) { + if (savedEvent) { + // The savedEvent can only have certain event types. Verify that. + ParamEvent::Type savedType = savedEvent->getType(); + + DCHECK_NE(savedType, ParamEvent::LastType); + DCHECK(savedType == ParamEvent::LinearRampToValue || + savedType == ParamEvent::ExponentialRampToValue || + savedType == ParamEvent::SetValueCurve); + } + + return WTF::wrapUnique( + new ParamEvent(ParamEvent::CancelValues, time, std::move(savedEvent))); +} + +std::unique_ptr<AudioParamTimeline::ParamEvent> +AudioParamTimeline::ParamEvent::createGeneralEvent( + Type type, + float value, + double time, + float initialValue, + double callTime, + double timeConstant, + double duration, + Vector<float>& curve, + double curvePointsPerSecond, + float curveEndValue, + std::unique_ptr<ParamEvent> savedEvent) { + return WTF::wrapUnique(new ParamEvent( + type, value, time, initialValue, callTime, timeConstant, duration, curve, + curvePointsPerSecond, curveEndValue, std::move(savedEvent))); +} + +AudioParamTimeline::ParamEvent* AudioParamTimeline::ParamEvent::savedEvent() + const { + DCHECK_EQ(getType(), ParamEvent::CancelValues); + return m_savedEvent.get(); +} + +bool AudioParamTimeline::ParamEvent::hasDefaultCancelledValue() const { + DCHECK_EQ(getType(), ParamEvent::CancelValues); + return m_hasDefaultCancelledValue; +} + +void AudioParamTimeline::ParamEvent::setCancelledValue(float value) { + DCHECK_EQ(getType(), ParamEvent::CancelValues); + m_value = value; + m_hasDefaultCancelledValue = true; +} + +// General event +AudioParamTimeline::ParamEvent::ParamEvent( + ParamEvent::Type type, + float value, + double time, + float initialValue, + double callTime, + double timeConstant, + double duration, + Vector<float>& curve, + double curvePointsPerSecond, + float curveEndValue, + std::unique_ptr<ParamEvent> savedEvent) + : m_type(type), + m_value(value), + m_time(time), + m_initialValue(initialValue), + m_callTime(callTime), + m_timeConstant(timeConstant), + m_duration(duration), + m_curvePointsPerSecond(curvePointsPerSecond), + m_curveEndValue(curveEndValue), + m_savedEvent(std::move(savedEvent)), + m_needsTimeClampCheck(true), + m_hasDefaultCancelledValue(false) { + m_curve = curve; +} + +// Create simplest event needing just a value and time, like setValueAtTime +AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type, + float value, + double time) + : m_type(type), + m_value(value), + m_time(time), + m_initialValue(0), + m_callTime(0), + m_timeConstant(0), + m_duration(0), + m_curvePointsPerSecond(0), + m_curveEndValue(0), + m_savedEvent(nullptr), + m_needsTimeClampCheck(true), + m_hasDefaultCancelledValue(false) { + DCHECK_EQ(type, ParamEvent::SetValue); +} + +// Create a linear or exponential ramp that requires an initial value and +// time in case +// there is no actual event that preceeds this event. +AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type, + float value, + double time, + float initialValue, + double callTime) + : m_type(type), + m_value(value), + m_time(time), + m_initialValue(initialValue), + m_callTime(callTime), + m_timeConstant(0), + m_duration(0), + m_curvePointsPerSecond(0), + m_curveEndValue(0), + m_savedEvent(nullptr), + m_needsTimeClampCheck(true), + m_hasDefaultCancelledValue(false) { + DCHECK(type == ParamEvent::LinearRampToValue || + type == ParamEvent::ExponentialRampToValue); +} + +// Create an event needing a time constant (setTargetAtTime) +AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type, + float value, + double time, + double timeConstant) + : m_type(type), + m_value(value), + m_time(time), + m_initialValue(0), + m_callTime(0), + m_timeConstant(timeConstant), + m_duration(0), + m_curvePointsPerSecond(0), + m_curveEndValue(0), + m_savedEvent(nullptr), + m_needsTimeClampCheck(true), + m_hasDefaultCancelledValue(false) { + DCHECK_EQ(type, ParamEvent::SetTarget); +} + +// Create a setValueCurve event +AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type, + double time, + double duration, + const DOMFloat32Array* curve, + double curvePointsPerSecond, + float curveEndValue) + : m_type(type), + m_value(0), + m_time(time), + m_initialValue(0), + m_callTime(0), + m_timeConstant(0), + m_duration(duration), + m_curvePointsPerSecond(curvePointsPerSecond), + m_curveEndValue(curveEndValue), + m_savedEvent(nullptr), + m_needsTimeClampCheck(true), + m_hasDefaultCancelledValue(false) { + DCHECK_EQ(type, ParamEvent::SetValueCurve); + if (curve) { + unsigned curveLength = curve->length(); + m_curve.resize(curve->length()); + memcpy(m_curve.data(), curve->data(), curveLength * sizeof(float)); + } +} + +// Create CancelValues event +AudioParamTimeline::ParamEvent::ParamEvent( + ParamEvent::Type type, + double time, + std::unique_ptr<ParamEvent> savedEvent) + : m_type(type), + m_value(0), + m_time(time), + m_initialValue(0), + m_callTime(0), + m_timeConstant(0), + m_duration(0), + m_curvePointsPerSecond(0), + m_curveEndValue(0), + m_savedEvent(std::move(savedEvent)), + m_needsTimeClampCheck(true), + m_hasDefaultCancelledValue(false) { + DCHECK_EQ(type, ParamEvent::CancelValues); } void AudioParamTimeline::setValueAtTime(float value, @@ -189,6 +411,7 @@ if (!isNonNegativeAudioParamTime(time, exceptionState)) return; + MutexLocker locker(m_eventsLock); insertEvent(ParamEvent::createSetValueEvent(value, time), exceptionState); } @@ -203,6 +426,7 @@ if (!isNonNegativeAudioParamTime(time, exceptionState)) return; + MutexLocker locker(m_eventsLock); insertEvent( ParamEvent::createLinearRampEvent(value, time, initialValue, callTime), exceptionState); @@ -229,6 +453,7 @@ return; } + MutexLocker locker(m_eventsLock); insertEvent(ParamEvent::createExponentialRampEvent(value, time, initialValue, callTime), exceptionState); @@ -245,6 +470,8 @@ "Time constant")) return; + MutexLocker locker(m_eventsLock); + // If timeConstant = 0, we instantly jump to the target value, so // insert a SetValueEvent instead of SetTargetEvent. if (timeConstant == 0) { @@ -273,6 +500,7 @@ return; } + MutexLocker locker(m_eventsLock); insertEvent(ParamEvent::createSetValueCurveEvent(curve, time, duration), exceptionState); @@ -284,73 +512,73 @@ exceptionState); } -void AudioParamTimeline::insertEvent(const ParamEvent& event, +void AudioParamTimeline::insertEvent(std::unique_ptr<ParamEvent> event, ExceptionState& exceptionState) { DCHECK(isMainThread()); // Sanity check the event. Be super careful we're not getting infected with // NaN or Inf. These should have been handled by the caller. - bool isValid = event.getType() < ParamEvent::LastType && - std::isfinite(event.value()) && std::isfinite(event.time()) && - std::isfinite(event.timeConstant()) && - std::isfinite(event.duration()) && event.duration() >= 0; + bool isValid = event->getType() < ParamEvent::LastType && + std::isfinite(event->value()) && + std::isfinite(event->time()) && + std::isfinite(event->timeConstant()) && + std::isfinite(event->duration()) && event->duration() >= 0; DCHECK(isValid); if (!isValid) return; - MutexLocker locker(m_eventsLock); - unsigned i = 0; - double insertTime = event.time(); + double insertTime = event->time(); if (!m_events.size() && - (event.getType() == ParamEvent::LinearRampToValue || - event.getType() == ParamEvent::ExponentialRampToValue)) { + (event->getType() == ParamEvent::LinearRampToValue || + event->getType() == ParamEvent::ExponentialRampToValue)) { // There are no events preceding these ramps. Insert a new setValueAtTime // event to set the starting point for these events. m_events.insert(0, AudioParamTimeline::ParamEvent::createSetValueEvent( - event.initialValue(), event.callTime())); + event->initialValue(), event->callTime())); } for (i = 0; i < m_events.size(); ++i) { - if (event.getType() == ParamEvent::SetValueCurve) { + if (event->getType() == ParamEvent::SetValueCurve) { // If this event is a SetValueCurve, make sure it doesn't overlap any // existing event. It's ok if the SetValueCurve starts at the same time as // the end of some other duration. - double endTime = event.time() + event.duration(); - if (m_events[i].time() > event.time() && m_events[i].time() < endTime) { + double endTime = event->time() + event->duration(); + if (m_events[i]->time() > event->time() && + m_events[i]->time() < endTime) { exceptionState.throwDOMException( NotSupportedError, - eventToString(event) + " overlaps " + eventToString(m_events[i])); + eventToString(*event) + " overlaps " + eventToString(*m_events[i])); return; } } else { // Otherwise, make sure this event doesn't overlap any existing // SetValueCurve event. - if (m_events[i].getType() == ParamEvent::SetValueCurve) { - double endTime = m_events[i].time() + m_events[i].duration(); - if (event.time() >= m_events[i].time() && event.time() < endTime) { + if (m_events[i]->getType() == ParamEvent::SetValueCurve) { + double endTime = m_events[i]->time() + m_events[i]->duration(); + if (event->time() >= m_events[i]->time() && event->time() < endTime) { exceptionState.throwDOMException( - NotSupportedError, - eventToString(event) + " overlaps " + eventToString(m_events[i])); + NotSupportedError, eventToString(*event) + " overlaps " + + eventToString(*m_events[i])); return; } } } // Overwrite same event type and time. - if (m_events[i].time() == insertTime && - m_events[i].getType() == event.getType()) { - m_events[i] = event; + if (m_events[i]->time() == insertTime && + m_events[i]->getType() == event->getType()) { + m_events[i] = std::move(event); return; } - if (m_events[i].time() > insertTime) + if (m_events[i]->time() > insertTime) break; } - m_events.insert(i, event); + m_events.insert(i, std::move(event)); } bool AudioParamTimeline::hasValues() const { @@ -383,13 +611,130 @@ // Remove all events starting at startTime. for (unsigned i = 0; i < m_events.size(); ++i) { - if (m_events[i].time() >= startTime) { + if (m_events[i]->time() >= startTime) { m_events.remove(i, m_events.size() - i); break; } } } +void AudioParamTimeline::cancelValuesAndHoldAtTime( + double cancelTime, + ExceptionState& exceptionState) { + DCHECK(isMainThread()); + + if (!isNonNegativeAudioParamTime(cancelTime, exceptionState)) + return; + + MutexLocker locker(m_eventsLock); + + unsigned i; + // Find the first event at or just past cancelTime. + for (i = 0; i < m_events.size(); ++i) { + if (m_events[i]->time() > cancelTime) { + break; + } + } + + // The event that is being cancelled. This is the event just past + // cancelTime, if any. + unsigned cancelledEventIndex = i; + + // If the event just before cancelTime is a SetTarget or SetValueCurve + // event, we need to handle that event specially instead of the event after. + if (i > 0 && ((m_events[i - 1]->getType() == ParamEvent::SetTarget) || + (m_events[i - 1]->getType() == ParamEvent::SetValueCurve))) { + cancelledEventIndex = i - 1; + } else if (i >= m_events.size()) { + // If there were no events occurring after |cancelTime| (and the + // previous event is not SetTarget or SetValueCurve, we're done. + return; + } + + // cancelledEvent is the event that is being cancelled. + ParamEvent* cancelledEvent = m_events[cancelledEventIndex].get(); + ParamEvent::Type eventType = cancelledEvent->getType(); + + // New event to be inserted, if any, and a SetValueEvent if needed. + std::unique_ptr<ParamEvent> newEvent = nullptr; + std::unique_ptr<ParamEvent> newSetValueEvent = nullptr; + + switch (eventType) { + case ParamEvent::LinearRampToValue: + case ParamEvent::ExponentialRampToValue: { + // For these events we need to remember the parameters of the event + // for a CancelValues event so that we can properly cancel the event + // and hold the value. + std::unique_ptr<ParamEvent> savedEvent = ParamEvent::createGeneralEvent( + eventType, cancelledEvent->value(), cancelledEvent->time(), + cancelledEvent->initialValue(), cancelledEvent->callTime(), + cancelledEvent->timeConstant(), cancelledEvent->duration(), + cancelledEvent->curve(), cancelledEvent->curvePointsPerSecond(), + cancelledEvent->curveEndValue(), nullptr); + + newEvent = ParamEvent::createCancelValuesEvent(cancelTime, + std::move(savedEvent)); + } break; + case ParamEvent::SetTarget: { + // Don't want to remove the SetTarget event, so bump the index. But + // we do want to insert a cancelEvent so that we stop this + // automation and hold the value when we get there. + ++cancelledEventIndex; + + newEvent = ParamEvent::createCancelValuesEvent(cancelTime, nullptr); + } break; + case ParamEvent::SetValueCurve: { + double newDuration = cancelTime - cancelledEvent->time(); + + if (cancelTime > cancelledEvent->time() + cancelledEvent->duration()) { + // If the cancellation time is past the end of the curve, + // there's nothing to do except remove the following events. + ++cancelledEventIndex; + } else { + // Cancellation time is in the middle of the curve. Therefore, + // create a new SetValueCurve event with the appropriate new + // parameters to cancel this event properly. Since it's illegal + // to insert any event within a SetValueCurve event, we can + // compute the new end value now instead of doing when running + // the timeline. + float endValue = valueCurveAtTime( + cancelTime, cancelledEvent->time(), cancelledEvent->duration(), + cancelledEvent->curve().data(), cancelledEvent->curve().size()); + + // Replace the existing SetValueCurve with this new one that is + // identical except for the duration. + newEvent = ParamEvent::createGeneralEvent( + eventType, cancelledEvent->value(), cancelledEvent->time(), + cancelledEvent->initialValue(), cancelledEvent->callTime(), + cancelledEvent->timeConstant(), newDuration, + cancelledEvent->curve(), cancelledEvent->curvePointsPerSecond(), + endValue, nullptr); + + newSetValueEvent = ParamEvent::createSetValueEvent( + endValue, cancelledEvent->time() + newDuration); + } + } break; + case ParamEvent::SetValue: + case ParamEvent::CancelValues: + // Nothing needs to be done for a SetValue or CancelValues event. + break; + case ParamEvent::LastType: + NOTREACHED(); + break; + } + + // Now remove all the following events from the timeline. + if (cancelledEventIndex < m_events.size()) + m_events.remove(cancelledEventIndex, m_events.size() - cancelledEventIndex); + + // Insert the new event, if any. + if (newEvent) { + insertEvent(std::move(newEvent), exceptionState); + if (newSetValueEvent) + insertEvent(std::move(newSetValueEvent), exceptionState); + } +} + float AudioParamTimeline::valueForContextTime( AudioDestinationHandler& audioDestination, float defaultValue, @@ -399,7 +744,7 @@ { MutexTryLocker tryLocker(m_eventsLock); if (!tryLocker.locked() || !m_events.size() || - audioDestination.currentTime() < m_events[0].time()) { + audioDestination.currentTime() < m_events[0]->time()) { hasValue = false; return defaultValue; } @@ -462,7 +807,7 @@ // Return default value if there are no events matching the desired time // range. - if (!m_events.size() || (endFrame / sampleRate <= m_events[0].time())) { + if (!m_events.size() || (endFrame / sampleRate <= m_events[0]->time())) { for (unsigned i = 0; i < numberOfValues; ++i) values[i] = defaultValue; return defaultValue; @@ -477,20 +822,20 @@ // Look at all the events in the timeline and check to see if any needs // to clamp the start time to the current time. for (int k = 0; k < numberOfEvents; ++k) { - ParamEvent& event = m_events[k]; + ParamEvent* event = m_events[k].get(); // We're examining the event for the first time and the event time is // in the past so clamp the event time to the current time (start of // the rendering quantum). - if (event.needsTimeClampCheck()) { - if (event.time() < currentTime) { - event.setTime(currentTime); + if (event->needsTimeClampCheck()) { + if (event->time() < currentTime) { + event->setTime(currentTime); clampedSomeEventTime = true; } // In all cases, we can clear the flag because the event is either // in the future, or we've already checked it (just now). - event.clearTimeClampCheck(); + event->clearTimeClampCheck(); } } @@ -503,9 +848,9 @@ } // Optimize the case where the last event is in the past. - ParamEvent& lastEvent = m_events[m_events.size() - 1]; - ParamEvent::Type lastEventType = lastEvent.getType(); - double lastEventTime = lastEvent.time(); + ParamEvent* lastEvent = m_events[m_events.size() - 1].get(); + ParamEvent::Type lastEventType = lastEvent->getType(); + double lastEventTime = lastEvent->time(); // If the last event is in the past and the event has ended, then we can // just propagate the same value. Except for SetTarget which lasts @@ -531,7 +876,7 @@ // If first event is after startFrame then fill initial part of values buffer // with defaultValue until we reach the first event time. - double firstEventTime = m_events[0].time(); + double firstEventTime = m_events[0]->time(); if (firstEventTime > startFrame / sampleRate) { // |fillToFrame| is an exclusive upper bound, so use ceil() to compute the // bound from the firstEventTime. @@ -555,8 +900,8 @@ // stopping when we've rendered all the requested values. int lastSkippedEventIndex = 0; for (int i = 0; i < numberOfEvents && writeIndex < numberOfValues; ++i) { - ParamEvent& event = m_events[i]; - ParamEvent* nextEvent = i < numberOfEvents - 1 ? &(m_events[i + 1]) : 0; + ParamEvent* event = m_events[i].get(); + ParamEvent* nextEvent = i < numberOfEvents - 1 ? m_events[i + 1].get() : 0; // Wait until we get a more recent event. // @@ -579,12 +924,12 @@ // and not applied, which is wrong. Other events don't have this problem. // (Because currentFrame is unsigned, we do the time check in this funny, // but equivalent way.) - double eventFrame = event.time() * sampleRate; + double eventFrame = event->time() * sampleRate; // Condition is currentFrame - 1 < eventFrame <= currentFrame, but // currentFrame is unsigned and could be 0, so use // currentFrame < eventFrame + 1 instead. - if (!((event.getType() == ParamEvent::SetValue && + if (!((event->getType() == ParamEvent::SetValue && (eventFrame <= currentFrame) && (currentFrame < eventFrame + 1)))) { // This is not the special SetValue event case, and nextEvent is @@ -605,7 +950,7 @@ // LinearRampToValue or ExponentialRampToValue, special handling is needed. // In this case, the linear and exponential ramp should start at wherever // the SetTarget processing has reached. - if (event.getType() == ParamEvent::SetTarget && + if (event->getType() == ParamEvent::SetTarget && (nextEventType == ParamEvent::LinearRampToValue || nextEventType == ParamEvent::ExponentialRampToValue)) { // Replace the SetTarget with a SetValue to set the starting time and @@ -627,36 +972,111 @@ // -2 <= 2 * Fs * t0 - 2 * f <= 0 // -1 <= 2 * Fs * t0 - 2 * f + 1 <= 1 // abs(2 * Fs * t0 - 2 * f + 1) <= 1 - if (fabs(2 * sampleRate * event.time() - 2 * currentFrame + 1) <= 1) { + if (fabs(2 * sampleRate * event->time() - 2 * currentFrame + 1) <= 1) { // SetTarget is starting somewhere between currentFrame - 1 and // currentFrame. Compute the value the SetTarget would have at the // currentFrame. - value = event.value() + - (value - event.value()) * - exp(-(currentFrame / sampleRate - event.time()) / - event.timeConstant()); + value = event->value() + + (value - event->value()) * + exp(-(currentFrame / sampleRate - event->time()) / + event->timeConstant()); } else { // SetTarget has already started. Update |value| one frame because it's // the value from the previous frame. float discreteTimeConstant = static_cast<float>( AudioUtilities::discreteTimeConstantForSampleRate( - event.timeConstant(), controlRate)); - value += (event.value() - value) * discreteTimeConstant; + event->timeConstant(), controlRate)); + value += (event->value() - value) * discreteTimeConstant; } // Insert a SetValueEvent to mark the starting value and time. // Clear the clamp check because this doesn't need it. m_events[i] = ParamEvent::createSetValueEvent(value, currentFrame / sampleRate); - m_events[i].clearTimeClampCheck(); + m_events[i]->clearTimeClampCheck(); + + // Update our pointer to the current event because we just changed it. + event = m_events[i].get(); } - float value1 = event.value(); - double time1 = event.time(); + float value1 = event->value(); + double time1 = event->time(); float value2 = nextEvent ? nextEvent->value() : value1; double time2 = nextEvent ? nextEvent->time() : endFrame / sampleRate + 1; + // Check to see if an event was cancelled. + if (nextEventType == ParamEvent::CancelValues) { + switch (event->getType()) { + case ParamEvent::LinearRampToValue: + case ParamEvent::ExponentialRampToValue: + case ParamEvent::SetValue: { + // These three events potentially establish a starting value for + // the following event, so we need to examine the cancelled + // event to see what to do. + const ParamEvent* savedEvent = nextEvent->savedEvent(); + + // Update the end time and type to pretend that we're running + // this saved event type. + time2 = nextEvent->time(); + nextEventType = savedEvent->getType(); + + if (nextEvent->hasDefaultCancelledValue()) { + // We've already established a value for the cancelled + // event, so just return it. + value2 = nextEvent->value(); + } else { + // If the next event would have been a LinearRamp or + // ExponentialRamp, we need to compute a new end value for + // the event so that the curve works continues as if it were + // not cancelled. + switch (savedEvent->getType()) { + case ParamEvent::LinearRampToValue: + value2 = + linearRampAtTime(nextEvent->time(), value1, time1, + savedEvent->value(), savedEvent->time()); + break; + case ParamEvent::ExponentialRampToValue: + value2 = exponentialRampAtTime(nextEvent->time(), value1, time1, + savedEvent->value(), + savedEvent->time()); + break; + case ParamEvent::SetValueCurve: + case ParamEvent::SetValue: + case ParamEvent::SetTarget: + case ParamEvent::CancelValues: + // These cannot be possible types for the saved event + // because they can't be created. + // createCancelValuesEvent doesn't allow them (SetValue, + // SetTarget, CancelValues) or cancelScheduledValues() + // doesn't create such an event (SetValueCurve). + NOTREACHED(); + break; + case ParamEvent::LastType: + // Illegal event type. + NOTREACHED(); + break; + } + + // Cache the new value so we don't keep computing it over and over. + nextEvent->setCancelledValue(value2); + } + } break; + case ParamEvent::SetValueCurve: + // Everything needed for this was handled when cancelling was + // done. + break; + case ParamEvent::SetTarget: + case ParamEvent::CancelValues: + // Nothing special needs to be done for SetTarget or + // CancelValues followed by CancelValues. + break; + case ParamEvent::LastType: + NOTREACHED(); + break; + } + } + DCHECK_GE(time2, time1); double deltaTime = time2 - time1; float k = deltaTime > 0 ? 1 / deltaTime : 0; @@ -788,13 +1208,13 @@ } } else { // Handle event types not requiring looking ahead to the next event. - switch (event.getType()) { + switch (event->getType()) { case ParamEvent::SetValue: case ParamEvent::LinearRampToValue: { currentFrame = fillToEndFrame; // Simply stay at a constant value. - value = event.value(); + value = event->value(); for (; writeIndex < fillToFrame; ++writeIndex) values[writeIndex] = value; @@ -802,6 +1222,37 @@ break; } + case ParamEvent::CancelValues: { + // If the previous event was a SetTarget or ExponentialRamp + // event, the current value is one sample behind. Update + // the sample value by one sample, but only at the start of + // this CancelValues event. + if (event->hasDefaultCancelledValue()) { + value = event->value(); + } else { + double cancelFrame = time1 * sampleRate; + if (i >= 1 && cancelFrame <= currentFrame && + currentFrame < cancelFrame + 1) { + ParamEvent::Type lastEventType = m_events[i - 1]->getType(); + if (lastEventType == ParamEvent::SetTarget) { + float target = m_events[i - 1]->value(); + float timeConstant = m_events[i - 1]->timeConstant(); + float discreteTimeConstant = static_cast<float>( + AudioUtilities::discreteTimeConstantForSampleRate( + timeConstant, controlRate)); + value += (target - value) * discreteTimeConstant; + } + } + } + + // Simply stay at the current value. + for (; writeIndex < fillToFrame; ++writeIndex) + values[writeIndex] = value; + + currentFrame = fillToEndFrame; + break; + } + case ParamEvent::ExponentialRampToValue: { currentFrame = fillToEndFrame; @@ -809,8 +1260,8 @@ // (because the start and end values have the same sign, and neither // is 0), use the actual end value. If not, we have to propagate // whatever we have. - if (i >= 1 && ((m_events[i - 1].value() * event.value()) > 0)) - value = event.value(); + if (i >= 1 && ((m_events[i - 1]->value() * event->value()) > 0)) + value = event->value(); // Simply stay at a constant value from the last time. We don't want // to use the value of the event in case value1 * value2 < 0. In this @@ -827,8 +1278,8 @@ // v(t) = v2 + (v1 - v2)*exp(-(t-t1/tau)) // - float target = event.value(); - float timeConstant = event.timeConstant(); + float target = event->value(); + float timeConstant = event->timeConstant(); float discreteTimeConstant = static_cast<float>( AudioUtilities::discreteTimeConstantForSampleRate(timeConstant, controlRate)); @@ -917,16 +1368,18 @@ } case ParamEvent::SetValueCurve: { - Vector<float> curve = event.curve(); + Vector<float> curve = event->curve(); float* curveData = curve.data(); unsigned numberOfCurvePoints = curve.size(); + float curveEndValue = event->curveEndValue(); + // Curve events have duration, so don't just use next event time. - double duration = event.duration(); + double duration = event->duration(); // How much to step the curve index for each frame. This is basically // the term (N - 1)/Td in the specification. double curvePointsPerFrame = - (numberOfCurvePoints - 1) / duration / sampleRate; + event->curvePointsPerSecond() / sampleRate; if (!numberOfCurvePoints || duration <= 0 || sampleRate <= 0) { // Error condition - simply propagate previous value. @@ -976,7 +1429,7 @@ } // Set the default value in case fillToFrame is 0. - value = curveData[numberOfCurvePoints - 1]; + value = curveEndValue; // Render the stretched curve data using linear interpolation. // Oversampled curve data can be provided if sharp discontinuities are @@ -1079,11 +1532,12 @@ // If there's any time left after the duration of this event and the // start of the next, then just propagate the last value of the - // curveData. - if (writeIndex < nextEventFillToFrame) - value = curveData[numberOfCurvePoints - 1]; - for (; writeIndex < nextEventFillToFrame; ++writeIndex) - values[writeIndex] = value; + // curveData. Don't modify |value| unless there is time left. + if (writeIndex < nextEventFillToFrame) { + value = curveEndValue; + for (; writeIndex < nextEventFillToFrame; ++writeIndex) + values[writeIndex] = value; + } // Re-adjust current time currentFrame += nextEventFillToFrame;
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h index eeb09099..7899745 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h
@@ -64,6 +64,7 @@ double duration, ExceptionState&); void cancelScheduledValues(double startTime, ExceptionState&); + void cancelValuesAndHoldAtTime(double cancelTime, ExceptionState&); // hasValue is set to true if a valid timeline value is returned. // otherwise defaultValue is returned. @@ -105,27 +106,50 @@ ExponentialRampToValue, SetTarget, SetValueCurve, + // For cancelValuesAndHold + CancelValues, LastType }; - static ParamEvent createLinearRampEvent(float value, - double time, - float initialValue, - double callTime); - static ParamEvent createExponentialRampEvent(float value, - double time, - float initialValue, - double callTime); - static ParamEvent createSetValueEvent(float value, double time); - static ParamEvent createSetTargetEvent(float value, - double time, - double timeConstant); - static ParamEvent createSetValueCurveEvent(const DOMFloat32Array* curve, - double time, - double duration); + static std::unique_ptr<ParamEvent> createLinearRampEvent(float value, + double time, + float initialValue, + double callTime); + static std::unique_ptr<ParamEvent> createExponentialRampEvent( + float value, + double time, + float initialValue, + double callTime); + static std::unique_ptr<ParamEvent> createSetValueEvent(float value, + double time); + static std::unique_ptr<ParamEvent> + createSetTargetEvent(float value, double time, double timeConstant); + static std::unique_ptr<ParamEvent> createSetValueCurveEvent( + const DOMFloat32Array* curve, + double time, + double duration); + static std::unique_ptr<ParamEvent> createCancelValuesEvent( + double time, + std::unique_ptr<ParamEvent> savedEvent); + // Needed for creating a saved event where we want to supply all + // the possible parameters because we're mostly copying an + // existing event. + static std::unique_ptr<ParamEvent> createGeneralEvent( + Type, + float value, + double time, + float initialValue, + double callTime, + double timeConstant, + double duration, + Vector<float>& curve, + double curvePointsPerSecond, + float curveEndValue, + std::unique_ptr<ParamEvent> savedEvent); - static bool eventPreceeds(const ParamEvent& a, const ParamEvent& b) { - return a.time() < b.time(); + static bool eventPreceeds(const std::unique_ptr<ParamEvent>& a, + const std::unique_ptr<ParamEvent>& b) { + return a->time() < b->time(); } Type getType() const { return m_type; } @@ -140,34 +164,104 @@ bool needsTimeClampCheck() const { return m_needsTimeClampCheck; } void clearTimeClampCheck() { m_needsTimeClampCheck = false; } + double curvePointsPerSecond() const { return m_curvePointsPerSecond; } + float curveEndValue() const { return m_curveEndValue; } + + // For CancelValues events. Not valid for any other event. + ParamEvent* savedEvent() const; + bool hasDefaultCancelledValue() const; + void setCancelledValue(float); + private: + // General event ParamEvent(Type type, float value, double time, + float initialValue, + double callTime, double timeConstant, double duration, + Vector<float>& curve, + double curvePointsPerSecond, + float curveEndValue, + std::unique_ptr<ParamEvent> savedEvent); + + // Create simplest event needing just a value and time, like + // setValueAtTime. + ParamEvent(Type, float value, double time); + + // Create a linear or exponential ramp that requires an initial + // value and time in case there is no actual event that preceeds + // this event. + ParamEvent(Type, + float value, + double time, + float initialValue, + double callTime); + + // Create an event needing a time constant (setTargetAtTime) + ParamEvent(Type, float value, double time, double timeConstant); + + // Create a setValueCurve event + ParamEvent(Type, + double time, + double duration, const DOMFloat32Array* curve, - float initialValue = 0, - double callTime = 0); + double curvePointsPerSecond, + float curveEndValue); + + // Create CancelValues event + ParamEvent(Type, double time, std::unique_ptr<ParamEvent> savedEvent); Type m_type; + + // The value for the event. The interpretation of this depends on + // the event type. Not used for SetValueCurve. For CancelValues, + // it is the end value to use when cancelling a LinearRampToValue + // or ExponentialRampToValue event. float m_value; + + // The time for the event. The interpretation of this depends on + // the event type. double m_time; - // Only used for SetTarget events - double m_timeConstant; - // Only used for SetValueCurve events. - double m_duration; - Vector<float> m_curve; + // Initial value and time to use for linear and exponential ramps that don't // have a preceding event. float m_initialValue; double m_callTime; + + // Only used for SetTarget events + double m_timeConstant; + + // The following items are only used for SetValueCurve events. + // + // The duration of the curve. + double m_duration; + // The array of curve points. + Vector<float> m_curve; + // The number of curve points per second. it is used to compute + // the curve index step when running the automation. + double m_curvePointsPerSecond; + // The default value to use at the end of the curve. Normally + // it's the last entry in m_curve, but cancelling a SetValueCurve + // will set this to a new value. + float m_curveEndValue; + + // For CancelValues. If CancelValues is in the middle of an event, this + // holds the event that is being cancelled, so that processing can + // continue as if the event still existed up until we reach the actual + // scheduled cancel time. + std::unique_ptr<ParamEvent> m_savedEvent; + // True if the start time needs to be checked against current time // to implement clamping. bool m_needsTimeClampCheck; + + // True if a default value has been assigned to the CancelValues event. + bool m_hasDefaultCancelledValue; }; - void insertEvent(const ParamEvent&, ExceptionState&); + void insertEvent(std::unique_ptr<ParamEvent>, ExceptionState&); float valuesForFrameRangeImpl(size_t startFrame, size_t endFrame, float defaultValue, @@ -178,7 +272,33 @@ // Produce a nice string describing the event in human-readable form. String eventToString(const ParamEvent&); - Vector<ParamEvent> m_events; + + // Automation functions that compute the vlaue of the specified + // automation at the specified time. + float linearRampAtTime(double t, + float value1, + double time1, + float value2, + double time2); + float exponentialRampAtTime(double t, + float value1, + double time1, + float value2, + double time2); + float targetValueAtTime(double t, + float value1, + double time1, + float value2, + float timeConstant); + float valueCurveAtTime(double t, + double time1, + double duration, + const float* curveData, + unsigned curveLength); + + // Vector of all automation events for the AudioParam. Access must + // be locked via m_eventsLock. + Vector<std::unique_ptr<ParamEvent>> m_events; mutable Mutex m_eventsLock;
diff --git a/third_party/WebKit/Source/platform/exported/WebMixedContent.cpp b/third_party/WebKit/Source/platform/exported/WebMixedContent.cpp index d2d3641..f572535 100644 --- a/third_party/WebKit/Source/platform/exported/WebMixedContent.cpp +++ b/third_party/WebKit/Source/platform/exported/WebMixedContent.cpp
@@ -33,7 +33,7 @@ namespace blink { // static -WebMixedContent::ContextType WebMixedContent::contextTypeFromRequestContext( +WebMixedContentContextType WebMixedContent::contextTypeFromRequestContext( WebURLRequest::RequestContext context, bool strictMixedContentCheckingForPlugin) { switch (context) { @@ -42,13 +42,13 @@ case WebURLRequest::RequestContextFavicon: case WebURLRequest::RequestContextImage: case WebURLRequest::RequestContextVideo: - return ContextType::OptionallyBlockable; + return WebMixedContentContextType::OptionallyBlockable; // Plugins! Oh how dearly we love plugin-loaded content! case WebURLRequest::RequestContextPlugin: { return strictMixedContentCheckingForPlugin - ? ContextType::Blockable - : ContextType::OptionallyBlockable; + ? WebMixedContentContextType::Blockable + : WebMixedContentContextType::OptionallyBlockable; } // "Blockable" mixed content @@ -78,96 +78,19 @@ case WebURLRequest::RequestContextWorker: case WebURLRequest::RequestContextXMLHttpRequest: case WebURLRequest::RequestContextXSLT: - return ContextType::Blockable; + return WebMixedContentContextType::Blockable; // FIXME: Contexts that we should block, but don't currently. // https://crbug.com/388650 case WebURLRequest::RequestContextDownload: case WebURLRequest::RequestContextPrefetch: - return ContextType::ShouldBeBlockable; + return WebMixedContentContextType::ShouldBeBlockable; case WebURLRequest::RequestContextUnspecified: NOTREACHED(); } NOTREACHED(); - return ContextType::Blockable; -} - -// static -const char* WebMixedContent::requestContextName( - WebURLRequest::RequestContext context) { - switch (context) { - case WebURLRequest::RequestContextAudio: - return "audio file"; - case WebURLRequest::RequestContextBeacon: - return "Beacon endpoint"; - case WebURLRequest::RequestContextCSPReport: - return "Content Security Policy reporting endpoint"; - case WebURLRequest::RequestContextDownload: - return "download"; - case WebURLRequest::RequestContextEmbed: - return "plugin resource"; - case WebURLRequest::RequestContextEventSource: - return "EventSource endpoint"; - case WebURLRequest::RequestContextFavicon: - return "favicon"; - case WebURLRequest::RequestContextFetch: - return "resource"; - case WebURLRequest::RequestContextFont: - return "font"; - case WebURLRequest::RequestContextForm: - return "form action"; - case WebURLRequest::RequestContextFrame: - return "frame"; - case WebURLRequest::RequestContextHyperlink: - return "resource"; - case WebURLRequest::RequestContextIframe: - return "frame"; - case WebURLRequest::RequestContextImage: - return "image"; - case WebURLRequest::RequestContextImageSet: - return "image"; - case WebURLRequest::RequestContextImport: - return "HTML Import"; - case WebURLRequest::RequestContextInternal: - return "resource"; - case WebURLRequest::RequestContextLocation: - return "resource"; - case WebURLRequest::RequestContextManifest: - return "manifest"; - case WebURLRequest::RequestContextObject: - return "plugin resource"; - case WebURLRequest::RequestContextPing: - return "hyperlink auditing endpoint"; - case WebURLRequest::RequestContextPlugin: - return "plugin data"; - case WebURLRequest::RequestContextPrefetch: - return "prefetch resource"; - case WebURLRequest::RequestContextScript: - return "script"; - case WebURLRequest::RequestContextServiceWorker: - return "Service Worker script"; - case WebURLRequest::RequestContextSharedWorker: - return "Shared Worker script"; - case WebURLRequest::RequestContextStyle: - return "stylesheet"; - case WebURLRequest::RequestContextSubresource: - return "resource"; - case WebURLRequest::RequestContextTrack: - return "Text Track"; - case WebURLRequest::RequestContextUnspecified: - return "resource"; - case WebURLRequest::RequestContextVideo: - return "video"; - case WebURLRequest::RequestContextWorker: - return "Worker script"; - case WebURLRequest::RequestContextXMLHttpRequest: - return "XMLHttpRequest endpoint"; - case WebURLRequest::RequestContextXSLT: - return "XSLT"; - } - NOTREACHED(); - return "resource"; + return WebMixedContentContextType::Blockable; } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontCache.cpp b/third_party/WebKit/Source/platform/fonts/FontCache.cpp index 46d0b1d..64be67e 100644 --- a/third_party/WebKit/Source/platform/fonts/FontCache.cpp +++ b/third_party/WebKit/Source/platform/fonts/FontCache.cpp
@@ -233,12 +233,9 @@ return fontVerticalDataCache; } -void FontCache::setFontManager(const sk_sp<SkFontMgr>& fontManager) { +void FontCache::setFontManager(sk_sp<SkFontMgr> fontManager) { DCHECK(!s_staticFontManager); - s_staticFontManager = fontManager.get(); - // Explicitly AddRef since we're going to hold on to the object for the life - // of the program. - s_staticFontManager->ref(); + s_staticFontManager = fontManager.release(); } PassRefPtr<OpenTypeVerticalData> FontCache::getVerticalData(
diff --git a/third_party/WebKit/Source/platform/fonts/FontCache.h b/third_party/WebKit/Source/platform/fonts/FontCache.h index 1e0ff6a..8b5febdd8 100644 --- a/third_party/WebKit/Source/platform/fonts/FontCache.h +++ b/third_party/WebKit/Source/platform/fonts/FontCache.h
@@ -114,7 +114,7 @@ void invalidate(); SkFontMgr* fontManager() { return m_fontManager.get(); } - static void setFontManager(const sk_sp<SkFontMgr>&); + static void setFontManager(sk_sp<SkFontMgr>); #if !OS(MACOSX) static const AtomicString& systemFontFamily(); @@ -246,6 +246,7 @@ sk_sp<SkFontMgr> m_fontManager; + // A leaky owning bare pointer. static SkFontMgr* s_staticFontManager; #if OS(WIN)
diff --git a/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp b/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp index 4b51489..a96b8ba 100644 --- a/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp +++ b/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
@@ -34,14 +34,8 @@ namespace blink { -FontCache::FontCache() : m_purgePreventCount(0) { - if (s_staticFontManager) { - adopted(s_staticFontManager); - m_fontManager = sk_ref_sp(s_staticFontManager); - } else { - m_fontManager = nullptr; - } -} +FontCache::FontCache() + : m_purgePreventCount(0), m_fontManager(sk_ref_sp(s_staticFontManager)) {} static AtomicString& mutableSystemFontFamily() { DEFINE_STATIC_LOCAL(AtomicString, systemFontFamily, ());
diff --git a/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp b/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp index ed5c3ec..8aebb5e 100644 --- a/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp +++ b/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp
@@ -104,7 +104,7 @@ FontCache::FontCache() : m_purgePreventCount(0) { m_fontManager = sk_ref_sp(s_staticFontManager); if (!m_fontManager) - m_fontManager.reset(SkFontMgr_New_DirectWrite()); + m_fontManager = SkFontMgr_New_DirectWrite(); ASSERT(m_fontManager.get()); }
diff --git a/third_party/WebKit/Source/web/linux/WebFontRendering.cpp b/third_party/WebKit/Source/web/linux/WebFontRendering.cpp index 398fc31..8a901e8 100644 --- a/third_party/WebKit/Source/web/linux/WebFontRendering.cpp +++ b/third_party/WebKit/Source/web/linux/WebFontRendering.cpp
@@ -41,9 +41,8 @@ namespace blink { // static -void WebFontRendering::setSkiaFontManager(SkFontMgr* fontMgr) { - WTF::adopted(fontMgr); - FontCache::setFontManager(sk_ref_sp(fontMgr)); +void WebFontRendering::setSkiaFontManager(sk_sp<SkFontMgr> fontMgr) { + FontCache::setFontManager(std::move(fontMgr)); } // static
diff --git a/third_party/WebKit/Source/web/win/WebFontRendering.cpp b/third_party/WebKit/Source/web/win/WebFontRendering.cpp index 4d468805..56f73fd 100644 --- a/third_party/WebKit/Source/web/win/WebFontRendering.cpp +++ b/third_party/WebKit/Source/web/win/WebFontRendering.cpp
@@ -9,9 +9,8 @@ namespace blink { // static -void WebFontRendering::setSkiaFontManager(SkFontMgr* fontMgr) { - WTF::adopted(fontMgr); - FontCache::setFontManager(sk_ref_sp(fontMgr)); +void WebFontRendering::setSkiaFontManager(sk_sp<SkFontMgr> fontMgr) { + FontCache::setFontManager(std::move(fontMgr)); } // static
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index 47e5c4a..18b84024 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -236,6 +236,7 @@ "platform/WebMessagePortChannel.h", "platform/WebMessagePortChannelClient.h", "platform/WebMixedContent.h", + "platform/WebMixedContentContextType.h", "platform/WebMockClipboard.h", "platform/WebNativeScrollBehavior.h", "platform/WebNavigationHintType.h",
diff --git a/third_party/WebKit/public/platform/WebMixedContent.h b/third_party/WebKit/public/platform/WebMixedContent.h index e263e5c2c..c8596eb 100644 --- a/third_party/WebKit/public/platform/WebMixedContent.h +++ b/third_party/WebKit/public/platform/WebMixedContent.h
@@ -31,26 +31,17 @@ #ifndef WebMixedContent_h #define WebMixedContent_h +#include "public/platform/WebMixedContentContextType.h" #include "public/platform/WebURLRequest.h" namespace blink { -// Types and helper functions related to mixed content checks. +// Helper functions related to mixed content checks. class WebMixedContent { public: - enum class ContextType { - NotMixedContent, - Blockable, - OptionallyBlockable, - ShouldBeBlockable, - }; - - BLINK_PLATFORM_EXPORT static ContextType contextTypeFromRequestContext( - WebURLRequest::RequestContext, - bool strictMixedContentCheckingForPlugin); - - BLINK_PLATFORM_EXPORT static const char* requestContextName( - WebURLRequest::RequestContext); + BLINK_PLATFORM_EXPORT static WebMixedContentContextType + contextTypeFromRequestContext(WebURLRequest::RequestContext, + bool strictMixedContentCheckingForPlugin); }; } // namespace blink
diff --git a/third_party/WebKit/public/platform/WebMixedContentContextType.h b/third_party/WebKit/public/platform/WebMixedContentContextType.h new file mode 100644 index 0000000..604526c --- /dev/null +++ b/third_party/WebKit/public/platform/WebMixedContentContextType.h
@@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebMixedContentContextType_h +#define WebMixedContentContextType_h + +namespace blink { + +// Types and helper functions related to mixed content checks. +enum class WebMixedContentContextType { + NotMixedContent, + Blockable, + OptionallyBlockable, + ShouldBeBlockable, + Last = ShouldBeBlockable +}; + +} // namespace blink + +#endif // WebMixedContentContextType_h
diff --git a/third_party/WebKit/public/web/linux/WebFontRendering.h b/third_party/WebKit/public/web/linux/WebFontRendering.h index d52b018..f3097e68 100644 --- a/third_party/WebKit/public/web/linux/WebFontRendering.h +++ b/third_party/WebKit/public/web/linux/WebFontRendering.h
@@ -42,7 +42,7 @@ public: // Set global font renderering preferences. - BLINK_EXPORT static void setSkiaFontManager(SkFontMgr*); + BLINK_EXPORT static void setSkiaFontManager(sk_sp<SkFontMgr>); BLINK_EXPORT static void setHinting(SkPaint::Hinting); BLINK_EXPORT static void setAutoHint(bool); BLINK_EXPORT static void setUseBitmaps(bool);
diff --git a/third_party/WebKit/public/web/win/WebFontRendering.h b/third_party/WebKit/public/web/win/WebFontRendering.h index a4933e1..cdb39bda 100644 --- a/third_party/WebKit/public/web/win/WebFontRendering.h +++ b/third_party/WebKit/public/web/win/WebFontRendering.h
@@ -6,6 +6,7 @@ #define WebFontRendering_h #include "public/platform/WebCommon.h" +#include "third_party/skia/include/core/SkRefCnt.h" class SkFontMgr; class SkTypeface; @@ -14,7 +15,7 @@ class WebFontRendering { public: - BLINK_EXPORT static void setSkiaFontManager(SkFontMgr*); + BLINK_EXPORT static void setSkiaFontManager(sk_sp<SkFontMgr>); BLINK_EXPORT static void setDeviceScaleFactor(float); BLINK_EXPORT static void addSideloadedFontForTesting(SkTypeface*); BLINK_EXPORT static void setMenuFontMetrics(const wchar_t* familyName,
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index 2a8d12b5..7fcfd85 100644 --- a/third_party/libvpx/README.chromium +++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@ License File: source/libvpx/LICENSE Security Critical: yes -Date: Tuesday December 20 2016 +Date: Monday January 09 2017 Branch: master -Commit: f27276f44fa3a66c07a2a92a381f31aaf8371add +Commit: 5b1a8ca5e846f838062becaec9ed6b5ecef306e5 Description: Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/libvpx_srcs.gni b/third_party/libvpx/libvpx_srcs.gni index d57d692..664a0fd 100644 --- a/third_party/libvpx/libvpx_srcs.gni +++ b/third_party/libvpx/libvpx_srcs.gni
@@ -2306,7 +2306,6 @@ "//third_party/libvpx/source/libvpx/vpx_dsp/arm/hadamard_neon.c", "//third_party/libvpx/source/libvpx/vpx_dsp/arm/idct16x16_1_add_neon.c", "//third_party/libvpx/source/libvpx/vpx_dsp/arm/idct16x16_add_neon.c", - "//third_party/libvpx/source/libvpx/vpx_dsp/arm/idct16x16_neon.c", "//third_party/libvpx/source/libvpx/vpx_dsp/arm/idct32x32_135_add_neon.c", "//third_party/libvpx/source/libvpx/vpx_dsp/arm/idct32x32_1_add_neon.c", "//third_party/libvpx/source/libvpx/vpx_dsp/arm/idct32x32_34_add_neon.c",
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h index a1696e9..c9d867d 100644 --- a/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h
@@ -427,10 +427,12 @@ #define vpx_lpf_vertical_8_dual vpx_lpf_vertical_8_dual_neon void vpx_mbpost_proc_across_ip_c(unsigned char *dst, int pitch, int rows, int cols,int flimit); -#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_c +void vpx_mbpost_proc_across_ip_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit); +#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_neon void vpx_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols,int flimit); -#define vpx_mbpost_proc_down vpx_mbpost_proc_down_c +void vpx_mbpost_proc_down_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit); +#define vpx_mbpost_proc_down vpx_mbpost_proc_down_neon void vpx_minmax_8x8_c(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max); void vpx_minmax_8x8_neon(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h index a1696e9..c9d867d 100644 --- a/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h
@@ -427,10 +427,12 @@ #define vpx_lpf_vertical_8_dual vpx_lpf_vertical_8_dual_neon void vpx_mbpost_proc_across_ip_c(unsigned char *dst, int pitch, int rows, int cols,int flimit); -#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_c +void vpx_mbpost_proc_across_ip_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit); +#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_neon void vpx_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols,int flimit); -#define vpx_mbpost_proc_down vpx_mbpost_proc_down_c +void vpx_mbpost_proc_down_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit); +#define vpx_mbpost_proc_down vpx_mbpost_proc_down_neon void vpx_minmax_8x8_c(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max); void vpx_minmax_8x8_neon(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h index 5bfb6e77..2712530 100644 --- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
@@ -427,10 +427,12 @@ RTCD_EXTERN void (*vpx_lpf_vertical_8_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1); void vpx_mbpost_proc_across_ip_c(unsigned char *dst, int pitch, int rows, int cols,int flimit); -#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_c +void vpx_mbpost_proc_across_ip_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit); +RTCD_EXTERN void (*vpx_mbpost_proc_across_ip)(unsigned char *dst, int pitch, int rows, int cols,int flimit); void vpx_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols,int flimit); -#define vpx_mbpost_proc_down vpx_mbpost_proc_down_c +void vpx_mbpost_proc_down_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit); +RTCD_EXTERN void (*vpx_mbpost_proc_down)(unsigned char *dst, int pitch, int rows, int cols,int flimit); void vpx_minmax_8x8_c(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max); void vpx_minmax_8x8_neon(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max); @@ -988,6 +990,10 @@ if (flags & HAS_NEON) vpx_lpf_vertical_8 = vpx_lpf_vertical_8_neon; vpx_lpf_vertical_8_dual = vpx_lpf_vertical_8_dual_c; if (flags & HAS_NEON) vpx_lpf_vertical_8_dual = vpx_lpf_vertical_8_dual_neon; + vpx_mbpost_proc_across_ip = vpx_mbpost_proc_across_ip_c; + if (flags & HAS_NEON) vpx_mbpost_proc_across_ip = vpx_mbpost_proc_across_ip_neon; + vpx_mbpost_proc_down = vpx_mbpost_proc_down_c; + if (flags & HAS_NEON) vpx_mbpost_proc_down = vpx_mbpost_proc_down_neon; vpx_minmax_8x8 = vpx_minmax_8x8_c; if (flags & HAS_NEON) vpx_minmax_8x8 = vpx_minmax_8x8_neon; vpx_mse16x16 = vpx_mse16x16_c;
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h index a1696e9..c9d867d 100644 --- a/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
@@ -427,10 +427,12 @@ #define vpx_lpf_vertical_8_dual vpx_lpf_vertical_8_dual_neon void vpx_mbpost_proc_across_ip_c(unsigned char *dst, int pitch, int rows, int cols,int flimit); -#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_c +void vpx_mbpost_proc_across_ip_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit); +#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_neon void vpx_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols,int flimit); -#define vpx_mbpost_proc_down vpx_mbpost_proc_down_c +void vpx_mbpost_proc_down_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit); +#define vpx_mbpost_proc_down vpx_mbpost_proc_down_neon void vpx_minmax_8x8_c(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max); void vpx_minmax_8x8_neon(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h index a1696e9..c9d867d 100644 --- a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
@@ -427,10 +427,12 @@ #define vpx_lpf_vertical_8_dual vpx_lpf_vertical_8_dual_neon void vpx_mbpost_proc_across_ip_c(unsigned char *dst, int pitch, int rows, int cols,int flimit); -#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_c +void vpx_mbpost_proc_across_ip_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit); +#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_neon void vpx_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols,int flimit); -#define vpx_mbpost_proc_down vpx_mbpost_proc_down_c +void vpx_mbpost_proc_down_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit); +#define vpx_mbpost_proc_down vpx_mbpost_proc_down_neon void vpx_minmax_8x8_c(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max); void vpx_minmax_8x8_neon(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h index 2617545..07f046e 100644 --- a/third_party/libvpx/source/config/vpx_version.h +++ b/third_party/libvpx/source/config/vpx_version.h
@@ -1,7 +1,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 6 #define VERSION_PATCH 0 -#define VERSION_EXTRA "843-gf27276f" +#define VERSION_EXTRA "903-g5b1a8ca5e" #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.6.0-843-gf27276f" -#define VERSION_STRING " v1.6.0-843-gf27276f" +#define VERSION_STRING_NOSP "v1.6.0-903-g5b1a8ca5e" +#define VERSION_STRING " v1.6.0-903-g5b1a8ca5e"
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath index d1882a5..2ce8f3b 100644 --- a/tools/android/eclipse/.classpath +++ b/tools/android/eclipse/.classpath
@@ -17,7 +17,6 @@ {% endblock %} --> <classpath> <classpathentry kind="src" path="android_webview/glue/java/src"/> - <classpathentry kind="src" path="android_webview/java/generated_src"/> <classpathentry kind="src" path="android_webview/java/src"/> <classpathentry kind="src" path="android_webview/javatests/src"/> <classpathentry kind="src" path="android_webview/test/shell/src"/>
diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp index bf1d77d..2d6713c 100644 --- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp +++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
@@ -431,15 +431,39 @@ return false; } - // If the expression is a template input then its coming at compile time so - // we consider it const. And we can't check isEvaluatable() in this case as - // it will do bad things/crash. - if (expr->isInstantiationDependent()) - return true; + // If the expression depends on template input, we can not call + // isEvaluatable() on it as it will do bad things/crash. + if (!expr->isInstantiationDependent()) { + // If the expression can be evaluated at compile time, then it should have a + // kFoo style name. Otherwise, not. + return expr->isEvaluatable(context); + } - // If the expression can be evaluated at compile time, then it should have a - // kFoo style name. Otherwise, not. - return expr->isEvaluatable(context); + // We do our best to figure out special cases as we come across them here, for + // template dependent situations. Some cases in code are only considered + // instantiation dependent for some template instantiations! Which is + // terrible! So most importantly we try to match isEvaluatable in those cases. + switch (expr->getStmtClass()) { + case clang::Stmt::CXXThisExprClass: + return false; + case clang::Stmt::DeclRefExprClass: { + auto* declref = clang::dyn_cast<clang::DeclRefExpr>(expr); + auto* decl = declref->getDecl(); + if (auto* vardecl = clang::dyn_cast<clang::VarDecl>(decl)) { + if (auto* initializer = vardecl->getInit()) + return CanBeEvaluatedAtCompileTime(initializer, context); + return false; + } + break; + } + + default: + break; + } + + // Otherwise, we consider depending on template parameters to not interfere + // with being const.. with exceptions hopefully covered above. + return true; } bool IsProbablyConst(const clang::VarDecl& decl,
diff --git a/tools/clang/rewrite_to_chrome_style/tests/template-expected.cc b/tools/clang/rewrite_to_chrome_style/tests/template-expected.cc index dc46c19a3a..5c9103d9 100644 --- a/tools/clang/rewrite_to_chrome_style/tests/template-expected.cc +++ b/tools/clang/rewrite_to_chrome_style/tests/template-expected.cc
@@ -64,6 +64,8 @@ const bool kComplexConst = number || (number + 1); // A complex statement with a non-const thing is not const. const bool complex_not_const = number || (g_global_number + 1); + // A const built from other consts is a const. + const bool kConstFromAConst = kComplexConst || number; } template <int number, typename... T> @@ -76,6 +78,40 @@ const int kIsAConstToo = number; } +namespace test_member_in_template { + +template <typename T> +class HasAMember { + public: + HasAMember() {} + HasAMember(const T&) {} + + void UsesMember() { const int not_const = i_; } + void AlsoUsesMember(); + + private: + int i_; +}; + +template <typename T> +void HasAMember<T>::AlsoUsesMember() { + const int not_const = i_; +} + +template <typename T> +static void BasedOnSubType(const HasAMember<T>& t) { + const HasAMember<T> problematic_not_const(t); +} + +void Run() { + HasAMember<int>().UsesMember(); + + BasedOnSubType<int>(HasAMember<int>()); + enum E { A }; + BasedOnSubType<E>(HasAMember<E>()); +} +} + namespace test_template_arg_is_function { void F(int x) {}
diff --git a/tools/clang/rewrite_to_chrome_style/tests/template-original.cc b/tools/clang/rewrite_to_chrome_style/tests/template-original.cc index 754e755d..47aef5d8 100644 --- a/tools/clang/rewrite_to_chrome_style/tests/template-original.cc +++ b/tools/clang/rewrite_to_chrome_style/tests/template-original.cc
@@ -63,6 +63,8 @@ const bool complexConst = number || (number + 1); // A complex statement with a non-const thing is not const. const bool complexNotConst = number || (g_globalNumber + 1); + // A const built from other consts is a const. + const bool constFromAConst = complexConst || number; } template <int number, typename... T> @@ -75,6 +77,40 @@ const int isAConstToo = number; } +namespace test_member_in_template { + +template <typename T> +class HasAMember { + public: + HasAMember() {} + HasAMember(const T&) {} + + void usesMember() { const int notConst = m_i; } + void alsoUsesMember(); + + private: + int m_i; +}; + +template <typename T> +void HasAMember<T>::alsoUsesMember() { + const int notConst = m_i; +} + +template <typename T> +static void basedOnSubType(const HasAMember<T>& t) { + const HasAMember<T> problematicNotConst(t); +} + +void Run() { + HasAMember<int>().usesMember(); + + basedOnSubType<int>(HasAMember<int>()); + enum E { A }; + basedOnSubType<E>(HasAMember<E>()); +} +} + namespace test_template_arg_is_function { void f(int x) {}
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 7457a91..c231521 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -399,8 +399,7 @@ need_gold_plugin = 'LLVM_DOWNLOAD_GOLD_PLUGIN' in os.environ or ( sys.platform.startswith('linux') and - 'buildtype=Official' in os.environ.get('GYP_DEFINES', '') and - 'branding=Chrome' in os.environ.get('GYP_DEFINES', '')) + 'buildtype=Official' in os.environ.get('GYP_DEFINES', '')) if ReadStampFile() == PACKAGE_VERSION and not args.force_local_build: print 'Clang is already up to date.'
diff --git a/tools/perf/generate_perf_json.py b/tools/perf/generate_perf_json.py index 08bb666..7819421 100755 --- a/tools/perf/generate_perf_json.py +++ b/tools/perf/generate_perf_json.py
@@ -328,7 +328,11 @@ 'device_ids': [ 'build164-m1', 'build165-m1', 'build166-m1', 'build167-m1', 'build168-m1' - ] + ], + 'perf_tests': [ + ('angle_perftests', 2), + ('load_library_perf_tests', 2), + ('performance_browser_tests', 2)] } ]) waterfall = add_tester(
diff --git a/tools/resource_prefetch_predictor/prefetch_predictor_tool.py b/tools/resource_prefetch_predictor/prefetch_predictor_tool.py index 1160f5f..9680c65 100755 --- a/tools/resource_prefetch_predictor/prefetch_predictor_tool.py +++ b/tools/resource_prefetch_predictor/prefetch_predictor_tool.py
@@ -13,6 +13,7 @@ import argparse import sqlite3 +import os from resource_prefetch_predictor_pb2 import (PrefetchData, ResourceData) @@ -77,6 +78,15 @@ continue self._PrettyPrintResource(resource) +# The version of python sqlite3 library we have in Ubuntu 14.04 LTS doesn't +# support views but command line util does. +# TODO(alexilin): get rid of this when python sqlite3 adds view support. +def CreateCompatibleDatabaseCopy(filename): + import tempfile, shutil, subprocess + _, tmpfile = tempfile.mkstemp() + shutil.copy2(filename, tmpfile) + subprocess.call(['sqlite3', tmpfile, 'DROP VIEW MmapStatus']) + return tmpfile def DatabaseStats(filename, domain): connection = sqlite3.connect(filename) @@ -94,7 +104,12 @@ help='Path to the database') parser.add_argument('-d', dest='domain', default=None, help='Domain') args = parser.parse_args() - DatabaseStats(args.database_filename, args.domain) + try: + database_copy = CreateCompatibleDatabaseCopy(args.database_filename) + DatabaseStats(database_copy, args.domain) + finally: + if os.path.exists(database_copy): + os.remove(database_copy) if __name__ == '__main__':
diff --git a/ui/events/keycodes/keyboard_code_conversion_android.cc b/ui/events/keycodes/keyboard_code_conversion_android.cc index f20e0737..5baef199 100644 --- a/ui/events/keycodes/keyboard_code_conversion_android.cc +++ b/ui/events/keycodes/keyboard_code_conversion_android.cc
@@ -334,13 +334,13 @@ case AKEYCODE_TV_INPUT_HDMI_4: return DomKey::TV_INPUT_HDMI4; case AKEYCODE_TV_INPUT_COMPOSITE_1: - return DomKey::TV_INPUT_COMPONENT1; - case AKEYCODE_TV_INPUT_COMPOSITE_2: - return DomKey::TV_INPUT_COMPONENT2; - case AKEYCODE_TV_INPUT_COMPONENT_1: return DomKey::TV_INPUT_COMPOSITE1; - case AKEYCODE_TV_INPUT_COMPONENT_2: + case AKEYCODE_TV_INPUT_COMPOSITE_2: return DomKey::TV_INPUT_COMPOSITE2; + case AKEYCODE_TV_INPUT_COMPONENT_1: + return DomKey::TV_INPUT_COMPONENT1; + case AKEYCODE_TV_INPUT_COMPONENT_2: + return DomKey::TV_INPUT_COMPONENT2; case AKEYCODE_TV_INPUT_VGA_1: return DomKey::TV_INPUT_VGA1; case AKEYCODE_TV_AUDIO_DESCRIPTION:
diff --git a/ui/gfx/vector_icons/BUILD.gn b/ui/gfx/vector_icons/BUILD.gn index d2ce06e..9751ed4 100644 --- a/ui/gfx/vector_icons/BUILD.gn +++ b/ui/gfx/vector_icons/BUILD.gn
@@ -122,20 +122,6 @@ "warning.icon", "warning_badge.icon", "web.icon", - "window_control_back.1x.icon", - "window_control_back.icon", - "window_control_close.1x.icon", - "window_control_close.icon", - "window_control_left_snapped.1x.icon", - "window_control_left_snapped.icon", - "window_control_maximize.1x.icon", - "window_control_maximize.icon", - "window_control_minimize.1x.icon", - "window_control_minimize.icon", - "window_control_restore.1x.icon", - "window_control_restore.icon", - "window_control_right_snapped.1x.icon", - "window_control_right_snapped.icon", "zoom_minus.icon", "zoom_plus.icon", "${branding_path_component}/product.icon",
diff --git a/ui/gfx/win/direct_write.cc b/ui/gfx/win/direct_write.cc index bf30f64c..72bb0e62 100644 --- a/ui/gfx/win/direct_write.cc +++ b/ui/gfx/win/direct_write.cc
@@ -10,6 +10,7 @@ #include "base/win/scoped_comptr.h" #include "base/win/windows_version.h" #include "skia/ext/fontmgr_default_win.h" +#include "third_party/skia/include/ports/SkFontMgr.h" #include "third_party/skia/include/ports/SkTypeface_win.h" #include "ui/gfx/platform_font_win.h" #include "ui/gfx/switches.h" @@ -52,10 +53,11 @@ // factory. The GetSystemFontCollection method in the IDWriteFactory // interface fails with E_INVALIDARG on certain Windows 7 gold versions // (6.1.7600.*). We should just use GDI in these cases. - SkFontMgr* direct_write_font_mgr = SkFontMgr_New_DirectWrite(factory.get()); + sk_sp<SkFontMgr> direct_write_font_mgr = + SkFontMgr_New_DirectWrite(factory.get()); if (!direct_write_font_mgr) return; - SetDefaultSkiaFactory(direct_write_font_mgr); + SetDefaultSkiaFactory(std::move(direct_write_font_mgr)); gfx::PlatformFontWin::SetDirectWriteFactory(factory.get()); }
diff --git a/ui/message_center/views/message_center_button_bar.cc b/ui/message_center/views/message_center_button_bar.cc index fb86d93..5f89a6a 100644 --- a/ui/message_center/views/message_center_button_bar.cc +++ b/ui/message_center/views/message_center_button_bar.cc
@@ -68,9 +68,9 @@ int text_id) : views::ToggleImageButton(listener), size_(kButtonSize, kButtonSize) { ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance(); - SetImage(STATE_NORMAL, resource_bundle.GetImageSkiaNamed(normal_id)); - SetImage(STATE_HOVERED, resource_bundle.GetImageSkiaNamed(hover_id)); - SetImage(STATE_PRESSED, resource_bundle.GetImageSkiaNamed(pressed_id)); + SetImage(STATE_NORMAL, *resource_bundle.GetImageSkiaNamed(normal_id)); + SetImage(STATE_HOVERED, *resource_bundle.GetImageSkiaNamed(hover_id)); + SetImage(STATE_PRESSED, *resource_bundle.GetImageSkiaNamed(pressed_id)); SetImageAlignment(views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE); if (text_id) @@ -159,7 +159,7 @@ IDS_MESSAGE_CENTER_CLEAR_ALL); close_all_button_->SetImage( views::Button::STATE_DISABLED, - resource_bundle.GetImageSkiaNamed(IDR_NOTIFICATION_CLEAR_ALL_DISABLED)); + *resource_bundle.GetImageSkiaNamed(IDR_NOTIFICATION_CLEAR_ALL_DISABLED)); button_container_->AddChildView(close_all_button_); settings_button_ =
diff --git a/ui/views/controls/button/image_button.cc b/ui/views/controls/button/image_button.cc index e875612c..fd2151e2a 100644 --- a/ui/views/controls/button/image_button.cc +++ b/ui/views/controls/button/image_button.cc
@@ -48,10 +48,14 @@ } void ImageButton::SetImage(ButtonState for_state, const gfx::ImageSkia* image) { + SetImage(for_state, image ? *image : gfx::ImageSkia()); +} + +void ImageButton::SetImage(ButtonState for_state, const gfx::ImageSkia& image) { if (for_state == STATE_HOVERED) - set_animate_on_state_change(image != nullptr); + set_animate_on_state_change(!image.isNull()); const gfx::Size old_preferred_size = GetPreferredSize(); - images_[for_state] = image ? *image : gfx::ImageSkia(); + images_[for_state] = image; if (old_preferred_size != GetPreferredSize()) PreferredSizeChanged(); @@ -250,11 +254,11 @@ } void ToggleImageButton::SetImage(ButtonState image_state, - const gfx::ImageSkia* image) { + const gfx::ImageSkia& image) { if (toggled_) { - alternate_images_[image_state] = image ? *image : gfx::ImageSkia(); + alternate_images_[image_state] = image; } else { - images_[image_state] = image ? *image : gfx::ImageSkia(); + images_[image_state] = image; if (state() == image_state) SchedulePaint(); }
diff --git a/ui/views/controls/button/image_button.h b/ui/views/controls/button/image_button.h index 94f70ba8..eba2a835 100644 --- a/ui/views/controls/button/image_button.h +++ b/ui/views/controls/button/image_button.h
@@ -44,7 +44,12 @@ virtual const gfx::ImageSkia& GetImage(ButtonState state) const; // Set the image the button should use for the provided state. - virtual void SetImage(ButtonState state, const gfx::ImageSkia* image); + void SetImage(ButtonState state, const gfx::ImageSkia* image); + + // As above, but takes a const ref. TODO(estade): all callers should be + // updated to use this version, and then the implementations can be + // consolidated. + virtual void SetImage(ButtonState state, const gfx::ImageSkia& image); // Set the background details. void SetBackground(SkColor color, @@ -142,7 +147,7 @@ // Overridden from ImageButton: const gfx::ImageSkia& GetImage(ButtonState state) const override; - void SetImage(ButtonState state, const gfx::ImageSkia* image) override; + void SetImage(ButtonState state, const gfx::ImageSkia& image) override; // Overridden from View: bool GetTooltipText(const gfx::Point& p,