diff --git a/DEPS b/DEPS index 2344ffd..a09ff2c 100644 --- a/DEPS +++ b/DEPS
@@ -79,11 +79,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': '50ea238a8898475b51c573a9cbea148ae8b94f70', + 'skia_revision': '4125b6165d4314c6c64ce12d31b2565d52c6fad3', # 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': '610f27b9dc2777501807617177404b2b481a1633', + 'v8_revision': '5c0ec61e5061683382c0d5953b1af43b4419f88b', # 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. @@ -91,7 +91,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'b391ec40837c3e2773b43a4a0687b3c6d5e8ca36', + 'angle_revision': 'd429ac569e9772c25b16c09d6b90228064adf63b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -103,7 +103,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': 'b3a5240832fce3f0b706c16070a1e69c2c1edb86', + 'pdfium_revision': '2e6405c333d8daae4e3edaa6b48f5ac5a8d7675b', # 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. @@ -155,7 +155,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'feed_revision': '0ff595791bd7e6316f8bae206090dd2583f2cf27', + 'feed_revision': '089c8e9316ed3a2afd631ba2b773f13e69121dc7', } # Only these hosts are allowed for dependencies in this DEPS file. @@ -664,7 +664,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '3c1cb0203b6cfc10389e85a350b2ea6ca29d01ce', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '2e0da5aa389fca1a238edb0e2ed79d9a17a7eff9', # commit position 21742 + Var('webrtc_git') + '/src.git' + '@' + '3dc0125cf7e8df6e60222fc5b69f08c52486a959', # commit position 21742 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 117881c0..e6c28f9 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -557,8 +557,8 @@ # Bypass the AUTHORS check for these accounts. _KNOWN_ROBOTS = set( '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s - for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools', 'nacl', - 'pdfium', 'skia', 'src-internal', 'webrtc')) + for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools', + 'fuchsia-sdk', 'nacl', 'pdfium', 'skia', 'src-internal', 'webrtc')) def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc index 4ca3e476..3382cee5 100644 --- a/android_webview/browser/aw_browser_main_parts.cc +++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -132,9 +132,6 @@ browser_client_->GetNetLog()); content::RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView(); - - // TODO(meacer): Remove when PlzNavigate ships. - content::RenderFrameHost::AllowDataUrlNavigationForAndroidWebView(); } bool AwBrowserMainParts::MainMessageLoopRun(int* result_code) {
diff --git a/android_webview/browser/net/aw_request_interceptor.cc b/android_webview/browser/net/aw_request_interceptor.cc index ebe8b2c2..bfccbbe 100644 --- a/android_webview/browser/net/aw_request_interceptor.cc +++ b/android_webview/browser/net/aw_request_interceptor.cc
@@ -154,9 +154,9 @@ if (request->GetUserData(kRequestAlreadyHasJobDataKey)) return nullptr; - // With PlzNavigate, we now seem to receive blob URLs in interceptor. - // Ignore these URLs. - // TODO(sgurun) is this the best place to do that? Talk with jam@. + // It's not useful to emit shouldInterceptRequest for blob URLs, so we + // intentionally skip the callback for all such URLs. See + // http://crbug.com/822983. if (request->url().SchemeIs(url::kBlobScheme)) { return nullptr; }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwAutofillManager.java b/android_webview/java/src/org/chromium/android_webview/AwAutofillManager.java index e910b75..82dc863 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwAutofillManager.java +++ b/android_webview/java/src/org/chromium/android_webview/AwAutofillManager.java
@@ -12,7 +12,6 @@ import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; -import org.chromium.base.BuildInfo; import org.chromium.base.Log; import java.lang.ref.WeakReference; @@ -48,10 +47,10 @@ public AwAutofillManager(Context context) { if (DEBUG) Log.i(TAG, "constructor"); - mDisabled = !BuildInfo.isAtLeastP() && AwContents.activityFromContext(context) == null; + mAutofillManager = context.getSystemService(AutofillManager.class); + mDisabled = mAutofillManager == null || !mAutofillManager.isEnabled(); if (mDisabled) return; - mAutofillManager = context.getSystemService(AutofillManager.class); mMonitor = new AutofillInputUIMonitor(this); mAutofillManager.registerCallback(mMonitor); }
diff --git a/ash/DEPS b/ash/DEPS index 12ec130..00816fed 100644 --- a/ash/DEPS +++ b/ash/DEPS
@@ -75,6 +75,9 @@ "+chromeos/settings/timezone_settings.h", "+chromeos/system", + # InputMethodManager lives in the browser process. Use ImeController. + "-ui/base/ime/chromeos/input_method_manager.h" + # Ozone does not run in process in mus/mash. "-ui/events/ozone", "-ui/ozone",
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index 5cade50..b49e3b70 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -44,8 +44,6 @@ #include "ui/aura/window.h" #include "ui/base/ime/chromeos/fake_ime_keyboard.h" #include "ui/base/ime/chromeos/ime_keyboard.h" -#include "ui/base/ime/chromeos/input_method_manager.h" -#include "ui/base/ime/chromeos/mock_input_method_manager.h" #include "ui/display/manager/display_manager.h" #include "ui/display/screen.h" #include "ui/events/event.h" @@ -54,8 +52,6 @@ #include "ui/message_center/message_center.h" #include "ui/views/widget/widget.h" -using chromeos::input_method::InputMethodManager; - namespace ash { namespace { @@ -138,23 +134,6 @@ DISALLOW_COPY_AND_ASSIGN(DummyBrightnessControlDelegate); }; -class TestInputMethodManager - : public chromeos::input_method::MockInputMethodManager { - public: - TestInputMethodManager() = default; - ~TestInputMethodManager() override = default; - - // MockInputMethodManager: - chromeos::input_method::ImeKeyboard* GetImeKeyboard() override { - return &keyboard_; - } - - chromeos::input_method::FakeImeKeyboard keyboard_; - - private: - DISALLOW_COPY_AND_ASSIGN(TestInputMethodManager); -}; - class DummyKeyboardBrightnessControlDelegate : public KeyboardBrightnessControlDelegate { public: @@ -211,18 +190,6 @@ AcceleratorControllerTest() = default; ~AcceleratorControllerTest() override = default; - void SetUp() override { - AshTestBase::SetUp(); - test_input_method_manager_ = new TestInputMethodManager; - // Takes ownership. - InputMethodManager::Initialize(test_input_method_manager_); - } - - void TearDown() override { - InputMethodManager::Shutdown(); - AshTestBase::TearDown(); - } - protected: static AcceleratorController* GetController(); @@ -291,9 +258,6 @@ Shell::Get()->keyboard_brightness_control_delegate_ = std::move(delegate); } - // Owned by InputMethodManager. - TestInputMethodManager* test_input_method_manager_ = nullptr; - private: DISALLOW_COPY_AND_ASSIGN(AcceleratorControllerTest); };
diff --git a/ash/shelf/shelf_application_menu_model.cc b/ash/shelf/shelf_application_menu_model.cc index 9c2d2fc8..76aabbbc9 100644 --- a/ash/shelf/shelf_application_menu_model.cc +++ b/ash/shelf/shelf_application_menu_model.cc
@@ -11,6 +11,7 @@ #include "ash/public/cpp/shelf_item_delegate.h" #include "base/metrics/histogram_macros.h" +#include "ui/base/ui_base_features.h" #include "ui/display/types/display_constants.h" #include "ui/gfx/image/image.h" @@ -27,9 +28,11 @@ std::vector<mojom::MenuItemPtr> items, ShelfItemDelegate* delegate) : ui::SimpleMenuModel(this), items_(std::move(items)), delegate_(delegate) { - AddSeparator(ui::SPACING_SEPARATOR); + if (!features::IsTouchableAppContextMenuEnabled()) + AddSeparator(ui::SPACING_SEPARATOR); AddItem(kInvalidCommandId, title); - AddSeparator(ui::SPACING_SEPARATOR); + if (!features::IsTouchableAppContextMenuEnabled()) + AddSeparator(ui::SPACING_SEPARATOR); for (size_t i = 0; i < items_.size(); i++) { mojom::MenuItem* item = items_[i].get();
diff --git a/ash/shelf/shelf_constants.h b/ash/shelf/shelf_constants.h index bf70054..8eaa292 100644 --- a/ash/shelf/shelf_constants.h +++ b/ash/shelf/shelf_constants.h
@@ -58,6 +58,9 @@ // notifications, etc). ASH_EXPORT constexpr SkColor kShelfIconColor = SK_ColorWHITE; +// The dip offset for showing a context menu with a long touch press. +ASH_EXPORT constexpr int kScaledIconContextMenuOffset = 5; + // The alpha value for the shelf background when a window is overlapping. ASH_EXPORT constexpr int kShelfTranslucentAlpha = 153;
diff --git a/ash/shelf/shelf_context_menu_model.cc b/ash/shelf/shelf_context_menu_model.cc index f24f777..136f37eb 100644 --- a/ash/shelf/shelf_context_menu_model.cc +++ b/ash/shelf/shelf_context_menu_model.cc
@@ -23,6 +23,7 @@ #include "base/numerics/safe_conversions.h" #include "components/prefs/pref_service.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/ui_base_features.h" #include "ui/gfx/image/image.h" using l10n_util::GetStringUTF16; @@ -128,8 +129,9 @@ menu_items_(std::move(menu_items)), delegate_(delegate), display_id_(display_id) { - // Append some menu items that are handled locally by Ash. - AddLocalMenuItems(&menu_items_, display_id); + // Append shelf settings and wallpaper items if no shelf item was selected. + if (!features::IsTouchableAppContextMenuEnabled() || !delegate) + AddLocalMenuItems(&menu_items_, display_id); menu_utils::PopulateMenuFromMojoMenuItems(this, this, menu_items_, &submenus_); }
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index 56aca09..6212ede 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -63,17 +63,17 @@ // The proportion of the shelf space reserved for non-panel icons. Panels // may flow into this space but will be put into the overflow bubble if there // is contention for the space. -const float kReservedNonPanelIconProportion = 0.67f; +constexpr float kReservedNonPanelIconProportion = 0.67f; // The distance of the cursor from the outer rim of the shelf before it // separates. -const int kRipOffDistance = 48; +constexpr int kRipOffDistance = 48; // The rip off drag and drop proxy image should get scaled by this factor. -const float kDragAndDropProxyScale = 1.2f; +constexpr float kDragAndDropProxyScale = 1.2f; // The opacity represents that this partially disappeared item will get removed. -const float kDraggedImageOpacity = 0.5f; +constexpr float kDraggedImageOpacity = 0.5f; namespace { @@ -1463,6 +1463,99 @@ overflow_view->last_visible_index_ = last_overflow_index; } +gfx::Rect ShelfView::GetMenuAnchorRect(const views::View* source, + const gfx::Point& location, + ui::MenuSourceType source_type, + bool context_menu) const { + if (context_menu) { + if (source_type == ui::MenuSourceType::MENU_SOURCE_TOUCH) + return GetTouchMenuAnchorRect(source, location); + return gfx::Rect(location, gfx::Size()); + } + + // The menu is for an application list. + DCHECK(source) << "Application lists require a source button view."; + // Application lists use a bubble. It is possible to invoke the menu while + // it is sliding into view. To cover that case, the screen coordinates are + // offsetted by the animation delta. + aura::Window* window = GetWidget()->GetNativeWindow(); + gfx::Rect anchor = + source->GetBoundsInScreen() + + (window->GetTargetBounds().origin() - window->bounds().origin()); + if (source->border()) + anchor.Inset(source->border()->GetInsets()); + return anchor; +} + +gfx::Rect ShelfView::GetTouchMenuAnchorRect(const views::View* source, + const gfx::Point& location) const { + const bool for_item = ShelfItemForView(source); + const bool use_touchable_menu_alignment = + features::IsTouchableAppContextMenuEnabled() && for_item; + const gfx::Rect shelf_bounds = + is_overflow_mode() + ? owner_overflow_bubble_->bubble_view()->GetBubbleBounds() + : screen_util::GetDisplayBoundsWithShelf( + shelf_widget_->GetNativeWindow()); + const gfx::Rect& source_bounds_in_screen = source->GetBoundsInScreen(); + gfx::Point origin; + switch (shelf_->alignment()) { + case SHELF_ALIGNMENT_BOTTOM: + case SHELF_ALIGNMENT_BOTTOM_LOCKED: + origin = + gfx::Point(use_touchable_menu_alignment ? source_bounds_in_screen.x() + : location.x(), + shelf_bounds.bottom() - kShelfSize); + break; + case SHELF_ALIGNMENT_LEFT: + if (use_touchable_menu_alignment) + origin = gfx::Point(shelf_bounds.x(), source_bounds_in_screen.y()); + else + origin = gfx::Point(shelf_bounds.x() + kShelfSize, location.y()); + break; + case SHELF_ALIGNMENT_RIGHT: + origin = + gfx::Point(shelf_bounds.right() - kShelfSize, + use_touchable_menu_alignment ? source_bounds_in_screen.y() + : location.y()); + break; + } + if (use_touchable_menu_alignment) { + // When showing a context menu with long press, the icon enlarges by 20% + // from the center point. After the context menu is shown and the long + // press is released the icon will scale back down and the context menu + // is left 5px off. + origin.Offset( + shelf_->IsHorizontalAlignment() ? kScaledIconContextMenuOffset : 0, + shelf_->IsHorizontalAlignment() ? 0 : kScaledIconContextMenuOffset); + } + return gfx::Rect(origin, + for_item ? source_bounds_in_screen.size() : gfx::Size()); +} + +views::MenuAnchorPosition ShelfView::GetMenuAnchorPosition( + bool for_item, + bool context_menu) const { + if (features::IsTouchableAppContextMenuEnabled() && for_item) { + return shelf_->IsHorizontalAlignment() + ? views::MENU_ANCHOR_BUBBLE_TOUCHABLE_ABOVE + : views::MENU_ANCHOR_BUBBLE_TOUCHABLE_LEFT; + } + if (!context_menu) { + switch (shelf_->alignment()) { + case SHELF_ALIGNMENT_BOTTOM: + case SHELF_ALIGNMENT_BOTTOM_LOCKED: + return views::MENU_ANCHOR_BUBBLE_ABOVE; + case SHELF_ALIGNMENT_LEFT: + return views::MENU_ANCHOR_BUBBLE_RIGHT; + case SHELF_ALIGNMENT_RIGHT: + return views::MENU_ANCHOR_BUBBLE_LEFT; + } + } + return shelf_->IsHorizontalAlignment() ? views::MENU_ANCHOR_FIXED_BOTTOMCENTER + : views::MENU_ANCHOR_FIXED_SIDECENTER; +} + gfx::Rect ShelfView::GetBoundsForDragInsertInScreen() { gfx::Size preferred_size; if (is_overflow_mode()) { @@ -1839,35 +1932,9 @@ void ShelfView::ShowContextMenuForView(views::View* source, const gfx::Point& point, ui::MenuSourceType source_type) { - gfx::Point context_menu_point = point; - aura::Window* shelf_window = shelf_widget_->GetNativeWindow(); - - // Align the context menu to the edge of the shelf for touch events. - if (source_type == ui::MenuSourceType::MENU_SOURCE_TOUCH) { - gfx::Rect shelf_bounds = - is_overflow_mode() - ? owner_overflow_bubble_->bubble_view()->GetBubbleBounds() - : screen_util::GetDisplayBoundsWithShelf(shelf_window); - - switch (shelf_->alignment()) { - case SHELF_ALIGNMENT_BOTTOM: - case SHELF_ALIGNMENT_BOTTOM_LOCKED: - context_menu_point.SetPoint(point.x(), - shelf_bounds.bottom() - kShelfSize); - break; - case SHELF_ALIGNMENT_LEFT: - context_menu_point.SetPoint(shelf_bounds.x() + kShelfSize, point.y()); - break; - case SHELF_ALIGNMENT_RIGHT: - context_menu_point.SetPoint(shelf_bounds.right() - kShelfSize, - point.y()); - break; - } - } last_pressed_index_ = -1; - - const int64_t display_id = GetDisplayIdForView(this); const ShelfItem* item = ShelfItemForView(source); + const int64_t display_id = GetDisplayIdForView(this); if (!item || !model_->GetShelfItemDelegate(item->id)) { UMA_HISTOGRAM_ENUMERATION("Apps.ContextMenuShowSource.Shelf", source_type, ui::MENU_SOURCE_TYPE_LAST); @@ -1876,8 +1943,7 @@ std::make_unique<ShelfContextMenuModel>( std::vector<mojom::MenuItemPtr>(), nullptr, display_id); menu_model->set_histogram_name(kNonAppContextMenuExecuteCommand); - ShowMenu(std::move(menu_model), source, context_menu_point, true, - source_type, nullptr); + ShowMenu(std::move(menu_model), source, point, true, source_type, nullptr); return; } @@ -1888,8 +1954,8 @@ // Get any custom entries; show the context menu in AfterGetContextMenuItems. model_->GetShelfItemDelegate(item->id)->GetContextMenuItems( display_id, base::Bind(&ShelfView::AfterGetContextMenuItems, - weak_factory_.GetWeakPtr(), item->id, - context_menu_point, source, source_type)); + weak_factory_.GetWeakPtr(), item->id, point, + source, source_type)); } void ShelfView::ShowMenu(std::unique_ptr<ui::MenuModel> menu_model, @@ -1898,16 +1964,22 @@ bool context_menu, ui::MenuSourceType source_type, views::InkDrop* ink_drop) { - menu_model_ = std::move(menu_model); + if (menu_model->GetItemCount() == 0) + return; + menu_model_ = std::move(menu_model); closing_event_time_ = base::TimeTicks(); int run_types = 0; if (context_menu) run_types |= views::MenuRunner::CONTEXT_MENU | views::MenuRunner::FIXED_ANCHOR; - // Only selected shelf items with context menu opened can be dragged. const ShelfItem* item = ShelfItemForView(source); + // Only use the touchable layout if the menu is for an app. + if (features::IsTouchableAppContextMenuEnabled() && item) + run_types |= views::MenuRunner::USE_TOUCHABLE_LAYOUT; + + // Only selected shelf items with context menu opened can be dragged. if (context_menu && item && ShelfButtonIsInDrag(item->type, source) && source_type == ui::MenuSourceType::MENU_SOURCE_TOUCH) { run_types |= views::MenuRunner::SEND_GESTURE_EVENTS_TO_OWNER; @@ -1917,47 +1989,11 @@ menu_model_.get(), run_types, base::Bind(&ShelfView::OnMenuClosed, base::Unretained(this), ink_drop)); - views::MenuAnchorPosition menu_alignment = views::MENU_ANCHOR_TOPLEFT; - gfx::Rect anchor = gfx::Rect(click_point, gfx::Size()); - - if (!context_menu) { - DCHECK(source) << "Application lists require a source button view."; - // Application lists use a bubble. - // It is possible to invoke the menu while it is sliding into view. To cover - // that case, the screen coordinates are offsetted by the animation delta. - aura::Window* window = GetWidget()->GetNativeWindow(); - anchor = source->GetBoundsInScreen() + - (window->GetTargetBounds().origin() - window->bounds().origin()); - - // Adjust the anchor location for shelf items with asymmetrical borders. - if (source->border()) - anchor.Inset(source->border()->GetInsets()); - - // Determine the menu alignment dependent on the shelf. - switch (shelf_->alignment()) { - case SHELF_ALIGNMENT_BOTTOM: - case SHELF_ALIGNMENT_BOTTOM_LOCKED: - menu_alignment = views::MENU_ANCHOR_BUBBLE_ABOVE; - break; - case SHELF_ALIGNMENT_LEFT: - menu_alignment = views::MENU_ANCHOR_BUBBLE_RIGHT; - break; - case SHELF_ALIGNMENT_RIGHT: - menu_alignment = views::MENU_ANCHOR_BUBBLE_LEFT; - break; - } - } else { - // Distinguish the touch events that triggered on the bottom or left / right - // shelf. Since they should have different |MenuAnchorPosition|. - if (shelf_->IsHorizontalAlignment()) - menu_alignment = views::MENU_ANCHOR_FIXED_BOTTOMCENTER; - else - menu_alignment = views::MENU_ANCHOR_FIXED_SIDECENTER; - } - // NOTE: if you convert to HAS_MNEMONICS be sure to update menu building code. - launcher_menu_runner_->RunMenuAt(GetWidget(), nullptr, anchor, menu_alignment, - source_type); + launcher_menu_runner_->RunMenuAt( + GetWidget(), nullptr, + GetMenuAnchorRect(source, click_point, source_type, context_menu), + GetMenuAnchorPosition(item, context_menu), source_type); } void ShelfView::OnMenuClosed(views::InkDrop* ink_drop) {
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h index da49b56..b529e42 100644 --- a/ash/shelf/shelf_view.h +++ b/ash/shelf/shelf_view.h
@@ -24,6 +24,7 @@ #include "ui/views/animation/ink_drop_state.h" #include "ui/views/context_menu_controller.h" #include "ui/views/controls/button/button.h" +#include "ui/views/controls/menu/menu_types.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/view.h" #include "ui/views/view_model.h" @@ -294,6 +295,28 @@ // Updates the visible range of overflow items in |overflow_view|. void UpdateOverflowRange(ShelfView* overflow_view) const; + // Gets the menu anchor rect for menus. |source| is the view that is + // asking for a menu, |location| is the location of the event, + // |source_type| is the type of event that asked for the menu, and + // |context_menu| is whether the menu is for a context or app menu. + gfx::Rect GetMenuAnchorRect(const views::View* source, + const gfx::Point& location, + ui::MenuSourceType source_type, + bool context_menu) const; + + // Gets the menu anchor rect that aligns the menu to the edge of the + // shelf for touch events. |source| is the view that is asking for the + // menu, |location| is the location of the event. + gfx::Rect GetTouchMenuAnchorRect(const views::View* source, + const gfx::Point& location) const; + + // Gets the menu anchor position for a menu. |for_item| is true if the menu is + // for an item on the shelf, or false if the menu is for the shelf view + // itself, |context_menu| is whether the menu will be an application menu or + // context menu, and |touch_menu| is whether the menu was initiated by touch. + views::MenuAnchorPosition GetMenuAnchorPosition(bool for_item, + bool context_menu) const; + // Overridden from views::View: gfx::Size CalculatePreferredSize() const override; void OnBoundsChanged(const gfx::Rect& previous_bounds) override; @@ -334,16 +357,6 @@ ShelfAction action, base::Optional<std::vector<mojom::MenuItemPtr>> menu_items); - // Show a list of all running items for this shelf |item|; it only shows a - // menu if there are multiple running items. |source| specifies the view - // responsible for showing the menu, and the bubble will point towards it. - // The |event_flags| are the flags of the event which triggered this menu. - // Returns |true| if a menu is shown. - bool ShowListMenuForView(const ShelfItem& item, - views::View* source, - const ui::Event& event, - views::InkDrop* ink_drop); - // Overridden from views::ContextMenuController: void ShowContextMenuForView(views::View* source, const gfx::Point& point,
diff --git a/ash/shelf/shelf_view_test_api.cc b/ash/shelf/shelf_view_test_api.cc index 9c0c037..5f0fda44 100644 --- a/ash/shelf/shelf_view_test_api.cc +++ b/ash/shelf/shelf_view_test_api.cc
@@ -117,6 +117,14 @@ shelf_view_->bounds_animator_->RemoveObserver(observer.get()); } +gfx::Rect ShelfViewTestAPI::GetMenuAnchorRect(const views::View* source, + const gfx::Point& location, + ui::MenuSourceType source_type, + bool context_menu) const { + return shelf_view_->GetMenuAnchorRect(source, location, source_type, + context_menu); +} + bool ShelfViewTestAPI::CloseMenu() { if (!shelf_view_->launcher_menu_runner_) return false;
diff --git a/ash/shelf/shelf_view_test_api.h b/ash/shelf/shelf_view_test_api.h index 97aab42..cc1a63d 100644 --- a/ash/shelf/shelf_view_test_api.h +++ b/ash/shelf/shelf_view_test_api.h
@@ -7,8 +7,10 @@ #include "ash/public/cpp/shelf_item.h" #include "base/macros.h" +#include "ui/base/ui_base_types.h" namespace gfx { +class Point; class Rect; } @@ -71,6 +73,13 @@ // Runs message loop and waits until all add/remove animations are done. void RunMessageLoopUntilAnimationsDone(); + // Gets the anchor point that would be used for a context menu with these + // parameters. + gfx::Rect GetMenuAnchorRect(const views::View* source, + const gfx::Point& location, + ui::MenuSourceType source_type, + bool context_menu) const; + // Close any open app list or context menu; returns true if a menu was closed. bool CloseMenu();
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index 868db6e..9bb1803 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -16,6 +16,7 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/window_properties.h" #include "ash/root_window_controller.h" +#include "ash/screen_util.h" #include "ash/session/session_controller.h" #include "ash/shelf/app_list_button.h" #include "ash/shelf/back_button.h" @@ -2006,7 +2007,8 @@ EXPECT_TRUE(test_api_->CloseMenu()); } -// Tests that the app list button shows a context menu on right click. +// Tests that the app list button shows a context menu on right click when +// touchable app context menus are not enabled. TEST_F(ShelfViewTest, AppListButtonShowsContextMenu) { ui::test::EventGenerator& generator = GetEventGenerator(); AppListButton* app_list_button = shelf_view_->GetAppListButton(); @@ -2078,6 +2080,94 @@ DISALLOW_COPY_AND_ASSIGN(ShelfViewTouchableContextMenuTest); }; +// Tests that anchor points are aligned with the shelf button bounds for touch. +TEST_F(ShelfViewTouchableContextMenuTest, + ShelfViewContextMenuAnchorPointTouch) { + const ShelfButton* shelf_button = GetButtonByID(AddApp()); + EXPECT_EQ(ash::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM, + GetPrimaryShelf()->alignment()); + + // Test for bottom shelf. + EXPECT_EQ(shelf_button->GetBoundsInScreen().y(), + test_api_ + ->GetMenuAnchorRect(shelf_button, gfx::Point(), + ui::MenuSourceType::MENU_SOURCE_TOUCH, + true /*context_menu*/) + .y()); + + // Test for left shelf. + GetPrimaryShelf()->SetAlignment(ash::ShelfAlignment::SHELF_ALIGNMENT_LEFT); + + EXPECT_EQ(shelf_button->GetBoundsInScreen().x(), + test_api_ + ->GetMenuAnchorRect(shelf_button, gfx::Point(), + ui::MenuSourceType::MENU_SOURCE_TOUCH, + true /*context_menu*/) + .x()); + + // Test for right shelf. + GetPrimaryShelf()->SetAlignment(ash::ShelfAlignment::SHELF_ALIGNMENT_RIGHT); + + EXPECT_EQ(shelf_button->GetBoundsInScreen().x(), + test_api_ + ->GetMenuAnchorRect(shelf_button, gfx::Point(), + ui::MenuSourceType::MENU_SOURCE_TOUCH, + true /*context_menu*/) + .x()); +} + +// Tests that anchor points are the click point for mouse context menus. +TEST_F(ShelfViewTouchableContextMenuTest, ShelfViewContextMenuAnchorPoint) { + const ShelfButton* shelf_button = GetButtonByID(AddApp()); + EXPECT_EQ(ash::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM, + GetPrimaryShelf()->alignment()); + + // Test for bottom shelf. + const gfx::Point click_point_bottom = + shelf_button->GetBoundsInScreen().CenterPoint(); + + EXPECT_EQ(click_point_bottom, + test_api_ + ->GetMenuAnchorRect(shelf_button, click_point_bottom, + ui::MenuSourceType::MENU_SOURCE_MOUSE, + true /*context_menu*/) + .origin()); + + // Test for left shelf. + GetPrimaryShelf()->SetAlignment(ash::ShelfAlignment::SHELF_ALIGNMENT_LEFT); + const gfx::Point click_point_left = + shelf_button->GetBoundsInScreen().CenterPoint(); + + EXPECT_EQ(click_point_left, + test_api_ + ->GetMenuAnchorRect(shelf_button, click_point_left, + ui::MenuSourceType::MENU_SOURCE_MOUSE, + true /*context_menu*/) + .origin()); + + // Test for right shelf. + GetPrimaryShelf()->SetAlignment(ash::ShelfAlignment::SHELF_ALIGNMENT_RIGHT); + const gfx::Point click_point_right = + shelf_button->GetBoundsInScreen().CenterPoint(); + + EXPECT_EQ(click_point_right, + test_api_ + ->GetMenuAnchorRect(shelf_button, click_point_right, + ui::MenuSourceType::MENU_SOURCE_MOUSE, + true /*context_menu*/) + .origin()); +} + +// Tests that the app list button does not show a context menu on right click +// when touchable app context menus are enabled. +TEST_F(ShelfViewTouchableContextMenuTest, AppListButtonDoesNotShowContextMenu) { + ui::test::EventGenerator& generator = GetEventGenerator(); + const AppListButton* app_list_button = shelf_view_->GetAppListButton(); + generator.MoveMouseTo(app_list_button->GetBoundsInScreen().CenterPoint()); + generator.PressRightButton(); + EXPECT_FALSE(test_api_->CloseMenu()); +} + // Tests that an item has a notification indicator when it recieves a // notification. TEST_F(ShelfViewTouchableContextMenuTest, AddedItemHasNotificationIndicator) {
diff --git a/ash/shelf/shelf_window_watcher_item_delegate.cc b/ash/shelf/shelf_window_watcher_item_delegate.cc index 27f5c7b1..4fa0b6e 100644 --- a/ash/shelf/shelf_window_watcher_item_delegate.cc +++ b/ash/shelf/shelf_window_watcher_item_delegate.cc
@@ -17,6 +17,7 @@ #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/ui_base_features.h" #include "ui/events/event_constants.h" #include "ui/wm/core/window_animations.h" @@ -84,9 +85,11 @@ close->label = l10n_util::GetStringUTF16(IDS_CLOSE); close->enabled = true; items.push_back(std::move(close)); - ash::mojom::MenuItemPtr separator(ash::mojom::MenuItem::New()); - separator->type = ui::MenuModel::TYPE_SEPARATOR; - items.push_back(std::move(separator)); + if (!features::IsTouchableAppContextMenuEnabled()) { + ash::mojom::MenuItemPtr separator(ash::mojom::MenuItem::New()); + separator->type = ui::MenuModel::TYPE_SEPARATOR; + items.push_back(std::move(separator)); + } std::move(callback).Run(std::move(items)); }
diff --git a/ash/system/ime_menu/ime_menu_tray_unittest.cc b/ash/system/ime_menu/ime_menu_tray_unittest.cc index f0f9a28..b3b4563 100644 --- a/ash/system/ime_menu/ime_menu_tray_unittest.cc +++ b/ash/system/ime_menu/ime_menu_tray_unittest.cc
@@ -17,16 +17,12 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "ui/accessibility/ax_node_data.h" -#include "ui/base/ime/chromeos/input_method_manager.h" -#include "ui/base/ime/chromeos/mock_input_method_manager.h" #include "ui/base/ime/ime_bridge.h" #include "ui/base/ime/text_input_flags.h" #include "ui/events/event.h" #include "ui/views/controls/label.h" using base::UTF8ToUTF16; -using chromeos::input_method::InputMethodManager; -using chromeos::input_method::MockInputMethodManager; namespace ash { namespace { @@ -54,18 +50,6 @@ ImeMenuTrayTest() = default; ~ImeMenuTrayTest() override = default; - void SetUp() override { - AshTestBase::SetUp(); - // MockInputMethodManager enables emoji, handwriting and voice input by - // default. - InputMethodManager::Initialize(new MockInputMethodManager); - } - - void TearDown() override { - InputMethodManager::Shutdown(); - AshTestBase::TearDown(); - } - protected: // Returns true if the IME menu tray is visible. bool IsVisible() { return GetTray()->visible(); }
diff --git a/base/BUILD.gn b/base/BUILD.gn index 2af1fcd..6450041 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -2976,9 +2976,29 @@ fuzzer_test("base_json_correctness_fuzzer") { sources = [ - "json/correctness_fuzzer.cc", + "json/json_correctness_fuzzer.cc", ] deps = [ ":base", ] + dict = "//testing/libfuzzer/fuzzers/dicts/json.dict" +} + +fuzzer_test("base_json_reader_fuzzer") { + sources = [ + "json/json_reader_fuzzer.cc", + ] + deps = [ + "//base", + ] + dict = "//testing/libfuzzer/fuzzers/dicts/json.dict" +} + +fuzzer_test("base_json_string_escape_fuzzer") { + sources = [ + "json/string_escape_fuzzer.cc", + ] + deps = [ + "//base", + ] }
diff --git a/base/allocator/partition_allocator/page_allocator_unittest.cc b/base/allocator/partition_allocator/page_allocator_unittest.cc index 02e4f61..9323d666 100644 --- a/base/allocator/partition_allocator/page_allocator_unittest.cc +++ b/base/allocator/partition_allocator/page_allocator_unittest.cc
@@ -11,12 +11,12 @@ #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" -#if defined(OS_POSIX) +#if defined(OS_POSIX) && !defined(OS_FUCHSIA) #include <setjmp.h> #include <signal.h> #include <sys/mman.h> #include <sys/time.h> -#endif // defined(OS_POSIX) +#endif // defined(OS_POSIX) && !defined(OS_FUCHSIA) #if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) @@ -103,7 +103,7 @@ } // Test permission setting on POSIX, where we can set a trap handler. -#if defined(OS_POSIX) +#if defined(OS_POSIX) && !defined(OS_FUCHSIA) namespace { sigjmp_buf g_continuation; @@ -186,7 +186,7 @@ FreePages(buffer, kPageAllocationGranularity); } -#endif // defined(OS_POSIX) +#endif // defined(OS_POSIX) && !defined(OS_FUCHSIA) } // namespace base
diff --git a/base/android/java/src/org/chromium/base/TraceEvent.java b/base/android/java/src/org/chromium/base/TraceEvent.java index 8795c8c..0710a199 100644 --- a/base/android/java/src/org/chromium/base/TraceEvent.java +++ b/base/android/java/src/org/chromium/base/TraceEvent.java
@@ -205,9 +205,9 @@ /** * Constructor used to support the "try with resource" construct. */ - private TraceEvent(String name) { + private TraceEvent(String name, String arg) { mName = name; - begin(name); + begin(name, arg); } @Override @@ -221,11 +221,19 @@ * Note that if tracing is not enabled, this will not result in allocating an object. * * @param name Trace event name. + * @param name The arguments of the event. * @return a TraceEvent, or null if tracing is not enabled. */ - public static TraceEvent scoped(String name) { + public static TraceEvent scoped(String name, String arg) { if (!(EarlyTraceEvent.enabled() || enabled())) return null; - return new TraceEvent(name); + return new TraceEvent(name, arg); + } + + /** + * Similar to {@link #scoped(String, String arg)}, but uses null for |arg|. + */ + public static TraceEvent scoped(String name) { + return scoped(name, null); } /**
diff --git a/base/json/correctness_fuzzer.cc b/base/json/json_correctness_fuzzer.cc similarity index 100% rename from base/json/correctness_fuzzer.cc rename to base/json/json_correctness_fuzzer.cc
diff --git a/testing/libfuzzer/fuzzers/base_json_reader_fuzzer.cc b/base/json/json_reader_fuzzer.cc similarity index 92% rename from testing/libfuzzer/fuzzers/base_json_reader_fuzzer.cc rename to base/json/json_reader_fuzzer.cc index afae71f..a8490da 100644 --- a/testing/libfuzzer/fuzzers/base_json_reader_fuzzer.cc +++ b/base/json/json_reader_fuzzer.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <stddef.h> -#include <stdint.h> - -#include <string> - #include "base/json/json_reader.h" #include "base/values.h" @@ -15,7 +10,7 @@ // Entry point for LibFuzzer. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - if (size < 1) + if (size < 2) return 0; // Create a copy of input buffer, as otherwise we don't catch
diff --git a/base/json/string_escape_fuzzer.cc b/base/json/string_escape_fuzzer.cc new file mode 100644 index 0000000..bdd754b --- /dev/null +++ b/base/json/string_escape_fuzzer.cc
@@ -0,0 +1,35 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/json/string_escape.h" + +std::string escaped_string; + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (size < 2) + return 0; + + const bool put_in_quotes = data[size - 1]; + + // Create a copy of input buffer, as otherwise we don't catch + // overflow that touches the last byte (which is used in put_in_quotes). + size_t actual_size_char8 = size - 1; + std::unique_ptr<char[]> input(new char[actual_size_char8]); + memcpy(input.get(), data, actual_size_char8); + + base::StringPiece input_string(input.get(), actual_size_char8); + base::EscapeJSONString(input_string, put_in_quotes, &escaped_string); + + // Test for wide-strings if available size is even. + if (actual_size_char8 & 1) + return 0; + + size_t actual_size_char16 = actual_size_char8 / 2; + base::StringPiece16 input_string16( + reinterpret_cast<base::char16*>(input.get()), actual_size_char16); + base::EscapeJSONString(input_string16, put_in_quotes, &escaped_string); + + return 0; +}
diff --git a/base/process/process_metrics.h b/base/process/process_metrics.h index 71ff0484..45e9f07 100644 --- a/base/process/process_metrics.h +++ b/base/process/process_metrics.h
@@ -135,11 +135,6 @@ // convenience wrapper for CreateProcessMetrics(). static std::unique_ptr<ProcessMetrics> CreateCurrentProcessMetrics(); - // Returns private and sharedusage, in bytes. Private bytes is the amount of - // memory currently allocated to a process that cannot be shared. Returns - // false on platform specific error conditions. Note: |private_bytes| - // returns 0 on unsupported OSes: prior to XP SP2. - bool GetMemoryBytes(size_t* private_bytes, size_t* shared_bytes) const; // Fills a CommittedKBytes with both resident and paged // memory usage as per definition of CommittedBytes. void GetCommittedKBytes(CommittedKBytes* usage) const; @@ -175,14 +170,6 @@ uint64_t compressed = 0; }; TaskVMInfo GetTaskVMInfo() const; - - // Returns private, shared, and total resident bytes. |locked_bytes| refers to - // bytes that must stay resident. |locked_bytes| only counts bytes locked by - // this task, not bytes locked by the kernel. - bool GetMemoryBytes(size_t* private_bytes, - size_t* shared_bytes, - size_t* resident_bytes, - size_t* locked_bytes) const; #endif // Returns the percentage of time spent executing, across all threads of the
diff --git a/base/process/process_metrics_freebsd.cc b/base/process/process_metrics_freebsd.cc index 1f9e4b6..45385e16 100644 --- a/base/process/process_metrics_freebsd.cc +++ b/base/process/process_metrics_freebsd.cc
@@ -39,21 +39,6 @@ } } // namespace -bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, - size_t* shared_bytes) const { - WorkingSetKBytes ws_usage; - if (!GetWorkingSetKBytes(&ws_usage)) - return false; - - if (private_bytes) - *private_bytes = ws_usage.priv << 10; - - if (shared_bytes) - *shared_bytes = ws_usage.shared * 1024; - - return true; -} - bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { // TODO(bapt) be sure we can't be precise size_t priv = GetWorkingSetSize();
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc index 27c1496..aec4f625f 100644 --- a/base/process/process_metrics_linux.cc +++ b/base/process/process_metrics_linux.cc
@@ -216,21 +216,6 @@ getpagesize(); } -bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, - size_t* shared_bytes) const { - WorkingSetKBytes ws_usage; - if (!GetWorkingSetKBytes(&ws_usage)) - return false; - - if (private_bytes) - *private_bytes = ws_usage.priv * 1024; - - if (shared_bytes) - *shared_bytes = ws_usage.shared * 1024; - - return true; -} - bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { #if defined(OS_CHROMEOS) if (GetWorkingSetKBytesTotmaps(ws_usage))
diff --git a/base/process/process_metrics_mac.cc b/base/process/process_metrics_mac.cc index 0a8112bd..91e249d 100644 --- a/base/process/process_metrics_mac.cc +++ b/base/process/process_metrics_mac.cc
@@ -68,33 +68,6 @@ return kr == KERN_SUCCESS; } -bool GetCPUType(cpu_type_t* cpu_type) { - size_t len = sizeof(*cpu_type); - int result = sysctlbyname("sysctl.proc_cputype", - cpu_type, - &len, - NULL, - 0); - if (result != 0) { - DPLOG(ERROR) << "sysctlbyname(""sysctl.proc_cputype"")"; - return false; - } - - return true; -} - -bool IsAddressInSharedRegion(mach_vm_address_t addr, cpu_type_t type) { - if (type == CPU_TYPE_I386) { - return addr >= SHARED_REGION_BASE_I386 && - addr < (SHARED_REGION_BASE_I386 + SHARED_REGION_SIZE_I386); - } else if (type == CPU_TYPE_X86_64) { - return addr >= SHARED_REGION_BASE_X86_64 && - addr < (SHARED_REGION_BASE_X86_64 + SHARED_REGION_SIZE_X86_64); - } else { - return false; - } -} - MachVMRegionResult ParseOutputFromMachVMRegion(kern_return_t kr) { if (kr == KERN_INVALID_ADDRESS) { // We're at the end of the address space. @@ -132,121 +105,6 @@ return WrapUnique(new ProcessMetrics(process, port_provider)); } -bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, - size_t* shared_bytes) const { - return GetMemoryBytes(private_bytes, shared_bytes, nullptr, nullptr); -} - -// This is a rough approximation of the algorithm that libtop uses. -// private_bytes is the size of private resident memory. -// shared_bytes is the size of shared resident memory. -bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, - size_t* shared_bytes, - size_t* resident_bytes, - size_t* locked_bytes) const { - size_t private_pages_count = 0; - size_t shared_pages_count = 0; - size_t wired_pages_count = 0; - - mach_port_t task = TaskForPid(process_); - if (task == MACH_PORT_NULL) { - DLOG(ERROR) << "Invalid process"; - return false; - } - - cpu_type_t cpu_type; - if (!GetCPUType(&cpu_type)) - return false; - - // The same region can be referenced multiple times. To avoid double counting - // we need to keep track of which regions we've already counted. - hash_set<int> seen_objects; - - // We iterate through each VM region in the task's address map. For shared - // memory we add up all the pages that are marked as shared. Like libtop we - // try to avoid counting pages that are also referenced by other tasks. Since - // we don't have access to the VM regions of other tasks the only hint we have - // is if the address is in the shared region area. - // - // Private memory is much simpler. We simply count the pages that are marked - // as private or copy on write (COW). - // - // See libtop_update_vm_regions in - // http://www.opensource.apple.com/source/top/top-67/libtop.c - mach_vm_size_t size = 0; - mach_vm_address_t address = MACH_VM_MIN_ADDRESS; - while (true) { - base::CheckedNumeric<mach_vm_address_t> next_address(address); - next_address += size; - if (!next_address.IsValid()) - return false; - address = next_address.ValueOrDie(); - - mach_vm_address_t address_copy = address; - vm_region_top_info_data_t info; - MachVMRegionResult result = GetTopInfo(task, &size, &address, &info); - if (result == MachVMRegionResult::Error) - return false; - if (result == MachVMRegionResult::Finished) - break; - - vm_region_basic_info_64 basic_info; - mach_vm_size_t dummy_size = 0; - result = GetBasicInfo(task, &dummy_size, &address_copy, &basic_info); - if (result == MachVMRegionResult::Error) - return false; - if (result == MachVMRegionResult::Finished) - break; - - bool is_wired = basic_info.user_wired_count > 0; - - if (IsAddressInSharedRegion(address, cpu_type) && - info.share_mode != SM_PRIVATE) - continue; - - if (info.share_mode == SM_COW && info.ref_count == 1) - info.share_mode = SM_PRIVATE; - - switch (info.share_mode) { - case SM_LARGE_PAGE: - case SM_PRIVATE: - private_pages_count += info.private_pages_resident; - private_pages_count += info.shared_pages_resident; - break; - case SM_COW: - private_pages_count += info.private_pages_resident; - FALLTHROUGH; - case SM_SHARED: - case SM_PRIVATE_ALIASED: - case SM_TRUESHARED: - case SM_SHARED_ALIASED: - if (seen_objects.count(info.obj_id) == 0) { - // Only count the first reference to this region. - seen_objects.insert(info.obj_id); - shared_pages_count += info.shared_pages_resident; - } - break; - default: - break; - } - if (is_wired) { - wired_pages_count += - info.private_pages_resident + info.shared_pages_resident; - } - } - - if (private_bytes) - *private_bytes = private_pages_count * PAGE_SIZE; - if (shared_bytes) - *shared_bytes = shared_pages_count * PAGE_SIZE; - if (resident_bytes) - *resident_bytes = (private_pages_count + shared_pages_count) * PAGE_SIZE; - if (locked_bytes) - *locked_bytes = wired_pages_count * PAGE_SIZE; - - return true; -} - void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const { WorkingSetKBytes unused; if (!GetCommittedAndWorkingSetKBytes(usage, &unused)) {
diff --git a/base/process/process_metrics_openbsd.cc b/base/process/process_metrics_openbsd.cc index 5a700dd..40d810f 100644 --- a/base/process/process_metrics_openbsd.cc +++ b/base/process/process_metrics_openbsd.cc
@@ -40,22 +40,6 @@ } } // namespace -bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, - size_t* shared_bytes) const { - WorkingSetKBytes ws_usage; - - if (!GetWorkingSetKBytes(&ws_usage)) - return false; - - if (private_bytes) - *private_bytes = ws_usage.priv << 10; - - if (shared_bytes) - *shared_bytes = ws_usage.shared * 1024; - - return true; -} - bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { // TODO(bapt): be sure we can't be precise size_t priv = GetWorkingSetSize();
diff --git a/base/process/process_metrics_unittest.cc b/base/process/process_metrics_unittest.cc index c622050..cb952950 100644 --- a/base/process/process_metrics_unittest.cc +++ b/base/process/process_metrics_unittest.cc
@@ -57,44 +57,6 @@ DISALLOW_COPY_AND_ASSIGN(SystemMetricsTest); }; -///////////////////////////////////////////////////////////////////////////// - -#if defined(OS_MACOSX) && !defined(OS_IOS) && !defined(ADDRESS_SANITIZER) -TEST_F(SystemMetricsTest, LockedBytes) { - ProcessHandle handle = GetCurrentProcessHandle(); - std::unique_ptr<ProcessMetrics> metrics( - ProcessMetrics::CreateProcessMetrics(handle, nullptr)); - - size_t initial_locked_bytes; - bool result = - metrics->GetMemoryBytes(nullptr, nullptr, nullptr, &initial_locked_bytes); - ASSERT_TRUE(result); - - size_t size = 8 * 1024 * 1024; - std::unique_ptr<char[]> memory(new char[size]); - int r = mlock(memory.get(), size); - ASSERT_EQ(0, r); - - size_t new_locked_bytes; - result = - metrics->GetMemoryBytes(nullptr, nullptr, nullptr, &new_locked_bytes); - ASSERT_TRUE(result); - - // There should be around |size| more locked bytes, but multi-threading might - // cause noise. - EXPECT_LT(initial_locked_bytes + size / 2, new_locked_bytes); - EXPECT_GT(initial_locked_bytes + size * 1.5, new_locked_bytes); - - r = munlock(memory.get(), size); - ASSERT_EQ(0, r); - - result = - metrics->GetMemoryBytes(nullptr, nullptr, nullptr, &new_locked_bytes); - ASSERT_TRUE(result); - EXPECT_EQ(initial_locked_bytes, new_locked_bytes); -} -#endif // defined(OS_MACOSX) && !defined(OS_IOS) && !defined(ADDRESS_SANITIZER) - #if defined(OS_LINUX) || defined(OS_ANDROID) TEST_F(SystemMetricsTest, IsValidDiskName) { const char invalid_input1[] = "";
diff --git a/base/process/process_metrics_win.cc b/base/process/process_metrics_win.cc index 6d1c7d5..32b9282 100644 --- a/base/process/process_metrics_win.cc +++ b/base/process/process_metrics_win.cc
@@ -46,31 +46,6 @@ return WrapUnique(new ProcessMetrics(process)); } -bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, - size_t* shared_bytes) const { - // PROCESS_MEMORY_COUNTERS_EX is not supported until XP SP2. - // GetProcessMemoryInfo() will simply fail on prior OS. So the requested - // information is simply not available. Hence, we will return 0 on unsupported - // OSes. Unlike most Win32 API, we don't need to initialize the "cb" member. - PROCESS_MEMORY_COUNTERS_EX pmcx; - if (private_bytes && - GetProcessMemoryInfo(process_.Get(), - reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&pmcx), - sizeof(pmcx))) { - *private_bytes = pmcx.PrivateUsage; - } - - if (shared_bytes) { - WorkingSetKBytes ws_usage; - if (!GetWorkingSetKBytes(&ws_usage)) - return false; - - *shared_bytes = ws_usage.shared * 1024; - } - - return true; -} - void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const { MEMORY_BASIC_INFORMATION mbi = {0}; size_t committed_private = 0;
diff --git a/base/strings/string_tokenizer.h b/base/strings/string_tokenizer.h index 8defbac..03ec687 100644 --- a/base/strings/string_tokenizer.h +++ b/base/strings/string_tokenizer.h
@@ -147,9 +147,9 @@ const_iterator token_begin() const { return token_begin_; } const_iterator token_end() const { return token_end_; } str token() const { return str(token_begin_, token_end_); } - base::StringPiece token_piece() const { - return base::StringPiece(&*token_begin_, - std::distance(token_begin_, token_end_)); + BasicStringPiece<str> token_piece() const { + return BasicStringPiece<str>(&*token_begin_, + std::distance(token_begin_, token_end_)); } private:
diff --git a/base/trace_event/memory_infra_background_whitelist.cc b/base/trace_event/memory_infra_background_whitelist.cc index ee0919e1..df33eb4 100644 --- a/base/trace_event/memory_infra_background_whitelist.cc +++ b/base/trace_event/memory_infra_background_whitelist.cc
@@ -35,6 +35,7 @@ "gpu::TextureManager", "FontCaches", "HistoryReport", + "IPCChannel", "IndexedDBBackingStore", "InMemoryURLIndex", "JavaHeap", @@ -47,6 +48,7 @@ "MojoLevelDB", "PartitionAlloc", "ProcessMemoryMetrics", + "RenderProcessHost", "SharedMemoryTracker", "Skia", "Sql", @@ -110,6 +112,8 @@ "mojo/data_pipe_producer", "mojo/message_pipe", "mojo/platform_handle", + "mojo/queued_ipc_channel_message/0x?", + "mojo/render_process_host/0x?", "mojo/shared_buffer", "mojo/unknown", "mojo/watcher",
diff --git a/build/android/apk_operations.py b/build/android/apk_operations.py index 2143003..740ae5c 100755 --- a/build/android/apk_operations.py +++ b/build/android/apk_operations.py
@@ -447,8 +447,7 @@ # possibly forked() processes. if ':' not in process.name and self._primary_pid is None: self._primary_pid = process.pid - else: - self._my_pids.add(process.pid) + self._my_pids.add(process.pid) def _GetPidStyle(self, pid, dim=False): if pid == self._primary_pid:
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index bb3eb22..ebc99b5 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -1346,6 +1346,12 @@ # TODO(hans): https://crbug.com/766891 "-Wno-null-pointer-arithmetic", ] + if (llvm_force_head_revision) { + cflags += [ + # TODO(crbug.com/823655): Enable by default in next clang roll. + "-Wno-ignored-pragma-optimize", + ] + } } else if (use_xcode_clang) { cflags += [ # TODO(thakis): https://crbug.com/604888
diff --git a/build/config/fuchsia/OWNERS b/build/config/fuchsia/OWNERS index 3f809e82..e7034ea 100644 --- a/build/config/fuchsia/OWNERS +++ b/build/config/fuchsia/OWNERS
@@ -1 +1 @@ -scottmg@chromium.org +file://build/fuchsia/OWNERS
diff --git a/build/config/mac/rules.gni b/build/config/mac/rules.gni index d5a4561..9872661 100644 --- a/build/config/mac/rules.gni +++ b/build/config/mac/rules.gni
@@ -125,6 +125,15 @@ # # Arguments # +# framework_version: +# string, version of the framework. Typically this is a +# single letter, like "A". +# +# framework_contents: +# list of string, top-level items in the framework. This is +# the list of symlinks to create in the .framework directory that link +# into Versions/Current/. +# # info_plist: # (optional) string, path to the Info.plist file that will be used for # the bundle. @@ -138,17 +147,6 @@ # (optional) string, name of the generated framework without the # .framework suffix. If omitted, defaults to target_name. # -# framework_version: -# (optional) string, version of the framework. Typically this is a -# single letter, like "A". If omitted, the Versions/ subdirectory -# structure will not be created, and build output will go directly -# into the framework subdirectory. -# -# framework_contents: -# (optional) list of string, top-level items in the framework. For -# frameworks with a framework_version, this is the list of symlinks to -# create in the .framework directory that link into Versions/Current/. -# # extra_substitutions: # (optional) string array, 'key=value' pairs for extra fields which are # specified in a source Info.plist template. @@ -222,9 +220,8 @@ template("mac_framework_bundle") { assert(defined(invoker.deps), "Dependencies must be specified for $target_name") - assert(!defined(invoker.framework_contents) || - defined(invoker.framework_version), - "framework_contents requres a versioned framework") + assert(invoker.framework_version != "", "framework_version is required") + assert(defined(invoker.framework_contents), "framework_contents is required") _info_plist_target = target_name + "_info_plist" @@ -263,18 +260,11 @@ # Create a file to track the build dependency on the framework_version and # framework_contents variables. - _framework_toc = [] - if (defined(invoker.framework_version)) { - _framework_toc += [ - "Version=" + invoker.framework_version, - _output_name, - ] - _framework_contents = [ _output_name ] - } - if (defined(invoker.framework_contents)) { - _framework_toc += invoker.framework_contents - _framework_contents += invoker.framework_contents - } + _framework_toc = [ + "Version=" + invoker.framework_version, + _output_name, + ] + invoker.framework_contents + _framework_contents = [ _output_name ] + invoker.framework_contents _framework_toc_file = "$target_out_dir/${target_name}.toc" write_file(_framework_toc_file, _framework_toc) @@ -282,24 +272,16 @@ _framework_target = _target_name _framework_name = _output_name + ".framework" _framework_base_dir = "$root_out_dir/$_framework_name" - if (defined(invoker.framework_version) && invoker.framework_version != "") { - _framework_version = invoker.framework_version - _framework_root_dir = _framework_base_dir + "/Versions/$_framework_version" - } else { - _framework_root_dir = _framework_base_dir - } + _framework_root_dir = + _framework_base_dir + "/Versions/${invoker.framework_version}" # Clean the entire framework if the framework_version changes. - _version_arg = "''" - if (defined(invoker.framework_version)) { - _version_arg = _framework_version - } _version_file = "$target_out_dir/${target_name}_version" exec_script("//build/config/mac/prepare_framework_version.py", [ rebase_path(_version_file), rebase_path(_framework_base_dir), - _version_arg, + invoker.framework_version, ]) # Create the symlinks. @@ -322,22 +304,18 @@ visibility = [ ":$_framework_target" ] args = [ - "--framework", - rebase_path(_framework_base_dir, root_build_dir), - "--stamp", - rebase_path(_stamp_file, root_build_dir), - ] + "--framework", + rebase_path(_framework_base_dir, root_build_dir), + "--stamp", + rebase_path(_stamp_file, root_build_dir), + "--version", + invoker.framework_version, + "--contents", + ] + _framework_contents - if (defined(invoker.framework_version)) { - args += [ - "--version", - invoker.framework_version, - "--contents", - ] + _framework_contents - # It is not possible to list _framework_contents as outputs, since - # ninja does not properly stat symbolic links. - # https://github.com/ninja-build/ninja/issues/1186 - } + # It is not possible to list _framework_contents as outputs, since + # ninja does not properly stat symbolic links. + # https://github.com/ninja-build/ninja/issues/1186 } _link_shared_library_target = target_name + "_shared_library"
diff --git a/build/fuchsia/update_sdk.py b/build/fuchsia/update_sdk.py index 61c1c478..cdee484 100755 --- a/build/fuchsia/update_sdk.py +++ b/build/fuchsia/update_sdk.py
@@ -13,7 +13,7 @@ import tarfile import tempfile -SDK_HASH = '6e46feb3b26db267c65ea0923426a16f4da835bb' +SDK_HASH = '62b7da622853d3517d79ff76607522f7092989a6' REPOSITORY_ROOT = os.path.abspath(os.path.join( os.path.dirname(__file__), '..', '..'))
diff --git a/cc/blink/web_layer_impl.cc b/cc/blink/web_layer_impl.cc index df7e0a8a..4b3e0ca 100644 --- a/cc/blink/web_layer_impl.cc +++ b/cc/blink/web_layer_impl.cc
@@ -460,8 +460,8 @@ layer_->SetScrollOffsetFromImplSide(offset); } -void WebLayerImpl::SetLayerClient(base::WeakPtr<cc::LayerClient> client) { - layer_->SetLayerClient(std::move(client)); +void WebLayerImpl::SetLayerClient(cc::LayerClient* client) { + layer_->SetLayerClient(client); } const cc::Layer* WebLayerImpl::CcLayer() const {
diff --git a/cc/blink/web_layer_impl.h b/cc/blink/web_layer_impl.h index 17f2fa34..84e3d2b 100644 --- a/cc/blink/web_layer_impl.h +++ b/cc/blink/web_layer_impl.h
@@ -122,7 +122,7 @@ const override; void SetScrollClient(blink::WebLayerScrollClient* client) override; void SetScrollOffsetFromImplSideForTesting(const gfx::ScrollOffset&) override; - void SetLayerClient(base::WeakPtr<cc::LayerClient> client) override; + void SetLayerClient(cc::LayerClient* client) override; const cc::Layer* CcLayer() const override; cc::Layer* CcLayer() override; void SetElementId(const cc::ElementId&) override;
diff --git a/cc/layers/layer.h b/cc/layers/layer.h index 0a9129af..ad25a15d 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h
@@ -335,9 +335,7 @@ TakeDebugInfo(); virtual void didUpdateMainThreadScrollingReasons(); - void SetLayerClient(base::WeakPtr<LayerClient> client) { - inputs_.client = std::move(client); - } + void SetLayerClient(LayerClient* client) { inputs_.client = client; } virtual bool IsSnapped(); @@ -629,7 +627,7 @@ bool hide_layer_and_subtree : 1; // The following elements can not and are not serialized. - base::WeakPtr<LayerClient> client; + LayerClient* client; base::Callback<void(const gfx::ScrollOffset&, const ElementId&)> did_scroll_callback; std::vector<std::unique_ptr<viz::CopyOutputRequest>> copy_requests;
diff --git a/cc/paint/display_item_list.h b/cc/paint/display_item_list.h index 273caf3..a7a211a 100644 --- a/cc/paint/display_item_list.h +++ b/cc/paint/display_item_list.h
@@ -68,14 +68,26 @@ // Push functions construct a new op on the paint op buffer, while maintaining // bookkeeping information. Must be called after invoking StartPaint(). + // Returns the id (which is an opaque value) of the operation that can be used + // in UpdateSaveLayerBounds(). template <typename T, typename... Args> - void push(Args&&... args) { + size_t push(Args&&... args) { #if DCHECK_IS_ON() DCHECK(IsPainting()); #endif + size_t offset = paint_op_buffer_.next_op_offset(); if (usage_hint_ == kTopLevelDisplayItemList) - offsets_.push_back(paint_op_buffer_.next_op_offset()); + offsets_.push_back(offset); paint_op_buffer_.push<T>(std::forward<Args>(args)...); + return offset; + } + + // Called by blink::PaintChunksToCcLayer when an effect ends, to update the + // bounds of a SaveLayerOp which was emitted when the effect started. This is + // needed because blink doesn't know the bounds when an effect starts. Don't + // add other mutation methods like this if there is better alternative. + void UpdateSaveLayerBounds(size_t id, const SkRect& bounds) { + paint_op_buffer_.UpdateSaveLayerBounds(id, bounds); } void EndPaintOfUnpaired(const gfx::Rect& visual_rect) {
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc index 864a5f3..3ec40ab 100644 --- a/cc/paint/paint_op_buffer.cc +++ b/cc/paint/paint_op_buffer.cc
@@ -269,6 +269,10 @@ return "UNKNOWN"; } +std::ostream& operator<<(std::ostream& os, PaintOpType type) { + return os << PaintOpTypeToString(type); +} + template <typename T> size_t SimpleSerialize(const PaintOp* op, void* memory, size_t size) { if (sizeof(T) > size)
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h index 122730b8..26ca2e30 100644 --- a/cc/paint/paint_op_buffer.h +++ b/cc/paint/paint_op_buffer.h
@@ -90,6 +90,7 @@ }; CC_PAINT_EXPORT std::string PaintOpTypeToString(PaintOpType type); +CC_PAINT_EXPORT std::ostream& operator<<(std::ostream&, PaintOpType); struct CC_PAINT_EXPORT PlaybackParams { using CustomDataRasterCallback = @@ -893,6 +894,18 @@ AnalyzeAddedOp(op); } + void UpdateSaveLayerBounds(size_t offset, const SkRect& bounds) { + CHECK_LT(offset, used_); + CHECK_LE(offset + sizeof(SaveLayerOp), used_); + + auto* op = reinterpret_cast<SaveLayerOp*>(data_.get() + offset); + CHECK_EQ(op->type, static_cast<uint32_t>(SaveLayerOp::kType)); + size_t skip = op->skip; + DCHECK_EQ(skip, ComputeOpSkip(sizeof(SaveLayerOp))); + + op->bounds = bounds; + } + template <typename T> void AnalyzeAddedOp(const T* op) { static_assert(!std::is_same<T, PaintOp>::value, @@ -909,6 +922,16 @@ subrecord_bytes_used_ += op->AdditionalBytesUsed(); } + template <typename T> + const T* GetOpAtForTesting(size_t index) const { + size_t i = 0; + for (PaintOpBuffer::Iterator it(this); it && i <= index; ++it, ++i) { + if (i == index && (*it)->GetType() == T::kType) + return static_cast<const T*>(*it); + } + return nullptr; + } + class CC_PAINT_EXPORT Iterator { public: explicit Iterator(const PaintOpBuffer* buffer)
diff --git a/cc/test/fake_ui_resource_layer_tree_host_impl.cc b/cc/test/fake_ui_resource_layer_tree_host_impl.cc index f1b602ed..2b80fc0 100644 --- a/cc/test/fake_ui_resource_layer_tree_host_impl.cc +++ b/cc/test/fake_ui_resource_layer_tree_host_impl.cc
@@ -23,12 +23,14 @@ DeleteUIResource(uid); UIResourceData data; - data.resource_id = resource_provider()->CreateGpuTextureResource( - bitmap.GetSize(), viz::ResourceTextureHint::kDefault, viz::RGBA_8888, - gfx::ColorSpace()); + + data.resource_id_for_export = resource_provider()->ImportResource( + viz::TransferableResource::MakeGL(gpu::Mailbox::Generate(), GL_LINEAR, + GL_TEXTURE_2D, gpu::SyncToken()), + viz::SingleReleaseCallback::Create(base::DoNothing())); data.opaque = bitmap.GetOpaque(); - fake_ui_resource_map_[uid] = data; + fake_ui_resource_map_[uid] = std::move(data); } void FakeUIResourceLayerTreeHostImpl::DeleteUIResource(UIResourceId uid) { @@ -39,15 +41,15 @@ viz::ResourceId FakeUIResourceLayerTreeHostImpl::ResourceIdForUIResource( UIResourceId uid) const { - UIResourceMap::const_iterator iter = fake_ui_resource_map_.find(uid); + auto iter = fake_ui_resource_map_.find(uid); if (iter != fake_ui_resource_map_.end()) - return iter->second.resource_id; - return 0; + return iter->second.resource_id_for_export; + return viz::kInvalidResourceId; } bool FakeUIResourceLayerTreeHostImpl::IsUIResourceOpaque(UIResourceId uid) const { - UIResourceMap::const_iterator iter = fake_ui_resource_map_.find(uid); + auto iter = fake_ui_resource_map_.find(uid); DCHECK(iter != fake_ui_resource_map_.end()); return iter->second.opaque; }
diff --git a/cc/test/fake_ui_resource_layer_tree_host_impl.h b/cc/test/fake_ui_resource_layer_tree_host_impl.h index bfd77f9..45e89e7 100644 --- a/cc/test/fake_ui_resource_layer_tree_host_impl.h +++ b/cc/test/fake_ui_resource_layer_tree_host_impl.h
@@ -29,9 +29,8 @@ bool IsUIResourceOpaque(UIResourceId uid) const override; private: - using UIResourceMap = - std::unordered_map<UIResourceId, LayerTreeHostImpl::UIResourceData>; - UIResourceMap fake_ui_resource_map_; + std::unordered_map<UIResourceId, LayerTreeHostImpl::UIResourceData> + fake_ui_resource_map_; }; } // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 8c4d640..7d6ab52e 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -80,6 +80,7 @@ #include "cc/trees/tree_synchronizer.h" #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/delay_based_time_source.h" +#include "components/viz/common/gpu/texture_allocation.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/quads/compositor_frame_metadata.h" #include "components/viz/common/quads/frame_deadline.h" @@ -87,6 +88,7 @@ #include "components/viz/common/quads/shared_quad_state.h" #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h" +#include "components/viz/common/resources/bitmap_allocation.h" #include "components/viz/common/traced_value.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" @@ -99,6 +101,7 @@ #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/geometry/vector2d_conversions.h" +#include "ui/gfx/skia_util.h" namespace cc { namespace { @@ -175,12 +178,14 @@ ImageInvalidationUpdateDurationHistogramTimer, "Scheduling.%s.ImageInvalidationUpdateDuration"); -LayerTreeHostImpl::FrameData::FrameData() - : render_surface_list(nullptr), - has_no_damage(false), - may_contain_video(false) {} - +LayerTreeHostImpl::FrameData::FrameData() = default; LayerTreeHostImpl::FrameData::~FrameData() = default; +LayerTreeHostImpl::UIResourceData::UIResourceData() = default; +LayerTreeHostImpl::UIResourceData::~UIResourceData() = default; +LayerTreeHostImpl::UIResourceData::UIResourceData(UIResourceData&&) noexcept = + default; +LayerTreeHostImpl::UIResourceData& LayerTreeHostImpl::UIResourceData::operator=( + UIResourceData&&) = default; std::unique_ptr<LayerTreeHostImpl> LayerTreeHostImpl::Create( const LayerTreeSettings& settings, @@ -1842,6 +1847,7 @@ RenderFrameMetadata metadata; metadata.root_scroll_offset = gfx::ScrollOffsetToVector2dF(active_tree_->TotalScrollOffset()); + metadata.root_background_color = active_tree_->background_color(); return metadata; } @@ -4472,6 +4478,8 @@ const gfx::Size source_size = bitmap.GetSize(); gfx::Size upload_size = bitmap.GetSize(); bool scaled = false; + // UIResources are assumed to be rastered in SRGB. + const gfx::ColorSpace& color_space = gfx::ColorSpace::CreateSRGB(); int max_texture_size = resource_provider_->max_texture_size(); if (source_size.width() > max_texture_size || @@ -4484,18 +4492,48 @@ upload_size = gfx::ScaleToCeiledSize(source_size, scale, scale); } + // For gpu compositing, a texture will be allocated and the UIResource + // will be uploaded into it. + viz::TextureAllocation texture_alloc; + // For software compositing, shared memory will be allocated and the + // UIResource will be copied into it. + std::unique_ptr<base::SharedMemory> shared_memory; + viz::SharedBitmapId shared_bitmap_id; + if (layer_tree_frame_sink_->context_provider()) { - id = resource_provider_->CreateGpuTextureResource( - upload_size, viz::ResourceTextureHint::kDefault, format, - gfx::ColorSpace::CreateSRGB()); + viz::ContextProvider* context_provider = + layer_tree_frame_sink_->context_provider(); + texture_alloc = viz::TextureAllocation::MakeTextureId( + context_provider->ContextGL(), context_provider->ContextCapabilities(), + format, settings_.resource_settings.use_gpu_memory_buffer_resources, + /*for_framebuffer_attachment=*/false); } else { - DCHECK_EQ(format, viz::RGBA_8888); - id = resource_provider_->CreateBitmapResource( - upload_size, gfx::ColorSpace::CreateSRGB(), viz::RGBA_8888); + shared_memory = + viz::bitmap_allocation::AllocateMappedBitmap(upload_size, format); + shared_bitmap_id = viz::SharedBitmap::GenerateId(); } if (!scaled) { - resource_provider_->CopyToResource(id, bitmap.GetPixels(), source_size); + // If not scaled, we can copy the pixels 1:1 from the source bitmap to our + // destination backing of a texture or shared bitmap. + if (layer_tree_frame_sink_->context_provider()) { + viz::TextureAllocation::UploadStorage( + layer_tree_frame_sink_->context_provider()->ContextGL(), + layer_tree_frame_sink_->context_provider()->ContextCapabilities(), + format, upload_size, texture_alloc, color_space, bitmap.GetPixels()); + } else { + DCHECK_EQ(bitmap.GetFormat(), UIResourceBitmap::RGBA8); + SkImageInfo src_info = + SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(source_size)); + SkImageInfo dst_info = + SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(upload_size)); + + sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect( + dst_info, shared_memory->memory(), dst_info.minRowBytes()); + surface->getCanvas()->writePixels( + src_info, const_cast<uint8_t*>(bitmap.GetPixels()), + src_info.minRowBytes(), 0, 0); + } } else { // Only support auto-resizing for N32 textures (since this is primarily for // scrollbars). Users of other types need to ensure they are not too big. @@ -4506,57 +4544,170 @@ float canvas_scale_y = upload_size.height() / static_cast<float>(source_size.height()); - // Uses kPremul_SkAlphaType since that is what SkBitmap's allocN32Pixels - // makes, and we only support the RGBA8 format here. - SkImageInfo info = SkImageInfo::MakeN32( - source_size.width(), source_size.height(), kPremul_SkAlphaType); - int row_bytes = source_size.width() * 4; + // Uses N32Premul since that is what SkBitmap's allocN32Pixels makes, and we + // only support the RGBA8 format here. + SkImageInfo info = + SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(source_size)); SkBitmap source_bitmap; - source_bitmap.setInfo(info, row_bytes); + source_bitmap.setInfo(info); source_bitmap.setPixels(const_cast<uint8_t*>(bitmap.GetPixels())); - // This applies the scale to draw the |bitmap| into |scaled_bitmap|. - SkBitmap scaled_bitmap; - scaled_bitmap.allocN32Pixels(upload_size.width(), upload_size.height()); - SkCanvas scaled_canvas(scaled_bitmap); - scaled_canvas.scale(canvas_scale_x, canvas_scale_y); + // This applies the scale to draw the |bitmap| into |scaled_surface|. For + // gpu compositing, we scale into a software bitmap-backed SkSurface here, + // then upload from there into a texture. For software compositing, we scale + // directly into the shared memory backing. + sk_sp<SkSurface> scaled_surface; + if (layer_tree_frame_sink_->context_provider()) { + scaled_surface = SkSurface::MakeRasterN32Premul(upload_size.width(), + upload_size.height()); + } else { + SkImageInfo dst_info = + SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(upload_size)); + scaled_surface = SkSurface::MakeRasterDirect( + dst_info, shared_memory->memory(), dst_info.minRowBytes()); + } + SkCanvas* scaled_canvas = scaled_surface->getCanvas(); + scaled_canvas->scale(canvas_scale_x, canvas_scale_y); // The |canvas_scale_x| and |canvas_scale_y| may have some floating point // error for large enough values, causing pixels on the edge to be not // fully filled by drawBitmap(), so we ensure they start empty. (See // crbug.com/642011 for an example.) - scaled_canvas.clear(SK_ColorTRANSPARENT); - scaled_canvas.drawBitmap(source_bitmap, 0, 0); + scaled_canvas->clear(SK_ColorTRANSPARENT); + scaled_canvas->drawBitmap(source_bitmap, 0, 0); - auto* pixels = static_cast<uint8_t*>(scaled_bitmap.getPixels()); - resource_provider_->CopyToResource(id, pixels, upload_size); + if (layer_tree_frame_sink_->context_provider()) { + SkPixmap pixmap; + scaled_surface->peekPixels(&pixmap); + viz::TextureAllocation::UploadStorage( + layer_tree_frame_sink_->context_provider()->ContextGL(), + layer_tree_frame_sink_->context_provider()->ContextCapabilities(), + format, upload_size, texture_alloc, color_space, pixmap.addr()); + } } + // Once the backing has the UIResource inside it, we have to prepare it for + // export to the display compositor via ImportResource(). For gpu compositing, + // this requires a Mailbox+SyncToken as well. For software compositing, the + // SharedBitmapId must be notified to the LayerTreeFrameSink. The + // OnUIResourceReleased() method will be called once the resource is deleted + // and the display compositor is no longer using it, to free the memory + // allocated in this method above. + viz::TransferableResource transferable; + if (layer_tree_frame_sink_->context_provider()) { + gpu::gles2::GLES2Interface* gl = + layer_tree_frame_sink_->context_provider()->ContextGL(); + gpu::Mailbox mailbox = gpu::Mailbox::Generate(); + gl->ProduceTextureDirectCHROMIUM(texture_alloc.texture_id, mailbox.name); + gpu::SyncToken sync_token = + LayerTreeResourceProvider::GenerateSyncTokenHelper(gl); + + transferable = viz::TransferableResource::MakeGLOverlay( + mailbox, GL_LINEAR, texture_alloc.texture_target, sync_token, + upload_size, texture_alloc.overlay_candidate); + transferable.format = format; + transferable.buffer_format = viz::BufferFormat(format); + } else { + mojo::ScopedSharedBufferHandle memory_handle = + viz::bitmap_allocation::DuplicateAndCloseMappedBitmap( + shared_memory.get(), upload_size, format); + layer_tree_frame_sink_->DidAllocateSharedBitmap(std::move(memory_handle), + shared_bitmap_id); + transferable = viz::TransferableResource::MakeSoftware(shared_bitmap_id, 0, + upload_size, format); + } + transferable.color_space = color_space; + id = resource_provider_->ImportResource( + transferable, + // The OnUIResourceReleased method is bound with a WeakPtr, but the + // resource backing will be deleted when the LayerTreeFrameSink is + // removed before shutdown, so nothing leaks if the WeakPtr is + // invalidated. + viz::SingleReleaseCallback::Create(base::BindOnce( + &LayerTreeHostImpl::OnUIResourceReleased, AsWeakPtr(), uid))); + UIResourceData data; - data.resource_id = id; data.opaque = bitmap.GetOpaque(); - ui_resource_map_[uid] = data; + data.format = format; + data.shared_bitmap_id = shared_bitmap_id; + data.shared_memory = std::move(shared_memory); + data.texture_id = texture_alloc.texture_id; + data.resource_id_for_export = id; + ui_resource_map_[uid] = std::move(data); MarkUIResourceNotEvicted(uid); } void LayerTreeHostImpl::DeleteUIResource(UIResourceId uid) { - viz::ResourceId id = ResourceIdForUIResource(uid); - if (id) { - if (has_valid_layer_tree_frame_sink_) - resource_provider_->DeleteResource(id); - ui_resource_map_.erase(uid); + auto it = ui_resource_map_.find(uid); + if (it != ui_resource_map_.end()) { + UIResourceData& data = it->second; + viz::ResourceId id = data.resource_id_for_export; + // Move the |data| to |deleted_ui_resources_| before removing it from the + // LayerTreeResourceProvider, so that the ReleaseCallback can see it there. + deleted_ui_resources_[uid] = std::move(data); + ui_resource_map_.erase(it); + + resource_provider_->RemoveImportedResource(id); } MarkUIResourceNotEvicted(uid); } +void LayerTreeHostImpl::DeleteUIResourceBacking( + UIResourceData data, + const gpu::SyncToken& sync_token) { + // Resources are either software or gpu backed, not both. + DCHECK(!(data.shared_memory && data.texture_id)); + if (data.shared_memory) + layer_tree_frame_sink_->DidDeleteSharedBitmap(data.shared_bitmap_id); + if (data.texture_id) { + gpu::gles2::GLES2Interface* gl = + layer_tree_frame_sink_->context_provider()->ContextGL(); + if (sync_token.HasData()) + gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); + gl->DeleteTextures(1, &data.texture_id); + } + // |data| goes out of scope and deletes anything it owned. +} + +void LayerTreeHostImpl::OnUIResourceReleased(UIResourceId uid, + const gpu::SyncToken& sync_token, + bool lost) { + auto it = deleted_ui_resources_.find(uid); + if (it == deleted_ui_resources_.end()) { + // Backing was already deleted, eg if the context was lost. + return; + } + UIResourceData& data = it->second; + // We don't recycle backings here, so |lost| is not relevant, we always delete + // them. + DeleteUIResourceBacking(std::move(data), sync_token); + deleted_ui_resources_.erase(it); +} + void LayerTreeHostImpl::ClearUIResources() { - for (UIResourceMap::const_iterator iter = ui_resource_map_.begin(); - iter != ui_resource_map_.end(); ++iter) { - evicted_ui_resources_.insert(iter->first); - resource_provider_->DeleteResource(iter->second.resource_id); + for (auto& pair : ui_resource_map_) { + UIResourceId uid = pair.first; + UIResourceData& data = pair.second; + resource_provider_->RemoveImportedResource(data.resource_id_for_export); + // Immediately drop the backing instead of waiting for the resource to be + // returned from the ResourceProvider, as this is called in cases where the + // ability to clean up the backings will go away (context loss, shutdown). + DeleteUIResourceBacking(std::move(data), gpu::SyncToken()); + // This resource is not deleted, and its |uid| is still valid, so it moves + // to the evicted list, not the |deleted_ui_resources_| set. Also, its + // backing is gone, so it would not belong in |deleted_ui_resources_|. + evicted_ui_resources_.insert(uid); } ui_resource_map_.clear(); + for (auto& pair : deleted_ui_resources_) { + UIResourceData& data = pair.second; + // Immediately drop the backing instead of waiting for the resource to be + // returned from the ResourceProvider, as this is called in cases where the + // ability to clean up the backings will go away (context loss, shutdown). + DeleteUIResourceBacking(std::move(data), gpu::SyncToken()); + } + deleted_ui_resources_.clear(); } void LayerTreeHostImpl::EvictAllUIResources() { @@ -4571,14 +4722,14 @@ viz::ResourceId LayerTreeHostImpl::ResourceIdForUIResource( UIResourceId uid) const { - UIResourceMap::const_iterator iter = ui_resource_map_.find(uid); + auto iter = ui_resource_map_.find(uid); if (iter != ui_resource_map_.end()) - return iter->second.resource_id; - return 0; + return iter->second.resource_id_for_export; + return viz::kInvalidResourceId; } bool LayerTreeHostImpl::IsUIResourceOpaque(UIResourceId uid) const { - UIResourceMap::const_iterator iter = ui_resource_map_.find(uid); + auto iter = ui_resource_map_.find(uid); DCHECK(iter != ui_resource_map_.end()); return iter->second.opaque; }
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 20af257..a5f0fe3 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -166,6 +166,56 @@ public MutatorHostClient, public base::SupportsWeakPtr<LayerTreeHostImpl> { public: + // This structure is used to build all the state required for producing a + // single CompositorFrame. The |render_passes| list becomes the set of + // RenderPasses in the quad, and the other fields are used for computation + // or become part of the CompositorFrameMetadata. + struct CC_EXPORT FrameData { + FrameData(); + ~FrameData(); + void AsValueInto(base::trace_event::TracedValue* value) const; + + std::vector<viz::SurfaceId> activation_dependencies; + base::Optional<uint32_t> deadline_in_frames; + bool use_default_lower_bound_deadline = false; + std::vector<gfx::Rect> occluding_screen_space_rects; + std::vector<gfx::Rect> non_occluding_screen_space_rects; + viz::RenderPassList render_passes; + const RenderSurfaceList* render_surface_list = nullptr; + LayerImplList will_draw_layers; + bool has_no_damage = false; + bool may_contain_video = false; + viz::BeginFrameAck begin_frame_ack; + + private: + DISALLOW_COPY_AND_ASSIGN(FrameData); + }; + + // A struct of data for a single UIResource, including the backing + // pixels, and metadata about it. + struct CC_EXPORT UIResourceData { + UIResourceData(); + ~UIResourceData(); + UIResourceData(UIResourceData&&) noexcept; + UIResourceData& operator=(UIResourceData&&); + + bool opaque; + viz::ResourceFormat format; + + // Backing for software compositing. + viz::SharedBitmapId shared_bitmap_id; + std::unique_ptr<base::SharedMemory> shared_memory; + // Backing for gpu compositing. + uint32_t texture_id; + + // The name with which to refer to the resource in frames submitted to the + // display compositor. + viz::ResourceId resource_id_for_export; + + private: + DISALLOW_COPY_AND_ASSIGN(UIResourceData); + }; + static std::unique_ptr<LayerTreeHostImpl> Create( const LayerTreeSettings& settings, LayerTreeHostImplClient* client, @@ -245,27 +295,6 @@ resourceless_software_draw_ = true; } - struct CC_EXPORT FrameData { - FrameData(); - ~FrameData(); - void AsValueInto(base::trace_event::TracedValue* value) const; - - std::vector<viz::SurfaceId> activation_dependencies; - base::Optional<uint32_t> deadline_in_frames; - bool use_default_lower_bound_deadline = false; - std::vector<gfx::Rect> occluding_screen_space_rects; - std::vector<gfx::Rect> non_occluding_screen_space_rects; - viz::RenderPassList render_passes; - const RenderSurfaceList* render_surface_list; - LayerImplList will_draw_layers; - bool has_no_damage; - bool may_contain_video; - viz::BeginFrameAck begin_frame_ack; - - private: - DISALLOW_COPY_AND_ASSIGN(FrameData); - }; - virtual void DidSendBeginMainFrame() {} virtual void BeginMainFrameAborted( CommitEarlyOutReason reason, @@ -567,11 +596,6 @@ virtual bool IsUIResourceOpaque(UIResourceId uid) const; - struct UIResourceData { - viz::ResourceId resource_id; - bool opaque; - }; - // Returns the amount of delta that can be applied to scroll_node, taking // page scale into account. gfx::Vector2dF ComputeScrollDelta(const ScrollNode& scroll_node, @@ -758,8 +782,22 @@ void StartScrollbarFadeRecursive(LayerImpl* layer); void SetManagedMemoryPolicy(const ManagedMemoryPolicy& policy); + // Once a resource is uploaded or deleted, it is no longer an evicted id, this + // removes it from the evicted set, and updates if we're able to draw now that + // all UIResources are valid. void MarkUIResourceNotEvicted(UIResourceId uid); + // Deletes all UIResource backings, and marks all the ids as evicted. void ClearUIResources(); + // Frees the textures/bitmaps backing the UIResource, held in the + // UIResourceData. + void DeleteUIResourceBacking(UIResourceData data, + const gpu::SyncToken& sync_token); + // Callback for when a UIResource is deleted *and* no longer in use by the + // display compositor. It will DeleteUIResourceBacking() if the backing was + // not already deleted preemptively. + void OnUIResourceReleased(UIResourceId uid, + const gpu::SyncToken& sync_token, + bool lost); void NotifySwapPromiseMonitorsOfSetNeedsRedraw(); void NotifySwapPromiseMonitorsOfForwardingToMainThread(); @@ -803,12 +841,14 @@ // active tree. void ActivateStateForImages(); - using UIResourceMap = std::unordered_map<UIResourceId, UIResourceData>; - UIResourceMap ui_resource_map_; - + std::unordered_map<UIResourceId, UIResourceData> ui_resource_map_; + // UIResources are held here once requested to be deleted until they are + // released from the display compositor, then the backing can be deleted. + std::unordered_map<UIResourceId, UIResourceData> deleted_ui_resources_; // Resources that were evicted by EvictAllUIResources. Resources are removed // from this when they are touched by a create or destroy from the UI resource - // request queue. + // request queue. The resource IDs held in here do not have any backing + // associated with them anymore, as that is freed at the time of eviction. std::set<UIResourceId> evicted_ui_resources_; LayerTreeFrameSink* layer_tree_frame_sink_;
diff --git a/cc/trees/render_frame_metadata.cc b/cc/trees/render_frame_metadata.cc index fd3a1b9..8d98106 100644 --- a/cc/trees/render_frame_metadata.cc +++ b/cc/trees/render_frame_metadata.cc
@@ -15,11 +15,11 @@ RenderFrameMetadata::~RenderFrameMetadata() {} +// static bool RenderFrameMetadata::HasAlwaysUpdateMetadataChanged( const RenderFrameMetadata& rfm1, const RenderFrameMetadata& rfm2) { - // TODO(jonross): as low frequency fields are added, update this method. - return false; + return rfm1.root_background_color != rfm2.root_background_color; } RenderFrameMetadata& RenderFrameMetadata::operator=( @@ -29,7 +29,8 @@ RenderFrameMetadata&& other) = default; bool RenderFrameMetadata::operator==(const RenderFrameMetadata& other) { - return root_scroll_offset == other.root_scroll_offset; + return root_scroll_offset == other.root_scroll_offset && + root_background_color == other.root_background_color; } bool RenderFrameMetadata::operator!=(const RenderFrameMetadata& other) {
diff --git a/cc/trees/render_frame_metadata.h b/cc/trees/render_frame_metadata.h index a733fe6d..c31ea7b 100644 --- a/cc/trees/render_frame_metadata.h +++ b/cc/trees/render_frame_metadata.h
@@ -7,6 +7,7 @@ #include "base/optional.h" #include "cc/cc_export.h" +#include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/vector2d_f.h" namespace cc { @@ -29,6 +30,11 @@ bool operator==(const RenderFrameMetadata& other); bool operator!=(const RenderFrameMetadata& other); + // The background color of a CompositorFrame. It can be used for filling the + // content area if the primary surface is unavailable and fallback is not + // specified. + SkColor root_background_color = SK_ColorWHITE; + // Scroll offset of the root layer. This optional parameter is only valid // during tests. base::Optional<gfx::Vector2dF> root_scroll_offset;
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 4ab1fa9b..d7be7791 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -315,7 +315,7 @@ data_deps += [ "//chrome/browser/resources/media/mei_preload:component", - "//third_party/widevine/cdm:widevinecdmadapter", + "//third_party/widevine/cdm", ] if (is_multi_dll_chrome) { @@ -766,9 +766,7 @@ ":verify_chrome_framework_order", ] - # Only official builds that include Widevine need the widevine - # signature file. - if (is_chrome_branded && enable_library_cdms) { + if (enable_widevine_cdm_host_verification) { sources += [ "$root_out_dir/Widevine Resources.bundle" ] public_deps += [ ":widevine_resources_bundle" ] } @@ -1046,52 +1044,20 @@ } } - _should_bundle_widevine = - (is_chrome_branded || enable_widevine) && enable_library_cdms - if (_should_bundle_widevine) { - # The Widevine CDM and manifest are either the actual Widevine CDM and - # manifest or stubs used for testing only. The choice is made within the - # corresponding Widevine targets based on branding. + if (should_bundle_widevine_cdm) { bundle_data("widevine_cdm_library_binaries") { sources = [ - "$root_out_dir/$widevine_cdm_path/widevinecdmadapter.plugin", - "$root_out_dir/libwidevinecdm.dylib", - ] - outputs = [ - "{{bundle_contents_dir}}/Libraries/$widevine_cdm_path/{{source_file_part}}", - ] - public_deps = [ - # Need this intermediate dependency because "widevinecdm" is a - # shared_library if !is_chrome_branded, and then depending on - # "widevinecdm" directly would cause it to be linked into the Chromium - # Framework, which we don't want. - ":widevine_cdm_library_copy", - "//third_party/widevine/cdm:widevinecdmadapter", - ] - - # Signatures are only generated for official chrome. - if (is_chrome_branded) { - sources += [ - "$root_out_dir/$widevine_cdm_path/widevinecdmadapter.plugin.sig", - "$root_out_dir/libwidevinecdm.dylib.sig", - ] - public_deps += [ ":sign_cdm_adapter_for_widevine" ] - } - } - - copy("widevine_cdm_library_copy") { - sources = [ "$root_out_dir/$widevine_cdm_path/libwidevinecdm.dylib", ] - if (is_chrome_branded) { + if (enable_widevine_cdm_host_verification) { sources += [ "$root_out_dir/$widevine_cdm_path/libwidevinecdm.dylib.sig" ] } outputs = [ - "$root_out_dir/{{source_file_part}}", + "{{bundle_contents_dir}}/Libraries/$widevine_cdm_path/{{source_file_part}}", ] - deps = [ - "//third_party/widevine/cdm:widevinecdm", + public_deps = [ + "//third_party/widevine/cdm", ] } @@ -1103,18 +1069,21 @@ "{{bundle_contents_dir}}/Libraries/WidevineCdm/{{source_file_part}}", ] public_deps = [ - "//third_party/widevine/cdm:widevine_cdm_manifest", + "//third_party/widevine/cdm", ] } + } - widevine_sign_file("sign_cdm_adapter_for_widevine") { - file = "$root_out_dir/$widevine_cdm_path/widevinecdmadapter.plugin" - flags = 0 + group("widevine_cdm_library") { + if (should_bundle_widevine_cdm) { deps = [ - "//third_party/widevine/cdm:widevinecdmadapter", + ":widevine_cdm_library_binaries", + ":widevine_cdm_library_manifest", ] } + } + if (enable_widevine_cdm_host_verification) { widevine_sign_file("sign_chrome_framework_for_widevine") { file = "$root_out_dir/$chrome_framework_name.framework/" if (defined(chrome_framework_version)) { @@ -1174,15 +1143,6 @@ } } - group("widevine_cdm_library") { - if (_should_bundle_widevine) { - deps = [ - ":widevine_cdm_library_binaries", - ":widevine_cdm_library_manifest", - ] - } - } - if (is_chrome_branded) { action("keystone_registration_framework") { script = "//chrome/tools/build/mac/copy_keystone_framework.py"
diff --git a/chrome/MAJOR_BRANCH_DATE b/chrome/MAJOR_BRANCH_DATE index cc6d536..77b7ef4 100644 --- a/chrome/MAJOR_BRANCH_DATE +++ b/chrome/MAJOR_BRANCH_DATE
@@ -1 +1 @@ -MAJOR_BRANCH_DATE=2018/03/02 +MAJOR_BRANCH_DATE=2018-03-02
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index 93c7aa2..1d3cb16 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -164,8 +164,6 @@ public static final String CHROME_HOME = "ChromeHome"; public static final String CHROME_HOME_DROP_ALL_BUT_FIRST_THUMBNAIL = "ChromeHomeDropAllButFirstThumbnail"; - public static final String CHROME_HOME_INACTIVITY_SHEET_EXPANSION = - "ChromeHomeInactivitySheetExpansion"; public static final String CHROME_HOME_MENU_ITEMS_EXPAND_SHEET = "ChromeHomeMenuItemsExpandSheet"; public static final String CHROME_HOME_PERSISTENT_IPH = "ChromeHomePersistentIph";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index ad367d4..cf09ce1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -946,33 +946,6 @@ if (!mIntentHandler.isIntentUserVisible()) return false; - if (FeatureUtilities.isChromeHomeEnabled() - && ChromeFeatureList.isEnabled( - ChromeFeatureList.CHROME_HOME_INACTIVITY_SHEET_EXPANSION)) { - BottomSheet bottomSheet = getBottomSheet(); - assert bottomSheet != null; - - int timeoutMinsFieldTrialValue = ChromeFeatureList.getFieldTrialParamByFeatureAsInt( - ChromeFeatureList.CHROME_HOME_INACTIVITY_SHEET_EXPANSION, - TIME_SINCE_BACKGROUNDED_IN_MINS_PARAM, - TIME_SINCE_BACKGROUNDED_TO_SHOW_BOTTOM_SHEET_HALF_MINS); - long timeoutExpandBottomSheet = TimeUnit.MINUTES.toMillis(timeoutMinsFieldTrialValue); - if (bottomSheet.isSheetOpen() - || (getTimeSinceLastBackgroundedMs() < timeoutExpandBottomSheet)) { - return false; - } - - if (isInOverviewMode()) return false; - - boolean hasTabs = getCurrentTabModel().getCount() > 0 - || mTabModelSelectorImpl.getRestoredTabCount() > 0; - if (hasTabs) { - bottomSheet.setSheetState( - BottomSheet.SHEET_STATE_HALF, true, StateChangeReason.STARTUP); - } - return false; - } - if (!ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_LAUNCH_AFTER_INACTIVITY)) { return false; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java index 1a43d68..1c17561 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -885,12 +885,6 @@ notifyDownloadFailed(id, fileName, icon); return; } - // Download is already paused. - if (entry != null && !entry.isAutoResumable) { - // Shutdown the service in case it was restarted unnecessarily. - stopTrackingInProgressDownload(id, true); - return; - } boolean canDownloadWhileMetered = entry == null ? false : entry.canDownloadWhileMetered; // If download is interrupted due to network disconnection, show download pending state. if (isAutoResumable) { @@ -899,6 +893,12 @@ stopTrackingInProgressDownload(id, true); return; } + // Download is already paused. + if (entry != null && !entry.isAutoResumable) { + // Shutdown the service in case it was restarted unnecessarily. + stopTrackingInProgressDownload(id, true); + return; + } String contentText = mContext.getResources().getString(R.string.download_notification_paused);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService2.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService2.java index 49f6d1a..f831309d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService2.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService2.java
@@ -304,8 +304,6 @@ notifyDownloadFailed(id, fileName, icon); return; } - // If download is already paused, do nothing. - if (entry != null && !entry.isAutoResumable && !forceRebuild) return; boolean canDownloadWhileMetered = entry == null ? false : entry.canDownloadWhileMetered; // If download is interrupted due to network disconnection, show download pending state. if (isAutoResumable) { @@ -314,6 +312,8 @@ stopTrackingInProgressDownload(id); return; } + // If download is already paused, do nothing. + if (entry != null && !entry.isAutoResumable && !forceRebuild) return; int notificationId = entry == null ? getNotificationId(id) : entry.notificationId; Context context = ContextUtils.getApplicationContext();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index b8c0e04..2d8ebf2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -291,7 +291,7 @@ if (renderFrameHost == null) return; if (TemplateUrlService.getInstance().isSearchResultsPageFromDefaultSearchProvider( url)) { - renderFrameHost.setHasReceivedUserGesture(); + renderFrameHost.notifyUserActivation(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogController.java b/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogController.java index e1d9ec1..459e436 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogController.java
@@ -173,8 +173,7 @@ @Override public void onSheetClosed(int reason) { bottomSheet.removeObserver(this); - if (reason == BottomSheet.StateChangeReason.NAVIGATION - || reason == BottomSheet.StateChangeReason.NEW_TAB) { + if (reason == BottomSheet.StateChangeReason.NAVIGATION) { // Dismiss the prompt as it would otherwise be dismissed momentarily once // the navigation completes. // TODO(timloh): This logs a dismiss (and we also already logged a show),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java index 10cefdef..3506330d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -85,21 +85,15 @@ public static final int SHEET_STATE_SCROLLING = 4; /** The different reasons that the sheet's state can change. */ - @IntDef({StateChangeReason.NONE, StateChangeReason.OMNIBOX_FOCUS, StateChangeReason.SWIPE, - StateChangeReason.NEW_TAB, StateChangeReason.EXPAND_BUTTON, StateChangeReason.STARTUP, - StateChangeReason.BACK_PRESS, StateChangeReason.TAP_SCRIM, - StateChangeReason.NAVIGATION}) + @IntDef({StateChangeReason.NONE, StateChangeReason.SWIPE, StateChangeReason.BACK_PRESS, + StateChangeReason.TAP_SCRIM, StateChangeReason.NAVIGATION}) @Retention(RetentionPolicy.SOURCE) public @interface StateChangeReason { int NONE = 0; - int OMNIBOX_FOCUS = 1; - int SWIPE = 2; - int NEW_TAB = 3; - int EXPAND_BUTTON = 4; - int STARTUP = 5; - int BACK_PRESS = 6; - int TAP_SCRIM = 7; - int NAVIGATION = 8; + int SWIPE = 1; + int BACK_PRESS = 2; + int TAP_SCRIM = 3; + int NAVIGATION = 4; } /** @@ -414,13 +408,6 @@ mIsTouchEnabled = enabled; } - /** - * A notification that the "expand" button for the bottom sheet has been pressed. - */ - public void onExpandButtonPressed() { - setSheetState(BottomSheet.SHEET_STATE_HALF, true, StateChangeReason.EXPAND_BUTTON); - } - /** Immediately end all animations and null the animators. */ public void endAnimations() { if (mSettleAnimator != null) mSettleAnimator.end();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetMetrics.java index f153c32c..a6aae78 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetMetrics.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetMetrics.java
@@ -23,15 +23,14 @@ * The different ways that the bottom sheet can be opened. This is used to back a UMA * histogram and should therefore be treated as append-only. */ - @IntDef({OPENED_BY_SWIPE, OPENED_BY_OMNIBOX_FOCUS, OPENED_BY_NEW_TAB_CREATION, - OPENED_BY_EXPAND_BUTTON, OPENED_BY_STARTUP}) + @IntDef({OPENED_BY_SWIPE, OPENED_BY_BOUNDARY}) @Retention(RetentionPolicy.SOURCE) private @interface SheetOpenReason {} private static final int OPENED_BY_SWIPE = 0; - private static final int OPENED_BY_OMNIBOX_FOCUS = 1; - private static final int OPENED_BY_NEW_TAB_CREATION = 2; - private static final int OPENED_BY_EXPAND_BUTTON = 3; - private static final int OPENED_BY_STARTUP = 4; + // Obsolete: private static final int OPENED_BY_OMNIBOX_FOCUS = 1; + // Obsolete: private static final int OPENED_BY_NEW_TAB_CREATION = 2; + // Obsolete: private static final int OPENED_BY_EXPAND_BUTTON = 3; + // Obsolete: private static final int OPENED_BY_STARTUP = 4; private static final int OPENED_BY_BOUNDARY = 5; private static final CachedMetrics.TimesHistogramSample TIMES_FIRST_OPEN = @@ -57,14 +56,6 @@ private static final CachedMetrics.ActionEvent ACTION_OPENED_BY_SWIPE = new CachedMetrics.ActionEvent("Android.ChromeHome.OpenedBySwipe"); - private static final CachedMetrics.ActionEvent ACTION_OPENED_BY_OMNIBOX_FOCUS = - new CachedMetrics.ActionEvent("Android.ChromeHome.OpenedByOmnibox"); - private static final CachedMetrics.ActionEvent ACTION_OPENED_BY_NEW_TAB_CREATION = - new CachedMetrics.ActionEvent("Android.ChromeHome.OpenedByNTP"); - private static final CachedMetrics.ActionEvent ACTION_OPENED_BY_EXPAND_BUTTON = - new CachedMetrics.ActionEvent("Android.ChromeHome.OpenedByExpandButton"); - private static final CachedMetrics.ActionEvent ACTION_OPENED_BY_STARTUP = - new CachedMetrics.ActionEvent("Android.ChromeHome.OpenedByStartup"); private static final CachedMetrics.ActionEvent ACTION_CLOSED_BY_SWIPE = new CachedMetrics.ActionEvent("Android.ChromeHome.ClosedBySwipe"); @@ -143,22 +134,6 @@ metricsReason = OPENED_BY_SWIPE; ACTION_OPENED_BY_SWIPE.record(); break; - case StateChangeReason.OMNIBOX_FOCUS: - metricsReason = OPENED_BY_OMNIBOX_FOCUS; - ACTION_OPENED_BY_OMNIBOX_FOCUS.record(); - break; - case StateChangeReason.NEW_TAB: - metricsReason = OPENED_BY_NEW_TAB_CREATION; - ACTION_OPENED_BY_NEW_TAB_CREATION.record(); - break; - case StateChangeReason.EXPAND_BUTTON: - metricsReason = OPENED_BY_EXPAND_BUTTON; - ACTION_OPENED_BY_EXPAND_BUTTON.record(); - break; - case StateChangeReason.STARTUP: - metricsReason = OPENED_BY_STARTUP; - ACTION_OPENED_BY_STARTUP.record(); - break; case StateChangeReason.NONE: // Intentionally empty. break;
diff --git a/chrome/app/theme/default_100_percent/common/allowed_midi.png b/chrome/app/theme/default_100_percent/common/allowed_midi.png deleted file mode 100644 index eb621fb..0000000 --- a/chrome/app/theme/default_100_percent/common/allowed_midi.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/blocked_camera.png b/chrome/app/theme/default_100_percent/common/blocked_camera.png deleted file mode 100644 index c423740..0000000 --- a/chrome/app/theme/default_100_percent/common/blocked_camera.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/blocked_popups.png b/chrome/app/theme/default_100_percent/common/blocked_popups.png deleted file mode 100644 index 893fc9e..0000000 --- a/chrome/app/theme/default_100_percent/common/blocked_popups.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/notification_welcome_icon.png b/chrome/app/theme/default_100_percent/common/notification_welcome_icon.png deleted file mode 100644 index 5f69528..0000000 --- a/chrome/app/theme/default_100_percent/common/notification_welcome_icon.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_extension_app_selected.png b/chrome/app/theme/default_100_percent/common/omnibox_extension_app_selected.png deleted file mode 100644 index 923d432..0000000 --- a/chrome/app/theme/default_100_percent/common/omnibox_extension_app_selected.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_http_selected.png b/chrome/app/theme/default_100_percent/common/omnibox_http_selected.png deleted file mode 100644 index 1667dce4..0000000 --- a/chrome/app/theme/default_100_percent/common/omnibox_http_selected.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_search_selected.png b/chrome/app/theme/default_100_percent/common/omnibox_search_selected.png deleted file mode 100644 index 1d37d3c..0000000 --- a/chrome/app/theme/default_100_percent/common/omnibox_search_selected.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/allowed_midi.png b/chrome/app/theme/default_200_percent/common/allowed_midi.png deleted file mode 100644 index 511b5e5..0000000 --- a/chrome/app/theme/default_200_percent/common/allowed_midi.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/blocked_camera.png b/chrome/app/theme/default_200_percent/common/blocked_camera.png deleted file mode 100644 index 6402932..0000000 --- a/chrome/app/theme/default_200_percent/common/blocked_camera.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/blocked_popups.png b/chrome/app/theme/default_200_percent/common/blocked_popups.png deleted file mode 100644 index aa858b0..0000000 --- a/chrome/app/theme/default_200_percent/common/blocked_popups.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_extension_app_selected.png b/chrome/app/theme/default_200_percent/common/omnibox_extension_app_selected.png deleted file mode 100644 index d26d988..0000000 --- a/chrome/app/theme/default_200_percent/common/omnibox_extension_app_selected.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_http_selected.png b/chrome/app/theme/default_200_percent/common/omnibox_http_selected.png deleted file mode 100644 index 3e94af65..0000000 --- a/chrome/app/theme/default_200_percent/common/omnibox_http_selected.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 2e4d080..adb9ac8 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd
@@ -54,7 +54,6 @@ <structure type="chrome_scaled_image" name="IDR_BACK_P" file="common/browser_back_pressed.png" /> </if> <structure type="chrome_scaled_image" name="IDR_BLOCKED_EXTENSION_SCRIPT" file="common/blocked_extension_script.png" /> - <structure type="chrome_scaled_image" name="IDR_BLOCKED_POPUPS" file="common/blocked_popups.png" /> <if expr="chromeos"> <structure type="chrome_scaled_image" name="IDR_BLUETOOTH_KEYBOARD" file="cros/bluetooth_pairing_keyboard.png" /> <structure type="chrome_scaled_image" name="IDR_BLUETOOTH_MOUSE" file="cros/bluetooth_pairing_mouse.png" />
diff --git a/chrome/browser/android/download/download_controller.cc b/chrome/browser/android/download/download_controller.cc index 7430c53d..20caa0fb 100644 --- a/chrome/browser/android/download/download_controller.cc +++ b/chrome/browser/android/download/download_controller.cc
@@ -107,6 +107,7 @@ dl_params->set_request_origin( offline_pages::android::OfflinePageBridge::GetEncodedOriginApp( web_contents)); + dl_params->set_suggested_name(params.suggested_filename); RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU); dl_params->set_download_source(download::DownloadSource::CONTEXT_MENU); dlm->DownloadUrl(std::move(dl_params));
diff --git a/chrome/browser/android/resource_id.h b/chrome/browser/android/resource_id.h index 18b994c..9cb569a 100644 --- a/chrome/browser/android/resource_id.h +++ b/chrome/browser/android/resource_id.h
@@ -21,11 +21,12 @@ LINK_RESOURCE_ID(IDR_INFOBAR_3D_BLOCKED, R.drawable.infobar_3d_blocked) LINK_RESOURCE_ID(IDR_INFOBAR_AUTOFILL_CC, R.drawable.infobar_autofill_cc) LINK_RESOURCE_ID(IDR_INFOBAR_TRANSLATE, R.drawable.infobar_translate) -LINK_RESOURCE_ID(IDR_BLOCKED_POPUPS, R.drawable.infobar_blocked_popups) // Android only infobars. DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_ACCESSIBILITY_EVENTS, R.drawable.infobar_accessibility_events) +DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_BLOCKED_POPUPS, + R.drawable.infobar_blocked_popups) DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_CLIPBOARD, R.drawable.infobar_clipboard) DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_FOLDER, R.drawable.ic_folder_blue_24dp) @@ -49,8 +50,6 @@ R.drawable.infobar_protected_media_identifier) DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_SAVE_PASSWORD, R.drawable.infobar_savepassword) -DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_ADS_BLOCKED, - R.drawable.infobar_blocked_popups) DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_WARNING, R.drawable.infobar_warning) // PageInfoUI images, used in ConnectionInfoPopup
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index 58724db..f988ff1 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -2138,6 +2138,7 @@ "platform_apps/web_view/storage_persistence", "PRE_StoragePersistence", kFlagEnableFileAccess)) << message_; + content::EnsureCookiesFlushed(profile()); } // This is the post-reset portion of the StoragePersistence test. See @@ -3071,6 +3072,8 @@ // Leak the temporary download directory. We'll retake ownership in the next // browser session. temporary_download_dir.Take(); + + content::EnsureCookiesFlushed(profile()); } IN_PROC_BROWSER_TEST_P(WebViewTest, DownloadCookieIsolation_CrossSession) {
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index ddd9d20..b57636f 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -48,6 +48,8 @@ <structure name="IDR_CUSTOM_ELEMENTS_USER_POD_HTML" file="resources\chromeos\login\custom_elements_user_pod.html" flattenhtml="true" type="chrome_html" /> <structure name="IDR_CUSTOM_ELEMENTS_LOGIN_HTML" file="resources\chromeos\login\custom_elements_login.html" flattenhtml="true" type="chrome_html" /> <structure name="IDR_CUSTOM_ELEMENTS_LOGIN_JS" file="resources\chromeos\login\custom_elements_login.js" flattenhtml="true" type="chrome_html" /> + <structure name="IDR_ASSISTANT_OPTIN_HTML" file="resources\chromeos\assistant_optin\assistant_optin.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" /> + <structure name="IDR_ASSISTANT_OPTIN_JS" file="resources\chromeos\assistant_optin\assistant_optin.js" flattenhtml="true" allowexternalscript="true" type="chrome_html" /> </if> <structure name="IDR_SIGNIN_SHARED_CSS_HTML" file="resources\signin\signin_shared_css.html" preprocess="true" allowexternalscript="true" type="chrome_html" /> <if expr="not is_android and not chromeos"> @@ -385,7 +387,6 @@ <if expr="enable_print_preview"> <include name="IDR_PRINT_PREVIEW_HTML" file="resources\print_preview\print_preview.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_PRINT_PREVIEW_JS" file="resources\print_preview\print_preview.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_PRINT_PREVIEW_PDF_PREVIEW_HTML" file="resources\print_preview\pdf_preview.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_PRINT_PREVIEW_IMAGES_1X_PRINTER" file="resources\print_preview\images\1x\printer.png" type="BINDATA" /> <include name="IDR_PRINT_PREVIEW_IMAGES_2X_PRINTER"
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 7f9ba4a..571970b 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -57,6 +57,8 @@ #include "chrome/browser/memory/chrome_memory_coordinator_delegate.h" #include "chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.h" #include "chrome/browser/nacl_host/nacl_browser_delegate_impl.h" +#include "chrome/browser/net/profile_network_context_service.h" +#include "chrome/browser/net/profile_network_context_service_factory.h" #include "chrome/browser/net_benchmarking.h" #include "chrome/browser/notifications/platform_notification_service_impl.h" #include "chrome/browser/page_load_metrics/metrics_navigation_throttle.h" @@ -925,6 +927,11 @@ registry->RegisterBooleanPref(prefs::kSitePerProcess, false); registry->RegisterBooleanPref(prefs::kWebDriverOverridesIncompatiblePolicies, false); +#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) + // TODO(chrisha): Move this to chrome/browser/conflicts as we build the + // logic that responds to this pref. + registry->RegisterBooleanPref(prefs::kThirdPartyBlockingEnabled, true); +#endif } // static @@ -3921,6 +3928,7 @@ content::BrowserContext* context, bool in_memory, const base::FilePath& relative_partition_path) { + Profile* profile = Profile::FromBrowserContext(context); // If the relative partition path is empty, this is creating the Profile's // main NetworkContext. if (relative_partition_path.empty()) { @@ -3928,12 +3936,17 @@ // ProfileIOData is removed. Currently, TestProfile (used in unit tests) // needs to be able to bypass ProfileNetworkContextServiceFactory, since // TestProfile bypasses ProfileIOData's URLRequestContext creation logic. - Profile* profile = Profile::FromBrowserContext(context); return profile->CreateMainNetworkContext(); } - // TODO(mmenke): Implement this once ProfileNetworkContextServiceFactory can - // create a fully functional NetworkContext for Apps when the network service - // is disabled. + + // TODO(mmenke): Share this with the non-network service code path once + // ProfileNetworkContextServiceFactory can create a fully functional + // NetworkContext for Apps when the network service is disabled. + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { + return ProfileNetworkContextServiceFactory::GetForContext(context) + ->CreateNetworkContextForPartition(in_memory, relative_partition_path); + } + return ContentBrowserClient::CreateNetworkContext(context, in_memory, relative_partition_path); }
diff --git a/chrome/browser/chrome_content_utility_manifest_overlay.json b/chrome/browser/chrome_content_utility_manifest_overlay.json index 5bd06f88..c4d3d70 100644 --- a/chrome/browser/chrome_content_utility_manifest_overlay.json +++ b/chrome/browser/chrome_content_utility_manifest_overlay.json
@@ -7,9 +7,6 @@ "chrome::mojom::DialDeviceDescriptionParser", "chrome::mojom::ProfileImport", "chrome::mojom::ShellHandler", - "extensions::mojom::ExtensionUnpacker", - "extensions::mojom::ManifestParser", - "extensions::mojom::MediaParser", "payments::mojom::PaymentManifestParser", "profiling::mojom::ProfilingClient", "proxy_resolver::mojom::ProxyResolverFactory",
diff --git a/chrome/browser/chromeos/attestation/fake_certificate.cc b/chrome/browser/chromeos/attestation/fake_certificate.cc index 1571bde..4ed3cbc 100644 --- a/chrome/browser/chromeos/attestation/fake_certificate.cc +++ b/chrome/browser/chromeos/attestation/fake_certificate.cc
@@ -66,7 +66,7 @@ return false; } return net::x509_util::CreateSelfSignedCert( - test_key.get(), net::x509_util::DIGEST_SHA256, "CN=subject", 12345, + test_key->key(), net::x509_util::DIGEST_SHA256, "CN=subject", 12345, valid_start, valid_expiry, certificate); }
diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.cc b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.cc index e35e7fc..526b42b 100644 --- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.cc +++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" #include "chrome/browser/chromeos/login/users/supervised_user_manager.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" #include "chromeos/login/auth/extended_authenticator.h" #include "chromeos/login/auth/user_context.h" @@ -260,6 +261,34 @@ Release(); // Balanced in Run(). } +// quickUnlockPrivate.setLockScreenEnabled + +QuickUnlockPrivateSetLockScreenEnabledFunction:: + QuickUnlockPrivateSetLockScreenEnabledFunction() + : chrome_details_(this) {} + +QuickUnlockPrivateSetLockScreenEnabledFunction:: + ~QuickUnlockPrivateSetLockScreenEnabledFunction() {} + +ExtensionFunction::ResponseAction +QuickUnlockPrivateSetLockScreenEnabledFunction::Run() { + auto params = + quick_unlock_private::SetLockScreenEnabled::Params::Create(*args_); + Profile* profile = Profile::FromBrowserContext(browser_context()); + QuickUnlockStorage* quick_unlock_storage = + chromeos::quick_unlock::QuickUnlockFactory::GetForProfile(profile); + if (quick_unlock_storage->GetAuthTokenExpired()) + return RespondNow(Error(kAuthTokenExpired)); + if (params->token != quick_unlock_storage->GetAuthToken()) + return RespondNow(Error(kAuthTokenInvalid)); + + profile->GetPrefs()->SetBoolean(prefs::kEnableAutoScreenLock, + params->enabled); + + return RespondNow(ArgumentList( + quick_unlock_private::SetLockScreenEnabled::Results::Create())); +} + // quickUnlockPrivate.getAvailableModes QuickUnlockPrivateGetAvailableModesFunction::
diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h index 658ad5bd..764ed0b1 100644 --- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h +++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h
@@ -57,6 +57,25 @@ DISALLOW_COPY_AND_ASSIGN(QuickUnlockPrivateGetAuthTokenFunction); }; +class QuickUnlockPrivateSetLockScreenEnabledFunction + : public UIThreadExtensionFunction { + public: + QuickUnlockPrivateSetLockScreenEnabledFunction(); + DECLARE_EXTENSION_FUNCTION("quickUnlockPrivate.setLockScreenEnabled", + QUICKUNLOCKPRIVATE_SETLOCKSCREENENABLED); + + protected: + ~QuickUnlockPrivateSetLockScreenEnabledFunction() override; + + // ExtensionFunction overrides. + ResponseAction Run() override; + + private: + ChromeExtensionFunctionDetails chrome_details_; + + DISALLOW_COPY_AND_ASSIGN(QuickUnlockPrivateSetLockScreenEnabledFunction); +}; + class QuickUnlockPrivateGetAvailableModesFunction : public UIThreadExtensionFunction { public:
diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc index ee0ab12..9c83fc6 100644 --- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc +++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
@@ -177,6 +177,25 @@ return RunFunctionAndReturnError(func, std::move(params)); } + // Wrapper for chrome.quickUnlockPrivate.setLockScreenEnabled. + void SetLockScreenEnabled(const std::string& token, bool enabled) { + auto params = std::make_unique<base::ListValue>(); + params->AppendString(token); + params->AppendBoolean(enabled); + RunFunction(new QuickUnlockPrivateSetLockScreenEnabledFunction(), + std::move(params)); + } + + // Wrapper for chrome.quickUnlockPrivate.setLockScreenEnabled. + std::string SetLockScreenEnabledWithInvalidToken(bool enabled) { + auto params = std::make_unique<base::ListValue>(); + params->AppendString(kInvalidToken); + params->AppendBoolean(enabled); + return RunFunctionAndReturnError( + new QuickUnlockPrivateSetLockScreenEnabledFunction(), + std::move(params)); + } + // Wrapper for chrome.quickUnlockPrivate.getAvailableModes. QuickUnlockModeList GetAvailableModes() { // Run the function. @@ -338,6 +357,8 @@ return api_test_utils::RunFunctionAndReturnError(func, args, profile()); } + std::string token() { return token_; } + private: // Runs the given |func| with the given |params|. std::unique_ptr<base::Value> RunFunction( @@ -397,6 +418,33 @@ EXPECT_FALSE(error.empty()); } +// Verifies that setting lock screen enabled modifies the setting. +TEST_F(QuickUnlockPrivateUnitTest, SetLockScreenEnabled) { + PrefService* pref_service = profile()->GetPrefs(); + bool lock_screen_enabled = + pref_service->GetBoolean(prefs::kEnableAutoScreenLock); + + SetLockScreenEnabled(token(), !lock_screen_enabled); + + EXPECT_EQ(!lock_screen_enabled, + pref_service->GetBoolean(prefs::kEnableAutoScreenLock)); +} + +// Verifies that setting lock screen enabled fails to modify the setting with +// an invalid token. +TEST_F(QuickUnlockPrivateUnitTest, SetLockScreenEnabledFailsWithInvalidToken) { + PrefService* pref_service = profile()->GetPrefs(); + bool lock_screen_enabled = + pref_service->GetBoolean(prefs::kEnableAutoScreenLock); + + std::string error = + SetLockScreenEnabledWithInvalidToken(!lock_screen_enabled); + EXPECT_FALSE(error.empty()); + + EXPECT_EQ(lock_screen_enabled, + pref_service->GetBoolean(prefs::kEnableAutoScreenLock)); +} + // Verifies that this returns PIN for GetAvailableModes. TEST_F(QuickUnlockPrivateUnitTest, GetAvailableModes) { EXPECT_EQ(GetAvailableModes(),
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc index bd3df7df..c3adf60 100644 --- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc +++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -37,6 +37,7 @@ #include "chrome/grit/generated_resources.h" #include "chrome/test/base/testing_browser_process.h" #include "chromeos/chromeos_switches.h" +#include "chromeos/dbus/fake_auth_policy_client.h" #include "chromeos/dbus/fake_session_manager_client.h" #include "chromeos/login/auth/authpolicy_login_helper.h" #include "chromeos/login/auth/key.h" @@ -80,6 +81,8 @@ const char kGaiaID[] = "12345"; const char kUsername[] = "test_user@gmail.com"; +const char kUserWhitelist[] = "*@gmail.com"; +const char kUserNotMatchingWhitelist[] = "user@another_mail.com"; const char kSupervisedUserID[] = "supervised_user@locally-managed.localhost"; const char kPassword[] = "test_password"; const char kActiveDirectoryRealm[] = "active.directory.realm"; @@ -773,12 +776,48 @@ EXPECT_CALL(*mock_login_display_, SetUIEnabled(true)).Times(1); } + void ExpectLoginWhitelistFailure() { + EXPECT_CALL(*mock_login_display_, SetUIEnabled(false)).Times(2); + EXPECT_CALL(*mock_login_display_, ShowWhitelistCheckFailedError()).Times(1); + EXPECT_CALL(*mock_login_display_, SetUIEnabled(true)).Times(1); + } + void ExpectLoginSuccess() { EXPECT_CALL(*mock_login_display_, SetUIEnabled(false)).Times(2); EXPECT_CALL(*mock_login_display_, SetUIEnabled(true)).Times(1); } }; +class ExistingUserControllerActiveDirectoryUserWhitelistTest + : public ExistingUserControllerActiveDirectoryTest { + public: + ExistingUserControllerActiveDirectoryUserWhitelistTest() = default; + + void SetUpInProcessBrowserTestFixture() override { + ExistingUserControllerActiveDirectoryTest:: + SetUpInProcessBrowserTestFixture(); + chromeos::FakeAuthPolicyClient* fake_authpolicy_client = + static_cast<chromeos::FakeAuthPolicyClient*>( + chromeos::DBusThreadManager::Get()->GetAuthPolicyClient()); + em::ChromeDeviceSettingsProto device_policy; + device_policy.mutable_user_whitelist()->add_user_whitelist()->assign( + kUserWhitelist); + fake_authpolicy_client->set_device_policy(device_policy); + } + + void SetUpLoginDisplay() override { + EXPECT_CALL(*mock_login_display_host_.get(), CreateLoginDisplay(_)) + .Times(1) + .WillOnce(Return(mock_login_display_)); + EXPECT_CALL(*mock_login_display_host_.get(), GetNativeWindow()) + .Times(1) + .WillOnce(ReturnNull()); + EXPECT_CALL(*mock_login_display_host_.get(), OnPreferencesChanged()) + .Times(1); + EXPECT_CALL(*mock_login_display_, Init(_, false, true, false)).Times(1); + } +}; + // Tests that Active Directory online login succeeds on the Active Directory // managed device. IN_PROC_BROWSER_TEST_F(ExistingUserControllerActiveDirectoryTest, @@ -824,6 +863,37 @@ existing_user_controller()->CompleteLogin(user_context); } +// Tests that authentication succeeds if user email matches whitelist. +IN_PROC_BROWSER_TEST_F(ExistingUserControllerActiveDirectoryUserWhitelistTest, + Success) { + ExpectLoginSuccess(); + UserContext user_context(ad_account_id_); + user_context.SetKey(Key(kPassword)); + user_context.SetUserIDHash(ad_account_id_.GetUserEmail()); + user_context.SetAuthFlow(UserContext::AUTH_FLOW_ACTIVE_DIRECTORY); + user_context.SetUserType(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY); + content::WindowedNotificationObserver profile_prepared_observer( + chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, + content::NotificationService::AllSources()); + existing_user_controller()->CompleteLogin(user_context); + + profile_prepared_observer.Wait(); +} + +// Tests that authentication fails if user email does not match whitelist. +IN_PROC_BROWSER_TEST_F(ExistingUserControllerActiveDirectoryUserWhitelistTest, + Fail) { + ExpectLoginWhitelistFailure(); + AccountId account_id = + AccountId::AdFromUserEmailObjGuid(kUserNotMatchingWhitelist, kGaiaID); + UserContext user_context(account_id); + user_context.SetKey(Key(kPassword)); + user_context.SetUserIDHash(account_id.GetUserEmail()); + user_context.SetAuthFlow(UserContext::AUTH_FLOW_ACTIVE_DIRECTORY); + user_context.SetUserType(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY); + existing_user_controller()->CompleteLogin(user_context); +} + class ExistingUserControllerSavePasswordHashTest : public ExistingUserControllerTest { public:
diff --git a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc index 243da32..13ea44e 100644 --- a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc +++ b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc
@@ -57,6 +57,8 @@ NotificationParams* params = &controller->params_; params->title_message_id = IDS_QUICK_UNLOCK_NOTIFICATION_TITLE; params->body_message_id = IDS_QUICK_UNLOCK_NOTIFICATION_BODY; + // TODO(http://crbug.com/291747): Change this to actual icon for quick unlock + // feature notification, also use a vector icon instead of raster asset. params->icon_id = IDR_SCREENSHOT_NOTIFICATION_ICON; params->notifier = kNotifierPinUnlock; params->feature_name_id = IDS_PIN_UNLOCK_FEATURE_NOTIFIER_NAME; @@ -110,6 +112,7 @@ NotificationParams* params = &controller->params_; params->title_message_id = IDS_FINGERPRINT_NOTIFICATION_TITLE; params->body_message_id = IDS_FINGERPRINT_NOTIFICATION_BODY; + // TODO(sammiequon): Change to a vector icon identifier. params->icon_id = IDR_NOTIFICATION_FINGERPRINT; params->notifier = kNotifierFingerprintUnlock; params->feature_name_id = IDS_FINGERPRINT_UNLOCK_FEATURE_NOTIFIER_NAME; @@ -215,8 +218,6 @@ message_center::NOTIFICATION_TYPE_SIMPLE, params_.notification_id, l10n_util::GetStringUTF16(params_.title_message_id), l10n_util::GetStringUTF16(params_.body_message_id), - // TODO(http://crbug.com/291747): Change this to actual icon for - // quick unlock feature notification. ui::ResourceBundle::GetSharedInstance().GetImageNamed(params_.icon_id), l10n_util::GetStringUTF16(params_.feature_name_id), GURL(), message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT,
diff --git a/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc b/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc index 4165c74..5888138c 100644 --- a/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc +++ b/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc
@@ -375,7 +375,6 @@ base::BindOnce(&chrome::AttemptUserExit) /* fatal_error_callback */, account_id, base::ThreadTaskRunnerHandle::Get(), io_task_runner); - // TODO(tnagel): Enable whitelist for Active Directory. bool wildcard_match = false; if (connector->IsEnterpriseManaged() && chromeos::CrosSettings::Get()->IsUserWhitelisted(
diff --git a/chrome/browser/chromeos/printing/cups_print_job.h b/chrome/browser/chromeos/printing/cups_print_job.h index e01e926..df2f1d9 100644 --- a/chrome/browser/chromeos/printing/cups_print_job.h +++ b/chrome/browser/chromeos/printing/cups_print_job.h
@@ -53,7 +53,6 @@ const std::string& document_title() const { return document_title_; } int total_page_number() const { return total_page_number_; } int printed_page_number() const { return printed_page_number_; } - bool expired() const { return expired_; } State state() const { return state_; } ErrorCode error_code() const { return error_code_; } @@ -61,7 +60,6 @@ void set_printed_page_number(int page_number) { printed_page_number_ = page_number; } - void set_expired(bool expired) { expired_ = expired; } void set_state(State state) { state_ = state; } void set_error_code(ErrorCode error_code) { error_code_ = error_code; } @@ -79,9 +77,6 @@ int total_page_number_ = 0; int printed_page_number_ = 0; - // True if the job has expired due to timeout. - bool expired_ = false; - State state_ = State::STATE_NONE; ErrorCode error_code_ = ErrorCode::NO_ERROR;
diff --git a/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc b/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc index 3f2d3cea..5325295 100644 --- a/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc +++ b/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc
@@ -39,11 +39,6 @@ // The rate in milliseconds at which we will poll CUPS for print job updates. const int kPollRate = 1000; -// How long we'll wait to connect to a printer before declaring an error. -// TODO(crbug.com/786182): Increase to 120s to give pipeline more time to -// complete. -const int kConnectingTimeout = 120; - // Threshold for giving up on communicating with CUPS. const int kRetryMax = 6; @@ -121,16 +116,6 @@ return State::STATE_NONE; } -// Returns true if |printer_status|.reasons contains |reason|. -bool ContainsReason(const printing::PrinterStatus printer_status, - PrinterReason::Reason reason) { - return std::find_if(printer_status.reasons.begin(), - printer_status.reasons.end(), - [&reason](const PrinterReason& r) { - return r.reason == reason; - }) != printer_status.reasons.end(); -} - // Returns true if |job|.state_reasons contains |reason| bool JobContainsReason(const ::printing::CupsJob& job, base::StringPiece reason) { @@ -158,15 +143,6 @@ return chromeos::CupsPrintJob::ErrorCode::NO_ERROR; } -// Check if the job should timeout. Returns true if the job has timed out. -bool DidTimeout(const printing::CupsJob& job, - chromeos::CupsPrintJob* print_job) { - // Check to see if we should time out. - base::TimeDelta time_waiting = - base::Time::Now() - base::Time::FromTimeT(job.processing_started); - return time_waiting > base::TimeDelta::FromSeconds(kConnectingTimeout); -} - // Update the current printed page. Returns true of the page has been updated. bool UpdateCurrentPage(const printing::CupsJob& job, chromeos::CupsPrintJob* print_job) { @@ -195,17 +171,7 @@ bool pages_updated = false; switch (job.state) { case ::printing::CupsJob::PROCESSING: - if (ContainsReason(printer_status, PrinterReason::CONNECTING_TO_DEVICE)) { - if (DidTimeout(job, print_job)) { - LOG(WARNING) << "Connecting to printer timed out"; - print_job->set_state(chromeos::CupsPrintJob::State::STATE_ERROR); - print_job->set_error_code( - chromeos::CupsPrintJob::ErrorCode::PRINTER_UNREACHABLE); - print_job->set_expired(true); - } - } else { - pages_updated = UpdateCurrentPage(job, print_job); - } + pages_updated = UpdateCurrentPage(job, print_job); break; case ::printing::CupsJob::COMPLETED: DCHECK_GE(job.current_pages, print_job->total_page_number()); @@ -476,12 +442,7 @@ NotifyJobStateUpdate(print_job); } - if (print_job->expired()) { - // Job needs to be forcibly cancelled. - RecordJobResult(TIMEOUT_CANCEL); - FinishPrintJob(print_job); - // Beware, print_job was removed from jobs_ and deleted. - } else if (print_job->PipelineDead()) { + if (print_job->PipelineDead()) { RecordJobResult(FILTER_FAILED); FinishPrintJob(print_job); } else if (print_job->IsJobFinished()) {
diff --git a/chrome/browser/component_updater/sw_reporter_installer_win.cc b/chrome/browser/component_updater/sw_reporter_installer_win.cc index 900a761..ae1e9f9 100644 --- a/chrome/browser/component_updater/sw_reporter_installer_win.cc +++ b/chrome/browser/component_updater/sw_reporter_installer_win.cc
@@ -93,7 +93,7 @@ int current_failure_run = 0; bool last_result = false; while (tokenizer.GetNext()) { - if (tokenizer.token() == L"0") { + if (tokenizer.token_piece() == L"0") { ++failure_count; ++current_failure_run; last_result = false;
diff --git a/chrome/browser/component_updater/third_party_module_list_component_installer_win.cc b/chrome/browser/component_updater/third_party_module_list_component_installer_win.cc index bd1dc33d..0741121 100644 --- a/chrome/browser/component_updater/third_party_module_list_component_installer_win.cc +++ b/chrome/browser/component_updater/third_party_module_list_component_installer_win.cc
@@ -19,7 +19,6 @@ #include "base/values.h" #include "base/version.h" #include "chrome/browser/conflicts/module_database_win.h" -#include "chrome/browser/conflicts/third_party_conflicts_manager_win.h" #include "components/component_updater/component_updater_paths.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/conflicts/module_database_win.cc b/chrome/browser/conflicts/module_database_win.cc index 42d7fd04..6ad367cb 100644 --- a/chrome/browser/conflicts/module_database_win.cc +++ b/chrome/browser/conflicts/module_database_win.cc
@@ -13,12 +13,6 @@ #include "base/win/windows_version.h" #include "chrome/browser/conflicts/module_database_observer_win.h" -#if defined(GOOGLE_CHROME_BUILD) -#include "chrome/browser/conflicts/third_party_conflicts_manager_win.h" -#include "chrome/common/chrome_features.h" -#include "components/prefs/pref_registry_simple.h" -#endif - namespace { // Document the assumptions made on the ProcessType enum in order to convert @@ -55,7 +49,11 @@ AddObserver(&third_party_metrics_); #if defined(GOOGLE_CHROME_BUILD) - MaybeInitializeThirdPartyConflictsManager(); + if (base::win::GetVersion() >= base::win::VERSION_WIN10) { + third_party_conflicts_manager_ = + std::make_unique<ThirdPartyConflictsManager>(this); + AddObserver(third_party_conflicts_manager_.get()); + } #endif } @@ -174,15 +172,6 @@ module_inspector_.IncreaseInspectionPriority(); } -#if defined(GOOGLE_CHROME_BUILD) -// static -void ModuleDatabase::RegisterLocalStatePrefs(PrefRegistrySimple* registry) { - // Register the pref used to disable the Incompatible Applications warning - // using group policy. - registry->RegisterBooleanPref(prefs::kThirdPartyBlockingEnabled, true); -} -#endif - // static uint32_t ModuleDatabase::ProcessTypeToBit(content::ProcessType process_type) { uint32_t bit_index = @@ -269,23 +258,3 @@ observer->OnNewModuleFound(module.first, module.second); } } - -#if defined(GOOGLE_CHROME_BUILD) -void ModuleDatabase::MaybeInitializeThirdPartyConflictsManager() { - // Early exit if disabled via group policy. - const PrefService::Preference* third_party_blocking_enabled_pref = - g_browser_process->local_state()->FindPreference( - prefs::kThirdPartyBlockingEnabled); - if (third_party_blocking_enabled_pref->IsManaged() && - !third_party_blocking_enabled_pref->GetValue()->GetBool()) - return; - - if (base::FeatureList::IsEnabled( - features::kIncompatibleApplicationsWarning) && - base::win::GetVersion() >= base::win::VERSION_WIN10) { - third_party_conflicts_manager_ = - std::make_unique<ThirdPartyConflictsManager>(this); - AddObserver(third_party_conflicts_manager_.get()); - } -} -#endif
diff --git a/chrome/browser/conflicts/module_database_win.h b/chrome/browser/conflicts/module_database_win.h index 80bb624..e9583721 100644 --- a/chrome/browser/conflicts/module_database_win.h +++ b/chrome/browser/conflicts/module_database_win.h
@@ -19,13 +19,12 @@ #include "chrome/browser/conflicts/third_party_metrics_recorder_win.h" #include "content/public/common/process_type.h" -class ModuleDatabaseObserver; - #if defined(GOOGLE_CHROME_BUILD) -class PrefRegistrySimple; -class ThirdPartyConflictsManager; +#include "chrome/browser/conflicts/third_party_conflicts_manager_win.h" #endif +class ModuleDatabaseObserver; + namespace base { class FilePath; } @@ -116,11 +115,9 @@ void IncreaseInspectionPriority(); #if defined(GOOGLE_CHROME_BUILD) - static void RegisterLocalStatePrefs(PrefRegistrySimple* registry); - // Accessor for the third party conflicts manager. This is exposed so that the // manager can be wired up to the ThirdPartyModuleListComponentInstaller. - // Returns null if the tracking of incompatible applications is disabled. + // Returns returns null on Windows 8.1 and lower. ThirdPartyConflictsManager* third_party_conflicts_manager() { return third_party_conflicts_manager_.get(); } @@ -173,15 +170,6 @@ // OnNewModuleFound(). void NotifyLoadedModules(ModuleDatabaseObserver* observer); -#if defined(GOOGLE_CHROME_BUILD) - // Initializes the ThirdPartyConflictsManager, which controls the warning of - // incompatible applications that injects into Chrome. - // The manager is not initialized if it is disabled via a base::Feature or a - // group policy. Note that it is also not initialized on Windows version - // 8.1 and less. - void MaybeInitializeThirdPartyConflictsManager(); -#endif - // The task runner to which this object is bound. scoped_refptr<base::SequencedTaskRunner> task_runner_;
diff --git a/chrome/browser/conflicts/module_event_sink_impl_win_unittest.cc b/chrome/browser/conflicts/module_event_sink_impl_win_unittest.cc index e90c718..a4880258 100644 --- a/chrome/browser/conflicts/module_event_sink_impl_win_unittest.cc +++ b/chrome/browser/conflicts/module_event_sink_impl_win_unittest.cc
@@ -11,8 +11,6 @@ #include "base/threading/sequenced_task_runner_handle.h" #include "chrome/browser/conflicts/module_database_win.h" #include "chrome/common/conflicts/module_watcher_win.h" -#include "chrome/test/base/scoped_testing_local_state.h" -#include "chrome/test/base/testing_browser_process.h" #include "testing/gtest/include/gtest/gtest.h" #include <windows.h> @@ -31,8 +29,7 @@ class ModuleEventSinkImplTest : public testing::Test { protected: ModuleEventSinkImplTest() - : scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()), - module_database_(std::make_unique<ModuleDatabase>( + : module_database_(std::make_unique<ModuleDatabase>( base::SequencedTaskRunnerHandle::Get())) {} void CreateModuleSinkImpl() { @@ -47,7 +44,6 @@ // Must be before |module_database_|. base::test::ScopedTaskEnvironment scoped_task_environment_; - ScopedTestingLocalState scoped_testing_local_state_; std::unique_ptr<ModuleDatabase> module_database_; std::unique_ptr<ModuleEventSinkImpl> module_event_sink_impl_;
diff --git a/chrome/browser/conflicts/problematic_programs_updater_win.cc b/chrome/browser/conflicts/problematic_programs_updater_win.cc index 8f9408f..07fa38b 100644 --- a/chrome/browser/conflicts/problematic_programs_updater_win.cc +++ b/chrome/browser/conflicts/problematic_programs_updater_win.cc
@@ -139,6 +139,9 @@ } // namespace +const base::Feature kIncompatibleApplicationsWarning{ + "IncompatibleApplicationsWarning", base::FEATURE_DISABLED_BY_DEFAULT}; + // ProblematicProgram ---------------------------------------------------------- ProblematicProgramsUpdater::ProblematicProgram::ProblematicProgram( @@ -157,14 +160,6 @@ // ProblematicProgramsUpdater -------------------------------------------------- -ProblematicProgramsUpdater::ProblematicProgramsUpdater( - const ModuleListFilter& module_list_filter, - const InstalledPrograms& installed_programs) - : module_list_filter_(module_list_filter), - installed_programs_(installed_programs) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); -} - ProblematicProgramsUpdater::~ProblematicProgramsUpdater() = default; // static @@ -174,16 +169,37 @@ } // static -bool ProblematicProgramsUpdater::IsIncompatibleApplicationsWarningEnabled() { - return ModuleDatabase::GetInstance() && - ModuleDatabase::GetInstance()->third_party_conflicts_manager(); +std::unique_ptr<ProblematicProgramsUpdater> +ProblematicProgramsUpdater::MaybeCreate( + const ModuleListFilter& module_list_filter, + const InstalledPrograms& installed_programs) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + std::unique_ptr<ProblematicProgramsUpdater> instance; + + if (base::FeatureList::IsEnabled(kIncompatibleApplicationsWarning)) { + instance.reset( + new ProblematicProgramsUpdater(module_list_filter, installed_programs)); + } + + return instance; } // static bool ProblematicProgramsUpdater::HasCachedPrograms() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - return !GetCachedPrograms().empty(); + if (!base::FeatureList::IsEnabled(kIncompatibleApplicationsWarning)) + return false; + + std::vector<ProblematicProgram> programs = ConvertToProblematicProgramsVector( + *g_browser_process->local_state() + ->FindPreference(prefs::kProblematicPrograms) + ->GetValue()); + + RemoveStaleEntriesAndUpdateCache(&programs); + + return !programs.empty(); } // static @@ -191,7 +207,12 @@ ProblematicProgramsUpdater::GetCachedPrograms() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - std::vector<ProblematicProgram> programs = ConvertToProblematicProgramsVector( + std::vector<ProblematicProgram> programs; + + if (!base::FeatureList::IsEnabled(kIncompatibleApplicationsWarning)) + return programs; + + programs = ConvertToProblematicProgramsVector( *g_browser_process->local_state() ->FindPreference(prefs::kProblematicPrograms) ->GetValue()); @@ -273,3 +294,9 @@ std::move(element.second)); } } + +ProblematicProgramsUpdater::ProblematicProgramsUpdater( + const ModuleListFilter& module_list_filter, + const InstalledPrograms& installed_programs) + : module_list_filter_(module_list_filter), + installed_programs_(installed_programs) {}
diff --git a/chrome/browser/conflicts/problematic_programs_updater_win.h b/chrome/browser/conflicts/problematic_programs_updater_win.h index f0f579a..90ffabe3 100644 --- a/chrome/browser/conflicts/problematic_programs_updater_win.h +++ b/chrome/browser/conflicts/problematic_programs_updater_win.h
@@ -8,19 +8,28 @@ #include <memory> #include <vector> +#include "base/feature_list.h" #include "base/macros.h" #include "chrome/browser/conflicts/installed_programs_win.h" #include "chrome/browser/conflicts/module_database_observer_win.h" #include "chrome/browser/conflicts/proto/module_list.pb.h" +#include "url/gurl.h" class ModuleListFilter; class PrefRegistrySimple; +// A feature that controls whether Chrome warns about incompatible applications. +extern const base::Feature kIncompatibleApplicationsWarning; + // Maintains a list of problematic programs that are installed on the machine. // These programs cause unwanted DLLs to be loaded into Chrome. // // Because the list is expensive to build, it is cached into the Local State // file so that it is available at startup. +// +// When kIncompatibleApplicationsWarning is disabled, this class always behaves +// as-if there are no problematic programs on the computer. This makes it safe +// to use all of the class' static functions unconditionally. class ProblematicProgramsUpdater : public ModuleDatabaseObserver { public: struct ProblematicProgram { @@ -37,24 +46,22 @@ std::unique_ptr<chrome::conflicts::BlacklistAction> blacklist_action; }; - // Creates an instance of the updater. |module_list_filter| and - // |installed_programs| must outlive the lifetime of this class. - ProblematicProgramsUpdater(const ModuleListFilter& module_list_filter, - const InstalledPrograms& installed_programs); ~ProblematicProgramsUpdater() override; static void RegisterLocalStatePrefs(PrefRegistrySimple* registry); - // Returns true if the tracking of incompatible applications is enabled. The - // return value will not change throughout the lifetime of the process. - static bool IsIncompatibleApplicationsWarningEnabled(); + // Creates an instance of the updater. Returns nullptr if the + // kIncompatibleApplicationsWarning experiment is disabled. + // + // |installed_programs| must outlive the lifetime of this class. + static std::unique_ptr<ProblematicProgramsUpdater> MaybeCreate( + const ModuleListFilter& module_list_filter, + const InstalledPrograms& installed_programs); // Returns true if the cache contains at least one problematic program. - // Only call this if IsIncompatibleApplicationsWarningEnabled() returns true. static bool HasCachedPrograms(); // Returns all the cached problematic programs. - // Only call this if IsIncompatibleApplicationsWarningEnabled() returns true. static std::vector<ProblematicProgram> GetCachedPrograms(); // ModuleDatabaseObserver: @@ -63,6 +70,9 @@ void OnModuleDatabaseIdle() override; private: + ProblematicProgramsUpdater(const ModuleListFilter& module_list_filter, + const InstalledPrograms& installed_programs); + const ModuleListFilter& module_list_filter_; const InstalledPrograms& installed_programs_;
diff --git a/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc b/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc index 719aeaf3..faa57f8 100644 --- a/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc +++ b/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc
@@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" +#include "base/test/scoped_feature_list.h" #include "base/test/test_reg_util_win.h" #include "base/win/registry.h" #include "chrome/browser/conflicts/module_info_win.h" @@ -95,6 +96,7 @@ void SetUp() override { ASSERT_NO_FATAL_FAILURE( registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER)); + scoped_feature_list_.InitAndEnableFeature(kIncompatibleApplicationsWarning); } enum class Option { @@ -128,10 +130,15 @@ private: content::TestBrowserThreadBundle test_browser_thread_bundle_; + + base::test::ScopedFeatureList scoped_feature_list_; + ScopedTestingLocalState scoped_testing_local_state_; + registry_util::RegistryOverrideManager registry_override_manager_; MockModuleListFilter module_list_filter_; + MockInstalledPrograms installed_programs_; DISALLOW_COPY_AND_ASSIGN(ProblematicProgramsUpdaterTest); @@ -147,9 +154,8 @@ // ProblematicProgramsUpdater doesn't do anything when there is no registered // installed programs. TEST_F(ProblematicProgramsUpdaterTest, NoProblematicPrograms) { - auto problematic_programs_updater = - std::make_unique<ProblematicProgramsUpdater>(module_list_filter(), - installed_programs()); + auto problematic_programs_updater = ProblematicProgramsUpdater::MaybeCreate( + module_list_filter(), installed_programs()); // Simulate some arbitrary module loading into the process. problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0), @@ -163,9 +169,8 @@ TEST_F(ProblematicProgramsUpdaterTest, OneConflict) { AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY); - auto problematic_programs_updater = - std::make_unique<ProblematicProgramsUpdater>(module_list_filter(), - installed_programs()); + auto problematic_programs_updater = ProblematicProgramsUpdater::MaybeCreate( + module_list_filter(), installed_programs()); // Simulate the module loading into the process. problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0), @@ -182,9 +187,8 @@ AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY); AddProblematicProgram(dll2_, L"Bar", Option::ADD_REGISTRY_ENTRY); - auto problematic_programs_updater = - std::make_unique<ProblematicProgramsUpdater>(module_list_filter(), - installed_programs()); + auto problematic_programs_updater = ProblematicProgramsUpdater::MaybeCreate( + module_list_filter(), installed_programs()); // Simulate the module loading into the process. problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0), @@ -210,9 +214,8 @@ TEST_F(ProblematicProgramsUpdaterTest, PersistsThroughRestarts) { AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY); - auto problematic_programs_updater = - std::make_unique<ProblematicProgramsUpdater>(module_list_filter(), - installed_programs()); + auto problematic_programs_updater = ProblematicProgramsUpdater::MaybeCreate( + module_list_filter(), installed_programs()); // Simulate the module loading into the process. problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0), @@ -232,9 +235,8 @@ AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY); AddProblematicProgram(dll2_, L"Bar", Option::NO_REGISTRY_ENTRY); - auto problematic_programs_updater = - std::make_unique<ProblematicProgramsUpdater>(module_list_filter(), - installed_programs()); + auto problematic_programs_updater = ProblematicProgramsUpdater::MaybeCreate( + module_list_filter(), installed_programs()); // Simulate the modules loading into the process. problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
diff --git a/chrome/browser/conflicts/third_party_conflicts_manager_win.cc b/chrome/browser/conflicts/third_party_conflicts_manager_win.cc index 08b85293..0f1e100 100644 --- a/chrome/browser/conflicts/third_party_conflicts_manager_win.cc +++ b/chrome/browser/conflicts/third_party_conflicts_manager_win.cc
@@ -97,8 +97,8 @@ void ThirdPartyConflictsManager::InitializeProblematicProgramsUpdater() { DCHECK(module_list_filter_); DCHECK(installed_programs_); - - problematic_programs_updater_ = std::make_unique<ProblematicProgramsUpdater>( + problematic_programs_updater_ = ProblematicProgramsUpdater::MaybeCreate( *module_list_filter_, *installed_programs_); - module_database_->AddObserver(problematic_programs_updater_.get()); + if (problematic_programs_updater_) + module_database_->AddObserver(problematic_programs_updater_.get()); }
diff --git a/chrome/browser/devtools/devtools_eye_dropper.cc b/chrome/browser/devtools/devtools_eye_dropper.cc index b7a00c15..e412ed86 100644 --- a/chrome/browser/devtools/devtools_eye_dropper.cc +++ b/chrome/browser/devtools/devtools_eye_dropper.cc
@@ -70,6 +70,8 @@ false); video_capturer_->SetAutoThrottlingEnabled(false); video_capturer_->SetMinSizeChangePeriod(base::TimeDelta()); + video_capturer_->SetFormat(media::PIXEL_FORMAT_ARGB, + media::COLOR_SPACE_UNSPECIFIED); video_capturer_->SetMinCapturePeriod(base::TimeDelta::FromSeconds(1) / kMaxFrameRate); @@ -324,22 +326,17 @@ DLOG(ERROR) << "Shared memory mapping failed."; return; } - scoped_refptr<media::VideoFrame> frame = media::VideoFrame::WrapExternalData( - info->pixel_format, info->coded_size, info->visible_rect, - info->visible_rect.size(), static_cast<uint8_t*>(mapping.get()), - buffer_size, info->timestamp); - if (!frame) - return; - frame->AddDestructionObserver(base::BindOnce( - [](mojo::ScopedSharedBufferMapping mapping) {}, std::move(mapping))); - SkBitmap skbitmap; - skbitmap.allocN32Pixels(info->visible_rect.width(), - info->visible_rect.height()); - cc::SkiaPaintCanvas canvas(skbitmap); - video_renderer_.Copy(frame, &canvas, media::Context3D()); + SkImageInfo image_info = SkImageInfo::MakeN32( + content_rect.width(), content_rect.height(), kPremul_SkAlphaType); + SkPixmap pixmap(image_info, mapping.get(), + media::VideoFrame::RowBytes(media::VideoFrame::kARGBPlane, + info->pixel_format, + info->coded_size.width())); + frame_.installPixels(pixmap); + shared_memory_mapping_ = std::move(mapping); + shared_memory_releaser_ = std::move(callbacks); - frame_ = skbitmap; UpdateCursor(); }
diff --git a/chrome/browser/devtools/devtools_eye_dropper.h b/chrome/browser/devtools/devtools_eye_dropper.h index 9650051..7d5eaef 100644 --- a/chrome/browser/devtools/devtools_eye_dropper.h +++ b/chrome/browser/devtools/devtools_eye_dropper.h
@@ -55,6 +55,13 @@ void OnTargetLost(const viz::FrameSinkId& frame_sink_id) override; void OnStopped() override; + // This object keeps the shared memory that backs |frame_| mapped. + mojo::ScopedSharedBufferMapping shared_memory_mapping_; + + // This object prevents FrameSinkVideoCapturer from recycling the shared + // memory that backs |frame_|. + viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr shared_memory_releaser_; + EyeDropperCallback callback_; SkBitmap frame_; int last_cursor_x_;
diff --git a/chrome/browser/devtools/devtools_file_system_indexer.cc b/chrome/browser/devtools/devtools_file_system_indexer.cc index 576a6206..4c7ad3ce 100644 --- a/chrome/browser/devtools/devtools_file_system_indexer.cc +++ b/chrome/browser/devtools/devtools_file_system_indexer.cc
@@ -77,6 +77,8 @@ const Time& time); vector<FilePath> Search(const string& query); void NormalizeVectors(); + void Reset(); + void EnsureInitialized(); private: FileId GetFileId(const FilePath& file_path); @@ -148,6 +150,20 @@ } Index::Index() : last_file_id_(0) { + Reset(); +} + +void Index::Reset() { + file_ids_.clear(); + index_.clear(); + index_times_.clear(); + is_normalized_.clear(); + last_file_id_ = 0; +} + +void Index::EnsureInitialized() { + if (index_.size() != 0) + return; index_.resize(kTrigramCount); is_normalized_.resize(kTrigramCount); std::fill(is_normalized_.begin(), is_normalized_.end(), true); @@ -155,6 +171,7 @@ Time Index::LastModifiedTimeForFile(const FilePath& file_path) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + EnsureInitialized(); Time last_modified_time; if (index_times_.find(file_path) != index_times_.end()) last_modified_time = index_times_[file_path]; @@ -165,6 +182,7 @@ const vector<Trigram>& index, const Time& time) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + EnsureInitialized(); FileId file_id = GetFileId(file_path); vector<Trigram>::const_iterator it = index.begin(); for (; it != index.end(); ++it) { @@ -177,6 +195,7 @@ vector<FilePath> Index::Search(const string& query) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + EnsureInitialized(); const char* data = query.c_str(); vector<TrigramChar> trigram_chars; trigram_chars.reserve(query.size()); @@ -221,6 +240,7 @@ FileId Index::GetFileId(const FilePath& file_path) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + EnsureInitialized(); string file_path_str = file_path.AsUTF8Unsafe(); if (file_ids_.find(file_path) != file_ids_.end()) return file_ids_[file_path]; @@ -230,6 +250,7 @@ void Index::NormalizeVectors() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + EnsureInitialized(); for (size_t i = 0; i < kTrigramCount; ++i) { if (!is_normalized_[i]) { std::sort(index_[i].begin(), index_[i].end()); @@ -409,9 +430,19 @@ } } -DevToolsFileSystemIndexer::DevToolsFileSystemIndexer() {} +static int g_instance_count = 0; -DevToolsFileSystemIndexer::~DevToolsFileSystemIndexer() {} +DevToolsFileSystemIndexer::DevToolsFileSystemIndexer() { + ++g_instance_count; +} + +DevToolsFileSystemIndexer::~DevToolsFileSystemIndexer() { + --g_instance_count; + if (!g_instance_count) { + impl_task_runner()->PostTask( + FROM_HERE, base::BindOnce([]() { g_trigram_index.Get().Reset(); })); + } +} scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob> DevToolsFileSystemIndexer::IndexPath(
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 0070301..0846b6e 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -65,15 +65,19 @@ // controlled or owner controlled. return true; } +#endif -bool IsCrosSettingReadOnly(const std::string& pref_name) { - if (chromeos::system::PerUserTimezoneEnabled()) { - // System timezone is never directly changable by user. - return pref_name == chromeos::kSystemTimezone; - } +bool IsSettingReadOnly(const std::string& pref_name) { +#if defined(OS_CHROMEOS) + // System timezone is never directly changable by the user. + if (pref_name == chromeos::kSystemTimezone) + return chromeos::system::PerUserTimezoneEnabled(); + // enable_screen_lock must be changed through the quickUnlockPrivate API. + if (pref_name == ::prefs::kEnableAutoScreenLock) + return true; +#endif return false; } -#endif } // namespace @@ -254,6 +258,7 @@ settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[chromeos::kAccountsPrefUsers] = settings_api::PrefType::PREF_TYPE_LIST; + // kEnableAutoScreenLock is read-only. (*s_whitelist)[::prefs::kEnableAutoScreenLock] = settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[::prefs::kEnableQuickUnlockFingerprint] = @@ -804,10 +809,8 @@ } bool PrefsUtil::IsPrefUserModifiable(const std::string& pref_name) { -#if defined(OS_CHROMEOS) - if (IsCrosSettingReadOnly(pref_name)) + if (IsSettingReadOnly(pref_name)) return false; -#endif const PrefService::Preference* profile_pref = profile_->GetPrefs()->FindPreference(pref_name);
diff --git a/chrome/browser/extensions/context_menu_matcher.cc b/chrome/browser/extensions/context_menu_matcher.cc index e950cf6..caab407 100644 --- a/chrome/browser/extensions/context_menu_matcher.cc +++ b/chrome/browser/extensions/context_menu_matcher.cc
@@ -12,6 +12,7 @@ #include "content/public/browser/browser_context.h" #include "content/public/common/context_menu_params.h" #include "extensions/browser/extension_registry.h" +#include "ui/base/ui_base_features.h" #include "ui/gfx/favicon_size.h" #include "ui/gfx/image/image.h" @@ -74,7 +75,10 @@ // If this is the first extension-provided menu item, and there are other // items in the menu, and the last item is not a separator add a separator. - bool prepend_separator = *index == 0 && menu_model_->GetItemCount(); + // Separators are not required when the context menu is a touchable app + // context menu. + const bool prepend_separator = *index == 0 && menu_model_->GetItemCount() && + !features::IsTouchableAppContextMenuEnabled(); // Extensions (other than platform apps) are only allowed one top-level slot // (and it can't be a radio or checkbox item because we are going to put the @@ -259,13 +263,17 @@ int radio_group_id = 1; int num_visible_items = 0; + // Separators are not required when the context menu is a touchable app + // context menu. + const bool enable_separators = !features::IsTouchableAppContextMenuEnabled(); + for (auto i = items.begin(); i != items.end(); ++i) { MenuItem* item = *i; // If last item was of type radio but the current one isn't, auto-insert // a separator. The converse case is handled below. - if (last_type == MenuItem::RADIO && - item->type() != MenuItem::RADIO) { + if (last_type == MenuItem::RADIO && item->type() != MenuItem::RADIO && + enable_separators) { menu_model->AddSeparator(ui::NORMAL_SEPARATOR); last_type = MenuItem::SEPARATOR; } @@ -307,11 +315,12 @@ radio_group_id++; // Auto-append a separator if needed. - menu_model->AddSeparator(ui::NORMAL_SEPARATOR); + if (enable_separators) + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); } menu_model->AddRadioItem(menu_id, title, radio_group_id); - } else if (item->type() == MenuItem::SEPARATOR) { + } else if (item->type() == MenuItem::SEPARATOR && enable_separators) { menu_model->AddSeparator(ui::NORMAL_SEPARATOR); } last_type = item->type();
diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc index 74c8c05..a96fbe0 100644 --- a/chrome/browser/infobars/infobars_browsertest.cc +++ b/chrome/browser/infobars/infobars_browsertest.cc
@@ -10,6 +10,7 @@ #include "base/optional.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "build/buildflag.h" #include "chrome/browser/banners/app_banner_infobar_delegate_desktop.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/devtools/devtools_infobar_delegate.h" @@ -56,6 +57,7 @@ #include "extensions/browser/test_extension_registry_observer.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/ui_features.h" #if !defined(OS_CHROMEOS) #include "chrome/browser/ui/startup/default_browser_infobar_delegate.h" @@ -589,7 +591,7 @@ ShowAndVerifyUi(); } -#if defined(OS_MACOSX) +#if defined(OS_MACOSX) && !BUILDFLAG(MAC_VIEWS_BROWSER) IN_PROC_BROWSER_TEST_F(InfoBarUiTest, InvokeUi_session_crashed) { ShowAndVerifyUi(); }
diff --git a/chrome/browser/interstitials/chrome_metrics_helper.cc b/chrome/browser/interstitials/chrome_metrics_helper.cc index 41585e9b..7b00fc3 100644 --- a/chrome/browser/interstitials/chrome_metrics_helper.cc +++ b/chrome/browser/interstitials/chrome_metrics_helper.cc
@@ -10,7 +10,6 @@ #include "chrome/common/buildflags.h" #include "components/history/core/browser/history_service.h" #include "content/public/browser/web_contents.h" -#include "extensions/buildflags/buildflags.h" #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) #include "chrome/browser/ssl/captive_portal_metrics_recorder.h" @@ -26,7 +25,7 @@ HistoryServiceFactory::GetForProfile( Profile::FromBrowserContext(web_contents->GetBrowserContext()), ServiceAccessType::EXPLICIT_ACCESS)), -#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) || BUILDFLAG(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) web_contents_(web_contents), #endif request_url_(request_url) {
diff --git a/chrome/browser/interstitials/chrome_metrics_helper.h b/chrome/browser/interstitials/chrome_metrics_helper.h index caed2b8..f51fd64e 100644 --- a/chrome/browser/interstitials/chrome_metrics_helper.h +++ b/chrome/browser/interstitials/chrome_metrics_helper.h
@@ -10,7 +10,6 @@ #include "base/macros.h" #include "chrome/common/buildflags.h" #include "components/security_interstitials/core/metrics_helper.h" -#include "extensions/buildflags/buildflags.h" #include "url/gurl.h" namespace content { @@ -39,7 +38,7 @@ void RecordExtraShutdownMetrics() override; private: -#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) || BUILDFLAG(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) content::WebContents* web_contents_; #endif const GURL request_url_;
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 6c03ace2..29f5845b 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -427,12 +427,6 @@ return globals_; } -void IOThread::SetGlobalsForTesting(Globals* globals) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(!globals || !globals_); - globals_ = globals; -} - net_log::ChromeNetLog* IOThread::net_log() { return net_log_; }
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index 05be580..12e8246 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h
@@ -165,11 +165,6 @@ // Can only be called on the IO thread. Globals* globals(); - // Allows overriding Globals in tests where IOThread::Init() and - // IOThread::CleanUp() are not called. This allows for injecting mocks into - // IOThread global objects. - void SetGlobalsForTesting(Globals* globals); - net_log::ChromeNetLog* net_log(); // Handles changing to On The Record mode, discarding confidential data.
diff --git a/chrome/browser/media/webrtc/webrtc_browsertest_base.cc b/chrome/browser/media/webrtc/webrtc_browsertest_base.cc index 6f39913..b49ae90 100644 --- a/chrome/browser/media/webrtc/webrtc_browsertest_base.cc +++ b/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
@@ -388,6 +388,17 @@ EXPECT_EQ("ok-peerconnection-created", ExecuteJavascript(javascript, tab)); } +void WebRtcTestBase::SetupPeerconnectionWithConstraintsAndLocalStream( + content::WebContents* tab, + const std::string& constraints, + const std::string& certificate_keygen_algorithm) const { + std::string javascript = base::StringPrintf( + "preparePeerConnection(%s, %s)", certificate_keygen_algorithm.c_str(), + constraints.c_str()); + EXPECT_EQ("ok-peerconnection-created", ExecuteJavascript(javascript, tab)); + EXPECT_EQ("ok-added", ExecuteJavascript("addLocalStream()", tab)); +} + std::string WebRtcTestBase::CreateLocalOffer( content::WebContents* from_tab) const { std::string response = ExecuteJavascript("createLocalOffer({})", from_tab);
diff --git a/chrome/browser/media/webrtc/webrtc_browsertest_base.h b/chrome/browser/media/webrtc/webrtc_browsertest_base.h index 0c12cbfd..e2f9975 100644 --- a/chrome/browser/media/webrtc/webrtc_browsertest_base.h +++ b/chrome/browser/media/webrtc/webrtc_browsertest_base.h
@@ -147,6 +147,13 @@ void SetupPeerconnectionWithCertificateWithoutLocalStream( content::WebContents* tab, const std::string& certificate) const; + // Same as |SetupPeerconnectionWithLocalStream| except RTCPeerConnection + // constraints are specified. + void SetupPeerconnectionWithConstraintsAndLocalStream( + content::WebContents* tab, + const std::string& constraints, + const std::string& certificate_keygen_algorithm = + kUseDefaultCertKeygen) const; void CreateDataChannel(content::WebContents* tab, const std::string& label);
diff --git a/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc b/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc index 00bdd82..f87ff67 100644 --- a/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc +++ b/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc
@@ -152,8 +152,12 @@ const int process_id = base::GetProcId( right_tab->GetRenderViewHost()->GetProcess()->GetHandle()); - SetupPeerconnectionWithLocalStream(left_tab); - SetupPeerconnectionWithLocalStream(right_tab); + const std::string disable_cpu_adaptation_constraint( + "{'optional': [{'googCpuOveruseDetection': false}]}"); + SetupPeerconnectionWithConstraintsAndLocalStream( + left_tab, disable_cpu_adaptation_constraint); + SetupPeerconnectionWithConstraintsAndLocalStream( + right_tab, disable_cpu_adaptation_constraint); if (!video_codec.empty()) { SetDefaultVideoCodec(left_tab, video_codec,
diff --git a/chrome/browser/metrics/BUILD.gn b/chrome/browser/metrics/BUILD.gn index dac8ad8..5401072 100644 --- a/chrome/browser/metrics/BUILD.gn +++ b/chrome/browser/metrics/BUILD.gn
@@ -12,4 +12,5 @@ namespace = "chrome_metrics" header_filename = "expired_histograms_array.h" major_branch_date_filepath = "//chrome/MAJOR_BRANCH_DATE" + milestone_filepath = "//chrome/VERSION" }
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc index 5e9f503..3d418fcf 100644 --- a/chrome/browser/net/profile_network_context_service.cc +++ b/chrome/browser/net/profile_network_context_service.cc
@@ -67,6 +67,18 @@ return network_context; } +network::mojom::NetworkContextPtr +ProfileNetworkContextService::CreateNetworkContextForPartition( + bool in_memory, + const base::FilePath& relative_partition_path) { + DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); + network::mojom::NetworkContextPtr network_context; + content::GetNetworkService()->CreateNetworkContext( + MakeRequest(&network_context), + CreateNetworkContextParams(in_memory, relative_partition_path)); + return network_context; +} + void ProfileNetworkContextService::SetUpProfileIODataMainContext( network::mojom::NetworkContextRequest* network_context_request, network::mojom::NetworkContextParamsPtr* network_context_params) { @@ -125,6 +137,14 @@ network::mojom::NetworkContextParamsPtr ProfileNetworkContextService::CreateMainNetworkContextParams() { + return CreateNetworkContextParams(profile_->IsOffTheRecord(), + base::FilePath()); +} + +network::mojom::NetworkContextParamsPtr +ProfileNetworkContextService::CreateNetworkContextParams( + bool in_memory, + const base::FilePath& relative_partition_path) { // TODO(mmenke): Set up parameters here. network::mojom::NetworkContextParamsPtr network_context_params = CreateDefaultNetworkContextParams(); @@ -136,13 +156,17 @@ // Always enable the HTTP cache. network_context_params->http_cache_enabled = true; + base::FilePath path = profile_->GetPath(); + if (!relative_partition_path.empty()) + path = path.Append(relative_partition_path); + // Configure on-disk storage for non-OTR profiles. OTR profiles just use // default behavior (in memory storage, default sizes). PrefService* prefs = profile_->GetPrefs(); - if (!profile_->IsOffTheRecord()) { + if (!in_memory) { // Configure the HTTP cache path and size. base::FilePath base_cache_path; - chrome::GetUserCacheDirectory(profile_->GetPath(), &base_cache_path); + chrome::GetUserCacheDirectory(path, &base_cache_path); base::FilePath disk_cache_dir = prefs->GetFilePath(prefs::kDiskCacheDir); if (!disk_cache_dir.empty()) base_cache_path = disk_cache_dir.Append(base_cache_path.BaseName()); @@ -154,20 +178,26 @@ // Currently this just contains HttpServerProperties, but that will likely // change. network_context_params->http_server_properties_path = - profile_->GetPath().Append(chrome::kNetworkPersistentStateFilename); + path.Append(chrome::kNetworkPersistentStateFilename); - base::FilePath cookie_path = profile_->GetPath(); + base::FilePath cookie_path = path; cookie_path = cookie_path.Append(chrome::kCookieFilename); network_context_params->cookie_path = cookie_path; - base::FilePath channel_id_path = profile_->GetPath(); + base::FilePath channel_id_path = path; channel_id_path = channel_id_path.Append(chrome::kChannelIDFilename); network_context_params->channel_id_path = channel_id_path; - network_context_params->restore_old_session_cookies = - profile_->ShouldRestoreOldSessionCookies(); - network_context_params->persist_session_cookies = - profile_->ShouldPersistSessionCookies(); + if (relative_partition_path.empty()) { + network_context_params->restore_old_session_cookies = + profile_->ShouldRestoreOldSessionCookies(); + network_context_params->persist_session_cookies = + profile_->ShouldPersistSessionCookies(); + } else { + // Copy behavior of ProfileImplIOData::InitializeAppRequestContext. + network_context_params->restore_old_session_cookies = false; + network_context_params->persist_session_cookies = false; + } } // NOTE(mmenke): Keep these protocol handlers and
diff --git a/chrome/browser/net/profile_network_context_service.h b/chrome/browser/net/profile_network_context_service.h index d663b63..eb53691 100644 --- a/chrome/browser/net/profile_network_context_service.h +++ b/chrome/browser/net/profile_network_context_service.h
@@ -30,6 +30,12 @@ // SetUpProfileIODataMainContext. network::mojom::NetworkContextPtr CreateMainNetworkContext(); + // Create a network context for the given |relative_parition_path|. This is + // only used when the network service is enabled for now. + network::mojom::NetworkContextPtr CreateNetworkContextForPartition( + bool in_memory, + const base::FilePath& relative_partition_path); + // Initializes |*network_context_params| to set up the ProfileIOData's // main URLRequestContext and |*network_context_request| to be one end of a // Mojo pipe to be bound to the NetworkContext for that URLRequestContext. @@ -73,6 +79,13 @@ // it initializes some class members. network::mojom::NetworkContextParamsPtr CreateMainNetworkContextParams(); + // Creates parameters for the NetworkContext. Use |in_memory| instead of + // |profile_->IsOffTheRecord()| because sometimes normal profiles want off the + // record partitions (e.g. for webview tag). + network::mojom::NetworkContextParamsPtr CreateNetworkContextParams( + bool in_memory, + const base::FilePath& relative_partition_path); + Profile* const profile_; ProxyConfigMonitor proxy_config_monitor_;
diff --git a/chrome/browser/notifications/notification_launch_id.h b/chrome/browser/notifications/notification_launch_id.h index 8cc5322c..2a40e64 100644 --- a/chrome/browser/notifications/notification_launch_id.h +++ b/chrome/browser/notifications/notification_launch_id.h
@@ -16,6 +16,7 @@ NotificationLaunchId(); NotificationLaunchId(const NotificationLaunchId& other); + // |notification_id| and |profile_id| must be UTF8 strings. NotificationLaunchId(NotificationHandler::Type notification_type, const std::string& notification_id, const std::string& profile_id, @@ -48,40 +49,61 @@ DCHECK(is_valid()); return notification_type_; } + const std::string& notification_id() const { DCHECK(is_valid()); return notification_id_; } + const std::string& profile_id() const { DCHECK(is_valid()); return profile_id_; } + bool incognito() const { DCHECK(is_valid()); return incognito_; } + const GURL& origin_url() const { DCHECK(is_valid()); return origin_url_; } + int button_index() const { DCHECK(is_valid()); return button_index_; } + bool is_for_context_menu() const { DCHECK(is_valid()); return is_for_context_menu_; } private: + // The notification type this launch ID is associated with. NotificationHandler::Type notification_type_; + + // The notification id this launch ID is associated with. The string is UTF8. std::string notification_id_; + + // The profile id this launch ID is associated with. The string is UTF8. std::string profile_id_; + + // A flat indicating if the notification associated with this launch ID is in + // incognito mode or not. bool incognito_ = false; + + // The original URL this launch ID is associated with. GURL origin_url_; + + // The button index this launch ID is associated with. int button_index_ = -1; + + // A flag indicating if this launch ID is targeting for context menu or not. bool is_for_context_menu_ = false; + // A flag indicating if this launch ID is valid. bool is_valid_ = false; };
diff --git a/chrome/browser/notifications/notification_platform_bridge_win.cc b/chrome/browser/notifications/notification_platform_bridge_win.cc index 65a01d49..577e8df 100644 --- a/chrome/browser/notifications/notification_platform_bridge_win.cc +++ b/chrome/browser/notifications/notification_platform_bridge_win.cc
@@ -748,8 +748,8 @@ const base::CommandLine& command_line) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - NotificationLaunchId launch_id( - command_line.GetSwitchValueASCII(switches::kNotificationLaunchId)); + NotificationLaunchId launch_id(base::UTF16ToUTF8( + command_line.GetSwitchValueNative(switches::kNotificationLaunchId))); if (!launch_id.is_valid()) return false; @@ -773,8 +773,8 @@ // static std::string NotificationPlatformBridgeWin::GetProfileIdFromLaunchId( - const std::string& launch_id_str) { - NotificationLaunchId launch_id(launch_id_str); + const base::string16& launch_id_str) { + NotificationLaunchId launch_id(base::UTF16ToUTF8(launch_id_str)); return launch_id.is_valid() ? launch_id.profile_id() : std::string(); }
diff --git a/chrome/browser/notifications/notification_platform_bridge_win.h b/chrome/browser/notifications/notification_platform_bridge_win.h index fab79ac4..cf2e778 100644 --- a/chrome/browser/notifications/notification_platform_bridge_win.h +++ b/chrome/browser/notifications/notification_platform_bridge_win.h
@@ -48,7 +48,8 @@ static bool HandleActivation(const base::CommandLine& command_line); // Extracts the profile ID from |launch_id_str|. - static std::string GetProfileIdFromLaunchId(const std::string& launch_id_str); + static std::string GetProfileIdFromLaunchId( + const base::string16& launch_id_str); // Checks if native notification is enabled. static bool NativeNotificationEnabled();
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 91b4eb6..a1bb49f 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -272,7 +272,6 @@ #include "chrome/browser/apps/app_launch_for_metro_restart_win.h" #include "chrome/browser/component_updater/sw_reporter_installer_win.h" #if defined(GOOGLE_CHROME_BUILD) -#include "chrome/browser/conflicts/module_database_win.h" #include "chrome/browser/conflicts/problematic_programs_updater_win.h" #endif // defined(GOOGLE_CHROME_BUILD) #include "chrome/browser/safe_browsing/chrome_cleaner/settings_resetter_win.h" @@ -467,7 +466,6 @@ desktop_ios_promotion::RegisterLocalPrefs(registry); password_manager::PasswordManager::RegisterLocalPrefs(registry); #if defined(GOOGLE_CHROME_BUILD) - ModuleDatabase::RegisterLocalStatePrefs(registry); ProblematicProgramsUpdater::RegisterLocalStatePrefs(registry); #endif // defined(GOOGLE_CHROME_BUILD) #endif
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index 98bd3dc6..e7f8c66 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -1482,9 +1482,3 @@ return base::WrapUnique<net::NetworkDelegate>( chrome_network_delegate.release()); } - -void ProfileIOData::SetCookieSettingsForTesting( - content_settings::CookieSettings* cookie_settings) { - DCHECK(!cookie_settings_.get()); - cookie_settings_ = cookie_settings; -}
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h index 0fa7a65..176ae1f93 100644 --- a/chrome/browser/profiles/profile_io_data.h +++ b/chrome/browser/profiles/profile_io_data.h
@@ -460,9 +460,6 @@ net::HttpTransactionFactory* main_http_factory, std::unique_ptr<net::HttpCache::BackendFactory> backend) const; - void SetCookieSettingsForTesting( - content_settings::CookieSettings* cookie_settings); - private: class ResourceContext : public content::ResourceContext { public:
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 9bbe0de..d6efe0a 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -2417,7 +2417,8 @@ headers = data_reduction_proxy::chrome_proxy_pass_through_header(); } - source_web_contents_->SaveFrameWithHeaders(url, referrer, headers); + source_web_contents_->SaveFrameWithHeaders(url, referrer, headers, + params_.suggested_filename); } }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc index 1409c10..085556b 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc
@@ -553,3 +553,30 @@ DestroyDataReductionProxySettings(); } + +// Verify that the suggested file name is propagated to web contents when save a +// media file in context menu. +TEST_F(RenderViewContextMenuPrefsTest, SaveMediaSuggestedFileName) { + const base::string16 kTestSuggestedFileName = base::ASCIIToUTF16("test_file"); + content::ContextMenuParams params = CreateParams(MenuItem::VIDEO); + params.suggested_filename = kTestSuggestedFileName; + auto menu = std::make_unique<TestRenderViewContextMenu>( + web_contents()->GetMainFrame(), params); + menu->ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEAVAS, 0 /* event_flags */); + + // Video item should have suggested file name. + base::string16 suggested_filename = + content::WebContentsTester::For(web_contents())->GetSuggestedFileName(); + EXPECT_EQ(kTestSuggestedFileName, suggested_filename); + + params = CreateParams(MenuItem::AUDIO); + params.suggested_filename = kTestSuggestedFileName; + menu = std::make_unique<TestRenderViewContextMenu>( + web_contents()->GetMainFrame(), params); + menu->ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEAVAS, 0 /* event_flags */); + + // Audio item should have suggested file name. + suggested_filename = + content::WebContentsTester::For(web_contents())->GetSuggestedFileName(); + EXPECT_EQ(kTestSuggestedFileName, suggested_filename); +}
diff --git a/chrome/browser/resource_coordinator/tab_manager_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_unittest.cc index d201205..0210b78 100644 --- a/chrome/browser/resource_coordinator/tab_manager_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_unittest.cc
@@ -1294,10 +1294,10 @@ // |ignored_web_contents| is not managed by TabManager, thus will be ignored // and shouldn't cause any crash or side effect. - WebContents* ignored_web_contents = - WebContentsTester::CreateTestWebContents(browser_context(), nullptr); + std::unique_ptr<WebContents> ignored_web_contents( + WebContentsTester::CreateTestWebContents(browser_context(), nullptr)); tab_manager_->resource_coordinator_signal_observer_->OnPageAlmostIdle( - ignored_web_contents); + ignored_web_contents.get()); EXPECT_TRUE(tab_manager_->IsTabLoadingForTest(contents3_.get())); EXPECT_FALSE(tab_manager_->IsNavigationDelayedForTest(nav_handle3_.get())); }
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.css new file mode 100644 index 0000000..25fe468 --- /dev/null +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.css
@@ -0,0 +1,10 @@ +/* Copyright 2018 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +#value-prop { + display: flex; + flex-flow: column; + font-size: 16px; + width: 576px; +}
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html new file mode 100644 index 0000000..566bc9a --- /dev/null +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html
@@ -0,0 +1,47 @@ +<!-- Copyright 2018 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<!doctype html> +<html i18n-values="dir:textdirection;lang:language"> +<head> +<meta charset="utf-8"> + +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://oobe/custom_elements.html"> +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/html/util.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> + +<include src="../login/oobe_buttons.html"> +<include src="../login/oobe_change_picture.html"> +<include src="../login/oobe_dialog.html"> +<include src="assistant_value_prop.html"> + +<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css"> +<link rel="stylesheet" href="../login/oobe_dialog_parameters.css"> +<link rel="stylesheet" href="../login/oobe_flex_layout.css"> +<link rel="stylesheet" href="../login/oobe_text_button.css"> +<link rel="stylesheet" href="../login/oobe_screen.css"> +<link rel="stylesheet" href="assistant_optin.css"> + +<script src="chrome://resources/js/cr.js"></script> +<script src="chrome://resources/js/load_time_data.js"></script> +<script src="chrome://resources/js/util.js"></script> +<script src="strings.js"></script> +<script src="assistant_optin.js"></script> +</head> +<body> + +<div id="value-prop" role="group"> + <assistant-value-prop-md id="value-prop-md"> + </assistant-value-prop-md> +</div> + +<script src="chrome://resources/js/i18n_template.js"></script> + +</body> +</html>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js new file mode 100644 index 0000000..3ed6a7c4 --- /dev/null +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js
@@ -0,0 +1,24 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// <include src="../login/oobe_types.js"> +// <include src="../login/oobe_buttons.js"> +// <include src="../login/oobe_change_picture.js"> +// <include src="../login/oobe_dialog.js"> +// <include src="assistant_value_prop.js"> + +cr.define('assistantOptin', function() { + return { + + // Starts the assistant opt-in flow. + Show: function() { + $('value-prop-md').locale = loadTimeData.getString('locale'); + $('value-prop-md').onShow(); + } + }; +}); + +document.addEventListener('DOMContentLoaded', function() { + assistantOptin.Show(); +});
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.css new file mode 100644 index 0000000..36d0b2b --- /dev/null +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.css
@@ -0,0 +1,74 @@ +/* Copyright 2018 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +#value-prop-view { + display: block; + height: 372px; + margin: auto; + padding: 0; +} + +.value-prop-loading #retry-button, +.value-prop-loaded #retry-button, +.value-prop-error #next-button { + display: none; +} + +#loading-container, +#error-container, +#view-container { + position: absolute; + visibility: hidden; + width: 480px; +} + +.value-prop-loading-animation #loading-container, +.value-prop-loaded #view-container, +.value-prop-error #error-container { + visibility: visible; +} + +.value-prop-loading #retry-button, +.value-prop-loading #next-button, +.value-prop-loading #skip-button { + pointer-events: none; +} + +.title { + font-size: 18px; +} + +#subtitle { + font-size: 12px; + padding: 14px 0 0 0; +} + +#loading-message { + color: rgba(0, 0, 0, .54); + font-size: 12px; + line: 17px; + padding: 168px 0 0 0; +} + +paper-progress { + --paper-progress-active-color: rgb(66, 133, 244); + --paper-progress-container-color: #CEE0FC; + --paper-progress-secondary-color: rgb(66, 133, 244); + display: block; + height: 3px; + padding: 4px 0 0 0; + width: 100%; +} + +#skip-button { + color: rgb(66, 133, 244); +} + +#retry-button { + -webkit-margin-end: 18px; +} + +#next-button { + -webkit-margin-end: 18px; +}
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html new file mode 100644 index 0000000..e5125ca --- /dev/null +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
@@ -0,0 +1,47 @@ +<!-- Copyright 2018 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<dom-module id="assistant-value-prop-md"> + <template> + <link rel="stylesheet" href="../login/oobe_dialog_parameters.css"> + <link rel="stylesheet" href="../login/oobe_flex_layout.css"> + <link rel="stylesheet" href="assistant_value_prop.css"> + <oobe-dialog id="value-prop-dialog" class="value-prop-loading" role="dialog" + hide-shadow has-buttons no-footer-padding android> + <div class = "header"> + <div id="view-container"> + <webview id="value-prop-view"></webview> + </div> + <div id="error-container"> + <div class="title" + i18n-content="voiceInteractionValuePropLoadErrorTitle"></div> + <div id="subtitle"> + <div i18n-content="voiceInteractionValuePropLoadErrorMessage"></div> + </div> + </div> + <div id="loading-container"> + <div id="loading-message"> + <div i18n-content="voiceInteractionValuePropLoading"></div> + </div> + <paper-progress class="slow" indeterminate></paper-progress> + </div> + </div> + <div class="bottom-buttons flex layout horizontal"> + <oobe-text-button id="skip-button" android on-tap="onSkipTap_" + disabled="[[valuePropButtonsDisabled]]"> + <div i18n-content="voiceInteractionValuePropSkipButton"></div> + </oobe-text-button> + <div class="flex"></div> + <oobe-text-button id="retry-button" inverse android on-tap="onRetryTap_" + disabled="[[valuePropButtonsDisabled]]"> + <div i18n-content="voiceInteractionValuePropRetryButton"></div> + </oobe-text-button> + <oobe-text-button id="next-button" inverse android + on-tap="onNextTap_" disabled="[[valuePropButtonsDisabled]]"> + <div i18n-content="voiceInteractionValuePropNextButton"></div> + </oobe-text-button> + </div> + </oobe-dialog> + </template> +</dom-module>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js new file mode 100644 index 0000000..0735e63 --- /dev/null +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js
@@ -0,0 +1,254 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Polymer element for displaying material design voice + * interaction value prop screen. + */ + +Polymer({ + is: 'assistant-value-prop-md', + + properties: { + /** + * Buttons are disabled when the value prop content is loading. + */ + valuePropButtonsDisabled: { + type: Boolean, + value: true, + }, + + /** + * System locale. + */ + locale: { + type: String, + }, + + /** + * Default url for local en. + */ + defaultUrl: { + type: String, + value: + 'https://www.gstatic.com/opa-chromeos/oobe/en/value_proposition.html', + }, + }, + + /** + * Whether try to reload with the default url when a 404 error occurred. + * @type {boolean} + * @private + */ + reloadWithDefaultUrl_: false, + + /** + * Whether an error occurs while the webview is loading. + * @type: {boolean} + * @private + */ + valuePropError_: false, + + /** + * Timeout ID for loading animation. + * @type {number} + * @private + */ + animationTimeout_: null, + + /** + * Timeout ID for loading (will fire an error). + * @type {number} + * @private + */ + loadingTimeout_: null, + + /** + * The value prop view object. + * @type {Object} + * @private + */ + valuePropView_: null, + + /** + * Whether the screen has been initialized. + * @type {boolean} + * @private + */ + initialized_: false, + + /** + * Whether the response header has been received for the value prop view + * @type: {boolean} + * @private + */ + headerReceived_: false, + + /** + * On-tap event handler for skip button. + * + * @private + */ + onSkipTap_: function() { + chrome.send('AssistantValuePropScreen.userActed', ['skip-pressed']); + }, + + /** + * On-tap event handler for retry button. + * + * @private + */ + onRetryTap_: function() { + this.reloadValueProp(); + }, + + /** + * On-tap event handler for next button. + * + * @private + */ + onNextTap_: function() { + chrome.send('AssistantValuePropScreen.userActed', ['next-pressed']); + }, + + /** + * Add class to the list of classes of root elements. + * @param {string} className class to add + * + * @private + */ + addClass_: function(className) { + this.$['value-prop-dialog'].classList.add(className); + }, + + /** + * Remove class to the list of classes of root elements. + * @param {string} className class to remove + * + * @private + */ + removeClass_: function(className) { + this.$['value-prop-dialog'].classList.remove(className); + }, + + /** + * Reloads value prop. + */ + reloadValueProp: function() { + this.valuePropError_ = false; + this.headerReceived_ = false; + this.valuePropView_.src = 'https://www.gstatic.com/opa-chromeos/oobe/' + + this.locale + '/value_proposition.html'; + + window.clearTimeout(this.animationTimeout_); + window.clearTimeout(this.loadingTimeout_); + this.removeClass_('value-prop-loaded'); + this.removeClass_('value-prop-error'); + this.addClass_('value-prop-loading'); + this.valuePropButtonsDisabled = true; + + this.animationTimeout_ = window.setTimeout(function() { + this.addClass_('value-prop-loading-animation'); + }.bind(this), 500); + this.loadingTimeout_ = window.setTimeout(function() { + this.onValueViewErrorOccurred(); + }.bind(this), 5000); + }, + + /** + * Handles event when value prop view cannot be loaded. + */ + onValueViewErrorOccurred: function(details) { + this.valuePropError_ = true; + window.clearTimeout(this.animationTimeout_); + window.clearTimeout(this.loadingTimeout_); + this.removeClass_('value-prop-loading-animation'); + this.removeClass_('value-prop-loading'); + this.removeClass_('value-prop-loaded'); + this.addClass_('value-prop-error'); + + this.valuePropButtonsDisabled = false; + this.$['retry-button'].focus(); + }, + + /** + * Handles event when value prop view is loaded. + */ + onValueViewContentLoad: function(details) { + if (details == null) { + return; + } + if (this.valuePropError_ || !this.headerReceived_) { + return; + } + if (this.reloadWithDefaultUrl_) { + this.valuePropView_.src = this.defaultUrl; + this.headerReceived_ = false; + this.reloadWithDefaultUrl_ = false; + return; + } + + window.clearTimeout(this.animationTimeout_); + window.clearTimeout(this.loadingTimeout_); + this.removeClass_('value-prop-loading-animation'); + this.removeClass_('value-prop-loading'); + this.removeClass_('value-prop-error'); + this.addClass_('value-prop-loaded'); + + this.valuePropButtonsDisabled = false; + this.$['next-button'].focus(); + }, + + /** + * Handles event when webview request headers received. + */ + onValueViewHeadersReceived: function(details) { + if (details == null) { + return; + } + this.headerReceived_ = true; + if (details.statusCode == '404') { + if (details.url != this.defaultUrl) { + this.reloadWithDefaultUrl_ = true; + return; + } else { + this.onValueViewErrorOccurred(); + } + } + if (details.statusCode != '200') { + this.onValueViewErrorOccurred(); + } + }, + + /** + * Signal from host to show the screen. + */ + onShow: function() { + var requestFilter = {urls: ['<all_urls>'], types: ['main_frame']}; + this.valuePropView_ = this.$['value-prop-view']; + + if (!this.initialized_) { + this.valuePropView_.request.onErrorOccurred.addListener( + this.onValueViewErrorOccurred.bind(this), requestFilter); + this.valuePropView_.request.onHeadersReceived.addListener( + this.onValueViewHeadersReceived.bind(this), requestFilter); + this.valuePropView_.request.onCompleted.addListener( + this.onValueViewContentLoad.bind(this), requestFilter); + + this.valuePropView_.addContentScripts([{ + name: 'stripLinks', + matches: ['<all_urls>'], + js: { + code: 'document.querySelectorAll(\'a\').forEach(' + + 'function(anchor){anchor.href=\'javascript:void(0)\';})' + }, + run_at: 'document_end' + }]); + + this.initialized_ = true; + } + + this.reloadValueProp(); + }, +});
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd index 78dc8f5d..fccd3d7 100644 --- a/chrome/browser/resources/component_extension_resources.grd +++ b/chrome/browser/resources/component_extension_resources.grd
@@ -101,8 +101,11 @@ <include name="IDR_ARC_SUPPORT_ICON_HEADER" file="chromeos/arc_support/images/header.png" type="BINDATA" /> </if> <if expr="enable_plugins"> - <include name="IDR_PDF_INDEX_CSS" file="pdf/index.css" allowexternalscript="true" type="BINDATA" /> + <!-- Note that resources included here also must be included in + print_preview_ui.cc such these resources will be exposed to + PDF in print preview. --> <include name="IDR_PDF_INDEX_HTML" file="pdf/index.html" allowexternalscript="true" type="BINDATA" /> + <include name="IDR_PDF_INDEX_CSS" file="pdf/index.css" allowexternalscript="true" type="BINDATA" /> <include name="IDR_PDF_MAIN_JS" file="pdf/main.js" type="BINDATA" /> <include name="IDR_PDF_PDF_JS" file="pdf/pdf.js" type="BINDATA" /> <include name="IDR_PDF_UI_MANAGER_JS" file="pdf/toolbar_manager.js" type="BINDATA" /> @@ -115,7 +118,6 @@ <include name="IDR_PDF_ZOOM_MANAGER_JS" file="pdf/zoom_manager.js" type="BINDATA" /> <include name="IDR_PDF_GESTURE_DETECTOR_JS" file="pdf/gesture_detector.js" type="BINDATA" /> <include name="IDR_PDF_BROWSER_API_JS" file="pdf/browser_api.js" type="BINDATA" /> - <include name="IDR_PDF_CONTENT_SCRIPT_JS" file="pdf/content_script.js" type="BINDATA" /> <include name="IDR_PDF_METRICS_JS" file="pdf/metrics.js" type="BINDATA" /> <include name="IDR_PDF_COORDS_TRANSFORMER_JS" file="pdf/coords_transformer.js" type="BINDATA" />
diff --git a/chrome/browser/resources/md_extensions/options_dialog.html b/chrome/browser/resources/md_extensions/options_dialog.html index 5c5abc51..524b35a 100644 --- a/chrome/browser/resources/md_extensions/options_dialog.html +++ b/chrome/browser/resources/md_extensions/options_dialog.html
@@ -22,19 +22,26 @@ ExtensionOptions { display: block; - min-width: 300px; + height: 100%; overflow: hidden; } dialog { --scroll-border: 0; - width: fit-content; --cr-dialog-body: { + height: 100%; padding: 0; }; + --cr-dialog-wrapper: { + height: 100%; + max-height: initial; + overflow: hidden; + }; + --cr-dialog-body-container: { border: none; + height: 100%; min-height: initial; }; }
diff --git a/chrome/browser/resources/md_extensions/options_dialog.js b/chrome/browser/resources/md_extensions/options_dialog.js index d9ecf14..e5dbb639 100644 --- a/chrome/browser/resources/md_extensions/options_dialog.js +++ b/chrome/browser/resources/md_extensions/options_dialog.js
@@ -37,10 +37,27 @@ data_: Object, }, + /** @private {?Function} */ + boundResizeListener_: null, + get open() { return this.$$('dialog').open; }, + /** + * Resizes the dialog to the given width/height, taking into account the + * window width/height. + * @param {number} width + * @param {number} height + * @private + */ + updateDialogSize_: function(width, height) { + const effectiveHeight = Math.min(window.innerHeight, height); + const effectiveWidth = Math.min(window.innerWidth, width); + this.$.dialog.style.height = effectiveHeight + 'px'; + this.$.dialog.style.width = effectiveWidth + 'px'; + }, + /** @param {chrome.developerPrivate.ExtensionInfo} data */ show: function(data) { this.data_ = data; @@ -50,15 +67,25 @@ this.extensionOptions_.extension = this.data_.id; this.extensionOptions_.onclose = this.close.bind(this); + let preferredSize = null; const onSizeChanged = e => { - this.extensionOptions_.style.height = e.height + 'px'; - this.extensionOptions_.style.width = e.width + 'px'; - - if (!this.$$('dialog').open) - this.$$('dialog').showModal(); + preferredSize = e; + this.updateDialogSize_(preferredSize.width, preferredSize.height); + this.$$('dialog').showModal(); + this.extensionOptions_.onpreferredsizechanged = null; }; + this.boundResizeListener_ = () => { + this.updateDialogSize_(preferredSize.width, preferredSize.height); + }; + + // Only handle the 1st instance of 'preferredsizechanged' event, to get + // the preferred size. this.extensionOptions_.onpreferredsizechanged = onSizeChanged; + + // Add a 'resize' such that the dialog is resized when window size + // changes. + window.addEventListener('resize', this.boundResizeListener_); this.$.body.appendChild(this.extensionOptions_); }); }, @@ -70,6 +97,11 @@ /** @private */ onClose_: function() { + if (this.boundResizeListener_) { + window.removeEventListener('resize', this.boundResizeListener_); + this.boundResizeListener_ = null; + } + const currentPage = extensions.navigation.getCurrentPage(); // We update the page when the options dialog closes, but only if we're // still on the details page. We could be on a different page if the
diff --git a/chrome/browser/resources/pdf/content_script.js b/chrome/browser/resources/pdf/content_script.js deleted file mode 100644 index dce77e6..0000000 --- a/chrome/browser/resources/pdf/content_script.js +++ /dev/null
@@ -1,7 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This is to work-around an issue where this extension is not granted -// permission to access chrome://resources when iframed for print preview. -// See https://crbug.com/444752.
diff --git a/chrome/browser/resources/pdf/index.html b/chrome/browser/resources/pdf/index.html index 69c1c39c..dcec3cc 100644 --- a/chrome/browser/resources/pdf/index.html +++ b/chrome/browser/resources/pdf/index.html
@@ -1,7 +1,6 @@ <!doctype html> <html> <head> - <base href="chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/"> <meta charset="utf-8"> <link rel="import" href="elements/viewer-error-screen/viewer-error-screen.html"> <link rel="import" href="elements/viewer-page-indicator/viewer-page-indicator.html">
diff --git a/chrome/browser/resources/pdf/manifest.json b/chrome/browser/resources/pdf/manifest.json index c3d0a80..6e09e51 100644 --- a/chrome/browser/resources/pdf/manifest.json +++ b/chrome/browser/resources/pdf/manifest.json
@@ -16,11 +16,5 @@ "application/pdf" ], "content_security_policy": "script-src 'self' blob: filesystem: chrome://resources; object-src * blob: externalfile: file: filesystem: data:; plugin-types application/x-google-chrome-pdf", - "mime_types_handler": "index.html", - "web_accessible_resources": [ - "*.js", - "*.html", - "*.css", - "*.png" - ] + "mime_types_handler": "index.html" }
diff --git a/chrome/browser/resources/pdf/pdf_scripting_api.js b/chrome/browser/resources/pdf/pdf_scripting_api.js index a133b52..b4ed5b9b 100644 --- a/chrome/browser/resources/pdf/pdf_scripting_api.js +++ b/chrome/browser/resources/pdf/pdf_scripting_api.js
@@ -231,13 +231,14 @@ * interface which provides access to various features of the viewer for use * by print preview and accessibility. * @param {string} src the source URL of the PDF to load initially. + * @param {string} baseUrl the base URL of the PDF viewer * @return {HTMLIFrameElement} the iframe element containing the PDF viewer. */ -function PDFCreateOutOfProcessPlugin(src) { +function PDFCreateOutOfProcessPlugin(src, baseUrl) { var client = new PDFScriptingAPI(window, null); var iframe = assertInstanceof( window.document.createElement('iframe'), HTMLIFrameElement); - iframe.setAttribute('src', 'pdf_preview.html?' + src); + iframe.setAttribute('src', baseUrl + '/index.html?' + src); // Prevent the frame from being tab-focusable. iframe.setAttribute('tabindex', '-1');
diff --git a/chrome/browser/resources/print_preview/new/preview_area.html b/chrome/browser/resources/print_preview/new/preview_area.html index bfdbe31ef..718f60a 100644 --- a/chrome/browser/resources/print_preview/new/preview_area.html +++ b/chrome/browser/resources/print_preview/new/preview_area.html
@@ -149,7 +149,6 @@ </print-preview-margin-control-container> </template> <script src="preview_area.js"></script> - <script - src="chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_scripting_api.js"> + <script src="../pdf/pdf_scripting_api.js"> </script> </dom-module>
diff --git a/chrome/browser/resources/print_preview/new/preview_area.js b/chrome/browser/resources/print_preview/new/preview_area.js index cedc1db..5738b4f 100644 --- a/chrome/browser/resources/print_preview/new/preview_area.js +++ b/chrome/browser/resources/print_preview/new/preview_area.js
@@ -445,7 +445,7 @@ assert(!this.plugin_); const srcUrl = this.getPreviewUrl_(previewUid, index); this.plugin_ = /** @type {print_preview_new.PDFPlugin} */ ( - PDFCreateOutOfProcessPlugin(srcUrl)); + PDFCreateOutOfProcessPlugin(srcUrl, 'chrome://print/pdf')); this.plugin_.classList.add('preview-area-plugin'); this.plugin_.setAttribute('aria-live', 'polite'); this.plugin_.setAttribute('aria-atomic', 'true');
diff --git a/chrome/browser/resources/print_preview/pdf_preview.html b/chrome/browser/resources/print_preview/pdf_preview.html deleted file mode 100644 index ba3ea35..0000000 --- a/chrome/browser/resources/print_preview/pdf_preview.html +++ /dev/null
@@ -1 +0,0 @@ -<include src="../pdf/index.html"> \ No newline at end of file
diff --git a/chrome/browser/resources/print_preview/previewarea/preview_area.js b/chrome/browser/resources/print_preview/previewarea/preview_area.js index a545d6259..bb24c19c 100644 --- a/chrome/browser/resources/print_preview/previewarea/preview_area.js +++ b/chrome/browser/resources/print_preview/previewarea/preview_area.js
@@ -488,7 +488,7 @@ createPlugin_: function(srcUrl) { assert(!this.plugin_); this.plugin_ = /** @type {print_preview.PDFPlugin} */ ( - PDFCreateOutOfProcessPlugin(srcUrl)); + PDFCreateOutOfProcessPlugin(srcUrl, 'chrome://print/pdf')); this.plugin_.setKeyEventCallback(this.keyEventCallback_); this.plugin_.setAttribute('class', 'preview-area-plugin');
diff --git a/chrome/browser/resources/print_preview/print_preview_resources.grd b/chrome/browser/resources/print_preview/print_preview_resources.grd index 4730a65f..a4ebaca 100644 --- a/chrome/browser/resources/print_preview/print_preview_resources.grd +++ b/chrome/browser/resources/print_preview/print_preview_resources.grd
@@ -149,9 +149,6 @@ <structure name="IDR_PRINT_PREVIEW_NEW_PREVIEW_AREA_JS" file="new/preview_area.js" type="chrome_html" /> - <structure name="IDR_PDF_PDF_SCRIPTING_API_JS" - file="../pdf/pdf_scripting_api.js" - type="chrome_html" /> <structure name="IDR_PRINT_PREVIEW_NEW_HEADER_HTML" file="new/header.html" type="chrome_html" />
diff --git a/chrome/browser/resources/settings/people_page/compiled_resources2.gyp b/chrome/browser/resources/settings/people_page/compiled_resources2.gyp index 3d6b9bd..3c72741d 100644 --- a/chrome/browser/resources/settings/people_page/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
@@ -87,6 +87,7 @@ 'dependencies': [ '../compiled_resources2.gyp:route', '../controls/compiled_resources2.gyp:settings_dropdown_menu', + '../controls/compiled_resources2.gyp:settings_toggle_button', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
diff --git a/chrome/browser/resources/settings/people_page/lock_screen.html b/chrome/browser/resources/settings/people_page/lock_screen.html index df6f253..a68afd0 100644 --- a/chrome/browser/resources/settings/people_page/lock_screen.html +++ b/chrome/browser/resources/settings/people_page/lock_screen.html
@@ -76,8 +76,9 @@ </style> <div> - <settings-toggle-button id="screenLockDiv" class="first" + <settings-toggle-button id="enableLockScreen" class="first" pref="{{prefs.settings.enable_screen_lock}}" + on-settings-boolean-control-change="onScreenLockChange_" no-set-pref label="$i18n{enableScreenlock}"> </settings-toggle-button> @@ -198,7 +199,8 @@ <template is="dom-if" if="[[showPasswordPromptDialog_]]" restamp> <settings-password-prompt-dialog id="passwordPrompt" - on-close="onPasswordPromptDialogClose_" set-modes="{{setModes_}}"> + on-close="onPasswordPromptDialogClose_" set-modes="{{setModes_}}" + auth-token="{{authToken_}}"> </settings-password-prompt-dialog> </template>
diff --git a/chrome/browser/resources/settings/people_page/lock_screen.js b/chrome/browser/resources/settings/people_page/lock_screen.js index bbf51e7..4edb4a4 100644 --- a/chrome/browser/resources/settings/people_page/lock_screen.js +++ b/chrome/browser/resources/settings/people_page/lock_screen.js
@@ -41,10 +41,8 @@ prefs: {type: Object}, /** - * setModes_ is a partially applied function that stores the previously - * entered password. It's defined only when the user has already entered a - * valid password. - * + * setModes_ is a partially applied function that stores the current auth + * token. It's defined only when the user has entered a valid password. * @type {Object|undefined} * @private */ @@ -54,6 +52,12 @@ }, /** + * Authentication token provided by password-prompt-dialog. + * @private + */ + authToken_: String, + + /** * writeUma_ is a function that handles writing uma stats. It may be * overridden for tests. * @@ -231,6 +235,20 @@ }, /** + * @param {!Event} event + * @private + */ + onScreenLockChange_: function(event) { + const target = /** @type {!SettingsToggleButtonElement} */ (event.target); + if (!this.authToken_) { + console.error('Screen lock changed with expired token.'); + target.checked = !target.checked; + return; + } + this.setLockScreenEnabled(this.authToken_, target.checked); + }, + + /** * Called when the unlock type has changed. * @param {!string} selected The current unlock type. * @private @@ -269,7 +287,7 @@ else if (!this.$$('#unlockType').disabled) cr.ui.focusWithoutInk(assert(this.$$('#unlockType'))); else - cr.ui.focusWithoutInk(assert(this.$$('#screenLockDiv'))); + cr.ui.focusWithoutInk(assert(this.$$('#enableLockScreen'))); }, /**
diff --git a/chrome/browser/resources/settings/people_page/lock_state_behavior.js b/chrome/browser/resources/settings/people_page/lock_state_behavior.js index 3f2f27c..0caa83e 100644 --- a/chrome/browser/resources/settings/people_page/lock_state_behavior.js +++ b/chrome/browser/resources/settings/people_page/lock_state_behavior.js
@@ -71,4 +71,9 @@ } }); }, + + /** Sets the lock screen enabled state. */ + setLockScreenEnabled(authToken, enabled) { + this.quickUnlockPrivate_.setLockScreenEnabled(authToken, enabled); + }, };
diff --git a/chrome/browser/resources/settings/people_page/password_prompt_dialog.html b/chrome/browser/resources/settings/people_page/password_prompt_dialog.html index af784ee..3a5e4b6 100644 --- a/chrome/browser/resources/settings/people_page/password_prompt_dialog.html +++ b/chrome/browser/resources/settings/people_page/password_prompt_dialog.html
@@ -18,8 +18,7 @@ } </style> - <dialog is="cr-dialog" id="dialog" on-close="onClose_" - close-text="$i18n{close}"> + <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}"> <div slot="title">$i18n{passwordPromptTitle}</div> <div slot="body">
diff --git a/chrome/browser/resources/settings/people_page/password_prompt_dialog.js b/chrome/browser/resources/settings/people_page/password_prompt_dialog.js index f0285c22..00a484c 100644 --- a/chrome/browser/resources/settings/people_page/password_prompt_dialog.js +++ b/chrome/browser/resources/settings/people_page/password_prompt_dialog.js
@@ -45,10 +45,13 @@ /** * Authhentication token used when calling setModes, returned by - * quickUnlockPrivate.getAuthToken. + * quickUnlockPrivate.getAuthToken. Reflected to lock-screen. * @private */ - token_: String, + authToken: { + type: String, + notify: true, + }, /** * Helper property which marks password as valid/invalid. @@ -93,14 +96,6 @@ }, /** - * Called whenever the dialog is closed. - * @private - */ - onClose_: function() { - this.token_ = ''; - }, - - /** * Run the account password check. * @private */ @@ -127,6 +122,7 @@ return; } + this.authToken = tokenInfo.token; this.passwordInvalid_ = false; // Create the |this.setModes| closure and automatically clear it after
diff --git a/chrome/browser/sessions/better_session_restore_browsertest.cc b/chrome/browser/sessions/better_session_restore_browsertest.cc index 9f5efc80..2a306139 100644 --- a/chrome/browser/sessions/better_session_restore_browsertest.cc +++ b/chrome/browser/sessions/better_session_restore_browsertest.cc
@@ -468,6 +468,7 @@ // Set the startup preference to "continue where I left off" and visit a page // which stores a session cookie. StoreDataWithPage("session_cookies.html"); + content::EnsureCookiesFlushed(browser()->profile()); } IN_PROC_BROWSER_TEST_F(ContinueWhereILeftOffTest, SessionCookies) { @@ -696,6 +697,7 @@ IN_PROC_BROWSER_TEST_F(RestartTest, PRE_SessionCookies) { StoreDataWithPage("session_cookies.html"); + content::EnsureCookiesFlushed(browser()->profile()); Restart(); } @@ -725,6 +727,7 @@ IN_PROC_BROWSER_TEST_F(RestartTest, PRE_CookiesClearedOnExit) { StoreDataWithPage("cookies.html"); + content::EnsureCookiesFlushed(browser()->profile()); CookieSettingsFactory::GetForProfile(browser()->profile()) ->SetDefaultCookieSetting(CONTENT_SETTING_SESSION_ONLY); Restart(); @@ -826,6 +829,7 @@ IN_PROC_BROWSER_TEST_F(NoSessionRestoreTest, PRE_PRE_CookiesClearedOnExit) { StoreDataWithPage("cookies.html"); + content::EnsureCookiesFlushed(browser()->profile()); } IN_PROC_BROWSER_TEST_F(NoSessionRestoreTest, PRE_CookiesClearedOnExit) {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index dd8b3813..452ba8c 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1756,6 +1756,15 @@ assert(enable_extensions) assert(toolkit_views) sources += [ + "app_list/app_list_controller_impl.cc", + "app_list/app_list_controller_impl.h", + "app_list/app_sync_ui_state.cc", + "app_list/app_sync_ui_state.h", + "app_list/app_sync_ui_state_factory.cc", + "app_list/app_sync_ui_state_factory.h", + "app_list/app_sync_ui_state_observer.h", + "app_list/app_sync_ui_state_watcher.cc", + "app_list/app_sync_ui_state_watcher.h", "app_list/search/launcher_search/launcher_search_icon_image_loader.cc", "app_list/search/launcher_search/launcher_search_icon_image_loader.h", "app_list/search/launcher_search/launcher_search_icon_image_loader_impl.cc", @@ -1766,17 +1775,6 @@ "app_list/search/launcher_search/launcher_search_result.h", "ash/accessibility/accessibility_controller_client.cc", "ash/accessibility/accessibility_controller_client.h", - "ash/app_list/app_list_controller_ash.cc", - "ash/app_list/app_list_controller_ash.h", - "ash/app_list/app_list_service_ash.cc", - "ash/app_list/app_list_service_ash.h", - "ash/app_list/app_sync_ui_state_watcher.cc", - "ash/app_list/app_sync_ui_state_watcher.h", - "ash/app_sync_ui_state.cc", - "ash/app_sync_ui_state.h", - "ash/app_sync_ui_state_factory.cc", - "ash/app_sync_ui_state_factory.h", - "ash/app_sync_ui_state_observer.h", "ash/ash_shell_init.cc", "ash/ash_shell_init.h", "ash/ash_util.cc", @@ -1936,6 +1934,11 @@ "views/select_file_dialog_extension_factory.h", "views/tabs/window_finder_ash.cc", "views/touch_uma/touch_uma_ash.cc", + "webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h", + "webui/chromeos/assistant_optin/assistant_optin_ui.cc", + "webui/chromeos/assistant_optin/assistant_optin_ui.h", + "webui/chromeos/assistant_optin/value_prop_screen_handler.cc", + "webui/chromeos/assistant_optin/value_prop_screen_handler.h", "webui/chromeos/bluetooth_dialog_localized_strings_provider.cc", "webui/chromeos/bluetooth_dialog_localized_strings_provider.h", "webui/chromeos/bluetooth_pairing_dialog.cc", @@ -3436,7 +3439,6 @@ "app_list/app_list_model_builder.h", "app_list/app_list_model_updater.h", "app_list/app_list_model_updater_delegate.h", - "app_list/app_list_service.cc", "app_list/app_list_service.h", "app_list/app_list_service_impl.cc", "app_list/app_list_service_impl.h", @@ -3458,9 +3460,6 @@ "app_list/extension_app_model_builder.h", "app_list/extension_uninstaller.cc", "app_list/extension_uninstaller.h", - "app_list/profile_loader.cc", - "app_list/profile_loader.h", - "app_list/profile_store.h", "app_list/search/answer_card/answer_card_contents.cc", "app_list/search/answer_card/answer_card_contents.h", "app_list/search/answer_card/answer_card_result.cc",
diff --git a/chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.cc b/chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.cc index 5e971b2..0a425558 100644 --- a/chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.cc +++ b/chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.cc
@@ -50,7 +50,7 @@ } int AdsBlockedInfobarDelegate::GetIconId() const { - return IDR_ANDROID_INFOBAR_ADS_BLOCKED; + return IDR_ANDROID_INFOBAR_BLOCKED_POPUPS; } base::string16 AdsBlockedInfobarDelegate::GetMessageText() const {
diff --git a/chrome/browser/ui/android/content_settings/popup_blocked_infobar_delegate.cc b/chrome/browser/ui/android/content_settings/popup_blocked_infobar_delegate.cc index 2c97bc5..b7f1e16 100644 --- a/chrome/browser/ui/android/content_settings/popup_blocked_infobar_delegate.cc +++ b/chrome/browser/ui/android/content_settings/popup_blocked_infobar_delegate.cc
@@ -6,13 +6,14 @@ #include <stddef.h> #include <utility> + +#include "chrome/browser/android/android_theme_resources.h" #include "chrome/browser/content_settings/chrome_content_settings_utils.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h" #include "chrome/grit/generated_resources.h" -#include "chrome/grit/theme_resources.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" @@ -20,7 +21,6 @@ #include "components/prefs/pref_service.h" #include "ui/base/l10n/l10n_util.h" - // static void PopupBlockedInfoBarDelegate::Create(content::WebContents* web_contents, int num_popups) { @@ -63,7 +63,7 @@ } int PopupBlockedInfoBarDelegate::GetIconId() const { - return IDR_BLOCKED_POPUPS; + return IDR_ANDROID_INFOBAR_BLOCKED_POPUPS; } PopupBlockedInfoBarDelegate*
diff --git a/chrome/browser/ui/ash/app_list/app_list_browsertest.cc b/chrome/browser/ui/app_list/app_list_browsertest.cc similarity index 79% rename from chrome/browser/ui/ash/app_list/app_list_browsertest.cc rename to chrome/browser/ui/app_list/app_list_browsertest.cc index 6a05b90c..52eb49a 100644 --- a/chrome/browser/ui/ash/app_list/app_list_browsertest.cc +++ b/chrome/browser/ui/app_list/app_list_browsertest.cc
@@ -5,8 +5,7 @@ #include "chrome/browser/apps/app_browsertest_util.h" #include "chrome/browser/chromeos/ash_config.h" #include "chrome/browser/extensions/extension_browsertest.h" -#include "chrome/browser/ui/ash/app_list/app_list_controller_ash.h" -#include "chrome/browser/ui/ash/app_list/app_list_service_ash.h" +#include "chrome/browser/ui/app_list/app_list_controller_impl.h" #include "chrome/browser/ui/extensions/app_launch_params.h" #include "chrome/browser/ui/extensions/application_launch.h" #include "chrome/test/base/in_process_browser_test.h" @@ -20,14 +19,14 @@ #include "ui/wm/core/window_util.h" using AppListTest = InProcessBrowserTest; -using AppListControllerDelegateAshTest = extensions::PlatformAppBrowserTest; +using AppListControllerDelegateImplTest = extensions::PlatformAppBrowserTest; // TODO(crbug.com/759779, crbug.com/819386): Add back // |ClickingContextMenuDoesNotDismiss|. -// Test AppListControllerDelegateAsh::IsAppOpen for extension apps. -IN_PROC_BROWSER_TEST_F(AppListControllerDelegateAshTest, IsExtensionAppOpen) { - AppListControllerDelegateAsh delegate; +// Test AppListControllerDelegateImpl::IsAppOpen for extension apps. +IN_PROC_BROWSER_TEST_F(AppListControllerDelegateImplTest, IsExtensionAppOpen) { + AppListControllerDelegateImpl delegate; EXPECT_FALSE(delegate.IsAppOpen("fake_extension_app_id")); base::FilePath extension_path = test_data_dir_.AppendASCII("app"); @@ -46,9 +45,9 @@ EXPECT_TRUE(delegate.IsAppOpen(extension_app->id())); } -// Test AppListControllerDelegateAsh::IsAppOpen for platform apps. -IN_PROC_BROWSER_TEST_F(AppListControllerDelegateAshTest, IsPlatformAppOpen) { - AppListControllerDelegateAsh delegate; +// Test AppListControllerDelegateImpl::IsAppOpen for platform apps. +IN_PROC_BROWSER_TEST_F(AppListControllerDelegateImplTest, IsPlatformAppOpen) { + AppListControllerDelegateImpl delegate; EXPECT_FALSE(delegate.IsAppOpen("fake_platform_app_id")); const extensions::Extension* app = InstallPlatformApp("minimal");
diff --git a/chrome/browser/ui/app_list/app_list_client_impl.cc b/chrome/browser/ui/app_list/app_list_client_impl.cc index 5692c948..a72656ba 100644 --- a/chrome/browser/ui/app_list/app_list_client_impl.cc +++ b/chrome/browser/ui/app_list/app_list_client_impl.cc
@@ -12,9 +12,9 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" #include "chrome/browser/ui/app_list/app_list_model_updater.h" +#include "chrome/browser/ui/app_list/app_list_service_impl.h" #include "chrome/browser/ui/app_list/app_list_view_delegate.h" #include "chrome/browser/ui/app_list/search/search_controller.h" -#include "chrome/browser/ui/ash/app_list/app_list_service_ash.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "content/public/common/service_manager_connection.h" #include "services/service_manager/public/cpp/connector.h" @@ -28,7 +28,7 @@ ash::mojom::AppListClientPtr client; binding_.Bind(mojo::MakeRequest(&client)); app_list_controller_->SetClient(std::move(client)); - AppListServiceAsh::GetInstance()->SetAppListControllerAndClient( + AppListServiceImpl::GetInstance()->SetAppListControllerAndClient( app_list_controller_.get(), this); } @@ -81,11 +81,11 @@ } void AppListClientImpl::OnAppListTargetVisibilityChanged(bool visible) { - AppListServiceAsh::GetInstance()->set_app_list_target_visible(visible); + AppListServiceImpl::GetInstance()->set_app_list_target_visible(visible); } void AppListClientImpl::OnAppListVisibilityChanged(bool visible) { - AppListServiceAsh::GetInstance()->set_app_list_visible(visible); + AppListServiceImpl::GetInstance()->set_app_list_visible(visible); } void AppListClientImpl::StartVoiceInteractionSession() { @@ -121,7 +121,7 @@ } AppListViewDelegate* AppListClientImpl::GetViewDelegate() { - return AppListServiceAsh::GetInstance()->GetViewDelegate(); + return AppListServiceImpl::GetInstance()->GetViewDelegate(); } void AppListClientImpl::FlushMojoForTesting() {
diff --git a/chrome/browser/ui/app_list/app_list_controller_browsertest.cc b/chrome/browser/ui/app_list/app_list_controller_browsertest.cc index e73f317a..3b59960 100644 --- a/chrome/browser/ui/app_list/app_list_controller_browsertest.cc +++ b/chrome/browser/ui/app_list/app_list_controller_browsertest.cc
@@ -73,7 +73,7 @@ const std::string title = extension->name(); // Show the app list first, otherwise we won't have a search box to update. - service->ShowForProfile(browser()->profile()); + service->Show(); service->FlushForTesting(); // Currently the search box is empty, so we have no result. @@ -125,6 +125,6 @@ AppListService* service = AppListService::Get(); EXPECT_TRUE(service->GetCurrentAppListProfile()); - service->ShowForProfile(browser()->profile()); + service->Show(); EXPECT_EQ(browser()->profile(), service->GetCurrentAppListProfile()); }
diff --git a/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc b/chrome/browser/ui/app_list/app_list_controller_impl.cc similarity index 65% rename from chrome/browser/ui/ash/app_list/app_list_controller_ash.cc rename to chrome/browser/ui/app_list/app_list_controller_impl.cc index a93b7e60..a45c479 100644 --- a/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc +++ b/chrome/browser/ui/app_list/app_list_controller_impl.cc
@@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/ash/app_list/app_list_controller_ash.h" +#include "chrome/browser/ui/app_list/app_list_controller_impl.h" #include <utility> #include "ash/public/interfaces/app_list.mojom.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/ash/app_list/app_list_service_ash.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_util.h" #include "chrome/browser/ui/browser_commands.h" @@ -19,30 +18,30 @@ #include "ui/display/screen.h" #include "ui/display/types/display_constants.h" -AppListControllerDelegateAsh::AppListControllerDelegateAsh() {} +AppListControllerDelegateImpl::AppListControllerDelegateImpl() {} -AppListControllerDelegateAsh::~AppListControllerDelegateAsh() {} +AppListControllerDelegateImpl::~AppListControllerDelegateImpl() {} -void AppListControllerDelegateAsh::SetAppListController( +void AppListControllerDelegateImpl::SetAppListController( ash::mojom::AppListController* app_list_controller) { app_list_controller_ = app_list_controller; } -void AppListControllerDelegateAsh::DismissView() { +void AppListControllerDelegateImpl::DismissView() { if (!app_list_controller_) return; app_list_controller_->DismissAppList(); } -int64_t AppListControllerDelegateAsh::GetAppListDisplayId() { +int64_t AppListControllerDelegateImpl::GetAppListDisplayId() { return display_id_; } -void AppListControllerDelegateAsh::SetAppListDisplayId(int64_t display_id) { +void AppListControllerDelegateImpl::SetAppListDisplayId(int64_t display_id) { display_id_ = display_id; } -void AppListControllerDelegateAsh::GetAppInfoDialogBounds( +void AppListControllerDelegateImpl::GetAppInfoDialogBounds( GetAppInfoDialogBoundsCallback callback) { if (!app_list_controller_) { LOG(ERROR) << "app_list_controller_ is null"; @@ -52,52 +51,50 @@ app_list_controller_->GetAppInfoDialogBounds(std::move(callback)); } -bool AppListControllerDelegateAsh::IsAppPinned(const std::string& app_id) { +bool AppListControllerDelegateImpl::IsAppPinned(const std::string& app_id) { return ChromeLauncherController::instance()->IsAppPinned(app_id); } -bool AppListControllerDelegateAsh::IsAppOpen(const std::string& app_id) const { +bool AppListControllerDelegateImpl::IsAppOpen(const std::string& app_id) const { return ChromeLauncherController::instance()->IsOpen(ash::ShelfID(app_id)); } -void AppListControllerDelegateAsh::PinApp(const std::string& app_id) { +void AppListControllerDelegateImpl::PinApp(const std::string& app_id) { ChromeLauncherController::instance()->PinAppWithID(app_id); } -void AppListControllerDelegateAsh::UnpinApp(const std::string& app_id) { +void AppListControllerDelegateImpl::UnpinApp(const std::string& app_id) { ChromeLauncherController::instance()->UnpinAppWithID(app_id); } -AppListControllerDelegate::Pinnable AppListControllerDelegateAsh::GetPinnable( +AppListControllerDelegate::Pinnable AppListControllerDelegateImpl::GetPinnable( const std::string& app_id) { return GetPinnableForAppID(app_id, ChromeLauncherController::instance()->profile()); } -void AppListControllerDelegateAsh::OnShowChildDialog() { -} +void AppListControllerDelegateImpl::OnShowChildDialog() {} -void AppListControllerDelegateAsh::OnCloseChildDialog() { -} +void AppListControllerDelegateImpl::OnCloseChildDialog() {} -void AppListControllerDelegateAsh::CreateNewWindow(Profile* profile, - bool incognito) { +void AppListControllerDelegateImpl::CreateNewWindow(Profile* profile, + bool incognito) { if (incognito) chrome::NewEmptyWindow(profile->GetOffTheRecordProfile()); else chrome::NewEmptyWindow(profile); } -void AppListControllerDelegateAsh::OpenURL(Profile* profile, - const GURL& url, - ui::PageTransition transition, - WindowOpenDisposition disposition) { +void AppListControllerDelegateImpl::OpenURL(Profile* profile, + const GURL& url, + ui::PageTransition transition, + WindowOpenDisposition disposition) { NavigateParams params(profile, url, transition); params.disposition = disposition; Navigate(¶ms); } -void AppListControllerDelegateAsh::ActivateApp( +void AppListControllerDelegateImpl::ActivateApp( Profile* profile, const extensions::Extension* extension, AppListSource source, @@ -116,7 +113,7 @@ DismissView(); } -void AppListControllerDelegateAsh::LaunchApp( +void AppListControllerDelegateImpl::LaunchApp( Profile* profile, const extensions::Extension* extension, AppListSource source, @@ -129,7 +126,7 @@ } ash::ShelfLaunchSource -AppListControllerDelegateAsh::AppListSourceToLaunchSource( +AppListControllerDelegateImpl::AppListSourceToLaunchSource( AppListSource source) { switch (source) { case LAUNCH_FROM_APP_LIST:
diff --git a/chrome/browser/ui/ash/app_list/app_list_controller_ash.h b/chrome/browser/ui/app_list/app_list_controller_impl.h similarity index 83% rename from chrome/browser/ui/ash/app_list/app_list_controller_ash.h rename to chrome/browser/ui/app_list/app_list_controller_impl.h index bd40d54..3238b47 100644 --- a/chrome/browser/ui/ash/app_list/app_list_controller_ash.h +++ b/chrome/browser/ui/app_list/app_list_controller_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_ASH_APP_LIST_APP_LIST_CONTROLLER_ASH_H_ -#define CHROME_BROWSER_UI_ASH_APP_LIST_APP_LIST_CONTROLLER_ASH_H_ +#ifndef CHROME_BROWSER_UI_APP_LIST_APP_LIST_CONTROLLER_IMPL_H_ +#define CHROME_BROWSER_UI_APP_LIST_APP_LIST_CONTROLLER_IMPL_H_ #include <string> @@ -20,10 +20,10 @@ } // namespace mojom } // namespace ash -class AppListControllerDelegateAsh : public AppListControllerDelegate { +class AppListControllerDelegateImpl : public AppListControllerDelegate { public: - AppListControllerDelegateAsh(); - ~AppListControllerDelegateAsh() override; + AppListControllerDelegateImpl(); + ~AppListControllerDelegateImpl() override; // AppListControllerDelegate overrides: void DismissView() override; @@ -64,7 +64,7 @@ // Not owned. ash::mojom::AppListController* app_list_controller_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(AppListControllerDelegateAsh); + DISALLOW_COPY_AND_ASSIGN(AppListControllerDelegateImpl); }; -#endif // CHROME_BROWSER_UI_ASH_APP_LIST_APP_LIST_CONTROLLER_ASH_H_ +#endif // CHROME_BROWSER_UI_APP_LIST_APP_LIST_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/ui/ash/app_list/app_list_interactive_uitest.cc b/chrome/browser/ui/app_list/app_list_interactive_uitest.cc similarity index 100% rename from chrome/browser/ui/ash/app_list/app_list_interactive_uitest.cc rename to chrome/browser/ui/app_list/app_list_interactive_uitest.cc
diff --git a/chrome/browser/ui/app_list/app_list_service.cc b/chrome/browser/ui/app_list/app_list_service.cc deleted file mode 100644 index 85568513..0000000 --- a/chrome/browser/ui/app_list/app_list_service.cc +++ /dev/null
@@ -1,159 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/app_list/app_list_service.h" - -#include <stdint.h> - -#include "base/command_line.h" -#include "base/metrics/histogram_macros.h" -#include "base/process/process_info.h" -#include "base/strings/string_number_conversions.h" -#include "base/time/time.h" -#include "build/build_config.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/pref_names.h" -#include "components/prefs/pref_registry_simple.h" - -namespace { - -enum StartupType { - COLD_START, - WARM_START, - WARM_START_FAST, -}; - -// For when an app list show request is received via CommandLine. Indicates -// whether the Profile the app list was previously showing was the SAME, OTHER -// or NONE with respect to the new Profile to show. -enum ProfileLoadState { - PROFILE_LOADED_SAME, - PROFILE_LOADED_OTHER, - PROFILE_LOADED_NONE, -}; - -base::Time GetOriginalProcessStartTime(const base::CommandLine& command_line) { - if (command_line.HasSwitch(switches::kOriginalProcessStartTime)) { - std::string start_time_string = - command_line.GetSwitchValueASCII(switches::kOriginalProcessStartTime); - int64_t remote_start_time; - base::StringToInt64(start_time_string, &remote_start_time); - return base::Time::FromInternalValue(remote_start_time); - } - - return base::CurrentProcessInfo::CreationTime(); -} - -StartupType GetStartupType(const base::CommandLine& command_line) { - // The presence of kOriginalProcessStartTime implies that another process - // has sent us its command line to handle, ie: we are already running. - if (command_line.HasSwitch(switches::kOriginalProcessStartTime)) { - return command_line.HasSwitch(switches::kFastStart) ? - WARM_START_FAST : WARM_START; - } - return COLD_START; -} - -// The time the process that caused the app list to be shown started. This isn't -// necessarily the currently executing process as we may be processing a command -// line given to a short-lived Chrome instance. -int64_t g_original_process_start_time; - -// The type of startup the the current app list show has gone through. -StartupType g_app_show_startup_type; - -// The state of the active app list profile at the most recent launch. -ProfileLoadState g_profile_load_state; - -void RecordFirstPaintTiming() { - base::Time start_time( - base::Time::FromInternalValue(g_original_process_start_time)); - base::TimeDelta elapsed = base::Time::Now() - start_time; - switch (g_app_show_startup_type) { - case COLD_START: - DCHECK_EQ(PROFILE_LOADED_NONE, g_profile_load_state); - UMA_HISTOGRAM_LONG_TIMES("Startup.AppListFirstPaintColdStart", elapsed); - break; - case WARM_START: - // For warm starts, only record showing the same profile. "NONE" should - // only occur in the first 30 seconds after startup. "OTHER" only occurs - // for multi-profile cases. In these cases, timings are also affected by - // whether or not a profile has been loaded from disk, which makes the - // profile load asynchronous and skews results unpredictably. - if (g_profile_load_state == PROFILE_LOADED_SAME) - UMA_HISTOGRAM_LONG_TIMES("Startup.AppListFirstPaintWarmStart", elapsed); - break; - case WARM_START_FAST: - if (g_profile_load_state == PROFILE_LOADED_SAME) { - UMA_HISTOGRAM_LONG_TIMES("Startup.AppListFirstPaintWarmStartFast", - elapsed); - } - break; - } -} - -void RecordStartupInfo(AppListService* service, - const base::CommandLine& command_line, - Profile* launch_profile) { - base::Time start_time = GetOriginalProcessStartTime(command_line); - if (start_time.is_null()) - return; - - base::TimeDelta elapsed = base::Time::Now() - start_time; - StartupType startup_type = GetStartupType(command_line); - switch (startup_type) { - case COLD_START: - UMA_HISTOGRAM_LONG_TIMES("Startup.ShowAppListColdStart", elapsed); - break; - case WARM_START: - UMA_HISTOGRAM_LONG_TIMES("Startup.ShowAppListWarmStart", elapsed); - break; - case WARM_START_FAST: - UMA_HISTOGRAM_LONG_TIMES("Startup.ShowAppListWarmStartFast", elapsed); - break; - } - - g_original_process_start_time = start_time.ToInternalValue(); - g_app_show_startup_type = startup_type; - - Profile* current_profile = service->GetCurrentAppListProfile(); - if (!current_profile) - g_profile_load_state = PROFILE_LOADED_NONE; - else if (current_profile == launch_profile) - g_profile_load_state = PROFILE_LOADED_SAME; - else - g_profile_load_state = PROFILE_LOADED_OTHER; - - service->SetAppListNextPaintCallback(RecordFirstPaintTiming); -} - -} // namespace - -// static -void AppListService::RegisterPrefs(PrefRegistrySimple* registry) { - registry->RegisterInt64Pref(prefs::kLastAppListLaunchPing, 0); - registry->RegisterIntegerPref(prefs::kAppListLaunchCount, 0); - registry->RegisterInt64Pref(prefs::kLastAppListAppLaunchPing, 0); - registry->RegisterIntegerPref(prefs::kAppListAppLaunchCount, 0); - registry->RegisterStringPref(prefs::kAppListProfile, std::string()); - registry->RegisterBooleanPref(prefs::kAppLauncherHasBeenEnabled, false); - registry->RegisterIntegerPref(prefs::kAppListEnableMethod, - ENABLE_NOT_RECORDED); - registry->RegisterInt64Pref(prefs::kAppListEnableTime, 0); -} - -// static -bool AppListService::HandleLaunchCommandLine( - const base::CommandLine& command_line, - Profile* launch_profile) { - if (!command_line.HasSwitch(switches::kShowAppList)) - return false; - - AppListService* service = Get(); - DCHECK(service); - RecordStartupInfo(service, command_line, launch_profile); - service->ShowForProfile(launch_profile); - return true; -}
diff --git a/chrome/browser/ui/app_list/app_list_service.h b/chrome/browser/ui/app_list/app_list_service.h index ff28076..be417455 100644 --- a/chrome/browser/ui/app_list/app_list_service.h +++ b/chrome/browser/ui/app_list/app_list_service.h
@@ -7,79 +7,19 @@ #include <string> -#include "base/compiler_specific.h" #include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "ui/gfx/native_widget_types.h" - -class AppListControllerDelegate; -class PrefRegistrySimple; -class Profile; - -namespace base { -class CommandLine; -class FilePath; -} - -namespace content { -struct SpeechRecognitionSessionPreamble; -} +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/app_list/app_list_controller_delegate.h" class AppListService { public: - // Source that triggers the app launcher being enabled. This is used for UMA - // to track discoverability of the app lancher shortcut after install. Also - // used to provide custom install behavior (e.g. "always" enable). - enum AppListEnableSource { - ENABLE_NOT_RECORDED, // Indicates app launcher not recently enabled. - ENABLE_FOR_APP_INSTALL, // Triggered by a webstore packaged app install. - ENABLE_VIA_WEBSTORE_LINK, // Triggered by webstore explicitly via API. - ENABLE_VIA_COMMAND_LINE, // Triggered by --enable-app-list. - ENABLE_ON_REINSTALL_UNUSED, // Triggered by Chrome reinstall finding pref. - // Unused since detecting a reinstall and - // detecting a pref are mutually exclusive. - ENABLE_SHOWN_UNDISCOVERED, // This overrides a prior ENABLE_FOR_APP_INSTALL - // when the launcher is auto-shown without - // being "discovered" beforehand. - ENABLE_NUM_ENABLE_SOURCES - }; - // Get the AppListService. static AppListService* Get(); - static void RegisterPrefs(PrefRegistrySimple* registry); - - // Initializes the AppListService, and returns true if |command_line| is for - // showing the app list. - static bool HandleLaunchCommandLine(const base::CommandLine& command_line, - Profile* launch_profile); - - // Indicates that |callback| should be called next time the app list is - // painted. - virtual void SetAppListNextPaintCallback(void (*callback)()) = 0; - - virtual base::FilePath GetProfilePath( - const base::FilePath& user_data_dir) = 0; - virtual void SetProfilePath(const base::FilePath& profile_path) = 0; - // Show the app list for the profile configured in the user data dir for the // current browser process. virtual void Show() = 0; - // Show the app list for the given profile. If it differs from the profile the - // app list is currently showing, repopulate the app list and save the new - // profile to local prefs as the default app list profile. - virtual void ShowForProfile(Profile* requested_profile) = 0; - - // Shows the app list, and reveals the page that contains |extension_id|. This - // should only be called for things that show in the app list, and only when - // they begin or complete installing. If |start_discovery_tracking| is set, - // the app launcher will not actually be shown, but will start tracking UMA - // for app launcher discovery. - virtual void ShowForAppInstall(Profile* profile, - const std::string& extension_id, - bool start_discovery_tracking) = 0; - // Dismiss the app list. virtual void DismissAppList() = 0; @@ -92,17 +32,9 @@ // Returns true if the app list is visible. virtual bool IsAppListVisible() const = 0; - // Enable the app list. What this does specifically will depend on the host - // operating system and shell. - virtual void EnableAppList(Profile* initial_profile, - AppListEnableSource enable_source) = 0; - // Returns a pointer to the platform specific AppListControllerDelegate. virtual AppListControllerDelegate* GetControllerDelegate() = 0; - // Create a platform-specific shortcut for the app list. - virtual void CreateShortcut() = 0; - // Flush pending mojo calls to Ash AppListControllerImpl. virtual void FlushForTesting() = 0; @@ -110,9 +42,6 @@ AppListService() {} virtual ~AppListService() {} - // Do any once off initialization needed for the app list. - virtual void Init(Profile* initial_profile) = 0; - private: DISALLOW_COPY_AND_ASSIGN(AppListService); };
diff --git a/chrome/browser/ui/app_list/app_list_service_disabled_mac.h b/chrome/browser/ui/app_list/app_list_service_disabled_mac.h deleted file mode 100644 index 9a3fdea..0000000 --- a/chrome/browser/ui/app_list/app_list_service_disabled_mac.h +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_APP_LIST_APP_LIST_SERVICE_DISABLED_MAC_H_ -#define CHROME_BROWSER_UI_APP_LIST_APP_LIST_SERVICE_DISABLED_MAC_H_ - -class Profile; - -// Register the handler to accept connections from the old app_list shim, and -// perform |action|; e.g. to open chrome://apps rather than the deleted App -// Launcher UI. -void InitAppsPageLegacyShimHandler(void (*action)(Profile*)); - -#endif // CHROME_BROWSER_UI_APP_LIST_APP_LIST_SERVICE_DISABLED_MAC_H_
diff --git a/chrome/browser/ui/app_list/app_list_service_impl.cc b/chrome/browser/ui/app_list/app_list_service_impl.cc index b19ea5a..8ecc0f0 100644 --- a/chrome/browser/ui/app_list/app_list_service_impl.cc +++ b/chrome/browser/ui/app_list/app_list_service_impl.cc
@@ -9,277 +9,73 @@ #include <string> #include <utility> +#include "ash/app_list/app_list_controller_impl.h" +#include "ash/app_list/model/search/search_model.h" +#include "ash/shell.h" #include "base/bind.h" #include "base/command_line.h" +#include "base/files/file_path.h" #include "base/location.h" +#include "base/memory/singleton.h" #include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" #include "base/strings/string16.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_attributes_entry.h" -#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/app_list/app_list_client_impl.h" #include "chrome/browser/ui/app_list/app_list_view_delegate.h" -#include "chrome/browser/ui/app_list/profile_loader.h" -#include "chrome/browser/ui/app_list/profile_store.h" +#include "chrome/browser/ui/ash/ash_util.h" +#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "chrome/browser/ui/ash/session_util.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" +#include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_switches.h" - -namespace { - -const int kDiscoverabilityTimeoutMinutes = 60; - -void SendAppListAppLaunch(int count) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Apps.AppListDailyAppLaunches", count, 1, 1000, 50); - if (count > 0) - UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppToday", 1, 2); -} - -void SendAppListLaunch(int count) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Apps.AppListDailyLaunches", count, 1, 1000, 50); - if (count > 0) - UMA_HISTOGRAM_ENUMERATION("Apps.AppListHasLaunchedAppListToday", 1, 2); -} - -bool SendDailyEventFrequency( - const char* last_ping_pref, - const char* count_pref, - void (*send_callback)(int count)) { - PrefService* local_state = g_browser_process->local_state(); - - base::Time now = base::Time::Now(); - base::Time last = base::Time::FromInternalValue(local_state->GetInt64( - last_ping_pref)); - int days = (now - last).InDays(); - if (days > 0) { - send_callback(local_state->GetInteger(count_pref)); - local_state->SetInt64( - last_ping_pref, - (last + base::TimeDelta::FromDays(days)).ToInternalValue()); - local_state->SetInteger(count_pref, 0); - return true; - } - return false; -} - -void RecordDailyEventFrequency( - const char* last_ping_pref, - const char* count_pref, - void (*send_callback)(int count)) { - if (!g_browser_process) - return; // In a unit test. - - PrefService* local_state = g_browser_process->local_state(); - if (!local_state) - return; // In a unit test. - - int count = local_state->GetInteger(count_pref); - local_state->SetInteger(count_pref, count + 1); - if (SendDailyEventFrequency(last_ping_pref, count_pref, send_callback)) { - local_state->SetInteger(count_pref, 1); - } -} - -class ProfileStoreImpl : public ProfileStore { - public: - explicit ProfileStoreImpl(ProfileManager* profile_manager) - : profile_manager_(profile_manager), - weak_factory_(this) { - } - - void AddProfileObserver(ProfileAttributesStorage::Observer* observer) - override { - profile_manager_->GetProfileAttributesStorage().AddObserver(observer); - } - - void LoadProfileAsync(const base::FilePath& path, - base::Callback<void(Profile*)> callback) override { - profile_manager_->CreateProfileAsync( - path, - base::Bind(&ProfileStoreImpl::OnProfileCreated, - weak_factory_.GetWeakPtr(), - callback), - base::string16(), - std::string(), - std::string()); - } - - void OnProfileCreated(base::Callback<void(Profile*)> callback, - Profile* profile, - Profile::CreateStatus status) { - switch (status) { - case Profile::CREATE_STATUS_CREATED: - break; - case Profile::CREATE_STATUS_INITIALIZED: - callback.Run(profile); - break; - case Profile::CREATE_STATUS_LOCAL_FAIL: - case Profile::CREATE_STATUS_REMOTE_FAIL: - case Profile::CREATE_STATUS_CANCELED: - break; - case Profile::MAX_CREATE_STATUS: - NOTREACHED(); - break; - } - } - - Profile* GetProfileByPath(const base::FilePath& path) override { - DCHECK(!IsProfileLocked(path)); - return profile_manager_->GetProfileByPath(path); - } - - base::FilePath GetUserDataDir() override { - return profile_manager_->user_data_dir(); - } - - std::string GetLastUsedProfileName() override { - return profile_manager_->GetLastUsedProfileName(); - } - - bool IsProfileSupervised(const base::FilePath& profile_path) override { - ProfileAttributesEntry* entry = nullptr; - bool has_entry = g_browser_process->profile_manager()-> - GetProfileAttributesStorage(). - GetProfileAttributesWithPath(profile_path, &entry); - return has_entry && entry->IsSupervised(); - } - - bool IsProfileLocked(const base::FilePath& profile_path) override { - ProfileAttributesEntry* entry = nullptr; - bool has_entry = g_browser_process->profile_manager()-> - GetProfileAttributesStorage(). - GetProfileAttributesWithPath(profile_path, &entry); - return has_entry && entry->IsSigninRequired(); - } - - private: - ProfileManager* profile_manager_; - base::WeakPtrFactory<ProfileStoreImpl> weak_factory_; -}; - -void RecordAppListDiscoverability(PrefService* local_state, - bool is_startup_check) { - // Since this task may be delayed, ensure it does not interfere with shutdown - // when they unluckily coincide. - if (browser_shutdown::IsTryingToQuit()) - return; - - int64_t enable_time_value = local_state->GetInt64(prefs::kAppListEnableTime); - if (enable_time_value == 0) - return; // Already recorded or never enabled. - - base::Time app_list_enable_time = - base::Time::FromInternalValue(enable_time_value); - if (is_startup_check) { - // When checking at startup, only clear and record the "timeout" case, - // otherwise wait for a timeout. - base::TimeDelta time_remaining = - app_list_enable_time + - base::TimeDelta::FromMinutes(kDiscoverabilityTimeoutMinutes) - - base::Time::Now(); - if (time_remaining > base::TimeDelta()) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&RecordAppListDiscoverability, - base::Unretained(local_state), false), - time_remaining); - return; - } - } - - local_state->SetInt64(prefs::kAppListEnableTime, 0); - - AppListService::AppListEnableSource enable_source = - static_cast<AppListService::AppListEnableSource>( - local_state->GetInteger(prefs::kAppListEnableMethod)); - if (enable_source == AppListService::ENABLE_FOR_APP_INSTALL) { - base::TimeDelta time_taken = base::Time::Now() - app_list_enable_time; - // This means the user "discovered" the app launcher naturally, after it was - // enabled on the first app install. Record how long it took to discover. - // Note that the last bucket is essentially "not discovered": subtract 1 - // minute to account for clock inaccuracy. - UMA_HISTOGRAM_CUSTOM_TIMES( - "Apps.AppListTimeToDiscover", - time_taken, - base::TimeDelta::FromSeconds(1), - base::TimeDelta::FromMinutes(kDiscoverabilityTimeoutMinutes - 1), - 10 /* bucket_count */); - } - UMA_HISTOGRAM_ENUMERATION("Apps.AppListHowEnabled", - enable_source, - AppListService::ENABLE_NUM_ENABLE_SOURCES); -} - -// Checks whether a profile name is valid for the app list. Returns false if the -// name is empty, or represents a guest profile. -bool IsValidProfileName(const std::string& profile_name) { - if (profile_name.empty()) - return false; - - return - profile_name != base::FilePath(chrome::kGuestProfileDir).AsUTF8Unsafe() && - profile_name != base::FilePath(chrome::kSystemProfileDir).AsUTF8Unsafe(); -} - -} // namespace - -void AppListServiceImpl::RecordAppListLaunch() { - RecordDailyEventFrequency(prefs::kLastAppListLaunchPing, - prefs::kAppListLaunchCount, - &SendAppListLaunch); - RecordAppListDiscoverability(local_state_, false); -} +#include "ui/display/display.h" +#include "ui/display/screen.h" // static -void AppListServiceImpl::RecordAppListAppLaunch() { - RecordDailyEventFrequency(prefs::kLastAppListAppLaunchPing, - prefs::kAppListAppLaunchCount, - &SendAppListAppLaunch); -} - -// static -void AppListServiceImpl::SendAppListStats() { - if (!g_browser_process || g_browser_process->IsShuttingDown()) - return; - - SendDailyEventFrequency(prefs::kLastAppListLaunchPing, - prefs::kAppListLaunchCount, - &SendAppListLaunch); - SendDailyEventFrequency(prefs::kLastAppListAppLaunchPing, - prefs::kAppListAppLaunchCount, - &SendAppListAppLaunch); +AppListServiceImpl* AppListServiceImpl::GetInstance() { + return base::Singleton<AppListServiceImpl, + base::LeakySingletonTraits<AppListServiceImpl>>::get(); } AppListServiceImpl::AppListServiceImpl() - : profile_store_( - new ProfileStoreImpl(g_browser_process->profile_manager())), - command_line_(*base::CommandLine::ForCurrentProcess()), + : command_line_(*base::CommandLine::ForCurrentProcess()), local_state_(g_browser_process->local_state()), - profile_loader_(new ProfileLoader(profile_store_.get())), - weak_factory_(this) { - profile_store_->AddProfileObserver(this); -} + weak_factory_(this) {} -AppListServiceImpl::AppListServiceImpl( - const base::CommandLine& command_line, - PrefService* local_state, - std::unique_ptr<ProfileStore> profile_store) - : profile_store_(std::move(profile_store)), - command_line_(command_line), +AppListServiceImpl::AppListServiceImpl(const base::CommandLine& command_line, + PrefService* local_state) + : command_line_(command_line), local_state_(local_state), - profile_loader_(new ProfileLoader(profile_store_.get())), - weak_factory_(this) { - profile_store_->AddProfileObserver(this); + weak_factory_(this) {} + +AppListServiceImpl::~AppListServiceImpl() = default; + +void AppListServiceImpl::SetAppListControllerAndClient( + ash::mojom::AppListController* app_list_controller, + AppListClientImpl* app_list_client) { + app_list_controller_ = app_list_controller; + controller_delegate_.SetAppListController(app_list_controller); + app_list_client_ = app_list_client; } -AppListServiceImpl::~AppListServiceImpl() {} +ash::mojom::AppListController* AppListServiceImpl::GetAppListController() { + return app_list_controller_; +} + +app_list::SearchModel* AppListServiceImpl::GetSearchModelFromAsh() { + DCHECK(!ash_util::IsRunningInMash()); + return ash::Shell::HasInstance() + ? ash::Shell::Get()->app_list_controller()->search_model() + : nullptr; +} AppListViewDelegate* AppListServiceImpl::GetViewDelegate() { if (!view_delegate_) @@ -289,151 +85,47 @@ return view_delegate_.get(); } -void AppListServiceImpl::SetAppListNextPaintCallback(void (*callback)()) {} - -void AppListServiceImpl::Init(Profile* initial_profile) {} - -base::FilePath AppListServiceImpl::GetProfilePath( - const base::FilePath& user_data_dir) { - return user_data_dir.AppendASCII(GetProfileName()); +AppListControllerDelegate* AppListServiceImpl::GetControllerDelegate() { + return &controller_delegate_; } -void AppListServiceImpl::SetProfilePath(const base::FilePath& profile_path) { - local_state_->SetString( - prefs::kAppListProfile, - profile_path.BaseName().MaybeAsASCII()); -} - -void AppListServiceImpl::CreateShortcut() {} - -std::string AppListServiceImpl::GetProfileName() { - std::string app_list_profile = - local_state_->GetString(prefs::kAppListProfile); - if (IsValidProfileName(app_list_profile)) - return app_list_profile; - - // If the user has no profile preference for the app launcher, default to the - // last browser profile used. - app_list_profile = profile_store_->GetLastUsedProfileName(); - if (IsValidProfileName(app_list_profile)) - return app_list_profile; - - // If the last profile used was invalid (ie, guest profile), use the initial - // profile. - return chrome::kInitialProfile; -} - -void AppListServiceImpl::OnProfileWillBeRemoved( - const base::FilePath& profile_path) { - // We need to watch for profile removal to keep kAppListProfile updated, for - // the case that the deleted profile is being used by the app list. - std::string app_list_last_profile = local_state_->GetString( - prefs::kAppListProfile); - if (profile_path.BaseName().MaybeAsASCII() != app_list_last_profile) - return; - - // Switch the app list over to a valid profile. - // Before ProfileAttributesStorage::RemoveProfile() calls this function, - // ProfileManager::ScheduleProfileForDeletion() will have checked to see if - // the deleted profile was also "last used", and updated that setting with - // something valid. - local_state_->SetString(prefs::kAppListProfile, - local_state_->GetString(prefs::kProfileLastUsed)); - - // If the app list was never shown, there won't be a |view_delegate_| yet. - if (!view_delegate_) - return; - - // The Chrome AppListViewDelegate now needs its profile cleared, because: - // 1. it has many references to the profile and can't be profile-keyed, and - // 2. the last used profile might not be loaded yet. - // - this loading is sometimes done by the ProfileManager asynchronously, - // so the app list can't just switch to that. - // Only Mac supports showing the app list with a NULL profile, so tear down - // the view. - DestroyAppList(); - view_delegate_->SetProfile(NULL); +Profile* AppListServiceImpl::GetCurrentAppListProfile() { + return ChromeLauncherController::instance()->profile(); } void AppListServiceImpl::Show() { - profile_loader_->LoadProfileInvalidatingOtherLoads( - GetProfilePath(profile_store_->GetUserDataDir()), - base::Bind(&AppListServiceImpl::ShowForProfile, - weak_factory_.GetWeakPtr())); -} - -void AppListServiceImpl::ShowForAppInstall(Profile* profile, - const std::string& extension_id, - bool start_discovery_tracking) { - if (start_discovery_tracking) { - CreateForProfile(profile); - } else { - // Check if the app launcher has not yet been shown ever. Since this will - // show it, if discoverability UMA hasn't yet been recorded, it needs to be - // counted as undiscovered. - if (local_state_->GetInt64(prefs::kAppListEnableTime) != 0) { - local_state_->SetInteger(prefs::kAppListEnableMethod, - ENABLE_SHOWN_UNDISCOVERED); - } - ShowForProfile(profile); - } - if (extension_id.empty()) - return; // Nothing to highlight. Only used in tests. - - // The only way an install can happen is with the profile already loaded. So, - // ShowForProfile() can never be asynchronous, and the model is guaranteed to - // exist after a show. - DCHECK(view_delegate_->GetModelUpdater()); - view_delegate_->GetModelUpdater()->HighlightItemInstalledFromUI(extension_id); -} - -void AppListServiceImpl::EnableAppList(Profile* initial_profile, - AppListEnableSource enable_source) { - SetProfilePath(initial_profile->GetPath()); - // Always allow the webstore "enable" button to re-run the install flow. - if (enable_source != AppListService::ENABLE_VIA_WEBSTORE_LINK && - local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)) { + // This may not work correctly if the profile passed in is different from the + // one the ash Shell is currently using. + if (!app_list_controller_) return; - } - - local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, true); - CreateShortcut(); - - // UMA for launcher discoverability. - local_state_->SetInt64(prefs::kAppListEnableTime, - base::Time::Now().ToInternalValue()); - local_state_->SetInteger(prefs::kAppListEnableMethod, enable_source); - if (base::ThreadTaskRunnerHandle::IsSet()) { - // Ensure a value is recorded if the user "never" shows the app list. Note - // there is no message loop in unit tests. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&RecordAppListDiscoverability, - base::Unretained(local_state_), false), - base::TimeDelta::FromMinutes(kDiscoverabilityTimeoutMinutes)); - } + app_list_controller_->ShowAppList(); } -void AppListServiceImpl::InvalidatePendingProfileLoads() { - profile_loader_->InvalidatePendingProfileLoads(); +void AppListServiceImpl::ShowAndSwitchToState(ash::AppListState state) { + if (!app_list_controller_) + return; + app_list_controller_->ShowAppListAndSwitchToState(state); } -void AppListServiceImpl::PerformStartupChecks(Profile* initial_profile) { - // Except in rare, once-off cases, this just checks that a pref is "0" and - // returns. - RecordAppListDiscoverability(local_state_, true); +void AppListServiceImpl::DismissAppList() { + if (!app_list_controller_) + return; + app_list_controller_->DismissAppList(); +} - if (command_line_.HasSwitch(app_list::switches::kResetAppListInstallState)) - local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, false); +bool AppListServiceImpl::GetTargetVisibility() const { + return app_list_target_visible_; +} - if (command_line_.HasSwitch(app_list::switches::kEnableAppList)) - EnableAppList(initial_profile, ENABLE_VIA_COMMAND_LINE); +bool AppListServiceImpl::IsAppListVisible() const { + return app_list_visible_; +} - if (!base::ThreadTaskRunnerHandle::IsSet()) - return; // In a unit test. +// static +AppListService* AppListService::Get() { + return AppListServiceImpl::GetInstance(); +} - // Send app list usage stats after a delay. - const int kSendUsageStatsDelay = 5; - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&AppListServiceImpl::SendAppListStats), - base::TimeDelta::FromSeconds(kSendUsageStatsDelay)); +void AppListServiceImpl::FlushForTesting() { + app_list_client_->FlushMojoForTesting(); }
diff --git a/chrome/browser/ui/app_list/app_list_service_impl.h b/chrome/browser/ui/app_list/app_list_service_impl.h index ead6bdc..7f72d58 100644 --- a/chrome/browser/ui/app_list/app_list_service_impl.h +++ b/chrome/browser/ui/app_list/app_list_service_impl.h
@@ -8,36 +8,42 @@ #include <memory> #include <string> +#include "ash/public/interfaces/app_list.mojom.h" #include "base/command_line.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_attributes_storage.h" +#include "chrome/browser/ui/app_list/app_list_controller_impl.h" #include "chrome/browser/ui/app_list/app_list_service.h" -#include "chrome/browser/ui/app_list/profile_loader.h" +class AppListClientImpl; +class AppListControllerDelegateImpl; class AppListViewDelegate; -class ProfileStore; + +namespace app_list { +class SearchModel; +} // namespace app_list namespace base { -class FilePath; +template <typename T> +struct DefaultSingletonTraits; } namespace test { class AppListServiceImplTestApi; } -// Parts of the AppListService implementation shared between platforms. -class AppListServiceImpl : public AppListService, - public ProfileAttributesStorage::Observer { +// An implementation of AppListService. +class AppListServiceImpl : public AppListService { public: ~AppListServiceImpl() override; + static AppListServiceImpl* GetInstance(); + // Constructor used for testing. AppListServiceImpl(const base::CommandLine& command_line, - PrefService* local_state, - std::unique_ptr<ProfileStore> profile_store); + PrefService* local_state); // Lazily create the Chrome AppListViewDelegate and set it to the current user // profile. @@ -47,52 +53,63 @@ static void RecordAppListAppLaunch(); // AppListService overrides: - void SetAppListNextPaintCallback(void (*callback)()) override; - void Init(Profile* initial_profile) override; - base::FilePath GetProfilePath(const base::FilePath& user_data_dir) override; - void SetProfilePath(const base::FilePath& profile_path) override; + Profile* GetCurrentAppListProfile() override; void Show() override; - void ShowForAppInstall(Profile* profile, - const std::string& extension_id, - bool start_discovery_tracking) override; - void EnableAppList(Profile* initial_profile, - AppListEnableSource enable_source) override; - void CreateShortcut() override; + void DismissAppList() override; + bool IsAppListVisible() const override; + bool GetTargetVisibility() const override; + void FlushForTesting() override; + AppListControllerDelegate* GetControllerDelegate() override; + + // Shows the app list if it isn't already showing and Switches to |state|, + // unless it is |INVALID_STATE| (in which case, opens on the default state). + void ShowAndSwitchToState(ash::AppListState state); + + // Updates app list (target) visibility from AppListClientImpl. + void set_app_list_visible(bool visible) { app_list_visible_ = visible; } + void set_app_list_target_visible(bool visible) { + app_list_target_visible_ = visible; + } + + // Sets the pointers to the app list controller in Ash, and the app list + // client in Chrome. + void SetAppListControllerAndClient( + ash::mojom::AppListController* app_list_controller, + AppListClientImpl* app_list_client); + + // Returns a pointer to control the app list views in ash. + ash::mojom::AppListController* GetAppListController(); + + // TODO(hejq): Search model migration is not done yet. Chrome still accesses + // it directly in non-mus+ash mode. + app_list::SearchModel* GetSearchModelFromAsh(); protected: AppListServiceImpl(); - // Create the app list UI, and maintain its state, but do not show it. - virtual void CreateForProfile(Profile* requested_profile) = 0; - - // Destroy the app list. Called when the profile that the app list is showing - // is being deleted. - virtual void DestroyAppList() = 0; - - void InvalidatePendingProfileLoads(); - ProfileLoader& profile_loader() { return *profile_loader_; } - const ProfileLoader& profile_loader() const { return *profile_loader_; } - // Perform startup checks shared between desktop implementations of the app // list. Currently this checks command line flags to enable or disable the app // list, and records UMA stats delayed from a previous Chrome process. - void PerformStartupChecks(Profile* initial_profile); + void PerformStartupChecks(); private: friend class test::AppListServiceImplTestApi; + friend struct base::DefaultSingletonTraits<AppListServiceImpl>; static void SendAppListStats(); std::string GetProfileName(); - // ProfileAttributesStorage::Observer overrides: - void OnProfileWillBeRemoved(const base::FilePath& profile_path) override; - - std::unique_ptr<ProfileStore> profile_store_; base::CommandLine command_line_; PrefService* local_state_; - std::unique_ptr<ProfileLoader> profile_loader_; std::unique_ptr<AppListViewDelegate> view_delegate_; + AppListControllerDelegateImpl controller_delegate_; + ash::mojom::AppListController* app_list_controller_ = nullptr; + AppListClientImpl* app_list_client_ = nullptr; + + bool app_list_visible_ = false; + bool app_list_target_visible_ = false; + base::WeakPtrFactory<AppListServiceImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(AppListServiceImpl);
diff --git a/chrome/browser/ui/app_list/app_list_service_impl_browsertest.cc b/chrome/browser/ui/app_list/app_list_service_impl_browsertest.cc index cfa0b719..955856a8 100644 --- a/chrome/browser/ui/app_list/app_list_service_impl_browsertest.cc +++ b/chrome/browser/ui/app_list/app_list_service_impl_browsertest.cc
@@ -27,7 +27,6 @@ public: explicit AppListServiceImplTestApi(AppListServiceImpl* impl) : impl_(impl) {} - ProfileLoader* profile_loader() { return impl_->profile_loader_.get(); } AppListViewDelegate* view_delegate() { return impl_->view_delegate_.get(); } private: @@ -58,40 +57,6 @@ DISALLOW_COPY_AND_ASSIGN(AppListServiceImplBrowserTest); }; -// Test that showing a loaded profile for the first time is lazy and -// synchronous. Then tests that showing a second loaded profile without -// dismissing correctly switches profiles. -// crbug.com/459649 -IN_PROC_BROWSER_TEST_F(AppListServiceImplBrowserTest, - DISABLED_ShowLoadedProfiles) { - PrefService* local_state = g_browser_process->local_state(); - EXPECT_FALSE(local_state->HasPrefPath(prefs::kAppListProfile)); - - // When never shown, profile path should match the last used profile. - base::FilePath user_data_dir = - g_browser_process->profile_manager()->user_data_dir(); - EXPECT_EQ(service_->GetProfilePath(user_data_dir), - browser()->profile()->GetPath()); - - // Just requesting the profile path shouldn't set it. - EXPECT_FALSE(local_state->HasPrefPath(prefs::kAppListProfile)); - - // The app list service is bound to ChromeLauncherController, which should - // always have a profile. - EXPECT_TRUE(service_->GetCurrentAppListProfile()); - - // Showing the app list for an unspecified profile, uses the loaded profile. - service_->Show(); - - // Load should be synchronous. - EXPECT_FALSE(test_api_->profile_loader()->IsAnyProfileLoading()); - EXPECT_EQ(service_->GetCurrentAppListProfile(), browser()->profile()); - - // ChromeOS doesn't record the app list profile pref, and doesn't do profile - // switching. - EXPECT_FALSE(local_state->HasPrefPath(prefs::kAppListProfile)); -} - // Tests that the AppListViewDelegate is created lazily. IN_PROC_BROWSER_TEST_F(AppListServiceImplBrowserTest, CreatedLazily) { EXPECT_FALSE(test_api_->view_delegate()); @@ -106,7 +71,7 @@ EXPECT_TRUE(service); // Show the app list to ensure it has loaded a profile. - service_->ShowForProfile(browser()->profile()); + service_->Show(); AppListModelUpdater* model_updater = test::GetModelUpdater(service); EXPECT_TRUE(model_updater);
diff --git a/chrome/browser/ui/app_list/app_list_service_interactive_uitest.cc b/chrome/browser/ui/app_list/app_list_service_interactive_uitest.cc index 64097d4..5d8891c 100644 --- a/chrome/browser/ui/app_list/app_list_service_interactive_uitest.cc +++ b/chrome/browser/ui/app_list/app_list_service_interactive_uitest.cc
@@ -18,7 +18,7 @@ AppListClientImpl app_list_client; AppListService* service = AppListService::Get(); ASSERT_FALSE(service->IsAppListVisible()); - service->ShowForProfile(browser()->profile()); + service->Show(); app_list_client.FlushMojoForTesting(); ASSERT_TRUE(service->IsAppListVisible()); service->DismissAppList();
diff --git a/chrome/browser/ui/app_list/app_list_service_unittest.cc b/chrome/browser/ui/app_list/app_list_service_unittest.cc deleted file mode 100644 index 5280606..0000000 --- a/chrome/browser/ui/app_list/app_list_service_unittest.cc +++ /dev/null
@@ -1,277 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/app_list/app_list_service.h" - -#include <memory> -#include <utility> - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/macros.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profiles_state.h" -#include "chrome/browser/ui/app_list/app_list_service_impl.h" -#include "chrome/browser/ui/app_list/test/fake_profile.h" -#include "chrome/browser/ui/app_list/test/fake_profile_store.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/pref_names.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/prefs/pref_service.h" -#include "components/prefs/pref_service_factory.h" -#include "components/prefs/testing_pref_store.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/app_list/app_list_switches.h" - -class TestingAppListServiceImpl : public AppListServiceImpl { - public: - TestingAppListServiceImpl(const base::CommandLine& command_line, - PrefService* local_state, - std::unique_ptr<ProfileStore> profile_store) - : AppListServiceImpl(command_line, local_state, std::move(profile_store)), - showing_for_profile_(NULL), - destroy_app_list_call_count_(0) {} - - Profile* showing_for_profile() const { - return showing_for_profile_; - } - - int destroy_app_list_call_count() const { - return destroy_app_list_call_count_; - } - - void PerformStartupChecks(Profile* profile) { - AppListServiceImpl::PerformStartupChecks(profile); - } - - // AppListService overrides: - Profile* GetCurrentAppListProfile() override { - // We don't return showing_for_profile_ here because that is only defined if - // the app list is visible. - return NULL; - } - - void CreateForProfile(Profile* requested_profile) override {} - - void ShowForProfile(Profile* requested_profile) override { - showing_for_profile_ = requested_profile; - RecordAppListLaunch(); - } - - void DismissAppList() override { showing_for_profile_ = NULL; } - - bool IsAppListVisible() const override { return !!showing_for_profile_; } - - bool GetTargetVisibility() const override { return IsAppListVisible(); } - - AppListControllerDelegate* GetControllerDelegate() override { return NULL; } - - void FlushForTesting() override {} - - // AppListServiceImpl overrides: - void DestroyAppList() override { ++destroy_app_list_call_count_; } - - private: - Profile* showing_for_profile_; - int destroy_app_list_call_count_; - - DISALLOW_COPY_AND_ASSIGN(TestingAppListServiceImpl); -}; - -class AppListServiceUnitTest : public testing::Test { - public: - AppListServiceUnitTest() {} - - void SetUp() override { - SetupWithCommandLine(base::CommandLine(base::CommandLine::NO_PROGRAM)); - } - - protected: - void SetupWithCommandLine(const base::CommandLine& command_line) { - user_data_dir_ = base::FilePath(FILE_PATH_LITERAL("udd")); - profile1_.reset( - new FakeProfile("p1", user_data_dir_.AppendASCII("profile1"))); - profile2_.reset( - new FakeProfile("p2", user_data_dir_.AppendASCII("profile2"))); - PrefRegistrySimple* pref_registry = new PrefRegistrySimple; - - AppListService::RegisterPrefs(pref_registry); - profiles::RegisterPrefs(pref_registry); - - PrefServiceFactory factory; - factory.set_user_prefs(base::MakeRefCounted<TestingPrefStore>()); - local_state_ = factory.Create(pref_registry); - - profile_store_ = new FakeProfileStore(user_data_dir_, local_state_.get()); - service_.reset(new TestingAppListServiceImpl( - command_line, local_state_.get(), - std::unique_ptr<ProfileStore>(profile_store_))); - } - - void EnableAppList() { - service_->EnableAppList(profile1_.get(), - AppListService::ENABLE_VIA_COMMAND_LINE); - } - - base::FilePath user_data_dir_; - std::unique_ptr<PrefService> local_state_; - FakeProfileStore* profile_store_; - std::unique_ptr<TestingAppListServiceImpl> service_; - std::unique_ptr<FakeProfile> profile1_; - std::unique_ptr<FakeProfile> profile2_; - - DISALLOW_COPY_AND_ASSIGN(AppListServiceUnitTest); -}; - -TEST_F(AppListServiceUnitTest, EnablingStateIsPersisted) { - EXPECT_FALSE(local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)); - EnableAppList(); - EXPECT_TRUE(local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)); - EXPECT_EQ(profile1_->GetPath(), user_data_dir_.Append( - local_state_->GetFilePath(prefs::kAppListProfile))); -} - -TEST_F(AppListServiceUnitTest, ShowingForProfileLoadsAProfile) { - profile_store_->LoadProfile(profile1_.get()); - EnableAppList(); - service_->Show(); - EXPECT_EQ(profile1_.get(), service_->showing_for_profile()); - EXPECT_TRUE(service_->IsAppListVisible()); -} - -TEST_F(AppListServiceUnitTest, RemovedProfileResetsToInitialProfile) { - EnableAppList(); - profile_store_->RemoveProfile(profile1_.get()); - - // kAppListProfile should have been cleared, and therefore GetProfilePath - // should return the initial profile. - EXPECT_EQ("", local_state_->GetString(prefs::kAppListProfile)); - base::FilePath initial_profile_path = - user_data_dir_.AppendASCII(chrome::kInitialProfile); - EXPECT_EQ(initial_profile_path, - service_->GetProfilePath(profile_store_->GetUserDataDir())); -} - -TEST_F(AppListServiceUnitTest, - RemovedProfileResetsToLastUsedProfileIfExists) { - local_state_->SetString(prefs::kProfileLastUsed, "last-used"); - EnableAppList(); - profile_store_->RemoveProfile(profile1_.get()); - - // kAppListProfile should have been set to kProfileLastUsed. - EXPECT_EQ("last-used", local_state_->GetString(prefs::kAppListProfile)); - base::FilePath last_used_profile_path = - user_data_dir_.AppendASCII("last-used"); - EXPECT_EQ(last_used_profile_path, - service_->GetProfilePath(profile_store_->GetUserDataDir())); - - // For this test, the AppListViewDelegate is not created because the - // app list is never shown, so there is nothing to destroy. - EXPECT_EQ(0, service_->destroy_app_list_call_count()); -} - -TEST_F(AppListServiceUnitTest, RefusesToLoadGuestAppListProfile) { - // Unlikely, but if somehow the user's app_list.profile pref was set to the - // guest profile, make sure we refuse to load it (or it would crash). - local_state_->SetString( - prefs::kAppListProfile, - base::FilePath(chrome::kGuestProfileDir).MaybeAsASCII()); - local_state_->SetString(prefs::kProfileLastUsed, "last-used"); - base::FilePath last_used_profile_path = - user_data_dir_.AppendASCII("last-used"); - EXPECT_EQ(last_used_profile_path, - service_->GetProfilePath(profile_store_->GetUserDataDir())); -} - -TEST_F(AppListServiceUnitTest, RefusesToLoadGuestLastUsedProfile) { - // If the user's most recent browser session was a guest session, make sure we - // do not open a guest profile in the launcher (which would crash). - local_state_->SetString( - prefs::kProfileLastUsed, - base::FilePath(chrome::kGuestProfileDir).MaybeAsASCII()); - base::FilePath initial_profile_path = - user_data_dir_.AppendASCII(chrome::kInitialProfile); - EXPECT_EQ(initial_profile_path, - service_->GetProfilePath(profile_store_->GetUserDataDir())); -} - -TEST_F(AppListServiceUnitTest, SwitchingProfilesPersists) { - profile_store_->LoadProfile(profile1_.get()); - profile_store_->LoadProfile(profile2_.get()); - EnableAppList(); - service_->SetProfilePath(profile2_->GetPath()); - service_->Show(); - EXPECT_EQ(profile2_.get(), service_->showing_for_profile()); - EXPECT_EQ(profile2_->GetPath(), - service_->GetProfilePath(profile_store_->GetUserDataDir())); - service_->SetProfilePath(profile1_->GetPath()); - EXPECT_EQ(profile1_->GetPath(), - service_->GetProfilePath(profile_store_->GetUserDataDir())); -} - -TEST_F(AppListServiceUnitTest, EnableViaCommandLineFlag) { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - command_line.AppendSwitch(app_list::switches::kEnableAppList); - SetupWithCommandLine(command_line); - service_->PerformStartupChecks(profile1_.get()); - EXPECT_TRUE(local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)); -} - -TEST_F(AppListServiceUnitTest, DisableViaCommandLineFlag) { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - command_line.AppendSwitch(app_list::switches::kResetAppListInstallState); - SetupWithCommandLine(command_line); - service_->PerformStartupChecks(profile1_.get()); - EXPECT_FALSE(local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)); -} - -TEST_F(AppListServiceUnitTest, UMAPrefStates) { - EXPECT_FALSE(local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)); - EXPECT_EQ(AppListService::ENABLE_NOT_RECORDED, - local_state_->GetInteger(prefs::kAppListEnableMethod)); - EXPECT_EQ(0, local_state_->GetInt64(prefs::kAppListEnableTime)); - - service_->EnableAppList(profile1_.get(), - AppListService::ENABLE_FOR_APP_INSTALL); - - // After enable, method and time should be recorded. - EXPECT_TRUE(local_state_->GetBoolean(prefs::kAppLauncherHasBeenEnabled)); - EXPECT_EQ(AppListService::ENABLE_FOR_APP_INSTALL, - local_state_->GetInteger(prefs::kAppListEnableMethod)); - EXPECT_NE(0, local_state_->GetInt64(prefs::kAppListEnableTime)); - - service_->ShowForProfile(profile1_.get()); - - // After a regular "show", time should be cleared, so UMA is not re-recorded. - EXPECT_EQ(AppListService::ENABLE_FOR_APP_INSTALL, - local_state_->GetInteger(prefs::kAppListEnableMethod)); - EXPECT_EQ(0, local_state_->GetInt64(prefs::kAppListEnableTime)); - - // A second enable should be a no-op. - service_->EnableAppList(profile1_.get(), - AppListService::ENABLE_FOR_APP_INSTALL); - EXPECT_EQ(AppListService::ENABLE_FOR_APP_INSTALL, - local_state_->GetInteger(prefs::kAppListEnableMethod)); - EXPECT_EQ(0, local_state_->GetInt64(prefs::kAppListEnableTime)); - - // An app install auto-show here should keep the recorded enable method. - service_->ShowForAppInstall(profile1_.get(), "", false); - EXPECT_EQ(AppListService::ENABLE_FOR_APP_INSTALL, - local_state_->GetInteger(prefs::kAppListEnableMethod)); - - // Clear the enable state, so we can enable again. - local_state_->SetBoolean(prefs::kAppLauncherHasBeenEnabled, false); - service_->EnableAppList(profile1_.get(), - AppListService::ENABLE_FOR_APP_INSTALL); - - EXPECT_EQ(AppListService::ENABLE_FOR_APP_INSTALL, - local_state_->GetInteger(prefs::kAppListEnableMethod)); - EXPECT_NE(0, local_state_->GetInt64(prefs::kAppListEnableTime)); - - // An auto-show here should update the enable method to prevent recording it - // as ENABLE_FOR_APP_INSTALL. - service_->ShowForAppInstall(profile1_.get(), "", false); - EXPECT_EQ(AppListService::ENABLE_SHOWN_UNDISCOVERED, - local_state_->GetInteger(prefs::kAppListEnableMethod)); -}
diff --git a/chrome/browser/ui/app_list/app_list_util.cc b/chrome/browser/ui/app_list/app_list_util.cc index 74f0f24..dfa3698 100644 --- a/chrome/browser/ui/app_list/app_list_util.cc +++ b/chrome/browser/ui/app_list/app_list_util.cc
@@ -5,18 +5,11 @@ #include "chrome/browser/ui/app_list/app_list_util.h" #include "build/build_config.h" -#include "chrome/browser/browser_process.h" -#include "chrome/common/pref_names.h" -#include "components/prefs/pref_service.h" bool IsAppLauncherEnabled() { -#if !BUILDFLAG(ENABLE_APP_LIST) - return false; -#elif defined(OS_CHROMEOS) +#if defined(OS_CHROMEOS) return true; #else - PrefService* prefs = g_browser_process->local_state(); - // In some tests, the prefs aren't initialised. - return prefs && prefs->GetBoolean(prefs::kAppLauncherHasBeenEnabled); + return false; #endif }
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc index 6d4e9a8..86e032d 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.cc +++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -24,11 +24,11 @@ #include "chrome/browser/ui/app_list/app_list_model_updater.h" #include "chrome/browser/ui/app_list/app_list_syncable_service.h" #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" +#include "chrome/browser/ui/app_list/app_sync_ui_state_watcher.h" #include "chrome/browser/ui/app_list/search/search_controller.h" #include "chrome/browser/ui/app_list/search/search_controller_factory.h" #include "chrome/browser/ui/app_list/search/search_resource_manager.h" #include "chrome/browser/ui/apps/chrome_app_delegate.h" -#include "chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h" #include "chrome/browser/ui/ash/wallpaper_controller_client.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/ui/ash/app_sync_ui_state.cc b/chrome/browser/ui/app_list/app_sync_ui_state.cc similarity index 95% rename from chrome/browser/ui/ash/app_sync_ui_state.cc rename to chrome/browser/ui/app_list/app_sync_ui_state.cc index 6ce06111e8..dadc384 100644 --- a/chrome/browser/ui/ash/app_sync_ui_state.cc +++ b/chrome/browser/ui/app_list/app_sync_ui_state.cc
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/ash/app_sync_ui_state.h" +#include "chrome/browser/ui/app_list/app_sync_ui_state.h" #include "build/build_config.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/pending_extension_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" -#include "chrome/browser/ui/ash/app_sync_ui_state_factory.h" -#include "chrome/browser/ui/ash/app_sync_ui_state_observer.h" +#include "chrome/browser/ui/app_list/app_sync_ui_state_factory.h" +#include "chrome/browser/ui/app_list/app_sync_ui_state_observer.h" #include "components/browser_sync/profile_sync_service.h" #include "components/prefs/pref_service.h" #include "components/user_manager/user_manager.h"
diff --git a/chrome/browser/ui/ash/app_sync_ui_state.h b/chrome/browser/ui/app_list/app_sync_ui_state.h similarity index 94% rename from chrome/browser/ui/ash/app_sync_ui_state.h rename to chrome/browser/ui/app_list/app_sync_ui_state.h index 0e9901b..db16b2d9 100644 --- a/chrome/browser/ui/ash/app_sync_ui_state.h +++ b/chrome/browser/ui/app_list/app_sync_ui_state.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_ASH_APP_SYNC_UI_STATE_H_ -#define CHROME_BROWSER_UI_ASH_APP_SYNC_UI_STATE_H_ +#ifndef CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_H_ +#define CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_H_ #include "base/compiler_specific.h" #include "base/macros.h" @@ -91,4 +91,4 @@ DISALLOW_COPY_AND_ASSIGN(AppSyncUIState); }; -#endif // CHROME_BROWSER_UI_ASH_APP_SYNC_UI_STATE_H_ +#endif // CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_H_
diff --git a/chrome/browser/ui/ash/app_sync_ui_state_factory.cc b/chrome/browser/ui/app_list/app_sync_ui_state_factory.cc similarity index 91% rename from chrome/browser/ui/ash/app_sync_ui_state_factory.cc rename to chrome/browser/ui/app_list/app_sync_ui_state_factory.cc index 71e1ae1..9bc9a00 100644 --- a/chrome/browser/ui/ash/app_sync_ui_state_factory.cc +++ b/chrome/browser/ui/app_list/app_sync_ui_state_factory.cc
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/ash/app_sync_ui_state_factory.h" +#include "chrome/browser/ui/app_list/app_sync_ui_state_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" -#include "chrome/browser/ui/ash/app_sync_ui_state.h" +#include "chrome/browser/ui/app_list/app_sync_ui_state.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "extensions/browser/extension_registry_factory.h"
diff --git a/chrome/browser/ui/ash/app_sync_ui_state_factory.h b/chrome/browser/ui/app_list/app_sync_ui_state_factory.h similarity index 83% rename from chrome/browser/ui/ash/app_sync_ui_state_factory.h rename to chrome/browser/ui/app_list/app_sync_ui_state_factory.h index 250b62de..e4b5759 100644 --- a/chrome/browser/ui/ash/app_sync_ui_state_factory.h +++ b/chrome/browser/ui/app_list/app_sync_ui_state_factory.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_ASH_APP_SYNC_UI_STATE_FACTORY_H_ -#define CHROME_BROWSER_UI_ASH_APP_SYNC_UI_STATE_FACTORY_H_ +#ifndef CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_FACTORY_H_ +#define CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_FACTORY_H_ #include "base/compiler_specific.h" #include "base/macros.h" @@ -33,4 +33,4 @@ DISALLOW_COPY_AND_ASSIGN(AppSyncUIStateFactory); }; -#endif // CHROME_BROWSER_UI_ASH_APP_SYNC_UI_STATE_FACTORY_H_ +#endif // CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_FACTORY_H_
diff --git a/chrome/browser/ui/ash/app_sync_ui_state_observer.h b/chrome/browser/ui/app_list/app_sync_ui_state_observer.h similarity index 65% rename from chrome/browser/ui/ash/app_sync_ui_state_observer.h rename to chrome/browser/ui/app_list/app_sync_ui_state_observer.h index 361648e8..d13820e 100644 --- a/chrome/browser/ui/ash/app_sync_ui_state_observer.h +++ b/chrome/browser/ui/app_list/app_sync_ui_state_observer.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_ASH_APP_SYNC_UI_STATE_OBSERVER_H_ -#define CHROME_BROWSER_UI_ASH_APP_SYNC_UI_STATE_OBSERVER_H_ +#ifndef CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_OBSERVER_H_ +#define CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_OBSERVER_H_ class AppSyncUIStateObserver { public: @@ -14,4 +14,4 @@ virtual ~AppSyncUIStateObserver() {} }; -#endif // CHROME_BROWSER_UI_ASH_APP_SYNC_UI_STATE_OBSERVER_H_ +#endif // CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_OBSERVER_H_
diff --git a/chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.cc b/chrome/browser/ui/app_list/app_sync_ui_state_watcher.cc similarity index 88% rename from chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.cc rename to chrome/browser/ui/app_list/app_sync_ui_state_watcher.cc index f45f34f..326a694 100644 --- a/chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.cc +++ b/chrome/browser/ui/app_list/app_sync_ui_state_watcher.cc
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h" +#include "chrome/browser/ui/app_list/app_sync_ui_state_watcher.h" #include "chrome/browser/ui/app_list/app_list_model_updater.h" -#include "chrome/browser/ui/ash/app_sync_ui_state.h" +#include "chrome/browser/ui/app_list/app_sync_ui_state.h" AppSyncUIStateWatcher::AppSyncUIStateWatcher(Profile* profile, AppListModelUpdater* model_updater)
diff --git a/chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h b/chrome/browser/ui/app_list/app_sync_ui_state_watcher.h similarity index 76% rename from chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h rename to chrome/browser/ui/app_list/app_sync_ui_state_watcher.h index 8c21e10..fe5a6fb 100644 --- a/chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h +++ b/chrome/browser/ui/app_list/app_sync_ui_state_watcher.h
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_ASH_APP_LIST_APP_SYNC_UI_STATE_WATCHER_H_ -#define CHROME_BROWSER_UI_ASH_APP_LIST_APP_SYNC_UI_STATE_WATCHER_H_ +#ifndef CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_WATCHER_H_ +#define CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_WATCHER_H_ #include "base/compiler_specific.h" #include "base/macros.h" -#include "chrome/browser/ui/ash/app_sync_ui_state_observer.h" +#include "chrome/browser/ui/app_list/app_sync_ui_state_observer.h" class AppListModelUpdater; class AppSyncUIState; @@ -31,4 +31,4 @@ DISALLOW_COPY_AND_ASSIGN(AppSyncUIStateWatcher); }; -#endif // CHROME_BROWSER_UI_ASH_APP_LIST_APP_SYNC_UI_STATE_WATCHER_H_ +#endif // CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_WATCHER_H_
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc index c161d57..64d3bfd 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -1457,32 +1457,6 @@ observer.OnNotificationsEnabledChanged(package_name, enabled); } -void ArcAppListPrefs::MaybeShowPackageInAppLauncher( - const arc::mojom::ArcPackageInfo& package_info) { - // Ignore system packages and auxiliary packages. - if (!package_info.sync || package_info.system) - return; - - std::unordered_set<std::string> app_ids = - GetAppsForPackage(package_info.package_name); - for (const auto& app_id : app_ids) { - std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = GetApp(app_id); - if (!app_info) { - NOTREACHED(); - continue; - } - if (!app_info->showInLauncher) - continue; - - AppListService* service = AppListService::Get(); - CHECK(service); - service->ShowForAppInstall(profile_, app_id, false); - last_shown_batch_installation_revision_ = - current_batch_installation_revision_; - break; - } -} - bool ArcAppListPrefs::IsUnknownPackage(const std::string& package_name) const { return !GetPackage(package_name) && sync_service_ && !sync_service_->IsPackageSyncing(package_name); @@ -1492,18 +1466,9 @@ arc::mojom::ArcPackageInfoPtr package_info) { DCHECK(IsArcAndroidEnabledForProfile(profile_)); - // Ignore packages installed by internal sync. - const bool unknown_package = IsUnknownPackage(package_info->package_name); - AddOrUpdatePackagePrefs(prefs_, *package_info); for (auto& observer : observer_list_) observer.OnPackageInstalled(*package_info); - - if (unknown_package && - current_batch_installation_revision_ != - last_shown_batch_installation_revision_) { - MaybeShowPackageInAppLauncher(*package_info); - } } void ArcAppListPrefs::OnPackageModified( @@ -1618,9 +1583,6 @@ void ArcAppListPrefs::OnInstallationStarted( const base::Optional<std::string>& package_name) { - // Start new batch installation group if this is first installation. - if (!installing_packages_count_) - ++current_batch_installation_revision_; ++installing_packages_count_; if (package_name.has_value() && default_apps_.HasPackage(*package_name))
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h index 25a5fe18..d7b7174 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
@@ -402,12 +402,6 @@ const std::string& package_name, const std::string& activity); - // Reveals first app from provided package in app launcher if package is newly - // installed by user. If all apps in package are hidden then app list is not - // shown. - void MaybeShowPackageInAppLauncher( - const arc::mojom::ArcPackageInfo& package_info); - // Returns true is specified package is new in the system, was not installed // and it is not scheduled to install by sync. bool IsUnknownPackage(const std::string& package_name) const; @@ -490,7 +484,6 @@ bool default_apps_ready_ = false; ArcDefaultAppList default_apps_; base::Closure default_apps_ready_callback_; - int last_shown_batch_installation_revision_ = -1; int current_batch_installation_revision_ = 0; // TODO (b/70566216): Remove this once fixed.
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc index b3376fc..2232123 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc +++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
@@ -9,8 +9,8 @@ #include "ash/app_list/model/search/search_model.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/app_list/app_list_service_impl.h" #include "chrome/browser/ui/app_list/chrome_app_list_item.h" -#include "chrome/browser/ui/ash/app_list/app_list_service_ash.h" #include "chrome/browser/ui/ash/ash_util.h" #include "extensions/common/constants.h" #include "ui/base/models/menu_model.h" @@ -19,7 +19,7 @@ : profile_(profile), weak_ptr_factory_(this) { // TODO(hejq): remove this when search migration is done. if (!ash_util::IsRunningInMash()) - search_model_ = AppListServiceAsh::GetInstance()->GetSearchModelFromAsh(); + search_model_ = AppListServiceImpl::GetInstance()->GetSearchModelFromAsh(); } ChromeAppListModelUpdater::~ChromeAppListModelUpdater() {} @@ -30,7 +30,7 @@ return; app_list_controller_ = - active ? AppListServiceAsh::GetInstance()->GetAppListController() + active ? AppListServiceImpl::GetInstance()->GetAppListController() : nullptr; if (!app_list_controller_) return;
diff --git a/chrome/browser/ui/app_list/profile_loader.cc b/chrome/browser/ui/app_list/profile_loader.cc deleted file mode 100644 index 5dea8aac..0000000 --- a/chrome/browser/ui/app_list/profile_loader.cc +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/app_list/profile_loader.h" - -#include "base/bind.h" -#include "base/files/file_path.h" -#include "chrome/browser/ui/app_list/profile_store.h" -#include "components/keep_alive_registry/keep_alive_types.h" -#include "components/keep_alive_registry/scoped_keep_alive.h" - -#if !defined(OS_CHROMEOS) -#include "chrome/browser/ui/user_manager.h" -#endif // !defined(OS_CHROMEOS) - -ProfileLoader::ProfileLoader(ProfileStore* profile_store) - : profile_store_(profile_store), - profile_load_sequence_id_(0), - pending_profile_loads_(0), - weak_factory_(this) { -} - -ProfileLoader::~ProfileLoader() { -} - -bool ProfileLoader::IsAnyProfileLoading() const { - return pending_profile_loads_ > 0; -} - -void ProfileLoader::InvalidatePendingProfileLoads() { - ++profile_load_sequence_id_; -} - -void ProfileLoader::LoadProfileInvalidatingOtherLoads( - const base::FilePath& profile_file_path, - base::Callback<void(Profile*)> callback) { - InvalidatePendingProfileLoads(); - - if (profile_store_->IsProfileLocked(profile_file_path)) { -#if !defined(OS_CHROMEOS) - UserManager::Show(base::FilePath(), - profiles::USER_MANAGER_SELECT_PROFILE_APP_LAUNCHER); -#endif // !defined(OS_CHROMEOS) - return; - } - - Profile* profile = profile_store_->GetProfileByPath(profile_file_path); - if (profile) { - callback.Run(profile); - return; - } - - IncrementPendingProfileLoads(); - profile_store_->LoadProfileAsync( - profile_file_path, - base::Bind(&ProfileLoader::OnProfileLoaded, - weak_factory_.GetWeakPtr(), - profile_load_sequence_id_, - callback)); -} - -void ProfileLoader::OnProfileLoaded(int profile_load_sequence_id, - base::Callback<void(Profile*)> callback, - Profile* profile) { - DecrementPendingProfileLoads(); - if (profile_load_sequence_id == profile_load_sequence_id_) - callback.Run(profile); -} - -void ProfileLoader::IncrementPendingProfileLoads() { - pending_profile_loads_++; - if (pending_profile_loads_ == 1) - keep_alive_.reset(new ScopedKeepAlive(KeepAliveOrigin::PROFILE_LOADER, - KeepAliveRestartOption::DISABLED)); -} - -void ProfileLoader::DecrementPendingProfileLoads() { - pending_profile_loads_--; - if (pending_profile_loads_ == 0) - keep_alive_.reset(); -}
diff --git a/chrome/browser/ui/app_list/profile_loader.h b/chrome/browser/ui/app_list/profile_loader.h deleted file mode 100644 index e5cbd42d..0000000 --- a/chrome/browser/ui/app_list/profile_loader.h +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_APP_LIST_PROFILE_LOADER_H_ -#define CHROME_BROWSER_UI_APP_LIST_PROFILE_LOADER_H_ - -#include <memory> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" - -namespace base { -class FilePath; -} - -class Profile; -class ProfileLoaderUnittest; -class ProfileStore; -class ScopedKeepAlive; - -// This class loads profiles asynchronously and calls the provided callback once -// the profile is ready. Only the callback for the most recent load request is -// called, and only if the load was successful. -// -// This is useful for loading profiles in response to user interaction where -// only the latest requested profile is required. -// TODO(koz): Merge this into AppListServiceImpl. -class ProfileLoader { - public: - explicit ProfileLoader(ProfileStore* profile_store); - ~ProfileLoader(); - - bool IsAnyProfileLoading() const; - void InvalidatePendingProfileLoads(); - void LoadProfileInvalidatingOtherLoads( - const base::FilePath& profile_file_path, - base::Callback<void(Profile*)> callback); - - private: - friend class ::ProfileLoaderUnittest; - - void OnProfileLoaded(int profile_load_sequence_id, - base::Callback<void(Profile*)> callback, - Profile* profile); - - void IncrementPendingProfileLoads(); - void DecrementPendingProfileLoads(); - - ProfileStore* profile_store_; - std::unique_ptr<ScopedKeepAlive> keep_alive_; - int profile_load_sequence_id_; - int pending_profile_loads_; - - base::WeakPtrFactory<ProfileLoader> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(ProfileLoader); -}; - -#endif // CHROME_BROWSER_UI_APP_LIST_PROFILE_LOADER_H_
diff --git a/chrome/browser/ui/app_list/profile_loader_unittest.cc b/chrome/browser/ui/app_list/profile_loader_unittest.cc deleted file mode 100644 index 39cd45d..0000000 --- a/chrome/browser/ui/app_list/profile_loader_unittest.cc +++ /dev/null
@@ -1,119 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/app_list/profile_loader.h" - -#include <memory> - -#include "base/bind.h" -#include "base/files/file_path.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/app_list/test/fake_profile.h" -#include "chrome/browser/ui/app_list/test/fake_profile_store.h" -#include "testing/gtest/include/gtest/gtest.h" - -class ProfileLoaderUnittest : public testing::Test { - public: - void SetUp() override { - last_callback_result_ = NULL; - profile1_.reset( - new FakeProfile("p1", base::FilePath(FILE_PATH_LITERAL("profile1")))); - profile2_.reset( - new FakeProfile("p2", base::FilePath(FILE_PATH_LITERAL("profile2")))); - - profile_store_.reset(new FakeProfileStore( - base::FilePath(FILE_PATH_LITERAL("udd")), nullptr)); - loader_.reset(new ProfileLoader(profile_store_.get())); - } - - void StartLoadingProfile(Profile* profile) { - loader_->LoadProfileInvalidatingOtherLoads( - profile->GetPath(), - base::Bind(&ProfileLoaderUnittest::OnProfileLoaded, - base::Unretained(this))); - } - - void FinishLoadingProfile(Profile* profile) { - profile_store_->LoadProfile(profile); - } - - void OnProfileLoaded(Profile* profile) { - last_callback_result_ = profile; - } - - bool HasKeepAlive() const { - return loader_->keep_alive_.get() != NULL; - } - - protected: - std::unique_ptr<ProfileLoader> loader_; - std::unique_ptr<FakeProfileStore> profile_store_; - std::unique_ptr<FakeProfile> profile1_; - std::unique_ptr<FakeProfile> profile2_; - Profile* last_callback_result_; -}; - -TEST_F(ProfileLoaderUnittest, LoadASecondProfileBeforeTheFirstFinishes) { - EXPECT_FALSE(loader_->IsAnyProfileLoading()); - - StartLoadingProfile(profile1_.get()); - EXPECT_TRUE(loader_->IsAnyProfileLoading()); - - StartLoadingProfile(profile2_.get()); - FinishLoadingProfile(profile1_.get()); - EXPECT_EQ(NULL, last_callback_result_); - - FinishLoadingProfile(profile2_.get()); - EXPECT_EQ(profile2_.get(), last_callback_result_); - EXPECT_FALSE(loader_->IsAnyProfileLoading()); -} - -TEST_F(ProfileLoaderUnittest, TestKeepsAliveWhileLoadingProfiles) { - EXPECT_FALSE(loader_->IsAnyProfileLoading()); - EXPECT_FALSE(HasKeepAlive()); - - StartLoadingProfile(profile1_.get()); - EXPECT_TRUE(loader_->IsAnyProfileLoading()); - EXPECT_TRUE(HasKeepAlive()); - - FinishLoadingProfile(profile1_.get()); - EXPECT_FALSE(loader_->IsAnyProfileLoading()); - EXPECT_FALSE(HasKeepAlive()); -} - -TEST_F(ProfileLoaderUnittest, TestKeepsAliveWhileLoadingMultipleProfiles) { - EXPECT_FALSE(loader_->IsAnyProfileLoading()); - EXPECT_FALSE(HasKeepAlive()); - - StartLoadingProfile(profile1_.get()); - EXPECT_TRUE(loader_->IsAnyProfileLoading()); - EXPECT_TRUE(HasKeepAlive()); - - StartLoadingProfile(profile2_.get()); - EXPECT_TRUE(loader_->IsAnyProfileLoading()); - EXPECT_TRUE(HasKeepAlive()); - - FinishLoadingProfile(profile1_.get()); - EXPECT_TRUE(loader_->IsAnyProfileLoading()); - EXPECT_TRUE(HasKeepAlive()); - - FinishLoadingProfile(profile2_.get()); - EXPECT_FALSE(loader_->IsAnyProfileLoading()); - EXPECT_FALSE(HasKeepAlive()); -} - -TEST_F(ProfileLoaderUnittest, TestInvalidatingCurrentLoad) { - EXPECT_FALSE(loader_->IsAnyProfileLoading()); - EXPECT_FALSE(HasKeepAlive()); - - StartLoadingProfile(profile1_.get()); - loader_->InvalidatePendingProfileLoads(); - // The profile is still considered loading even though we will do nothing when - // it gets here. - EXPECT_TRUE(loader_->IsAnyProfileLoading()); - EXPECT_TRUE(HasKeepAlive()); - - FinishLoadingProfile(profile1_.get()); - EXPECT_EQ(NULL, last_callback_result_); -}
diff --git a/chrome/browser/ui/app_list/profile_store.h b/chrome/browser/ui/app_list/profile_store.h deleted file mode 100644 index ca943f58..0000000 --- a/chrome/browser/ui/app_list/profile_store.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_APP_LIST_PROFILE_STORE_H_ -#define CHROME_BROWSER_UI_APP_LIST_PROFILE_STORE_H_ - -#include "base/callback_forward.h" -#include "base/files/file_path.h" -#include "chrome/browser/profiles/profile_attributes_storage.h" - -class Profile; - -// Represents something that knows how to load profiles asynchronously. -class ProfileStore { - public: - virtual ~ProfileStore() {} - virtual void AddProfileObserver( - ProfileAttributesStorage::Observer* observer) = 0; - - // Loads the profile at |path| and calls |callback| when its done. A NULL - // Profile* represents an error. - virtual void LoadProfileAsync(const base::FilePath& path, - base::Callback<void(Profile*)> callback) = 0; - - // Returns the profile at |path| if it is already loaded. - virtual Profile* GetProfileByPath(const base::FilePath& path) = 0; - - // The user data directory that profiles are stored under in this instance of - // Chrome. - virtual base::FilePath GetUserDataDir() = 0; - - // The name of the last used profile. - virtual std::string GetLastUsedProfileName() = 0; - - // Returns true if the profile at |path| is supervised. - virtual bool IsProfileSupervised(const base::FilePath& path) = 0; - - // Returns true if the profile at |path| is locked. - virtual bool IsProfileLocked(const base::FilePath& path) = 0; -}; - -#endif // CHROME_BROWSER_UI_APP_LIST_PROFILE_STORE_H_
diff --git a/chrome/browser/ui/app_list/test/fake_profile_store.cc b/chrome/browser/ui/app_list/test/fake_profile_store.cc deleted file mode 100644 index 83be0ec..0000000 --- a/chrome/browser/ui/app_list/test/fake_profile_store.cc +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/app_list/test/fake_profile_store.h" - -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/pref_names.h" -#include "components/prefs/pref_service.h" - -FakeProfileStore::FakeProfileStore(const base::FilePath& user_data_dir, - PrefService* local_state) - : user_data_dir_(user_data_dir), local_state_(local_state) { -} - -FakeProfileStore::~FakeProfileStore() { -} - -void FakeProfileStore::LoadProfile(Profile* profile) { - loaded_profiles_[profile->GetPath()] = profile; - CallbacksByPath::iterator it = callbacks_.find(profile->GetPath()); - if (it != callbacks_.end()) { - it->second.Run(profile); - callbacks_.erase(it); - } -} - -void FakeProfileStore::RemoveProfile(Profile* profile) { - base::FilePath path(profile->GetPath()); - for (auto& observer : observer_list_) - observer.OnProfileWillBeRemoved(path); - loaded_profiles_.erase(path); - for (auto& observer : observer_list_) - observer.OnProfileWasRemoved(path, base::string16()); -} - -void FakeProfileStore::AddProfileObserver( - ProfileAttributesStorage::Observer* observer) { - observer_list_.AddObserver(observer); -} - -void FakeProfileStore::LoadProfileAsync( - const base::FilePath& path, - base::Callback<void(Profile*)> callback) { - Profile* profile = GetProfileByPath(path); - if (profile) { - callback.Run(profile); - return; - } - callbacks_[path] = callback; -} - -Profile* FakeProfileStore::GetProfileByPath( - const base::FilePath& path) { - ProfilesByPath::const_iterator it = loaded_profiles_.find(path); - if (it != loaded_profiles_.end()) - return it->second; - return NULL; -} - -base::FilePath FakeProfileStore::GetUserDataDir() { - return user_data_dir_; -} - -std::string FakeProfileStore::GetLastUsedProfileName() { - std::string profile_name = local_state_->GetString(prefs::kProfileLastUsed); - - if (!profile_name.empty()) - return profile_name; - - // If there is no last used profile recorded, use the initial profile. - return chrome::kInitialProfile; -} - -bool FakeProfileStore::IsProfileSupervised(const base::FilePath& path) { - return false; -} - -bool FakeProfileStore::IsProfileLocked(const base::FilePath& path) { - return false; -}
diff --git a/chrome/browser/ui/app_list/test/fake_profile_store.h b/chrome/browser/ui/app_list/test/fake_profile_store.h deleted file mode 100644 index 06a3c550..0000000 --- a/chrome/browser/ui/app_list/test/fake_profile_store.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_APP_LIST_TEST_FAKE_PROFILE_STORE_H_ -#define CHROME_BROWSER_UI_APP_LIST_TEST_FAKE_PROFILE_STORE_H_ - -#include <map> - -#include "base/callback.h" -#include "base/observer_list.h" -#include "chrome/browser/profiles/profile_attributes_storage.h" -#include "chrome/browser/ui/app_list/profile_store.h" - -class PrefService; - -class FakeProfileStore : public ProfileStore { - public: - FakeProfileStore(const base::FilePath& user_data_dir, - PrefService* local_state); - ~FakeProfileStore() override; - - void LoadProfile(Profile* profile); - void RemoveProfile(Profile* profile); - - // ProfileStore overrides. - void AddProfileObserver(ProfileAttributesStorage::Observer* observer) - override; - void LoadProfileAsync(const base::FilePath& path, - base::Callback<void(Profile*)> callback) override; - Profile* GetProfileByPath(const base::FilePath& path) override; - base::FilePath GetUserDataDir() override; - std::string GetLastUsedProfileName() override; - bool IsProfileSupervised(const base::FilePath& path) override; - bool IsProfileLocked(const base::FilePath& path) override; - - private: - base::FilePath user_data_dir_; - PrefService* local_state_; - typedef std::map<base::FilePath, base::Callback<void(Profile*)> > - CallbacksByPath; - CallbacksByPath callbacks_; - base::ObserverList<ProfileAttributesStorage::Observer> observer_list_; - typedef std::map<base::FilePath, Profile*> ProfilesByPath; - ProfilesByPath loaded_profiles_; -}; - -#endif // CHROME_BROWSER_UI_APP_LIST_TEST_FAKE_PROFILE_STORE_H_
diff --git a/chrome/browser/ui/ash/app_list/app_list_service_ash.cc b/chrome/browser/ui/ash/app_list/app_list_service_ash.cc deleted file mode 100644 index 8a2b265d..0000000 --- a/chrome/browser/ui/ash/app_list/app_list_service_ash.cc +++ /dev/null
@@ -1,126 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/ash/app_list/app_list_service_ash.h" - -#include <string> -#include <utility> - -#include "ash/app_list/app_list_controller_impl.h" -#include "ash/app_list/model/search/search_model.h" -#include "ash/shell.h" -#include "base/files/file_path.h" -#include "base/memory/singleton.h" -#include "build/build_config.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/app_list/app_list_client_impl.h" -#include "chrome/browser/ui/app_list/app_list_view_delegate.h" -#include "chrome/browser/ui/ash/ash_util.h" -#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" -#include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_switches.h" -#include "ui/display/display.h" -#include "ui/display/screen.h" - -// static -AppListServiceAsh* AppListServiceAsh::GetInstance() { - return base::Singleton<AppListServiceAsh, - base::LeakySingletonTraits<AppListServiceAsh>>::get(); -} - -AppListServiceAsh::AppListServiceAsh() = default; -AppListServiceAsh::~AppListServiceAsh() = default; - -void AppListServiceAsh::SetAppListControllerAndClient( - ash::mojom::AppListController* app_list_controller, - AppListClientImpl* app_list_client) { - app_list_controller_ = app_list_controller; - controller_delegate_.SetAppListController(app_list_controller); - app_list_client_ = app_list_client; -} - -ash::mojom::AppListController* AppListServiceAsh::GetAppListController() { - return app_list_controller_; -} - -app_list::SearchModel* AppListServiceAsh::GetSearchModelFromAsh() { - DCHECK(!ash_util::IsRunningInMash()); - return ash::Shell::HasInstance() - ? ash::Shell::Get()->app_list_controller()->search_model() - : nullptr; -} - -void AppListServiceAsh::OnProfileWillBeRemoved( - const base::FilePath& profile_path) {} - -void AppListServiceAsh::ShowAndSwitchToState(ash::AppListState state) { - if (!app_list_controller_) - return; - app_list_controller_->ShowAppListAndSwitchToState(state); -} - -base::FilePath AppListServiceAsh::GetProfilePath( - const base::FilePath& user_data_dir) { - return ChromeLauncherController::instance()->profile()->GetPath(); -} - -void AppListServiceAsh::ShowForProfile(Profile* /*default_profile*/) { - // This may not work correctly if the profile passed in is different from the - // one the ash Shell is currently using. - if (!app_list_controller_) - return; - app_list_controller_->ShowAppList(); -} - -void AppListServiceAsh::ShowForAppInstall(Profile* profile, - const std::string& extension_id, - bool start_discovery_tracking) { - if (app_list::features::IsFullscreenAppListEnabled()) - return; - ShowAndSwitchToState(ash::AppListState::kStateApps); - AppListServiceImpl::ShowForAppInstall(profile, extension_id, - start_discovery_tracking); -} - -bool AppListServiceAsh::GetTargetVisibility() const { - return app_list_target_visible_; -} - -bool AppListServiceAsh::IsAppListVisible() const { - return app_list_visible_; -} - -void AppListServiceAsh::FlushForTesting() { - app_list_client_->FlushMojoForTesting(); -} - -void AppListServiceAsh::DismissAppList() { - if (!app_list_controller_) - return; - app_list_controller_->DismissAppList(); -} - -void AppListServiceAsh::EnableAppList(Profile* initial_profile, - AppListEnableSource enable_source) {} - -Profile* AppListServiceAsh::GetCurrentAppListProfile() { - return ChromeLauncherController::instance()->profile(); -} - -AppListControllerDelegate* AppListServiceAsh::GetControllerDelegate() { - return &controller_delegate_; -} - -void AppListServiceAsh::CreateForProfile(Profile* default_profile) {} - -void AppListServiceAsh::DestroyAppList() { - // On Ash, the app list is torn down whenever it is dismissed, so just ensure - // that it is dismissed. - DismissAppList(); -} - -// static -AppListService* AppListService::Get() { - return AppListServiceAsh::GetInstance(); -}
diff --git a/chrome/browser/ui/ash/app_list/app_list_service_ash.h b/chrome/browser/ui/ash/app_list/app_list_service_ash.h deleted file mode 100644 index 1ad1508..0000000 --- a/chrome/browser/ui/ash/app_list/app_list_service_ash.h +++ /dev/null
@@ -1,102 +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. - -#ifndef CHROME_BROWSER_UI_ASH_APP_LIST_APP_LIST_SERVICE_ASH_H_ -#define CHROME_BROWSER_UI_ASH_APP_LIST_APP_LIST_SERVICE_ASH_H_ - -#include <memory> -#include <string> - -#include "ash/public/interfaces/app_list.mojom.h" -#include "base/macros.h" -#include "chrome/browser/ui/app_list/app_list_service_impl.h" -#include "chrome/browser/ui/ash/app_list/app_list_controller_ash.h" - -class AppListClientImpl; - -namespace app_list { -class SearchModel; -} // namespace app_list - -namespace base { -template <typename T> -struct DefaultSingletonTraits; -} - -class AppListControllerDelegateAsh; - -// AppListServiceAsh wraps functionality in ChromeLauncherController and the Ash -// Shell for showing and hiding the app list on the Ash desktop. -class AppListServiceAsh : public AppListServiceImpl { - public: - static AppListServiceAsh* GetInstance(); - - // Returns a pointer to control the app list views in ash. - ash::mojom::AppListController* GetAppListController(); - - // TODO(hejq): Search model migration is not done yet. Chrome still accesses - // it directly in non-mus+ash mode. - app_list::SearchModel* GetSearchModelFromAsh(); - - // ProfileAttributesStorage::Observer overrides: - // On ChromeOS this should never happen. On other platforms, there is always a - // Non-ash AppListService that is responsible for handling this. - // TODO(calamity): Ash shouldn't observe the ProfileAttributesStorage at all. - void OnProfileWillBeRemoved(const base::FilePath& profile_path) override; - - // AppListService overrides: - bool IsAppListVisible() const override; - bool GetTargetVisibility() const override; - void FlushForTesting() override; - - // Updates app list (target) visibility from AppListClientImpl. - void set_app_list_visible(bool visible) { app_list_visible_ = visible; } - void set_app_list_target_visible(bool visible) { - app_list_target_visible_ = visible; - } - - // Sets the pointers to the app list controller in Ash, and the app list - // client in Chrome. - void SetAppListControllerAndClient( - ash::mojom::AppListController* app_list_controller, - AppListClientImpl* app_list_client); - - private: - friend struct base::DefaultSingletonTraits<AppListServiceAsh>; - friend class AppListServiceAshTestApi; - - AppListServiceAsh(); - ~AppListServiceAsh() override; - - // Shows the app list if it isn't already showing and Switches to |state|, - // unless it is |INVALID_STATE| (in which case, opens on the default state). - void ShowAndSwitchToState(ash::AppListState state); - - // AppListService overrides: - base::FilePath GetProfilePath(const base::FilePath& user_data_dir) override; - void ShowForProfile(Profile* default_profile) override; - void ShowForAppInstall(Profile* profile, - const std::string& extension_id, - bool start_discovery_tracking) override; - void DismissAppList() override; - void EnableAppList(Profile* initial_profile, - AppListEnableSource enable_source) override; - Profile* GetCurrentAppListProfile() override; - AppListControllerDelegate* GetControllerDelegate() override; - - // ApplistServiceImpl overrides: - void CreateForProfile(Profile* default_profile) override; - void DestroyAppList() override; - - AppListControllerDelegateAsh controller_delegate_; - ash::mojom::AppListController* app_list_controller_ = nullptr; - AppListClientImpl* app_list_client_ = nullptr; - - bool app_list_visible_ = false; - bool app_list_target_visible_ = false; - - DISALLOW_COPY_AND_ASSIGN(AppListServiceAsh); -}; - -#endif // CHROME_BROWSER_UI_ASH_APP_LIST_APP_LIST_SERVICE_ASH_H_
diff --git a/chrome/browser/ui/ash/launcher/arc_launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/arc_launcher_context_menu.cc index 89915c3b..bd70e63 100644 --- a/chrome/browser/ui/ash/launcher/arc_launcher_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/arc_launcher_context_menu.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/ui/ash/launcher/arc_app_shelf_id.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "chrome/grit/generated_resources.h" +#include "ui/base/ui_base_features.h" ArcLauncherContextMenu::ArcLauncherContextMenu( ChromeLauncherController* controller, @@ -40,7 +41,8 @@ if (!app_is_open) { DCHECK(app_info->launchable); AddItemWithStringId(MENU_OPEN_NEW, IDS_APP_CONTEXT_MENU_ACTIVATE_ARC); - AddSeparator(ui::NORMAL_SEPARATOR); + if (!features::IsTouchableAppContextMenuEnabled()) + AddSeparator(ui::NORMAL_SEPARATOR); } if (!app_id.has_shelf_group_id() && app_info->launchable) @@ -48,5 +50,6 @@ if (app_is_open) AddItemWithStringId(MENU_CLOSE, IDS_LAUNCHER_CONTEXT_MENU_CLOSE); - AddSeparator(ui::NORMAL_SEPARATOR); + if (!features::IsTouchableAppContextMenuEnabled()) + AddSeparator(ui::NORMAL_SEPARATOR); }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc index d2611dc..38e1254 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -4,6 +4,10 @@ #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" +#include <algorithm> +#include <set> +#include <utility> + #include "ash/multi_profile_uma.h" #include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/remote_shelf_item_delegate.h" @@ -26,11 +30,11 @@ #include "chrome/browser/prefs/pref_service_syncable_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/app_list/app_list_service_impl.h" #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" +#include "chrome/browser/ui/app_list/app_sync_ui_state.h" #include "chrome/browser/ui/app_list/arc/arc_app_icon_loader.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" -#include "chrome/browser/ui/ash/app_list/app_list_service_ash.h" -#include "chrome/browser/ui/ash/app_sync_ui_state.h" #include "chrome/browser/ui/ash/ash_util.h" #include "chrome/browser/ui/ash/chrome_launcher_prefs.h" #include "chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h" @@ -514,7 +518,7 @@ } if (window->IsActive() && allow_minimize && - !AppListServiceAsh::GetInstance()->GetTargetVisibility()) { + !AppListServiceImpl::GetInstance()->GetTargetVisibility()) { window->Minimize(); return ash::SHELF_ACTION_WINDOW_MINIMIZED; }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h index 0f2a592..3b1d5e79 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
@@ -18,7 +18,7 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/app_icon_loader_delegate.h" #include "chrome/browser/ui/app_list/app_list_syncable_service.h" -#include "chrome/browser/ui/ash/app_sync_ui_state_observer.h" +#include "chrome/browser/ui/app_list/app_sync_ui_state_observer.h" #include "chrome/browser/ui/ash/launcher/launcher_app_updater.h" #include "chrome/browser/ui/ash/launcher/settings_window_observer.h" #include "components/prefs/pref_change_registrar.h"
diff --git a/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc index faf951b..35ad49d 100644 --- a/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc
@@ -21,6 +21,7 @@ #include "chrome/grit/generated_resources.h" #include "content/public/common/context_menu_params.h" #include "extensions/browser/extension_prefs.h" +#include "ui/base/ui_base_features.h" namespace { @@ -53,7 +54,8 @@ ? IDS_APP_LIST_CONTEXT_MENU_NEW_TAB : IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW; AddItemWithStringId(MENU_OPEN_NEW, string_id); - AddSeparator(ui::NORMAL_SEPARATOR); + if (!features::IsTouchableAppContextMenuEnabled()) + AddSeparator(ui::NORMAL_SEPARATOR); } AddPinMenu(); @@ -63,7 +65,8 @@ if (!controller()->IsPlatformApp(item().id) && item().type == ash::TYPE_PINNED_APP) { - AddSeparator(ui::NORMAL_SEPARATOR); + if (!features::IsTouchableAppContextMenuEnabled()) + AddSeparator(ui::NORMAL_SEPARATOR); if (extensions::util::IsNewBookmarkAppsEnabled()) { // With bookmark apps enabled, hosted apps launch in a window by // default. This menu item is re-interpreted as a single, toggle-able @@ -98,14 +101,16 @@ } else if (controller()->IsOpen(item().id)) { AddItemWithStringId(MENU_CLOSE, IDS_LAUNCHER_CONTEXT_MENU_CLOSE); } - AddSeparator(ui::NORMAL_SEPARATOR); + if (!features::IsTouchableAppContextMenuEnabled()) + AddSeparator(ui::NORMAL_SEPARATOR); if (item().type == ash::TYPE_PINNED_APP || item().type == ash::TYPE_APP) { const extensions::MenuItem::ExtensionKey app_key(item().id.app_id); if (!app_key.empty()) { int index = 0; extension_items_->AppendExtensionItems(app_key, base::string16(), &index, false); // is_action_menu - AddSeparator(ui::NORMAL_SEPARATOR); + if (!features::IsTouchableAppContextMenuEnabled()) + AddSeparator(ui::NORMAL_SEPARATOR); } } }
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index 68b755d..6647784 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -1864,7 +1864,7 @@ EXPECT_EQ(title, title_watcher.WaitAndGetTitle()); } -// Flaky on Chrome OS only. TODO(https://crbug.com/823396) fix it. +// Flaky on Chrome OS only. TODO(https://crbug.com/823043) fix it. #if defined(OS_CHROMEOS) #define MAYBE_WindowOpenClose2 DISABLED_WindowOpenClose2 #else
diff --git a/chrome/browser/ui/cocoa/download/md_download_item_view.mm b/chrome/browser/ui/cocoa/download/md_download_item_view.mm index 2e257af..9167ebe 100644 --- a/chrome/browser/ui/cocoa/download/md_download_item_view.mm +++ b/chrome/browser/ui/cocoa/download/md_download_item_view.mm
@@ -79,6 +79,15 @@ } } // namespace +@interface MDDownloadItemButton : MDHoverButton +@end + +@implementation MDDownloadItemButton +- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent*)event { + return YES; +} +@end + @interface MDDownloadItemMenuButton : MDHoverButton @end @@ -243,7 +252,7 @@ const NSRect buttonRect = NSMakeRect(kButtonXInset, kButtonYInset, NSWidth(bounds) - kButtonXInset * 2, NSHeight(bounds) - kButtonYInset * 2); - base::scoped_nsobject<MDHoverButton> button([[MDHoverButton alloc] + base::scoped_nsobject<MDHoverButton> button([[MDDownloadItemButton alloc] initWithFrame:[self cr_localizedRect:buttonRect]]); button_ = button; button_.imagePosition = NSImageOnly;
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc index 696ec685..077dd20 100644 --- a/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -100,10 +100,6 @@ #include "chrome/browser/printing/print_dialog_cloud.h" #endif -#if BUILDFLAG(ENABLE_APP_LIST) -#include "chrome/browser/ui/app_list/app_list_service.h" -#endif - using content::BrowserThread; using content::ChildProcessSecurityPolicy; @@ -276,6 +272,7 @@ void ShowUserManagerOnStartup(const base::CommandLine& command_line) { #if !defined(OS_CHROMEOS) + // TODO(crbug/821659): Clean up the desktop UserManager webui. profiles::UserManagerAction action = command_line.HasSwitch(switches::kShowAppList) ? profiles::USER_MANAGER_SELECT_PROFILE_APP_LAUNCHER : @@ -960,7 +957,7 @@ if (command_line.HasSwitch(switches::kNotificationLaunchId)) { std::string profile_id = NotificationPlatformBridgeWin::GetProfileIdFromLaunchId( - command_line.GetSwitchValueASCII(switches::kNotificationLaunchId)); + command_line.GetSwitchValueNative(switches::kNotificationLaunchId)); if (!profile_id.empty()) { return user_data_dir.Append( base::FilePath(base::UTF8ToUTF16(profile_id))); @@ -968,13 +965,6 @@ } #endif // defined(OS_WIN) -#if BUILDFLAG(ENABLE_APP_LIST) - // If we are showing the app list then chrome isn't shown so load the app - // list's profile rather than chrome's. - if (command_line.HasSwitch(switches::kShowAppList)) - return AppListService::Get()->GetProfilePath(user_data_dir); -#endif - return g_browser_process->profile_manager()->GetLastUsedProfileDir( user_data_dir); }
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc index c146cdf7..fe6b7334 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -679,8 +679,6 @@ // Check if there are any incompatible applications cached from the last // Chrome run. has_incompatible_applications = - ProblematicProgramsUpdater:: - IsIncompatibleApplicationsWarningEnabled() && ProblematicProgramsUpdater::HasCachedPrograms(); } #endif
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc index d5176c8..3cb3555 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" +#include "build/build_config.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -14,6 +15,9 @@ // Test is Flaky on Windows see crbug.com/600201. #if defined(OS_WIN) #define MAYBE_InactiveSeparatorColor DISABLED_InactiveSeparatorColor +#elif defined(OS_MACOSX) +// Widget activation doesn't work on Mac: https://crbug.com/823543 +#define MAYBE_InactiveSeparatorColor DISABLED_InactiveSeparatorColor #else #define MAYBE_InactiveSeparatorColor InactiveSeparatorColor #endif
diff --git a/chrome/browser/ui/views/hover_button.cc b/chrome/browser/ui/views/hover_button.cc index 60b8447..3ded50b3 100644 --- a/chrome/browser/ui/views/hover_button.cc +++ b/chrome/browser/ui/views/hover_button.cc
@@ -221,8 +221,7 @@ } void HoverButton::SetSubtitleElideBehavior(gfx::ElideBehavior elide_behavior) { - DCHECK(subtitle_); - if (!subtitle_->text().empty()) + if (subtitle_ && !subtitle_->text().empty()) subtitle_->SetElideBehavior(elide_behavior); } @@ -360,7 +359,8 @@ } void HoverButton::SetSubtitleColor(SkColor color) { - subtitle_->SetEnabledColor(color); + if (subtitle_) + subtitle_->SetEnabledColor(color); } void HoverButton::OnMenuButtonClicked(MenuButton* source,
diff --git a/chrome/browser/ui/views/hover_button_unittest.cc b/chrome/browser/ui/views/hover_button_unittest.cc index 5851b003..fb8a108 100644 --- a/chrome/browser/ui/views/hover_button_unittest.cc +++ b/chrome/browser/ui/views/hover_button_unittest.cc
@@ -153,3 +153,12 @@ EXPECT_EQ(expected, base::UTF8ToUTF16(accessible_name)); } } + +// Tests that setting the style and the subtitle elide behavior don't lead to a +// crash for a HoverButton with an empty subtitle. +TEST_F(HoverButtonTest, SetStyleAndSubtitleElideBehavior) { + HoverButton button(nullptr, CreateIcon(), base::ASCIIToUTF16("Test title"), + base::string16()); + button.SetStyle(HoverButton::STYLE_PROMINENT); + button.SetSubtitleElideBehavior(gfx::ELIDE_EMAIL); +}
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view_browsertest.cc b/chrome/browser/ui/views/location_bar/location_icon_view_browsertest.cc index 47e5db45..b04a7e4 100644 --- a/chrome/browser/ui/views/location_bar/location_icon_view_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/location_icon_view_browsertest.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_view.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/views/scoped_macviews_browser_mode.h" #include "components/omnibox/browser/omnibox_edit_model.h" #include "ui/views/animation/test/ink_drop_host_view_test_api.h" @@ -30,6 +31,7 @@ LocationIconView* icon_view() const { return icon_view_.get(); } private: + test::ScopedMacViewsBrowserMode views_mode_{true}; LocationBarView* location_bar_; std::unique_ptr<LocationIconView> icon_view_;
diff --git a/chrome/browser/ui/views/media_router/web_contents_display_observer_view_unittest.cc b/chrome/browser/ui/views/media_router/web_contents_display_observer_view_unittest.cc index a5daf4d..dd900e8 100644 --- a/chrome/browser/ui/views/media_router/web_contents_display_observer_view_unittest.cc +++ b/chrome/browser/ui/views/media_router/web_contents_display_observer_view_unittest.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/ui/views/media_router/web_contents_display_observer_view.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "content/public/browser/web_contents.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/display/display.h" @@ -48,8 +49,9 @@ void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); + web_contents_.reset(CreateTestWebContents()); display_observer_ = std::make_unique<TestWebContentsDisplayObserverView>( - CreateTestWebContents(), + web_contents_.get(), base::BindRepeating(&MockCallback::OnDisplayChanged, base::Unretained(&callback_)), display1_); @@ -57,10 +59,12 @@ void TearDown() override { display_observer_.reset(); + web_contents_.reset(); ChromeRenderViewHostTestHarness::TearDown(); } protected: + std::unique_ptr<content::WebContents> web_contents_; std::unique_ptr<TestWebContentsDisplayObserverView> display_observer_; MockCallback callback_; const display::Display display1_;
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc index 6067862..0ee06544 100644 --- a/chrome/browser/ui/views/overlay/overlay_window_views.cc +++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -45,9 +45,8 @@ }; OverlayWindowViews::OverlayWindowViews() { - // TODO(apacible): Change window type to TYPE_WINDOW_FRAMELESS. It is - // temporarily TYPE_WINDOW for resizing purposes. - views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); + views::Widget::InitParams params( + views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.bounds = CalculateAndUpdateBounds(); params.keep_on_top = true;
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container_browsertest.cc b/chrome/browser/ui/views/toolbar/browser_actions_container_browsertest.cc index c67312c5..78dc260 100644 --- a/chrome/browser/ui/views/toolbar/browser_actions_container_browsertest.cc +++ b/chrome/browser/ui/views/toolbar/browser_actions_container_browsertest.cc
@@ -397,8 +397,14 @@ EXPECT_TRUE(VerifyVisibleCount(1u)); } +class BrowserActionsContainerOverflowViewsTest + : public BrowserActionsContainerOverflowTest { + private: + test::ScopedMacViewsBrowserMode views_mode_{true}; +}; + // Test drag and drop between the overflow container and the main container. -IN_PROC_BROWSER_TEST_F(BrowserActionsContainerOverflowTest, +IN_PROC_BROWSER_TEST_F(BrowserActionsContainerOverflowViewsTest, TestOverflowDragging) { LoadExtensions();
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index b64af50..944bd9d7b 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -134,6 +134,7 @@ #include "base/sys_info.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_factory.h" +#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h" #include "chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.h" #include "chrome/browser/ui/webui/chromeos/certificate_manager_dialog_ui.h" #include "chrome/browser/ui/webui/chromeos/cryptohome_ui.h" @@ -466,6 +467,8 @@ if (url.host_piece() == chrome::kChromeUISysInternalsHost && SysInternalsUI::IsEnabled()) return &NewWebUI<SysInternalsUI>; + if (url.host_piece() == chrome::kChromeUIAssistantOptInHost) + return &NewWebUI<chromeos::AssistantOptInUI>; #if !defined(OFFICIAL_BUILD) if (!base::SysInfo::IsRunningOnChromeOS()) { if (url.host_piece() == chrome::kChromeUIDeviceEmulatorHost)
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h new file mode 100644 index 0000000..d406d9e --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h
@@ -0,0 +1,25 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_ASSISTANT_OPTIN_SCREEN_EXIT_CODE_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_ASSISTANT_OPTIN_SCREEN_EXIT_CODE_H_ + +#include <string> + +#include "base/callback.h" + +namespace chromeos { + +enum class AssistantOptInScreenExitCode { + VALUE_PROP_SKIPPED = 0, + VALUE_PROP_ACCEPTED = 1, + EXIT_CODES_COUNT +}; + +using OnAssistantOptInScreenExitCallback = + base::OnceCallback<void(AssistantOptInScreenExitCode exit_code)>; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_ASSISTANT_OPTIN_SCREEN_EXIT_CODE_H_
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc new file mode 100644 index 0000000..fe56a24e --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
@@ -0,0 +1,124 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h" + +#include <memory> + +#include "base/bind.h" +#include "base/macros.h" +#include "chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.h" +#include "chrome/common/url_constants.h" +#include "chrome/grit/browser_resources.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" + +namespace chromeos { + +namespace { + +bool is_active = false; + +constexpr int kAssistantOptInDialogWidth = 576; +constexpr int kAssistantOptInDialogHeight = 480; + +} // namespace + +AssistantOptInUI::AssistantOptInUI(content::WebUI* web_ui) + : ui::WebDialogUI(web_ui), weak_factory_(this) { + // Set up the chrome://assistant-optin source. + content::WebUIDataSource* source = + content::WebUIDataSource::Create(chrome::kChromeUIAssistantOptInHost); + + AddScreenHandler(std::make_unique<ValuePropScreenHandler>( + base::BindOnce(&AssistantOptInUI::OnExit, weak_factory_.GetWeakPtr()))); + + base::DictionaryValue localized_strings; + for (auto* handler : screen_handlers_) + handler->GetLocalizedStrings(&localized_strings); + source->AddLocalizedStrings(localized_strings); + + source->SetJsonPath("strings.js"); + + source->AddResourcePath("assistant_optin.js", IDR_ASSISTANT_OPTIN_JS); + source->SetDefaultResource(IDR_ASSISTANT_OPTIN_HTML); + + content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source); +} + +AssistantOptInUI::~AssistantOptInUI() {} + +void AssistantOptInUI::AddScreenHandler( + std::unique_ptr<BaseWebUIHandler> handler) { + screen_handlers_.push_back(handler.get()); + web_ui()->AddMessageHandler(std::move(handler)); +} + +void AssistantOptInUI::OnExit(AssistantOptInScreenExitCode exit_code) { + switch (exit_code) { + case AssistantOptInScreenExitCode::VALUE_PROP_SKIPPED: + // TODO(updowndota) Update the action to use the new Assistant service. + GetVoiceInteractionHomeService()->OnAssistantCanceled(); + CloseDialog(nullptr); + break; + case AssistantOptInScreenExitCode::VALUE_PROP_ACCEPTED: + // TODO(updowndota) Update the action to use the new Assistant service. + GetVoiceInteractionHomeService()->OnAssistantAppRequested(); + CloseDialog(nullptr); + break; + default: + NOTREACHED(); + } +} + +arc::ArcVoiceInteractionArcHomeService* +AssistantOptInUI::GetVoiceInteractionHomeService() { + Profile* const profile = Profile::FromWebUI(web_ui()); + arc::ArcVoiceInteractionArcHomeService* const home_service = + arc::ArcVoiceInteractionArcHomeService::GetForBrowserContext(profile); + DCHECK(home_service); + return home_service; +} + +// AssistantOptInDialog + +// static +void AssistantOptInDialog::Show() { + DCHECK(!is_active); + AssistantOptInDialog* dialog = new AssistantOptInDialog(); + dialog->ShowSystemDialog(); +} + +// static +bool AssistantOptInDialog::IsActive() { + return is_active; +} + +AssistantOptInDialog::AssistantOptInDialog() + : SystemWebDialogDelegate(GURL(chrome::kChromeUIAssistantOptInURL), + base::string16()) { + DCHECK(!is_active); + is_active = true; +} + +AssistantOptInDialog::~AssistantOptInDialog() { + is_active = false; +} + +void AssistantOptInDialog::GetDialogSize(gfx::Size* size) const { + size->SetSize(kAssistantOptInDialogWidth, kAssistantOptInDialogHeight); +} + +std::string AssistantOptInDialog::GetDialogArgs() const { + return std::string(); +} + +bool AssistantOptInDialog::ShouldShowDialogTitle() const { + return false; +} + +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h new file mode 100644 index 0000000..7fff533 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h
@@ -0,0 +1,70 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_ASSISTANT_OPTIN_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_ASSISTANT_OPTIN_UI_H_ + +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h" +#include "chrome/browser/ui/webui/chromeos/login/base_webui_handler.h" +#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h" +#include "content/public/browser/web_ui_controller.h" +#include "ui/web_dialogs/web_dialog_ui.h" + +namespace arc { +class ArcVoiceInteractionArcHomeService; +} + +namespace chromeos { + +// Controller for chrome://assistant-optin/ page. +class AssistantOptInUI : public ui::WebDialogUI { + public: + explicit AssistantOptInUI(content::WebUI* web_ui); + ~AssistantOptInUI() override; + + private: + // Add message handler for optin screens. + void AddScreenHandler(std::unique_ptr<BaseWebUIHandler> handler); + + // Called by a screen when user's done with it. + void OnExit(AssistantOptInScreenExitCode exit_code); + + // Get ArcHomeService for user action handling. + arc::ArcVoiceInteractionArcHomeService* GetVoiceInteractionHomeService(); + + std::vector<BaseWebUIHandler*> screen_handlers_; + base::WeakPtrFactory<AssistantOptInUI> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(AssistantOptInUI); +}; + +// Dialog delegate for the assistant optin page. +class AssistantOptInDialog : public SystemWebDialogDelegate { + public: + // Shows the assistant optin dialog. + static void Show(); + + // Returns whether the dialog is being shown. + static bool IsActive(); + + protected: + AssistantOptInDialog(); + ~AssistantOptInDialog() override; + + // ui::WebDialogDelegate + void GetDialogSize(gfx::Size* size) const override; + std::string GetDialogArgs() const override; + bool ShouldShowDialogTitle() const override; + + private: + DISALLOW_COPY_AND_ASSIGN(AssistantOptInDialog); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_ASSISTANT_OPTIN_UI_H_
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.cc new file mode 100644 index 0000000..e601e28f --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.cc
@@ -0,0 +1,66 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.h" + +#include "chrome/browser/browser_process.h" +#include "chrome/grit/generated_resources.h" +#include "components/login/localized_values_builder.h" + +namespace { + +const char kJsScreenPath[] = "AssistantValuePropScreen"; + +constexpr const char kUserActionSkipPressed[] = "skip-pressed"; +constexpr const char kUserActionNextPressed[] = "next-pressed"; + +} // namespace + +namespace chromeos { + +ValuePropScreenHandler::ValuePropScreenHandler( + OnAssistantOptInScreenExitCallback callback) + : BaseWebUIHandler(), exit_callback_(std::move(callback)) { + set_call_js_prefix(kJsScreenPath); +} + +ValuePropScreenHandler::~ValuePropScreenHandler() = default; + +void ValuePropScreenHandler::DeclareLocalizedValues( + ::login::LocalizedValuesBuilder* builder) { + builder->Add("locale", g_browser_process->GetApplicationLocale()); + builder->Add("voiceInteractionValuePropLoading", + IDS_VOICE_INTERACTION_VALUE_PROP_LOADING); + builder->Add("voiceInteractionValuePropLoadErrorTitle", + IDS_VOICE_INTERACTION_VALUE_PROP_LOAD_ERROR_TITLE); + builder->Add("voiceInteractionValuePropLoadErrorMessage", + IDS_VOICE_INTERACTION_VALUE_PROP_LOAD_ERROR_MESSAGE); + builder->Add("voiceInteractionValuePropSkipButton", + IDS_VOICE_INTERACTION_VALUE_PROP_SKIP_BUTTON); + builder->Add("voiceInteractionValuePropRetryButton", + IDS_VOICE_INTERACTION_VALUE_PROP_RETRY_BUTTON); + builder->Add("voiceInteractionValuePropNextButton", + IDS_VOICE_INTERACTION_VALUE_PROP_NEXT_BUTTION); + + builder->Add("back", IDS_EULA_BACK_BUTTON); + builder->Add("next", IDS_EULA_NEXT_BUTTON); +} + +void ValuePropScreenHandler::RegisterMessages() { + AddPrefixedCallback("userActed", &ValuePropScreenHandler::HandleUserAction); +} + +void ValuePropScreenHandler::Initialize() {} + +void ValuePropScreenHandler::HandleUserAction(const std::string& action) { + DCHECK(exit_callback_); + if (action == kUserActionSkipPressed) + std::move(exit_callback_) + .Run(AssistantOptInScreenExitCode::VALUE_PROP_SKIPPED); + else if (action == kUserActionNextPressed) + std::move(exit_callback_) + .Run(AssistantOptInScreenExitCode::VALUE_PROP_ACCEPTED); +} + +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.h b/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.h new file mode 100644 index 0000000..ec8e0324 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.h
@@ -0,0 +1,38 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_VALUE_PROP_SCREEN_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_VALUE_PROP_SCREEN_HANDLER_H_ + +#include <memory> +#include <string> + +#include "base/macros.h" +#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h" +#include "chrome/browser/ui/webui/chromeos/login/base_webui_handler.h" + +namespace chromeos { + +class ValuePropScreenHandler : public BaseWebUIHandler { + public: + explicit ValuePropScreenHandler(OnAssistantOptInScreenExitCallback callback); + ~ValuePropScreenHandler() override; + + // BaseWebUIHandler: + void DeclareLocalizedValues( + ::login::LocalizedValuesBuilder* builder) override; + void RegisterMessages() override; + void Initialize() override; + + private: + void HandleUserAction(const std::string& action); + + OnAssistantOptInScreenExitCallback exit_callback_; + + DISALLOW_COPY_AND_ASSIGN(ValuePropScreenHandler); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_VALUE_PROP_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc index 60482c6..aab42a4 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -35,6 +35,7 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/chromium_strings.h" +#include "chrome/grit/component_extension_resources.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/print_preview_resources.h" #include "chrome/grit/print_preview_resources_map.h" @@ -420,13 +421,92 @@ } void SetupPrintPreviewPlugin(content::WebUIDataSource* source) { - source->AddResourcePath("pdf_preview.html", - IDR_PRINT_PREVIEW_PDF_PREVIEW_HTML); + source->AddResourcePath("pdf/index.html", IDR_PDF_INDEX_HTML); + source->AddResourcePath("pdf/index.css", IDR_PDF_INDEX_CSS); + source->AddResourcePath("pdf/main.js", IDR_PDF_MAIN_JS); + source->AddResourcePath("pdf/pdf.js", IDR_PDF_PDF_JS); + source->AddResourcePath("pdf/toolbar_manager.js", IDR_PDF_UI_MANAGER_JS); + source->AddResourcePath("pdf/pdf_fitting_type.js", + IDR_PDF_PDF_FITTING_TYPE_JS); + source->AddResourcePath("pdf/viewport.js", IDR_PDF_VIEWPORT_JS); + source->AddResourcePath("pdf/open_pdf_params_parser.js", + IDR_PDF_OPEN_PDF_PARAMS_PARSER_JS); + source->AddResourcePath("pdf/navigator.js", IDR_PDF_NAVIGATOR_JS); + source->AddResourcePath("pdf/viewport_scroller.js", + IDR_PDF_VIEWPORT_SCROLLER_JS); + source->AddResourcePath("pdf/pdf_scripting_api.js", + IDR_PDF_PDF_SCRIPTING_API_JS); + source->AddResourcePath("pdf/zoom_manager.js", IDR_PDF_ZOOM_MANAGER_JS); + source->AddResourcePath("pdf/gesture_detector.js", + IDR_PDF_GESTURE_DETECTOR_JS); + source->AddResourcePath("pdf/browser_api.js", IDR_PDF_BROWSER_API_JS); + source->AddResourcePath("pdf/metrics.js", IDR_PDF_METRICS_JS); + source->AddResourcePath("pdf/coords_transformer.js", + IDR_PDF_COORDS_TRANSFORMER_JS); + + source->AddResourcePath("pdf/elements/shared-vars.html", + IDR_PDF_SHARED_VARS_HTML); + source->AddResourcePath("pdf/elements/icons.html", IDR_PDF_ICONS_HTML); + source->AddResourcePath("pdf/elements/viewer-bookmark/viewer-bookmark.html", + IDR_PDF_VIEWER_BOOKMARK_HTML); + source->AddResourcePath("pdf/elements/viewer-bookmark/viewer-bookmark.js", + IDR_PDF_VIEWER_BOOKMARK_JS); + source->AddResourcePath( + "pdf/elements/viewer-bookmarks-content/viewer-bookmarks-content.html", + IDR_PDF_VIEWER_BOOKMARKS_CONTENT_HTML); + source->AddResourcePath( + "pdf/elements/viewer-bookmarks-content/viewer-bookmarks-content.js", + IDR_PDF_VIEWER_BOOKMARKS_CONTENT_JS); + source->AddResourcePath( + "pdf/elements/viewer-error-screen/viewer-error-screen.html", + IDR_PDF_VIEWER_ERROR_SCREEN_HTML); + source->AddResourcePath( + "pdf/elements/viewer-error-screen/viewer-error-screen.js", + IDR_PDF_VIEWER_ERROR_SCREEN_JS); + source->AddResourcePath( + "pdf/elements/viewer-page-indicator/viewer-page-indicator.html", + IDR_PDF_VIEWER_PAGE_INDICATOR_HTML); + source->AddResourcePath( + "pdf/elements/viewer-page-indicator/viewer-page-indicator.js", + IDR_PDF_VIEWER_PAGE_INDICATOR_JS); + source->AddResourcePath( + "pdf/elements/viewer-page-selector/viewer-page-selector.html", + IDR_PDF_VIEWER_PAGE_SELECTOR_HTML); + source->AddResourcePath( + "pdf/elements/viewer-page-selector/viewer-page-selector.js", + IDR_PDF_VIEWER_PAGE_SELECTOR_JS); + source->AddResourcePath( + "pdf/elements/viewer-password-screen/viewer-password-screen.html", + IDR_PDF_VIEWER_PASSWORD_SCREEN_HTML); + source->AddResourcePath( + "pdf/elements/viewer-password-screen/viewer-password-screen.js", + IDR_PDF_VIEWER_PASSWORD_SCREEN_JS); + source->AddResourcePath( + "pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html", + IDR_PDF_VIEWER_PDF_TOOLBAR_HTML); + source->AddResourcePath( + "pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js", + IDR_PDF_VIEWER_PDF_TOOLBAR_JS); + source->AddResourcePath( + "pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html", + IDR_PDF_VIEWER_TOOLBAR_DROPDOWN_HTML); + source->AddResourcePath( + "pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js", + IDR_PDF_VIEWER_TOOLBAR_DROPDOWN_JS); + source->AddResourcePath( + "pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.html", + IDR_PDF_VIEWER_ZOOM_BUTTON_HTML); + source->AddResourcePath( + "pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.js", + IDR_PDF_VIEWER_ZOOM_BUTTON_JS); + source->AddResourcePath( + "pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html", + IDR_PDF_VIEWER_ZOOM_SELECTOR_HTML); + source->AddResourcePath( + "pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js", + IDR_PDF_VIEWER_ZOOM_SELECTOR_JS); + source->SetRequestFilter(base::BindRepeating(&HandleRequestCallback)); - source->OverrideContentSecurityPolicyScriptSrc( - base::StringPrintf("script-src chrome://resources 'self' 'unsafe-eval' " - "chrome-extension://%s;", - extension_misc::kPdfExtensionId)); source->OverrideContentSecurityPolicyChildSrc("child-src 'self';"); source->DisableDenyXFrameOptions(); source->OverrideContentSecurityPolicyObjectSrc("object-src 'self';");
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc index c3d1a1d2..2475c9d 100644 --- a/chrome/browser/ui/webui/settings/md_settings_ui.cc +++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -230,7 +230,6 @@ #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) bool has_incompatible_applications = - ProblematicProgramsUpdater::IsIncompatibleApplicationsWarningEnabled() && ProblematicProgramsUpdater::HasCachedPrograms(); html_source->AddBoolean("showIncompatibleApplications", has_incompatible_applications);
diff --git a/chrome/browser/vr/PRESUBMIT.py b/chrome/browser/vr/PRESUBMIT.py index 09b5bb6..c3aa1c2 100644 --- a/chrome/browser/vr/PRESUBMIT.py +++ b/chrome/browser/vr/PRESUBMIT.py
@@ -58,7 +58,7 @@ cl, [ 'luci.chromium.try:linux_optional_gpu_tests_rel', - 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'luci.chromium.try:mac_optional_gpu_tests_rel', 'master.tryserver.chromium.win:win_optional_gpu_tests_rel', 'master.tryserver.chromium.android:android_optional_gpu_tests_rel', 'master.tryserver.chromium.linux:linux_vr',
diff --git a/chrome/browser/vr/elements/content_element.cc b/chrome/browser/vr/elements/content_element.cc index 9d0b8b8..45066b9 100644 --- a/chrome/browser/vr/elements/content_element.cc +++ b/chrome/browser/vr/elements/content_element.cc
@@ -48,17 +48,11 @@ void ContentElement::Render(UiElementRenderer* renderer, const CameraModel& model) const { gfx::RectF copy_rect(0, 0, 1, 1); - if (texture_id_) { - renderer->DrawTexturedQuad(texture_id_, texture_location_, - model.view_proj_matrix * world_space_transform(), - copy_rect, computed_opacity(), size(), - corner_radius()); - } - if (overlay_texture_id_) { - renderer->DrawTexturedQuad(overlay_texture_id_, overlay_texture_location_, - model.view_proj_matrix * world_space_transform(), - copy_rect, computed_opacity(), size(), - corner_radius()); + if (texture_id_ || overlay_texture_id_) { + renderer->DrawTexturedQuad( + texture_id_, overlay_texture_id_, texture_location_, + model.view_proj_matrix * world_space_transform(), copy_rect, + computed_opacity(), size(), corner_radius()); } }
diff --git a/chrome/browser/vr/elements/textured_element.cc b/chrome/browser/vr/elements/textured_element.cc index afb7624..dc3e897 100644 --- a/chrome/browser/vr/elements/textured_element.cc +++ b/chrome/browser/vr/elements/textured_element.cc
@@ -90,7 +90,7 @@ gfx::RectF copy_rect(0, 0, drawn_size.width() / texture_size_.width(), drawn_size.height() / texture_size_.height()); renderer->DrawTexturedQuad( - texture_handle_, UiElementRenderer::kTextureLocationLocal, + texture_handle_, 0, UiElementRenderer::kTextureLocationLocal, model.view_proj_matrix * world_space_transform(), copy_rect, computed_opacity(), size(), corner_radius()); }
diff --git a/chrome/browser/vr/renderers/external_textured_quad_renderer.cc b/chrome/browser/vr/renderers/external_textured_quad_renderer.cc index 5786b09..36d7359 100644 --- a/chrome/browser/vr/renderers/external_textured_quad_renderer.cc +++ b/chrome/browser/vr/renderers/external_textured_quad_renderer.cc
@@ -15,15 +15,20 @@ static constexpr char const* kFragmentShader = OEIE_SHADER( precision highp float; uniform samplerExternalOES u_Texture; + uniform samplerExternalOES u_OverlayTexture; uniform vec4 u_CopyRect; varying vec2 v_TexCoordinate; varying vec2 v_CornerPosition; uniform mediump float u_Opacity; + uniform mediump float u_OverlayOpacity; void main() { vec2 scaledTex = vec2(u_CopyRect[0] + v_TexCoordinate.x * u_CopyRect[2], u_CopyRect[1] + v_TexCoordinate.y * u_CopyRect[3]); lowp vec4 color = texture2D(u_Texture, scaledTex); + lowp vec4 overlay_color = texture2D(u_OverlayTexture, scaledTex); + overlay_color = overlay_color * u_OverlayOpacity; + color = mix(color, overlay_color, overlay_color.a); float mask = 1.0 - step(1.0, length(v_CornerPosition)); gl_FragColor = color * u_Opacity * mask; }
diff --git a/chrome/browser/vr/renderers/textured_quad_renderer.cc b/chrome/browser/vr/renderers/textured_quad_renderer.cc index 008eaf2..aedd0c9 100644 --- a/chrome/browser/vr/renderers/textured_quad_renderer.cc +++ b/chrome/browser/vr/renderers/textured_quad_renderer.cc
@@ -140,10 +140,12 @@ static constexpr char const* kFragmentShader = SHADER( precision highp float; uniform sampler2D u_Texture; + uniform sampler2D u_OverlayTexture; uniform vec4 u_CopyRect; varying vec2 v_TexCoordinate; varying vec2 v_CornerPosition; uniform mediump float u_Opacity; + uniform mediump float u_OverlayOpacity; void main() { vec2 scaledTex = vec2(u_CopyRect[0] + v_TexCoordinate.x * u_CopyRect[2], @@ -174,12 +176,17 @@ copy_rect_handler_ = glGetUniformLocation(program_handle_, "u_CopyRect"); opacity_handle_ = glGetUniformLocation(program_handle_, "u_Opacity"); + overlay_opacity_handle_ = + glGetUniformLocation(program_handle_, "u_OverlayOpacity"); texture_handle_ = glGetUniformLocation(program_handle_, "u_Texture"); + overlay_texture_handle_ = + glGetUniformLocation(program_handle_, "u_OverlayTexture"); } TexturedQuadRenderer::~TexturedQuadRenderer() = default; void TexturedQuadRenderer::AddQuad(int texture_data_handle, + int overlay_texture_data_handle, const gfx::Transform& model_view_proj_matrix, const gfx::RectF& copy_rect, float opacity, @@ -187,6 +194,7 @@ float corner_radius) { QuadData quad; quad.texture_data_handle = texture_data_handle; + quad.overlay_texture_data_handle = overlay_texture_data_handle; quad.model_view_proj_matrix = model_view_proj_matrix; quad.copy_rect = copy_rect; quad.opacity = opacity; @@ -200,6 +208,7 @@ return; int last_texture = 0; + int last_overlay_texture = -1; float last_opacity = -1.0f; gfx::SizeF last_element_size; float last_corner_radius = -1.0f; @@ -212,9 +221,10 @@ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_); // Link texture data with texture unit. - glActiveTexture(GL_TEXTURE0); glUniform1i(texture_handle_, 0); + glUniform1i(overlay_texture_handle_, 1); + // Set up position attribute. glVertexAttribPointer(position_handle_, kPositionDataSize, GL_FLOAT, false, kDataStride, VOID_OFFSET(kPositionDataOffset)); @@ -241,10 +251,19 @@ // Only change texture ID or opacity when they differ between quads. if (last_texture != quad.texture_data_handle) { last_texture = quad.texture_data_handle; + glActiveTexture(GL_TEXTURE0); glBindTexture(TextureType(), last_texture); SetTexParameters(TextureType()); } + if (last_overlay_texture != quad.overlay_texture_data_handle) { + last_overlay_texture = quad.overlay_texture_data_handle; + glActiveTexture(GL_TEXTURE1); + glBindTexture(TextureType(), last_overlay_texture); + SetTexParameters(TextureType()); + glUniform1f(overlay_opacity_handle_, last_overlay_texture ? 1.0f : 0.0f); + } + if (last_opacity != quad.opacity) { last_opacity = quad.opacity; glUniform1f(opacity_handle_, last_opacity);
diff --git a/chrome/browser/vr/renderers/textured_quad_renderer.h b/chrome/browser/vr/renderers/textured_quad_renderer.h index 0ea4b89..05c299f 100644 --- a/chrome/browser/vr/renderers/textured_quad_renderer.h +++ b/chrome/browser/vr/renderers/textured_quad_renderer.h
@@ -24,6 +24,7 @@ // Enqueues a textured quad for rendering. The GL will ultimately be issued // in |Flush|. void AddQuad(int texture_data_handle, + int overlay_texture_data_handle, const gfx::Transform& model_view_proj_matrix, const gfx::RectF& copy_rect, float opacity, @@ -44,6 +45,7 @@ private: struct QuadData { int texture_data_handle; + int overlay_texture_data_handle; gfx::Transform model_view_proj_matrix; gfx::RectF copy_rect; float opacity; @@ -58,7 +60,9 @@ GLuint model_view_proj_matrix_handle_; GLuint corner_offset_handle_; GLuint opacity_handle_; + GLuint overlay_opacity_handle_; GLuint texture_handle_; + GLuint overlay_texture_handle_; GLuint copy_rect_handler_; // Attributes
diff --git a/chrome/browser/vr/test/fake_ui_element_renderer.cc b/chrome/browser/vr/test/fake_ui_element_renderer.cc index 4714e5c3..800fc77 100644 --- a/chrome/browser/vr/test/fake_ui_element_renderer.cc +++ b/chrome/browser/vr/test/fake_ui_element_renderer.cc
@@ -13,6 +13,7 @@ void FakeUiElementRenderer::DrawTexturedQuad( int texture_data_handle, + int overlay_texture_data_handle, TextureLocation texture_location, const gfx::Transform& view_proj_matrix, const gfx::RectF& copy_rect,
diff --git a/chrome/browser/vr/test/fake_ui_element_renderer.h b/chrome/browser/vr/test/fake_ui_element_renderer.h index 55f92a2..0c69424 100644 --- a/chrome/browser/vr/test/fake_ui_element_renderer.h +++ b/chrome/browser/vr/test/fake_ui_element_renderer.h
@@ -19,6 +19,7 @@ float opacity() const { return opacity_; } void DrawTexturedQuad(int texture_data_handle, + int overlay_texture_data_handle, TextureLocation texture_location, const gfx::Transform& view_proj_matrix, const gfx::RectF& copy_rect,
diff --git a/chrome/browser/vr/testapp/test_keyboard_renderer.cc b/chrome/browser/vr/testapp/test_keyboard_renderer.cc index e88a7479..d9c46994 100644 --- a/chrome/browser/vr/testapp/test_keyboard_renderer.cc +++ b/chrome/browser/vr/testapp/test_keyboard_renderer.cc
@@ -51,7 +51,7 @@ void TestKeyboardRenderer::Draw(const CameraModel& model, const gfx::Transform& world_space_transform) { renderer_->DrawTexturedQuad( - texture_handle_, UiElementRenderer::kTextureLocationLocal, + texture_handle_, 0, UiElementRenderer::kTextureLocationLocal, model.view_proj_matrix * world_space_transform, gfx::RectF(0, 0, 1, 1), 1, {drawn_size_.width(), drawn_size_.height()}, 0); }
diff --git a/chrome/browser/vr/ui.cc b/chrome/browser/vr/ui.cc index d8ae6dc3..d69c3d40 100644 --- a/chrome/browser/vr/ui.cc +++ b/chrome/browser/vr/ui.cc
@@ -387,7 +387,12 @@ os << std::endl; scene_->root_element().DumpHierarchy(std::vector<size_t>(), &os, include_bindings); - LOG(ERROR) << os.str(); + + std::stringstream ss(os.str()); + std::string line; + while (std::getline(ss, line, '\n')) { + LOG(ERROR) << line; + } #endif }
diff --git a/chrome/browser/vr/ui_element_renderer.cc b/chrome/browser/vr/ui_element_renderer.cc index fbb98d7e..9bb787a 100644 --- a/chrome/browser/vr/ui_element_renderer.cc +++ b/chrome/browser/vr/ui_element_renderer.cc
@@ -53,6 +53,7 @@ void UiElementRenderer::DrawTexturedQuad( int texture_data_handle, + int overlay_texture_data_handle, TextureLocation texture_location, const gfx::Transform& model_view_proj_matrix, const gfx::RectF& copy_rect, @@ -69,8 +70,9 @@ ? external_textured_quad_renderer_.get() : textured_quad_renderer_.get(); FlushIfNecessary(renderer); - renderer->AddQuad(texture_data_handle, model_view_proj_matrix, copy_rect, - opacity, element_size, corner_radius); + renderer->AddQuad(texture_data_handle, overlay_texture_data_handle, + model_view_proj_matrix, copy_rect, opacity, element_size, + corner_radius); } void UiElementRenderer::DrawGradientQuad(
diff --git a/chrome/browser/vr/ui_element_renderer.h b/chrome/browser/vr/ui_element_renderer.h index 28c37560..b141792 100644 --- a/chrome/browser/vr/ui_element_renderer.h +++ b/chrome/browser/vr/ui_element_renderer.h
@@ -60,6 +60,7 @@ VIRTUAL_FOR_MOCKS void DrawTexturedQuad( int texture_data_handle, + int overlay_texture_data_handle, TextureLocation texture_location, const gfx::Transform& model_view_proj_matrix, const gfx::RectF& copy_rect,
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 1eb24b9..5682b22 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -314,12 +314,6 @@ const base::Feature kImprovedRecoveryComponent{ "ImprovedRecoveryComponent", base::FEATURE_DISABLED_BY_DEFAULT}; -#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) -// A feature that controls whether Chrome warns about incompatible applications. -const base::Feature kIncompatibleApplicationsWarning{ - "IncompatibleApplicationsWarning", base::FEATURE_DISABLED_BY_DEFAULT}; -#endif - #if !defined(OS_ANDROID) // Enables Casting a Presentation API-enabled website to a secondary display. const base::Feature kLocalScreenCasting{"LocalScreenCasting",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index f86990b..b64e64dc 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -172,10 +172,6 @@ extern const base::Feature kImprovedRecoveryComponent; -#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) -extern const base::Feature kIncompatibleApplicationsWarning; -#endif - #if !defined(OS_ANDROID) extern const base::Feature kLocalScreenCasting; #endif
diff --git a/chrome/common/extensions/api/quick_unlock_private.idl b/chrome/common/extensions/api/quick_unlock_private.idl index 6ab2cab..dd0394a 100644 --- a/chrome/common/extensions/api/quick_unlock_private.idl +++ b/chrome/common/extensions/api/quick_unlock_private.idl
@@ -2,14 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Use the <code>chrome.quickUnlockPrivate</code> API to change tthe active quick -// unlock modes and to change their respective credentials. -// -// Quick unlock only supports unlocking an account that has already been signed -// in. -// -// The quick unlock authentication facilities are not available through this -// API; they are built directly into the lock screen. +// Use the <code>chrome.quickUnlockPrivate</code> API to change whether the +// lock screen is enabled and which modes are allowed (active) for unlocking a +// Chrome OS device from the lock screen. The API is also used to set quick +// unlock credentials. +// Note: The API is named 'quickUnlock' for historical reasons but it should be +// used for all lock screen settings. +// Note: This API can not be used to actually unlock the device. [platforms=("chromeos"), implemented_in="chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h"] @@ -69,6 +68,16 @@ static void getAuthToken(DOMString accountPassword, TokenResultCallback onComplete); + // Sets the lock screen enabled state. NOTE: The lock enabled state is + // reflected in the settings.enable_screen_lock pref, which can be read + // but not written using the settings_private API (which also provides + // policy information). This API must be used to change the pref. + // |token|: The token returned by $(ref:getAuthToken). + // |enabled|: Whether to enable the lock screen. + static void setLockScreenEnabled(DOMString token, + boolean enabled, + optional VoidResultCallback onComplete); + // Returns the set of quick unlock modes that are available for the user to // use. Some quick unlock modes may be disabled by policy. static void getAvailableModes(ModesCallback onComplete); @@ -98,10 +107,10 @@ // Update the set of quick unlock modes that are currently active/enabled. // |token|: The token returned by $(ref:getAuthToken). // |modes|: The quick unlock modes that should be active. - // |credentials|: The associated credential for each mode. To keep - // the credential the same for the associated mode, pass an empty string. + // |credentials|: The associated credential for each mode. To keep the + // credential the same for the associated mode, pass an empty string. // |onComplete|: Called with true if the quick unlock state was updated, - // false otherwise. The update is treated as a single atomic operation. + // false otherwise. The update is treated as a single atomic operation. static void setModes(DOMString token, QuickUnlockMode[] modes, DOMString[] credentials,
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 2736e567..3dbe0464 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -2097,44 +2097,9 @@ #endif #if BUILDFLAG(ENABLE_APP_LIST) -// The directory in user data dir that contains the profile to be used with the -// app launcher. -const char kAppListProfile[] = "app_list.profile"; - -// The number of times the app launcher was launched since last ping and -// the time of the last ping. -const char kAppListLaunchCount[] = "app_list.launch_count"; -const char kLastAppListLaunchPing[] = "app_list.last_launch_ping"; - -// The number of times the an app was launched from the app launcher since last -// ping and the time of the last ping. -const char kAppListAppLaunchCount[] = "app_list.app_launch_count"; -const char kLastAppListAppLaunchPing[] = "app_list.last_app_launch_ping"; - -// A boolean that tracks whether the user has ever enabled the app launcher. -const char kAppLauncherHasBeenEnabled[] = - "apps.app_launcher.has_been_enabled"; - -// An enum indicating how the app launcher was enabled. E.g., via webstore, app -// install, command line, etc. For UMA. -const char kAppListEnableMethod[] = "app_list.how_enabled"; - -// The time that the app launcher was enabled. Cleared when UMA is recorded. -const char kAppListEnableTime[] = "app_list.when_enabled"; - // Keeps local state of app list while sync service is not available. const char kAppListLocalState[] = "app_list.local_state"; - -// A dictionary that tracks the Drive app to Chrome app mapping. The key is -// a Drive app id and the value is the corresponding Chrome app id. The pref -// is unsynable and used to track local mappings only. -const char kAppLauncherDriveAppMapping[] = - "apps.app_launcher.drive_app_mapping"; - -// A list of Drive app ids that tracks the uninstallable Drive apps. -const char kAppLauncherUninstalledDriveApps[] = - "apps.app_launcher.uninstalled_drive_apps"; -#endif // BUILDFLAG(ENABLE_APP_LIST) +#endif #if defined(OS_WIN) // If set, the user requested to launch the app with this extension id while
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index ec53ec0..d624baf 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -754,17 +754,7 @@ #endif #if BUILDFLAG(ENABLE_APP_LIST) -extern const char kAppListProfile[]; -extern const char kLastAppListLaunchPing[]; -extern const char kAppListLaunchCount[]; -extern const char kLastAppListAppLaunchPing[]; -extern const char kAppListAppLaunchCount[]; -extern const char kAppLauncherHasBeenEnabled[]; -extern const char kAppListEnableMethod[]; -extern const char kAppListEnableTime[]; extern const char kAppListLocalState[]; -extern const char kAppLauncherDriveAppMapping[]; -extern const char kAppLauncherUninstalledDriveApps[]; #endif // BUILDFLAG(ENABLE_APP_LIST) #if defined(OS_WIN)
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 5e3c3929..94844462 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -217,6 +217,8 @@ const char kChromeUITermsOemURL[] = "chrome://terms/oem"; const char kChromeUIUserImageHost[] = "userimage"; const char kChromeUIUserImageURL[] = "chrome://userimage/"; +const char kChromeUIAssistantOptInHost[] = "assistant-optin"; +const char kChromeUIAssistantOptInURL[] = "chrome://assistant-optin/"; #endif // defined(OS_CHROMEOS) #if defined(OS_WIN) @@ -387,6 +389,7 @@ kChromeUIPowerHost, kChromeUIInternetConfigDialogHost, kChromeUIInternetDetailDialogHost, + kChromeUIAssistantOptInHost, #endif #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) kChromeUIDiscardsHost,
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 4c13040..3d601a7 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -213,6 +213,8 @@ extern const char kChromeUITermsOemURL[]; extern const char kChromeUIUserImageHost[]; extern const char kChromeUIUserImageURL[]; +extern const char kChromeUIAssistantOptInHost[]; +extern const char kChromeUIAssistantOptInURL[]; #endif // defined(OS_CHROMEOS) #if defined(OS_WIN)
diff --git a/chrome/installer/linux/BUILD.gn b/chrome/installer/linux/BUILD.gn index 2ea8f90..fbabd6c3 100644 --- a/chrome/installer/linux/BUILD.gn +++ b/chrome/installer/linux/BUILD.gn
@@ -49,10 +49,8 @@ # The widevine BUILD.gn only produces shared libraries for x86 and x64 if (is_chrome_branded && (current_cpu == "x86" || current_cpu == "x64")) { - packaging_files_shlibs += [ - "$root_out_dir/$widevine_cdm_path/libwidevinecdmadapter.so", - "$root_out_dir/$widevine_cdm_path/libwidevinecdm.so", - ] + packaging_files_shlibs += + [ "$root_out_dir/$widevine_cdm_path/libwidevinecdm.so" ] } if (!libcpp_is_static && use_custom_libcxx) { @@ -370,10 +368,7 @@ ] } if (current_cpu == "x86" || current_cpu == "x64") { - public_deps += [ - "//third_party/widevine/cdm:widevinecdm", - "//third_party/widevine/cdm:widevinecdmadapter", - ] + public_deps += [ "//third_party/widevine/cdm" ] } if (!is_chromeos) { public_deps += [ ":rpm_packaging_files" ]
diff --git a/chrome/installer/linux/common/installer.include b/chrome/installer/linux/common/installer.include index 96996f5d..58b8061 100644 --- a/chrome/installer/linux/common/installer.include +++ b/chrome/installer/linux/common/installer.include
@@ -194,8 +194,7 @@ fi # Widevine CDM. - if [ -f "${BUILDDIR}/libwidevinecdmadapter.so" ]; then - install -m ${SHLIB_PERMS} -s "${BUILDDIR}/libwidevinecdmadapter.so" "${STAGEDIR}/${INSTALLDIR}/" + if [ -f "${BUILDDIR}/libwidevinecdm.so" ]; then # No need to strip; libwidevinecdm.so starts out stripped. install -m ${SHLIB_PERMS} "${BUILDDIR}/libwidevinecdm.so" "${STAGEDIR}/${INSTALLDIR}/" fi
diff --git a/chrome/installer/mac/sign_versioned_dir.sh.in b/chrome/installer/mac/sign_versioned_dir.sh.in index a9db32c..7a853e3 100644 --- a/chrome/installer/mac/sign_versioned_dir.sh.in +++ b/chrome/installer/mac/sign_versioned_dir.sh.in
@@ -91,7 +91,6 @@ helper_app="${versioned_dir}/@MAC_PRODUCT_NAME@ Helper.app" app_mode_loader_app="${framework}/Resources/app_mode_loader.app" app_mode_loader="${app_mode_loader_app}/Contents/MacOS/app_mode_loader" -widevine_plugin="${framework}/Libraries/WidevineCdm/_platform_specific/mac_x64/widevinecdmadapter.plugin" codesign_with_options "${crashpad_handler}" \ "${enforcement_flags_helpers}" \ @@ -120,12 +119,6 @@ "${enforcement_flags_helpers}" \ "${xpc_bundle_id}" -# Only sign widevine plugin if it is present in the bundle. -# ${enforcement_flags*} are meaningless for dynamic libraries. -if [[ -f "${widevine_plugin}" ]]; then - codesign_with_options "${widevine_plugin}" "" "widevinecdmadapter" -fi - # The framework is a dylib, so ${enforcement_flags_helpers} are meaningless. codesign_with_options "${framework}" "" "com.google.Chrome.framework" @@ -133,10 +126,6 @@ "${enforcement_flags_app}" \ "com.google.Chrome.helper" -if [[ -f "${widevine_plugin}" ]]; then - codesign_display_and_verify "${widevine_plugin}" -fi - codesign_display_and_verify "${crashpad_handler}" --deep codesign_display_and_verify "${app_mode_loader}" --ignore-resources codesign_display_and_verify "${notification_service}" --deep
diff --git a/chrome/installer/mini_installer/chrome.release b/chrome/installer/mini_installer/chrome.release index cc944d6..4a502c6 100644 --- a/chrome/installer/mini_installer/chrome.release +++ b/chrome/installer/mini_installer/chrome.release
@@ -79,10 +79,8 @@ WidevineCdm\manifest.json: %(VersionDir)s\WidevineCdm\ WidevineCdm\_platform_specific\win_x86\widevinecdm.dll: %(VersionDir)s\WidevineCdm\_platform_specific\win_x86\ WidevineCdm\_platform_specific\win_x86\widevinecdm.dll.sig: %(VersionDir)s\WidevineCdm\_platform_specific\win_x86\ -WidevineCdm\_platform_specific\win_x86\widevinecdmadapter.dll: %(VersionDir)s\WidevineCdm\_platform_specific\win_x86\ WidevineCdm\_platform_specific\win_x64\widevinecdm.dll: %(VersionDir)s\WidevineCdm\_platform_specific\win_x64\ WidevineCdm\_platform_specific\win_x64\widevinecdm.dll.sig: %(VersionDir)s\WidevineCdm\_platform_specific\win_x64\ -WidevineCdm\_platform_specific\win_x64\widevinecdmadapter.dll: %(VersionDir)s\WidevineCdm\_platform_specific\win_x64\ # # MEI Preload sub dir
diff --git a/chrome/installer/setup/install_worker.cc b/chrome/installer/setup/install_worker.cc index aa26cb1d..85b9e2ea 100644 --- a/chrome/installer/setup/install_worker.cc +++ b/chrome/installer/setup/install_worker.cc
@@ -890,6 +890,10 @@ AddOsUpgradeWorkItems(installer_state, setup_path, new_version, product, install_list); +#if defined(GOOGLE_CHROME_BUILD) + AddEnterpriseEnrollmentWorkItems(installer_state, setup_path, new_version, + product, install_list); +#endif AddFirewallRulesWorkItems(installer_state, dist, current_version == nullptr, install_list); @@ -1056,4 +1060,42 @@ } } +#if defined(GOOGLE_CHROME_BUILD) +void AddEnterpriseEnrollmentWorkItems(const InstallerState& installer_state, + const base::FilePath& setup_path, + const base::Version& new_version, + const Product& product, + WorkItemList* install_list) { + if (!installer_state.system_install()) + return; + + const HKEY root_key = installer_state.root_key(); + const base::string16 cmd_key( + GetRegCommandKey(product.distribution(), kCmdStoreDMToken)); + + if (installer_state.operation() == InstallerState::UNINSTALL) { + install_list->AddDeleteRegKeyWorkItem(root_key, cmd_key, KEY_WOW64_32KEY) + ->set_log_message("Removing store DM token command"); + } else { + // Register a command to allow Chrome to request Google Update to run + // setup.exe --store-dmtoken=<token>, which will store the specifed token in + // the registry. + base::CommandLine cmd_line( + installer_state.GetInstallerDirectory(new_version) + .Append(setup_path.BaseName())); + cmd_line.AppendSwitchASCII(switches::kStoreDMToken, "%1"); + cmd_line.AppendSwitch(switches::kSystemLevel); + cmd_line.AppendSwitch(switches::kVerboseLogging); + InstallUtil::AppendModeSwitch(&cmd_line); + + AppCommand cmd(cmd_line.GetCommandLineString()); + // TODO(alito): For now setting this command as web accessible is required + // by Google Update. Could revisit this should Google Update change the + // way permissions are handled for commands. + cmd.set_is_web_accessible(true); + cmd.AddWorkItems(root_key, cmd_key, install_list); + } +} +#endif + } // namespace installer
diff --git a/chrome/installer/setup/install_worker.h b/chrome/installer/setup/install_worker.h index 28b9e249..e145aa1 100644 --- a/chrome/installer/setup/install_worker.h +++ b/chrome/installer/setup/install_worker.h
@@ -119,6 +119,19 @@ const Product& product, WorkItemList* install_list); +#if defined(GOOGLE_CHROME_BUILD) +// Adds work items to add or remove the "store-dmtoken" command to |product|'s +// version key. This method is a no-op if this is anything other than +// system-level Chrome. The command is used when enrolling Chrome browser +// instances into enterprise management. |new_version| is the version of the +// product(s) currently being installed -- can be empty on uninstall. +void AddEnterpriseEnrollmentWorkItems(const InstallerState& installer_state, + const base::FilePath& setup_path, + const base::Version& new_version, + const Product& product, + WorkItemList* install_list); +#endif + } // namespace installer #endif // CHROME_INSTALLER_SETUP_INSTALL_WORKER_H_
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc index 2f68e9f..74cece8 100644 --- a/chrome/installer/setup/setup_main.cc +++ b/chrome/installer/setup/setup_main.cc
@@ -1021,6 +1021,20 @@ cmd_line.GetSwitchValueNative( installer::switches::kSetDisplayVersionValue)); *exit_code = OverwriteDisplayVersions(registry_product, registry_value); +#if defined(GOOGLE_CHROME_BUILD) + } else if (cmd_line.HasSwitch(installer::switches::kStoreDMToken)) { + // Write the specified token to the registry, overwriting any already + // existing value. + base::string16 token_switch_value = + cmd_line.GetSwitchValueNative(installer::switches::kStoreDMToken); + base::Optional<std::string> token; + if (!(token = installer::DecodeDMTokenSwitchValue(token_switch_value)) || + !installer::StoreDMToken(*token)) { + *exit_code = installer::STORE_DMTOKEN_FAILED; + } else { + *exit_code = installer::STORE_DMTOKEN_SUCCESS; + } +#endif } else { handled = false; }
diff --git a/chrome/installer/setup/setup_util.cc b/chrome/installer/setup/setup_util.cc index 15d0a00..0f1337df 100644 --- a/chrome/installer/setup/setup_util.cc +++ b/chrome/installer/setup/setup_util.cc
@@ -20,6 +20,7 @@ #include <string> #include <utility> +#include "base/base64.h" #include "base/bind.h" #include "base/callback_helpers.h" #include "base/command_line.h" @@ -879,4 +880,54 @@ windows_version >= base::win::VERSION_WIN10_RS1; } +base::Optional<std::string> DecodeDMTokenSwitchValue( + const base::string16& encoded_token) { + if (encoded_token.empty()) { + LOG(ERROR) << "Empty DMToken specified on the command line"; + return base::nullopt; + } + + // The token passed on the command line is base64-encoded, but since this is + // on Windows, it is passed in as a wide string containing base64 values only. + std::string token; + if (!base::IsStringASCII(encoded_token) || + !base::Base64Decode(base::UTF16ToASCII(encoded_token), &token)) { + LOG(ERROR) << "DMToken passed on the command line is not correctly encoded"; + return base::nullopt; + } + + return token; +} + +bool StoreDMToken(const std::string& token) { + DCHECK(install_static::IsSystemInstall()); + + std::wstring path; + std::wstring name; + InstallUtil::GetMachineLevelUserCloudPolicyDMTokenRegistryPath(&path, + &name); + + base::win::RegKey key; + LONG result = key.Create(HKEY_LOCAL_MACHINE, path.c_str(), + KEY_WRITE | KEY_WOW64_64KEY); + if (result != ERROR_SUCCESS) { + LOG(ERROR) << "Unable to create/open registry key HKLM\\" << path + << " for writing result=" << result; + return false; + } + + result = + key.WriteValue(name.c_str(), token.data(), + base::saturated_cast<DWORD>(token.size()), REG_BINARY); + if (result != ERROR_SUCCESS) { + LOG(ERROR) << "Unable to write specified DMToken to the registry at HKLM\\" + << path << "\\" << name << " result=" << result; + return false; + } + + VLOG(1) << "Successfully stored specified DMToken in the registry."; + + return true; +} + } // namespace installer
diff --git a/chrome/installer/setup/setup_util.h b/chrome/installer/setup/setup_util.h index b39be6f..1dde01a 100644 --- a/chrome/installer/setup/setup_util.h +++ b/chrome/installer/setup/setup_util.h
@@ -14,6 +14,7 @@ #include <memory> #include <vector> +#include "base/optional.h" #include "base/strings/string16.h" #include "base/time/time.h" #include "chrome/installer/util/browser_distribution.h" @@ -162,6 +163,16 @@ // tiles. bool OsSupportsDarkTextTiles(); +// Returns a DM token decoded from the base-64 |encoded_token|, or null in case +// of a decoding error. The returned DM token is an opaque binary blob and +// should not be treated as an ASCII or UTF-8 string. +base::Optional<std::string> DecodeDMTokenSwitchValue( + const base::string16& encoded_token); + +// Saves a DM token to a global location on the machine accessible to all +// install modes of the browser (i.e., stable and all three side-by-side modes). +bool StoreDMToken(const std::string& token); + } // namespace installer #endif // CHROME_INSTALLER_SETUP_SETUP_UTIL_H_
diff --git a/chrome/installer/setup/setup_util_unittest.cc b/chrome/installer/setup/setup_util_unittest.cc index 22e3439..c2ea3ad 100644 --- a/chrome/installer/setup/setup_util_unittest.cc +++ b/chrome/installer/setup/setup_util_unittest.cc
@@ -10,6 +10,7 @@ #include <memory> #include <string> +#include "base/base64.h" #include "base/command_line.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -18,6 +19,7 @@ #include "base/process/launch.h" #include "base/process/process_handle.h" #include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "base/test/histogram_tester.h" #include "base/test/test_reg_util_win.h" #include "base/test/test_timeouts.h" @@ -26,12 +28,15 @@ #include "base/win/registry.h" #include "base/win/scoped_handle.h" #include "chrome/install_static/install_details.h" +#include "chrome/install_static/install_util.h" +#include "chrome/install_static/test/scoped_install_details.h" #include "chrome/installer/setup/installer_state.h" #include "chrome/installer/setup/setup_constants.h" #include "chrome/installer/setup/setup_util.h" #include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/google_update_constants.h" #include "chrome/installer/util/installation_state.h" +#include "chrome/installer/util/install_util.h" #include "chrome/installer/util/updating_app_registration_data.h" #include "chrome/installer/util/util_constants.h" #include "testing/gtest/include/gtest/gtest.h" @@ -453,6 +458,44 @@ EXPECT_FALSE(start_time.is_null()); } +TEST(SetupUtilTest, DecodeDMTokenSwitchValue) { + // Expect false with empty or badly formed base64-encoded string. + EXPECT_FALSE(installer::DecodeDMTokenSwitchValue(L"")); + EXPECT_FALSE(installer::DecodeDMTokenSwitchValue(L"not-ascii\xff")); + EXPECT_FALSE(installer::DecodeDMTokenSwitchValue(L"not-base64-string")); + + std::string token("this is a token"); + std::string encoded; + base::Base64Encode(token, &encoded); + EXPECT_EQ(token, + *installer::DecodeDMTokenSwitchValue(base::UTF8ToUTF16(encoded))); +} + +TEST(SetupUtilTest, StoreDMTokenToRegistry) { + install_static::ScopedInstallDetails scoped_install_details(true); + registry_util::RegistryOverrideManager registry_override_manager; + registry_override_manager.OverrideRegistry(HKEY_LOCAL_MACHINE); + + std::string token("tokens are \0 binary data"); + EXPECT_TRUE(installer::StoreDMToken(token)); + + std::wstring path; + std::wstring name; + InstallUtil::GetMachineLevelUserCloudPolicyDMTokenRegistryPath(&path, &name); + base::win::RegKey key; + ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, path.c_str(), + KEY_QUERY_VALUE | KEY_WOW64_64KEY)); + + DWORD size = 64; + std::vector<char> raw_value(size); + DWORD dtype; + ASSERT_EQ(ERROR_SUCCESS, + key.ReadValue(name.c_str(), raw_value.data(), &size, &dtype)); + EXPECT_EQ(REG_BINARY, dtype); + ASSERT_EQ(token.length(), size); + EXPECT_EQ(0, memcmp(token.data(), raw_value.data(), size)); +} + namespace installer { class DeleteRegistryKeyPartialTest : public ::testing::Test {
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc index d3642b3..cfa3efe2 100644 --- a/chrome/installer/util/install_util.cc +++ b/chrome/installer/util/install_util.cc
@@ -503,7 +503,7 @@ bool system_install, const BrowserDistribution* dist) { DCHECK(dist); - base::win::RegKey key; + RegKey key; base::string16 downgrade_version; if (key.Open(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, dist->GetStateKey().c_str(), @@ -538,6 +538,70 @@ } } +// static +void InstallUtil::GetMachineLevelUserCloudPolicyEnrollmentTokenRegistryPath( + std::wstring* key_path, + std::wstring* value_name) { + // This token applies to all installs on the machine, even though only a + // system install can set it. This is to prevent users from doing a user + // install of chrome to get around policies. + *key_path = L"SOFTWARE\\Policies\\"; + install_static::AppendChromeInstallSubDirectory( + install_static::InstallDetails::Get().mode(), false /* !include_suffix */, + key_path); + *value_name = L"MachineLevelUserCloudPolicyEnrollmentToken"; +} + +// static +void InstallUtil::GetMachineLevelUserCloudPolicyDMTokenRegistryPath( + std::wstring* key_path, + std::wstring* value_name) { + // This token applies to all installs on the machine, even though only a + // system install can set it. This is to prevent users from doing a user + // install of chrome to get around policies. + *key_path = L"SOFTWARE\\"; + install_static::AppendChromeInstallSubDirectory( + install_static::InstallDetails::Get().mode(), false /* !include_suffix */, + key_path); + key_path->append(L"\\Enrollment"); + *value_name = L"dmtoken"; +} + +// static +std::wstring InstallUtil::GetMachineLevelUserCloudPolicyEnrollmentToken() { + // Because chrome needs to know if machine level user cloud policies must be + // initialized even before the entire policy service is brought up, this + // helper function exists to directly read the token from the system policies. + // + // Putting the enrollment token in the system policy area is a convenient + // way for administrators to enroll chrome throughout their fleet by pushing + // this token via SCCM. + // TODO(rogerta): This may not be the best place for the helpers dealing with + // the enrollment and/or DM tokens. See crbug.com/823852 for details. + std::wstring key_path; + std::wstring value_name; + GetMachineLevelUserCloudPolicyEnrollmentTokenRegistryPath(&key_path, + &value_name); + + RegKey key; + LONG result = key.Open(HKEY_LOCAL_MACHINE, key_path.c_str(), KEY_READ); + if (result != ERROR_SUCCESS) { + LOG(ERROR) << "Unable to create registry key HKLM\\" << key_path + << " for reading result=" << result; + return std::wstring(); + } + + std::wstring value; + result = key.ReadValue(value_name.c_str(), &value); + if (result != ERROR_SUCCESS) { + LOG(ERROR) << "Unable to read registry value HKLM\\" << key_path + << "\\" << value_name << " for writing result=" << result; + return std::wstring(); + } + + return value; +} + InstallUtil::ProgramCompare::ProgramCompare(const base::FilePath& path_to_match) : path_to_match_(path_to_match), file_info_() {
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h index 7c6bf75..cc67722 100644 --- a/chrome/installer/util/install_util.h +++ b/chrome/installer/util/install_util.h
@@ -190,6 +190,23 @@ const BrowserDistribution* dist, WorkItemList* list); + // Returns the registry key path and value name where the enrollment token is + // stored for machine level user cloud policies. + static void GetMachineLevelUserCloudPolicyEnrollmentTokenRegistryPath( + std::wstring* key_path, + std::wstring* value_name); + + // Returns the registry key path and value name where the enrollment token is + // stored for machine level user cloud policies. + static void GetMachineLevelUserCloudPolicyDMTokenRegistryPath( + std::wstring* key_path, + std::wstring* value_name); + + // Returns the token used to enroll this chrome instance for machine level + // user cloud policies. Returns an empty string if this machine should not + // be enrolled. + static std::wstring GetMachineLevelUserCloudPolicyEnrollmentToken(); + // A predicate that compares the program portion of a command line with a // given file path. First, the file paths are compared directly. If they do // not match, the filesystem is consulted to determine if the paths reference
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc index 601fdd05..4ed3469f 100644 --- a/chrome/installer/util/util_constants.cc +++ b/chrome/installer/util/util_constants.cc
@@ -124,6 +124,9 @@ // line flag so that we try the launch only once. const char kRunAsAdmin[] = "run-as-admin"; +// Saves the specified device management token to the registry. +const char kStoreDMToken[] = "store-dmtoken"; + // Combined with --uninstall, signals to setup.exe that this uninstall was // triggered by a self-destructing Chrome. const char kSelfDestruct[] = "self-destruct"; @@ -188,6 +191,7 @@ const wchar_t kChromeNewExe[] = L"new_chrome.exe"; const wchar_t kChromeOldExe[] = L"old_chrome.exe"; const wchar_t kCmdOnOsUpgrade[] = L"on-os-upgrade"; +const wchar_t kCmdStoreDMToken[] = L"store-dmtoken"; const wchar_t kEULASentinelFile[] = L"EULA Accepted"; const wchar_t kInstallBinaryDir[] = L"Application"; const wchar_t kInstallerDir[] = L"Installer";
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h index eaf99442..13232e50 100644 --- a/chrome/installer/util/util_constants.h +++ b/chrome/installer/util/util_constants.h
@@ -106,8 +106,11 @@ // delete all files that belong // to old versions of Chrome too // many times without success. - - MAX_INSTALL_STATUS = 64, // When adding a new result, bump this and update + STORE_DMTOKEN_FAILED = 64, // Failed to write the specified DMToken to the + // registry. + STORE_DMTOKEN_SUCCESS = 65, // Writing the specified DMToken to the registry + // succeeded. + MAX_INSTALL_STATUS = 66, // When adding a new result, bump this and update // the InstallStatus enum in histograms.xml. }; @@ -172,6 +175,7 @@ extern const char kRenameChromeExe[]; extern const char kRemoveChromeRegistration[]; extern const char kRunAsAdmin[]; +extern const char kStoreDMToken[]; extern const char kSelfDestruct[]; extern const char kSystemLevel[]; extern const char kTriggerActiveSetup[]; @@ -200,6 +204,7 @@ extern const wchar_t kChromeNewExe[]; extern const wchar_t kChromeOldExe[]; extern const wchar_t kCmdOnOsUpgrade[]; +extern const wchar_t kCmdStoreDMToken[]; extern const wchar_t kEULASentinelFile[]; extern const wchar_t kInstallBinaryDir[]; extern const wchar_t kInstallerDir[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index b1ddcc55..64021945 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1644,10 +1644,10 @@ "../browser/extensions/api/vpn_provider/vpn_provider_apitest.cc", "../browser/mash_service_registry_browsertest.cc", "../browser/signin/chromeos_mirror_account_consistency_browsertest.cc", + "../browser/ui/app_list/app_list_browsertest.cc", "../browser/ui/app_list/arc/arc_usb_host_permission_browsertest.cc", "../browser/ui/app_list/crostini/crostini_installer_view_browsertest.cc", "../browser/ui/ash/accelerator_commands_browsertest.cc", - "../browser/ui/ash/app_list/app_list_browsertest.cc", "../browser/ui/ash/chrome_new_window_client_browsertest.cc", "../browser/ui/ash/chrome_screenshot_grabber_browsertest.cc", "../browser/ui/ash/keyboard_controller_browsertest.cc", @@ -1966,7 +1966,7 @@ # Runtime dependencies. data_deps += [ "//media/cdm/library_cdm/clear_key_cdm", - "//third_party/widevine/cdm:widevinecdmadapter", + "//third_party/widevine/cdm", ] } if (enable_print_preview) { @@ -4300,7 +4300,6 @@ if (enable_app_list) { sources += [ "../browser/ui/app_list/app_context_menu_unittest.cc", - "../browser/ui/app_list/app_list_service_unittest.cc", "../browser/ui/app_list/app_list_syncable_service_unittest.cc", "../browser/ui/app_list/app_list_test_util.cc", "../browser/ui/app_list/app_list_test_util.h", @@ -4310,7 +4309,6 @@ "../browser/ui/app_list/arc/arc_app_utils_unittest.cc", "../browser/ui/app_list/arc/arc_vpn_provider_unittest.cc", "../browser/ui/app_list/extension_app_model_builder_unittest.cc", - "../browser/ui/app_list/profile_loader_unittest.cc", "../browser/ui/app_list/search/answer_card/answer_card_result_unittest.cc", "../browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc", "../browser/ui/app_list/search/arc/arc_app_data_search_provider_unittest.cc", @@ -4329,8 +4327,6 @@ "../browser/ui/app_list/test/fake_app_list_model_updater.h", "../browser/ui/app_list/test/fake_profile.cc", "../browser/ui/app_list/test/fake_profile.h", - "../browser/ui/app_list/test/fake_profile_store.cc", - "../browser/ui/app_list/test/fake_profile_store.h", "../browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc", ] deps += [ @@ -4817,7 +4813,7 @@ "../browser/chromeos/login/test/oobe_base_test.cc", "../browser/chromeos/login/test/oobe_base_test.h", "../browser/download/notification/download_notification_interactive_uitest.cc", - "../browser/ui/ash/app_list/app_list_interactive_uitest.cc", + "../browser/ui/app_list/app_list_interactive_uitest.cc", "../browser/ui/ash/tab_scrubber_browsertest.cc", "../browser/ui/views/apps/chrome_native_app_window_views_aura_ash_interactive_uitest.cc", "../browser/ui/webui/chromeos/login/oobe_display_chooser_browsertest.cc", @@ -5444,7 +5440,7 @@ deps += [ "//media/cdm:cdm_paths" ] data_deps = [ "//media/cdm/library_cdm/clear_key_cdm", - "//third_party/widevine/cdm:widevinecdmadapter", + "//third_party/widevine/cdm", ] }
diff --git a/chrome/test/chromedriver/test/test_expectations b/chrome/test/chromedriver/test/test_expectations index 0e5668e..8af6ec9 100644 --- a/chrome/test/chromedriver/test/test_expectations +++ b/chrome/test/chromedriver/test/test_expectations
@@ -274,33 +274,23 @@ # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2286 'CorrectEventFiringTest.testClearingAnElementShouldCauseTheOnChangeHandlerToFire', 'CorrectEventFiringTest.testClickEventsShouldBubble', - 'CorrectEventFiringTest.testSubmittingFormFromFormElementShouldFireOnSubmitForThatForm', 'CorrectEventFiringTest.testSendingKeysToAFocusedElementShouldNotBlurThatElement', - 'CorrectEventFiringTest.testShouldReportTheXAndYCoordinatesWhenClicking', - 'CorrectEventFiringTest.testShouldEmitClickEventWhenClickingOnATextInputElement', - 'CorrectEventFiringTest.testSendingKeysToAnElementShouldCauseTheFocusEventToFire', - 'ElementAttributeTest.testShouldReturnAnAbsoluteUrlWhenGettingHrefAttributeOfAValidAnchorTag', - 'ElementAttributeTest.testCanRetrieveTheCurrentValueOfATextFormField_emailInput', - 'ElementAttributeTest.testShouldReturnTrueForPresentBooleanAttributes', - 'ElementAttributeTest.testShouldReturnValueOfOnClickAttribute', - 'ElementAttributeTest.testCanRetrieveTheCurrentValueOfATextFormField_textInput', - 'ElementAttributeTest.testGetAttributeDoesNotReturnAnObjectForSvgProperties', - 'ElementAttributeTest.testShouldReturnNullForNonPresentBooleanAttributes', - 'JavascriptEnabledDriverTest.testShouldBeAbleToFindElementAfterJavascriptCausesANewPageToLoad', - 'JavascriptEnabledDriverTest.testShouldBeAbleToSwitchToFocusedElement', - 'JavascriptEnabledDriverTest.testShouldBeAbleToDetermineTheLocationOfAnElement', - 'JavascriptEnabledDriverTest.testIfNoElementHasFocusTheActiveElementIsTheBody', - 'JavascriptEnabledDriverTest.testShouldWaitForLoadsToCompleteAfterJavascriptCausesANewPageToLoad', 'FormHandlingTest.testShouldSubmitAFormUsingTheEnterKey', 'FormHandlingTest.testShouldSubmitAFormUsingTheNewlineLiteral', - 'FormHandlingTest.testCanClickOnAnExternalSubmitButton', - 'FormHandlingTest.testShouldBeAbleToUploadTheSameFileTwice', + 'JavascriptEnabledDriverTest.testShouldBeAbleToFindElementAfterJavascriptCausesANewPageToLoad', + 'JavascriptEnabledDriverTest.testShouldBeAbleToDetermineTheLocationOfAnElement', + 'JavascriptEnabledDriverTest.testShouldBeAbleToSwitchToFocusedElement', + 'JavascriptEnabledDriverTest.testIfNoElementHasFocusTheActiveElementIsTheBody', + 'JavascriptEnabledDriverTest.testShouldWaitForLoadsToCompleteAfterJavascriptCausesANewPageToLoad', + 'TypingTest.testShouldBeAbleToUseArrowKeys', + 'TypingTest.testShouldReportKeyCodeOfArrowKeysUpDownEvents', + 'TypingTest.testShouldBeAbleToMixUpperAndLowerCaseLetters', 'BasicMouseInterfaceTest.testDoubleClickThenGet', 'MiscTest.testShouldReturnTheSourceOfAPage', 'MiscTest.testClickingShouldNotTrampleWOrHInGlobalScope', 'MiscTest.testShouldReportTheCurrentUrlCorrectly', 'MiscTest.testStimulatesStrangeOnloadInteractionInFirefox', - 'TypingTest.testShouldBeAbleToUseArrowKeys', + 'ElementAttributeTest.testShouldCorrectlyReportValueOfColspan', ] ) _OS_NEGATIVE_FILTER['android:chrome_beta'] = ( @@ -323,11 +313,10 @@ 'TypingTest.testShouldReportKeyCodeOfArrowKeys', # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1006 'ClickScrollingTest.testShouldBeAbleToClickElementThatIsOutOfViewInANestedFrameThatIsOutOfView', - # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2330 - 'VisibilityTest.testShouldModifyTheVisibilityOfAnElementDynamically', + # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2330 + 'VisibilityTest.testShouldModifyTheVisibilityOfAnElementDynamically', # Not applicable on ChromeDriverWebViewShell (doesn't support tabs). 'WindowSwitchingTest.*', - 'TakesScreenshotTest.testShouldCaptureScreenshot', ] )
diff --git a/chrome/test/data/webrtc/peerconnection.js b/chrome/test/data/webrtc/peerconnection.js index 7d921f2..78bddd5 100644 --- a/chrome/test/data/webrtc/peerconnection.js +++ b/chrome/test/data/webrtc/peerconnection.js
@@ -69,18 +69,22 @@ * to be used as parameter to |RTCPeerConnection.generateCertificate|. The * resulting certificate will be used by the peer connection. If null, a default * certificate is generated by the |RTCPeerConnection| instead. + * @param {string} peerConnectionConstraints Unless null, this adds peer + * connection constraints when creating new RTCPeerConnection. */ -function preparePeerConnection(keygenAlgorithm = null) { +function preparePeerConnection( + keygenAlgorithm = null, peerConnectionConstraints = null) { if (gPeerConnection !== null) throw failTest('Creating peer connection, but we already have one.'); if (keygenAlgorithm === null) { - gPeerConnection = createPeerConnection_(null); + gPeerConnection = createPeerConnection_(null, peerConnectionConstraints); returnToTest('ok-peerconnection-created'); } else { RTCPeerConnection.generateCertificate(keygenAlgorithm).then( function(certificate) { - preparePeerConnectionWithCertificate(certificate); + preparePeerConnectionWithCertificate(certificate, + peerConnectionConstraints); }, function() { failTest('Certificate generation failed. keygenAlgorithm: ' + @@ -94,12 +98,15 @@ * in this file. Alternatively, see |preparePeerConnection|. * @param {!Object} certificate The |RTCCertificate| that will be used by the * peer connection. + * @param {string} peerConnectionConstraints Unless null, this adds peer + * connection constraints when creating new RTCPeerConnection. */ -function preparePeerConnectionWithCertificate(certificate) { +function preparePeerConnectionWithCertificate( + certificate, peerConnectionConstraints = null) { if (gPeerConnection !== null) throw failTest('Creating peer connection, but we already have one.'); gPeerConnection = createPeerConnection_( - {iceServers:[], certificates:[certificate]}); + {iceServers:[], certificates:[certificate]}, peerConnectionConstraints); returnToTest('ok-peerconnection-created'); } @@ -509,9 +516,10 @@ // Internals. /** @private */ -function createPeerConnection_(rtcConfig) { +function createPeerConnection_(rtcConfig, peerConnectionConstraints) { try { - peerConnection = new RTCPeerConnection(rtcConfig, {}); + peerConnection = + new RTCPeerConnection(rtcConfig, peerConnectionConstraints); } catch (exception) { throw failTest('Failed to create peer connection: ' + exception); }
diff --git a/chrome/test/data/webui/extensions/extension_options_dialog_test.js b/chrome/test/data/webui/extensions/extension_options_dialog_test.js index efa80e9..6433c686 100644 --- a/chrome/test/data/webui/extensions/extension_options_dialog_test.js +++ b/chrome/test/data/webui/extensions/extension_options_dialog_test.js
@@ -48,27 +48,6 @@ data.name, assert(optionsDialog.$$('#icon-and-name-wrapper span')) .textContent.trim()); - - var optionEle = optionsDialog.$$('extensionoptions'); - - var mockOptions = optionsDialog.extensionOptions_; - assertEquals(data.id, mockOptions.extension); - - // Setting the preferred width to something below the min width - // changes the width property. But visually, min-width still prevails. - mockOptions.onpreferredsizechanged({height: 100, width: 100}); - assertEquals('100px', optionEle.style.width); - var computedStyle = window.getComputedStyle(optionEle); - assertEquals('300px', computedStyle.minWidth); - - // Setting the preferred size to between the min and max dimensions - // should change the dimensions. - mockOptions.onpreferredsizechanged({height: 500, width: 400}); - assertEquals('500px', optionEle.style.height); - assertEquals('400px', optionEle.style.width); - - mockOptions.onclose(); - assertFalse(isDialogVisible()); }); }); });
diff --git a/chrome/test/data/webui/settings/fake_quick_unlock_private.js b/chrome/test/data/webui/settings/fake_quick_unlock_private.js index 544d547..be53f27 100644 --- a/chrome/test/data/webui/settings/fake_quick_unlock_private.js +++ b/chrome/test/data/webui/settings/fake_quick_unlock_private.js
@@ -22,13 +22,14 @@ */ function FakeQuickUnlockPrivate() { /** @type {!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>} */ - this.availableModes = [chrome.quickUnlockPrivate.QuickUnlockMode.PIN]; + this.availableModes = [chrome.quickUnlockPrivate.QuickUnlockMode.PIN]; /** @type {!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>} */ - this.activeModes = []; + this.activeModes = []; /** @type {!Array<string>} */ this.credentials = []; /** @type {string} */ this.accountPassword = ''; /** @type {!chrome.quickUnlockPrivate.CredentialRequirements} */ - this.credentialRequirements = {minLength: 4, maxLength: 0}; + this.credentialRequirements = {minLength: 4, maxLength: 0}; + /** @type {boolean} */ this.lockScreenEnabled = false; } function clearError_() { @@ -59,6 +60,24 @@ /** * @override + * @param {string} token + * @param {boolean} enabled + * @param {function(boolean):void}= onComplete + */ + setLockScreenEnabled: function(token, enabled, onComplete) { + if (token != FAKE_TOKEN) { + chrome.runtime.lastError = 'Authentication token invalid'; + } else { + // Note: Fake does not set pref value. + this.lockScreenEnabled = enabled; + clearError_(); + } + if (onComplete) + onComplete(); + }, + + /** + * @override * @param {function( * !Array<!chrome.quickUnlockPrivate.QuickUnlockMode>):void} onComplete */
diff --git a/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js b/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js index 9dbb09f5..634e7e23 100644 --- a/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js +++ b/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js
@@ -266,6 +266,24 @@ assertDeepEquals([], quickUnlockPrivateApi.activeModes); }); + // Toggling the lock screen preference calls setLockScreenEnabled. + test('SetLockScreenEnabled', function() { + testElement.authToken_ = quickUnlockPrivateApi.getFakeToken(); + let toggle = getFromElement('#enableLockScreen'); + let lockScreenEnabled = toggle.checked; + quickUnlockPrivateApi.lockScreenEnabled = lockScreenEnabled; + + MockInteractions.tap(toggle); + assertEquals(toggle.checked, !lockScreenEnabled); + assertEquals( + quickUnlockPrivateApi.lockScreenEnabled, !lockScreenEnabled); + + MockInteractions.tap(toggle); + assertEquals(toggle.checked, lockScreenEnabled); + assertEquals( + quickUnlockPrivateApi.lockScreenEnabled, lockScreenEnabled); + }); + // The various radio buttons update internal state and do not modify // prefs. test('TappingButtonsChangesUnderlyingState', function() {
diff --git a/chrome/test/mini_installer/config/chrome_system_installed.prop b/chrome/test/mini_installer/config/chrome_system_installed.prop index 8622a31..2171fe32 100644 --- a/chrome/test/mini_installer/config/chrome_system_installed.prop +++ b/chrome/test/mini_installer/config/chrome_system_installed.prop
@@ -26,6 +26,21 @@ }, "wow_key": "KEY_WOW64_32KEY" }, + "HKEY_LOCAL_MACHINE\\$CHROME_UPDATE_REGISTRY_SUBKEY\\Commands\\store-dmtoken": { + "condition": "'$CHROME_SHORT_NAME' == 'Chrome'", + "exists": "required", + "values": { + "CommandLine": { + "type": "SZ", + "data": "\"$PROGRAM_FILES\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --store-dmtoken=%1 --system-level --verbose-logging" + }, + "WebAccessible": { + "type": "DWORD", + "data": 1 + } + }, + "wow_key": "KEY_WOW64_32KEY" + }, "HKEY_LOCAL_MACHINE\\$BINARIES_UPDATE_REGISTRY_SUBKEY": { "exists": "forbidden", "wow_key": "KEY_WOW64_32KEY"
diff --git a/chrome/test/mini_installer/config/chrome_system_updated.prop b/chrome/test/mini_installer/config/chrome_system_updated.prop index 0663428..ee54760 100644 --- a/chrome/test/mini_installer/config/chrome_system_updated.prop +++ b/chrome/test/mini_installer/config/chrome_system_updated.prop
@@ -26,6 +26,21 @@ }, "wow_key": "KEY_WOW64_32KEY" }, + "HKEY_LOCAL_MACHINE\\$CHROME_UPDATE_REGISTRY_SUBKEY\\Commands\\store-dmtoken": { + "condition": "'$CHROME_SHORT_NAME' == 'Chrome'", + "exists": "required", + "values": { + "CommandLine": { + "type": "SZ", + "data": "\"$PROGRAM_FILES\\$CHROME_DIR\\Application\\$NEXT_VERSION_MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --store-dmtoken=%1 --system-level --verbose-logging" + }, + "WebAccessible": { + "type": "DWORD", + "data": 1 + } + }, + "wow_key": "KEY_WOW64_32KEY" + }, "HKEY_LOCAL_MACHINE\\$BINARIES_UPDATE_REGISTRY_SUBKEY": { "exists": "forbidden", "wow_key": "KEY_WOW64_32KEY"
diff --git a/chrome/test/vr/auto_bisect.py b/chrome/test/vr/auto_bisect.py index 2debc78..3b97939 100755 --- a/chrome/test/vr/auto_bisect.py +++ b/chrome/test/vr/auto_bisect.py
@@ -89,6 +89,14 @@ 'syncing. This has the potential to accidentally ' 'delete any uncommitted changes, but can help avoid ' 'random bisect failures.') + parser.add_argument('--num-attempts-before-marking-good', type=int, default=1, + help='The number of times the test will be run before ' + 'a revision can be marked as good. If all runs are ' + 'found to be good, then the revision is good, ' + 'otherwise bad. Overriding this can help when ' + 'bisecting flaky metrics that fluctuate between ' + 'good/bad values, but can significantly increase ' + 'bisect time.') parser.add_argument_group('swarming arguments') parser.add_argument('--swarming-server', required=True, @@ -129,6 +137,12 @@ if len(args.dimensions) == 0: raise RuntimeError('No swarming dimensions provided') + # Make sure we're set to run at least one attempt per revision + if args.num_attempts_before_marking_good < 1: + raise RuntimeError( + '--num-attempts-before-marking-good set to invalid value %d' % + args.num_attempts_before_marking_good) + return (args, unknown_args) @@ -161,6 +175,9 @@ for pair in args.checkout_overrides: for key, val in pair.iteritems(): print '%s will be synced to revision %s' % (key, val) + if args.num_attempts_before_marking_good > 1: + print ('Each revision must be found to be good %d times before actually ' + 'being marked as good' % args.num_attempts_before_marking_good) print '======' print 'The test target %s will be built to %s' % (args.build_target, args.build_output_dir) @@ -320,30 +337,42 @@ revision: The git revision to sync to and test output_dir: The directory to save swarming results to """ - result = GetValueAtRevision(args, unknown_args, revision, output_dir) + revision_good = True + for attempt in xrange(1, args.num_attempts_before_marking_good + 1): + # Only bother syncing and building if this is our first attempt on this + # revision. + result = GetValueAtRevision(args, unknown_args, revision, output_dir, + sync=(attempt == 1)) + # Regression was an increased value. + if args.bad_value > args.good_value: + # If we're greater than the provided bad value or between good and bad, + # but closer to bad, we're still bad. + if (result > args.bad_value or + abs(args.bad_value - result) < abs(args.good_value - result)): + print '=== Attempt %d found revision that is BAD ===' % attempt + revision_good = False + break + else: + print '=== Attempt %d found that revision is GOOD ===' % attempt + # Regression was a decreased value. + else: + # If we're smaller than the provided bad value or between good and bad, + # but closer to bad, we're still bad. + if (result < args.bad_value or + abs(args.bad_value - result) < abs(args.good_value - result)): + print '=== Attempt %d found that revision is BAD ===' % attempt + revision_good = False + break + else: + print '=== Attempt %d found that revision is GOOD ===' % attempt + output = "" - # Regression was an increased value - if args.bad_value > args.good_value: - # If we're greater than the provided bad value or between good and bad, but - # closer to bad, we're still bad - if (result > args.bad_value or - abs(args.bad_value - result) < abs(args.good_value - result)): - print '=== Current revision is BAD ===' - output = subprocess.check_output(['git', 'bisect', 'bad']) - else: - print '=== Current revision is GOOD ===' - output = subprocess.check_output(['git', 'bisect', 'good']) - # Regression was a decreased value + if revision_good: + print '=== Current revision is GOOD ===' + output = subprocess.check_output(['git', 'bisect', 'good']) else: - # If we're smaller than the provided bad value or between good and bad, but - # closer to bad, we're still bad - if (result < args.bad_value or - abs(args.bad_value - result) < abs(args.good_value - result)): - print '=== Current revision is BAD ===' - output = subprocess.check_output(['git', 'bisect', 'bad']) - else: - print '=== Current revision is GOOD ===' - output = subprocess.check_output(['git', 'bisect', 'good']) + print '=== Current revision is BAD ===' + output = subprocess.check_output(['git', 'bisect', 'bad']) print output if output.startswith('Bisecting:'): @@ -374,6 +403,16 @@ 'they are not, remove them and try again. If the issue persists, try ' 'running with --reset-before-sync') + # Ensure that the VR assets are synced to the current revision since it isn't + # guaranteed that gclient will handle it properly + # TODO(https://crbug.com/823882): Remove this once asset downloading is more + # robust in gclient. + subprocess.check_output([ + 'python', 'third_party/depot_tools/download_from_google_storage.py', + '--bucket', 'chrome-vr-assets', + '--recursive', + '--directory', 'chrome/browser/resources/vr/assets/google_chrome']) + # Checkout any specified revisions. cwd = os.getcwd() for override in args.checkout_overrides: @@ -414,7 +453,7 @@ subprocess.check_output(['git', 'bisect', 'reset']) -def GetValueAtRevision(args, unknown_args, revision, output_dir): +def GetValueAtRevision(args, unknown_args, revision, output_dir, sync=True): """Builds and runs the test at a particular revision. Args: @@ -426,7 +465,8 @@ Returns: The value of the story/metric combo at the given revision """ - SyncAndBuild(args, unknown_args, revision) + if sync: + SyncAndBuild(args, unknown_args, revision) RunTestOnSwarming(args, unknown_args, output_dir) return GetSwarmingResult(args, unknown_args, output_dir)
diff --git a/chrome/tools/build/chromeos/FILES.cfg b/chrome/tools/build/chromeos/FILES.cfg index 891bb23..13324be 100644 --- a/chrome/tools/build/chromeos/FILES.cfg +++ b/chrome/tools/build/chromeos/FILES.cfg
@@ -80,17 +80,12 @@ 'filename': 'xdg-settings', 'buildtype': ['dev', 'official'], }, - # CDM files (each has an adapter and the actual CDM): + # CDM files { 'filename': 'libclearkeycdm.so', 'buildtype': ['dev', 'official'], }, { - 'filename': 'libwidevinecdmadapter.so', - 'arch': ['32bit', '64bit', 'arm'], - 'buildtype': ['official'], - }, - { 'filename': 'libwidevinecdm.so', 'arch': ['32bit', '64bit', 'arm'], 'buildtype': ['official'],
diff --git a/chrome/tools/build/linux/FILES.cfg b/chrome/tools/build/linux/FILES.cfg index afd951a..18da58cb 100644 --- a/chrome/tools/build/linux/FILES.cfg +++ b/chrome/tools/build/linux/FILES.cfg
@@ -97,11 +97,6 @@ 'buildtype': ['dev', 'official'], }, { - 'filename': 'libwidevinecdmadapter.so', - 'arch': ['32bit', '64bit'], - 'buildtype': ['official'], - }, - { 'filename': 'libwidevinecdm.so', 'arch': ['32bit', '64bit'], 'buildtype': ['official'],
diff --git a/chrome/tools/build/win/FILES.cfg b/chrome/tools/build/win/FILES.cfg index b12f5380..848e660 100644 --- a/chrome/tools/build/win/FILES.cfg +++ b/chrome/tools/build/win/FILES.cfg
@@ -348,11 +348,6 @@ 'buildtype': ['official'], }, { - 'filename': 'WidevineCdm/_platform_specific/win_x86/widevinecdmadapter.dll', - 'arch': ['32bit'], - 'buildtype': ['official'], - }, - { 'filename': 'WidevineCdm/_platform_specific/win_x64/widevinecdm.dll', 'arch': ['64bit'], 'buildtype': ['official'], @@ -362,11 +357,6 @@ 'arch': ['64bit'], 'buildtype': ['official'], }, - { - 'filename': 'WidevineCdm/_platform_specific/win_x64/widevinecdmadapter.dll', - 'arch': ['64bit'], - 'buildtype': ['official'], - }, # ANGLE files: { 'filename': 'D3DCompiler_47.dll',
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn index 4d2a41af..8e74729 100644 --- a/chromecast/browser/BUILD.gn +++ b/chromecast/browser/BUILD.gn
@@ -216,6 +216,8 @@ "cast_web_view_extension.h", "extension_request_protocol_handler.cc", "extension_request_protocol_handler.h", + "extensions/api/bookmarks/bookmarks_api.cc", + "extensions/api/bookmarks/bookmarks_api.h", "extensions/api/identity/identity_api.cc", "extensions/api/identity/identity_api.h", "extensions/cast_display_info_provider.cc", @@ -239,6 +241,7 @@ deps += [ "//chromecast/common/extensions_api:api_registration_bundle_generator_registration", + "//chromecast/common/extensions_api:api_schema_generator", "//components/guest_view/browser", "//components/keyed_service/content", "//components/pref_registry",
diff --git a/chromecast/browser/extensions/api/bookmarks/bookmarks_api.cc b/chromecast/browser/extensions/api/bookmarks/bookmarks_api.cc new file mode 100644 index 0000000..5da96ab --- /dev/null +++ b/chromecast/browser/extensions/api/bookmarks/bookmarks_api.cc
@@ -0,0 +1,58 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/browser/extensions/api/bookmarks/bookmarks_api.h" + +namespace extensions { +namespace cast { +namespace api { + +BookmarksFunction::~BookmarksFunction() {} + +void BookmarksFunction::Destruct() const { + delete this; +} + +BookmarksStubFunction::~BookmarksStubFunction() {} + +ExtensionFunction::ResponseAction BookmarksStubFunction::Run() { + return RespondNow(Error("Not implemented")); +} + +ExtensionFunction::ResponseAction BookmarksGetFunction::Run() { + return RespondNow(ArgumentList(cast::api::bookmarks::Get::Results::Create( + std::vector<cast::api::bookmarks::BookmarkTreeNode>()))); +} + +ExtensionFunction::ResponseAction BookmarksGetChildrenFunction::Run() { + return RespondNow( + ArgumentList(cast::api::bookmarks::GetChildren::Results::Create( + std::vector<cast::api::bookmarks::BookmarkTreeNode>()))); +} + +ExtensionFunction::ResponseAction BookmarksGetRecentFunction::Run() { + return RespondNow( + ArgumentList(cast::api::bookmarks::GetRecent::Results::Create( + std::vector<cast::api::bookmarks::BookmarkTreeNode>()))); +} + +ExtensionFunction::ResponseAction BookmarksGetTreeFunction::Run() { + return RespondNow(ArgumentList(cast::api::bookmarks::GetTree::Results::Create( + std::vector<cast::api::bookmarks::BookmarkTreeNode>()))); +} + +ExtensionFunction::ResponseAction BookmarksGetSubTreeFunction::Run() { + return RespondNow( + ArgumentList(cast::api::bookmarks::GetSubTree::Results::Create( + std::vector<cast::api::bookmarks::BookmarkTreeNode>()))); +} + +ExtensionFunction::ResponseAction BookmarksSearchFunction::Run() { + return RespondNow(ArgumentList(cast::api::bookmarks::Search::Results::Create( + std::vector<cast::api::bookmarks::BookmarkTreeNode>()))); +} + +} // namespace api +} // namespace cast +} // namespace extensions
diff --git a/chromecast/browser/extensions/api/bookmarks/bookmarks_api.h b/chromecast/browser/extensions/api/bookmarks/bookmarks_api.h new file mode 100644 index 0000000..a18c21fe --- /dev/null +++ b/chromecast/browser/extensions/api/bookmarks/bookmarks_api.h
@@ -0,0 +1,153 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_BROWSER_EXTENSIONS_API_BOOKMARKS_BOOKMARKS_API_H_ +#define CHROMECAST_BROWSER_EXTENSIONS_API_BOOKMARKS_BOOKMARKS_API_H_ + +#include <vector> + +#include "chromecast/common/extensions_api/bookmarks.h" +#include "extensions/browser/extension_function.h" + +namespace extensions { +namespace cast { +namespace api { + +class BookmarksFunction : public ExtensionFunction { + public: + void Destruct() const override; + + protected: + ~BookmarksFunction() override; +}; + +class BookmarksStubFunction : public BookmarksFunction { + public: + ResponseAction Run() override; + + protected: + ~BookmarksStubFunction() override; +}; + +class BookmarksGetFunction : public BookmarksFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.get", BOOKMARKS_GET) + + protected: + ~BookmarksGetFunction() override {} + + ResponseAction Run() override; +}; + +class BookmarksGetChildrenFunction : public BookmarksFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.getChildren", BOOKMARKS_GETCHILDREN) + + protected: + ~BookmarksGetChildrenFunction() override {} + + ResponseAction Run() override; +}; + +class BookmarksGetRecentFunction : public BookmarksFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.getRecent", BOOKMARKS_GETRECENT) + + protected: + ~BookmarksGetRecentFunction() override {} + + ResponseAction Run() override; +}; + +class BookmarksGetTreeFunction : public BookmarksFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.getTree", BOOKMARKS_GETTREE) + + protected: + ~BookmarksGetTreeFunction() override {} + + ResponseAction Run() override; +}; + +class BookmarksGetSubTreeFunction : public BookmarksFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.getSubTree", BOOKMARKS_GETSUBTREE) + + protected: + ~BookmarksGetSubTreeFunction() override {} + + ResponseAction Run() override; +}; + +class BookmarksSearchFunction : public BookmarksFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.search", BOOKMARKS_SEARCH) + + protected: + ~BookmarksSearchFunction() override {} + + ResponseAction Run() override; +}; + +class BookmarksRemoveFunction : public BookmarksStubFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.remove", BOOKMARKS_REMOVE); + + protected: + ~BookmarksRemoveFunction() override {} +}; + +class BookmarksRemoveTreeFunction : public BookmarksStubFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.removeTree", BOOKMARKS_REMOVETREE) + + protected: + ~BookmarksRemoveTreeFunction() override {} +}; + +class BookmarksCreateFunction : public BookmarksStubFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.create", BOOKMARKS_CREATE) + + protected: + ~BookmarksCreateFunction() override {} +}; + +class BookmarksMoveFunction : public BookmarksStubFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.move", BOOKMARKS_MOVE) + + protected: + ~BookmarksMoveFunction() override {} +}; + +class BookmarksUpdateFunction : public BookmarksStubFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.update", BOOKMARKS_UPDATE) + + protected: + ~BookmarksUpdateFunction() override {} +}; + +class BookmarksImportFunction : public BookmarksStubFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.import", BOOKMARKS_IMPORT) + + private: + ~BookmarksImportFunction() override {} +}; + +class BookmarksExportFunction : public BookmarksStubFunction { + public: + DECLARE_EXTENSION_FUNCTION("bookmarks.export", BOOKMARKS_EXPORT) + + private: + ~BookmarksExportFunction() override {} +}; + +} // namespace api +} // namespace cast +} // namespace extensions + +#endif // CHROMECAST_BROWSER_EXTENSIONS_API_BOOKMARKS_BOOKMARKS_API_H_
diff --git a/chromecast/common/BUILD.gn b/chromecast/common/BUILD.gn index 08f2e6f..8540444 100644 --- a/chromecast/common/BUILD.gn +++ b/chromecast/common/BUILD.gn
@@ -35,6 +35,7 @@ deps += [ "//chromecast/common/extensions_api:api", "//chromecast/common/extensions_api:api_registration", + "//chromecast/common/extensions_api:api_schema_generator", "//chromecast/common/extensions_api:extensions_features", "//components/version_info", "//extensions:extensions_resources_grd_grit",
diff --git a/chromecast/common/extensions_api/BUILD.gn b/chromecast/common/extensions_api/BUILD.gn index 3d8d2f7..f5ea3fc 100644 --- a/chromecast/common/extensions_api/BUILD.gn +++ b/chromecast/common/extensions_api/BUILD.gn
@@ -9,7 +9,10 @@ assert(enable_extensions, "Cannot depend on extensions because enable_extensions=false.") -schema_sources = [ "identity.idl" ] +schema_sources = [ + "bookmarks.json", + "identity.idl", +] root_namespace = "extensions::cast::api::%(namespace)s" json_schema_api("api") { @@ -45,6 +48,7 @@ provider_class = "CastPermissionFeatureProvider" sources = [ "../../../extensions/common/api/_permission_features.json", + "_permission_features.json", ] }
diff --git a/chromecast/common/extensions_api/_api_features.json b/chromecast/common/extensions_api/_api_features.json index ed747fa..7b672c49 100644 --- a/chromecast/common/extensions_api/_api_features.json +++ b/chromecast/common/extensions_api/_api_features.json
@@ -18,5 +18,16 @@ "channel": "dev", "contexts": ["blessed_extension"], "extension_types": ["platform_app"] - } + }, + "bookmarks": [{ + "dependencies": ["permission:bookmarks"], + "contexts": ["blessed_extension"], + "default_parent": true + }, { + "channel": "stable", + "contexts": ["webui"], + "matches": [ + "chrome://bookmarks/*" + ] + }] }
diff --git a/chromecast/common/extensions_api/_permission_features.json b/chromecast/common/extensions_api/_permission_features.json new file mode 100644 index 0000000..7542497c --- /dev/null +++ b/chromecast/common/extensions_api/_permission_features.json
@@ -0,0 +1,10 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +{ + "bookmarks": { + "channel": "stable", + "extension_types": ["extension", "legacy_packaged_app"] + } +}
diff --git a/chromecast/common/extensions_api/bookmarks.json b/chromecast/common/extensions_api/bookmarks.json new file mode 100644 index 0000000..bc7d8ff --- /dev/null +++ b/chromecast/common/extensions_api/bookmarks.json
@@ -0,0 +1,560 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + { + "namespace": "bookmarks", + "description": "Use the <code>chrome.bookmarks</code> API to create, organize, and otherwise manipulate bookmarks. Also see <a href='override'>Override Pages</a>, which you can use to create a custom Bookmark Manager page.", + "properties": { + "MAX_WRITE_OPERATIONS_PER_HOUR": { + "value": 1000000, + "deprecated": "Bookmark write operations are no longer limited by Chrome.", + "description": "" + }, + "MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE": { + "value": 1000000, + "deprecated": "Bookmark write operations are no longer limited by Chrome.", + "description": "" + } + }, + "types": [ + { + "id": "BookmarkTreeNodeUnmodifiable", + "type": "string", + "enum": ["managed"], + "description": "Indicates the reason why this node is unmodifiable. The <var>managed</var> value indicates that this node was configured by the system administrator. Omitted if the node can be modified by the user and the extension (default)." + }, + { + "id": "BookmarkTreeNode", + "type": "object", + "description": "A node (either a bookmark or a folder) in the bookmark tree. Child nodes are ordered within their parent folder.", + "properties": { + "id": { + "type": "string", + "minimum": 0, + "description": "The unique identifier for the node. IDs are unique within the current profile, and they remain valid even after the browser is restarted." + }, + "parentId": { + "type": "string", + "minimum": 0, + "optional": true, + "description": "The <code>id</code> of the parent folder. Omitted for the root node." + }, + "index": { + "type": "integer", + "optional": true, + "description": "The 0-based position of this node within its parent folder." + }, + "url": { + "type": "string", + "optional": true, + "description": "The URL navigated to when a user clicks the bookmark. Omitted for folders." + }, + "title": { + "type": "string", + "description": "The text displayed for the node." + }, + "dateAdded": { + "type": "number", + "optional": true, + "description": "When this node was created, in milliseconds since the epoch (<code>new Date(dateAdded)</code>)." + }, + "dateGroupModified": { + "type": "number", + "optional": true, + "description": "When the contents of this folder last changed, in milliseconds since the epoch." + }, + "unmodifiable": { + "$ref": "BookmarkTreeNodeUnmodifiable", + "optional": true, + "description": "Indicates the reason why this node is unmodifiable. The <var>managed</var> value indicates that this node was configured by the system administrator or by the custodian of a supervised user. Omitted if the node can be modified by the user and the extension (default)." + }, + "children": { + "type": "array", + "optional": true, + "items": { "$ref": "BookmarkTreeNode" }, + "description": "An ordered list of children of this node." + } + } + }, + { + "id": "CreateDetails", + "description": "Object passed to the create() function.", + "inline_doc": true, + "type": "object", + "properties": { + "parentId": { + "type": "string", + "serialized_type": "int64", + "optional": true, + "description": "Defaults to the Other Bookmarks folder." + }, + "index": { + "type": "integer", + "minimum": 0, + "optional": true + }, + "title": { + "type": "string", + "optional": true + }, + "url": { + "type": "string", + "optional": true + } + } + } + ], + "functions": [ + { + "name": "get", + "type": "function", + "description": "Retrieves the specified BookmarkTreeNode(s).", + "parameters": [ + { + "name": "idOrIdList", + "description": "A single string-valued id, or an array of string-valued ids", + "choices": [ + { + "type": "string", + "serialized_type": "int64" + }, + { + "type": "array", + "items": { + "type": "string", + "serialized_type": "int64" + }, + "minItems": 1 + } + ] + }, + { + "type": "function", + "name": "callback", + "parameters": [ + { + "name": "results", + "type": "array", + "items": { "$ref": "BookmarkTreeNode" } + } + ] + } + ] + }, + { + "name": "getChildren", + "type": "function", + "description": "Retrieves the children of the specified BookmarkTreeNode id.", + "parameters": [ + { + "type": "string", + "serialized_type": "int64", + "name": "id" + }, + { + "type": "function", + "name": "callback", + "parameters": [ + { + "name": "results", + "type": "array", + "items": { "$ref": "BookmarkTreeNode"} + } + ] + } + ] + }, + { + "name": "getRecent", + "type": "function", + "description": "Retrieves the recently added bookmarks.", + "parameters": [ + { + "type": "integer", + "minimum": 1, + "name": "numberOfItems", + "description": "The maximum number of items to return." + }, + { + "type": "function", + "name": "callback", + "parameters": [ + { + "name": "results", + "type": "array", + "items": { "$ref": "BookmarkTreeNode" } + } + ] + } + ] + }, + { + "name": "getTree", + "type": "function", + "description": "Retrieves the entire Bookmarks hierarchy.", + "parameters": [ + { + "type": "function", + "name": "callback", + "parameters": [ + { + "name": "results", + "type": "array", + "items": { "$ref": "BookmarkTreeNode" } + } + ] + } + ] + }, + { + "name": "getSubTree", + "type": "function", + "description": "Retrieves part of the Bookmarks hierarchy, starting at the specified node.", + "parameters": [ + { + "type": "string", + "serialized_type": "int64", + "name": "id", + "description": "The ID of the root of the subtree to retrieve." + }, + { + "type": "function", + "name": "callback", + "parameters": [ + { + "name": "results", + "type": "array", + "items": { "$ref": "BookmarkTreeNode" } + } + ] + } + ] + }, + { + "name": "search", + "type": "function", + "description": "Searches for BookmarkTreeNodes matching the given query. Queries specified with an object produce BookmarkTreeNodes matching all specified properties.", + "parameters": [ + { + "name": "query", + "description": "Either a string of words and quoted phrases that are matched against bookmark URLs and titles, or an object. If an object, the properties <code>query</code>, <code>url</code>, and <code>title</code> may be specified and bookmarks matching all specified properties will be produced.", + "choices": [ + { + "type": "string", + "description": "A string of words and quoted phrases that are matched against bookmark URLs and titles." + }, + { + "type": "object", + "description": "An object specifying properties and values to match when searching. Produces bookmarks matching all properties.", + "properties": { + "query": { + "type": "string", + "optional": true, + "description": "A string of words and quoted phrases that are matched against bookmark URLs and titles." + }, + "url": { + "type": "string", + "optional": true, + "description": "The URL of the bookmark; matches verbatim. Note that folders have no URL." + }, + "title": { + "type": "string", + "optional": true, + "description": "The title of the bookmark; matches verbatim." + } + } + } + ] + }, + { + "type": "function", + "name": "callback", + "parameters": [ + { + "name": "results", + "type": "array", + "items": { "$ref": "BookmarkTreeNode" } + } + ] + } + ] + }, + { + "name": "create", + "type": "function", + "description": "Creates a bookmark or folder under the specified parentId. If url is NULL or missing, it will be a folder.", + "parameters": [ + { + "$ref": "CreateDetails", + "name": "bookmark" + }, + { + "type": "function", + "name": "callback", + "optional": true, + "parameters": [ + { + "name": "result", + "$ref": "BookmarkTreeNode" + } + ] + } + ] + }, + { + "name": "move", + "type": "function", + "description": "Moves the specified BookmarkTreeNode to the provided location.", + "parameters": [ + { + "type": "string", + "serialized_type": "int64", + "name": "id" + }, + { + "type": "object", + "name": "destination", + "properties": { + "parentId": { + "type": "string", + "optional": true + }, + "index": { + "type": "integer", + "minimum": 0, + "optional": true + } + } + }, + { + "type": "function", + "name": "callback", + "optional": true, + "parameters": [ + { + "name": "result", + "$ref": "BookmarkTreeNode" + } + ] + } + ] + }, + { + "name": "update", + "type": "function", + "description": "Updates the properties of a bookmark or folder. Specify only the properties that you want to change; unspecified properties will be left unchanged. <b>Note:</b> Currently, only 'title' and 'url' are supported.", + "parameters": [ + { + "type": "string", + "serialized_type": "int64", + "name": "id" + }, + { + "type": "object", + "name": "changes", + "properties": { + "title": { + "type": "string", + "optional": true + }, + "url": { + "type": "string", + "optional": true + } + } + }, + { + "type": "function", + "name": "callback", + "optional": true, + "parameters": [ + { + "name": "result", + "$ref": "BookmarkTreeNode" + } + ] + } + ] + }, + { + "name": "remove", + "type": "function", + "description": "Removes a bookmark or an empty bookmark folder.", + "parameters": [ + { + "type": "string", + "serialized_type": "int64", + "name": "id" + }, + { + "type": "function", + "name": "callback", + "optional": true, + "parameters": [] + } + ] + }, + { + "name": "removeTree", + "type": "function", + "description": "Recursively removes a bookmark folder.", + "parameters": [ + { + "type": "string", + "serialized_type": "int64", + "name": "id" + }, + { + "type": "function", + "name": "callback", + "optional": true, + "parameters": [] + } + ] + }, + { + "name": "import", + "type": "function", + "description": "Imports bookmarks from a chrome html bookmark file", + "nodoc": "true", + "parameters": [ + { + "type": "function", + "name": "callback", + "optional": true, + "parameters": [] + } + ] + }, + { + "name": "export", + "type": "function", + "description": "Exports bookmarks to a chrome html bookmark file", + "nodoc": "true", + "parameters": [ + { + "type": "function", + "name": "callback", + "optional": true, + "parameters": [] + } + ] + } + ], + "events": [ + { + "name": "onCreated", + "type": "function", + "description": "Fired when a bookmark or folder is created.", + "parameters": [ + { + "type": "string", + "name": "id" + }, + { + "$ref": "BookmarkTreeNode", + "name": "bookmark" + } + ] + }, + { + "name": "onRemoved", + "type": "function", + "description": "Fired when a bookmark or folder is removed. When a folder is removed recursively, a single notification is fired for the folder, and none for its contents.", + "parameters": [ + { + "type": "string", + "name": "id" + }, + { + "type": "object", + "name": "removeInfo", + "properties": { + "parentId": { "type": "string" }, + "index": { "type": "integer" }, + "node": { "$ref": "BookmarkTreeNode" } + } + } + ] + }, + { + "name": "onChanged", + "type": "function", + "description": "Fired when a bookmark or folder changes. <b>Note:</b> Currently, only title and url changes trigger this.", + "parameters": [ + { + "type": "string", + "name": "id" + }, + { + "type": "object", + "name": "changeInfo", + "properties": { + "title": { "type": "string" }, + "url": { + "type": "string", + "optional": true + } + } + } + ] + }, + { + "name": "onMoved", + "type": "function", + "description": "Fired when a bookmark or folder is moved to a different parent folder.", + "parameters": [ + { + "type": "string", + "name": "id" + }, + { + "type": "object", + "name": "moveInfo", + "properties": { + "parentId": { "type": "string" }, + "index": { "type": "integer" }, + "oldParentId": { "type": "string" }, + "oldIndex": { "type": "integer" } + } + } + ] + }, + { + "name": "onChildrenReordered", + "type": "function", + "description": "Fired when the children of a folder have changed their order due to the order being sorted in the UI. This is not called as a result of a move().", + "parameters": [ + { + "type": "string", + "name": "id" + }, + { + "type": "object", + "name": "reorderInfo", + "properties": { + "childIds": { + "type": "array", + "items": { "type": "string" } + } + } + } + ] + }, + { + "name": "onImportBegan", + "type": "function", + "description": "Fired when a bookmark import session is begun. Expensive observers should ignore onCreated updates until onImportEnded is fired. Observers should still handle other notifications immediately.", + "parameters": [] + }, + { + "name": "onImportEnded", + "type": "function", + "description": "Fired when a bookmark import session is ended.", + "parameters": [] + } + ] + } +]
diff --git a/chromecast/media/cma/backend/video/av_sync_video.cc b/chromecast/media/cma/backend/video/av_sync_video.cc index 0cbacd31..a759bc2 100644 --- a/chromecast/media/cma/backend/video/av_sync_video.cc +++ b/chromecast/media/cma/backend/video/av_sync_video.cc
@@ -38,6 +38,10 @@ constexpr base::TimeDelta kAvSyncUpkeepInterval = base::TimeDelta::FromMilliseconds(10); +// Time interval between checking playbacks statistics. +constexpr base::TimeDelta kPlaybackStatisticsCheckInterval = + base::TimeDelta::FromSeconds(1); + // When we're in sync (i.e. the apts and vpts difference is // < kSoftCorrectionThresholdUs), if the apts and vpts slopes are different by // this threshold, we'll reset the video playback rate to be equal to the apts @@ -190,6 +194,48 @@ } } +void AvSyncVideo::GatherPlaybackStatistics() { + int64_t frame_rate_difference = + (backend_->video_decoder()->GetCurrentContentRefreshRate() - + backend_->video_decoder()->GetOutputRefreshRate()) / + 1000; + + int64_t expected_dropped_frames_per_second = + std::max<int64_t>(frame_rate_difference, 0); + + int64_t expected_repeated_frames_per_second = + std::max<int64_t>(-frame_rate_difference, 0); + + int64_t current_time = backend_->MonotonicClockNow(); + int64_t expected_dropped_frames = + std::round(expected_dropped_frames_per_second * + (current_time - last_gather_timestamp_us_) / 1000000); + + int64_t expected_repeated_frames = + std::round(expected_repeated_frames_per_second * + (current_time - last_gather_timestamp_us_) / 1000000); + + int64_t dropped_frames = backend_->video_decoder()->GetDroppedFrames(); + int64_t repeated_frames = backend_->video_decoder()->GetRepeatedFrames(); + + int64_t unexpected_dropped_frames = + (dropped_frames - last_dropped_frames_) - expected_dropped_frames; + int64_t unexpected_repeated_frames = + (repeated_frames - last_repeated_frames_) - expected_repeated_frames; + + VLOG_IF(2, unexpected_dropped_frames != 0 || unexpected_repeated_frames != 0) + << "Playback diagnostics:" + << " CurrentContentRefreshRate=" + << backend_->video_decoder()->GetCurrentContentRefreshRate() + << " OutputRefreshRate=" + << backend_->video_decoder()->GetOutputRefreshRate() + << " unexpected_dropped_frames=" << unexpected_dropped_frames + << " unexpected_repeated_frames=" << unexpected_repeated_frames; + last_gather_timestamp_us_ = current_time; + last_repeated_frames_ = repeated_frames; + last_dropped_frames_ = dropped_frames; +} + void AvSyncVideo::StopAvSync() { audio_pts_.reset( new WeightedMovingLinearRegression(kLinearRegressionDataLifetimeUs)); @@ -197,12 +243,12 @@ new WeightedMovingLinearRegression(kLinearRegressionDataLifetimeUs)); error_.reset( new WeightedMovingLinearRegression(kLinearRegressionDataLifetimeUs)); - timer_.Stop(); + upkeep_av_sync_timer_.Stop(); + playback_statistics_timer_.Stop(); } void AvSyncVideo::NotifyStart() { - timer_.Start(FROM_HERE, kAvSyncUpkeepInterval, this, - &AvSyncVideo::UpkeepAvSync); + StartAvSync(); } void AvSyncVideo::NotifyStop() { @@ -215,8 +261,19 @@ } void AvSyncVideo::NotifyResume() { - timer_.Start(FROM_HERE, kAvSyncUpkeepInterval, this, - &AvSyncVideo::UpkeepAvSync); + StartAvSync(); +} + +void AvSyncVideo::StartAvSync() { + upkeep_av_sync_timer_.Start(FROM_HERE, kAvSyncUpkeepInterval, this, + &AvSyncVideo::UpkeepAvSync); +#if DCHECK_IS_ON() + // TODO(almasrymina): if this logic turns out to be useful for metrics + // recording, keep it and remove this TODO. Otherwise remove it. + playback_statistics_timer_.Start(FROM_HERE, kPlaybackStatisticsCheckInterval, + this, + &AvSyncVideo::GatherPlaybackStatistics); +#endif } AvSyncVideo::~AvSyncVideo() = default;
diff --git a/chromecast/media/cma/backend/video/av_sync_video.h b/chromecast/media/cma/backend/video/av_sync_video.h index 17b9630..8fcc105 100644 --- a/chromecast/media/cma/backend/video/av_sync_video.h +++ b/chromecast/media/cma/backend/video/av_sync_video.h
@@ -39,9 +39,12 @@ private: void UpkeepAvSync(); + void StartAvSync(); void StopAvSync(); + void GatherPlaybackStatistics(); - base::RepeatingTimer timer_; + base::RepeatingTimer upkeep_av_sync_timer_; + base::RepeatingTimer playback_statistics_timer_; bool setup_video_clock_ = false; // TODO(almasrymina): having a linear regression for the audio pts is @@ -54,6 +57,10 @@ std::unique_ptr<WeightedMovingLinearRegression> error_; double current_video_playback_rate_ = 1.0; + int64_t last_gather_timestamp_us_ = 0; + int64_t last_repeated_frames_ = 0; + int64_t last_dropped_frames_ = 0; + const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; MediaPipelineBackendForMixer* const backend_;
diff --git a/chromecast/media/cma/backend/video_decoder_for_mixer.h b/chromecast/media/cma/backend/video_decoder_for_mixer.h index d600245..53c966b 100644 --- a/chromecast/media/cma/backend/video_decoder_for_mixer.h +++ b/chromecast/media/cma/backend/video_decoder_for_mixer.h
@@ -52,7 +52,7 @@ // playback rate prior to pausing. virtual bool Resume() = 0; - // Get the current video PTS. This will typically be the pts of the last + // Returns the current video PTS. This will typically be the pts of the last // video frame displayed. virtual int64_t GetCurrentPts() const = 0; @@ -72,6 +72,32 @@ // Implementation is encouraged to smooth out this transition, such that // minimal jitter in the video is shown, but that is not necessary. virtual bool SetCurrentPts(int64_t pts) = 0; + + // Returns number of frames dropped since the last call to Start(). This is + // used to estimate video playback smoothness. + // This is different from VideoDecoder::Statistics::dropped_frames. That + // value is the number of *decoded* dropped frames. The value returned here + // must be the total number of dropped frames, whether the frames have been + // decoded or not. + virtual int64_t GetDroppedFrames() = 0; + + // Returns number of frames repeated since the last call to Start(). This is + // used to estimate video playback smoothness. Note that repeated frames could + // be due to changes in the rate of playback, setting the PTS, or simply due + // to frame rate conversion. This number should be the sum of all of these + // factors. + // + // For example, if the current OutputRefreshRate is 60hz, and the current + // content frame rate is 24fps, it is expected to repeat 36fps. + virtual int64_t GetRepeatedFrames() = 0; + + // Returns the output refresh rate on this platform, in mHz (millihertz). On + // display devices, this will be the display refresh rate. On HDMI devices, + // this will be the refresh rate of the HDMI connection. + virtual int64_t GetOutputRefreshRate() = 0; + + // Returns the current content refresh rate in mHz (millihertz). + virtual int64_t GetCurrentContentRefreshRate() = 0; }; } // namespace media
diff --git a/chromecast/media/cma/backend/video_decoder_null.cc b/chromecast/media/cma/backend/video_decoder_null.cc index ac154c9f..0d83c82 100644 --- a/chromecast/media/cma/backend/video_decoder_null.cc +++ b/chromecast/media/cma/backend/video_decoder_null.cc
@@ -80,5 +80,21 @@ return true; } +int64_t VideoDecoderNull::GetDroppedFrames() { + return 0; +} + +int64_t VideoDecoderNull::GetRepeatedFrames() { + return 0; +} + +int64_t VideoDecoderNull::GetOutputRefreshRate() { + return 0; +} + +int64_t VideoDecoderNull::GetCurrentContentRefreshRate() { + return 0; +} + } // namespace media } // namespace chromecast
diff --git a/chromecast/media/cma/backend/video_decoder_null.h b/chromecast/media/cma/backend/video_decoder_null.h index dda9382..2f339a2 100644 --- a/chromecast/media/cma/backend/video_decoder_null.h +++ b/chromecast/media/cma/backend/video_decoder_null.h
@@ -34,6 +34,10 @@ int64_t GetCurrentPts() const override; bool SetPlaybackRate(float rate) override; bool SetCurrentPts(int64_t pts) override; + int64_t GetDroppedFrames() override; + int64_t GetRepeatedFrames() override; + int64_t GetOutputRefreshRate() override; + int64_t GetCurrentContentRefreshRate() override; private: void OnEndOfStream();
diff --git a/chromeos/services/assistant/BUILD.gn b/chromeos/services/assistant/BUILD.gn index 91c0ba8..59b0825 100644 --- a/chromeos/services/assistant/BUILD.gn +++ b/chromeos/services/assistant/BUILD.gn
@@ -54,7 +54,7 @@ "//libassistant/contrib/platform/net", "//libassistant/contrib/platform/resources", "//libassistant/contrib/platform/system", - "//libassistant/internal/assistant/controller:libassistant_static", + "//libassistant/internal/assistant/controller:libassistant", "//libassistant/shared/internal_api/c:api_wrappers_for_caller_no_chromium", "//libassistant/shared/proto:assistant_proto", "//libassistant/shared/public",
diff --git a/chromeos/services/assistant/platform/audio_input_provider_impl.cc b/chromeos/services/assistant/platform/audio_input_provider_impl.cc index ad72192a6..af40c9e 100644 --- a/chromeos/services/assistant/platform/audio_input_provider_impl.cc +++ b/chromeos/services/assistant/platform/audio_input_provider_impl.cc
@@ -133,5 +133,10 @@ return audio_input_; } +int64_t AudioInputProviderImpl::GetCurrentAudioTime() { + // TODO(xiaohuic): see if we can support real timestamp. + return 0; +} + } // namespace assistant } // namespace chromeos
diff --git a/chromeos/services/assistant/platform/audio_input_provider_impl.h b/chromeos/services/assistant/platform/audio_input_provider_impl.h index b9453e3c..86598d3 100644 --- a/chromeos/services/assistant/platform/audio_input_provider_impl.h +++ b/chromeos/services/assistant/platform/audio_input_provider_impl.h
@@ -73,8 +73,9 @@ // assistant_client::AudioInputProvider overrides: assistant_client::AudioInputConfig& GetAudioInputConfig() override; assistant_client::AudioInput& GetAudioInput() override; - + // Assumes no config would change. void RegisterConfigChangeCallback(ConfigChangeCallback callback) override {} + int64_t GetCurrentAudioTime() override; private: AudioInputConfigImpl audio_input_config_;
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java index 082a047..0928f3ca 100644 --- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java +++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java
@@ -31,76 +31,78 @@ @Override public boolean schedule(Context context, TaskInfo taskInfo) { - TraceEvent.begin( - "BackgroundTaskScheduler.schedule", Integer.toString(taskInfo.getTaskId())); - ThreadUtils.assertOnUiThread(); - boolean success = mSchedulerDelegate.schedule(context, taskInfo); - BackgroundTaskSchedulerUma.getInstance().reportTaskScheduled(taskInfo.getTaskId(), success); - if (success) { - BackgroundTaskSchedulerPrefs.addScheduledTask(taskInfo); + try (TraceEvent te = TraceEvent.scoped( + "BackgroundTaskScheduler.schedule", Integer.toString(taskInfo.getTaskId()))) { + ThreadUtils.assertOnUiThread(); + boolean success = mSchedulerDelegate.schedule(context, taskInfo); + BackgroundTaskSchedulerUma.getInstance().reportTaskScheduled( + taskInfo.getTaskId(), success); + if (success) { + BackgroundTaskSchedulerPrefs.addScheduledTask(taskInfo); + } + return success; } - TraceEvent.end("BackgroundTaskScheduler.schedule"); - return success; } @Override public void cancel(Context context, int taskId) { - TraceEvent.begin("BackgroundTaskScheduler.cancel", Integer.toString(taskId)); - ThreadUtils.assertOnUiThread(); - BackgroundTaskSchedulerUma.getInstance().reportTaskCanceled(taskId); - BackgroundTaskSchedulerPrefs.removeScheduledTask(taskId); - mSchedulerDelegate.cancel(context, taskId); - TraceEvent.end("BackgroundTaskScheduler.cancel"); + try (TraceEvent te = TraceEvent.scoped( + "BackgroundTaskScheduler.cancel", Integer.toString(taskId))) { + ThreadUtils.assertOnUiThread(); + BackgroundTaskSchedulerUma.getInstance().reportTaskCanceled(taskId); + BackgroundTaskSchedulerPrefs.removeScheduledTask(taskId); + mSchedulerDelegate.cancel(context, taskId); + } } @Override public void checkForOSUpgrade(Context context) { - TraceEvent.begin("BackgroundTaskScheduler.checkForOSUpgrade"); - int oldSdkInt = BackgroundTaskSchedulerPrefs.getLastSdkVersion(); - int newSdkInt = Build.VERSION.SDK_INT; + try (TraceEvent te = TraceEvent.scoped("BackgroundTaskScheduler.checkForOSUpgrade")) { + int oldSdkInt = BackgroundTaskSchedulerPrefs.getLastSdkVersion(); + int newSdkInt = Build.VERSION.SDK_INT; - if (oldSdkInt != newSdkInt) { - // Save the current SDK version to preferences. - BackgroundTaskSchedulerPrefs.setLastSdkVersion(newSdkInt); + if (oldSdkInt != newSdkInt) { + // Save the current SDK version to preferences. + BackgroundTaskSchedulerPrefs.setLastSdkVersion(newSdkInt); + } + + // No OS upgrade detected or OS upgrade does not change delegate. + if (oldSdkInt == newSdkInt || !osUpgradeChangesDelegateType(oldSdkInt, newSdkInt)) { + BackgroundTaskSchedulerUma.getInstance().flushStats(); + return; + } + + BackgroundTaskSchedulerUma.getInstance().removeCachedStats(); + + // Explicitly create and invoke old delegate type to cancel all scheduled tasks. + // All preference entries are kept until reschedule call, which removes then then. + BackgroundTaskSchedulerDelegate oldDelegate = + BackgroundTaskSchedulerFactory.getSchedulerDelegateForSdk(oldSdkInt); + Set<Integer> scheduledTaskIds = BackgroundTaskSchedulerPrefs.getScheduledTaskIds(); + for (int taskId : scheduledTaskIds) { + oldDelegate.cancel(context, taskId); + } + + reschedule(context); } - - // No OS upgrade detected or OS upgrade does not change delegate. - if (oldSdkInt == newSdkInt || !osUpgradeChangesDelegateType(oldSdkInt, newSdkInt)) { - BackgroundTaskSchedulerUma.getInstance().flushStats(); - return; - } - - BackgroundTaskSchedulerUma.getInstance().removeCachedStats(); - - // Explicitly create and invoke old delegate type to cancel all scheduled tasks. - // All preference entries are kept until reschedule call, which removes then then. - BackgroundTaskSchedulerDelegate oldDelegate = - BackgroundTaskSchedulerFactory.getSchedulerDelegateForSdk(oldSdkInt); - Set<Integer> scheduledTaskIds = BackgroundTaskSchedulerPrefs.getScheduledTaskIds(); - for (int taskId : scheduledTaskIds) { - oldDelegate.cancel(context, taskId); - } - - reschedule(context); - TraceEvent.end("BackgroundTaskScheduler.checkForOSUpgrade"); } @Override public void reschedule(Context context) { - TraceEvent.begin("BackgroundTaskScheduler.reschedule"); - Set<String> scheduledTasksClassNames = BackgroundTaskSchedulerPrefs.getScheduledTasks(); - BackgroundTaskSchedulerPrefs.removeAllTasks(); - for (String className : scheduledTasksClassNames) { - BackgroundTask task = - BackgroundTaskReflection.getBackgroundTaskFromClassName(className); - if (task == null) { - Log.w(TAG, "Cannot reschedule task for: " + className); - continue; - } + try (TraceEvent te = TraceEvent.scoped("BackgroundTaskScheduler.reschedule")) { + Set<String> scheduledTasksClassNames = BackgroundTaskSchedulerPrefs.getScheduledTasks(); + BackgroundTaskSchedulerPrefs.removeAllTasks(); + for (String className : scheduledTasksClassNames) { + BackgroundTask task = + BackgroundTaskReflection.getBackgroundTaskFromClassName(className); + if (task == null) { + Log.w(TAG, "Cannot reschedule task for: " + className); + continue; + } - task.reschedule(context); + task.reschedule(context); + } } - TraceEvent.end("BackgroundTaskScheduler.reschedule"); } private boolean osUpgradeChangesDelegateType(int oldSdkInt, int newSdkInt) {
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefs.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefs.java index adae668..607d5b3c 100644 --- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefs.java +++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefs.java
@@ -85,106 +85,108 @@ /** Adds a task to scheduler's preferences, so that it can be rescheduled with OS upgrade. */ public static void addScheduledTask(TaskInfo taskInfo) { - TraceEvent.begin("BackgroundTaskSchedulerPrefs.addScheduledTask", - Integer.toString(taskInfo.getTaskId())); - SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); - Set<String> scheduledTasks = - prefs.getStringSet(KEY_SCHEDULED_TASKS, new HashSet<String>(1)); - String prefsEntry = ScheduledTaskPreferenceEntry.createForTaskInfo(taskInfo).toString(); - if (scheduledTasks.contains(prefsEntry)) return; + try (TraceEvent te = TraceEvent.scoped("BackgroundTaskSchedulerPrefs.addScheduledTask", + Integer.toString(taskInfo.getTaskId()))) { + SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); + Set<String> scheduledTasks = + prefs.getStringSet(KEY_SCHEDULED_TASKS, new HashSet<String>(1)); + String prefsEntry = ScheduledTaskPreferenceEntry.createForTaskInfo(taskInfo).toString(); + if (scheduledTasks.contains(prefsEntry)) return; - // Set returned from getStringSet() should not be modified. - scheduledTasks = new HashSet<>(scheduledTasks); - scheduledTasks.add(prefsEntry); - updateScheduledTasks(prefs, scheduledTasks); - TraceEvent.end("BackgroundTaskSchedulerPrefs.addScheduledTask"); + // Set returned from getStringSet() should not be modified. + scheduledTasks = new HashSet<>(scheduledTasks); + scheduledTasks.add(prefsEntry); + updateScheduledTasks(prefs, scheduledTasks); + } } /** Removes a task from scheduler's preferences. */ public static void removeScheduledTask(int taskId) { - TraceEvent.begin( - "BackgroundTaskSchedulerPrefs.removeScheduledTask", Integer.toString(taskId)); - SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); - Set<String> scheduledTasks = getScheduledTaskEntries(prefs); + try (TraceEvent te = TraceEvent.scoped("BackgroundTaskSchedulerPrefs.removeScheduledTask", + Integer.toString(taskId))) { + SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); + Set<String> scheduledTasks = getScheduledTaskEntries(prefs); - String entryToRemove = null; - for (String entry : scheduledTasks) { - ScheduledTaskPreferenceEntry parsed = ScheduledTaskPreferenceEntry.parseEntry(entry); - if (parsed != null && parsed.getTaskId() == taskId) { - entryToRemove = entry; - break; + String entryToRemove = null; + for (String entry : scheduledTasks) { + ScheduledTaskPreferenceEntry parsed = + ScheduledTaskPreferenceEntry.parseEntry(entry); + if (parsed != null && parsed.getTaskId() == taskId) { + entryToRemove = entry; + break; + } } + + // Entry matching taskId was not found. + if (entryToRemove == null) return; + + // Set returned from getStringSet() should not be modified. + scheduledTasks = new HashSet<>(scheduledTasks); + scheduledTasks.remove(entryToRemove); + updateScheduledTasks(prefs, scheduledTasks); } - - // Entry matching taskId was not found. - if (entryToRemove == null) return; - - // Set returned from getStringSet() should not be modified. - scheduledTasks = new HashSet<>(scheduledTasks); - scheduledTasks.remove(entryToRemove); - updateScheduledTasks(prefs, scheduledTasks); - TraceEvent.end("BackgroundTaskSchedulerPrefs.removeScheduledTask"); } /** Gets a set of scheduled task class names. */ public static Set<String> getScheduledTasks() { - TraceEvent.begin("BackgroundTaskSchedulerPrefs.getScheduledTasks"); - SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); - Set<String> scheduledTask = getScheduledTaskEntries(prefs); - Set<String> scheduledTasksClassNames = new HashSet<>(scheduledTask.size()); - for (String entry : scheduledTask) { - ScheduledTaskPreferenceEntry parsed = ScheduledTaskPreferenceEntry.parseEntry(entry); - if (parsed != null) { - scheduledTasksClassNames.add(parsed.getBackgroundTaskClass()); + try (TraceEvent te = TraceEvent.scoped("BackgroundTaskSchedulerPrefs.getScheduledTasks")) { + SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); + Set<String> scheduledTask = getScheduledTaskEntries(prefs); + Set<String> scheduledTasksClassNames = new HashSet<>(scheduledTask.size()); + for (String entry : scheduledTask) { + ScheduledTaskPreferenceEntry parsed = + ScheduledTaskPreferenceEntry.parseEntry(entry); + if (parsed != null) { + scheduledTasksClassNames.add(parsed.getBackgroundTaskClass()); + } } + return scheduledTasksClassNames; } - - TraceEvent.end("BackgroundTaskSchedulerPrefs.getScheduledTasks"); - return scheduledTasksClassNames; } /** Gets a set of scheduled task IDs. */ public static Set<Integer> getScheduledTaskIds() { - TraceEvent.begin("BackgroundTaskSchedulerPrefs.getScheduledTaskIds"); - SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); - Set<String> scheduledTasks = getScheduledTaskEntries(prefs); - Set<Integer> scheduledTaskIds = new HashSet<>(scheduledTasks.size()); - for (String entry : scheduledTasks) { - ScheduledTaskPreferenceEntry parsed = ScheduledTaskPreferenceEntry.parseEntry(entry); - if (parsed != null) { - scheduledTaskIds.add(parsed.getTaskId()); + try (TraceEvent te = + TraceEvent.scoped("BackgroundTaskSchedulerPrefs.getScheduledTaskIds")) { + SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); + Set<String> scheduledTasks = getScheduledTaskEntries(prefs); + Set<Integer> scheduledTaskIds = new HashSet<>(scheduledTasks.size()); + for (String entry : scheduledTasks) { + ScheduledTaskPreferenceEntry parsed = + ScheduledTaskPreferenceEntry.parseEntry(entry); + if (parsed != null) { + scheduledTaskIds.add(parsed.getTaskId()); + } } + return scheduledTaskIds; } - - TraceEvent.end("BackgroundTaskSchedulerPrefs.getScheduledTaskIds"); - return scheduledTaskIds; } /** Removes all scheduled tasks from shared preferences store. */ public static void removeAllTasks() { - TraceEvent.begin("BackgroundTaskSchedulerPrefs.removeAllTasks"); - ContextUtils.getAppSharedPreferences().edit().remove(KEY_SCHEDULED_TASKS).apply(); - TraceEvent.end("BackgroundTaskSchedulerPrefs.removeAllTasks"); + try (TraceEvent te = TraceEvent.scoped("BackgroundTaskSchedulerPrefs.removeAllTasks")) { + ContextUtils.getAppSharedPreferences().edit().remove(KEY_SCHEDULED_TASKS).apply(); + } } /** Gets the last SDK version on which this instance ran. Defaults to current SDK version. */ public static int getLastSdkVersion() { - TraceEvent.begin("BackgroundTaskSchedulerPrefs.getLastSdkVersion"); - int sdkInt = ContextUtils.getAppSharedPreferences().getInt( - KEY_LAST_SDK_VERSION, Build.VERSION.SDK_INT); - TraceEvent.end("BackgroundTaskSchedulerPrefs.getLastSdkVersion"); - return sdkInt; + try (TraceEvent te = TraceEvent.scoped("BackgroundTaskSchedulerPrefs.getLastSdkVersion")) { + int sdkInt = ContextUtils.getAppSharedPreferences().getInt( + KEY_LAST_SDK_VERSION, Build.VERSION.SDK_INT); + return sdkInt; + } } /** Gets the last SDK version on which this instance ran. */ public static void setLastSdkVersion(int sdkVersion) { - TraceEvent.begin( - "BackgroundTaskSchedulerPrefs.setLastSdkVersion", Integer.toString(sdkVersion)); - ContextUtils.getAppSharedPreferences() - .edit() - .putInt(KEY_LAST_SDK_VERSION, sdkVersion) - .apply(); - TraceEvent.end("BackgroundTaskSchedulerPrefs.setLastSdkVersion"); + try (TraceEvent te = TraceEvent.scoped("BackgroundTaskSchedulerPrefs.setLastSdkVersion", + Integer.toString(sdkVersion))) { + ContextUtils.getAppSharedPreferences() + .edit() + .putInt(KEY_LAST_SDK_VERSION, sdkVersion) + .apply(); + } } private static void updateScheduledTasks(SharedPreferences prefs, Set<String> tasks) {
diff --git a/components/download/internal/common/download_task_runner.cc b/components/download/internal/common/download_task_runner.cc index cc24d67d..297e041 100644 --- a/components/download/internal/common/download_task_runner.cc +++ b/components/download/internal/common/download_task_runner.cc
@@ -4,6 +4,7 @@ #include "components/download/public/common/download_task_runner.h" +#include "base/lazy_instance.h" #include "base/task_scheduler/lazy_task_runner.h" #include "build/build_config.h" @@ -24,10 +25,22 @@ base::TaskTraits(base::MayBlock(), base::TaskPriority::USER_VISIBLE)); #endif +base::LazyInstance<scoped_refptr<base::SingleThreadTaskRunner>>::Leaky + g_io_task_runner = LAZY_INSTANCE_INITIALIZER; + } // namespace scoped_refptr<base::SequencedTaskRunner> GetDownloadTaskRunner() { return g_download_task_runner.Get(); } +void SetIOTaskRunner( + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { + g_io_task_runner.Get() = task_runner; +} + +scoped_refptr<base::SequencedTaskRunner> GetIOTaskRunner() { + return g_io_task_runner.Get(); +} + } // namespace download
diff --git a/components/download/public/common/download_task_runner.h b/components/download/public/common/download_task_runner.h index b7d5bd3..b5f75e1 100644 --- a/components/download/public/common/download_task_runner.h +++ b/components/download/public/common/download_task_runner.h
@@ -6,6 +6,7 @@ #define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_TASK_RUNNER_H_ #include "base/sequenced_task_runner.h" +#include "base/single_thread_task_runner.h" #include "components/download/public/common/download_export.h" namespace download { @@ -14,6 +15,14 @@ COMPONENTS_DOWNLOAD_EXPORT scoped_refptr<base::SequencedTaskRunner> GetDownloadTaskRunner(); +// Sets the task runner used to perform network IO. +COMPONENTS_DOWNLOAD_EXPORT void SetIOTaskRunner( + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner); + +// Returns the task runner used to save files and do other blocking operations. +COMPONENTS_DOWNLOAD_EXPORT scoped_refptr<base::SequencedTaskRunner> +GetIOTaskRunner(); + } // namespace download #endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_TASK_RUNNER_H_
diff --git a/components/download/public/common/url_download_handler.h b/components/download/public/common/url_download_handler.h index 01102b5b..7ab5198 100644 --- a/components/download/public/common/url_download_handler.h +++ b/components/download/public/common/url_download_handler.h
@@ -15,6 +15,8 @@ // Class for handling the download of a url. Implemented by child classes. class COMPONENTS_DOWNLOAD_EXPORT UrlDownloadHandler { public: + using UniqueUrlDownloadHandlerPtr = + std::unique_ptr<UrlDownloadHandler, base::OnTaskRunnerDeleter>; // Class to be notified when download starts/stops. class COMPONENTS_DOWNLOAD_EXPORT Delegate { public: @@ -22,8 +24,13 @@ std::unique_ptr<DownloadCreateInfo> download_create_info, std::unique_ptr<InputStream> input_stream, const DownloadUrlParameters::OnStartedCallback& callback) = 0; + // Called after the connection is cancelled or finished. virtual void OnUrlDownloadStopped(UrlDownloadHandler* downloader) = 0; + + // Called when a UrlDownloadHandler is created. + virtual void OnUrlDownloadHandlerCreated( + UniqueUrlDownloadHandlerPtr downloader) {} }; UrlDownloadHandler() = default;
diff --git a/components/metrics/generate_expired_histograms_array.gni b/components/metrics/generate_expired_histograms_array.gni index e44dee0..b211c66 100644 --- a/components/metrics/generate_expired_histograms_array.gni +++ b/components/metrics/generate_expired_histograms_array.gni
@@ -20,6 +20,9 @@ # major_branch_date_filepath: # A path to the file with the base date. # +# milestone_filepath: +# A path to the file with the milestone information. +# template("generate_expired_histograms_array") { action(target_name) { header_filename = "$target_gen_dir/" + invoker.header_filename @@ -31,6 +34,7 @@ inputs = invoker.inputs major_branch_date_filepath = invoker.major_branch_date_filepath + milestone_filepath = invoker.milestone_filepath args = [] @@ -42,6 +46,7 @@ "-o" + rebase_path(root_gen_dir, root_build_dir), "-H" + rebase_path(header_filename, root_gen_dir), "-d" + rebase_path(major_branch_date_filepath, root_build_dir), + "-m" + rebase_path(milestone_filepath), ] + rebase_path(inputs, root_build_dir) } }
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc index 2f5a7b4a..a31197e 100644 --- a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc +++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc
@@ -64,24 +64,59 @@ DCHECK(navigation_handle()->IsInMainFrame()); DCHECK(!parent_activation_state_); DCHECK(!ruleset_handle_); - // DISABLED implies null ruleset. - DCHECK(page_activation_state.activation_level != ActivationLevel::DISABLED || - !ruleset_handle); + DCHECK_NE(ActivationLevel::DISABLED, page_activation_state.activation_level); parent_activation_state_ = page_activation_state; ruleset_handle_ = ruleset_handle; } content::NavigationThrottle::ThrottleCheckResult +ActivationStateComputingNavigationThrottle::WillStartRequest() { + if (!navigation_handle()->IsInMainFrame()) + CheckActivationState(); + return content::NavigationThrottle::PROCEED; +} + +content::NavigationThrottle::ThrottleCheckResult +ActivationStateComputingNavigationThrottle::WillRedirectRequest() { + if (!navigation_handle()->IsInMainFrame()) + CheckActivationState(); + return content::NavigationThrottle::PROCEED; +} + +content::NavigationThrottle::ThrottleCheckResult ActivationStateComputingNavigationThrottle::WillProcessResponse() { - // Main frame navigations with disabled page-level activation become - // pass-through throttles. - if (!parent_activation_state_ || - parent_activation_state_->activation_level == ActivationLevel::DISABLED) { + // If no parent activation, this is main frame that was never notified of + // activation. + if (!parent_activation_state_) { DCHECK(navigation_handle()->IsInMainFrame()); + DCHECK(!async_filter_); DCHECK(!ruleset_handle_); return content::NavigationThrottle::PROCEED; } + // Throttles which have finished their last check should just proceed here. + // All others need to defer and either wait for their existing check to + // finish, or start a new check now if there was no previous speculative + // check. + if (async_filter_ && async_filter_->has_activation_state()) { + LogDelayMetrics(base::TimeDelta::FromMilliseconds(0)); + return content::NavigationThrottle::PROCEED; + } + DCHECK(!defer_timer_); + defer_timer_ = std::make_unique<base::ElapsedTimer>(); + if (!async_filter_) { + DCHECK(navigation_handle()->IsInMainFrame()); + CheckActivationState(); + } + return content::NavigationThrottle::DEFER; +} + +const char* ActivationStateComputingNavigationThrottle::GetNameForLogging() { + return "ActivationStateComputingNavigationThrottle"; +} + +void ActivationStateComputingNavigationThrottle::CheckActivationState() { + DCHECK(parent_activation_state_); DCHECK(ruleset_handle_); AsyncDocumentSubresourceFilter::InitializationParams params; params.document_url = navigation_handle()->GetURL(); @@ -92,24 +127,27 @@ params.parent_document_origin = parent->GetLastCommittedOrigin(); } + // If there is an existing |async_filter_| that hasn't called + // OnActivationStateComputed, it will be deleted here and never call that + // method. This is by design of the AsyncDocumentSubresourceFilter, which + // will drop the message via weak pointer semantics. async_filter_ = std::make_unique<AsyncDocumentSubresourceFilter>( ruleset_handle_, std::move(params), base::Bind(&ActivationStateComputingNavigationThrottle:: OnActivationStateComputed, weak_ptr_factory_.GetWeakPtr())); - - defer_timestamp_ = base::TimeTicks::Now(); - return content::NavigationThrottle::DEFER; -} - -const char* ActivationStateComputingNavigationThrottle::GetNameForLogging() { - return "ActivationStateComputingNavigationThrottle"; } void ActivationStateComputingNavigationThrottle::OnActivationStateComputed( ActivationState state) { - DCHECK(!defer_timestamp_.is_null()); - base::TimeDelta delay = base::TimeTicks::Now() - defer_timestamp_; + if (defer_timer_) { + LogDelayMetrics(defer_timer_->Elapsed()); + Resume(); + } +} + +void ActivationStateComputingNavigationThrottle::LogDelayMetrics( + base::TimeDelta delay) const { UMA_HISTOGRAM_CUSTOM_MICRO_TIMES( "SubresourceFilter.DocumentLoad.ActivationComputingDelay", delay, base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10), @@ -120,7 +158,6 @@ delay, base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10), 50); } - Resume(); } AsyncDocumentSubresourceFilter*
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h index fc67179..20e01345 100644 --- a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h +++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h
@@ -11,6 +11,7 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/time/time.h" +#include "base/timer/elapsed_timer.h" #include "components/subresource_filter/content/browser/verified_ruleset_dealer.h" #include "components/subresource_filter/core/common/activation_state.h" #include "content/public/browser/navigation_throttle.h" @@ -22,9 +23,15 @@ // NavigationThrottle responsible for determining the activation state of // subresource filtering for a given navigation (either in the main frame or in // a subframe); and for deferring that navigation at WillProcessResponse until -// the activation state computation on the blocking pool thread is complete. +// the activation state computation on the ruleset's task runner is complete. +// // Interested parties can retrieve the activation state after this point (most // likely in ReadyToCommitNavigation). +// +// Note: for performance, activation computation for subframes is done +// speculatively at navigation start and at every redirect. This is to reduce +// the wait time (most likely to 0) by WillProcessResponse time. +// TODO(crbug.com/809504): Implement speculation for main frames as well. class ActivationStateComputingNavigationThrottle : public content::NavigationThrottle { public: @@ -47,8 +54,10 @@ // Notification for main frames when the page level activation is computed. // Must be called at most once before WillProcessResponse is called on this - // throttle. If it is never called, or it is called with a DISABLED state, - // this object will never delay the navigation. + // throttle. If it is never called, this object will never delay the + // navigation for main frames. + // + // Should never be called with DISABLED activation. void NotifyPageActivationWithRuleset( VerifiedRuleset::Handle* ruleset_handle, const ActivationState& page_activation_state); @@ -58,6 +67,9 @@ } // content::NavigationThrottle: + content::NavigationThrottle::ThrottleCheckResult WillStartRequest() override; + content::NavigationThrottle::ThrottleCheckResult WillRedirectRequest() + override; content::NavigationThrottle::ThrottleCheckResult WillProcessResponse() override; const char* GetNameForLogging() override; @@ -74,8 +86,11 @@ void WillSendActivationToRenderer(); private: + void CheckActivationState(); void OnActivationStateComputed(ActivationState state); + void LogDelayMetrics(base::TimeDelta delay) const; + ActivationStateComputingNavigationThrottle( content::NavigationHandle* navigation_handle, const base::Optional<ActivationState> parent_activation_state, @@ -90,7 +105,9 @@ // nullptr until NotifyPageActivationWithRuleset is called. VerifiedRuleset::Handle* ruleset_handle_; - base::TimeTicks defer_timestamp_; + // Will be set when DEFER is called in WillProcessResponse. If nullptr, not + // deferred. + std::unique_ptr<base::ElapsedTimer> defer_timer_; // Callback to be run in the destructor. base::OnceClosure destruction_closure_;
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc index 6742720..36ced49 100644 --- a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc +++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
@@ -10,11 +10,13 @@ #include "base/callback.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" +#include "base/memory/scoped_refptr.h" #include "base/optional.h" #include "base/run_loop.h" +#include "base/sequenced_task_runner.h" #include "base/test/histogram_tester.h" #include "base/test/test_simple_task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "components/subresource_filter/content/browser/async_document_subresource_filter.h" #include "components/subresource_filter/content/browser/async_document_subresource_filter_test_utils.h" #include "components/subresource_filter/core/common/activation_level.h" @@ -36,7 +38,9 @@ : public content::RenderViewHostTestHarness, public content::WebContentsObserver { public: - ActivationStateComputingNavigationThrottleTest() {} + ActivationStateComputingNavigationThrottleTest() + : simple_task_runner_( + base::MakeRefCounted<base::TestSimpleTaskRunner>()) {} ~ActivationStateComputingNavigationThrottleTest() override {} void SetUp() override { @@ -49,7 +53,11 @@ void TearDown() override { ruleset_handle_.reset(); dealer_handle_.reset(); - RunUntilIdle(); + + // The various ruleset classes post tasks to delete their blocking task + // runners. Make sure that happens now to avoid test-only leaks. + base::RunLoop().RunUntilIdle(); + simple_task_runner()->RunUntilIdle(); content::RenderViewHostTestHarness::TearDown(); } @@ -78,12 +86,7 @@ // Make the blocking task runner run on the current task runner for the // tests, to ensure that the NavigationSimulator properly runs all necessary // tasks while waiting for throttle checks to finish. - dealer_handle_ = std::make_unique<VerifiedRulesetDealer::Handle>( - base::MessageLoop::current()->task_runner()); - dealer_handle_->TryOpenAndSetRulesetFile(test_ruleset_pair_.indexed.path, - base::DoNothing()); - ruleset_handle_ = - std::make_unique<VerifiedRuleset::Handle>(dealer_handle_.get()); + InitializeRulesetHandles(base::SequencedTaskRunnerHandle::Get()); } void NavigateAndCommitMainFrameWithPageActivationState( @@ -96,8 +99,6 @@ SimulateCommitAndExpectToProceed(); } - void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } - void CreateTestNavigationForMainFrame(const GURL& first_url) { navigation_simulator_ = content::NavigationSimulator::CreateRendererInitiated(first_url, @@ -136,12 +137,19 @@ navigation_simulator_->GetLastThrottleCheckResult()); } + void InitializeRulesetHandles( + scoped_refptr<base::SequencedTaskRunner> ruleset_task_runner) { + dealer_handle_ = std::make_unique<VerifiedRulesetDealer::Handle>( + std::move(ruleset_task_runner)); + dealer_handle_->TryOpenAndSetRulesetFile(test_ruleset_pair_.indexed.path, + base::DoNothing()); + ruleset_handle_ = + std::make_unique<VerifiedRuleset::Handle>(dealer_handle_.get()); + } + void NotifyPageActivation(ActivationState state) { - test_throttle_->NotifyPageActivationWithRuleset( - state.activation_level == ActivationLevel::DISABLED - ? nullptr - : ruleset_handle_.get(), - state); + test_throttle_->NotifyPageActivationWithRuleset(ruleset_handle_.get(), + state); } ActivationState last_activation_state() { @@ -154,6 +162,10 @@ return last_committed_frame_host_; } + scoped_refptr<base::TestSimpleTaskRunner> simple_task_runner() { + return simple_task_runner_; + } + protected: // content::WebContentsObserver: void DidStartNavigation( @@ -203,6 +215,8 @@ std::unique_ptr<content::NavigationSimulator> navigation_simulator_; + scoped_refptr<base::TestSimpleTaskRunner> simple_task_runner_; + // Owned by the current navigation. ActivationStateComputingNavigationThrottle* test_throttle_; base::Optional<ActivationState> last_activation_state_; @@ -241,16 +255,6 @@ } TEST_F(ActivationStateComputingThrottleMainFrameTest, - DisabledPageActivation_NoActivation) { - // Notify that the page level activation is explicitly disabled. Should be - // equivalent to not sending the message at all to the main frame throttle. - NavigateAndCommitMainFrameWithPageActivationState( - GURL("http://example.test/"), ActivationState(ActivationLevel::DISABLED)); - ActivationState state = last_activation_state(); - EXPECT_EQ(ActivationLevel::DISABLED, state.activation_level); -} - -TEST_F(ActivationStateComputingThrottleMainFrameTest, WhitelistDoesNotApply_CausesActivation) { NavigateAndCommitMainFrameWithPageActivationState( GURL("http://allow-child-to-be-whitelisted.com/"), @@ -474,4 +478,98 @@ histogram_tester.ExpectTotalCount(kActivationDelayMainFrame, 1); } +TEST_F(ActivationStateComputingThrottleSubFrameTest, SpeculativeSubframes) { + // Use the activation performance metric as a proxy for how many times + // activation computation occurred. + base::HistogramTester histogram_tester; + const char kActivationCPU[] = + "SubresourceFilter.DocumentLoad.Activation.CPUDuration"; + + // Main frames don't do speculative lookups, a navigation commit should only + // trigger a single ruleset lookup. + CreateTestNavigationForMainFrame(GURL("http://example.test/")); + SimulateStartAndExpectToProceed(); + histogram_tester.ExpectTotalCount(kActivationCPU, 0); + + SimulateRedirectAndExpectToProceed(GURL("http://example.test2/")); + histogram_tester.ExpectTotalCount(kActivationCPU, 0); + + NotifyPageActivation(ActivationState(ActivationLevel::ENABLED)); + SimulateCommitAndExpectToProceed(); + histogram_tester.ExpectTotalCount(kActivationCPU, 1); + + CreateSubframeAndInitTestNavigation(GURL("http://example.test/"), + last_committed_frame_host(), + last_activation_state()); + // For subframes, do a ruleset lookup at the start and every redirect. + SimulateStartAndExpectToProceed(); + histogram_tester.ExpectTotalCount(kActivationCPU, 2); + + SimulateRedirectAndExpectToProceed(GURL("http://example.test2/")); + histogram_tester.ExpectTotalCount(kActivationCPU, 3); + + // No ruleset lookup required at commit because we've already checked the + // latest URL. + SimulateCommitAndExpectToProceed(); + histogram_tester.ExpectTotalCount(kActivationCPU, 3); +} + +TEST_F(ActivationStateComputingThrottleSubFrameTest, + SpeculativeSubframesWithDelay) { + InitializeRulesetHandles(simple_task_runner()); + + // TODO(csharrison): Once crbug.com/822275 is resolved, implement this via a + // Wait() style interface on NavigationSimulator. Right now it is very hacky: + // essentially we post a task to finish tasks on |simple_task_runner_| before + // a navigation stage (when necessary). NavigationSimulator internals pump the + // run loop which runs this task after throttles run. + auto task_runner = simple_task_runner(); + auto post_advance = [task_runner]() { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&base::TestSimpleTaskRunner::RunPendingTasks, + base::RetainedRef(task_runner))); + }; + + // Use the activation performance metric as a proxy for how many times + // activation computation occurred. + base::HistogramTester histogram_tester; + const char kActivationCPU[] = + "SubresourceFilter.DocumentLoad.Activation.CPUDuration"; + + // Main frames don't do speculative lookups, a navigation commit should only + // trigger a single ruleset lookup. + CreateTestNavigationForMainFrame(GURL("http://example.test/")); + SimulateStartAndExpectToProceed(); + histogram_tester.ExpectTotalCount(kActivationCPU, 0); + + SimulateRedirectAndExpectToProceed(GURL("http://example.test2/")); + histogram_tester.ExpectTotalCount(kActivationCPU, 0); + + NotifyPageActivation(ActivationState(ActivationLevel::ENABLED)); + post_advance(); + SimulateCommitAndExpectToProceed(); + histogram_tester.ExpectTotalCount(kActivationCPU, 1); + + CreateSubframeAndInitTestNavigation(GURL("http://example.test/"), + last_committed_frame_host(), + last_activation_state()); + + // Simulate slow ruleset checks for the subframe, these should not delay the + // navigation until commit time. + SimulateStartAndExpectToProceed(); + histogram_tester.ExpectTotalCount(kActivationCPU, 1); + + // Calling redirect should ensure that the throttle does not receive the + // results of the check, but the task to actually perform the check will still + // happen. + SimulateRedirectAndExpectToProceed(GURL("http://example.test2/")); + histogram_tester.ExpectTotalCount(kActivationCPU, 1); + + // Finish the checks dispatched in the start and redirect phase when the + // navigation is ready to commit. + post_advance(); + SimulateCommitAndExpectToProceed(); + histogram_tester.ExpectTotalCount(kActivationCPU, 3); +} + } // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter.h b/components/subresource_filter/content/browser/async_document_subresource_filter.h index 1c3b511..749415f 100644 --- a/components/subresource_filter/content/browser/async_document_subresource_filter.h +++ b/components/subresource_filter/content/browser/async_document_subresource_filter.h
@@ -95,6 +95,9 @@ // with the current thread. If MemoryMappedRuleset is not present or // malformed, then a default ActivationState is reported (with ActivationLevel // equal to DISABLED). + // + // If deleted before |activation_state_callback| is called, the callback will + // never be called. AsyncDocumentSubresourceFilter( VerifiedRuleset::Handle* ruleset_handle, InitializationParams params,
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter_test_utils.h b/components/subresource_filter/content/browser/async_document_subresource_filter_test_utils.h index 4858add..60f9739 100644 --- a/components/subresource_filter/content/browser/async_document_subresource_filter_test_utils.h +++ b/components/subresource_filter/content/browser/async_document_subresource_filter_test_utils.h
@@ -25,6 +25,8 @@ void WaitForActivationDecision(); void ExpectReceivedOnce(const ActivationState& expected_state) const; + int callback_count() const { return callback_count_; } + private: void Callback(ActivationState activation_state);
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc b/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc index d3e3779e..7d4cb88 100644 --- a/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc +++ b/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc
@@ -151,6 +151,23 @@ ActivationState(ActivationLevel::ENABLED)); } +TEST_F(AsyncDocumentSubresourceFilterTest, DeleteFilter_NoActivationCallback) { + dealer_handle()->TryOpenAndSetRulesetFile(ruleset().path, base::DoNothing()); + auto ruleset_handle = CreateRulesetHandle(); + + AsyncDocumentSubresourceFilter::InitializationParams params( + GURL("http://example.com"), ActivationLevel::ENABLED, false); + + testing::TestActivationStateCallbackReceiver activation_state; + auto filter = std::make_unique<AsyncDocumentSubresourceFilter>( + ruleset_handle.get(), std::move(params), activation_state.GetCallback()); + + EXPECT_FALSE(filter->has_activation_state()); + filter.reset(); + RunUntilIdle(); + EXPECT_EQ(0, activation_state.callback_count()); +} + TEST_F(AsyncDocumentSubresourceFilterTest, ActivationStateIsComputedCorrectly) { dealer_handle()->TryOpenAndSetRulesetFile(ruleset().path, base::DoNothing()); auto ruleset_handle = CreateRulesetHandle();
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent.cc b/components/subresource_filter/content/renderer/subresource_filter_agent.cc index 7e5964c..3fbfe87 100644 --- a/components/subresource_filter/content/renderer/subresource_filter_agent.cc +++ b/components/subresource_filter/content/renderer/subresource_filter_agent.cc
@@ -58,11 +58,6 @@ web_frame->GetDocumentLoader()->SetSubresourceFilter(filter.release()); } -void SubresourceFilterAgent::SetIsAdSubframeForDocument(bool is_ad_subframe) { - blink::WebLocalFrame* web_frame = render_frame()->GetWebFrame(); - web_frame->GetDocumentLoader()->SetIsAdSubframe(is_ad_subframe); -} - void SubresourceFilterAgent:: SignalFirstSubresourceDisallowedForCommittedLoad() { render_frame()->Send(new SubresourceFilterHostMsg_DidDisallowFirstSubresource( @@ -207,12 +202,10 @@ AsWeakPtr())); auto filter = std::make_unique<WebDocumentSubresourceFilterImpl>( url::Origin::Create(url), activation_state, std::move(ruleset), - std::move(first_disallowed_load_callback)); + std::move(first_disallowed_load_callback), is_ad_subframe); filter_for_last_committed_load_ = filter->AsWeakPtr(); SetSubresourceFilterForCommittedLoad(std::move(filter)); - if (is_ad_subframe) - SetIsAdSubframeForDocument(true); } void SubresourceFilterAgent::DidFailProvisionalLoad( @@ -246,6 +239,12 @@ base::File ruleset_file = ruleset_dealer_->DuplicateRulesetFile(); if (!ruleset_file.IsValid()) return; + + // Propagate the information to the worker whether this is associated with an + // ad subframe. + bool is_ad_subframe = + render_frame()->GetWebFrame()->GetDocumentLoader()->GetIsAdSubframe(); + worker_fetch_context->SetSubresourceFilterBuilder( std::make_unique<WebDocumentSubresourceFilterImpl::BuilderImpl>( url::Origin::Create(GetDocumentURL()), @@ -253,7 +252,8 @@ std::move(ruleset_file), base::BindOnce(&SubresourceFilterAgent:: SignalFirstSubresourceDisallowedForCommittedLoad, - AsWeakPtr()))); + AsWeakPtr()), + is_ad_subframe)); } } // namespace subresource_filter
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent.h b/components/subresource_filter/content/renderer/subresource_filter_agent.h index def12ac..5860bf6a 100644 --- a/components/subresource_filter/content/renderer/subresource_filter_agent.h +++ b/components/subresource_filter/content/renderer/subresource_filter_agent.h
@@ -52,9 +52,6 @@ virtual void SetSubresourceFilterForCommittedLoad( std::unique_ptr<blink::WebDocumentSubresourceFilter> filter); - // Sets in the underlying document, whether this is identified as an ad. - virtual void SetIsAdSubframeForDocument(bool is_ad_subframe); - // Informs the browser that the first subresource load has been disallowed for // the most recently committed load. Not called if all resources are allowed. virtual void SignalFirstSubresourceDisallowedForCommittedLoad();
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc b/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc index 84270e6..f3b7b74 100644 --- a/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc +++ b/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc
@@ -59,12 +59,10 @@ OnSetSubresourceFilterForCommittedLoadCalled(); } - void SetIsAdSubframeForDocument(bool is_ad_subframe) override { - is_ad_subframe_ = is_ad_subframe; + bool GetIsAssociatedWithAdSubframe() { + return last_injected_filter_->GetIsAssociatedWithAdSubframe(); } - bool GetIsAdSubframe() { return is_ad_subframe_; } - blink::WebDocumentSubresourceFilter* filter() { return last_injected_filter_.get(); } @@ -74,7 +72,6 @@ } private: - bool is_ad_subframe_ = false; std::unique_ptr<blink::WebDocumentSubresourceFilter> last_injected_filter_; DISALLOW_COPY_AND_ASSIGN(SubresourceFilterAgentUnderTest); @@ -521,16 +518,21 @@ filter->ReportDisallowedLoad(); } -TEST_F(SubresourceFilterAgentTest, DryRun_DocumentIsAdSubframeTagging) { - base::HistogramTester histogram_tester; +TEST_F(SubresourceFilterAgentTest, + DryRun_IsAssociatedWithAdSubframeforDocumentOrDedicatedWorker) { ASSERT_NO_FATAL_FAILURE( SetTestRulesetToDisallowURLsWithPathSuffix(kTestFirstURLPathSuffix)); ExpectSubresourceFilterGetsInjected(); StartLoadAndSetActivationState(ActivationState(ActivationLevel::DRYRUN), - true /* is_ad_subframe */); + true /* is_associated_with_ad_subframe */); ASSERT_TRUE(::testing::Mock::VerifyAndClearExpectations(agent())); - EXPECT_TRUE(agent()->GetIsAdSubframe()); + // Test the ad subframe value that is set at the filter. + // This also represents the flag passed to a dedicated worker filter created. + // For testing the flag passed to the dedicated worker filter, the unit test + // is not able to test the implementation of WillCreateWorkerFetchContext as + // that will require setup of a WebWorkerFetchContextImpl. + EXPECT_TRUE(agent()->GetIsAssociatedWithAdSubframe()); } } // namespace subresource_filter
diff --git a/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc b/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc index 9fc90c56..9b0f151 100644 --- a/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc +++ b/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc
@@ -106,11 +106,13 @@ url::Origin document_origin, ActivationState activation_state, scoped_refptr<const MemoryMappedRuleset> ruleset, - base::OnceClosure first_disallowed_load_callback) + base::OnceClosure first_disallowed_load_callback, + bool is_associated_with_ad_subframe) : activation_state_(activation_state), filter_(std::move(document_origin), activation_state, std::move(ruleset)), first_disallowed_load_callback_( - std::move(first_disallowed_load_callback)) {} + std::move(first_disallowed_load_callback)), + is_associated_with_ad_subframe_(is_associated_with_ad_subframe) {} WebLoadPolicy WebDocumentSubresourceFilterImpl::GetLoadPolicy( const blink::WebURL& resourceUrl, @@ -134,6 +136,10 @@ return activation_state().enable_logging; } +bool WebDocumentSubresourceFilterImpl::GetIsAssociatedWithAdSubframe() const { + return is_associated_with_ad_subframe_; +} + WebLoadPolicy WebDocumentSubresourceFilterImpl::getLoadPolicyImpl( const blink::WebURL& url, proto::ElementType element_type) { @@ -151,13 +157,15 @@ url::Origin document_origin, ActivationState activation_state, base::File ruleset_file, - base::OnceClosure first_disallowed_load_callback) + base::OnceClosure first_disallowed_load_callback, + bool is_associated_with_ad_subframe) : document_origin_(std::move(document_origin)), activation_state_(std::move(activation_state)), ruleset_file_(std::move(ruleset_file)), first_disallowed_load_callback_( std::move(first_disallowed_load_callback)), - main_task_runner_(base::MessageLoop::current()->task_runner()) {} + main_task_runner_(base::MessageLoop::current()->task_runner()), + is_associated_with_ad_subframe_(is_associated_with_ad_subframe) {} WebDocumentSubresourceFilterImpl::BuilderImpl::~BuilderImpl() {} @@ -169,7 +177,8 @@ document_origin_, activation_state_, base::MakeRefCounted<MemoryMappedRuleset>(std::move(ruleset_file_)), base::BindOnce(&ProxyToTaskRunner, main_task_runner_, - std::move(first_disallowed_load_callback_))); + std::move(first_disallowed_load_callback_)), + is_associated_with_ad_subframe_); } } // namespace subresource_filter
diff --git a/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.h b/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.h index 826a07e..3b441713 100644 --- a/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.h +++ b/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.h
@@ -31,7 +31,8 @@ BuilderImpl(url::Origin document_origin, ActivationState activation_state, base::File ruleset_file, - base::OnceClosure first_disallowed_load_callback); + base::OnceClosure first_disallowed_load_callback, + bool is_associated_with_ad_subframe); ~BuilderImpl() override; std::unique_ptr<blink::WebDocumentSubresourceFilter> Build() override; @@ -42,6 +43,7 @@ base::File ruleset_file_; base::OnceClosure first_disallowed_load_callback_; scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + bool is_associated_with_ad_subframe_; DISALLOW_COPY_AND_ASSIGN(BuilderImpl); }; @@ -54,7 +56,8 @@ url::Origin document_origin, ActivationState activation_state, scoped_refptr<const MemoryMappedRuleset> ruleset, - base::OnceClosure first_disallowed_load_callback); + base::OnceClosure first_disallowed_load_callback, + bool is_associated_with_ad_subframe); ~WebDocumentSubresourceFilterImpl() override; @@ -67,6 +70,7 @@ const blink::WebURL& url) override; void ReportDisallowedLoad() override; bool ShouldLogToConsole() override; + bool GetIsAssociatedWithAdSubframe() const override; const ActivationState& activation_state() const { return filter_.activation_state(); @@ -80,6 +84,7 @@ ActivationState activation_state_; DocumentSubresourceFilter filter_; base::OnceClosure first_disallowed_load_callback_; + bool is_associated_with_ad_subframe_; DISALLOW_COPY_AND_ASSIGN(WebDocumentSubresourceFilterImpl); };
diff --git a/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc b/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc index ac9bcdfe..598225d 100644 --- a/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc +++ b/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc
@@ -106,7 +106,22 @@ } // namespace -TEST(SubresourceFilterFeaturesTest, ActivationLevel) { +class SubresourceFilterFeaturesTest : public ::testing::Test { + public: + SubresourceFilterFeaturesTest() {} + ~SubresourceFilterFeaturesTest() override {} + + void SetUp() override { + // Reset the global configuration at the start so tests start without a + // cached value from a previous in-process test run. + testing::GetAndSetActivateConfigurations(nullptr); + } + + private: + DISALLOW_COPY_AND_ASSIGN(SubresourceFilterFeaturesTest); +}; + +TEST_F(SubresourceFilterFeaturesTest, ActivationLevel) { const struct { bool feature_enabled; const char* activation_level_param; @@ -149,7 +164,7 @@ } } -TEST(SubresourceFilterFeaturesTest, ActivationScope) { +TEST_F(SubresourceFilterFeaturesTest, ActivationScope) { const struct { bool feature_enabled; const char* activation_scope_param; @@ -192,7 +207,7 @@ } } -TEST(SubresourceFilterFeaturesTest, ActivationLevelAndScope) { +TEST_F(SubresourceFilterFeaturesTest, ActivationLevelAndScope) { const struct { bool feature_enabled; const char* activation_level_param; @@ -255,7 +270,7 @@ } } -TEST(SubresourceFilterFeaturesTest, ActivationList) { +TEST_F(SubresourceFilterFeaturesTest, ActivationList) { const std::string activation_soc_eng( kActivationListSocialEngineeringAdsInterstitial); const std::string activation_phishing(kActivationListPhishingInterstitial); @@ -315,7 +330,7 @@ } } -TEST(SubresourceFilterFeaturesTest, ActivationPriority) { +TEST_F(SubresourceFilterFeaturesTest, ActivationPriority) { const struct { bool feature_enabled; const char* activation_priority_param; @@ -358,7 +373,7 @@ } } -TEST(SubresourceFilterFeaturesTest, PerfMeasurementRate) { +TEST_F(SubresourceFilterFeaturesTest, PerfMeasurementRate) { const struct { bool feature_enabled; const char* perf_measurement_param; @@ -400,7 +415,7 @@ } } -TEST(SubresourceFilterFeaturesTest, SuppressNotifications) { +TEST_F(SubresourceFilterFeaturesTest, SuppressNotifications) { const struct { bool feature_enabled; const char* suppress_notifications_param; @@ -439,7 +454,7 @@ } } -TEST(SubresourceFilterFeaturesTest, WhitelistSiteOnReload) { +TEST_F(SubresourceFilterFeaturesTest, WhitelistSiteOnReload) { const struct { bool feature_enabled; const char* whitelist_site_on_reload_param; @@ -478,7 +493,7 @@ } } -TEST(SubresourceFilterFeaturesTest, RulesetFlavor) { +TEST_F(SubresourceFilterFeaturesTest, RulesetFlavor) { const struct { bool feature_enabled; const char* ruleset_flavor_param; @@ -508,7 +523,7 @@ } } -TEST(SubresourceFilterFeaturesTest, LexicographicallyGreatestRulesetFlavor) { +TEST_F(SubresourceFilterFeaturesTest, LexicographicallyGreatestRulesetFlavor) { const struct { const char* expected_ruleset_flavor_selected; std::vector<std::string> ruleset_flavors; @@ -549,7 +564,7 @@ } } -TEST(SubresourceFilterFeaturesTest, EnabledConfigurations_FeatureDisabled) { +TEST_F(SubresourceFilterFeaturesTest, EnabledConfigurations_FeatureDisabled) { ScopedExperimentalStateToggle scoped_experimental_state( base::FeatureList::OVERRIDE_DISABLE_FEATURE, std::map<std::string, std::string>()); @@ -561,8 +576,8 @@ config_list->lexicographically_greatest_ruleset_flavor()); } -TEST(SubresourceFilterFeaturesTest, - EnabledConfigurations_FeatureEnabledWithNoParameters) { +TEST_F(SubresourceFilterFeaturesTest, + EnabledConfigurations_FeatureEnabledWithNoParameters) { ScopedExperimentalStateToggle scoped_experimental_state( base::FeatureList::OVERRIDE_ENABLE_FEATURE, std::map<std::string, std::string>()); @@ -577,8 +592,8 @@ config_list->lexicographically_greatest_ruleset_flavor()); } -TEST(SubresourceFilterFeaturesTest, - PresetForPerformanceTestingDryRunOnAllSites) { +TEST_F(SubresourceFilterFeaturesTest, + PresetForPerformanceTestingDryRunOnAllSites) { ExpectPresetCanBeEnabledByName( Configuration::MakePresetForPerformanceTestingDryRunOnAllSites(), kPresetPerformanceTestingDryRunOnAllSites); @@ -590,7 +605,7 @@ {kPerformanceMeasurementRateParameterName, "1.0"}}); } -TEST(SubresourceFilterFeaturesTest, PresetForLiveRunOnBetterAdsSites) { +TEST_F(SubresourceFilterFeaturesTest, PresetForLiveRunOnBetterAdsSites) { const Configuration config = Configuration::MakePresetForLiveRunForBetterAds(); EXPECT_EQ(ActivationList::BETTER_ADS, @@ -606,7 +621,7 @@ EXPECT_FALSE(config.activation_options.should_whitelist_site_on_reload); } -TEST(SubresourceFilterFeaturesTest, ConfigurationPriorities) { +TEST_F(SubresourceFilterFeaturesTest, ConfigurationPriorities) { const std::vector<Configuration> expected_order_by_decreasing_priority = { Configuration::MakePresetForLiveRunOnPhishingSites(), Configuration::MakePresetForLiveRunForBetterAds(), @@ -626,7 +641,7 @@ ::testing::ElementsAreArray(expected_order_by_decreasing_priority)); } -TEST(SubresourceFilterFeaturesTest, EnableDisableMultiplePresets) { +TEST_F(SubresourceFilterFeaturesTest, EnableDisableMultiplePresets) { const std::string kPhishing(kPresetLiveRunOnPhishingSites); const std::string kPerfTest(kPresetPerformanceTestingDryRunOnAllSites); const std::string kBAS(kPresetLiveRunForBetterAds); @@ -679,8 +694,8 @@ } } -TEST(SubresourceFilterFeaturesTest, - EnableMultiplePresetsAndExperimentalConfig) { +TEST_F(SubresourceFilterFeaturesTest, + EnableMultiplePresetsAndExperimentalConfig) { const std::string kPhishing(kPresetLiveRunOnPhishingSites); const std::string kPerfTest(kPresetPerformanceTestingDryRunOnAllSites); const std::string kBAS(kPresetLiveRunForBetterAds); @@ -713,7 +728,7 @@ config_list->lexicographically_greatest_ruleset_flavor()); } -TEST(SubresourceFilterFeaturesTest, ForcedActivation_NotConfigurable) { +TEST_F(SubresourceFilterFeaturesTest, ForcedActivation_NotConfigurable) { ScopedExperimentalStateToggle scoped_experimental_state( base::FeatureList::OVERRIDE_ENABLE_FEATURE, {{kActivationLevelParameterName, kActivationLevelEnabled}, @@ -730,7 +745,7 @@ EXPECT_FALSE(actual_configuration.activation_conditions.forced_activation); } -TEST(SubresourceFilterFeaturesTest, AdTagging_EnablesDryRun) { +TEST_F(SubresourceFilterFeaturesTest, AdTagging_EnablesDryRun) { const Configuration dryrun = Configuration::MakePresetForPerformanceTestingDryRunOnAllSites(); base::test::ScopedFeatureList scoped_feature; @@ -739,14 +754,7 @@ GetEnabledConfigurations()->configs_by_decreasing_priority(), dryrun)); } -// TODO(crbug.com/823449): Test fails on iOS. Re-enable after fixing. -#if defined(OS_IOS) -#define MAYBE_AdTaggingDisabled_DisablesDryRun \ - DISABLED_AdTaggingDisabled_DisablesDryRun -#else -#define MAYBE_AdTaggingDisabled_DisablesDryRun AdTaggingDisabled_DisablesDryRun -#endif -TEST(SubresourceFilterFeaturesTest, MAYBE_AdTaggingDisabled_DisablesDryRun) { +TEST_F(SubresourceFilterFeaturesTest, AdTaggingDisabled_DisablesDryRun) { const Configuration dryrun = Configuration::MakePresetForPerformanceTestingDryRunOnAllSites(); base::test::ScopedFeatureList scoped_feature;
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc index b2364574..8f02ddf 100644 --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc
@@ -13,7 +13,7 @@ // Enables running draw occlusion algorithm to remove Draw Quads that are not // shown on screen from CompositorFrame. const base::Feature kEnableDrawOcclusion{"DrawOcclusion", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; #if defined(USE_AURA) || defined(OS_MACOSX) const base::Feature kEnableSurfaceSynchronization{
diff --git a/components/viz/common/gpu/texture_allocation.cc b/components/viz/common/gpu/texture_allocation.cc index ef19a49..90b51e28 100644 --- a/components/viz/common/gpu/texture_allocation.cc +++ b/components/viz/common/gpu/texture_allocation.cc
@@ -5,6 +5,7 @@ #include "components/viz/common/gpu/texture_allocation.h" #include "components/viz/common/resources/resource_format_utils.h" +#include "components/viz/common/resources/resource_sizes.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/raster_interface.h" @@ -22,16 +23,14 @@ ResourceFormat format, bool use_gpu_memory_buffer_resources, bool for_framebuffer_attachment) { - bool overlay_textures = use_gpu_memory_buffer_resources && - caps.texture_storage_image && - IsGpuMemoryBufferFormatSupported(format); - uint32_t texture_target = GL_TEXTURE_2D; - bool overlay_candidate = false; - if (overlay_textures) { + + bool overlay_candidate = use_gpu_memory_buffer_resources && + caps.texture_storage_image && + IsGpuMemoryBufferFormatSupported(format); + if (overlay_candidate) { texture_target = gpu::GetBufferTextureTarget(gfx::BufferUsage::SCANOUT, BufferFormat(format), caps); - overlay_candidate = true; } uint32_t texture_id; @@ -106,4 +105,27 @@ } } +void TextureAllocation::UploadStorage(gpu::gles2::GLES2Interface* gl, + const gpu::Capabilities& caps, + ResourceFormat format, + const gfx::Size& size, + const TextureAllocation& alloc, + const gfx::ColorSpace& color_space, + const void* pixels) { + if (format == ETC1) { + DCHECK_EQ(alloc.texture_target, static_cast<GLenum>(GL_TEXTURE_2D)); + int num_bytes = ResourceSizes::CheckedSizeInBytes<int>(size, ETC1); + + gl->BindTexture(alloc.texture_target, alloc.texture_id); + gl->CompressedTexImage2D(alloc.texture_target, 0, GLInternalFormat(ETC1), + size.width(), size.height(), 0, num_bytes, + const_cast<void*>(pixels)); + } else { + AllocateStorage(gl, caps, format, size, alloc, color_space); + gl->TexSubImage2D(alloc.texture_target, 0, 0, 0, size.width(), + size.height(), GLDataFormat(format), GLDataType(format), + const_cast<void*>(pixels)); + } +} + } // namespace viz
diff --git a/components/viz/common/gpu/texture_allocation.h b/components/viz/common/gpu/texture_allocation.h index 61b40e4f..6524f61 100644 --- a/components/viz/common/gpu/texture_allocation.h +++ b/components/viz/common/gpu/texture_allocation.h
@@ -58,6 +58,18 @@ const gfx::Size& size, const TextureAllocation& alloc, const gfx::ColorSpace& color_space); + + // Allocates storage for a texture id previously generated by MakeTextureId(), + // and uploads the contents of |pixels| to it. |pixels| should point to a + // bitmap with a width and height of |size|, and no additional row stride + // padding. + static void UploadStorage(gpu::gles2::GLES2Interface* gl, + const gpu::Capabilities& caps, + ResourceFormat format, + const gfx::Size& size, + const TextureAllocation& alloc, + const gfx::ColorSpace& color_space, + const void* pixels); }; } // namespace viz
diff --git a/components/viz/common/resources/bitmap_allocation.cc b/components/viz/common/resources/bitmap_allocation.cc index 3924c58b..1e23ed5c61 100644 --- a/components/viz/common/resources/bitmap_allocation.cc +++ b/components/viz/common/resources/bitmap_allocation.cc
@@ -6,6 +6,7 @@ #include <stdint.h> +#include "base/debug/alias.h" #include "base/memory/shared_memory.h" #include "base/process/memory.h" #include "build/build_config.h" @@ -14,11 +15,6 @@ #include "mojo/public/cpp/system/platform_handle.h" #include "ui/gfx/geometry/size.h" -#if defined(OS_WIN) -#include "base/debug/alias.h" -#include "base/process/process_metrics.h" -#endif - namespace viz { namespace { @@ -27,25 +23,17 @@ ResourceFormat format, size_t alloc_size) { #if defined(OS_WIN) + DWORD last_error = GetLastError(); + base::debug::Alias(&last_error); +#endif + int width = size.width(); int height = size.height(); - DWORD last_error = GetLastError(); - - std::unique_ptr<base::ProcessMetrics> metrics( - base::ProcessMetrics::CreateProcessMetrics( - base::GetCurrentProcessHandle())); - - size_t private_bytes = 0; - size_t shared_bytes = 0; - metrics->GetMemoryBytes(&private_bytes, &shared_bytes); base::debug::Alias(&width); base::debug::Alias(&height); base::debug::Alias(&format); - base::debug::Alias(&last_error); - base::debug::Alias(&private_bytes); - base::debug::Alias(&shared_bytes); -#endif + base::TerminateBecauseOutOfMemory(alloc_size); } } // namespace
diff --git a/components/viz/common/resources/resource_format_utils.cc b/components/viz/common/resources/resource_format_utils.cc index 5433ef0..a7c072f52 100644 --- a/components/viz/common/resources/resource_format_utils.cc +++ b/components/viz/common/resources/resource_format_utils.cc
@@ -160,9 +160,10 @@ case LUMINANCE_8: case RGB_565: case LUMINANCE_F16: + // These types not allowed by IsGpuMemoryBufferFormatSupported(), so + // give a default value that will not be used. break; } - NOTREACHED(); return gfx::BufferFormat::RGBA_8888; }
diff --git a/components/viz/common/resources/resource_format_utils.h b/components/viz/common/resources/resource_format_utils.h index fb05834..5d6b4101 100644 --- a/components/viz/common/resources/resource_format_utils.h +++ b/components/viz/common/resources/resource_format_utils.h
@@ -27,6 +27,10 @@ VIZ_RESOURCE_FORMAT_EXPORT unsigned int GLCopyTextureInternalFormat( ResourceFormat format); +// Returns the pixel format of the resource when mapped into client-side memory. +// Returns a default value when IsGpuMemoryBufferFormatSupported() returns false +// for a given format, as in this case the resource will not be mapped into +// client-side memory, and the returned value is not used. VIZ_RESOURCE_FORMAT_EXPORT gfx::BufferFormat BufferFormat( ResourceFormat format); VIZ_RESOURCE_FORMAT_EXPORT bool IsResourceFormatCompressed(
diff --git a/components/viz/common/yuv_readback_unittest.cc b/components/viz/common/yuv_readback_unittest.cc index acdb53c..85dd3499 100644 --- a/components/viz/common/yuv_readback_unittest.cc +++ b/components/viz/common/yuv_readback_unittest.cc
@@ -404,7 +404,7 @@ const gfx::Rect paste_rect(gfx::Point(xmargin, ymargin), gfx::Size(xsize, ysize)); - media::LetterboxYUV(output_frame.get(), paste_rect); + media::LetterboxVideoFrame(output_frame.get(), paste_rect); run_loop.Run(); if (flip) {
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc index 70e0f88..1b7f689a 100644 --- a/components/viz/service/display/direct_renderer.cc +++ b/components/viz/service/display/direct_renderer.cc
@@ -276,6 +276,7 @@ cc::OverlayCandidate output_surface_plane; output_surface_plane.display_rect = gfx::RectF(device_viewport_size.width(), device_viewport_size.height()); + output_surface_plane.resource_size_in_pixels = device_viewport_size; output_surface_plane.format = output_surface_->GetOverlayBufferFormat(); output_surface_plane.use_output_surface_for_resource = true; output_surface_plane.overlay_handled = true;
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc index 41bdac1c..c343c05 100644 --- a/components/viz/service/display/display.cc +++ b/components/viz/service/display/display.cc
@@ -271,7 +271,9 @@ } base::ElapsedTimer aggregate_timer; - CompositorFrame frame = aggregator_->Aggregate(current_surface_id_); + CompositorFrame frame = aggregator_->Aggregate( + current_surface_id_, scheduler_ ? scheduler_->current_frame_display_time() + : base::TimeTicks::Now()); UMA_HISTOGRAM_COUNTS_1M("Compositing.SurfaceAggregator.AggregateUs", aggregate_timer.Elapsed().InMicroseconds()); @@ -372,7 +374,7 @@ frame.metadata.latency_info.emplace_back(ui::SourceEventType::FRAME); frame.metadata.latency_info.back().AddLatencyNumberWithTimestamp( ui::LATENCY_BEGIN_FRAME_DISPLAY_COMPOSITOR_COMPONENT, 0, 0, - scheduler_->CurrentFrameTime(), 1); + scheduler_->current_frame_time(), 1); } DLOG_IF(WARNING, !presented_callbacks_.empty())
diff --git a/components/viz/service/display/display_scheduler.h b/components/viz/service/display/display_scheduler.h index d8af7a42..d3cfbb04 100644 --- a/components/viz/service/display/display_scheduler.h +++ b/components/viz/service/display/display_scheduler.h
@@ -50,9 +50,13 @@ void SetRootSurfaceResourcesLocked(bool locked); void ForceImmediateSwapIfPossible(); void SetNeedsOneBeginFrame(); - base::TimeTicks CurrentFrameTime() { + base::TimeTicks current_frame_time() const { return current_begin_frame_args_.frame_time; } + base::TimeTicks current_frame_display_time() const { + return current_begin_frame_args_.frame_time + + current_begin_frame_args_.interval; + } virtual void DisplayResized(); virtual void SetNewRootSurface(const SurfaceId& root_surface_id); virtual void ProcessSurfaceDamage(const SurfaceId& surface_id,
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc index f63b2f10..a262fad 100644 --- a/components/viz/service/display/surface_aggregator.cc +++ b/components/viz/service/display/surface_aggregator.cc
@@ -1050,7 +1050,7 @@ // The following call can cause one or more copy requests to be added to the // Surface. Therefore, no code before this point should have assumed // anything about the presence or absence of copy requests after this point. - surface->NotifyAggregatedDamage(damage_rect); + surface->NotifyAggregatedDamage(damage_rect, expected_display_time_); } // If any CopyOutputRequests were made at FrameSink level, make sure we grab @@ -1150,7 +1150,11 @@ } } -CompositorFrame SurfaceAggregator::Aggregate(const SurfaceId& surface_id) { +CompositorFrame SurfaceAggregator::Aggregate( + const SurfaceId& surface_id, + base::TimeTicks expected_display_time) { + DCHECK(!expected_display_time.is_null()); + uma_stats_.Reset(); Surface* surface = manager_->GetSurfaceForId(surface_id); @@ -1169,6 +1173,7 @@ CompositorFrame frame; dest_pass_list_ = &frame.render_pass_list; + expected_display_time_ = expected_display_time; valid_surfaces_.clear(); has_cached_render_passes_ = false; @@ -1208,6 +1213,7 @@ return {}; dest_pass_list_ = nullptr; + expected_display_time_ = base::TimeTicks(); ProcessAddedAndRemovedSurfaces(); contained_surfaces_.swap(previous_contained_surfaces_); contained_surfaces_.clear();
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h index 17beb2c..9ff6edbe 100644 --- a/components/viz/service/display/surface_aggregator.h +++ b/components/viz/service/display/surface_aggregator.h
@@ -40,7 +40,8 @@ bool aggregate_only_damaged); ~SurfaceAggregator(); - CompositorFrame Aggregate(const SurfaceId& surface_id); + CompositorFrame Aggregate(const SurfaceId& surface_id, + base::TimeTicks expected_display_time); void ReleaseResources(const SurfaceId& surface_id); const SurfaceIndexMap& previous_contained_surfaces() const { return previous_contained_surfaces_; @@ -244,6 +245,9 @@ // This is the pass list for the aggregated frame. RenderPassList* dest_pass_list_; + // The target display time for the aggregated frame. + base::TimeTicks expected_display_time_; + // This is the set of aggregated pass ids that are affected by filters that // move pixels. base::flat_set<RenderPassId> moved_pixel_passes_;
diff --git a/components/viz/service/display/surface_aggregator_perftest.cc b/components/viz/service/display/surface_aggregator_perftest.cc index 2cb18bf1..9ae9e88 100644 --- a/components/viz/service/display/surface_aggregator_perftest.cc +++ b/components/viz/service/display/surface_aggregator_perftest.cc
@@ -6,6 +6,7 @@ #include "cc/resources/display_resource_provider.h" #include "cc/test/fake_output_surface_client.h" #include "cc/test/fake_resource_provider.h" +#include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/quads/surface_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h" @@ -106,6 +107,8 @@ auto root_support = std::make_unique<CompositorFrameSinkSupport>( nullptr, &manager_, FrameSinkId(1, num_surfaces + 1), kIsRoot, kNeedsSyncPoints); + base::TimeTicks next_fake_display_time = + base::TimeTicks() + base::TimeDelta::FromSeconds(1); timer_.Reset(); do { auto pass = RenderPass::Create(); @@ -133,7 +136,9 @@ CompositorFrame aggregated = aggregator_->Aggregate( SurfaceId(FrameSinkId(1, num_surfaces + 1), - LocalSurfaceId(num_surfaces + 1, kArbitraryToken))); + LocalSurfaceId(num_surfaces + 1, kArbitraryToken)), + next_fake_display_time); + next_fake_display_time += BeginFrameArgs::DefaultInterval(); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired());
diff --git a/components/viz/service/display/surface_aggregator_pixeltest.cc b/components/viz/service/display/surface_aggregator_pixeltest.cc index 8b3bbbd..7b90734 100644 --- a/components/viz/service/display/surface_aggregator_pixeltest.cc +++ b/components/viz/service/display/surface_aggregator_pixeltest.cc
@@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/time/time.h" #include "build/build_config.h" #include "cc/test/pixel_comparator.h" #include "cc/test/pixel_test.h" +#include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/quads/render_pass.h" #include "components/viz/common/quads/solid_color_draw_quad.h" @@ -42,10 +44,18 @@ kNeedsSyncPoints)) {} ~SurfaceAggregatorPixelTest() override {} + base::TimeTicks GetNextDisplayTime() { + base::TimeTicks display_time = next_display_time_; + next_display_time_ += BeginFrameArgs::DefaultInterval(); + return display_time; + } + protected: FrameSinkManagerImpl manager_; ParentLocalSurfaceIdAllocator allocator_; std::unique_ptr<CompositorFrameSinkSupport> support_; + base::TimeTicks next_display_time_ = + base::TimeTicks() + base::TimeDelta::FromSeconds(1); }; SharedQuadState* CreateAndAppendTestSharedQuadState( @@ -89,7 +99,8 @@ SurfaceAggregator aggregator(manager_.surface_manager(), resource_provider_.get(), true); - CompositorFrame aggregated_frame = aggregator.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator.Aggregate(root_surface_id, GetNextDisplayTime()); bool discard_alpha = false; cc::ExactPixelComparator pixel_comparator(discard_alpha); @@ -161,7 +172,8 @@ SurfaceAggregator aggregator(manager_.surface_manager(), resource_provider_.get(), true); - CompositorFrame aggregated_frame = aggregator.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator.Aggregate(root_surface_id, GetNextDisplayTime()); bool discard_alpha = false; cc::ExactPixelComparator pixel_comparator(discard_alpha); @@ -287,7 +299,8 @@ SurfaceAggregator aggregator(manager_.surface_manager(), resource_provider_.get(), true); - CompositorFrame aggregated_frame = aggregator.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator.Aggregate(root_surface_id, GetNextDisplayTime()); bool discard_alpha = false; cc::ExactPixelComparator pixel_comparator(discard_alpha);
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc index 0ad33ed..768aa885 100644 --- a/components/viz/service/display/surface_aggregator_unittest.cc +++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -13,9 +13,11 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/strings/stringprintf.h" +#include "base/time/time.h" #include "cc/resources/display_resource_provider.h" #include "cc/test/fake_resource_provider.h" #include "cc/test/render_pass_test_utils.h" +#include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/quads/render_pass.h" #include "components/viz/common/quads/render_pass_draw_quad.h" @@ -77,9 +79,11 @@ weak_ptr_factory_.GetWeakPtr()); } - MOCK_METHOD2(OnAggregatedDamage, + MOCK_METHOD4(OnAggregatedDamage, void(const LocalSurfaceId& local_surface_id, - const gfx::Rect& damage_rect)); + const gfx::Size& frame_size_in_pixels, + const gfx::Rect& damage_rect, + base::TimeTicks expected_display_time)); private: base::WeakPtrFactory<MockAggregatedDamageCallback> weak_ptr_factory_; @@ -87,7 +91,22 @@ DISALLOW_COPY_AND_ASSIGN(MockAggregatedDamageCallback); }; -class SurfaceAggregatorTest : public testing::Test { +class DisplayTimeSource { + public: + base::TimeTicks next_display_time() const { return next_display_time_; } + + base::TimeTicks GetNextDisplayTimeAndIncrement() { + const base::TimeTicks display_time = next_display_time_; + next_display_time_ += BeginFrameArgs::DefaultInterval(); + return display_time; + } + + private: + base::TimeTicks next_display_time_ = + base::TimeTicks() + base::TimeDelta::FromSeconds(1); +}; + +class SurfaceAggregatorTest : public testing::Test, public DisplayTimeSource { public: explicit SurfaceAggregatorTest(bool use_damage_rect) : observer_(false), @@ -372,7 +391,8 @@ SurfaceId* surface_ids, size_t expected_surface_count) { CompositorFrame aggregated_frame = aggregator_.Aggregate( - SurfaceId(support_->frame_sink_id(), root_local_surface_id_)); + SurfaceId(support_->frame_sink_id(), root_local_surface_id_), + GetNextDisplayTimeAndIncrement()); TestPassesMatchExpectations(expected_passes, expected_pass_count, &aggregated_frame.render_pass_list); @@ -462,7 +482,8 @@ // Check that the AggregatedDamageCallback is called with the right arguments. EXPECT_CALL( aggregated_damage_callback, - OnAggregatedDamage(root_local_surface_id_, gfx::Rect(SurfaceSize()))); + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + gfx::Rect(SurfaceSize()), next_display_time())); AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids)); @@ -498,7 +519,8 @@ root_local_surface_id_, device_scale_factor); SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); auto& render_pass_list = aggregated_frame.render_pass_list; ASSERT_EQ(2u, render_pass_list.size()); @@ -542,7 +564,8 @@ root_local_surface_id_, device_scale_factor); SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); auto& render_pass_list = aggregated_frame.render_pass_list; EXPECT_EQ(2u, render_pass_list.size()); @@ -587,13 +610,15 @@ SurfaceId surface_id(support_->frame_sink_id(), root_local_surface_id_); CompositorFrame aggregated_frame; - aggregated_frame = aggregator_.Aggregate(surface_id); + aggregated_frame = + aggregator_.Aggregate(surface_id, GetNextDisplayTimeAndIncrement()); auto id0 = aggregated_frame.render_pass_list[0]->id; auto id1 = aggregated_frame.render_pass_list[1]->id; EXPECT_NE(id1, id0); // Aggregated RenderPass ids should remain the same between frames. - aggregated_frame = aggregator_.Aggregate(surface_id); + aggregated_frame = + aggregator_.Aggregate(surface_id, GetNextDisplayTimeAndIncrement()); EXPECT_EQ(id0, aggregated_frame.render_pass_list[0]->id); EXPECT_EQ(id1, aggregated_frame.render_pass_list[1]->id); @@ -604,7 +629,8 @@ root_local_surface_id_, device_scale_factor); // The RenderPass that still exists should keep the same ID. - aggregated_frame = aggregator_.Aggregate(surface_id); + aggregated_frame = + aggregator_.Aggregate(surface_id, GetNextDisplayTimeAndIncrement()); auto id2 = aggregated_frame.render_pass_list[0]->id; EXPECT_NE(id2, id1); EXPECT_NE(id2, id0); @@ -615,7 +641,8 @@ // |id1| didn't exist in the previous frame, so it should be // mapped to a new ID. - aggregated_frame = aggregator_.Aggregate(surface_id); + aggregated_frame = + aggregator_.Aggregate(surface_id, GetNextDisplayTimeAndIncrement()); auto id3 = aggregated_frame.render_pass_list[0]->id; EXPECT_NE(id3, id2); EXPECT_NE(id3, id1); @@ -736,16 +763,18 @@ SurfaceId ids[] = {root_surface_id, fallback_child_surface_id}; EXPECT_CALL(aggregated_damage_callback, - OnAggregatedDamage(fallback_child_local_surface_id, _)) + OnAggregatedDamage(fallback_child_local_surface_id, fallback_size, + gfx::Rect(fallback_size), next_display_time())) .Times(1); EXPECT_CALL(aggregated_damage_callback, - OnAggregatedDamage(primary_child_local_surface_id, _)) + OnAggregatedDamage(primary_child_local_surface_id, SurfaceSize(), + gfx::Rect(SurfaceSize()), next_display_time())) .Times(0); // The whole root surface should be damaged because this is the first // aggregation. - EXPECT_CALL( - aggregated_damage_callback, - OnAggregatedDamage(root_local_surface_id_, gfx::Rect(SurfaceSize()))) + EXPECT_CALL(aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + gfx::Rect(SurfaceSize()), next_display_time())) .Times(1); // The primary_surface will not be listed in previously contained surfaces. @@ -762,7 +791,8 @@ // The damage should be equal to whole size of the primary SurfaceDrawQuad. EXPECT_CALL(aggregated_damage_callback, - OnAggregatedDamage(root_local_surface_id_, surface_quad_rect)) + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + surface_quad_rect, next_display_time())) .Times(1); AggregateAndVerify(expected_passes1, arraysize(expected_passes1), ids, @@ -793,17 +823,21 @@ SurfaceId ids2[] = {root_surface_id, primary_child_surface_id}; - EXPECT_CALL(aggregated_damage_callback, - OnAggregatedDamage(primary_child_local_surface_id, _)) + EXPECT_CALL( + aggregated_damage_callback, + OnAggregatedDamage(primary_child_local_surface_id, primary_surface_size, + gfx::Rect(primary_surface_size), next_display_time())) .Times(1); EXPECT_CALL(aggregated_damage_callback, - OnAggregatedDamage(fallback_child_local_surface_id, _)) + OnAggregatedDamage(fallback_child_local_surface_id, fallback_size, + gfx::Rect(fallback_size), next_display_time())) .Times(0); // The damage of the root should be equal to the damage of the primary // surface. - EXPECT_CALL(aggregated_damage_callback, - OnAggregatedDamage(root_local_surface_id_, - gfx::Rect(primary_surface_size))) + EXPECT_CALL( + aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + gfx::Rect(primary_surface_size), next_display_time())) .Times(1); AggregateAndVerify(expected_passes2, arraysize(expected_passes2), ids2, @@ -854,9 +888,12 @@ SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes), root_local_surface_id_, 1.0f); - EXPECT_CALL(aggregated_damage_callback, - OnAggregatedDamage(root_local_surface_id_, _)); - CompositorFrame frame = aggregator_.Aggregate(root_surface_id); + EXPECT_CALL( + aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + gfx::Rect(SurfaceSize()), next_display_time())); + CompositorFrame frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback); EXPECT_EQ(1u, frame.render_pass_list.size()); @@ -919,9 +956,12 @@ SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes), root_local_surface_id_, 2.0f); - EXPECT_CALL(aggregated_damage_callback, - OnAggregatedDamage(root_local_surface_id_, _)); - CompositorFrame frame = aggregator_.Aggregate(root_surface_id); + EXPECT_CALL( + aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + gfx::Rect(SurfaceSize()), next_display_time())); + CompositorFrame frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback); @@ -985,9 +1025,12 @@ SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes), root_local_surface_id_, 0.5f); - EXPECT_CALL(aggregated_damage_callback, - OnAggregatedDamage(root_local_surface_id_, _)); - CompositorFrame frame = aggregator_.Aggregate(root_surface_id); + EXPECT_CALL( + aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + gfx::Rect(SurfaceSize()), next_display_time())); + CompositorFrame frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback); EXPECT_EQ(1u, frame.render_pass_list.size()); @@ -1075,7 +1118,8 @@ SurfaceId ids[] = {root_surface_id, primary_child_surface_id}; EXPECT_CALL(aggregated_damage_callback, - OnAggregatedDamage(root_local_surface_id_, gfx::Rect(root_size))); + OnAggregatedDamage(root_local_surface_id_, root_size, + gfx::Rect(root_size), next_display_time())); // The fallback will not be contained within the aggregated frame. AggregateAndVerify(expected_passes1, arraysize(expected_passes1), ids, @@ -1089,9 +1133,9 @@ primary_child_local_surface_id, device_scale_factor); // The size of the damage should be equal to the size of the primary surface. - EXPECT_CALL( - aggregated_damage_callback, - OnAggregatedDamage(root_local_surface_id_, gfx::Rect(primary_size))); + EXPECT_CALL(aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, root_size, + gfx::Rect(primary_size), next_display_time())); // Generate a new aggregated frame. AggregateAndVerify(expected_passes1, arraysize(expected_passes1), ids, @@ -1132,7 +1176,8 @@ root_local_surface_id_, device_scale_factor); SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); Quad expected_quads[] = { Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)), @@ -1201,7 +1246,8 @@ } SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); Quad expected_quads[] = { Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)), @@ -1305,7 +1351,8 @@ } SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); // First pass should come from surface that had a copy request but was not // referenced directly. The second pass comes from the root surface. @@ -1378,7 +1425,8 @@ root_local_surface_id_, device_scale_factor); SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -1671,7 +1719,8 @@ root_local_surface_id_, device_scale_factor); SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -1847,7 +1896,8 @@ device_scale_factor, support_.get()); SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -1978,7 +2028,8 @@ std::move(root_frame)); SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -2051,6 +2102,11 @@ // Tests that damage rects are aggregated correctly when surfaces change. TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { + // Add a callback for when the surface is damaged. + MockAggregatedDamageCallback aggregated_damage_callback; + support_->SetAggregatedDamageCallbackForTesting( + aggregated_damage_callback.GetCallback()); + auto parent_support = std::make_unique<CompositorFrameSinkSupport>( nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot, kNeedsSyncPoints); @@ -2112,16 +2168,20 @@ support_->SubmitCompositorFrame(root_local_surface_id_, std::move(root_frame)); + // Damage rect for first aggregation should contain entire root surface. The + // damage rect reported to the callback is actually 10 pixels taller because + // of the 10-pixel vertical translation of the first RenderPass. SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); - + EXPECT_CALL( + aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + gfx::Rect(0, 0, 100, 110), next_display_time())); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); + testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; - ASSERT_EQ(2u, aggregated_pass_list.size()); - - // Damage rect for first aggregation should contain entire root surface. - EXPECT_TRUE( - aggregated_pass_list[1]->damage_rect.Contains(gfx::Rect(SurfaceSize()))); + EXPECT_EQ(gfx::Rect(SurfaceSize()), aggregated_pass_list[1]->damage_rect); { CompositorFrame child_frame = MakeEmptyCompositorFrame(); @@ -2136,17 +2196,19 @@ child_support_->SubmitCompositorFrame(child_local_surface_id, std::move(child_frame)); + // Outer surface didn't change, so a transformed inner damage rect is + // expected. SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); - + const gfx::Rect expected_damage_rect(10, 20, 10, 10); + EXPECT_CALL(aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + expected_damage_rect, next_display_time())); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; - ASSERT_EQ(2u, aggregated_pass_list.size()); - - // Outer surface didn't change, so transformed inner damage rect should be - // used. - EXPECT_EQ(gfx::Rect(10, 20, 10, 10).ToString(), + EXPECT_EQ(expected_damage_rect.ToString(), aggregated_pass_list[1]->damage_rect.ToString()); } @@ -2177,30 +2239,31 @@ support_->SubmitCompositorFrame(root_local_surface_id_, std::move(root_frame)); - SurfaceId root_surface_id(support_->frame_sink_id(), - root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); - - const auto& aggregated_pass_list = aggregated_frame.render_pass_list; - - ASSERT_EQ(2u, aggregated_pass_list.size()); - // The root surface was enqueued without being aggregated once, so it should // be treated as completely damaged. - EXPECT_TRUE(aggregated_pass_list[1]->damage_rect.Contains( - gfx::Rect(SurfaceSize()))); + SurfaceId root_surface_id(support_->frame_sink_id(), + root_local_surface_id_); + EXPECT_CALL( + aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + gfx::Rect(SurfaceSize()), next_display_time())); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); + const auto& aggregated_pass_list = aggregated_frame.render_pass_list; + ASSERT_EQ(2u, aggregated_pass_list.size()); + EXPECT_EQ(gfx::Rect(SurfaceSize()), aggregated_pass_list[1]->damage_rect); } // No Surface changed, so no damage should be given. { SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); - + EXPECT_CALL(aggregated_damage_callback, OnAggregatedDamage(_, _, _, _)) + .Times(0); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; - ASSERT_EQ(2u, aggregated_pass_list.size()); - EXPECT_TRUE(aggregated_pass_list[1]->damage_rect.IsEmpty()); } @@ -2208,12 +2271,14 @@ // marked as damaged. { aggregator_.SetFullDamageForSurface(root_surface_id); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); - + EXPECT_CALL( + aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + gfx::Rect(SurfaceSize()), next_display_time())); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; - ASSERT_EQ(2u, aggregated_pass_list.size()); - EXPECT_TRUE(aggregated_pass_list[1]->damage_rect.Contains( gfx::Rect(SurfaceSize()))); } @@ -2222,6 +2287,11 @@ // Tests that damage rects are aggregated correctly when surfaces stretch to // fit and device size is less than 1. TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRectWithSquashToFit) { + // Add a callback for when the surface is damaged. + MockAggregatedDamageCallback aggregated_damage_callback; + support_->SetAggregatedDamageCallbackForTesting( + aggregated_damage_callback.GetCallback()); + auto parent_support = std::make_unique<CompositorFrameSinkSupport>( nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot, kNeedsSyncPoints); @@ -2271,28 +2341,22 @@ Pass(root_render_pass_quads, arraysize(root_render_pass_quads), 2, SurfaceSize())}; - CompositorFrame root_frame = MakeEmptyCompositorFrame(); - AddPasses(&root_frame.render_pass_list, root_passes, arraysize(root_passes)); - - root_frame.render_pass_list[0] - ->shared_quad_state_list.front() - ->quad_to_target_transform.Translate(0, 10); - root_frame.render_pass_list[0]->damage_rect = gfx::Rect(5, 5, 10, 10); - root_frame.render_pass_list[1]->damage_rect = gfx::Rect(5, 5, 100, 100); - SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes), root_local_surface_id_, 1.0f); + // Damage rect for first aggregation should be exactly the entire root + // surface. SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); - + EXPECT_CALL( + aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + gfx::Rect(SurfaceSize()), next_display_time())); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); + testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; - ASSERT_EQ(2u, aggregated_pass_list.size()); - - // Damage rect for first aggregation should contain entire root surface. - EXPECT_TRUE( - aggregated_pass_list[1]->damage_rect.Contains(gfx::Rect(SurfaceSize()))); + EXPECT_EQ(gfx::Rect(SurfaceSize()), aggregated_pass_list[1]->damage_rect); { CompositorFrame child_frame = MakeEmptyCompositorFrame(); @@ -2305,19 +2369,21 @@ child_support_->SubmitCompositorFrame(child_local_surface_id, std::move(child_frame)); - SurfaceId root_surface_id(support_->frame_sink_id(), - root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); - - const auto& aggregated_pass_list = aggregated_frame.render_pass_list; - - ASSERT_EQ(2u, aggregated_pass_list.size()); - // Outer surface didn't change, so transformed inner damage rect should be // used. Since the child surface is stretching to fit the outer surface // which is half the size, we end up with a damage rect that is half the // size of the child surface. - EXPECT_EQ(gfx::Rect(5, 10, 10, 15).ToString(), + SurfaceId root_surface_id(support_->frame_sink_id(), + root_local_surface_id_); + const gfx::Rect expected_damage_rect(5, 10, 10, 15); + EXPECT_CALL(aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + expected_damage_rect, next_display_time())); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); + const auto& aggregated_pass_list = aggregated_frame.render_pass_list; + ASSERT_EQ(2u, aggregated_pass_list.size()); + EXPECT_EQ(expected_damage_rect.ToString(), aggregated_pass_list[1]->damage_rect.ToString()); } } @@ -2325,6 +2391,11 @@ // Tests that damage rects are aggregated correctly when surfaces stretch to // fit and device size is greater than 1. TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRectWithStretchToFit) { + // Add a callback for when the surface is damaged. + MockAggregatedDamageCallback aggregated_damage_callback; + support_->SetAggregatedDamageCallbackForTesting( + aggregated_damage_callback.GetCallback()); + auto parent_support = std::make_unique<CompositorFrameSinkSupport>( nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot, kNeedsSyncPoints); @@ -2374,28 +2445,23 @@ Pass(root_render_pass_quads, arraysize(root_render_pass_quads), 2, SurfaceSize())}; - CompositorFrame root_frame = MakeEmptyCompositorFrame(); - AddPasses(&root_frame.render_pass_list, root_passes, arraysize(root_passes)); - - root_frame.render_pass_list[0] - ->shared_quad_state_list.front() - ->quad_to_target_transform.Translate(0, 10); - root_frame.render_pass_list[0]->damage_rect = gfx::Rect(5, 5, 10, 10); - root_frame.render_pass_list[1]->damage_rect = gfx::Rect(5, 5, 100, 100); - SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes), root_local_surface_id_, 1.0f); + // Damage rect for first aggregation should contain entire root surface. The + // damage rect reported to the callback is actually 200x200, larger than the + // root surface size, because the root's Quad is 200x200. SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); - + EXPECT_CALL( + aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + gfx::Rect(0, 0, 200, 200), next_display_time())); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); + testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; - ASSERT_EQ(2u, aggregated_pass_list.size()); - - // Damage rect for first aggregation should contain entire root surface. - EXPECT_TRUE( - aggregated_pass_list[1]->damage_rect.Contains(gfx::Rect(SurfaceSize()))); + EXPECT_EQ(gfx::Rect(SurfaceSize()), aggregated_pass_list[1]->damage_rect); { CompositorFrame child_frame = MakeEmptyCompositorFrame(); @@ -2408,19 +2474,21 @@ child_support_->SubmitCompositorFrame(child_local_surface_id, std::move(child_frame)); - SurfaceId root_surface_id(support_->frame_sink_id(), - root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); - - const auto& aggregated_pass_list = aggregated_frame.render_pass_list; - - ASSERT_EQ(2u, aggregated_pass_list.size()); - // Outer surface didn't change, so transformed inner damage rect should be // used. Since the child surface is stretching to fit the outer surface // which is twice the size, we end up with a damage rect that is double the // size of the child surface. - EXPECT_EQ(gfx::Rect(20, 30, 40, 60).ToString(), + SurfaceId root_surface_id(support_->frame_sink_id(), + root_local_surface_id_); + const gfx::Rect expected_damage_rect(20, 30, 40, 60); + EXPECT_CALL(aggregated_damage_callback, + OnAggregatedDamage(root_local_surface_id_, SurfaceSize(), + expected_damage_rect, next_display_time())); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); + const auto& aggregated_pass_list = aggregated_frame.render_pass_list; + ASSERT_EQ(2u, aggregated_pass_list.size()); + EXPECT_EQ(expected_damage_rect.ToString(), aggregated_pass_list[1]->damage_rect.ToString()); } } @@ -2444,7 +2512,8 @@ { SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -2475,8 +2544,8 @@ std::move(root_frame)); } { - CompositorFrame aggregated_frame = - aggregator_.Aggregate(second_root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + second_root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -2485,8 +2554,8 @@ EXPECT_EQ(gfx::Rect(1, 2, 3, 4), aggregated_pass_list[0]->damage_rect); } { - CompositorFrame aggregated_frame = - aggregator_.Aggregate(second_root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + second_root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -2572,7 +2641,8 @@ } SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -2605,7 +2675,8 @@ } { - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -2654,7 +2725,8 @@ } { - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -2674,7 +2746,8 @@ } { - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; // There were no changes since last aggregation, so output should be empty @@ -2714,7 +2787,8 @@ } { - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -2763,7 +2837,8 @@ } { - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; ASSERT_EQ(3u, aggregated_pass_list.size()); @@ -2813,7 +2888,8 @@ } { - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -2833,7 +2909,8 @@ } } -class SurfaceAggregatorWithResourcesTest : public testing::Test { +class SurfaceAggregatorWithResourcesTest : public testing::Test, + public DisplayTimeSource { public: void SetUp() override { shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>(); @@ -2910,7 +2987,8 @@ SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(), support.get(), surface_id); - CompositorFrame frame = aggregator_->Aggregate(surface_id); + CompositorFrame frame = + aggregator_->Aggregate(surface_id, GetNextDisplayTimeAndIncrement()); // Nothing should be available to be returned yet. EXPECT_TRUE(client.returned_resources().empty()); @@ -2918,7 +2996,7 @@ SubmitCompositorFrameWithResources(nullptr, 0u, true, SurfaceId(), support.get(), surface_id); - frame = aggregator_->Aggregate(surface_id); + frame = aggregator_->Aggregate(surface_id, GetNextDisplayTimeAndIncrement()); ASSERT_EQ(3u, client.returned_resources().size()); ResourceId returned_ids[3]; @@ -2946,7 +3024,8 @@ SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(), support.get(), surface_id1); - CompositorFrame frame = aggregator_->Aggregate(surface_id1); + CompositorFrame frame = + aggregator_->Aggregate(surface_id1, GetNextDisplayTimeAndIncrement()); // Nothing should be available to be returned yet. EXPECT_TRUE(client.returned_resources().empty()); @@ -2957,7 +3036,7 @@ support.get(), surface_id2); manager_.surface_manager()->GarbageCollectSurfaces(); - frame = aggregator_->Aggregate(surface_id2); + frame = aggregator_->Aggregate(surface_id2, GetNextDisplayTimeAndIncrement()); ASSERT_EQ(3u, client.returned_resources().size()); ResourceId returned_ids[3]; @@ -2988,7 +3067,8 @@ .Build(); support->SubmitCompositorFrame(local_surface_id, std::move(frame)); - CompositorFrame returned_frame = aggregator_->Aggregate(surface_id); + CompositorFrame returned_frame = + aggregator_->Aggregate(surface_id, GetNextDisplayTimeAndIncrement()); // Nothing should be available to be returned yet. EXPECT_TRUE(client.returned_resources().empty()); @@ -3018,7 +3098,8 @@ SubmitCompositorFrameWithResources(ids2, arraysize(ids2), true, SurfaceId(), support2.get(), surface2_id); - CompositorFrame frame = aggregator_->Aggregate(surface1_id); + CompositorFrame frame = + aggregator_->Aggregate(surface1_id, GetNextDisplayTimeAndIncrement()); SubmitCompositorFrameWithResources(nullptr, 0, true, SurfaceId(), support1.get(), surface1_id); @@ -3026,7 +3107,7 @@ // Nothing should be available to be returned yet. EXPECT_TRUE(client.returned_resources().empty()); - frame = aggregator_->Aggregate(surface2_id); + frame = aggregator_->Aggregate(surface2_id, GetNextDisplayTimeAndIncrement()); // surface1_id wasn't referenced, so its resources should be returned. ASSERT_EQ(3u, client.returned_resources().size()); @@ -3076,7 +3157,8 @@ root_surface_id); CompositorFrame frame; - frame = aggregator_->Aggregate(root_surface_id); + frame = + aggregator_->Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); auto* pass_list = &frame.render_pass_list; ASSERT_EQ(1u, pass_list->size()); @@ -3086,7 +3168,8 @@ child_surface_id, middle_support.get(), middle_surface_id); - frame = aggregator_->Aggregate(root_surface_id); + frame = + aggregator_->Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); pass_list = &frame.render_pass_list; ASSERT_EQ(1u, pass_list->size()); @@ -3110,7 +3193,8 @@ SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(), support1.get(), surface1_id); - CompositorFrame frame = aggregator_->Aggregate(surface1_id); + CompositorFrame frame = + aggregator_->Aggregate(surface1_id, GetNextDisplayTimeAndIncrement()); auto* render_pass = frame.render_pass_list.back().get(); @@ -3133,14 +3217,14 @@ support2->SubmitCompositorFrame(local_frame2_id, std::move(frame)); } - frame = aggregator_->Aggregate(surface2_id); + frame = aggregator_->Aggregate(surface2_id, GetNextDisplayTimeAndIncrement()); EXPECT_EQ(1u, frame.render_pass_list.size()); render_pass = frame.render_pass_list.front().get(); // Parent has copy request, so texture should not be drawn. EXPECT_EQ(DrawQuad::SOLID_COLOR, render_pass->quad_list.back()->material); - frame = aggregator_->Aggregate(surface2_id); + frame = aggregator_->Aggregate(surface2_id, GetNextDisplayTimeAndIncrement()); EXPECT_EQ(1u, frame.render_pass_list.size()); render_pass = frame.render_pass_list.front().get(); @@ -3150,7 +3234,7 @@ aggregator_->set_output_is_secure(false); - frame = aggregator_->Aggregate(surface2_id); + frame = aggregator_->Aggregate(surface2_id, GetNextDisplayTimeAndIncrement()); render_pass = frame.render_pass_list.back().get(); // Output is insecure, so texture should be drawn. @@ -3177,19 +3261,22 @@ CompositorFrame aggregated_frame; aggregator_.SetOutputColorSpace(color_space1, color_space1); - aggregated_frame = aggregator_.Aggregate(surface_id); + aggregated_frame = + aggregator_.Aggregate(surface_id, GetNextDisplayTimeAndIncrement()); EXPECT_EQ(2u, aggregated_frame.render_pass_list.size()); EXPECT_EQ(color_space1, aggregated_frame.render_pass_list[0]->color_space); EXPECT_EQ(color_space1, aggregated_frame.render_pass_list[1]->color_space); aggregator_.SetOutputColorSpace(color_space2, color_space2); - aggregated_frame = aggregator_.Aggregate(surface_id); + aggregated_frame = + aggregator_.Aggregate(surface_id, GetNextDisplayTimeAndIncrement()); EXPECT_EQ(2u, aggregated_frame.render_pass_list.size()); EXPECT_EQ(color_space2, aggregated_frame.render_pass_list[0]->color_space); EXPECT_EQ(color_space2, aggregated_frame.render_pass_list[1]->color_space); aggregator_.SetOutputColorSpace(color_space1, color_space3); - aggregated_frame = aggregator_.Aggregate(surface_id); + aggregated_frame = + aggregator_.Aggregate(surface_id, GetNextDisplayTimeAndIncrement()); EXPECT_EQ(3u, aggregated_frame.render_pass_list.size()); EXPECT_EQ(color_space1, aggregated_frame.render_pass_list[0]->color_space); EXPECT_EQ(color_space1, aggregated_frame.render_pass_list[1]->color_space); @@ -3228,11 +3315,13 @@ // On first frame there is no existing cache texture to worry about re-using, // so we don't worry what this bool is set to. - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); // No Surface changed, so no damage should be given. { - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); EXPECT_FALSE(aggregated_frame.render_pass_list[0] ->has_damage_from_contributing_content); } @@ -3245,7 +3334,8 @@ child_support_->SubmitCompositorFrame(child_local_surface_id, std::move(child_surface_frame)); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); // True for new child_frame with damage. EXPECT_TRUE(aggregated_frame.render_pass_list[0] ->has_damage_from_contributing_content); @@ -3260,7 +3350,8 @@ child_support_->SubmitCompositorFrame(child_local_surface_id, std::move(child_surface_frame)); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); // False for new child_frame without damage. EXPECT_FALSE(aggregated_frame.render_pass_list[0] ->has_damage_from_contributing_content); @@ -3304,11 +3395,13 @@ // On first frame there is no existing cache texture to worry about re-using, // so we don't worry what this bool is set to. - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); // No Surface changed, so no damage should be given. { - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); EXPECT_FALSE(aggregated_frame.render_pass_list[0] ->has_damage_from_contributing_content); } @@ -3341,7 +3434,8 @@ child_support_->SubmitCompositorFrame(child_local_surface_id, std::move(child_surface_frame)); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); // True for new grand_child_frame. EXPECT_TRUE(aggregated_frame.render_pass_list[0] ->has_damage_from_contributing_content); @@ -3349,7 +3443,8 @@ // No Surface changed, so no damage should be given. { - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); EXPECT_FALSE(aggregated_frame.render_pass_list[0] ->has_damage_from_contributing_content); } @@ -3362,7 +3457,8 @@ grand_child_support->SubmitCompositorFrame(grand_child_local_surface_id, std::move(grand_child_frame)); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); // True for new grand_child_frame with damage. EXPECT_TRUE(aggregated_frame.render_pass_list[0] ->has_damage_from_contributing_content); @@ -3377,7 +3473,8 @@ grand_child_support->SubmitCompositorFrame(grand_child_local_surface_id, std::move(grand_child_frame)); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); // False for new grand_child_frame without damage. EXPECT_FALSE(aggregated_frame.render_pass_list[0] ->has_damage_from_contributing_content); @@ -3418,7 +3515,8 @@ std::move(root_frame)); SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); // On first frame there is no existing cache texture to worry about re-using, // so we don't worry what this bool is set to. @@ -3428,7 +3526,8 @@ // No Surface changed, so no damage should be given. { - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); EXPECT_FALSE(aggregated_frame.render_pass_list[0] ->has_damage_from_contributing_content); EXPECT_FALSE(aggregated_frame.render_pass_list[1] @@ -3443,7 +3542,8 @@ child_support_->SubmitCompositorFrame(child_local_surface_id, std::move(child_frame)); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); // True for new child_frame. EXPECT_TRUE(aggregated_frame.render_pass_list[0] ->has_damage_from_contributing_content); @@ -3471,7 +3571,8 @@ std::move(root_frame)); SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -3502,7 +3603,8 @@ support_->SubmitCompositorFrame(root_local_surface_id_, std::move(root_frame)); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; // Only the visible area is damaged. @@ -3529,7 +3631,8 @@ support_->SubmitCompositorFrame(root_local_surface_id_, std::move(root_frame)); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; // Should have full damage. @@ -3576,7 +3679,8 @@ std::move(root_frame)); SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -3607,7 +3711,8 @@ child_support_->SubmitCompositorFrame(child_local_surface_id, std::move(child_frame)); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; // Only the visible area is damaged. @@ -3634,7 +3739,8 @@ child_support_->SubmitCompositorFrame(child_local_surface_id, std::move(child_frame)); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; // Should have full damage. @@ -3707,7 +3813,8 @@ } SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_); - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = + aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; @@ -3745,7 +3852,8 @@ } { - CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id); + CompositorFrame aggregated_frame = aggregator_.Aggregate( + root_surface_id, GetNextDisplayTimeAndIncrement()); const auto& aggregated_pass_list = aggregated_frame.render_pass_list; ASSERT_EQ(3u, aggregated_pass_list.size());
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc index d96429b6..d3c3f5a 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -426,8 +426,6 @@ last_begin_frame_args_ = args; if (client_) client_->OnBeginFrame(args); - for (CapturableFrameSink::Client* capture_client : capture_clients_) - capture_client->OnBeginFrame(args); } const BeginFrameArgs& CompositorFrameSinkSupport::LastUsedBeginFrameArgs() @@ -525,17 +523,20 @@ void CompositorFrameSinkSupport::OnAggregatedDamage( const LocalSurfaceId& local_surface_id, + const gfx::Size& frame_size_in_pixels, const gfx::Rect& damage_rect, - const CompositorFrame& frame) const { + base::TimeTicks expected_display_time) const { DCHECK(!damage_rect.IsEmpty()); - if (aggregated_damage_callback_) - aggregated_damage_callback_.Run(local_surface_id, damage_rect); + if (aggregated_damage_callback_) { + aggregated_damage_callback_.Run(local_surface_id, frame_size_in_pixels, + damage_rect, expected_display_time); + } - const BeginFrameAck& ack = frame.metadata.begin_frame_ack; - const gfx::Size& frame_size = frame.size_in_pixels(); - for (CapturableFrameSink::Client* client : capture_clients_) - client->OnFrameDamaged(ack, frame_size, damage_rect); + for (CapturableFrameSink::Client* client : capture_clients_) { + client->OnFrameDamaged(frame_size_in_pixels, damage_rect, + expected_display_time); + } } } // namespace viz
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h index 6e179c3..d1612f6 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/compiler_specific.h" #include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/surfaces/surface_info.h" @@ -46,7 +47,9 @@ using AggregatedDamageCallback = base::RepeatingCallback<void(const LocalSurfaceId& local_surface_id, - const gfx::Rect& damage_rect)>; + const gfx::Size& frame_size_in_pixels, + const gfx::Rect& damage_rect, + base::TimeTicks expected_display_time)>; static const uint64_t kFrameIndexStart = 2; @@ -175,8 +178,9 @@ Surface* CreateSurface(const SurfaceInfo& surface_info); void OnAggregatedDamage(const LocalSurfaceId& local_surface_id, + const gfx::Size& frame_size_in_pixels, const gfx::Rect& damage_rect, - const CompositorFrame& frame) const; + base::TimeTicks expected_display_time) const; mojom::CompositorFrameSinkClient* const client_;
diff --git a/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h b/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h index 986efed..806133f8 100644 --- a/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h +++ b/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h
@@ -7,6 +7,7 @@ #include <memory> +#include "base/time/time.h" #include "ui/gfx/geometry/size.h" namespace gfx { @@ -15,8 +16,6 @@ namespace viz { -struct BeginFrameAck; -struct BeginFrameArgs; class CopyOutputRequest; // Interface for CompositorFrameSink implementations that support frame sink @@ -29,16 +28,15 @@ public: virtual ~Client() = default; - // Called to indicate compositing has started for a new frame. - virtual void OnBeginFrame(const BeginFrameArgs& args) = 0; - - // Called to indicate a frame's content has changed since the last - // frame. |ack| identifies the frame. |frame_size| is the output size of the - // frame, with |damage_rect| being the region within the frame that has - // changed. - virtual void OnFrameDamaged(const BeginFrameAck& ack, - const gfx::Size& frame_size, - const gfx::Rect& damage_rect) = 0; + // Called when a frame's content, or that of one or more of its child + // frames, has changed. |frame_size| is the output size of the currently- + // active compositor frame for the frame sink being monitored, with + // |damage_rect| being the region within that has changed (never empty). + // |expected_display_time| indicates when the content change was expected to + // appear on the Display. + virtual void OnFrameDamaged(const gfx::Size& frame_size, + const gfx::Rect& damage_rect, + base::TimeTicks expected_display_time) = 0; }; virtual ~CapturableFrameSink() = default;
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc index 0ee7870..1aaac05b 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -36,18 +36,6 @@ std::numeric_limits<int>::max(), std::numeric_limits<int>::max()); -// Returns |raw_size| truncated to positive even-numbered values. -gfx::Size AdjustSizeForI420(const gfx::Size& raw_size) { - gfx::Size result(raw_size.width() & ~1, raw_size.height() & ~1); - if (result.width() <= 0) { - result.set_width(2); - } - if (result.height() <= 0) { - result.set_height(2); - } - return result; -} - } // namespace // static @@ -57,10 +45,6 @@ // static constexpr media::ColorSpace FrameSinkVideoCapturerImpl::kDefaultColorSpace; -// static -constexpr base::TimeDelta - FrameSinkVideoCapturerImpl::kDisplayTimeCacheKeepAliveInterval; - FrameSinkVideoCapturerImpl::FrameSinkVideoCapturerImpl( FrameSinkVideoCapturerManager* frame_sink_manager, mojom::FrameSinkVideoCapturerRequest request) @@ -132,8 +116,9 @@ bool format_changed = false; - if (format != media::PIXEL_FORMAT_I420) { - LOG(DFATAL) << "Invalid pixel format: Only I420 supported."; + if (format != media::PIXEL_FORMAT_I420 && + format != media::PIXEL_FORMAT_ARGB) { + LOG(DFATAL) << "Invalid pixel format: Only I420 and ARGB are supported."; } else { format_changed |= (pixel_format_ != format); pixel_format_ = format; @@ -328,64 +313,16 @@ gfx::Rect(oracle_.source_size()), clock_->NowTicks()); } -void FrameSinkVideoCapturerImpl::OnBeginFrame(const BeginFrameArgs& args) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(args.IsValid()); - DCHECK(resolved_target_); - - // Note: It's possible that there are multiple BeginFrameSources that may call - // this method. It's not possible to know which one will be associated with a - // later OnFrameDamaged() call, so all recent timestamps must be cached. - - const size_t prior_source_count = frame_display_times_.size(); - TimeRingBuffer& ring_buffer = frame_display_times_[args.source_id]; - const base::TimeTicks display_time = args.frame_time + args.interval; - DCHECK(!display_time.is_null()); - ring_buffer[args.sequence_number % ring_buffer.size()] = display_time; - - // Garbage-collect |frame_display_times_| entries that are no longer being - // actively updated. This only runs when this method is being called with an - // as-yet-unseen |args.source_id|. An entry is pruned only if all of its - // timestamps are older than a reasonable threshold. - if (frame_display_times_.size() != prior_source_count) { - const base::TimeTicks threshold = - display_time - kDisplayTimeCacheKeepAliveInterval; - using KeyValuePair = decltype(frame_display_times_)::value_type; - base::EraseIf(frame_display_times_, [&threshold](const KeyValuePair& p) { - const TimeRingBuffer& ring_buffer = p.second; - return std::all_of(ring_buffer.begin(), ring_buffer.end(), - [&threshold](base::TimeTicks t) { - return t.is_null() || t < threshold; - }); - }); - } -} - -void FrameSinkVideoCapturerImpl::OnFrameDamaged(const BeginFrameAck& ack, - const gfx::Size& frame_size, - const gfx::Rect& damage_rect) { +void FrameSinkVideoCapturerImpl::OnFrameDamaged( + const gfx::Size& frame_size, + const gfx::Rect& damage_rect, + base::TimeTicks expected_display_time) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!frame_size.IsEmpty()); DCHECK(!damage_rect.IsEmpty()); + DCHECK(!expected_display_time.is_null()); DCHECK(resolved_target_); - base::TimeTicks display_time; - const auto it = frame_display_times_.find(ack.source_id); - if (it != frame_display_times_.end()) { - const TimeRingBuffer& ring_buffer = it->second; - display_time = ring_buffer[ack.sequence_number % ring_buffer.size()]; - } - if (display_time.is_null()) { - // This can sometimes occur for the first few frames when capture starts, - // or whenever Surfaces are changed; but should not otherwise happen. If - // this is too frequent, the oracle will be making suboptimal decisions. - VLOG(1) - << "OnFrameDamaged() called without prior OnBeginFrame() for source_id=" - << ack.source_id << " and sequence_number=" << ack.sequence_number - << ". Using NOW as a substitute display time."; - display_time = clock_->NowTicks(); - } - if (frame_size == oracle_.source_size()) { dirty_rect_.Union(damage_rect); } else { @@ -394,7 +331,7 @@ } MaybeCaptureFrame(VideoCaptureOracle::kCompositorUpdate, damage_rect, - display_time); + expected_display_time); } void FrameSinkVideoCapturerImpl::MaybeCaptureFrame( @@ -433,20 +370,20 @@ // Reserve a buffer from the pool for the next frame. const OracleFrameNumber oracle_frame_number = oracle_.next_frame_number(); - const gfx::Size i420_capture_size = AdjustSizeForI420(oracle_.capture_size()); + const gfx::Size capture_size = + AdjustSizeForPixelFormat(oracle_.capture_size()); scoped_refptr<VideoFrame> frame; if (dirty_rect_.IsEmpty()) { - frame = - frame_pool_.ResurrectLastVideoFrame(pixel_format_, i420_capture_size); + frame = frame_pool_.ResurrectLastVideoFrame(pixel_format_, capture_size); // If the resurrection failed, promote to a full frame capture. if (!frame) { TRACE_EVENT_INSTANT0("gpu.capture", "ResurrectionFailed", TRACE_EVENT_SCOPE_THREAD); dirty_rect_ = kMaxRect; - frame = frame_pool_.ReserveVideoFrame(pixel_format_, i420_capture_size); + frame = frame_pool_.ReserveVideoFrame(pixel_format_, capture_size); } } else { - frame = frame_pool_.ReserveVideoFrame(pixel_format_, i420_capture_size); + frame = frame_pool_.ReserveVideoFrame(pixel_format_, capture_size); } // Compute the current in-flight utilization and attenuate it: The utilization @@ -507,12 +444,23 @@ const gfx::Size& source_size = oracle_.source_size(); DCHECK(!source_size.IsEmpty()); - const gfx::Rect content_rect = - media::ComputeLetterboxRegionForI420(frame->visible_rect(), source_size); + gfx::Rect content_rect; + if (pixel_format_ == media::PIXEL_FORMAT_I420) { + content_rect = media::ComputeLetterboxRegionForI420(frame->visible_rect(), + source_size); + } else { + DCHECK_EQ(media::PIXEL_FORMAT_ARGB, pixel_format_); + content_rect = + media::ComputeLetterboxRegion(frame->visible_rect(), source_size); + } // Extreme edge-case: If somehow the source size is so tiny that the content // region becomes empty, just deliver a frame filled with black. if (content_rect.IsEmpty()) { - media::FillYUV(frame.get(), 0x00, 0x80, 0x80); + if (pixel_format_ == media::PIXEL_FORMAT_I420) { + media::FillYUV(frame.get(), 0x00, 0x80, 0x80); + } else { + media::LetterboxVideoFrame(frame.get(), gfx::Rect()); + } dirty_rect_ = gfx::Rect(); DidCaptureFrame(frame_number, oracle_frame_number, std::move(frame), gfx::Rect()); @@ -528,7 +476,9 @@ // Request a copy of the next frame from the frame sink. std::unique_ptr<CopyOutputRequest> request(new CopyOutputRequest( - CopyOutputRequest::ResultFormat::I420_PLANES, + pixel_format_ == media::PIXEL_FORMAT_I420 + ? CopyOutputRequest::ResultFormat::I420_PLANES + : CopyOutputRequest::ResultFormat::RGBA_BITMAP, base::BindOnce(&FrameSinkVideoCapturerImpl::DidCopyFrame, capture_weak_factory_.GetWeakPtr(), frame_number, oracle_frame_number, std::move(frame), content_rect))); @@ -554,38 +504,61 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_GE(frame_number, next_delivery_frame_number_); DCHECK(frame); - DCHECK_EQ(content_rect.x() % 2, 0); - DCHECK_EQ(content_rect.y() % 2, 0); - DCHECK_EQ(content_rect.width() % 2, 0); - DCHECK_EQ(content_rect.height() % 2, 0); DCHECK(result); // Stop() should have canceled any outstanding copy requests. So, by reaching // this point, |consumer_| should be bound. DCHECK(consumer_); - // Populate the VideoFrame from the CopyOutputResult. - const int y_stride = frame->stride(VideoFrame::kYPlane); - uint8_t* const y = frame->visible_data(VideoFrame::kYPlane) + - content_rect.y() * y_stride + content_rect.x(); - const int u_stride = frame->stride(VideoFrame::kUPlane); - uint8_t* const u = frame->visible_data(VideoFrame::kUPlane) + - (content_rect.y() / 2) * u_stride + (content_rect.x() / 2); - const int v_stride = frame->stride(VideoFrame::kVPlane); - uint8_t* const v = frame->visible_data(VideoFrame::kVPlane) + - (content_rect.y() / 2) * v_stride + (content_rect.x() / 2); - if (result->ReadI420Planes(y, y_stride, u, u_stride, v, v_stride)) { - // The result may be smaller than what was requested, if unforeseen clamping - // to the source boundaries occurred by the executor of the - // CopyOutputRequest. However, the result should never contain more than - // what was requested. - DCHECK_LE(result->size().width(), content_rect.width()); - DCHECK_LE(result->size().height(), content_rect.height()); - media::LetterboxYUV( - frame.get(), - gfx::Rect(content_rect.origin(), AdjustSizeForI420(result->size()))); + if (pixel_format_ == media::PIXEL_FORMAT_I420) { + DCHECK_EQ(content_rect.x() % 2, 0); + DCHECK_EQ(content_rect.y() % 2, 0); + DCHECK_EQ(content_rect.width() % 2, 0); + DCHECK_EQ(content_rect.height() % 2, 0); + // Populate the VideoFrame from the CopyOutputResult. + const int y_stride = frame->stride(VideoFrame::kYPlane); + uint8_t* const y = frame->visible_data(VideoFrame::kYPlane) + + content_rect.y() * y_stride + content_rect.x(); + const int u_stride = frame->stride(VideoFrame::kUPlane); + uint8_t* const u = frame->visible_data(VideoFrame::kUPlane) + + (content_rect.y() / 2) * u_stride + + (content_rect.x() / 2); + const int v_stride = frame->stride(VideoFrame::kVPlane); + uint8_t* const v = frame->visible_data(VideoFrame::kVPlane) + + (content_rect.y() / 2) * v_stride + + (content_rect.x() / 2); + if (result->ReadI420Planes(y, y_stride, u, u_stride, v, v_stride)) { + // The result may be smaller than what was requested, if unforeseen + // clamping to the source boundaries occurred by the executor of the + // CopyOutputRequest. However, the result should never contain more than + // what was requested. + DCHECK_LE(result->size().width(), content_rect.width()); + DCHECK_LE(result->size().height(), content_rect.height()); + media::LetterboxVideoFrame( + frame.get(), gfx::Rect(content_rect.origin(), + AdjustSizeForPixelFormat(result->size()))); + } else { + frame = nullptr; + } } else { - frame = nullptr; + // TODO(samans): Avoid doing an extra copy by implementing a method similar + // to ReadI420Planes() that copies directly from GPU memory into shared + // memory. https://crbug.com/822264 + DCHECK_EQ(media::PIXEL_FORMAT_ARGB, pixel_format_); + const SkBitmap& bitmap = result->AsSkBitmap(); + if (bitmap.readyToDraw()) { + SkImageInfo image_info = SkImageInfo::MakeN32( + bitmap.width(), bitmap.height(), kPremul_SkAlphaType); + const int stride = frame->stride(VideoFrame::kARGBPlane); + uint8_t* const pixels = frame->visible_data(VideoFrame::kARGBPlane) + + content_rect.y() * stride + content_rect.x() * 4; + bitmap.readPixels(image_info, pixels, stride, 0, 0); + media::LetterboxVideoFrame( + frame.get(), gfx::Rect(content_rect.origin(), + AdjustSizeForPixelFormat(result->size()))); + } else { + frame = nullptr; + } } DidCaptureFrame(frame_number, oracle_frame_number, std::move(frame), @@ -697,6 +670,25 @@ update_rect, content_rect, std::move(callbacks)); } +gfx::Size FrameSinkVideoCapturerImpl::AdjustSizeForPixelFormat( + const gfx::Size& raw_size) { + if (pixel_format_ == media::PIXEL_FORMAT_ARGB) { + gfx::Size result(raw_size); + if (result.width() <= 0) + result.set_width(1); + if (result.height() <= 0) + result.set_height(1); + return result; + } + DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format_); + gfx::Size result(raw_size.width() & ~1, raw_size.height() & ~1); + if (result.width() <= 0) + result.set_width(2); + if (result.height() <= 0) + result.set_height(2); + return result; +} + FrameSinkVideoCapturerImpl::CapturedFrame::CapturedFrame( int64_t fn, OracleFrameNumber ofn,
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h index 7c6b42c..cc1e20d 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
@@ -7,10 +7,8 @@ #include <stdint.h> -#include <array> #include <queue> -#include "base/containers/flat_map.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" @@ -19,7 +17,6 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "base/unguessable_token.h" -#include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h" #include "components/viz/service/frame_sinks/video_capture/in_flight_frame_delivery.h" @@ -130,7 +127,6 @@ private: friend class FrameSinkVideoCapturerTest; - using BeginFrameSourceId = decltype(BeginFrameArgs::source_id); using OracleFrameNumber = decltype(std::declval<media::VideoCaptureOracle>().next_frame_number()); @@ -158,10 +154,9 @@ void RefreshSoon(); // CapturableFrameSink::Client implementation: - void OnBeginFrame(const BeginFrameArgs& args) final; - void OnFrameDamaged(const BeginFrameAck& ack, - const gfx::Size& frame_size, - const gfx::Rect& damage_rect) final; + void OnFrameDamaged(const gfx::Size& frame_size, + const gfx::Rect& damage_rect, + base::TimeTicks target_display_time) final; // Consults the VideoCaptureOracle to decide whether to capture a frame, // then ensures prerequisites are met before initiating the capture: that @@ -194,6 +189,10 @@ scoped_refptr<media::VideoFrame> frame, const gfx::Rect& content_rect); + // For ARGB format, ensures that every dimension of |size| is positive. For + // I420 format, ensures that every dimension is even and at least 2. + gfx::Size AdjustSizeForPixelFormat(const gfx::Size& size); + // Owner/Manager of this instance. FrameSinkVideoCapturerManager* const frame_sink_manager_; @@ -230,13 +229,6 @@ // cleared when Stop() is called. mojom::FrameSinkVideoConsumerPtr consumer_; - // A cache of recently-recorded future frame display times, according to the - // BeginFrameArgs passed to OnBeginFrame() calls. There is one TimeRingBuffer - // per BeginFrameSource. TimeRingBuffer is an array mapping - // BeginFrameArgs::sequence_number to the expected display time. - using TimeRingBuffer = std::array<base::TimeTicks, kDesignLimitMaxFrames>; - base::flat_map<BeginFrameSourceId, TimeRingBuffer> frame_display_times_; - // The portion of the source content that has changed, but has not yet been // captured. gfx::Rect dirty_rect_; @@ -293,11 +285,6 @@ // copy output requests. base::WeakPtrFactory<FrameSinkVideoCapturerImpl> capture_weak_factory_; - // Retain entries in |frame_display_times_| that contain timestamps newer than - // this long ago. - static constexpr base::TimeDelta kDisplayTimeCacheKeepAliveInterval = - base::TimeDelta::FromMilliseconds(500); - DISALLOW_COPY_AND_ASSIGN(FrameSinkVideoCapturerImpl); };
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc index 8c60845..27bd0aa5 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
@@ -324,28 +324,19 @@ PropagateMojoTasks(); } - void AdvanceClockToNextVsync() { + base::TimeTicks GetNextVsync() const { const auto now = task_runner_->NowTicks(); const auto num_vsyncs_elapsed = (now - start_time_) / kVsyncInterval; - const auto advance_to_time = - start_time_ + (num_vsyncs_elapsed + 1) * kVsyncInterval; - task_runner_->FastForwardBy(advance_to_time - now); + return start_time_ + (num_vsyncs_elapsed + 1) * kVsyncInterval; } - void NotifyBeginFrame(int source_id, int frame_number) { - BeginFrameArgs args; - args.interval = kVsyncInterval; - args.frame_time = task_runner_->NowTicks(); - args.sequence_number = BeginFrameArgs::kStartingFrameNumber + frame_number; - args.source_id = source_id; - capturer_.OnBeginFrame(args); + void AdvanceClockToNextVsync() { + task_runner_->FastForwardBy(GetNextVsync() - task_runner_->NowTicks()); } - void NotifyFrameDamaged(int source_id, int frame_number) { - BeginFrameAck ack; - ack.sequence_number = BeginFrameArgs::kStartingFrameNumber + frame_number; - ack.source_id = source_id; - capturer_.OnFrameDamaged(ack, kSourceSize, gfx::Rect(kSourceSize)); + void NotifyFrameDamaged() { + capturer_.OnFrameDamaged(kSourceSize, gfx::Rect(kSourceSize), + GetNextVsync()); } void NotifyTargetWentAway() { @@ -362,15 +353,6 @@ PropagateMojoTasks(); } - bool HasCacheEntryForSource(int source_id) { - return capturer_.frame_display_times_.find(source_id) != - capturer_.frame_display_times_.end(); - } - - static constexpr base::TimeDelta GetDisplayTimeCacheKeepAliveInterval() { - return FrameSinkVideoCapturerImpl::kDisplayTimeCacheKeepAliveInterval; - } - protected: scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; base::TimeTicks start_time_; @@ -513,12 +495,10 @@ ++i) { SCOPED_TRACE(testing::Message() << "frame #" << i); - // Move time forward to the next display vsync and notify the capturer that - // compositing of the frame has begun. + // Move time forward to the next display vsync. AdvanceClockToNextVsync(); const base::TimeTicks expected_reference_time = task_runner_->NowTicks() + kVsyncInterval; - NotifyBeginFrame(1, i); // Change the content of the frame sink and notify the capturer of the // damage. @@ -527,7 +507,7 @@ task_runner_->FastForwardBy(kVsyncInterval / 4); const base::TimeTicks expected_capture_begin_time = task_runner_->NowTicks(); - NotifyFrameDamaged(1, i); + NotifyFrameDamaged(); // The frame sink should have received a CopyOutputRequest. Simulate a short // pause before the result is sent back to the capturer, and the capturer @@ -602,8 +582,7 @@ int num_frames = FrameSinkVideoCapturerImpl::kDesignLimitMaxFrames; for (int i = num_refresh_frames; i < num_frames; ++i) { AdvanceClockToNextVsync(); - NotifyBeginFrame(1, i); - NotifyFrameDamaged(1, i); + NotifyFrameDamaged(); // The oracle should not be rejecting captures caused by compositor updates. ASSERT_FALSE(IsRefreshRetryTimerRunning()); } @@ -613,10 +592,8 @@ // requests to be issued at this point. However, the refresh timer should be // scheduled to account for the capture of changed content that could not take // place. - const int first_uncaptured_frame = num_frames; AdvanceClockToNextVsync(); - NotifyBeginFrame(1, first_uncaptured_frame); - NotifyFrameDamaged(1, first_uncaptured_frame); + NotifyFrameDamaged(); ASSERT_EQ(num_frames, frame_sink_.num_copy_results()); EXPECT_TRUE(IsRefreshRetryTimerRunning()); @@ -625,10 +602,8 @@ // frame is still in the middle of being delivered/consumed. frame_sink_.SendCopyOutputResult(0); ASSERT_EQ(1, consumer.num_frames_received()); - const int second_uncaptured_frame = num_frames; AdvanceClockToNextVsync(); - NotifyBeginFrame(1, second_uncaptured_frame); - NotifyFrameDamaged(1, second_uncaptured_frame); + NotifyFrameDamaged(); ASSERT_EQ(num_frames, frame_sink_.num_copy_results()); EXPECT_TRUE(IsRefreshRetryTimerRunning()); @@ -638,10 +613,8 @@ // capture will satisfy the need to send updated content to the consumer. EXPECT_TRUE(consumer.TakeFrame(0)); consumer.SendDoneNotification(0); - const int first_capture_resumed_frame = second_uncaptured_frame + 1; AdvanceClockToNextVsync(); - NotifyBeginFrame(1, first_capture_resumed_frame); - NotifyFrameDamaged(1, first_capture_resumed_frame); + NotifyFrameDamaged(); ++num_frames; ASSERT_EQ(num_frames, frame_sink_.num_copy_results()); EXPECT_FALSE(IsRefreshRetryTimerRunning()); @@ -649,10 +622,8 @@ // With yet another compositor update, no new copy requests should be issued // because the pipeline became saturated again. Once again, the refresh timer // should be started to account for the need to capture at some future point. - const int third_uncaptured_frame = first_capture_resumed_frame + 1; AdvanceClockToNextVsync(); - NotifyBeginFrame(1, third_uncaptured_frame); - NotifyFrameDamaged(1, third_uncaptured_frame); + NotifyFrameDamaged(); ASSERT_EQ(num_frames, frame_sink_.num_copy_results()); EXPECT_TRUE(IsRefreshRetryTimerRunning()); @@ -664,10 +635,8 @@ frame_sink_.SendCopyOutputResult(i); } ASSERT_EQ(frame_sink_.num_copy_results(), consumer.num_frames_received()); - const int fourth_uncaptured_frame = third_uncaptured_frame + 1; AdvanceClockToNextVsync(); - NotifyBeginFrame(1, fourth_uncaptured_frame); - NotifyFrameDamaged(1, fourth_uncaptured_frame); + NotifyFrameDamaged(); ASSERT_EQ(num_frames, frame_sink_.num_copy_results()); EXPECT_TRUE(IsRefreshRetryTimerRunning()); @@ -678,10 +647,8 @@ EXPECT_TRUE(consumer.TakeFrame(i)); consumer.SendDoneNotification(i); } - const int second_capture_resumed_frame = fourth_uncaptured_frame + 1; AdvanceClockToNextVsync(); - NotifyBeginFrame(1, second_capture_resumed_frame); - NotifyFrameDamaged(1, second_capture_resumed_frame); + NotifyFrameDamaged(); ++num_frames; ASSERT_EQ(num_frames, frame_sink_.num_copy_results()); frame_sink_.SendCopyOutputResult(frame_sink_.num_copy_results() - 1); @@ -717,8 +684,7 @@ static_cast<uint8_t>((i << 4) + 0x20)}); frame_sink_.SetCopyOutputColor(colors.back()); AdvanceClockToNextVsync(); - NotifyBeginFrame(1, i); - NotifyFrameDamaged(1, i); + NotifyFrameDamaged(); } ASSERT_EQ(num_frames, frame_sink_.num_copy_results()); @@ -771,8 +737,7 @@ for (int i = num_refresh_frames; i < num_copy_requests; ++i) { SCOPED_TRACE(testing::Message() << "frame #" << i); AdvanceClockToNextVsync(); - NotifyBeginFrame(1, i); - NotifyFrameDamaged(1, i); + NotifyFrameDamaged(); } ASSERT_EQ(num_copy_requests, frame_sink_.num_copy_results()); @@ -820,8 +785,7 @@ if (i == 0) { // Expect that advancing the clock caused the refresh timer to fire. } else { - NotifyBeginFrame(1, num_copy_requests); - NotifyFrameDamaged(1, num_copy_requests); + NotifyFrameDamaged(); } ++num_copy_requests; ASSERT_EQ(num_copy_requests, frame_sink_.num_copy_results()); @@ -866,8 +830,7 @@ int num_frames = 1 + num_update_frames; for (int i = 1; i < num_frames; ++i) { AdvanceClockToNextVsync(); - NotifyBeginFrame(1, i); - NotifyFrameDamaged(1, i); + NotifyFrameDamaged(); ASSERT_EQ(i + 1, frame_sink_.num_copy_results()); ASSERT_FALSE(IsRefreshRetryTimerRunning()); frame_sink_.SendCopyOutputResult(i); @@ -893,41 +856,4 @@ StopCapture(); } -// Tests that the capturer caches display times from OnBeginFrame() -// notifications and throws away old data. -TEST_F(FrameSinkVideoCapturerTest, CachesAndPrunesDisplayTimes) { - EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId)) - .WillRepeatedly(Return(&frame_sink_)); - capturer_.ChangeTarget(kFrameSinkId); - - // The first OnBeginFrame() call should create a cache entry for source_id=1. - NotifyBeginFrame(1, 1); - EXPECT_TRUE(HasCacheEntryForSource(1)); - - // The next OnBeginFrame() call should create a second cache entry, for - // source_id=2. - NotifyBeginFrame(2, 1); - EXPECT_TRUE(HasCacheEntryForSource(1)); - EXPECT_TRUE(HasCacheEntryForSource(2)); - - // Make a sequence of OnBeginFrame() calls for source_id=2. The cache entries - // for both sources should remain. - const base::TimeTicks end_time = - task_runner_->NowTicks() + GetDisplayTimeCacheKeepAliveInterval(); - int seq = 2; - while (task_runner_->NowTicks() < end_time) { - task_runner_->FastForwardBy(kVsyncInterval); - NotifyBeginFrame(2, seq++); - ASSERT_TRUE(HasCacheEntryForSource(1)); - ASSERT_TRUE(HasCacheEntryForSource(2)); - } - - // Now, if a third source is introduced, the garbage collection will run and - // prune out the entry for source_id=1 since it has not been actively updated. - NotifyBeginFrame(3, 1); - EXPECT_FALSE(HasCacheEntryForSource(1)); - EXPECT_TRUE(HasCacheEntryForSource(2)); - EXPECT_TRUE(HasCacheEntryForSource(3)); -} - } // namespace viz
diff --git a/components/viz/service/frame_sinks/video_detector_unittest.cc b/components/viz/service/frame_sinks/video_detector_unittest.cc index 52bc5ce..f3cfe50 100644 --- a/components/viz/service/frame_sinks/video_detector_unittest.cc +++ b/components/viz/service/frame_sinks/video_detector_unittest.cc
@@ -81,7 +81,9 @@ ~VideoDetectorTest() override {} void SetUp() override { - mock_task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); + mock_task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>( + base::Time() + base::TimeDelta::FromSeconds(1), + base::TimeTicks() + base::TimeDelta::FromSeconds(1)); detector_ = frame_sink_manager_.CreateVideoDetectorForTesting( mock_task_runner_->DeprecatedGetMockTickClock(), mock_task_runner_); @@ -112,8 +114,8 @@ } void CreateDisplayFrame() { - surface_aggregator_.Aggregate( - root_frame_sink_->last_activated_surface_id()); + surface_aggregator_.Aggregate(root_frame_sink_->last_activated_surface_id(), + mock_task_runner_->NowTicks()); } void EmbedClient(CompositorFrameSinkSupport* frame_sink) {
diff --git a/components/viz/service/surfaces/surface.cc b/components/viz/service/surfaces/surface.cc index 1cb5b95..d46aa31 100644 --- a/components/viz/service/surfaces/surface.cc +++ b/components/viz/service/surfaces/surface.cc
@@ -485,13 +485,16 @@ std::move(active_frame_data_->draw_callback).Run(); } -void Surface::NotifyAggregatedDamage(const gfx::Rect& damage_rect) { +void Surface::NotifyAggregatedDamage(const gfx::Rect& damage_rect, + base::TimeTicks expected_display_time) { if (!active_frame_data_ || active_frame_data_->aggregated_damage_callback.is_null()) return; active_frame_data_->aggregated_damage_callback.Run( - surface_id().local_surface_id(), damage_rect, active_frame_data_->frame); + surface_id().local_surface_id(), + active_frame_data_->frame.size_in_pixels(), damage_rect, + expected_display_time); } void Surface::OnDeadline(base::TimeDelta duration) {
diff --git a/components/viz/service/surfaces/surface.h b/components/viz/service/surfaces/surface.h index c742367..4d9a63a 100644 --- a/components/viz/service/surfaces/surface.h +++ b/components/viz/service/surfaces/surface.h
@@ -18,6 +18,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" +#include "base/time/time.h" #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/surfaces/frame_sink_id.h" @@ -71,8 +72,9 @@ public: using AggregatedDamageCallback = base::RepeatingCallback<void(const LocalSurfaceId& local_surface_id, + const gfx::Size& frame_size_in_pixels, const gfx::Rect& damage_rect, - const CompositorFrame& frame)>; + base::TimeTicks expected_display_time)>; using PresentedCallback = base::OnceCallback<void(base::TimeTicks, base::TimeDelta, uint32_t)>; @@ -175,7 +177,8 @@ void TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info); bool TakePresentedCallback(PresentedCallback* callback); void RunDrawCallback(); - void NotifyAggregatedDamage(const gfx::Rect& damage_rect); + void NotifyAggregatedDamage(const gfx::Rect& damage_rect, + base::TimeTicks expected_display_time); const std::vector<SurfaceId>* active_referenced_surfaces() const { return active_frame_data_
diff --git a/content/OWNERS b/content/OWNERS index 0b7cd02..53d2f57 100644 --- a/content/OWNERS +++ b/content/OWNERS
@@ -17,6 +17,10 @@ # structural changes, please get a review from a reviewer in this file. per-file BUILD.gn=* +# For threading (BrowserThread, BrowserMainLoop, TaskScheduler, etc.) +per-file *browser_main_loop*=gab@chromium.org +per-file *browser_thread*=gab@chromium.org + # Mac Sandbox profiles. per-file *.sb=set noparent per-file *.sb=rsesek@chromium.org
diff --git a/content/browser/background_fetch/OWNERS b/content/browser/background_fetch/OWNERS index 317a557..a7cd217 100644 --- a/content/browser/background_fetch/OWNERS +++ b/content/browser/background_fetch/OWNERS
@@ -1,9 +1,10 @@ # This OWNERS file also covers: # +# //chrome/browser/background_fetch/ # //content/common/background_fetch/ +awdf@chromium.org peter@chromium.org -johnme@chromium.org delphick@chromium.org # TEAM: platform-capabilities@chromium.org
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc index a4b7f54..a3f6524 100644 --- a/content/browser/download/download_browsertest.cc +++ b/content/browser/download/download_browsertest.cc
@@ -2873,6 +2873,33 @@ ASSERT_TRUE(server.ShutdownAndWaitUntilComplete()); } +// Test that the target attribute is ignored on anchors with a download +// attribute. +IN_PROC_BROWSER_TEST_F(DownloadContentTest, + DownloadAttributeIgnoresTargetAttribute) { + net::EmbeddedTestServer server; + ASSERT_TRUE(server.InitializeAndListen()); + + GURL url = server.GetURL(std::string("/download-attribute-with-target.html")); + server.ServeFilesFromDirectory(GetTestFilePath("download", "")); + server.StartAcceptingConnections(); + + NavigateToURLAndWaitForDownload(shell(), url, + download::DownloadItem::COMPLETE); + + std::vector<download::DownloadItem*> downloads; + DownloadManagerForShell(shell())->GetAllDownloads(&downloads); + ASSERT_EQ(1u, downloads.size()); + + // The target="_blank" should have been ignored, and so no additional window + // was created. + ASSERT_EQ(1u, Shell::windows().size()); + + EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"), + downloads[0]->GetTargetFilePath().BaseName().value()); + ASSERT_TRUE(server.ShutdownAndWaitUntilComplete()); +} + // A request for a non-existent resource should result in an aborted navigation, // and the old site staying current. IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeServerError) {
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc index 9f0687b..1e178877 100644 --- a/content/browser/download/download_manager_impl.cc +++ b/content/browser/download/download_manager_impl.cc
@@ -151,14 +151,16 @@ item.GetGuid(), download::DownloadSource::UNKNOWN, GetUniqueDownloadId()); } -DownloadManagerImpl::UniqueUrlDownloadHandlerPtr BeginDownload( - std::unique_ptr<download::DownloadUrlParameters> params, - std::unique_ptr<storage::BlobDataHandle> blob_data_handle, - content::ResourceContext* resource_context, - uint32_t download_id, - base::WeakPtr<DownloadManagerImpl> download_manager) { +void BeginDownload(std::unique_ptr<download::DownloadUrlParameters> params, + std::unique_ptr<storage::BlobDataHandle> blob_data_handle, + content::ResourceContext* resource_context, + uint32_t download_id, + base::WeakPtr<DownloadManagerImpl> download_manager) { DCHECK_CURRENTLY_ON(BrowserThread::IO); + download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader( + nullptr, base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get())); + params->set_blob_storage_context_getter( base::BindOnce(&BlobStorageContextGetter, resource_context)); std::unique_ptr<net::URLRequest> url_request = @@ -179,21 +181,23 @@ // If the download was accepted, the DownloadResourceHandler is now // responsible for driving the request to completion. - if (reason == download::DOWNLOAD_INTERRUPT_REASON_NONE) - return nullptr; - // Otherwise, create an interrupted download. - CreateInterruptedDownload(params.get(), reason, download_manager); - return nullptr; + if (reason != download::DOWNLOAD_INTERRUPT_REASON_NONE) + CreateInterruptedDownload(params.get(), reason, download_manager); + } else { + downloader.reset(UrlDownloader::BeginDownload(download_manager, + std::move(url_request), + params.get(), false) + .release()); } - - return DownloadManagerImpl::UniqueUrlDownloadHandlerPtr( - UrlDownloader::BeginDownload(download_manager, std::move(url_request), - params.get(), false) - .release()); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce( + &download::UrlDownloadHandler::Delegate::OnUrlDownloadHandlerCreated, + download_manager, std::move(downloader))); } -DownloadManagerImpl::UniqueUrlDownloadHandlerPtr BeginResourceDownload( +void BeginResourceDownload( std::unique_ptr<download::DownloadUrlParameters> params, std::unique_ptr<network::ResourceRequest> request, std::unique_ptr<storage::BlobDataHandle> blob_data_handle, @@ -206,6 +210,9 @@ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { DCHECK_CURRENTLY_ON(BrowserThread::IO); + download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader( + nullptr, base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get())); + // Check if the renderer is permitted to request the requested URL. if (params->render_process_host_id() >= 0 && !CanRequestURLFromRenderer(params->render_process_host_id(), @@ -214,30 +221,35 @@ params.get(), download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST, download_manager); - return nullptr; - } - - scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory; - if (params->url().SchemeIs(url::kBlobScheme)) { - network::mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info; - storage::BlobURLLoaderFactory::Create( - std::move(blob_data_handle), params->url(), - mojo::MakeRequest(&url_loader_factory_ptr_info)); - shared_url_loader_factory = - base::MakeRefCounted<WrapperSharedURLLoaderFactory>( - std::move(url_loader_factory_ptr_info)); } else { - shared_url_loader_factory = url_loader_factory_getter->GetNetworkFactory(); + scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory; + if (params->url().SchemeIs(url::kBlobScheme)) { + network::mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info; + storage::BlobURLLoaderFactory::Create( + std::move(blob_data_handle), params->url(), + mojo::MakeRequest(&url_loader_factory_ptr_info)); + shared_url_loader_factory = + base::MakeRefCounted<WrapperSharedURLLoaderFactory>( + std::move(url_loader_factory_ptr_info)); + } else { + shared_url_loader_factory = + url_loader_factory_getter->GetNetworkFactory(); + } + // TODO(qinmin): Check the storage permission before creating the URLLoader. + // This is already done for context menu download, but it is missing for + // download service and download resumption. + downloader.reset( + download::ResourceDownloader::BeginDownload( + download_manager, std::move(params), std::move(request), + std::move(shared_url_loader_factory), site_url, tab_url, + tab_referrer_url, download_id, false, task_runner) + .release()); } - // TODO(qinmin): Check the storage permission before creating the URLLoader. - // This is already done for context menu download, but it is missing for - // download service and download resumption. - return DownloadManagerImpl::UniqueUrlDownloadHandlerPtr( - download::ResourceDownloader::BeginDownload( - download_manager, std::move(params), std::move(request), - std::move(shared_url_loader_factory), site_url, tab_url, - tab_referrer_url, download_id, false, task_runner) - .release()); + task_runner->PostTask( + FROM_HERE, + base::BindOnce( + &download::UrlDownloadHandler::Delegate::OnUrlDownloadHandlerCreated, + download_manager, std::move(downloader))); } class DownloadItemFactoryImpl : public DownloadItemFactory { @@ -390,10 +402,13 @@ delegate_(nullptr), weak_factory_(this) { DCHECK(browser_context); + download::SetIOTaskRunner( + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); } DownloadManagerImpl::~DownloadManagerImpl() { DCHECK(!shutdown_needed_); + download::SetIOTaskRunner(nullptr); } DownloadItemImpl* DownloadManagerImpl::CreateActiveItem( @@ -816,8 +831,8 @@ downloads_.erase(download->GetId()); } -void DownloadManagerImpl::AddUrlDownloadHandler( - UniqueUrlDownloadHandlerPtr downloader) { +void DownloadManagerImpl::OnUrlDownloadHandlerCreated( + download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (downloader) url_download_handlers_.push_back(std::move(downloader)); @@ -1195,20 +1210,20 @@ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - std::unique_ptr<download::ResourceDownloader> resource_downloader = + download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr resource_downloader( download::ResourceDownloader::InterceptNavigationResponse( download_manager, std::move(resource_request), render_process_id, render_frame_id, site_url, tab_url, tab_referrer_url, std::move(url_chain), suggested_filename, std::move(response), std::move(cert_status), std::move(url_loader_client_endpoints), - task_runner); + task_runner) + .release(), + base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get())); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::BindOnce(&DownloadManagerImpl::AddUrlDownloadHandler, - download_manager, - DownloadManagerImpl::UniqueUrlDownloadHandlerPtr( - resource_downloader.release()))); + base::BindOnce(&DownloadManagerImpl::OnUrlDownloadHandlerCreated, + download_manager, std::move(resource_downloader))); } void DownloadManagerImpl::BeginDownloadInternal( @@ -1232,24 +1247,20 @@ } } - BrowserThread::PostTaskAndReplyWithResult( + BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::BindOnce(&BeginResourceDownload, std::move(params), std::move(request), std::move(blob_data_handle), storage_partition->url_loader_factory_getter(), id, weak_factory_.GetWeakPtr(), site_url, tab_url, tab_referrer_url, - base::MessageLoop::current()->task_runner()), - base::BindOnce(&DownloadManagerImpl::AddUrlDownloadHandler, - weak_factory_.GetWeakPtr())); + base::MessageLoop::current()->task_runner())); } else { - BrowserThread::PostTaskAndReplyWithResult( + BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::BindOnce(&BeginDownload, std::move(params), std::move(blob_data_handle), browser_context_->GetResourceContext(), id, - weak_factory_.GetWeakPtr()), - base::BindOnce(&DownloadManagerImpl::AddUrlDownloadHandler, weak_factory_.GetWeakPtr())); } }
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h index 313e9f3..93d915b 100644 --- a/content/browser/download/download_manager_impl.h +++ b/content/browser/download/download_manager_impl.h
@@ -48,9 +48,6 @@ private DownloadItemImplDelegate { public: using DownloadItemImplCreated = base::Callback<void(DownloadItemImpl*)>; - using UniqueUrlDownloadHandlerPtr = - std::unique_ptr<download::UrlDownloadHandler, - BrowserThread::DeleteOnIOThread>; // Caller guarantees that |net_log| will remain valid // for the lifetime of DownloadManagerImpl (until Shutdown() is called). @@ -136,6 +133,9 @@ const download::DownloadUrlParameters::OnStartedCallback& callback) override; void OnUrlDownloadStopped(download::UrlDownloadHandler* downloader) override; + void OnUrlDownloadHandlerCreated( + download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader) + override; // For testing; specifically, accessed from TestFileErrorInjector. void SetDownloadItemFactoryForTesting( @@ -230,8 +230,6 @@ void ShowDownloadInShell(DownloadItemImpl* download) override; void DownloadRemoved(DownloadItemImpl* download) override; - void AddUrlDownloadHandler(UniqueUrlDownloadHandlerPtr downloader); - // Helper method to start or resume a download. void BeginDownloadInternal( std::unique_ptr<download::DownloadUrlParameters> params, @@ -310,7 +308,8 @@ // Allows an embedder to control behavior. Guaranteed to outlive this object. DownloadManagerDelegate* delegate_; - std::vector<UniqueUrlDownloadHandlerPtr> url_download_handlers_; + std::vector<download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr> + url_download_handlers_; base::WeakPtrFactory<DownloadManagerImpl> weak_factory_;
diff --git a/content/browser/download/download_worker.cc b/content/browser/download/download_worker.cc index 37981901f..1bde3542 100644 --- a/content/browser/download/download_worker.cc +++ b/content/browser/download/download_worker.cc
@@ -7,6 +7,7 @@ #include "base/message_loop/message_loop.h" #include "components/download/public/common/download_create_info.h" #include "components/download/public/common/download_interrupt_reasons.h" +#include "components/download/public/common/download_task_runner.h" #include "components/download/public/common/input_stream.h" #include "components/download/public/common/resource_downloader.h" #include "content/browser/download/download_utils.h" @@ -43,24 +44,23 @@ DISALLOW_COPY_AND_ASSIGN(CompletedInputStream); }; -std::unique_ptr<download::UrlDownloadHandler, BrowserThread::DeleteOnIOThread> -CreateUrlDownloadHandler( +void CreateUrlDownloadHandler( std::unique_ptr<download::DownloadUrlParameters> params, base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate, scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter, const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader( + nullptr, base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get())); if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { std::unique_ptr<network::ResourceRequest> request = CreateResourceRequest(params.get()); - return std::unique_ptr<download::ResourceDownloader, - BrowserThread::DeleteOnIOThread>( - download::ResourceDownloader::BeginDownload( - delegate, std::move(params), std::move(request), - url_loader_factory_getter->GetNetworkFactory(), GURL(), GURL(), - GURL(), download::DownloadItem::kInvalidId, true, task_runner) - .release()); + downloader.reset(download::ResourceDownloader::BeginDownload( + delegate, std::move(params), std::move(request), + url_loader_factory_getter->GetNetworkFactory(), GURL(), + GURL(), GURL(), download::DownloadItem::kInvalidId, + true, task_runner) + .release()); } else { // Build the URLRequest, BlobDataHandle is hold in original request for // image download. @@ -68,11 +68,15 @@ DownloadRequestCore::CreateRequestOnIOThread( download::DownloadItem::kInvalidId, params.get()); - return std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread>( - UrlDownloader::BeginDownload(delegate, std::move(url_request), - params.get(), true) - .release()); + downloader.reset(UrlDownloader::BeginDownload( + delegate, std::move(url_request), params.get(), true) + .release()); } + task_runner->PostTask( + FROM_HERE, + base::BindOnce( + &download::UrlDownloadHandler::Delegate::OnUrlDownloadHandlerCreated, + delegate, std::move(downloader))); } } // namespace @@ -86,6 +90,7 @@ is_paused_(false), is_canceled_(false), is_user_cancel_(false), + url_download_handler_(nullptr, base::OnTaskRunnerDeleter(nullptr)), weak_factory_(this) { DCHECK(delegate_); } @@ -95,14 +100,11 @@ void DownloadWorker::SendRequest( std::unique_ptr<download::DownloadUrlParameters> params, scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - BrowserThread::PostTaskAndReplyWithResult( - BrowserThread::IO, FROM_HERE, + download::GetIOTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&CreateUrlDownloadHandler, std::move(params), weak_factory_.GetWeakPtr(), url_loader_factory_getter, - base::MessageLoop::current()->task_runner()), - base::BindOnce(&DownloadWorker::AddUrlDownloadHandler, - weak_factory_.GetWeakPtr())); + base::ThreadTaskRunnerHandle::Get())); } void DownloadWorker::Pause() { @@ -166,9 +168,8 @@ url_download_handler_.reset(); } -void DownloadWorker::AddUrlDownloadHandler( - std::unique_ptr<download::UrlDownloadHandler, - BrowserThread::DeleteOnIOThread> downloader) { +void DownloadWorker::OnUrlDownloadHandlerCreated( + download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader) { url_download_handler_ = std::move(downloader); }
diff --git a/content/browser/download/download_worker.h b/content/browser/download/download_worker.h index b36bb211..7ccc36b 100644 --- a/content/browser/download/download_worker.h +++ b/content/browser/download/download_worker.h
@@ -15,7 +15,6 @@ #include "content/browser/download/download_request_core.h" #include "content/browser/url_loader_factory_getter.h" #include "content/common/content_export.h" -#include "content/public/browser/browser_thread.h" namespace content { @@ -62,10 +61,9 @@ const download::DownloadUrlParameters::OnStartedCallback& callback) override; void OnUrlDownloadStopped(download::UrlDownloadHandler* downloader) override; - - void AddUrlDownloadHandler( - std::unique_ptr<download::UrlDownloadHandler, - BrowserThread::DeleteOnIOThread> downloader); + void OnUrlDownloadHandlerCreated( + download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader) + override; DownloadWorker::Delegate* const delegate_; @@ -84,7 +82,7 @@ std::unique_ptr<download::DownloadRequestHandleInterface> request_handle_; // Used to handle the url request. Live and die on IO thread. - std::unique_ptr<download::UrlDownloadHandler, BrowserThread::DeleteOnIOThread> + download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr url_download_handler_; base::WeakPtrFactory<DownloadWorker> weak_factory_;
diff --git a/content/browser/frame_host/data_url_navigation_throttle.cc b/content/browser/frame_host/data_url_navigation_throttle.cc index 4e1e7112..4d725ab2 100644 --- a/content/browser/frame_host/data_url_navigation_throttle.cc +++ b/content/browser/frame_host/data_url_navigation_throttle.cc
@@ -33,18 +33,6 @@ NavigationThrottle::ThrottleCheckResult DataUrlNavigationThrottle::WillProcessResponse() { -#if defined(OS_ANDROID) - // This should ideally be done in CreateThrottleForNavigation(), but - // NavigationHandleImpl::GetRenderFrameHost() expects to not be run before - // WillProcessResponse(). - // TODO(meacer): Remove this special case when PlzNavigate is enabled. - if (!IsBrowserSideNavigationEnabled() && - navigation_handle() - ->GetRenderFrameHost() - ->IsDataUrlNavigationAllowedForAndroidWebView()) { - return PROCEED; - } -#endif NavigationHandleImpl* handle = static_cast<NavigationHandleImpl*>(navigation_handle()); if (handle->IsDownload())
diff --git a/content/browser/frame_host/render_frame_host_android.cc b/content/browser/frame_host/render_frame_host_android.cc index 9f36fd67..8ef7214 100644 --- a/content/browser/frame_host/render_frame_host_android.cc +++ b/content/browser/frame_host/render_frame_host_android.cc
@@ -93,10 +93,10 @@ env, render_frame_host_->GetOverlayRoutingToken()); } -void RenderFrameHostAndroid::SetHasReceivedUserGesture( +void RenderFrameHostAndroid::NotifyUserActivation( JNIEnv* env, const base::android::JavaParamRef<jobject>&) { - render_frame_host_->SetHasReceivedUserGesture(); + render_frame_host_->NotifyUserActivation(); } } // namespace content
diff --git a/content/browser/frame_host/render_frame_host_android.h b/content/browser/frame_host/render_frame_host_android.h index 90b9369..423e1a6 100644 --- a/content/browser/frame_host/render_frame_host_android.h +++ b/content/browser/frame_host/render_frame_host_android.h
@@ -49,8 +49,8 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>&) const; - void SetHasReceivedUserGesture(JNIEnv* env, - const base::android::JavaParamRef<jobject>&); + void NotifyUserActivation(JNIEnv* env, + const base::android::JavaParamRef<jobject>&); private: RenderFrameHostImpl* const render_frame_host_;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index b5137005..b44fe8c3 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -191,10 +191,6 @@ // Whether to allow injecting javascript into any kind of frame (for Android // WebView). bool g_allow_injecting_javascript = false; - -// Whether to allow data URL navigations for Android WebView. -// TODO(meacer): Remove after PlzNavigate ships. -bool g_allow_data_url_navigation = false; #endif // The (process id, routing id) pair that identifies one RenderFrame. @@ -389,16 +385,6 @@ void RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView() { g_allow_injecting_javascript = true; } - -// static -void RenderFrameHost::AllowDataUrlNavigationForAndroidWebView() { - g_allow_data_url_navigation = true; -} - -// static -bool RenderFrameHost::IsDataUrlNavigationAllowedForAndroidWebView() { - return g_allow_data_url_navigation; -} #endif // defined(OS_ANDROID) // static @@ -2744,8 +2730,8 @@ bounds_in_frame_widget.size())); } -void RenderFrameHostImpl::SetHasReceivedUserGesture() { - Send(new FrameMsg_SetHasReceivedUserGesture(routing_id_)); +void RenderFrameHostImpl::NotifyUserActivation() { + Send(new FrameMsg_NotifyUserActivation(routing_id_)); } void RenderFrameHostImpl::OnSetHasReceivedUserGesture() {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 46e4270..604dd2d 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -698,13 +698,13 @@ return active_sandbox_flags_; } - // Call |FlushForTesting()| on Network Service and FrameNavigationControl + // Calls |FlushForTesting()| on Network Service and FrameNavigationControl // related interfaces to make sure all in-flight mojo messages have been // received by the other end. For test use only. void FlushNetworkAndNavigationInterfacesForTesting(); - // Notifies the render frame that a user gesture was received. - void SetHasReceivedUserGesture(); + // Notifies the render frame about a user activation from the browser side. + void NotifyUserActivation(); // Returns the current size for this frame. const base::Optional<gfx::Size>& frame_size() const { return frame_size_; }
diff --git a/content/browser/media/capture/aura_window_capture_machine.cc b/content/browser/media/capture/aura_window_capture_machine.cc index 3797696f..2f6caae 100644 --- a/content/browser/media/capture/aura_window_capture_machine.cc +++ b/content/browser/media/capture/aura_window_capture_machine.cc
@@ -367,7 +367,7 @@ base::Bind(&CopyOutputFinishedForVideo, weak_factory_.GetWeakPtr(), event_time, capture_frame_cb, video_frame, region_in_frame, base::Passed(&release_callback))); - media::LetterboxYUV(video_frame.get(), region_in_frame); + media::LetterboxVideoFrame(video_frame.get(), region_in_frame); return true; }
diff --git a/content/browser/notifications/OWNERS b/content/browser/notifications/OWNERS index 81314bd..c172d4b 100644 --- a/content/browser/notifications/OWNERS +++ b/content/browser/notifications/OWNERS
@@ -4,8 +4,8 @@ # //content/renderer/notifications/ # //content/test/mock_platform_notification_service.* +awdf@chromium.org mkwst@chromium.org -mvanouwerkerk@chromium.org peter@chromium.org # TEAM: platform-capabilities@chromium.org
diff --git a/content/browser/renderer_host/p2p/socket_host_tcp.cc b/content/browser/renderer_host/p2p/socket_host_tcp.cc index 83d8168d..12ead42 100644 --- a/content/browser/renderer_host/p2p/socket_host_tcp.cc +++ b/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -126,7 +126,8 @@ // The default SSLConfig is good enough for us for now. const net::SSLConfig ssl_config; socket_ = proxy_resolving_socket_factory_->CreateSocket( - ssl_config, GURL("https://" + dest_host_port_pair.ToString())); + ssl_config, GURL("https://" + dest_host_port_pair.ToString()), + false /*use_tls*/); int status = socket_->Connect( base::Bind(&P2PSocketHostTcpBase::OnConnected,
diff --git a/content/browser/renderer_host/render_frame_metadata_provider_impl.cc b/content/browser/renderer_host/render_frame_metadata_provider_impl.cc index 46aff7e..d16a615 100644 --- a/content/browser/renderer_host/render_frame_metadata_provider_impl.cc +++ b/content/browser/renderer_host/render_frame_metadata_provider_impl.cc
@@ -58,6 +58,11 @@ observer.OnRenderFrameSubmission(); } +void RenderFrameMetadataProviderImpl::SetLastRenderFrameMetadataForTest( + cc::RenderFrameMetadata metadata) { + last_render_frame_metadata_ = metadata; +} + void RenderFrameMetadataProviderImpl::OnRenderFrameMetadataChanged( uint32_t frame_token, const cc::RenderFrameMetadata& metadata) {
diff --git a/content/browser/renderer_host/render_frame_metadata_provider_impl.h b/content/browser/renderer_host/render_frame_metadata_provider_impl.h index b59187e..48ab56154 100644 --- a/content/browser/renderer_host/render_frame_metadata_provider_impl.h +++ b/content/browser/renderer_host/render_frame_metadata_provider_impl.h
@@ -23,7 +23,7 @@ // notified of all frame submissions. // // All RenderFrameMetadataProvider::Observer will be notified. -class RenderFrameMetadataProviderImpl +class CONTENT_EXPORT RenderFrameMetadataProviderImpl : public RenderFrameMetadataProvider, public mojom::RenderFrameMetadataObserverClient { public: @@ -44,6 +44,8 @@ const cc::RenderFrameMetadata& LastRenderFrameMetadata() const override; private: + friend class FakeRenderWidgetHostViewAura; + // Paired with the mojom::RenderFrameMetadataObserverClient overrides, these // methods are enqueued in |frame_token_message_queue_|. They are invoked when // the browser process receives their associated frame tokens. These then @@ -51,6 +53,10 @@ void OnFrameTokenRenderFrameMetadataChanged(cc::RenderFrameMetadata metadata); void OnFrameTokenFrameSubmissionForTesting(); + // Set |last_render_frame_metadata_| to the given |metadata| for testing + // purpose. + void SetLastRenderFrameMetadataForTest(cc::RenderFrameMetadata metadata); + // mojom::RenderFrameMetadataObserverClient: void OnRenderFrameMetadataChanged( uint32_t frame_token,
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 29d8878..42252a6 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -54,6 +54,9 @@ #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "base/trace_event/memory_allocator_dump.h" +#include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "cc/base/switches.h" @@ -342,6 +345,50 @@ #endif +// Globally tracks all existing RenderProcessHostImpl instances. +// +// TODO(https://crbug.com/813045): Remove this. +class RenderProcessMemoryDumpProvider + : public base::trace_event::MemoryDumpProvider { + public: + RenderProcessMemoryDumpProvider() { + base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( + this, "RenderProcessHost", base::ThreadTaskRunnerHandle::Get()); + } + + ~RenderProcessMemoryDumpProvider() override { + base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( + this); + } + + void AddHost(RenderProcessHostImpl* host) { hosts_.insert(host); } + void RemoveHost(RenderProcessHostImpl* host) { hosts_.erase(host); } + + private: + // base::trace_event::MemoryDumpProvider: + bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, + base::trace_event::ProcessMemoryDump* pmd) override { + for (auto* host : hosts_) { + base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump( + base::StringPrintf("mojo/render_process_host/0x%" PRIxPTR, + reinterpret_cast<uintptr_t>(host))); + dump->AddScalar("is_initialized", + base::trace_event::MemoryAllocatorDump::kUnitsObjects, + host->is_initialized() ? 1 : 0); + } + return true; + } + + std::set<RenderProcessHostImpl*> hosts_; + + DISALLOW_COPY_AND_ASSIGN(RenderProcessMemoryDumpProvider); +}; + +RenderProcessMemoryDumpProvider& GetMemoryDumpProvider() { + static base::NoDestructor<RenderProcessMemoryDumpProvider> tracker; + return *tracker; +} + // the global list of all renderer processes base::LazyInstance<base::IDMap<RenderProcessHost*>>::Leaky g_all_hosts = LAZY_INSTANCE_INITIALIZER; @@ -1367,6 +1414,8 @@ if (!base::FeatureList::IsEnabled(features::kMash)) gpu_client_.reset(new GpuClient(GetID())); + + GetMemoryDumpProvider().AddHost(this); } // static @@ -1430,6 +1479,8 @@ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::BindOnce(&RemoveShaderInfo, GetID())); } + + GetMemoryDumpProvider().RemoveHost(this); } bool RenderProcessHostImpl::Init() {
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 89ff6281..dab3d66d 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -391,6 +391,8 @@ return *permission_service_context_; } + bool is_initialized() const { return is_initialized_; } + protected: // A proxy for our IPC::Channel that lives on the IO thread. std::unique_ptr<IPC::ChannelProxy> channel_;
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 5cf5706..e5038f8 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -694,11 +694,7 @@ // If we navigated in background, clear the displayed graphics of the // previous page before going visible. - if (new_content_rendering_timeout_ && - new_content_rendering_timeout_->IsRunning()) { - new_content_rendering_timeout_->Stop(); - ClearDisplayedGraphics(); - } + ForceFirstFrameAfterNavigationTimeout(); SendScreenRects(); RestartHangMonitorTimeoutIfNecessary(); @@ -3012,6 +3008,14 @@ new_content_rendering_timeout_->Stop(); } +void RenderWidgetHostImpl::ForceFirstFrameAfterNavigationTimeout() { + if (new_content_rendering_timeout_ && + new_content_rendering_timeout_->IsRunning()) { + new_content_rendering_timeout_->Stop(); + ClearDisplayedGraphics(); + } +} + void RenderWidgetHostImpl::StopFling() { if (input_router_) input_router_->StopFling();
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index a9e5d18..6206a2bb 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -95,7 +95,6 @@ class BrowserAccessibilityManager; class InputRouter; class MockRenderWidgetHost; -class RenderFrameMetadataProvider; class RenderWidgetHostOwnerDelegate; class SyntheticGestureController; class TimeoutMonitor; @@ -602,7 +601,7 @@ return last_auto_resize_request_number_; } - RenderFrameMetadataProvider* render_frame_metadata_provider() { + RenderFrameMetadataProviderImpl* render_frame_metadata_provider() { return &render_frame_metadata_provider_; } @@ -658,6 +657,13 @@ void DidReceiveFirstFrameAfterNavigation(); + // The RenderWidgetHostImpl will keep showing the old page (for a while) after + // navigation until the first frame of the new page arrives. This reduces + // flicker. However, if for some reason it is known that the frames won't be + // arriving, this call can be used for force a timeout, to avoid showing the + // content of the old page under UI from the new page. + void ForceFirstFrameAfterNavigationTimeout(); + uint32_t current_content_source_id() { return current_content_source_id_; } void SetScreenOrientationForTesting(uint16_t angle,
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index a62fdee..b7a19301 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -878,12 +878,6 @@ DCHECK(delegated_frame_host_); TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame"); - // Override the background color to the current compositor background. - // This allows us to, when navigating to a new page, transfer this color to - // that page. This allows us to pass this background color to new views on - // navigation. - UpdateBackgroundColorFromRenderer(frame.metadata.root_background_color); - last_scroll_offset_ = frame.metadata.root_scroll_offset; if (IsUseZoomForDSFEnabled()) { // With zoom-for-DSF Blink pixel coordinates are used and zoom is used to @@ -1783,6 +1777,16 @@ } //////////////////////////////////////////////////////////////////////////////// +// RenderWidgetHostViewAura, RenderFrameMetadataProvider::Observer +// implementation: +void RenderWidgetHostViewAura::OnRenderFrameMetadataChanged() { + UpdateBackgroundColorFromRenderer(host() + ->render_frame_metadata_provider() + ->LastRenderFrameMetadata() + .root_background_color); +} + +//////////////////////////////////////////////////////////////////////////////// // RenderWidgetHostViewAura, private: RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index 3c65a71..f54822b 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -283,6 +283,9 @@ void OnHostMovedInPixels(aura::WindowTreeHost* host, const gfx::Point& new_origin_in_pixels) override; + // RenderFrameMetadataProvider::Observer + void OnRenderFrameMetadataChanged() override; + #if defined(OS_WIN) // Gets the HWND of the host window. HWND GetHostWindowHWND() const; @@ -522,7 +525,9 @@ void UpdateNeedsBeginFramesInternal(); // Applies background color without notifying the RenderWidget about - // opaqueness changes. + // opaqueness changes. This allows us to, when navigating to a new page, + // transfer this color to that page. This allows us to pass this background + // color to new views on navigation. void UpdateBackgroundColorFromRenderer(SkColor color); const bool is_mus_browser_plugin_guest_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index eb3ee7b7..a916856 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -25,6 +25,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "build/build_config.h" +#include "cc/trees/render_frame_metadata.h" #include "components/viz/common/features.h" #include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/quads/compositor_frame.h" @@ -50,6 +51,7 @@ #include "content/browser/renderer_host/input/mouse_wheel_event_queue.h" #include "content/browser/renderer_host/overscroll_controller.h" #include "content/browser/renderer_host/overscroll_controller_delegate.h" +#include "content/browser/renderer_host/render_frame_metadata_provider_impl.h" #include "content/browser/renderer_host/render_view_host_factory.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" #include "content/browser/renderer_host/render_widget_host_impl.h" @@ -137,8 +139,6 @@ RenderWidgetHostViewAura* render_widget_host_view, std::unique_ptr<DelegatedFrameHostClient> delegated_frame_host_client); -namespace { - constexpr uint64_t kFrameIndexStart = viz::CompositorFrameSinkSupport::kFrameIndexStart; @@ -352,6 +352,11 @@ return event_handler()->pointer_state(); } + void SetRenderFrameMetadata(cc::RenderFrameMetadata metadata) { + host()->render_frame_metadata_provider()->SetLastRenderFrameMetadataForTest( + metadata); + } + bool resize_locked() const { return delegated_frame_host_client_->resize_locked(); } @@ -479,8 +484,6 @@ kAsyncWheelEvents, }; -} // namespace - class RenderWidgetHostViewAuraTest : public testing::Test { public: RenderWidgetHostViewAuraTest( @@ -2759,11 +2762,10 @@ gfx::Rect()); view_->SetSize(frame_size); view_->Show(); - viz::CompositorFrame frame = - MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)); - frame.metadata.root_background_color = SK_ColorRED; - view_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr); - + cc::RenderFrameMetadata metadata; + metadata.root_background_color = SK_ColorRED; + view_->SetRenderFrameMetadata(metadata); + view_->OnRenderFrameMetadataChanged(); ui::Layer* parent_layer = view_->GetNativeView()->layer(); EXPECT_EQ(gfx::Rect(0, 0, 100, 100), parent_layer->bounds());
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index 37da659..122a22ae 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -51,7 +51,9 @@ features::kTouchpadAndWheelScrollLatching)), web_contents_accessibility_(nullptr), renderer_frame_number_(0), - weak_factory_(this) {} + weak_factory_(this) { + host_->render_frame_metadata_provider()->AddObserver(this); +} RenderWidgetHostViewBase::~RenderWidgetHostViewBase() { DCHECK(!mouse_locked_); @@ -67,6 +69,8 @@ // so that the |text_input_manager_| will free its state. if (text_input_manager_) text_input_manager_->Unregister(this); + if (host_) + host_->render_frame_metadata_provider()->RemoveObserver(this); } RenderWidgetHostImpl* RenderWidgetHostViewBase::GetFocusedWidget() const { @@ -92,6 +96,10 @@ return false; } +void RenderWidgetHostViewBase::OnRenderFrameMetadataChanged() {} + +void RenderWidgetHostViewBase::OnRenderFrameSubmission() {} + void RenderWidgetHostViewBase::SetBackgroundColorToDefault() { SetBackgroundColor(SK_ColorWHITE); } @@ -468,7 +476,10 @@ } void RenderWidgetHostViewBase::Destroy() { - host_ = nullptr; + if (host_) { + host_->render_frame_metadata_provider()->RemoveObserver(this); + host_ = nullptr; + } } void RenderWidgetHostViewBase::TextInputStateChanged(
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index e44d950..5937ae30 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -23,6 +23,7 @@ #include "components/viz/common/surfaces/surface_id.h" #include "content/browser/renderer_host/event_with_latency_info.h" #include "content/common/content_export.h" +#include "content/public/browser/render_frame_metadata_provider.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/common/input_event_ack_state.h" #include "content/public/common/screen_info.h" @@ -88,8 +89,10 @@ struct TextInputState; // Basic implementation shared by concrete RenderWidgetHostView subclasses. -class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView, - public IPC::Listener { +class CONTENT_EXPORT RenderWidgetHostViewBase + : public RenderWidgetHostView, + public IPC::Listener, + public RenderFrameMetadataProvider::Observer { public: using CreateCompositorFrameSinkCallback = base::OnceCallback<void(const viz::FrameSinkId&)>; @@ -136,6 +139,10 @@ // IPC::Listener implementation: bool OnMessageReceived(const IPC::Message& msg) override; + // RenderFrameMetadataProvider::Observer + void OnRenderFrameMetadataChanged() override; + void OnRenderFrameSubmission() override; + void SetPopupType(blink::WebPopupType popup_type); blink::WebPopupType GetPopupType();
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc index 6f871af2..8f029c47 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -408,7 +408,6 @@ // RenderWidgetHostInputEventRouter afterwards. NotifyObserversAboutShutdown(); - host()->SetView(nullptr); RenderWidgetHostViewBase::Destroy(); delete this;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 992ea36..ce2f473 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3334,12 +3334,14 @@ void WebContentsImpl::SaveFrame(const GURL& url, const Referrer& referrer) { - SaveFrameWithHeaders(url, referrer, std::string()); + SaveFrameWithHeaders(url, referrer, std::string(), base::string16()); } -void WebContentsImpl::SaveFrameWithHeaders(const GURL& url, - const Referrer& referrer, - const std::string& headers) { +void WebContentsImpl::SaveFrameWithHeaders( + const GURL& url, + const Referrer& referrer, + const std::string& headers, + const base::string16& suggested_filename) { if (!GetLastCommittedURL().is_valid()) return; if (delegate_ && delegate_->SaveFrame(url, referrer)) @@ -3401,6 +3403,7 @@ params->add_request_header(key_value.first, key_value.second); } } + params->set_suggested_name(suggested_filename); params->set_download_source(download::DownloadSource::WEB_CONTENTS_API); BrowserContext::GetDownloadManager(GetBrowserContext()) ->DownloadUrl(std::move(params)); @@ -4684,6 +4687,16 @@ const base::string16& default_prompt, JavaScriptDialogType dialog_type, IPC::Message* reply_msg) { + // Ensure that if showing a dialog is the first thing that a page does, that + // the contents of the previous page aren't shown behind it. This is required + // because showing a dialog freezes the renderer, so no frames will be coming + // from it. https://crbug.com/823353 + auto* render_widget_host_impl = + static_cast<RenderFrameHostImpl*>(render_frame_host) + ->GetRenderWidgetHost(); + if (render_widget_host_impl) + render_widget_host_impl->ForceFirstFrameAfterNavigationTimeout(); + // Running a dialog causes an exit to webpage-initiated fullscreen. // http://crbug.com/728276 if (IsFullscreenForCurrentTab()) @@ -4743,6 +4756,16 @@ RenderFrameHost* render_frame_host, bool is_reload, IPC::Message* reply_msg) { + // Ensure that if showing a dialog is the first thing that a page does, that + // the contents of the previous page aren't shown behind it. This is required + // because showing a dialog freezes the renderer, so no frames will be coming + // from it. https://crbug.com/823353 + auto* render_widget_host_impl = + static_cast<RenderFrameHostImpl*>(render_frame_host) + ->GetRenderWidgetHost(); + if (render_widget_host_impl) + render_widget_host_impl->ForceFirstFrameAfterNavigationTimeout(); + // Running a dialog causes an exit to webpage-initiated fullscreen. // http://crbug.com/728276 if (IsFullscreenForCurrentTab())
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 6d682fb4..97527f1 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -418,7 +418,8 @@ void SaveFrame(const GURL& url, const Referrer& referrer) override; void SaveFrameWithHeaders(const GURL& url, const Referrer& referrer, - const std::string& headers) override; + const std::string& headers, + const base::string16& suggested_filename) override; void GenerateMHTML(const MHTMLGenerationParams& params, const base::Callback<void(int64_t)>& callback) override; const std::string& GetContentsMimeType() const override;
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc index 05abf08..9490c80 100644 --- a/content/browser/web_contents/web_contents_impl_unittest.cc +++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -3566,8 +3566,8 @@ blink::WebSandboxFlags::kPopups | blink::WebSandboxFlags::kModals | blink::WebSandboxFlags::kTopNavigation; params.starting_sandbox_flags = expected_flags; - WebContentsImpl* new_contents = - WebContentsImpl::CreateWithOpener(params, nullptr); + std::unique_ptr<WebContentsImpl> new_contents( + WebContentsImpl::CreateWithOpener(params, nullptr)); FrameTreeNode* root = new_contents->GetFrameTree()->root(); blink::WebSandboxFlags pending_flags = root->pending_frame_policy().sandbox_flags;
diff --git a/content/common/content_security_policy/csp_source_list_unittest.cc b/content/common/content_security_policy/csp_source_list_unittest.cc index 575eed4..2e0838d29 100644 --- a/content/common/content_security_policy/csp_source_list_unittest.cc +++ b/content/common/content_security_policy/csp_source_list_unittest.cc
@@ -94,10 +94,10 @@ false, // allow_star: std::vector<CSPSource>()); // source_list - EXPECT_TRUE(Allow( - source_list, - GURL("chrome://print/pdf_preview.html?chrome://print/1/0/print.pdf"), - &context)); + EXPECT_TRUE( + Allow(source_list, + GURL("chrome://print/pdf/index.html?chrome://print/1/0/print.pdf"), + &context)); } TEST(CSPSourceList, AllowNone) {
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index beb92fce..25e820f 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -1117,8 +1117,11 @@ // ScopedPageLoadDeferrer is on the stack for SwapOut. IPC_MESSAGE_ROUTED0(FrameMsg_SuppressFurtherDialogs) +// Notifies the RenderFrame about a user activation from the browser side. +IPC_MESSAGE_ROUTED0(FrameMsg_NotifyUserActivation) + // Tells the frame to consider itself to have received a user gesture (based -// on a user gesture processed in a different process). +// on a user gesture processed in a different renderer process). IPC_MESSAGE_ROUTED0(FrameMsg_SetHasReceivedUserGesture) // Tells the frame to mark that the previous document on that frame had received
diff --git a/content/common/render_frame_metadata.mojom b/content/common/render_frame_metadata.mojom index ffc97dc..bf659e5 100644 --- a/content/common/render_frame_metadata.mojom +++ b/content/common/render_frame_metadata.mojom
@@ -8,6 +8,11 @@ // See components/viz/service/quads/render_frame_metadata.h struct RenderFrameMetadata { + // The background color of a CompositorFrame. It can be used for filling the + // content area if the primary surface is unavailable and fallback is not + // specified. + uint32 root_background_color; + // Scroll offset of the root layer. This optional parameter is only sent // during tests. gfx.mojom.Vector2dF? root_scroll_offset;
diff --git a/content/common/render_frame_metadata_struct_traits.cc b/content/common/render_frame_metadata_struct_traits.cc index c8c2719..2897c954 100644 --- a/content/common/render_frame_metadata_struct_traits.cc +++ b/content/common/render_frame_metadata_struct_traits.cc
@@ -13,6 +13,7 @@ cc::RenderFrameMetadata>:: Read(content::mojom::RenderFrameMetadataDataView data, cc::RenderFrameMetadata* out) { + out->root_background_color = data.root_background_color(); return data.ReadRootScrollOffset(&out->root_scroll_offset); }
diff --git a/content/common/render_frame_metadata_struct_traits.h b/content/common/render_frame_metadata_struct_traits.h index ff267126..228a6792 100644 --- a/content/common/render_frame_metadata_struct_traits.h +++ b/content/common/render_frame_metadata_struct_traits.h
@@ -14,6 +14,11 @@ template <> struct StructTraits<content::mojom::RenderFrameMetadataDataView, cc::RenderFrameMetadata> { + static SkColor root_background_color( + const cc::RenderFrameMetadata& metadata) { + return metadata.root_background_color; + } + static base::Optional<gfx::Vector2dF> root_scroll_offset( const cc::RenderFrameMetadata& metadata) { return metadata.root_scroll_offset;
diff --git a/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java b/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java index b5a59b7..1c2ea6f 100644 --- a/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java
@@ -92,8 +92,8 @@ } @Override - public void setHasReceivedUserGesture() { - nativeSetHasReceivedUserGesture(mNativeRenderFrameHostAndroid); + public void notifyUserActivation() { + nativeNotifyUserActivation(mNativeRenderFrameHostAndroid); } /** @@ -109,5 +109,5 @@ long nativeRenderFrameHostAndroid, Callback<String> callback); private native UnguessableToken nativeGetAndroidOverlayRoutingToken( long nativeRenderFrameHostAndroid); - private native void nativeSetHasReceivedUserGesture(long nativeRenderFrameHostAndroid); + private native void nativeNotifyUserActivation(long nativeRenderFrameHostAndroid); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/remoteobjects/RemoteObjectImpl.java b/content/public/android/java/src/org/chromium/content/browser/remoteobjects/RemoteObjectImpl.java index af0f1f3..b8cf1c0 100644 --- a/content/public/android/java/src/org/chromium/content/browser/remoteobjects/RemoteObjectImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/remoteobjects/RemoteObjectImpl.java
@@ -9,6 +9,7 @@ import org.chromium.blink.mojom.RemoteInvocationArgument; import org.chromium.blink.mojom.RemoteInvocationError; import org.chromium.blink.mojom.RemoteInvocationResult; +import org.chromium.blink.mojom.RemoteInvocationResultValue; import org.chromium.blink.mojom.RemoteObject; import org.chromium.blink.mojom.SingletonJavaScriptValue; import org.chromium.mojo.system.MojoException; @@ -141,6 +142,8 @@ // return arrays. Spec requires calling the method and converting the // result to a JavaScript array. RemoteInvocationResult result = new RemoteInvocationResult(); + result.value = new RemoteInvocationResultValue(); + result.value.setSingletonValue(SingletonJavaScriptValue.UNDEFINED); callback.call(result); return; } @@ -356,8 +359,37 @@ } private RemoteInvocationResult convertResult(Object result, Class<?> returnType) { - // TODO(jbroman): Convert result. - return new RemoteInvocationResult(); + // Methods returning arrays should not be called (for legacy reasons). + assert !returnType.isArray(); + + // LIVECONNECT_COMPLIANCE: The specification suggests that the conversion should happen + // based on the type of the result value. Existing behavior is to rely on the declared + // return type of the method. This means, for instance, that a java.lang.String returned + // from a method declared as returning java.lang.Object will not be converted to a + // JavaScript string. + RemoteInvocationResultValue resultValue = new RemoteInvocationResultValue(); + if (returnType == void.class) { + resultValue.setSingletonValue(SingletonJavaScriptValue.UNDEFINED); + } else if (returnType == boolean.class) { + resultValue.setBooleanValue((Boolean) result); + } else if (returnType == char.class) { + resultValue.setNumberValue((Character) result); + } else if (returnType.isPrimitive()) { + resultValue.setNumberValue(((Number) result).doubleValue()); + } else if (returnType == String.class) { + if (result == null) { + // LIVECONNECT_COMPLIANCE: Existing behavior is to return undefined. + // Spec requires returning a null string. + resultValue.setSingletonValue(SingletonJavaScriptValue.UNDEFINED); + } else { + resultValue.setStringValue(javaStringToMojoString((String) result)); + } + } else { + // TODO(jbroman): Implement handling for other objects. + } + RemoteInvocationResult mojoResult = new RemoteInvocationResult(); + mojoResult.value = resultValue; + return mojoResult; } private static RemoteInvocationResult makeErrorResult(int error) { @@ -437,4 +469,14 @@ } return String.valueOf(chars); } + + private static String16 javaStringToMojoString(String string) { + short[] data = new short[string.length()]; + for (int i = 0; i < data.length; i++) { + data[i] = (short) string.charAt(i); + } + String16 mojoString = new String16(); + mojoString.data = data; + return mojoString; + } }
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/RenderFrameHost.java b/content/public/android/java/src/org/chromium/content_public/browser/RenderFrameHost.java index e87bda0..e6a5891 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/RenderFrameHost.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/RenderFrameHost.java
@@ -35,7 +35,7 @@ InterfaceProvider getRemoteInterfaces(); /** - * Notifies the native RenderFrameHost of a user gesture. + * Notifies the native RenderFrameHost about a user activation from the browser side. */ - void setHasReceivedUserGesture(); + void notifyUserActivation(); }
diff --git a/content/public/android/junit/src/org/chromium/content/browser/remoteobjects/RemoteObjectImplTest.java b/content/public/android/junit/src/org/chromium/content/browser/remoteobjects/RemoteObjectImplTest.java index e5ac6242..95ab21e 100644 --- a/content/public/android/junit/src/org/chromium/content/browser/remoteobjects/RemoteObjectImplTest.java +++ b/content/public/android/junit/src/org/chromium/content/browser/remoteobjects/RemoteObjectImplTest.java
@@ -4,6 +4,7 @@ package org.chromium.content.browser.remoteobjects; +import static org.mockito.AdditionalMatchers.and; import static org.mockito.AdditionalMatchers.aryEq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; @@ -22,6 +23,7 @@ import org.chromium.blink.mojom.RemoteInvocationArgument; import org.chromium.blink.mojom.RemoteInvocationError; import org.chromium.blink.mojom.RemoteInvocationResult; +import org.chromium.blink.mojom.RemoteInvocationResultValue; import org.chromium.blink.mojom.RemoteObject; import org.chromium.blink.mojom.SingletonJavaScriptValue; import org.chromium.mojo_base.mojom.String16; @@ -295,7 +297,7 @@ RemoteObject.InvokeMethodResponse response = mock(RemoteObject.InvokeMethodResponse.class); remoteObject.invokeMethod("returnsIntArray", new RemoteInvocationArgument[] {}, response); - verify(response).call(resultIsOk()); + verify(response).call(resultIsUndefined()); } @Test @@ -627,6 +629,106 @@ verify(consumer, times(2)).accept(null); } + @Test + public void testResultConversionVoid() { + Object target = new Object() { + @TestJavascriptInterface + public void returnsVoid() {} + }; + + RemoteObject remoteObject = new RemoteObjectImpl(target, TestJavascriptInterface.class); + RemoteObject.InvokeMethodResponse response = mock(RemoteObject.InvokeMethodResponse.class); + remoteObject.invokeMethod("returnsVoid", new RemoteInvocationArgument[] {}, response); + + verify(response).call(resultIsUndefined()); + } + + @Test + public void testConversionResultNumber() { + Object target = new Object() { + @TestJavascriptInterface + public int returnsInt() { + return 42; + } + + @TestJavascriptInterface + public float returnsFloat() { + return -1.5f; + } + + @TestJavascriptInterface + public char returnsChar() { + return '\ufeed'; + } + }; + + RemoteObject remoteObject = new RemoteObjectImpl(target, TestJavascriptInterface.class); + RemoteObject.InvokeMethodResponse response = mock(RemoteObject.InvokeMethodResponse.class); + remoteObject.invokeMethod("returnsInt", new RemoteInvocationArgument[] {}, response); + remoteObject.invokeMethod("returnsFloat", new RemoteInvocationArgument[] {}, response); + remoteObject.invokeMethod("returnsChar", new RemoteInvocationArgument[] {}, response); + + verify(response).call(resultIsNumber(42)); + verify(response).call(resultIsNumber(-1.5f)); + verify(response).call(resultIsNumber(0xfeed)); + } + + @Test + public void testConversionResultBoolean() { + Object target = new Object() { + @TestJavascriptInterface + public boolean returnsTrue() { + return true; + } + + @TestJavascriptInterface + public boolean returnsFalse() { + return false; + } + }; + + RemoteObject remoteObject = new RemoteObjectImpl(target, TestJavascriptInterface.class); + RemoteObject.InvokeMethodResponse response = mock(RemoteObject.InvokeMethodResponse.class); + remoteObject.invokeMethod("returnsTrue", new RemoteInvocationArgument[] {}, response); + remoteObject.invokeMethod("returnsFalse", new RemoteInvocationArgument[] {}, response); + + InOrder inOrder = inOrder(response); + inOrder.verify(response).call(resultIsBoolean(true)); + inOrder.verify(response).call(resultIsBoolean(false)); + } + + @Test + public void testConversionResultString() { + final String stringWithNonAsciiCharacterAndUnpairedSurrogate = "caf\u00e9\ud800"; + Object target = new Object() { + @TestJavascriptInterface + public String returnsHello() { + return "Hello"; + } + + @TestJavascriptInterface + public String returnsExoticString() { + return stringWithNonAsciiCharacterAndUnpairedSurrogate; + } + + @TestJavascriptInterface + public String returnsNull() { + return null; + } + }; + + RemoteObject remoteObject = new RemoteObjectImpl(target, TestJavascriptInterface.class); + RemoteObject.InvokeMethodResponse response = mock(RemoteObject.InvokeMethodResponse.class); + remoteObject.invokeMethod("returnsHello", new RemoteInvocationArgument[] {}, response); + remoteObject.invokeMethod( + "returnsExoticString", new RemoteInvocationArgument[] {}, response); + remoteObject.invokeMethod("returnsNull", new RemoteInvocationArgument[] {}, response); + + verify(response).call(resultIsString("Hello")); + verify(response).call(resultIsString(stringWithNonAsciiCharacterAndUnpairedSurrogate)); + verify(response).call(resultIsUndefined()); + } + private RemoteInvocationResult resultHasError(final int error) { return ArgumentMatchers.argThat(result -> result.error == error); } @@ -635,6 +737,42 @@ return resultHasError(RemoteInvocationError.OK); } + private RemoteInvocationResult resultIsUndefined() { + return and(resultIsOk(), ArgumentMatchers.argThat(result -> { + return result.value != null + && result.value.which() == RemoteInvocationResultValue.Tag.SingletonValue + && result.value.getSingletonValue() == SingletonJavaScriptValue.UNDEFINED; + })); + } + + private RemoteInvocationResult resultIsNumber(final double numberValue) { + return and(resultIsOk(), ArgumentMatchers.argThat(result -> { + return result.value != null + && result.value.which() == RemoteInvocationResultValue.Tag.NumberValue + && result.value.getNumberValue() == numberValue; + })); + } + + private RemoteInvocationResult resultIsBoolean(final boolean booleanValue) { + return and(resultIsOk(), ArgumentMatchers.argThat(result -> { + return result.value != null + && result.value.which() == RemoteInvocationResultValue.Tag.BooleanValue + && result.value.getBooleanValue() == booleanValue; + })); + } + + private RemoteInvocationResult resultIsString(String stringValue) { + final short[] expectedData = new short[stringValue.length()]; + for (int i = 0; i < expectedData.length; i++) { + expectedData[i] = (short) stringValue.charAt(i); + } + return and(resultIsOk(), ArgumentMatchers.argThat(result -> { + return result.value != null + && result.value.which() == RemoteInvocationResultValue.Tag.StringValue + && Arrays.equals(result.value.getStringValue().data, expectedData); + })); + } + private RemoteInvocationArgument numberArgument(double numberValue) { RemoteInvocationArgument argument = new RemoteInvocationArgument(); argument.setNumberValue(numberValue);
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h index e2edb70a..8c7ab68 100644 --- a/content/public/browser/render_frame_host.h +++ b/content/public/browser/render_frame_host.h
@@ -70,11 +70,6 @@ // is present only to support Android WebView and must not be used in other // configurations. static void AllowInjectingJavaScriptForAndroidWebView(); - - // Temporary hack to enable data URLs on Android Webview until PlzNavigate - // ships. - static void AllowDataUrlNavigationForAndroidWebView(); - static bool IsDataUrlNavigationAllowedForAndroidWebView(); #endif // Returns a RenderFrameHost given its accessibility tree ID.
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h index 42e684b..1df8201e 100644 --- a/content/public/browser/web_contents.h +++ b/content/public/browser/web_contents.h
@@ -611,9 +611,11 @@ // provided, is used to make a request to the URL rather than using cache. // Format of |headers| is a new line separated list of key value pairs: // "<key1>: <value1>\r\n<key2>: <value2>". - virtual void SaveFrameWithHeaders(const GURL& url, - const Referrer& referrer, - const std::string& headers) = 0; + virtual void SaveFrameWithHeaders( + const GURL& url, + const Referrer& referrer, + const std::string& headers, + const base::string16& suggested_filename) = 0; // Generate an MHTML representation of the current page in the given file. // If |use_binary_encoding| is specified, a Content-Transfer-Encoding value of
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/mock/MockRenderFrameHost.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/mock/MockRenderFrameHost.java index bdd9b27..7875778 100644 --- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/mock/MockRenderFrameHost.java +++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/mock/MockRenderFrameHost.java
@@ -26,5 +26,5 @@ } @Override - public void setHasReceivedUserGesture() {} + public void notifyUserActivation() {} }
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 2947844..f1ad61b 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -2483,6 +2483,16 @@ return simple_loader->NetError(); } +void EnsureCookiesFlushed(BrowserContext* browser_context) { + BrowserContext::ForEachStoragePartition( + browser_context, base::BindRepeating([](StoragePartition* partition) { + base::RunLoop run_loop; + partition->GetCookieManagerForBrowserProcess()->FlushCookieStore( + run_loop.QuitClosure()); + run_loop.Run(); + })); +} + bool HasValidProcessForProcessGroup(const std::string& process_group_name) { return ServiceManagerContext::HasValidProcessForProcessGroup( process_group_name);
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index 84201c5..36a1b4a6 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -1109,6 +1109,10 @@ int process_id = 0, int render_frame_id = 0); +// Ensures that all StoragePartitions for the given BrowserContext have their +// cookies flushed to disk. +void EnsureCookiesFlushed(BrowserContext* browser_context); + // Returns true if there is a valid process for |process_group_name|. Must be // called on the IO thread. bool HasValidProcessForProcessGroup(const std::string& process_group_name);
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc index 8ba67bab..305d531 100644 --- a/content/public/test/test_renderer_host.cc +++ b/content/public/test/test_renderer_host.cc
@@ -16,6 +16,7 @@ #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/site_instance_impl.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_widget_host_iterator.h" #include "content/public/browser/web_contents.h" #include "content/public/common/browser_side_navigation_policy.h" #include "content/public/test/browser_side_navigation_test_utils.h" @@ -296,8 +297,12 @@ #endif // Delete any RenderProcessHosts before the BrowserContext goes away. - if (rvh_test_enabler_->rph_factory_) + if (rvh_test_enabler_->rph_factory_) { + auto render_widget_hosts = RenderWidgetHost::GetRenderWidgetHosts(); + ASSERT_EQ(nullptr, render_widget_hosts->GetNextHost()) << + "Test is leaking at least one RenderWidgetHost."; rvh_test_enabler_->rph_factory_.reset(); + } rvh_test_enabler_.reset();
diff --git a/content/public/test/web_contents_tester.h b/content/public/test/web_contents_tester.h index b975bcd..a8d2b2e2 100644 --- a/content/public/test/web_contents_tester.h +++ b/content/public/test/web_contents_tester.h
@@ -114,7 +114,10 @@ // Returns headers that were passed in the previous SaveFrameWithHeaders(...) // call. - virtual const std::string& GetSaveFrameHeaders() = 0; + virtual const std::string& GetSaveFrameHeaders() const = 0; + + // Returns the suggested file name passed in the SaveFrameWithHeaders call. + virtual const base::string16& GetSuggestedFileName() const = 0; // Returns whether a download request triggered via DownloadImage() is in // progress for |url|.
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 9bd0d8e..c293c90 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -1823,8 +1823,8 @@ IPC_MESSAGE_HANDLER(FrameMsg_MixedContentFound, OnMixedContentFound) IPC_MESSAGE_HANDLER(FrameMsg_SetOverlayRoutingToken, OnSetOverlayRoutingToken) - IPC_MESSAGE_HANDLER(FrameMsg_SetHasReceivedUserGesture, - OnSetHasReceivedUserGesture) + IPC_MESSAGE_HANDLER(FrameMsg_NotifyUserActivation, OnNotifyUserActivation) + #if defined(OS_ANDROID) IPC_MESSAGE_HANDLER(FrameMsg_ActivateNearestFindResult, OnActivateNearestFindResult) @@ -3981,6 +3981,8 @@ params.url = request.Url(); params.referrer = RenderViewImpl::GetReferrerFromRequest(frame_, request); params.initiator_origin = request.RequestorOrigin(); + if (request.GetSuggestedFilename().has_value()) + params.suggested_name = request.GetSuggestedFilename()->Utf16(); Send(new FrameHostMsg_DownloadUrl(params)); } @@ -6516,10 +6518,6 @@ pending_routing_token_callbacks_.clear(); } -void RenderFrameImpl::OnSetHasReceivedUserGesture() { - frame_->SetHasReceivedUserGesture(); -} - void RenderFrameImpl::RequestOverlayRoutingToken( media::RoutingTokenCallback callback) { if (overlay_routing_token_.has_value()) { @@ -6534,6 +6532,10 @@ pending_routing_token_callbacks_.push_back(std::move(callback)); } +void RenderFrameImpl::OnNotifyUserActivation() { + frame_->NotifyUserActivation(); +} + #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) #if defined(OS_MACOSX) void RenderFrameImpl::OnSelectPopupMenuItem(int selected_index) {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 611a112..ffb8a794 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -1078,7 +1078,7 @@ void OnFindMatchRects(int current_version); #endif void OnSetOverlayRoutingToken(const base::UnguessableToken& token); - void OnSetHasReceivedUserGesture(); + void OnNotifyUserActivation(); #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) #if defined(OS_MACOSX)
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn index 448d5c5..36d89f7 100644 --- a/content/shell/BUILD.gn +++ b/content/shell/BUILD.gn
@@ -724,6 +724,13 @@ output_name = content_shell_framework_name + framework_version = "C" + + framework_contents = [ + "Helpers", + "Resources", + ] + sources = [ "app/shell_content_main.cc", "app/shell_content_main.h", @@ -758,11 +765,11 @@ if (is_component_build) { # Set up the rpath for the framework so that it can find dylibs in the # root output directory. The framework is at - # Content Shell.app/Contents/Frameworks/Content Shell Framework.framework/Content Shell Framework + # Content Shell.app/Contents/Frameworks/Content Shell Framework.framework/Versions/C/Content Shell Framework # so use loader_path to go back to the root output directory. ldflags += [ "-rpath", - "@loader_path/../../../..", + "@loader_path/../../../../../..", ] }
diff --git a/content/shell/android/BUILD.gn b/content/shell/android/BUILD.gn index 3c2e76a..89dd771 100644 --- a/content/shell/android/BUILD.gn +++ b/content/shell/android/BUILD.gn
@@ -200,6 +200,7 @@ instrumentation_test_apk("content_shell_test_apk") { deps = [ "//base:base_java_test_support", + "//base:base_javatests", "//content/public/android:content_javatests", "//net/android:net_javatests", "//third_party/android_support_test_runner:runner_java",
diff --git a/content/shell/test_runner/mock_web_document_subresource_filter.cc b/content/shell/test_runner/mock_web_document_subresource_filter.cc index 2b3f68c..c0c7b12 100644 --- a/content/shell/test_runner/mock_web_document_subresource_filter.cc +++ b/content/shell/test_runner/mock_web_document_subresource_filter.cc
@@ -50,4 +50,8 @@ return true; } +bool MockWebDocumentSubresourceFilter::GetIsAssociatedWithAdSubframe() const { + return false; +} + } // namespace test_runner
diff --git a/content/shell/test_runner/mock_web_document_subresource_filter.h b/content/shell/test_runner/mock_web_document_subresource_filter.h index c1aff78..4cec93f 100644 --- a/content/shell/test_runner/mock_web_document_subresource_filter.h +++ b/content/shell/test_runner/mock_web_document_subresource_filter.h
@@ -32,6 +32,7 @@ const blink::WebURL& url) override; void ReportDisallowedLoad() override; bool ShouldLogToConsole() override; + bool GetIsAssociatedWithAdSubframe() const override; private: LoadPolicy getLoadPolicyImpl(const blink::WebURL& url);
diff --git a/content/test/data/download/download-attribute-with-target.html b/content/test/data/download/download-attribute-with-target.html new file mode 100644 index 0000000..e658fcc3 --- /dev/null +++ b/content/test/data/download/download-attribute-with-target.html
@@ -0,0 +1,10 @@ +<!doctype html> +<html> +<body> +<a download="suggested-filename" href="data:application/octet-stream, ..." target="_blank">link</a> +<script> + var anchorElement = document.querySelector('a[download]'); + anchorElement.click(); +</script> +</body> +</html>
diff --git a/content/test/gpu/PRESUBMIT.py b/content/test/gpu/PRESUBMIT.py index 8e711b1..649911a6 100644 --- a/content/test/gpu/PRESUBMIT.py +++ b/content/test/gpu/PRESUBMIT.py
@@ -36,7 +36,7 @@ cl, [ 'luci.chromium.try:linux_optional_gpu_tests_rel', - 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'luci.chromium.try:mac_optional_gpu_tests_rel', 'master.tryserver.chromium.win:win_optional_gpu_tests_rel', 'master.tryserver.chromium.android:android_optional_gpu_tests_rel', ],
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc index 8d73aab..69a40ee 100644 --- a/content/test/test_web_contents.cc +++ b/content/test/test_web_contents.cc
@@ -161,10 +161,14 @@ rfh->SendNavigateWithParams(¶ms, was_within_same_document); } -const std::string& TestWebContents::GetSaveFrameHeaders() { +const std::string& TestWebContents::GetSaveFrameHeaders() const { return save_frame_headers_; } +const base::string16& TestWebContents::GetSuggestedFileName() const { + return suggested_filename_; +} + bool TestWebContents::HasPendingDownloadImage(const GURL& url) { return !pending_image_downloads_[url].empty(); } @@ -376,10 +380,13 @@ int route_id) { } -void TestWebContents::SaveFrameWithHeaders(const GURL& url, - const Referrer& referrer, - const std::string& headers) { +void TestWebContents::SaveFrameWithHeaders( + const GURL& url, + const Referrer& referrer, + const std::string& headers, + const base::string16& suggested_filename) { save_frame_headers_ = headers; + suggested_filename_ = suggested_filename; } void TestWebContents::SetMainFrameMimeType(const std::string& mime_type) {
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h index 579ae85..73361dd 100644 --- a/content/test/test_web_contents.h +++ b/content/test/test_web_contents.h
@@ -85,7 +85,8 @@ NavigationHandle* navigation_handle, scoped_refptr<net::HttpResponseHeaders> response_headers) override; void SetOpener(WebContents* opener) override; - const std::string& GetSaveFrameHeaders() override; + const std::string& GetSaveFrameHeaders() const override; + const base::string16& GetSuggestedFileName() const override; bool HasPendingDownloadImage(const GURL& url) override; bool TestDidDownloadImage( const GURL& url, @@ -170,7 +171,8 @@ void ShowCreatedFullscreenWidget(int process_id, int route_id) override; void SaveFrameWithHeaders(const GURL& url, const Referrer& referrer, - const std::string& headers) override; + const std::string& headers, + const base::string16& suggested_filename) override; RenderViewHostDelegateView* delegate_view_override_; @@ -179,6 +181,7 @@ int expect_set_history_offset_and_length_history_offset_; int expect_set_history_offset_and_length_history_length_; std::string save_frame_headers_; + base::string16 suggested_filename_; // Map keyed by image URL. Values are <id, callback> pairs. std::map<GURL, std::list<std::pair<int, ImageDownloadCallback>>> pending_image_downloads_;
diff --git a/docs/linux_chromium_packages.md b/docs/linux_chromium_packages.md index 8df344b7..775d440a6 100644 --- a/docs/linux_chromium_packages.md +++ b/docs/linux_chromium_packages.md
@@ -17,6 +17,7 @@ | ALT Linux | Andrey Cherepanov (Андрей Черепанов) `cas@altlinux.org` | http://packages.altlinux.org/en/Sisyphus/srpms/chromium | http://git.altlinux.org/gears/c/chromium.git?a=tree | | Mageia | Dexter Morgan `dmorgan@mageia.org` | http://svnweb.mageia.org/packages/cauldron/chromium-browser-stable/current/SPECS/ | http://svnweb.mageia.org/packages/cauldron/chromium-browser-stable/current/SOURCES/ | | NixOS | aszlig `"^[0-9]+$"@regexmail.net` | http://hydra.nixos.org/search?query=pkgs.chromium | https://github.com/NixOS/nixpkgs/tree/master/pkgs/applications/networking/browsers/chromium | +| OpenMandriva | Bernhard Rosenkraenzer `bero@lindev.ch` | n/a | https://github.com/OpenMandrivaAssociation/chromium-browser-stable https://github.com/OpenMandrivaAssociation/chromium-browser-beta https://github.com/OpenMandrivaAssociation/chromium-browser-dev | | Fedora | Tom Callaway `tcallawa@redhat.com` | https://src.fedoraproject.org/rpms/chromium/ | https://src.fedoraproject.org/rpms/chromium/tree/master | | Yocto | Raphael Kubo da Costa `raphael.kubo.da.costa@intel.com` | https://github.com/OSSystems/meta-browser | https://github.com/OSSystems/meta-browser/tree/master/recipes-browser/chromium/files |
diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn index bf9ba62..905631c 100644 --- a/extensions/BUILD.gn +++ b/extensions/BUILD.gn
@@ -118,8 +118,6 @@ "test/logging_timer.h", "test/result_catcher.cc", "test/result_catcher.h", - "test/test_content_browser_client.cc", - "test/test_content_browser_client.h", "test/test_content_utility_client.cc", "test/test_content_utility_client.h", "test/test_extension_dir.cc",
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index d1f0abef..58ab8cf 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1289,6 +1289,7 @@ WEBRTCLOGGINGPRIVATE_STARTEVENTLOGGING, VIRTUALKEYBOARDPRIVATE_SETCONTAINERBEHAVIOR, QUICKUNLOCKPRIVATE_GETAUTHTOKEN, + QUICKUNLOCKPRIVATE_SETLOCKSCREENENABLED, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/browser/extensions_test.cc b/extensions/browser/extensions_test.cc index c527c15..ef10b04a 100644 --- a/extensions/browser/extensions_test.cc +++ b/extensions/browser/extensions_test.cc
@@ -9,14 +9,12 @@ #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service_factory.h" #include "components/prefs/testing_pref_store.h" -#include "content/public/browser/content_browser_client.h" #include "content/public/common/content_client.h" #include "content/public/test/test_browser_context.h" #include "extensions/browser/extension_pref_value_map.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_prefs_factory.h" #include "extensions/browser/test_extensions_browser_client.h" -#include "extensions/test/test_content_browser_client.h" #include "extensions/test/test_content_utility_client.h" namespace { @@ -47,7 +45,6 @@ // posted tasks may use them. rvh_test_enabler_.reset(); thread_bundle_.reset(); - content::SetBrowserClientForTesting(nullptr); content::SetUtilityClientForTesting(nullptr); } @@ -59,7 +56,6 @@ } void ExtensionsTest::SetUp() { - content_browser_client_ = std::make_unique<TestContentBrowserClient>(); content_utility_client_ = std::make_unique<TestContentUtilityClient>(); browser_context_ = std::make_unique<content::TestBrowserContext>(); incognito_context_ = CreateTestIncognitoContext(); @@ -70,7 +66,6 @@ } extensions_browser_client_->SetMainContext(browser_context_.get()); - content::SetBrowserClientForTesting(content_browser_client_.get()); content::SetUtilityClientForTesting(content_utility_client_.get()); ExtensionsBrowserClient::Set(extensions_browser_client_.get()); extensions_browser_client_->set_extension_system_factory(
diff --git a/extensions/browser/extensions_test.h b/extensions/browser/extensions_test.h index c488858..c6cb8b1 100644 --- a/extensions/browser/extensions_test.h +++ b/extensions/browser/extensions_test.h
@@ -19,7 +19,6 @@ namespace content { class BrowserContext; -class ContentBrowserClient; class ContentUtilityClient; class RenderViewHostTestEnabler; } @@ -71,7 +70,6 @@ private: content::TestContentClientInitializer content_client_initializer_; - std::unique_ptr<content::ContentBrowserClient> content_browser_client_; std::unique_ptr<content::ContentUtilityClient> content_utility_client_; std::unique_ptr<content::BrowserContext> browser_context_; std::unique_ptr<content::BrowserContext> incognito_context_;
diff --git a/extensions/common/api/API_OWNERS b/extensions/common/api/API_OWNERS index aabb0dd..9853e49 100644 --- a/extensions/common/api/API_OWNERS +++ b/extensions/common/api/API_OWNERS
@@ -4,3 +4,4 @@ # For Chrome OS apps APIs. tbarzic@chromium.org +stevenjb@chromium.org
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json index 24ba9fd2..5c57352 100644 --- a/extensions/common/api/_api_features.json +++ b/extensions/common/api/_api_features.json
@@ -201,7 +201,8 @@ "chrome://chrome-signin/*", "chrome://media-router/*", "chrome://mobilesetup/*", - "chrome://oobe/*" + "chrome://oobe/*", + "chrome://assistant-optin/*" ] } ], @@ -558,7 +559,8 @@ "chrome://chrome-signin/*", "chrome://media-router/*", "chrome://mobilesetup/*", - "chrome://oobe/*" + "chrome://oobe/*", + "chrome://assistant-optin/*" ] }], "webViewInternal": [{ @@ -573,7 +575,8 @@ "chrome://chrome-signin/*", "chrome://media-router/*", "chrome://mobilesetup/*", - "chrome://oobe/*" + "chrome://oobe/*", + "chrome://assistant-optin/*" ] }], "webViewRequest": [{ @@ -586,7 +589,8 @@ "chrome://chrome-signin/*", "chrome://media-router/*", "chrome://mobilesetup/*", - "chrome://oobe/*" + "chrome://oobe/*", + "chrome://assistant-optin/*" ] }] }
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn index 01f8a88..d71fb85 100644 --- a/extensions/shell/BUILD.gn +++ b/extensions/shell/BUILD.gn
@@ -423,6 +423,8 @@ mac_framework_bundle("app_shell_framework") { testonly = true output_name = "App Shell Framework" + framework_version = "A" + framework_contents = [ "Resources" ] sources = [ "app/shell_main_mac.cc", "app/shell_main_mac.h",
diff --git a/extensions/test/data/OWNERS b/extensions/test/data/OWNERS deleted file mode 100644 index d13324a..0000000 --- a/extensions/test/data/OWNERS +++ /dev/null
@@ -1,4 +0,0 @@ -* - -per-file extensions_test_content_utility_manifest_overlay.json=set noparent -per-file extensions_test_content_utility_manifest_overlay.json=file://ipc/SECURITY_OWNERS
diff --git a/extensions/test/data/extensions_test_content_utility_manifest_overlay.json b/extensions/test/data/extensions_test_content_utility_manifest_overlay.json deleted file mode 100644 index 21285652..0000000 --- a/extensions/test/data/extensions_test_content_utility_manifest_overlay.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "name": "content_utility", - "interface_provider_specs": { - "service_manager:connector": { - "provides": { - "browser": [ - "extensions::mojom::ExtensionUnpacker", - "extensions::mojom::ManifestParser" - ] - } - } - } -}
diff --git a/extensions/test/test_content_browser_client.cc b/extensions/test/test_content_browser_client.cc deleted file mode 100644 index 4b83f11..0000000 --- a/extensions/test/test_content_browser_client.cc +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "extensions/test/test_content_browser_client.h" - -#include "base/files/file_util.h" -#include "base/json/json_reader.h" -#include "base/path_service.h" -#include "base/values.h" -#include "content/public/common/service_names.mojom.h" -#include "extensions/common/extension_paths.h" - -namespace extensions { - -TestContentBrowserClient::TestContentBrowserClient() = default; - -TestContentBrowserClient::~TestContentBrowserClient() = default; - -std::unique_ptr<base::Value> -TestContentBrowserClient::GetServiceManifestOverlay(base::StringPiece name) { - if (name != content::mojom::kUtilityServiceName) - return nullptr; - - base::FilePath extensions_test_data_dir; - CHECK(base::PathService::Get(DIR_TEST_DATA, &extensions_test_data_dir)); - - std::string contents; - CHECK(base::ReadFileToString( - extensions_test_data_dir.AppendASCII( - "extensions_test_content_utility_manifest_overlay.json"), - &contents)); - - return base::JSONReader::Read(contents); -} - -} // namespace extensions
diff --git a/extensions/test/test_content_browser_client.h b/extensions/test/test_content_browser_client.h deleted file mode 100644 index 9ae3f01..0000000 --- a/extensions/test/test_content_browser_client.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef EXTENSIONS_TEST_TEST_CONTENT_BROWSER_CLIENT_H_ -#define EXTENSIONS_TEST_TEST_CONTENT_BROWSER_CLIENT_H_ - -#include <memory> - -#include "base/strings/string_piece.h" -#include "content/public/browser/content_browser_client.h" - -namespace base { -class Value; -} - -namespace extensions { - -class TestContentBrowserClient : public content::ContentBrowserClient { - public: - TestContentBrowserClient(); - ~TestContentBrowserClient() override; - - // content::ContentBrowserClient: - std::unique_ptr<base::Value> GetServiceManifestOverlay( - base::StringPiece name) override; -}; - -} // namespace extensions - -#endif // EXTENSIONS_TEST_TEST_CONTENT_BROWSER_CLIENT_H_
diff --git a/google_apis/gcm/BUILD.gn b/google_apis/gcm/BUILD.gn index 298b5de..0a6ccbb 100644 --- a/google_apis/gcm/BUILD.gn +++ b/google_apis/gcm/BUILD.gn
@@ -67,6 +67,7 @@ "//base", "//base/third_party/dynamic_annotations", "//net", + "//services/network:network_service", "//third_party/leveldatabase", "//url", ]
diff --git a/google_apis/gcm/DEPS b/google_apis/gcm/DEPS index 047dc156..a044cbe8 100644 --- a/google_apis/gcm/DEPS +++ b/google_apis/gcm/DEPS
@@ -10,4 +10,5 @@ "+google", # For third_party/protobuf/src. "+net", "+third_party/leveldatabase", + "+services/network", ]
diff --git a/google_apis/gcm/engine/connection_factory_impl.cc b/google_apis/gcm/engine/connection_factory_impl.cc index fd11a5f32..31942da 100644 --- a/google_apis/gcm/engine/connection_factory_impl.cc +++ b/google_apis/gcm/engine/connection_factory_impl.cc
@@ -24,6 +24,7 @@ #include "net/socket/client_socket_handle.h" #include "net/socket/client_socket_pool_manager.h" #include "net/ssl/ssl_config_service.h" +#include "services/network/proxy_resolving_client_socket.h" namespace gcm { @@ -61,9 +62,6 @@ backoff_policy_(backoff_policy), gcm_network_session_(gcm_network_session), http_network_session_(http_network_session), - net_log_( - net::NetLogWithSource::Make(net_log, net::NetLogSourceType::SOCKET)), - proxy_resolve_request_(NULL), connecting_(false), waiting_for_backoff_(false), waiting_for_network_online_(false), @@ -79,11 +77,6 @@ ConnectionFactoryImpl::~ConnectionFactoryImpl() { CloseSocket(); net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); - if (proxy_resolve_request_) { - gcm_network_session_->proxy_resolution_service()->CancelRequest( - proxy_resolve_request_); - proxy_resolve_request_ = NULL; - } } void ConnectionFactoryImpl::Initialize( @@ -299,11 +292,11 @@ } net::IPEndPoint ConnectionFactoryImpl::GetPeerIP() { - if (!socket_handle_.socket()) + if (!socket_) return net::IPEndPoint(); net::IPEndPoint ip_endpoint; - int result = socket_handle_.socket()->GetPeerAddress(&ip_endpoint); + int result = socket_->GetPeerAddress(&ip_endpoint); if (result != net::OK) return net::IPEndPoint(); @@ -318,7 +311,7 @@ void ConnectionFactoryImpl::StartConnection() { DCHECK(!IsEndpointReachable()); // TODO(zea): Make this a dcheck again. crbug.com/462319 - CHECK(!socket_handle_.socket()); + CHECK(!socket_); // TODO(zea): if the network is offline, don't attempt to connect. // See crbug.com/396687 @@ -327,13 +320,14 @@ GURL current_endpoint = GetCurrentEndpoint(); recorder_->RecordConnectionInitiated(current_endpoint.host()); UpdateFromHttpNetworkSession(); - int status = gcm_network_session_->proxy_resolution_service()->ResolveProxy( - current_endpoint, std::string(), &proxy_info_, - base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, - weak_ptr_factory_.GetWeakPtr()), - &proxy_resolve_request_, NULL, net_log_); + net::SSLConfig ssl_config; + gcm_network_session_->ssl_config_service()->GetSSLConfig(&ssl_config); + socket_ = std::make_unique<network::ProxyResolvingClientSocket>( + gcm_network_session_, ssl_config, current_endpoint, true /*use_tls*/); + int status = socket_->Connect(base::BindRepeating( + &ConnectionFactoryImpl::OnConnectDone, weak_ptr_factory_.GetWeakPtr())); if (status != net::ERR_IO_PENDING) - OnProxyResolveDone(status); + OnConnectDone(status); } void ConnectionFactoryImpl::InitHandler() { @@ -381,8 +375,7 @@ "but does not have any effect on other Google Cloud messages." )"); - connection_handler_->Init(login_request, traffic_annotation, - socket_handle_.socket()); + connection_handler_->Init(login_request, traffic_annotation, socket_.get()); } std::unique_ptr<net::BackoffEntry> ConnectionFactoryImpl::CreateBackoffEntry( @@ -405,15 +398,8 @@ } void ConnectionFactoryImpl::OnConnectDone(int result) { + DCHECK_NE(net::ERR_IO_PENDING, result); if (result != net::OK) { - // If the connection fails, try another proxy. - result = ReconsiderProxyAfterError(result); - // ReconsiderProxyAfterError either returns an error (in which case it is - // not reconsidering a proxy) or returns ERR_IO_PENDING if it is considering - // another proxy. - DCHECK_NE(result, net::OK); - if (result == net::ERR_IO_PENDING) - return; // Proxy reconsideration pending. Return. LOG(ERROR) << "Failed to connect to MCS endpoint with error " << result; UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", false); recorder_->RecordConnectionFailure(result); @@ -436,9 +422,6 @@ UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", true); UMA_HISTOGRAM_COUNTS("GCM.ConnectionEndpoint", next_endpoint_); - UMA_HISTOGRAM_BOOLEAN("GCM.ConnectedViaProxy", - !(proxy_info_.is_empty() || proxy_info_.is_direct())); - ReportSuccessfulProxyConnection(); recorder_->RecordConnectionSuccess(); // Reset the endpoint back to the default. @@ -478,106 +461,15 @@ listener_->OnConnected(GetCurrentEndpoint(), GetPeerIP()); } -// This has largely been copied from -// HttpStreamFactoryImpl::Job::DoResolveProxyComplete. This should be -// refactored into some common place. -void ConnectionFactoryImpl::OnProxyResolveDone(int status) { - proxy_resolve_request_ = NULL; - DVLOG(1) << "Proxy resolution status: " << status; - - DCHECK_NE(status, net::ERR_IO_PENDING); - if (status == net::OK) { - // Remove unsupported proxies from the list. - proxy_info_.RemoveProxiesWithoutScheme( - net::ProxyServer::SCHEME_DIRECT | - net::ProxyServer::SCHEME_HTTP | net::ProxyServer::SCHEME_HTTPS | - net::ProxyServer::SCHEME_SOCKS4 | net::ProxyServer::SCHEME_SOCKS5); - - if (proxy_info_.is_empty()) { - // No proxies/direct to choose from. This happens when we don't support - // any of the proxies in the returned list. - status = net::ERR_NO_SUPPORTED_PROXIES; - } - } - - if (status != net::OK) { - // Failed to resolve proxy. Retry later. - OnConnectDone(status); - return; - } - - DVLOG(1) << "Resolved proxy with PAC:" << proxy_info_.ToPacString(); - - net::SSLConfig ssl_config; - gcm_network_session_->ssl_config_service()->GetSSLConfig(&ssl_config); - status = net::InitSocketHandleForTlsConnect( - net::HostPortPair::FromURL(GetCurrentEndpoint()), - gcm_network_session_, - proxy_info_, - ssl_config, - ssl_config, - net::PRIVACY_MODE_DISABLED, - net_log_, - &socket_handle_, - base::Bind(&ConnectionFactoryImpl::OnConnectDone, - weak_ptr_factory_.GetWeakPtr())); - if (status != net::ERR_IO_PENDING) - OnConnectDone(status); -} - -// This has largely been copied from -// HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError. This should be -// refactored into some common place. -// This method reconsiders the proxy on certain errors. If it does reconsider -// a proxy it always returns ERR_IO_PENDING and posts a call to -// OnProxyResolveDone with the result of the reconsideration. -int ConnectionFactoryImpl::ReconsiderProxyAfterError(int error) { - DCHECK(!proxy_resolve_request_); - DCHECK_NE(error, net::OK); - DCHECK_NE(error, net::ERR_IO_PENDING); - - // Check if the error was a proxy failure. - if (!net::CanFalloverToNextProxy(&error)) - return error; - - net::SSLConfig ssl_config; - gcm_network_session_->ssl_config_service()->GetSSLConfig(&ssl_config); - if (proxy_info_.is_https() && ssl_config.send_client_cert) { - gcm_network_session_->ssl_client_auth_cache()->Remove( - proxy_info_.proxy_server().host_port_pair()); - } - - if (!proxy_info_.Fallback(error, net_log_)) { - // There was nothing left to fall-back to, so fail the transaction - // with the last connection error we got. - return error; - } - - CloseSocket(); - - // If there is new proxy info, post OnProxyResolveDone to retry it. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, - weak_ptr_factory_.GetWeakPtr(), net::OK)); - - return net::ERR_IO_PENDING; -} - -void ConnectionFactoryImpl::ReportSuccessfulProxyConnection() { - if (gcm_network_session_ && gcm_network_session_->proxy_resolution_service()) - gcm_network_session_->proxy_resolution_service()->ReportSuccess(proxy_info_, - NULL); -} - void ConnectionFactoryImpl::CloseSocket() { // The connection handler needs to be reset, else it'll attempt to keep using // the destroyed socket. if (connection_handler_) connection_handler_->Reset(); - if (socket_handle_.socket() && socket_handle_.socket()->IsConnected()) - socket_handle_.socket()->Disconnect(); - socket_handle_.Reset(); + if (socket_) + socket_->Disconnect(); + socket_ = nullptr; } void ConnectionFactoryImpl::UpdateFromHttpNetworkSession() {
diff --git a/google_apis/gcm/engine/connection_factory_impl.h b/google_apis/gcm/engine/connection_factory_impl.h index 13885460..2b718aa 100644 --- a/google_apis/gcm/engine/connection_factory_impl.h +++ b/google_apis/gcm/engine/connection_factory_impl.h
@@ -18,11 +18,12 @@ #include "net/base/backoff_entry.h" #include "net/base/network_change_notifier.h" #include "net/log/net_log_with_source.h" -#include "net/proxy_resolution/proxy_info.h" -#include "net/proxy_resolution/proxy_resolution_service.h" -#include "net/socket/client_socket_handle.h" #include "url/gurl.h" +namespace network { +class ProxyResolvingClientSocket; +} + namespace net { class HttpNetworkSession; class NetLog; @@ -123,12 +124,6 @@ // handshake. On connection/handshake failure, goes into backoff. void ConnectImpl(); - // Proxy resolution and connection functions. - void OnProxyResolveDone(int status); - void OnProxyConnectDone(int status); - int ReconsiderProxyAfterError(int error); - void ReportSuccessfulProxyConnection(); - // Closes the local socket if one is present, and resets connection handler. void CloseSocket(); @@ -157,15 +152,8 @@ // HTTP Network session. If set, is used for extracting proxy auth // credentials. If nullptr, is ignored. net::HttpNetworkSession* http_network_session_; - // Net log to use in connection attempts. - net::NetLogWithSource net_log_; - // The current proxy resolution request, if one exists. Owned by the proxy - // service. - net::ProxyResolutionService::Request* proxy_resolve_request_; - // The current proxy info. - net::ProxyInfo proxy_info_; // The handle to the socket for the current connection, if one exists. - net::ClientSocketHandle socket_handle_; + std::unique_ptr<network::ProxyResolvingClientSocket> socket_; // Current backoff entry. std::unique_ptr<net::BackoffEntry> backoff_entry_; // Backoff entry from previous connection attempt. Updated on each login
diff --git a/gpu/PRESUBMIT.py b/gpu/PRESUBMIT.py index 0b04675f..8e1e112b 100644 --- a/gpu/PRESUBMIT.py +++ b/gpu/PRESUBMIT.py
@@ -24,7 +24,7 @@ cl, [ 'luci.chromium.try:linux_optional_gpu_tests_rel', - 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'luci.chromium.try:mac_optional_gpu_tests_rel', 'master.tryserver.chromium.win:win_optional_gpu_tests_rel', 'master.tryserver.chromium.android:android_optional_gpu_tests_rel', ],
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn index b04e255f..374093b 100644 --- a/ios/chrome/browser/ui/authentication/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -54,7 +54,6 @@ "//ios/chrome/browser/tabs", "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/alert_coordinator", - "//ios/chrome/browser/ui/collection_view", "//ios/chrome/browser/ui/collection_view/cells", "//ios/chrome/browser/ui/colors", "//ios/chrome/browser/ui/commands", @@ -70,6 +69,9 @@ "//ui/gfx", "//url", ] + public_deps = [ + "//ios/chrome/browser/ui/collection_view", + ] if (is_chrome_branded) { deps += [ "resources:signin_promo_logo_chrome_color" ] } else { @@ -118,6 +120,7 @@ "account_control_item_unittest.mm", "authentication_flow_unittest.mm", "authentication_ui_util_unittest.mm", + "chrome_signin_view_controller_unittest.mm", "re_signin_infobar_delegate_unittest.mm", "signed_in_accounts_view_controller_unittest.mm", "signin_promo_item_unittest.mm", @@ -129,19 +132,27 @@ ":authentication_ui", "//base", "//base/test:test_support", + "//components/consent_auditor", "//components/pref_registry", "//components/sync_preferences", "//components/sync_preferences:test_support", + "//components/version_info", + "//ios/chrome/app/strings:ios_chromium_strings_grit", + "//ios/chrome/app/strings:ios_strings_grit", + "//ios/chrome/browser", "//ios/chrome/browser/browser_state:test_support", + "//ios/chrome/browser/consent_auditor", "//ios/chrome/browser/infobars", "//ios/chrome/browser/prefs:browser_prefs", "//ios/chrome/browser/signin", "//ios/chrome/browser/signin:test_support", + "//ios/chrome/browser/sync", "//ios/chrome/browser/ui/colors", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/signin_interaction/public", "//ios/chrome/test:test_support", "//ios/public/provider/chrome/browser/signin:test_support", + "//ios/testing:ios_test_support", "//ios/third_party/material_components_ios", "//ios/web/public/test", "//testing/gtest",
diff --git a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h index 31038901..6563388e 100644 --- a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h +++ b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h
@@ -7,8 +7,10 @@ #import <UIKit/UIKit.h> +#include "base/timer/timer.h" #include "components/signin/core/browser/signin_metrics.h" #import "ios/chrome/browser/signin/constants.h" +#include "ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.h" @protocol ApplicationCommands; @class ChromeIdentity; @@ -18,6 +20,9 @@ class ChromeBrowserState; } // namespace ios +using TimerGeneratorBlock = + std::unique_ptr<base::Timer> (^)(bool retain_user_task, bool is_repeating); + @protocol ChromeSigninViewControllerDelegate<NSObject> // Informs the delegate that a sign-in operation will start in |controller|. @@ -59,7 +64,8 @@ // ChromeSigninViewController is a view controller that handles all the // sign-in UI flow. -@interface ChromeSigninViewController : UIViewController +@interface ChromeSigninViewController + : UIViewController<SigninConfirmationViewControllerDelegate> @property(nonatomic, weak) id<ChromeSigninViewControllerDelegate> delegate; @@ -69,6 +75,9 @@ @property(nonatomic, weak, readonly) id<ApplicationCommands> dispatcher; +// Sign-in conformation view controller. +@property(nonatomic, readonly) SigninConfirmationViewController* confirmationVC; + // Designated initializer. // * |browserState| is the current browser state. // * |accessPoint| represents the access point that initiated the sign-in. @@ -107,4 +116,12 @@ @end +// Exposes methods for testing. +@interface ChromeSigninViewController (Testing) + +// Timer generator. Should stay nil to use the default timer class: base::Timer. +@property(nonatomic, copy) TimerGeneratorBlock timerGenerator; + +@end + #endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_CHROME_SIGNIN_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm index ad75236..39f2238 100644 --- a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm
@@ -17,7 +17,6 @@ #include "base/metrics/user_metrics.h" #import "base/strings/sys_string_conversions.h" #include "base/timer/elapsed_timer.h" -#include "base/timer/timer.h" #include "components/consent_auditor/consent_auditor.h" #include "components/signin/core/browser/signin_metrics.h" #include "components/strings/grit/components_strings.h" @@ -118,7 +117,6 @@ ChromeIdentityInteractionManagerDelegate, ChromeIdentityServiceObserver, SigninAccountSelectorViewControllerDelegate, - SigninConfirmationViewControllerDelegate, MDCActivityIndicatorDelegate> @property(nonatomic, strong) ChromeIdentity* selectedIdentity; @@ -129,6 +127,7 @@ __weak id<ChromeSigninViewControllerDelegate> _delegate; std::unique_ptr<ChromeIdentityServiceObserverBridge> _identityServiceObserver; ChromeIdentity* _selectedIdentity; + TimerGeneratorBlock _timerGenerator; // Authentication AlertCoordinator* _alertCoordinator; @@ -167,6 +166,7 @@ @synthesize delegate = _delegate; @synthesize shouldClearData = _shouldClearData; @synthesize dispatcher = _dispatcher; +@synthesize confirmationVC = _confirmationVC; - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState accessPoint:(signin_metrics::AccessPoint)accessPoint @@ -603,7 +603,16 @@ [strongSelf->_activityIndicator stopAnimating]; strongSelf->_leavingPendingStateTimer.reset(); }; - _leavingPendingStateTimer.reset(new base::Timer(false, false)); + const bool retain_user_task = false; + const bool is_repeating = false; + if (self.timerGenerator) { + _leavingPendingStateTimer = + self.timerGenerator(retain_user_task, is_repeating); + DCHECK(_leavingPendingStateTimer); + } else { + _leavingPendingStateTimer = + std::make_unique<base::Timer>(retain_user_task, is_repeating); + } _leavingPendingStateTimer->Start(FROM_HERE, remainingTime, base::BindBlockArc(completionBlock)); } @@ -963,3 +972,15 @@ } @end + +@implementation ChromeSigninViewController (Testing) + +- (TimerGeneratorBlock)timerGenerator { + return _timerGenerator; +} + +- (void)setTimerGenerator:(TimerGeneratorBlock)timerGenerator { + _timerGenerator = [timerGenerator copy]; +} + +@end
diff --git a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller_unittest.mm b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller_unittest.mm new file mode 100644 index 0000000..50c43226 --- /dev/null +++ b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller_unittest.mm
@@ -0,0 +1,283 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h" + +#include "base/memory/ptr_util.h" +#import "base/test/ios/wait_util.h" +#include "base/timer/mock_timer.h" +#include "components/consent_auditor/consent_auditor.h" +#include "components/version_info/version_info.h" +#include "ios/chrome/browser/application_context.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#include "ios/chrome/browser/consent_auditor/consent_auditor_factory.h" +#import "ios/chrome/browser/signin/authentication_service_factory.h" +#import "ios/chrome/browser/signin/authentication_service_fake.h" +#include "ios/chrome/browser/sync/ios_user_event_service_factory.h" +#include "ios/chrome/grit/ios_chromium_strings.h" +#include "ios/chrome/grit/ios_strings.h" +#import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h" +#import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h" +#import "ios/testing/wait_util.h" +#include "ios/web/public/test/test_web_thread_bundle.h" +#import "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" +#include "third_party/ocmock/gtest_support.h" +#include "ui/base/l10n/l10n_util_mac.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +// Fake consent auditor used for the tests. +class FakeConsentAuditor : public consent_auditor::ConsentAuditor { + public: + static std::unique_ptr<KeyedService> CreateInstance( + web::BrowserState* context) { + ios::ChromeBrowserState* ios_context = + ios::ChromeBrowserState::FromBrowserState(context); + syncer::UserEventService* const user_event_service = + IOSUserEventServiceFactory::GetForBrowserState(ios_context); + return std::make_unique<FakeConsentAuditor>( + ios_context->GetPrefs(), user_event_service, + version_info::GetVersionNumber(), + GetApplicationContext()->GetApplicationLocale()); + } + + FakeConsentAuditor(PrefService* pref_service, + syncer::UserEventService* user_event_service, + const std::string& app_version, + const std::string& app_locale) + : ConsentAuditor(pref_service, + user_event_service, + app_version, + app_locale) {} + ~FakeConsentAuditor() override {} + + void RecordGaiaConsent(consent_auditor::Feature feature, + const std::vector<int>& description_grd_ids, + int confirmation_string_id, + consent_auditor::ConsentStatus status) override { + feature_ = feature; + recorded_ids_ = description_grd_ids; + confirmation_string_id_ = confirmation_string_id; + status_ = status; + } + + consent_auditor::Feature feature() const { return feature_; } + const std::vector<int>& recorded_ids() const { return recorded_ids_; } + int confirmation_string_id() const { return confirmation_string_id_; } + consent_auditor::ConsentStatus status() const { return status_; } + + private: + consent_auditor::Feature feature_; + std::vector<int> recorded_ids_; + int confirmation_string_id_ = -1; + consent_auditor::ConsentStatus status_; + + DISALLOW_COPY_AND_ASSIGN(FakeConsentAuditor); +}; + +// These tests verify that Chrome correctly records user's consent to Chrome +// Sync, which is a GDPR requirement. None of those tests should be turned off. +// If one of those tests fails, one of the following methods should be updated +// with the added or removed strings: +// - ExpectedConsentStringIds() +// - WhiteListLocalizedStrings() +class ChromeSigninViewControllerTest : public PlatformTest { + protected: + void SetUp() override { + PlatformTest::SetUp(); + identity_ = [FakeChromeIdentity identityWithEmail:@"foo1@gmail.com" + gaiaID:@"foo1ID" + name:@"Fake Foo 1"]; + // Setup services. + TestChromeBrowserState::Builder builder; + builder.AddTestingFactory( + AuthenticationServiceFactory::GetInstance(), + AuthenticationServiceFake::CreateAuthenticationService); + builder.AddTestingFactory(ConsentAuditorFactory::GetInstance(), + FakeConsentAuditor::CreateInstance); + context_ = builder.Build(); + ios::FakeChromeIdentityService* identity_service = + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider(); + identity_service->AddIdentity(identity_); + fake_consent_auditor_ = static_cast<FakeConsentAuditor*>( + ConsentAuditorFactory::GetForBrowserState(context_.get())); + // Setup view controller. + vc_ = [[ChromeSigninViewController alloc] + initWithBrowserState:context_.get() + accessPoint:signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS + promoAction:signin_metrics::PromoAction:: + PROMO_ACTION_WITH_DEFAULT + signInIdentity:identity_ + dispatcher:nil]; + __block base::MockTimer* mock_timer_ptr = nullptr; + vc_.timerGenerator = ^std::unique_ptr<base::Timer>(bool retain_user_task, + bool is_repeating) { + auto mock_timer = + std::make_unique<base::MockTimer>(retain_user_task, is_repeating); + mock_timer_ptr = mock_timer.get(); + return mock_timer; + }; + UIScreen* screen = [UIScreen mainScreen]; + UIWindow* window = [[UIWindow alloc] initWithFrame:screen.bounds]; + [window makeKeyAndVisible]; + [window addSubview:[vc_ view]]; + ASSERT_TRUE(mock_timer_ptr); + mock_timer_ptr->Fire(); + window_ = window; + } + + // Adds in |string_set|, all the strings displayed by |view| and its subviews, + // recursively. + static void AddStringsFromView(NSMutableSet<NSString*>* string_set, + UIView* view) { + for (UIView* subview in view.subviews) + AddStringsFromView(string_set, subview); + if ([view isKindOfClass:[UIButton class]]) { + UIButton* button = static_cast<UIButton*>(view); + if (button.currentTitle) + [string_set addObject:button.currentTitle]; + } else if ([view isKindOfClass:[UILabel class]]) { + UILabel* label = static_cast<UILabel*>(view); + if (label.text) + [string_set addObject:label.text]; + } else { + NSString* view_name = NSStringFromClass([view class]); + // Views that don't display strings. + NSArray* other_views = @[ + @"AccountControlCell", @"CollectionViewFooterCell", @"UIButtonLabel", + @"UICollectionView", @"UICollectionViewControllerWrapperView", + @"UIImageView", @"UIView", @"MDCActivityIndicator", @"MDCButtonBar", + @"MDCFlexibleHeaderView", @"MDCHeaderStackView", @"MDCInkView", + @"MDCNavigationBar" + ]; + // If this test fails, the unknown class should be added in other_views if + // it doesn't display any strings, otherwise the strings diplay by this + // class should be added in string_set. + EXPECT_TRUE([other_views containsObject:view_name]); + } + } + + // Returns the set of strings displayed on the screen based on the views + // displayed by the . + NSSet<NSString*>* LocalizedStringOnScreen() const { + NSMutableSet* string_set = [NSMutableSet set]; + AddStringsFromView(string_set, vc_.view); + return string_set; + } + + // Returns a localized string based on the string id. + NSString* LocalizedStringFromID(int string_id) const { + NSString* string = l10n_util::GetNSString(string_id); + string = [string stringByReplacingOccurrencesOfString:@"BEGIN_LINK" + withString:@""]; + string = [string stringByReplacingOccurrencesOfString:@"END_LINK" + withString:@""]; + return string; + } + + // Returns all the strings on screen that should be part of the user consent + // and part of the white list strings. + NSSet<NSString*>* LocalizedExpectedStringsOnScreen() const { + const std::vector<int>& string_ids = ExpectedConsentStringIds(); + NSMutableSet<NSString*>* set = [NSMutableSet set]; + for (auto it = string_ids.begin(); it != string_ids.end(); ++it) { + [set addObject:LocalizedStringFromID(*it)]; + } + [set unionSet:WhiteListLocalizedStrings()]; + return set; + } + + // Returns the list of string id that should be given to RecordGaiaConsent() + // then the consent is given. The list is ordered according to the position + // on the screen. + const std::vector<int> ExpectedConsentStringIds() const { + return { + IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_SYNC_TITLE, + IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_SYNC_DESCRIPTION, + IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_SERVICES_TITLE, + IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_SERVICES_DESCRIPTION, + IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OPEN_SETTINGS, + }; + } + + // Returns the white list of strings that can be displayed on screen but + // should not be part of ExpectedConsentStringIds(). + NSSet<NSString*>* WhiteListLocalizedStrings() const { + return [NSSet setWithObjects:@"Hi, Fake Foo 1", @"foo1@gmail.com", + @"OK, GOT IT", @"UNDO", nil]; + } + + // Waits until all expected strings are on the screen. + void WaitAndExpectAllStringsOnScreen() { + ConditionBlock condition = ^bool() { + return [LocalizedStringOnScreen() + isEqual:LocalizedExpectedStringsOnScreen()]; + }; + EXPECT_TRUE(testing::WaitUntilConditionOrTimeout(10, condition)); + } + + web::TestWebThreadBundle thread_bundle_; + std::unique_ptr<TestChromeBrowserState> context_; + FakeChromeIdentity* identity_; + UIWindow* window_; + ChromeSigninViewController* vc_; + FakeConsentAuditor* fake_consent_auditor_; +}; + +// Tests that all strings on the screen are either part of the consent string +// list defined in FakeConsentAuditor::ExpectedConsentStringIds()), or are part +// of the white list strings defined in +// FakeConsentAuditor::WhiteListLocalizedStrings(). +TEST_F(ChromeSigninViewControllerTest, TestAllStrings) { + WaitAndExpectAllStringsOnScreen(); +} + +// Tests when the user taps on "OK GOT IT", that RecordGaiaConsent() is called +// with the expected list of string ids, and +// IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON for the confirmation grd +// id. +TEST_F(ChromeSigninViewControllerTest, TestConsentWithOKGOTIT) { + WaitAndExpectAllStringsOnScreen(); + [vc_.primaryButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + const std::vector<int>& recorded_ids = fake_consent_auditor_->recorded_ids(); + EXPECT_EQ(ExpectedConsentStringIds(), recorded_ids); + EXPECT_EQ(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON, + fake_consent_auditor_->confirmation_string_id()); + EXPECT_EQ(consent_auditor::ConsentStatus::GIVEN, + fake_consent_auditor_->status()); + EXPECT_EQ(consent_auditor::Feature::CHROME_SYNC, + fake_consent_auditor_->feature()); +} + +// Tests that RecordGaiaConsent() is not called when the user taps on UNDO. +TEST_F(ChromeSigninViewControllerTest, TestRefusingConsent) { + WaitAndExpectAllStringsOnScreen(); + [vc_.secondaryButton sendActionsForControlEvents:UIControlEventTouchUpInside]; + const std::vector<int>& recorded_ids = fake_consent_auditor_->recorded_ids(); + EXPECT_EQ(0ul, recorded_ids.size()); + EXPECT_EQ(-1, fake_consent_auditor_->confirmation_string_id()); +} + +// Tests that RecordGaiaConsent() is called with the expected list of string +// ids, and IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OPEN_SETTINGS for the +// confirmation grd id. +TEST_F(ChromeSigninViewControllerTest, TestConsentWithSettings) { + WaitAndExpectAllStringsOnScreen(); + [vc_ signinConfirmationControllerDidTapSettingsLink:vc_.confirmationVC]; + const std::vector<int>& recorded_ids = fake_consent_auditor_->recorded_ids(); + EXPECT_EQ(ExpectedConsentStringIds(), recorded_ids); + EXPECT_EQ(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OPEN_SETTINGS, + fake_consent_auditor_->confirmation_string_id()); + EXPECT_EQ(consent_auditor::ConsentStatus::GIVEN, + fake_consent_auditor_->status()); + EXPECT_EQ(consent_auditor::Feature::CHROME_SYNC, + fake_consent_auditor_->feature()); +} + +} // namespace
diff --git a/ios/chrome/browser/ui/download/download_manager_coordinator.mm b/ios/chrome/browser/ui/download/download_manager_coordinator.mm index e3a0478..301eade 100644 --- a/ios/chrome/browser/ui/download/download_manager_coordinator.mm +++ b/ios/chrome/browser/ui/download/download_manager_coordinator.mm
@@ -22,6 +22,7 @@ #import "ios/chrome/browser/ui/presenters/contained_presenter_delegate.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/web/public/download/download_task.h" +#include "net/base/net_errors.h" #include "net/url_request/url_fetcher_response_writer.h" #include "ui/base/l10n/l10n_util_mac.h" @@ -188,6 +189,9 @@ - (void)downloadManagerViewControllerDidStartDownload: (DownloadManagerViewController*)controller { + if (_downloadTask->GetErrorCode() != net::OK) { + base::RecordAction(base::UserMetricsAction("MobileDownloadRetryDownload")); + } _mediator.StartDowloading(); }
diff --git a/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm b/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm index ff07aa9..3b735d0 100644 --- a/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
@@ -24,6 +24,7 @@ #import "ios/web/public/test/fakes/fake_download_task.h" #import "ios/web/public/test/fakes/test_web_state.h" #include "ios/web/public/test/test_web_thread_bundle.h" +#include "net/base/net_errors.h" #include "net/url_request/url_fetcher_response_writer.h" #include "testing/gtest_mac.h" #include "testing/platform_test.h" @@ -491,6 +492,38 @@ base::FilePath download_dir; ASSERT_TRUE(GetDownloadsDirectory(&download_dir)); EXPECT_TRUE(download_dir.IsParent(file)); + + ASSERT_EQ(0, + user_action_tester_.GetActionCount("MobileDownloadRetryDownload")); +} + +// Tests retrying the download. Verifies that kDownloadManagerRetryDownload UMA +// metric is logged. +TEST_F(DownloadManagerCoordinatorTest, RetryingDownload) { + web::FakeDownloadTask task(GURL(kTestUrl), kTestMimeType); + task.SetSuggestedFilename(base::SysNSStringToUTF16(kTestSuggestedFileName)); + task.SetErrorCode(net::ERR_INTERNET_DISCONNECTED); + web::DownloadTask* task_ptr = &task; + coordinator_.downloadTask = &task; + [coordinator_ start]; + + DownloadManagerViewController* viewController = + base_view_controller_.childViewControllers.firstObject; + ASSERT_EQ([DownloadManagerViewController class], [viewController class]); + @autoreleasepool { + // This call will retain coordinator, which should outlive thread bundle. + [viewController.delegate + downloadManagerViewControllerDidStartDownload:viewController]; + } + + // Starting download is async for model. + ASSERT_TRUE(WaitUntilConditionOrTimeout(testing::kWaitForDownloadTimeout, ^{ + base::RunLoop().RunUntilIdle(); + return task_ptr->GetState() == web::DownloadTask::State::kInProgress; + })); + + ASSERT_EQ(1, + user_action_tester_.GetActionCount("MobileDownloadRetryDownload")); } // Tests that viewController returns correct view controller if coordinator is
diff --git a/ios/chrome/browser/ui/first_run/BUILD.gn b/ios/chrome/browser/ui/first_run/BUILD.gn index 1971620..2424abaf 100644 --- a/ios/chrome/browser/ui/first_run/BUILD.gn +++ b/ios/chrome/browser/ui/first_run/BUILD.gn
@@ -99,6 +99,7 @@ "//ios/chrome/browser/geolocation:test_support", "//ios/chrome/browser/signin", "//ios/chrome/browser/sync", + "//ios/chrome/browser/ui/authentication", "//ios/chrome/browser/ui/authentication:eg_test_support", "//ios/chrome/test/app:test_support", "//ios/chrome/test/earl_grey:test_support",
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_view_controller.mm index e24083c4..35317cb 100644 --- a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_view_controller.mm +++ b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_view_controller.mm
@@ -74,7 +74,7 @@ // Key for saving whether the Recently Closed section is collapsed. NSString* const kRecentlyClosedCollapsedKey = @"RecentlyClosedCollapsed"; // There are 2 static sections before the first SessionSection. -int const kNumberOfSectionsBeforeSessions = 2; +int const kNumberOfSectionsBeforeSessions = 1; // Estimated Table Row height. const CGFloat kEstimatedRowHeight = 56; // The UI displays relative time for up to this number of hours and then @@ -160,14 +160,11 @@ [super loadModel]; [self addRecentlyClosedSection]; - // The other Devices header section is always present regardless if it has any - // items or not. - [self addOtherDevicesSectionHeader]; if (self.sessionState == SessionsSyncUserState::USER_SIGNED_IN_SYNC_ON_WITH_SESSIONS) { [self addSessionSections]; } else { - [self addOtherDevicesItemForState:self.sessionState]; + [self addOtherDevicesSectionForState:self.sessionState]; } } @@ -257,14 +254,11 @@ SessionsSyncUserState previousState = self.sessionState; if (previousState != SessionsSyncUserState::USER_SIGNED_IN_SYNC_ON_WITH_SESSIONS) { - // The previous state was one of the OtherDevices states, remove it to clean - // it up and re-add just the header. + // The previous state was one of the OtherDevices states, remove it. + [self.tableView deleteSections:[self otherDevicesSectionIndexSet] + withRowAnimation:UITableViewRowAnimationNone]; [self.tableViewModel removeSectionWithIdentifier:SectionIdentifierOtherDevices]; - [self addOtherDevicesSectionHeader]; - // Reload the TableViews section. - [self.tableView reloadSections:[self otherDevicesSectionIndexSet] - withRowAnimation:UITableViewRowAnimationNone]; } // Clean up any previously added SessionSections. @@ -349,6 +343,8 @@ // called inside a [UITableView beginUpdates] block on iOS10, or // performBatchUpdates on iOS11+. - (void)updateOtherDevicesSectionForState:(SessionsSyncUserState)newState { + DCHECK(newState != + SessionsSyncUserState::USER_SIGNED_IN_SYNC_ON_WITH_SESSIONS); TableViewModel* model = self.tableViewModel; SessionsSyncUserState previousState = self.sessionState; switch (previousState) { @@ -357,25 +353,22 @@ case SessionsSyncUserState::USER_SIGNED_OUT: case SessionsSyncUserState::USER_SIGNED_IN_SYNC_IN_PROGRESS: // The OtherDevices section will be updated, remove it in order to clean - // it up. After the clean up add just the header. + // it up. [model removeSectionWithIdentifier:SectionIdentifierOtherDevices]; - [self addOtherDevicesSectionHeader]; break; case SessionsSyncUserState::USER_SIGNED_IN_SYNC_ON_WITH_SESSIONS: // The Sessions Section exists, remove it. [self removeSessionSections]; break; } - // Add updated OtherDevices Item. - [self addOtherDevicesItemForState:newState]; - - // Update OtherDevices TableView Section. + // Add an updated OtherDevices Section and then reload the TableView section. + [self addOtherDevicesSectionForState:newState]; [self.tableView reloadSections:[self otherDevicesSectionIndexSet] withRowAnimation:UITableViewRowAnimationNone]; } // Adds Other Devices Section and its header. -- (void)addOtherDevicesSectionHeader { +- (void)addOtherDevicesSectionForState:(SessionsSyncUserState)state { TableViewModel* model = self.tableViewModel; [model addSectionWithIdentifier:SectionIdentifierOtherDevices]; [model setSectionIdentifier:SectionIdentifierOtherDevices @@ -385,11 +378,8 @@ header.text = l10n_util::GetNSString(IDS_IOS_RECENT_TABS_OTHER_DEVICES); [model setHeader:header forSectionWithIdentifier:SectionIdentifierOtherDevices]; -} -// Adds Other Devices item for |state|. -- (void)addOtherDevicesItemForState:(SessionsSyncUserState)state { - // Add item depending on |state|. + // Adds Other Devices item for |state|. TableViewTextItem* dummyCell = nil; switch (state) { case SessionsSyncUserState::USER_SIGNED_IN_SYNC_ON_WITH_SESSIONS: @@ -666,6 +656,9 @@ } - (synced_sessions::DistantSession const*)sessionForSection:(NSInteger)section { + NSInteger sectionIdentifer = + [self.tableViewModel sectionIdentifierForSection:section]; + DCHECK([self isSessionSectionIdentifier:sectionIdentifer]); return _syncedSessions->GetSession(section - kNumberOfSectionsBeforeSessions); } @@ -893,15 +886,11 @@ syncService->GetOpenTabsUIDelegate(); [self.tableViewModel removeSectionWithIdentifier:sectionIdentifier]; - _syncedSessions->EraseSession(sectionIdentifier - - kFirstSessionSectionIdentifier); + _syncedSessions->EraseSession(section - kNumberOfSectionsBeforeSessions); void (^tableUpdates)(void) = ^{ - [self.tableView - deleteSections:[NSIndexSet - indexSetWithIndex:sectionIdentifier - - kSectionIdentifierEnumZero] - withRowAnimation:UITableViewRowAnimationLeft]; + [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:section] + withRowAnimation:UITableViewRowAnimationLeft]; }; // If iOS11+ use performBatchUpdates: instead of beginUpdates/endUpdates.
diff --git a/ios/chrome/browser/ui/promos/BUILD.gn b/ios/chrome/browser/ui/promos/BUILD.gn index 7b12027a..a6dfa0f 100644 --- a/ios/chrome/browser/ui/promos/BUILD.gn +++ b/ios/chrome/browser/ui/promos/BUILD.gn
@@ -17,12 +17,14 @@ "//ios/chrome/app/strings", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/signin", - "//ios/chrome/browser/ui/authentication", "//ios/chrome/browser/ui/commands", "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/signin", "//net", ] + public_deps = [ + "//ios/chrome/browser/ui/authentication", + ] libs = [ "UIKit.framework" ] }
diff --git a/ios/chrome/browser/ui/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/BUILD.gn index 01a0f42..0b52790da 100644 --- a/ios/chrome/browser/ui/tab_grid/BUILD.gn +++ b/ios/chrome/browser/ui/tab_grid/BUILD.gn
@@ -18,6 +18,7 @@ deps = [ ":tab_grid_ui", + "grid:grid_ui", "//base", "//components/favicon/ios", "//ios/chrome/browser", @@ -37,20 +38,6 @@ source_set("tab_grid_ui") { sources = [ - "grid_cell.h", - "grid_cell.mm", - "grid_commands.h", - "grid_constants.h", - "grid_constants.mm", - "grid_consumer.h", - "grid_image_data_source.h", - "grid_item.h", - "grid_item.mm", - "grid_layout.h", - "grid_layout.mm", - "grid_theme.h", - "grid_view_controller.h", - "grid_view_controller.mm", "tab_grid_bottom_toolbar.h", "tab_grid_bottom_toolbar.mm", "tab_grid_constants.h", @@ -68,18 +55,17 @@ "tab_grid_transition_handler.mm", "tab_grid_view_controller.h", "tab_grid_view_controller.mm", - "top_aligned_image_view.h", - "top_aligned_image_view.mm", ] configs += [ "//build/config/compiler:enable_arc" ] deps = [ - "resources:grid_cell_close_button", + "grid:grid_ui", "resources:new_tab_floating_button", "resources:new_tab_floating_button_incognito", "resources:new_tab_toolbar_button", "resources:new_tab_toolbar_button_incognito", + "resources:page_control_assets", "//base", "//ios/chrome/app/strings", "//ios/chrome/browser", @@ -100,6 +86,7 @@ deps = [ ":tab_grid", ":tab_grid_ui", + "grid:grid_ui", "//base", "//base/test:test_support", "//ios/chrome/browser", @@ -127,6 +114,7 @@ deps = [ ":tab_grid_ui", + "grid:grid_ui", "//base", "//components/strings", "//ios/chrome/app:app_internal",
diff --git a/ios/chrome/browser/ui/tab_grid/grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/grid/BUILD.gn new file mode 100644 index 0000000..cfd8120 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/grid/BUILD.gn
@@ -0,0 +1,39 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//ios/public/provider/chrome/browser/build_config.gni") + +source_set("grid_ui") { + sources = [ + "grid_cell.h", + "grid_cell.mm", + "grid_commands.h", + "grid_constants.h", + "grid_constants.mm", + "grid_consumer.h", + "grid_image_data_source.h", + "grid_item.h", + "grid_item.mm", + "grid_layout.h", + "grid_layout.mm", + "grid_theme.h", + "grid_view_controller.h", + "grid_view_controller.mm", + "top_aligned_image_view.h", + "top_aligned_image_view.mm", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + "resources:grid_cell_close_button", + "//base", + "//ios/chrome/app/strings", + "//ios/chrome/browser", + "//ios/chrome/browser/ui:ui_util", + "//ios/chrome/browser/ui/tab_grid/transitions", + "//ios/chrome/browser/ui/util:constraints_ui", + "//ui/base", + ] +}
diff --git a/ios/chrome/browser/ui/tab_grid/grid/OWNERS b/ios/chrome/browser/ui/tab_grid/grid/OWNERS new file mode 100644 index 0000000..b98e1d4 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/grid/OWNERS
@@ -0,0 +1,2 @@ +edchin@chromium.org +marq@chromium.org
diff --git a/ios/chrome/browser/ui/tab_grid/grid_cell.h b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.h similarity index 83% rename from ios/chrome/browser/ui/tab_grid/grid_cell.h rename to ios/chrome/browser/ui/tab_grid/grid/grid_cell.h index 9778ed2..02208e72 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_cell.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.h
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_CELL_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_CELL_H_ +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_CELL_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_CELL_H_ #import <UIKit/UIKit.h> -#import "ios/chrome/browser/ui/tab_grid/grid_theme.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_theme.h" @class GridCell; @@ -37,4 +37,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_CELL_H_ +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_CELL_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_cell.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm similarity index 97% rename from ios/chrome/browser/ui/tab_grid/grid_cell.mm rename to ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm index 98c02ff4..28462c1 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_cell.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/tab_grid/grid_cell.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_cell.h" #import "base/logging.h" -#import "ios/chrome/browser/ui/tab_grid/grid_constants.h" -#import "ios/chrome/browser/ui/tab_grid/top_aligned_image_view.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_constants.h" +#import "ios/chrome/browser/ui/tab_grid/grid/top_aligned_image_view.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" #include "ios/chrome/grit/ios_strings.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/ios/chrome/browser/ui/tab_grid/grid_commands.h b/ios/chrome/browser/ui/tab_grid/grid/grid_commands.h similarity index 84% rename from ios/chrome/browser/ui/tab_grid/grid_commands.h rename to ios/chrome/browser/ui/tab_grid/grid/grid_commands.h index 02db60f5..56416df 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_commands.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_commands.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_COMMANDS_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_COMMANDS_H_ +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_COMMANDS_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_COMMANDS_H_ // Commands issued to a model backing a grid UI. @protocol GridCommands @@ -22,4 +22,4 @@ - (void)closeAllItems; @end -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_COMMANDS_H_ +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_constants.h b/ios/chrome/browser/ui/tab_grid/grid/grid_constants.h similarity index 94% rename from ios/chrome/browser/ui/tab_grid/grid_constants.h rename to ios/chrome/browser/ui/tab_grid/grid/grid_constants.h index 39c54d5..824bae8 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_constants.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_constants.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_CONSTANTS_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_CONSTANTS_H_ +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_CONSTANTS_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_CONSTANTS_H_ #import <UIKit/UIKit.h> @@ -77,4 +77,4 @@ extern const CGFloat kGridCellSelectionRingGapWidth; extern const CGFloat kGridCellSelectionRingTintWidth; -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_CONSTANTS_H_ +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_constants.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_constants.mm similarity index 97% rename from ios/chrome/browser/ui/tab_grid/grid_constants.mm rename to ios/chrome/browser/ui/tab_grid/grid/grid_constants.mm index 38091bc..9b27224 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_constants.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_constants.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/tab_grid/grid_constants.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_constants.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/chrome/browser/ui/tab_grid/grid_consumer.h b/ios/chrome/browser/ui/tab_grid/grid/grid_consumer.h similarity index 91% rename from ios/chrome/browser/ui/tab_grid/grid_consumer.h rename to ios/chrome/browser/ui/tab_grid/grid/grid_consumer.h index 4a9cc15..595c4ad 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_consumer.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_consumer.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_CONSUMER_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_CONSUMER_H_ +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_CONSUMER_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_CONSUMER_H_ @class GridItem; @@ -48,4 +48,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_CONSUMER_H_ +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_image_data_source.h b/ios/chrome/browser/ui/tab_grid/grid/grid_image_data_source.h similarity index 79% rename from ios/chrome/browser/ui/tab_grid/grid_image_data_source.h rename to ios/chrome/browser/ui/tab_grid/grid/grid_image_data_source.h index 4b0516a2..0686309 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_image_data_source.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_image_data_source.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_IMAGE_DATA_SOURCE_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_IMAGE_DATA_SOURCE_H_ +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_IMAGE_DATA_SOURCE_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_IMAGE_DATA_SOURCE_H_ #import <UIKit/UIKit.h> @@ -20,4 +20,4 @@ completion:(void (^)(UIImage*))completion; @end -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_IMAGE_DATA_SOURCE_H_ +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_IMAGE_DATA_SOURCE_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_item.h b/ios/chrome/browser/ui/tab_grid/grid/grid_item.h similarity index 68% rename from ios/chrome/browser/ui/tab_grid/grid_item.h rename to ios/chrome/browser/ui/tab_grid/grid/grid_item.h index 2a839e2..de68348f 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_item.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_item.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_ITEM_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_ITEM_H_ +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_ITEM_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_ITEM_H_ #import <Foundation/Foundation.h> @@ -13,4 +13,4 @@ @property(nonatomic, copy) NSString* title; @end -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_ITEM_H_ +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_ITEM_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_item.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_item.mm similarity index 86% rename from ios/chrome/browser/ui/tab_grid/grid_item.mm rename to ios/chrome/browser/ui/tab_grid/grid/grid_item.mm index afc827a..2559d053 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_item.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_item.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/tab_grid/grid_item.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_item.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/chrome/browser/ui/tab_grid/grid_layout.h b/ios/chrome/browser/ui/tab_grid/grid/grid_layout.h similarity index 70% rename from ios/chrome/browser/ui/tab_grid/grid_layout.h rename to ios/chrome/browser/ui/tab_grid/grid/grid_layout.h index 8a1b478..d851ae6 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_layout.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_layout.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_LAYOUT_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_LAYOUT_H_ +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_LAYOUT_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_LAYOUT_H_ #import <UIKit/UIKit.h> @@ -13,4 +13,4 @@ @interface GridLayout : UICollectionViewFlowLayout @end -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_LAYOUT_H_ +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_LAYOUT_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_layout.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_layout.mm similarity index 96% rename from ios/chrome/browser/ui/tab_grid/grid_layout.mm rename to ios/chrome/browser/ui/tab_grid/grid/grid_layout.mm index 81460b5f..c889be4 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_layout.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_layout.mm
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/tab_grid/grid_layout.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_layout.h" -#import "ios/chrome/browser/ui/tab_grid/grid_constants.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_constants.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/chrome/browser/ui/tab_grid/grid_theme.h b/ios/chrome/browser/ui/tab_grid/grid/grid_theme.h similarity index 62% rename from ios/chrome/browser/ui/tab_grid/grid_theme.h rename to ios/chrome/browser/ui/tab_grid/grid/grid_theme.h index df91777..eec1323 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_theme.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_theme.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_THEME_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_THEME_H_ +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_THEME_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_THEME_H_ // Theme describing the look of the grid. typedef NS_ENUM(NSUInteger, GridTheme) { @@ -11,4 +11,4 @@ GridThemeDark, }; -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_THEME_H_ +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_THEME_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_view_controller.h b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.h similarity index 85% rename from ios/chrome/browser/ui/tab_grid/grid_view_controller.h rename to ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.h index 6523f6d..bc0095f 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_view_controller.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_VIEW_CONTROLLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_VIEW_CONTROLLER_H_ #import <UIKit/UIKit.h> -#import "ios/chrome/browser/ui/tab_grid/grid_consumer.h" -#import "ios/chrome/browser/ui/tab_grid/grid_theme.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_consumer.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_theme.h" @protocol GridImageDataSource; @class GridTransitionLayout; @@ -53,4 +53,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_VIEW_CONTROLLER_H_ +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm similarity index 96% rename from ios/chrome/browser/ui/tab_grid/grid_view_controller.mm rename to ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm index be1a5e6..1c266e31 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/tab_grid/grid_view_controller.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.h" #import "base/mac/foundation_util.h" #import "base/numerics/safe_conversions.h" -#import "ios/chrome/browser/ui/tab_grid/grid_cell.h" -#import "ios/chrome/browser/ui/tab_grid/grid_constants.h" -#import "ios/chrome/browser/ui/tab_grid/grid_image_data_source.h" -#import "ios/chrome/browser/ui/tab_grid/grid_item.h" -#import "ios/chrome/browser/ui/tab_grid/grid_layout.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_cell.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_constants.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_image_data_source.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_item.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_layout.h" #import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h" #import "ios/chrome/browser/ui/uikit_ui_util.h"
diff --git a/ios/chrome/browser/ui/tab_grid/grid/resources/BUILD.gn b/ios/chrome/browser/ui/tab_grid/grid/resources/BUILD.gn new file mode 100644 index 0000000..2e88b9ff9 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/grid/resources/BUILD.gn
@@ -0,0 +1,14 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/ios/asset_catalog.gni") + +imageset("grid_cell_close_button") { + sources = [ + "grid_cell_close_button.imageset/Contents.json", + "grid_cell_close_button.imageset/grid_cell_close_button.png", + "grid_cell_close_button.imageset/grid_cell_close_button@2x.png", + "grid_cell_close_button.imageset/grid_cell_close_button@3x.png", + ] +}
diff --git a/ios/chrome/browser/ui/tab_grid/resources/grid_cell_close_button.imageset/Contents.json b/ios/chrome/browser/ui/tab_grid/grid/resources/grid_cell_close_button.imageset/Contents.json similarity index 100% rename from ios/chrome/browser/ui/tab_grid/resources/grid_cell_close_button.imageset/Contents.json rename to ios/chrome/browser/ui/tab_grid/grid/resources/grid_cell_close_button.imageset/Contents.json
diff --git a/ios/chrome/browser/ui/tab_grid/resources/grid_cell_close_button.imageset/grid_cell_close_button.png b/ios/chrome/browser/ui/tab_grid/grid/resources/grid_cell_close_button.imageset/grid_cell_close_button.png similarity index 100% rename from ios/chrome/browser/ui/tab_grid/resources/grid_cell_close_button.imageset/grid_cell_close_button.png rename to ios/chrome/browser/ui/tab_grid/grid/resources/grid_cell_close_button.imageset/grid_cell_close_button.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/grid_cell_close_button.imageset/grid_cell_close_button@2x.png b/ios/chrome/browser/ui/tab_grid/grid/resources/grid_cell_close_button.imageset/grid_cell_close_button@2x.png similarity index 100% rename from ios/chrome/browser/ui/tab_grid/resources/grid_cell_close_button.imageset/grid_cell_close_button@2x.png rename to ios/chrome/browser/ui/tab_grid/grid/resources/grid_cell_close_button.imageset/grid_cell_close_button@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/grid_cell_close_button.imageset/grid_cell_close_button@3x.png b/ios/chrome/browser/ui/tab_grid/grid/resources/grid_cell_close_button.imageset/grid_cell_close_button@3x.png similarity index 100% rename from ios/chrome/browser/ui/tab_grid/resources/grid_cell_close_button.imageset/grid_cell_close_button@3x.png rename to ios/chrome/browser/ui/tab_grid/grid/resources/grid_cell_close_button.imageset/grid_cell_close_button@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/top_aligned_image_view.h b/ios/chrome/browser/ui/tab_grid/grid/top_aligned_image_view.h similarity index 75% rename from ios/chrome/browser/ui/tab_grid/top_aligned_image_view.h rename to ios/chrome/browser/ui/tab_grid/grid/top_aligned_image_view.h index 3ba5daf..8997250 100644 --- a/ios/chrome/browser/ui/tab_grid/top_aligned_image_view.h +++ b/ios/chrome/browser/ui/tab_grid/grid/top_aligned_image_view.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TOP_ALIGNED_IMAGE_VIEW_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_TOP_ALIGNED_IMAGE_VIEW_H_ +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_TOP_ALIGNED_IMAGE_VIEW_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_TOP_ALIGNED_IMAGE_VIEW_H_ #import <UIKit/UIKit.h> @@ -19,4 +19,4 @@ - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; @end -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TOP_ALIGNED_IMAGE_VIEW_H_ +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_TOP_ALIGNED_IMAGE_VIEW_H_
diff --git a/ios/chrome/browser/ui/tab_grid/top_aligned_image_view.mm b/ios/chrome/browser/ui/tab_grid/grid/top_aligned_image_view.mm similarity index 96% rename from ios/chrome/browser/ui/tab_grid/top_aligned_image_view.mm rename to ios/chrome/browser/ui/tab_grid/grid/top_aligned_image_view.mm index 9745b5b..8f1b919 100644 --- a/ios/chrome/browser/ui/tab_grid/top_aligned_image_view.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/top_aligned_image_view.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/tab_grid/top_aligned_image_view.h" +#import "ios/chrome/browser/ui/tab_grid/grid/top_aligned_image_view.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/chrome/browser/ui/tab_grid/resources/BUILD.gn b/ios/chrome/browser/ui/tab_grid/resources/BUILD.gn index 7642f48..b05d9520 100644 --- a/ios/chrome/browser/ui/tab_grid/resources/BUILD.gn +++ b/ios/chrome/browser/ui/tab_grid/resources/BUILD.gn
@@ -4,15 +4,6 @@ import("//build/config/ios/asset_catalog.gni") -imageset("grid_cell_close_button") { - sources = [ - "grid_cell_close_button.imageset/Contents.json", - "grid_cell_close_button.imageset/grid_cell_close_button.png", - "grid_cell_close_button.imageset/grid_cell_close_button@2x.png", - "grid_cell_close_button.imageset/grid_cell_close_button@3x.png", - ] -} - imageset("new_tab_floating_button") { sources = [ "new_tab_floating_button.imageset/Contents.json", @@ -48,3 +39,68 @@ "new_tab_toolbar_button_incognito.imageset/new_tab_toolbar_button_incognito@3x.png", ] } + +imageset("page_control_incognito_tabs") { + sources = [ + "page_control_incognito_tabs.imageset/Contents.json", + "page_control_incognito_tabs.imageset/page_control_incognito_tabs.png", + "page_control_incognito_tabs.imageset/page_control_incognito_tabs@2x.png", + "page_control_incognito_tabs.imageset/page_control_incognito_tabs@3x.png", + ] +} + +imageset("page_control_incognito_tabs_selected") { + sources = [ + "page_control_incognito_tabs_selected.imageset/Contents.json", + "page_control_incognito_tabs_selected.imageset/page_control_incognito_tabs_selected.png", + "page_control_incognito_tabs_selected.imageset/page_control_incognito_tabs_selected@2x.png", + "page_control_incognito_tabs_selected.imageset/page_control_incognito_tabs_selected@3x.png", + ] +} + +imageset("page_control_regular_tabs") { + sources = [ + "page_control_regular_tabs.imageset/Contents.json", + "page_control_regular_tabs.imageset/page_control_regular_tabs.png", + "page_control_regular_tabs.imageset/page_control_regular_tabs@2x.png", + "page_control_regular_tabs.imageset/page_control_regular_tabs@3x.png", + ] +} + +imageset("page_control_regular_tabs_selected") { + sources = [ + "page_control_regular_tabs_selected.imageset/Contents.json", + "page_control_regular_tabs_selected.imageset/page_control_regular_tabs_selected.png", + "page_control_regular_tabs_selected.imageset/page_control_regular_tabs_selected@2x.png", + "page_control_regular_tabs_selected.imageset/page_control_regular_tabs_selected@3x.png", + ] +} + +imageset("page_control_remote_tabs") { + sources = [ + "page_control_remote_tabs.imageset/Contents.json", + "page_control_remote_tabs.imageset/page_control_remote_tabs.png", + "page_control_remote_tabs.imageset/page_control_remote_tabs@2x.png", + "page_control_remote_tabs.imageset/page_control_remote_tabs@3x.png", + ] +} + +imageset("page_control_remote_tabs_selected") { + sources = [ + "page_control_remote_tabs_selected.imageset/Contents.json", + "page_control_remote_tabs_selected.imageset/page_control_remote_tabs_selected.png", + "page_control_remote_tabs_selected.imageset/page_control_remote_tabs_selected@2x.png", + "page_control_remote_tabs_selected.imageset/page_control_remote_tabs_selected@3x.png", + ] +} + +group("page_control_assets") { + public_deps = [ + ":page_control_incognito_tabs", + ":page_control_incognito_tabs_selected", + ":page_control_regular_tabs", + ":page_control_regular_tabs_selected", + ":page_control_remote_tabs", + ":page_control_remote_tabs_selected", + ] +}
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs.imageset/Contents.json b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs.imageset/Contents.json new file mode 100644 index 0000000..71c94c0 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs.imageset/Contents.json
@@ -0,0 +1,23 @@ +{ + "images": [ + { + "idiom": "universal", + "scale": "1x", + "filename": "page_control_incognito_tabs.png" + }, + { + "idiom": "universal", + "scale": "2x", + "filename": "page_control_incognito_tabs@2x.png" + }, + { + "idiom": "universal", + "scale": "3x", + "filename": "page_control_incognito_tabs@3x.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +}
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs.imageset/page_control_incognito_tabs.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs.imageset/page_control_incognito_tabs.png new file mode 100644 index 0000000..7cf9bcf --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs.imageset/page_control_incognito_tabs.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs.imageset/page_control_incognito_tabs@2x.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs.imageset/page_control_incognito_tabs@2x.png new file mode 100644 index 0000000..6f162bd3 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs.imageset/page_control_incognito_tabs@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs.imageset/page_control_incognito_tabs@3x.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs.imageset/page_control_incognito_tabs@3x.png new file mode 100644 index 0000000..af72534 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs.imageset/page_control_incognito_tabs@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs_selected.imageset/Contents.json b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs_selected.imageset/Contents.json new file mode 100644 index 0000000..e8ebcee --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs_selected.imageset/Contents.json
@@ -0,0 +1,23 @@ +{ + "images": [ + { + "idiom": "universal", + "scale": "1x", + "filename": "page_control_incognito_tabs_selected.png" + }, + { + "idiom": "universal", + "scale": "2x", + "filename": "page_control_incognito_tabs_selected@2x.png" + }, + { + "idiom": "universal", + "scale": "3x", + "filename": "page_control_incognito_tabs_selected@3x.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +}
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs_selected.imageset/page_control_incognito_tabs_selected.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs_selected.imageset/page_control_incognito_tabs_selected.png new file mode 100644 index 0000000..70a81dc --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs_selected.imageset/page_control_incognito_tabs_selected.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs_selected.imageset/page_control_incognito_tabs_selected@2x.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs_selected.imageset/page_control_incognito_tabs_selected@2x.png new file mode 100644 index 0000000..7e27dec --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs_selected.imageset/page_control_incognito_tabs_selected@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs_selected.imageset/page_control_incognito_tabs_selected@3x.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs_selected.imageset/page_control_incognito_tabs_selected@3x.png new file mode 100644 index 0000000..f045ea1 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_incognito_tabs_selected.imageset/page_control_incognito_tabs_selected@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs.imageset/Contents.json b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs.imageset/Contents.json new file mode 100644 index 0000000..78a0ebe --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs.imageset/Contents.json
@@ -0,0 +1,23 @@ +{ + "images": [ + { + "idiom": "universal", + "scale": "1x", + "filename": "page_control_regular_tabs.png" + }, + { + "idiom": "universal", + "scale": "2x", + "filename": "page_control_regular_tabs@2x.png" + }, + { + "idiom": "universal", + "scale": "3x", + "filename": "page_control_regular_tabs@3x.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +}
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs.imageset/page_control_regular_tabs.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs.imageset/page_control_regular_tabs.png new file mode 100644 index 0000000..847cd45f --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs.imageset/page_control_regular_tabs.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs.imageset/page_control_regular_tabs@2x.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs.imageset/page_control_regular_tabs@2x.png new file mode 100644 index 0000000..0b55cc3 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs.imageset/page_control_regular_tabs@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs.imageset/page_control_regular_tabs@3x.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs.imageset/page_control_regular_tabs@3x.png new file mode 100644 index 0000000..20d6a04 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs.imageset/page_control_regular_tabs@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs_selected.imageset/Contents.json b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs_selected.imageset/Contents.json new file mode 100644 index 0000000..ef60fff0 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs_selected.imageset/Contents.json
@@ -0,0 +1,23 @@ +{ + "images": [ + { + "idiom": "universal", + "scale": "1x", + "filename": "page_control_regular_tabs_selected.png" + }, + { + "idiom": "universal", + "scale": "2x", + "filename": "page_control_regular_tabs_selected@2x.png" + }, + { + "idiom": "universal", + "scale": "3x", + "filename": "page_control_regular_tabs_selected@3x.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +}
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs_selected.imageset/page_control_regular_tabs_selected.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs_selected.imageset/page_control_regular_tabs_selected.png new file mode 100644 index 0000000..7b776fa9 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs_selected.imageset/page_control_regular_tabs_selected.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs_selected.imageset/page_control_regular_tabs_selected@2x.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs_selected.imageset/page_control_regular_tabs_selected@2x.png new file mode 100644 index 0000000..b632f46 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs_selected.imageset/page_control_regular_tabs_selected@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs_selected.imageset/page_control_regular_tabs_selected@3x.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs_selected.imageset/page_control_regular_tabs_selected@3x.png new file mode 100644 index 0000000..1122c3b --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_regular_tabs_selected.imageset/page_control_regular_tabs_selected@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs.imageset/Contents.json b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs.imageset/Contents.json new file mode 100644 index 0000000..fcd836c --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs.imageset/Contents.json
@@ -0,0 +1,23 @@ +{ + "images": [ + { + "idiom": "universal", + "scale": "1x", + "filename": "page_control_remote_tabs.png" + }, + { + "idiom": "universal", + "scale": "2x", + "filename": "page_control_remote_tabs@2x.png" + }, + { + "idiom": "universal", + "scale": "3x", + "filename": "page_control_remote_tabs@3x.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +}
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs.imageset/page_control_remote_tabs.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs.imageset/page_control_remote_tabs.png new file mode 100644 index 0000000..cf4488db --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs.imageset/page_control_remote_tabs.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs.imageset/page_control_remote_tabs@2x.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs.imageset/page_control_remote_tabs@2x.png new file mode 100644 index 0000000..73f042b --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs.imageset/page_control_remote_tabs@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs.imageset/page_control_remote_tabs@3x.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs.imageset/page_control_remote_tabs@3x.png new file mode 100644 index 0000000..4419bde --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs.imageset/page_control_remote_tabs@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs_selected.imageset/Contents.json b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs_selected.imageset/Contents.json new file mode 100644 index 0000000..36bf578e --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs_selected.imageset/Contents.json
@@ -0,0 +1,23 @@ +{ + "images": [ + { + "idiom": "universal", + "scale": "1x", + "filename": "page_control_remote_tabs_selected.png" + }, + { + "idiom": "universal", + "scale": "2x", + "filename": "page_control_remote_tabs_selected@2x.png" + }, + { + "idiom": "universal", + "scale": "3x", + "filename": "page_control_remote_tabs_selected@3x.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +}
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs_selected.imageset/page_control_remote_tabs_selected.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs_selected.imageset/page_control_remote_tabs_selected.png new file mode 100644 index 0000000..2002a21 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs_selected.imageset/page_control_remote_tabs_selected.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs_selected.imageset/page_control_remote_tabs_selected@2x.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs_selected.imageset/page_control_remote_tabs_selected@2x.png new file mode 100644 index 0000000..9ed594d --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs_selected.imageset/page_control_remote_tabs_selected@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs_selected.imageset/page_control_remote_tabs_selected@3x.png b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs_selected.imageset/page_control_remote_tabs_selected@3x.png new file mode 100644 index 0000000..54ddc93 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/resources/page_control_remote_tabs_selected.imageset/page_control_remote_tabs_selected@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm index 9d8c75f..f6d2fa84 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/tab_grid/grid_constants.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_constants.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h" #import "ios/chrome/test/app/chrome_test_util.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h index 4b5a372..6e2618d 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h
@@ -7,8 +7,8 @@ #import <Foundation/Foundation.h> -#import "ios/chrome/browser/ui/tab_grid/grid_commands.h" -#import "ios/chrome/browser/ui/tab_grid/grid_image_data_source.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_commands.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_image_data_source.h" @protocol GridConsumer; @class TabModel;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm index 415ac5c..98dc3fd 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
@@ -13,8 +13,8 @@ #include "ios/chrome/browser/chrome_url_constants.h" #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h" #import "ios/chrome/browser/tabs/tab_model.h" -#import "ios/chrome/browser/ui/tab_grid/grid_consumer.h" -#import "ios/chrome/browser/ui/tab_grid/grid_item.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_consumer.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_item.h" #import "ios/chrome/browser/web/tab_id_tab_helper.h" #include "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator_unittest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator_unittest.mm index 219614e1..63882f1 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator_unittest.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator_unittest.mm
@@ -11,9 +11,9 @@ #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/chrome_url_constants.h" #import "ios/chrome/browser/tabs/tab_model.h" -#import "ios/chrome/browser/ui/tab_grid/grid_commands.h" -#import "ios/chrome/browser/ui/tab_grid/grid_consumer.h" -#import "ios/chrome/browser/ui/tab_grid/grid_item.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_commands.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_consumer.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_item.h" #import "ios/chrome/browser/web/tab_id_tab_helper.h" #include "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h" #include "ios/chrome/browser/web_state_list/web_state_list.h"
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.h b/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.h index 8cc28e3..29c106d 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.h +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.h
@@ -33,7 +33,6 @@ // The numbers that the control should display in the appropriate sections. // Numbers less than 1 are not displayed. // Numbers greated than 99 are displayed as ':-)'. -@property(nonatomic, assign) NSUInteger incognitoTabCount; @property(nonatomic, assign) NSUInteger regularTabCount; // Create and return a new instance of this control. This is the preferred way
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm index 3a883a8c..a886fbb 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm
@@ -29,17 +29,14 @@ // // * The background view, a grey roundrect with vertical transparent bars. // * The background image views. -// * The numeric labels on the incognito and regular tab icons. +// * The numeric label on the regular tab icon. // * The "slider" view -- a white roundrect that's taller and wider than each // of the background segments. It clips its subview to its bounds, and it // adjusts its subview's frame so that it (the subview) remains fixed // relative to the background. // * The selected image view, which contains the selected images and labels // and is a subview of the slider. -// * The selected images and labels. -// -// (Note that currently only labels are used; images will be added once assets -// are available). +// * The selected images and label. // Notes on layout: // This control has an intrinsic size, and generally ignores frame changes. It's @@ -126,13 +123,15 @@ @property(nonatomic, weak) UIView* selectedImageView; // The labels for the incognito and regular sections, in regular and selected // variants. -@property(nonatomic, weak) UILabel* incognitoLabel; -@property(nonatomic, weak) UILabel* incognitoSelectedLabel; +@property(nonatomic, weak) UIView* incognitoIcon; +@property(nonatomic, weak) UIView* incognitoSelectedIcon; +@property(nonatomic, weak) UIView* regularIcon; +@property(nonatomic, weak) UIView* regularSelectedIcon; @property(nonatomic, weak) UILabel* regularLabel; @property(nonatomic, weak) UILabel* regularSelectedLabel; -// Temporary labels for the remote tabs section, to be replaced by image assets. -@property(nonatomic, weak) UILabel* remoteLabel; -@property(nonatomic, weak) UILabel* remoteSelectedLabel; + +@property(nonatomic, weak) UIView* remoteIcon; +@property(nonatomic, weak) UIView* remoteSelectedIcon; // The center point for the slider corresponding to a |sliderPosition| of 0. @property(nonatomic) CGFloat sliderOrigin; // The (signed) x-coordinate distance the slider moves over. The slider's @@ -147,7 +146,6 @@ // Public properties @synthesize selectedPage = _selectedPage; @synthesize sliderPosition = _sliderPosition; -@synthesize incognitoTabCount = _incognitoTabCount; @synthesize regularTabCount = _regularTabCount; // Private properties @synthesize incognitoGuide = _incognitoGuide; @@ -155,12 +153,14 @@ @synthesize remoteGuide = _remoteGuide; @synthesize sliderView = _sliderView; @synthesize selectedImageView = _selectedImageView; -@synthesize incognitoLabel = _incognitoLabel; -@synthesize incognitoSelectedLabel = _incognitoSelectedLabel; +@synthesize incognitoIcon = _incognitoIcon; +@synthesize incognitoSelectedIcon = _incognitoSelectedIconl; +@synthesize regularIcon = _regularIcon; +@synthesize regularSelectedIcon = _regularSelectedIcon; @synthesize regularLabel = _regularLabel; @synthesize regularSelectedLabel = _regularSelectedLabel; -@synthesize remoteLabel = _remoteLabel; -@synthesize remoteSelectedLabel = _remoteSelectedLabel; +@synthesize remoteIcon = _remoteIcon; +@synthesize remoteSelectedIcon = _remoteSelectedIcon; @synthesize sliderOrigin = _sliderOrigin; @synthesize sliderRange = _sliderRange; @@ -201,13 +201,6 @@ // the text in both labels (the regular and the "selected" versions that's // visible when the slider is over a segment), and an ivar to store values that // are set before the labels are created. -- (void)setIncognitoTabCount:(NSUInteger)incognitoTabCount { - NSString* incognitoText = StringForItemCount(incognitoTabCount); - self.incognitoLabel.text = incognitoText; - self.incognitoSelectedLabel.text = incognitoText; - _incognitoTabCount = incognitoTabCount; -} - - (void)setRegularTabCount:(NSUInteger)regularTabCount { NSString* regularText = StringForItemCount(regularTabCount); self.regularLabel.text = regularText; @@ -269,17 +262,19 @@ // guides can be set correctly. [super layoutSubviews]; // Position the section images and labels, which depend on the layout guides. - self.incognitoLabel.center = [self centerOfSegment:TabGridPageIncognitoTabs]; - self.incognitoSelectedLabel.center = + self.incognitoIcon.center = [self centerOfSegment:TabGridPageIncognitoTabs]; + self.incognitoSelectedIcon.center = [self centerOfSegment:TabGridPageIncognitoTabs]; + self.regularIcon.center = [self centerOfSegment:TabGridPageRegularTabs]; + self.regularSelectedIcon.center = + [self centerOfSegment:TabGridPageRegularTabs]; self.regularLabel.center = [self centerOfSegment:TabGridPageRegularTabs]; self.regularSelectedLabel.center = [self centerOfSegment:TabGridPageRegularTabs]; - self.remoteLabel.center = [self centerOfSegment:TabGridPageRemoteTabs]; - self.remoteSelectedLabel.center = - [self centerOfSegment:TabGridPageRemoteTabs]; + self.remoteIcon.center = [self centerOfSegment:TabGridPageRemoteTabs]; + self.remoteSelectedIcon.center = [self centerOfSegment:TabGridPageRemoteTabs]; // Determine the slider origin and range; this is based on the layout guides // and can't be computed until they are determined. @@ -338,15 +333,6 @@ constraintEqualToAnchor:regularGuide.trailingAnchor] ]]; - // Create the section images and labels and add them below the slider. - UILabel* incognitoLabel = [self labelSelected:NO incognito:YES]; - [self addSubview:incognitoLabel]; - self.incognitoLabel = incognitoLabel; - - UILabel* regularLabel = [self labelSelected:NO incognito:NO]; - [self addSubview:regularLabel]; - self.regularLabel = regularLabel; - // Add the slider above the section images and labels. CGRect sliderFrame = CGRectMake(0, 0, kSliderWidth, kSliderHeight); UIView* slider = [[UIView alloc] initWithFrame:sliderFrame]; @@ -357,36 +343,62 @@ [self addSubview:slider]; self.sliderView = slider; + // Selected images and labels are added to the selected image view so they + // will be clipped by the slider. UIView* selectedImageView = [[UIView alloc] initWithFrame:(CGRectMake(0, 0, kOverallWidth, kOverallHeight))]; [self.sliderView addSubview:selectedImageView]; self.selectedImageView = selectedImageView; - // Add the selected images and labels to the selected image view so they - // will be clipped by it. - UILabel* incognitoSelectedLabel = [self labelSelected:YES incognito:YES]; - [self.selectedImageView addSubview:incognitoSelectedLabel]; - self.incognitoSelectedLabel = incognitoSelectedLabel; + // Scale the selected images, since the current assets don't have a larger + // size for the selected state. + // TODO(crbug.com/804500): Remove this once the correct assets are available. + CGFloat scale = kSelectedLabelSize / kLabelSize; + CGAffineTransform scaleTransform = CGAffineTransformMakeScale(scale, scale); - UILabel* regularSelectedLabel = [self labelSelected:YES incognito:NO]; + // Icons and labels for the regular tabs. + UIImageView* regularIcon = [[UIImageView alloc] + initWithImage:[UIImage imageNamed:@"page_control_regular_tabs"]]; + [self insertSubview:regularIcon belowSubview:self.sliderView]; + self.regularIcon = regularIcon; + UIImageView* regularSelectedIcon = [[UIImageView alloc] + initWithImage:[UIImage imageNamed:@"page_control_regular_tabs_selected"]]; + regularSelectedIcon.transform = scaleTransform; + [self.selectedImageView addSubview:regularSelectedIcon]; + self.regularSelectedIcon = regularSelectedIcon; + UILabel* regularLabel = [self labelSelected:NO]; + [self insertSubview:regularLabel belowSubview:self.sliderView]; + self.regularLabel = regularLabel; + UILabel* regularSelectedLabel = [self labelSelected:YES]; [self.selectedImageView addSubview:regularSelectedLabel]; self.regularSelectedLabel = regularSelectedLabel; - // Create a temporary label for the remote tabs section. - // TODO(crbug.com/804500): Remove this when assets are available. - UILabel* remoteLabel = [self labelSelected:NO incognito:NO]; - [self insertSubview:remoteLabel belowSubview:self.sliderView]; - self.remoteLabel = remoteLabel; - UILabel* remoteSelectedLabel = [self labelSelected:YES incognito:NO]; - [self.selectedImageView addSubview:remoteSelectedLabel]; - self.remoteSelectedLabel = remoteSelectedLabel; - remoteLabel.text = @"R"; - remoteSelectedLabel.text = @"R"; + // Icons for the incognito tabs section. + UIImageView* incognitoIcon = [[UIImageView alloc] + initWithImage:[UIImage imageNamed:@"page_control_incognito_tabs"]]; + [self insertSubview:incognitoIcon belowSubview:self.sliderView]; + self.incognitoIcon = incognitoIcon; + UIImageView* incognitoSelectedIcon = [[UIImageView alloc] + initWithImage:[UIImage + imageNamed:@"page_control_incognito_tabs_selected"]]; + incognitoSelectedIcon.transform = scaleTransform; + [self.selectedImageView addSubview:incognitoSelectedIcon]; + self.incognitoSelectedIcon = incognitoSelectedIcon; + + // Icons for the remote tabs section. + UIImageView* remoteIcon = [[UIImageView alloc] + initWithImage:[UIImage imageNamed:@"page_control_remote_tabs"]]; + [self insertSubview:remoteIcon belowSubview:self.sliderView]; + self.remoteIcon = remoteIcon; + UIImageView* remoteSelectedIcon = [[UIImageView alloc] + initWithImage:[UIImage imageNamed:@"page_control_remote_tabs_selected"]]; + remoteSelectedIcon.transform = scaleTransform; + [self.selectedImageView addSubview:remoteSelectedIcon]; + self.remoteSelectedIcon = remoteSelectedIcon; // Update the label text, in case these properties have been set before the // views were set up. self.regularTabCount = _regularTabCount; - self.incognitoTabCount = _incognitoTabCount; // Mark the control's layout as dirty so the the guides will be computed, then // force a layout now so it won't be triggered later (perhaps during an @@ -403,22 +415,14 @@ // Creates a label for use in this control. // Selected labels use a different size and are black. -// Incognito labels have a solid background and use inverted text. -- (UILabel*)labelSelected:(BOOL)selected incognito:(BOOL)incognito { +- (UILabel*)labelSelected:(BOOL)selected { CGFloat size = selected ? kSelectedLabelSize : kLabelSize; - UIColor* color = selected ? UIColor.blackColor : UIColor.lightGrayColor; + UIColor* color = selected ? UIColor.blackColor : UIColorFromRGB(kSliderColor); UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, size, size)]; - label.backgroundColor = incognito ? color : UIColor.clearColor; - label.layer.borderWidth = 2.5; - label.layer.borderColor = color.CGColor; - label.layer.masksToBounds = YES; - label.layer.cornerRadius = 6.0; + label.backgroundColor = UIColor.clearColor; label.textAlignment = NSTextAlignmentCenter; - label.textColor = incognito ? (selected ? UIColorFromRGB(kSliderColor) - : UIColorFromRGB(kBackgroundColor)) - : color; - label.font = - [UIFont systemFontOfSize:size * .6 weight:UIFontWeightBold]; // ? + label.textColor = color; + label.font = [UIFont systemFontOfSize:size * .6 weight:UIFontWeightBold]; return label; }
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm index 5382884..8ccd3bf 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -5,10 +5,10 @@ #import "ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h" #include "base/strings/sys_string_conversions.h" -#import "ios/chrome/browser/ui/tab_grid/grid_commands.h" -#import "ios/chrome/browser/ui/tab_grid/grid_consumer.h" -#import "ios/chrome/browser/ui/tab_grid/grid_image_data_source.h" -#import "ios/chrome/browser/ui/tab_grid/grid_view_controller.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_commands.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_consumer.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_image_data_source.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_constants.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_empty_state_view.h" @@ -622,8 +622,6 @@ [self configureButtonsForCurrentPage]; if (gridViewController == self.regularTabsViewController) { self.topToolbar.pageControl.regularTabCount = count; - } else if (gridViewController == self.incognitoTabsViewController) { - self.topToolbar.pageControl.incognitoTabCount = count; } }
diff --git a/ios/public/provider/chrome/browser/signin/BUILD.gn b/ios/public/provider/chrome/browser/signin/BUILD.gn index d6d697d..a931d2c 100644 --- a/ios/public/provider/chrome/browser/signin/BUILD.gn +++ b/ios/public/provider/chrome/browser/signin/BUILD.gn
@@ -40,6 +40,7 @@ "//base", "//google_apis", "//ios/public/provider/chrome/browser", + "//ui/base:test_support", ] public_deps = [ "//testing/gmock",
diff --git a/ios/public/provider/chrome/browser/signin/DEPS b/ios/public/provider/chrome/browser/signin/DEPS new file mode 100644 index 0000000..eb0f651b --- /dev/null +++ b/ios/public/provider/chrome/browser/signin/DEPS
@@ -0,0 +1,5 @@ +specific_include_rules = { + "test_signin_resources_provider\.mm": [ + "+ui/base/test/ios/ui_image_test_utils.h", + ], +}
diff --git a/ios/public/provider/chrome/browser/signin/test_signin_resources_provider.mm b/ios/public/provider/chrome/browser/signin/test_signin_resources_provider.mm index 2e82643..461cdc6 100644 --- a/ios/public/provider/chrome/browser/signin/test_signin_resources_provider.mm +++ b/ios/public/provider/chrome/browser/signin/test_signin_resources_provider.mm
@@ -6,12 +6,18 @@ #import <UIKit/UIKit.h> +#include "ui/base/test/ios/ui_image_test_utils.h" + #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif TestSigninResourcesProvider::TestSigninResourcesProvider() - : default_avatar_([[UIImage alloc] init]) {} + : default_avatar_(ui::test::uiimage_utils::UIImageWithSizeAndSolidColor( + CGSizeMake(32, 32), + UIColor.whiteColor)) { + // A real UIImage for default_avatar_ is required to be cached/resized. +} TestSigninResourcesProvider::~TestSigninResourcesProvider() {}
diff --git a/ios/showcase/tab_grid/BUILD.gn b/ios/showcase/tab_grid/BUILD.gn index 8cbb1a6..cae774f 100644 --- a/ios/showcase/tab_grid/BUILD.gn +++ b/ios/showcase/tab_grid/BUILD.gn
@@ -18,6 +18,7 @@ deps = [ "//base", "//ios/chrome/browser/ui/tab_grid:tab_grid_ui", + "//ios/chrome/browser/ui/tab_grid/grid:grid_ui", "//ios/showcase/common", ] libs = [ "UIKit.framework" ]
diff --git a/ios/showcase/tab_grid/sc_grid_cell_view_controller.mm b/ios/showcase/tab_grid/sc_grid_cell_view_controller.mm index 899a47d..fd4930e 100644 --- a/ios/showcase/tab_grid/sc_grid_cell_view_controller.mm +++ b/ios/showcase/tab_grid/sc_grid_cell_view_controller.mm
@@ -6,8 +6,8 @@ #import "base/mac/foundation_util.h" #import "base/numerics/safe_conversions.h" -#import "ios/chrome/browser/ui/tab_grid/grid_cell.h" -#import "ios/chrome/browser/ui/tab_grid/grid_theme.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_cell.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_theme.h" #import "ios/showcase/common/protocol_alerter.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/showcase/tab_grid/sc_grid_coordinator.mm b/ios/showcase/tab_grid/sc_grid_coordinator.mm index 367151c7..7c38a681 100644 --- a/ios/showcase/tab_grid/sc_grid_coordinator.mm +++ b/ios/showcase/tab_grid/sc_grid_coordinator.mm
@@ -4,9 +4,9 @@ #import "ios/showcase/tab_grid/sc_grid_coordinator.h" -#import "ios/chrome/browser/ui/tab_grid/grid_image_data_source.h" -#import "ios/chrome/browser/ui/tab_grid/grid_item.h" -#import "ios/chrome/browser/ui/tab_grid/grid_view_controller.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_image_data_source.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_item.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.h" #import "ios/showcase/common/protocol_alerter.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/showcase/tab_grid/sc_image_view_controller.mm b/ios/showcase/tab_grid/sc_image_view_controller.mm index 1fbf6de..42bc16ad 100644 --- a/ios/showcase/tab_grid/sc_image_view_controller.mm +++ b/ios/showcase/tab_grid/sc_image_view_controller.mm
@@ -4,7 +4,7 @@ #import "ios/showcase/tab_grid/sc_image_view_controller.h" -#import "ios/chrome/browser/ui/tab_grid/top_aligned_image_view.h" +#import "ios/chrome/browser/ui/tab_grid/grid/top_aligned_image_view.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/showcase/tab_grid/sc_tab_grid_coordinator.mm b/ios/showcase/tab_grid/sc_tab_grid_coordinator.mm index 0690430..bdec3e44 100644 --- a/ios/showcase/tab_grid/sc_tab_grid_coordinator.mm +++ b/ios/showcase/tab_grid/sc_tab_grid_coordinator.mm
@@ -4,9 +4,9 @@ #import "ios/showcase/tab_grid/sc_tab_grid_coordinator.h" -#import "ios/chrome/browser/ui/tab_grid/grid_commands.h" -#import "ios/chrome/browser/ui/tab_grid/grid_consumer.h" -#import "ios/chrome/browser/ui/tab_grid/grid_item.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_commands.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_consumer.h" +#import "ios/chrome/browser/ui/tab_grid/grid/grid_item.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h" #import "ios/showcase/common/protocol_alerter.h"
diff --git a/ios/web/web_state/ui/crw_context_menu_controller.mm b/ios/web/web_state/ui/crw_context_menu_controller.mm index ffa82c9..3156c963 100644 --- a/ios/web/web_state/ui/crw_context_menu_controller.mm +++ b/ios/web/web_state/ui/crw_context_menu_controller.mm
@@ -338,6 +338,9 @@ [_pendingElementFetchRequests removeObjectForKey:requestID]; [self logElementFetchDurationWithStartTime:fetchRequest.creationTime]; [fetchRequest runHandlerWithResponse:response]; + } else { + UMA_HISTOGRAM_BOOLEAN( + "ContextMenu.UnexpectedFindElementResultHandlerMessage", true); } }
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc index cb86bda..e1007508 100644 --- a/ipc/ipc_mojo_bootstrap.cc +++ b/ipc/ipc_mojo_bootstrap.cc
@@ -4,10 +4,12 @@ #include "ipc/ipc_mojo_bootstrap.h" +#include <inttypes.h> #include <stdint.h> #include <map> #include <memory> +#include <set> #include <utility> #include <vector> @@ -16,10 +18,15 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/no_destructor.h" #include "base/single_thread_task_runner.h" +#include "base/strings/stringprintf.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/trace_event/memory_allocator_dump.h" +#include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/memory_dump_provider.h" #include "mojo/public/cpp/bindings/associated_group.h" #include "mojo/public/cpp/bindings/associated_group_controller.h" #include "mojo/public/cpp/bindings/connector.h" @@ -37,6 +44,50 @@ namespace { +class ChannelAssociatedGroupController; + +// Used to track some internal Channel state in pursuit of message leaks. +// +// TODO(https://crbug.com/813045): Remove this. +class ControllerMemoryDumpProvider + : public base::trace_event::MemoryDumpProvider { + public: + ControllerMemoryDumpProvider() { + base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( + this, "IPCChannel", nullptr); + } + + ~ControllerMemoryDumpProvider() override { + base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( + this); + } + + void AddController(ChannelAssociatedGroupController* controller) { + base::AutoLock lock(lock_); + controllers_.insert(controller); + } + + void RemoveController(ChannelAssociatedGroupController* controller) { + base::AutoLock lock(lock_); + controllers_.erase(controller); + } + + // base::trace_event::MemoryDumpProvider: + bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, + base::trace_event::ProcessMemoryDump* pmd) override; + + private: + base::Lock lock_; + std::set<ChannelAssociatedGroupController*> controllers_; + + DISALLOW_COPY_AND_ASSIGN(ControllerMemoryDumpProvider); +}; + +ControllerMemoryDumpProvider& GetMemoryDumpProvider() { + static base::NoDestructor<ControllerMemoryDumpProvider> provider; + return *provider; +} + class ChannelAssociatedGroupController : public mojo::AssociatedGroupController, public mojo::MessageReceiver, @@ -58,6 +109,13 @@ "IPC::mojom::Bootstrap [master] PipeControlMessageHandler"); filters_.Append<mojo::MessageHeaderValidator>( "IPC::mojom::Bootstrap [master] MessageHeaderValidator"); + + GetMemoryDumpProvider().AddController(this); + } + + size_t GetQueuedMessageCount() { + base::AutoLock lock(outgoing_messages_lock_); + return outgoing_messages_.size(); } void Bind(mojo::ScopedMessagePipeHandle handle) { @@ -86,7 +144,10 @@ void FlushOutgoingMessages() { std::vector<mojo::Message> outgoing_messages; - std::swap(outgoing_messages, outgoing_messages_); + { + base::AutoLock lock(outgoing_messages_lock_); + std::swap(outgoing_messages, outgoing_messages_); + } for (auto& message : outgoing_messages) SendMessage(&message); } @@ -127,6 +188,8 @@ connector_->CloseMessagePipe(); OnPipeError(); connector_.reset(); + + base::AutoLock lock(outgoing_messages_lock_); outgoing_messages_.clear(); } @@ -581,6 +644,8 @@ } DCHECK(endpoints_.empty()); + + GetMemoryDumpProvider().RemoveController(this); } bool SendMessage(mojo::Message* message) { @@ -588,6 +653,7 @@ DCHECK(thread_checker_.CalledOnValidThread()); if (!connector_ || paused_) { if (!shut_down_) { + base::AutoLock lock(outgoing_messages_lock_); outgoing_messages_.emplace_back(std::move(*message)); // TODO(https://crbug.com/813045): Remove this. Typically this queue @@ -871,6 +937,10 @@ // NOTE: It is unsafe to call into this object while holding |lock_|. mojo::PipeControlMessageProxy control_message_proxy_; + // Guards access to |outgoing_messages_| only. Used to support memory dumps + // which may be triggered from any thread. + base::Lock outgoing_messages_lock_; + // Outgoing messages that were sent before this controller was bound to a // real message pipe. std::vector<mojo::Message> outgoing_messages_; @@ -889,6 +959,22 @@ DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController); }; +bool ControllerMemoryDumpProvider::OnMemoryDump( + const base::trace_event::MemoryDumpArgs& args, + base::trace_event::ProcessMemoryDump* pmd) { + base::AutoLock lock(lock_); + for (auto* controller : controllers_) { + base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump( + base::StringPrintf("mojo/queued_ipc_channel_message/0x%" PRIxPTR, + reinterpret_cast<uintptr_t>(controller))); + dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount, + base::trace_event::MemoryAllocatorDump::kUnitsObjects, + controller->GetQueuedMessageCount()); + } + + return true; +} + class MojoBootstrapImpl : public MojoBootstrap { public: MojoBootstrapImpl(
diff --git a/jingle/glue/xmpp_client_socket_factory.cc b/jingle/glue/xmpp_client_socket_factory.cc index 20b26db2..6e8af3a 100644 --- a/jingle/glue/xmpp_client_socket_factory.cc +++ b/jingle/glue/xmpp_client_socket_factory.cc
@@ -39,7 +39,8 @@ const net::HostPortPair& host_and_port) { // TODO(akalin): Use socket pools. auto transport_socket = proxy_resolving_socket_factory_.CreateSocket( - ssl_config_, GURL("https://" + host_and_port.ToString())); + ssl_config_, GURL("https://" + host_and_port.ToString()), + false /*use_tls*/); return (use_fake_ssl_client_socket_ ? std::unique_ptr<net::StreamSocket>( new FakeSSLClientSocket(std::move(transport_socket)))
diff --git a/media/audio/PRESUBMIT.py b/media/audio/PRESUBMIT.py index dde9444..4cd32d6 100644 --- a/media/audio/PRESUBMIT.py +++ b/media/audio/PRESUBMIT.py
@@ -21,7 +21,7 @@ cl, [ 'luci.chromium.try:linux_optional_gpu_tests_rel', - 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'luci.chromium.try:mac_optional_gpu_tests_rel', 'master.tryserver.chromium.win:win_optional_gpu_tests_rel', 'master.tryserver.chromium.android:android_optional_gpu_tests_rel', ],
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index 9b5271e..5d84014 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc
@@ -602,6 +602,51 @@ } // static +int VideoFrame::BytesPerElement(VideoPixelFormat format, size_t plane) { + DCHECK(IsValidPlane(plane, format)); + switch (format) { + case PIXEL_FORMAT_ARGB: + case PIXEL_FORMAT_XRGB: + case PIXEL_FORMAT_RGB32: + return 4; + case PIXEL_FORMAT_RGB24: + return 3; + case PIXEL_FORMAT_Y16: + case PIXEL_FORMAT_UYVY: + case PIXEL_FORMAT_YUY2: + case PIXEL_FORMAT_YUV420P9: + case PIXEL_FORMAT_YUV422P9: + case PIXEL_FORMAT_YUV444P9: + case PIXEL_FORMAT_YUV420P10: + case PIXEL_FORMAT_YUV422P10: + case PIXEL_FORMAT_YUV444P10: + case PIXEL_FORMAT_YUV420P12: + case PIXEL_FORMAT_YUV422P12: + case PIXEL_FORMAT_YUV444P12: + return 2; + case PIXEL_FORMAT_NV12: + case PIXEL_FORMAT_NV21: + case PIXEL_FORMAT_MT21: { + static const int bytes_per_element[] = {1, 2}; + DCHECK_LT(plane, arraysize(bytes_per_element)); + return bytes_per_element[plane]; + } + case PIXEL_FORMAT_YV12: + case PIXEL_FORMAT_I420: + case PIXEL_FORMAT_I422: + case PIXEL_FORMAT_I420A: + case PIXEL_FORMAT_I444: + return 1; + case PIXEL_FORMAT_MJPEG: + return 0; + case PIXEL_FORMAT_UNKNOWN: + break; + } + NOTREACHED(); + return 0; +} + +// static size_t VideoFrame::Rows(size_t plane, VideoPixelFormat format, int height) { DCHECK(IsValidPlane(plane, format)); const int sample_height = SampleSize(format, plane).height(); @@ -882,9 +927,10 @@ // TODO(miu): This function should support any pixel format. // http://crbug.com/555909 - if (format != PIXEL_FORMAT_I420 && format != PIXEL_FORMAT_Y16) { - LOG(DFATAL) << "Only PIXEL_FORMAT_I420 and PIXEL_FORMAT_Y16 formats are" - "supported: " + if (format != PIXEL_FORMAT_I420 && format != PIXEL_FORMAT_Y16 && + format != PIXEL_FORMAT_ARGB) { + LOG(DFATAL) << "Only PIXEL_FORMAT_I420, PIXEL_FORMAT_Y16, and " + "PIXEL_FORMAT_ARGB formats are supported: " << VideoPixelFormatToString(format); return nullptr; } @@ -1130,51 +1176,6 @@ } // static -int VideoFrame::BytesPerElement(VideoPixelFormat format, size_t plane) { - DCHECK(IsValidPlane(plane, format)); - switch (format) { - case PIXEL_FORMAT_ARGB: - case PIXEL_FORMAT_XRGB: - case PIXEL_FORMAT_RGB32: - return 4; - case PIXEL_FORMAT_RGB24: - return 3; - case PIXEL_FORMAT_Y16: - case PIXEL_FORMAT_UYVY: - case PIXEL_FORMAT_YUY2: - case PIXEL_FORMAT_YUV420P9: - case PIXEL_FORMAT_YUV422P9: - case PIXEL_FORMAT_YUV444P9: - case PIXEL_FORMAT_YUV420P10: - case PIXEL_FORMAT_YUV422P10: - case PIXEL_FORMAT_YUV444P10: - case PIXEL_FORMAT_YUV420P12: - case PIXEL_FORMAT_YUV422P12: - case PIXEL_FORMAT_YUV444P12: - return 2; - case PIXEL_FORMAT_NV12: - case PIXEL_FORMAT_NV21: - case PIXEL_FORMAT_MT21: { - static const int bytes_per_element[] = {1, 2}; - DCHECK_LT(plane, arraysize(bytes_per_element)); - return bytes_per_element[plane]; - } - case PIXEL_FORMAT_YV12: - case PIXEL_FORMAT_I420: - case PIXEL_FORMAT_I422: - case PIXEL_FORMAT_I420A: - case PIXEL_FORMAT_I444: - return 1; - case PIXEL_FORMAT_MJPEG: - return 0; - case PIXEL_FORMAT_UNKNOWN: - break; - } - NOTREACHED(); - return 0; -} - -// static gfx::Size VideoFrame::CommonAlignment(VideoPixelFormat format) { int max_sample_width = 0; int max_sample_height = 0;
diff --git a/media/base/video_frame.h b/media/base/video_frame.h index b0c6273..ea98a28 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h
@@ -275,6 +275,9 @@ // The width may be aligned to format requirements. static size_t RowBytes(size_t plane, VideoPixelFormat format, int width); + // Returns the number of bytes per element for given |plane| and |format|. + static int BytesPerElement(VideoPixelFormat format, size_t plane); + // Returns the number of rows for the given plane, format, and height. // The height may be aligned to format requirements. static size_t Rows(size_t plane, VideoPixelFormat format, int height); @@ -489,9 +492,6 @@ // E.g. 2x2 for the U-plane in PIXEL_FORMAT_I420. static gfx::Size SampleSize(VideoPixelFormat format, size_t plane); - // Returns the number of bytes per element for given |plane| and |format|. - static int BytesPerElement(VideoPixelFormat format, size_t plane); - // Return the alignment for the whole frame, calculated as the max of the // alignment for each individual plane. static gfx::Size CommonAlignment(VideoPixelFormat format);
diff --git a/media/base/video_util.cc b/media/base/video_util.cc index 4f1f396..425a0ba 100644 --- a/media/base/video_util.cc +++ b/media/base/video_util.cc
@@ -113,12 +113,18 @@ static void LetterboxPlane(VideoFrame* frame, int plane, - const gfx::Rect& view_area, + const gfx::Rect& view_area_in_pixels, uint8_t fill_byte) { uint8_t* ptr = frame->data(plane); const int rows = frame->rows(plane); const int row_bytes = frame->row_bytes(plane); const int stride = frame->stride(plane); + const int bytes_per_element = + VideoFrame::BytesPerElement(frame->format(), plane); + gfx::Rect view_area(view_area_in_pixels.x() * bytes_per_element, + view_area_in_pixels.y(), + view_area_in_pixels.width() * bytes_per_element, + view_area_in_pixels.height()); CHECK_GE(stride, row_bytes); CHECK_GE(view_area.x(), 0); @@ -153,20 +159,27 @@ } } -void LetterboxYUV(VideoFrame* frame, const gfx::Rect& view_area) { - DCHECK(!(view_area.x() & 1)); - DCHECK(!(view_area.y() & 1)); - DCHECK(!(view_area.width() & 1)); - DCHECK(!(view_area.height() & 1)); - DCHECK(frame->format() == PIXEL_FORMAT_YV12 || - frame->format() == PIXEL_FORMAT_I420); - LetterboxPlane(frame, VideoFrame::kYPlane, view_area, 0x00); - gfx::Rect half_view_area(view_area.x() / 2, - view_area.y() / 2, - view_area.width() / 2, - view_area.height() / 2); - LetterboxPlane(frame, VideoFrame::kUPlane, half_view_area, 0x80); - LetterboxPlane(frame, VideoFrame::kVPlane, half_view_area, 0x80); +void LetterboxVideoFrame(VideoFrame* frame, const gfx::Rect& view_area) { + switch (frame->format()) { + case PIXEL_FORMAT_ARGB: + LetterboxPlane(frame, VideoFrame::kARGBPlane, view_area, 0x00); + break; + case PIXEL_FORMAT_YV12: + case PIXEL_FORMAT_I420: { + DCHECK(!(view_area.x() & 1)); + DCHECK(!(view_area.y() & 1)); + DCHECK(!(view_area.width() & 1)); + DCHECK(!(view_area.height() & 1)); + LetterboxPlane(frame, VideoFrame::kYPlane, view_area, 0x00); + gfx::Rect half_view_area(view_area.x() / 2, view_area.y() / 2, + view_area.width() / 2, view_area.height() / 2); + LetterboxPlane(frame, VideoFrame::kUPlane, half_view_area, 0x80); + LetterboxPlane(frame, VideoFrame::kVPlane, half_view_area, 0x80); + break; + } + default: + NOTREACHED(); + } } void RotatePlaneByPixels(const uint8_t* src, @@ -378,7 +391,7 @@ const int uv_stride = frame->stride(kU); if (region_in_frame != gfx::Rect(frame->coded_size())) { - LetterboxYUV(frame, region_in_frame); + LetterboxVideoFrame(frame, region_in_frame); } const int y_offset =
diff --git a/media/base/video_util.h b/media/base/video_util.h index ac255e5..6db9f79c 100644 --- a/media/base/video_util.h +++ b/media/base/video_util.h
@@ -31,12 +31,12 @@ uint8_t v, uint8_t a); -// Creates a border in |frame| such that all pixels outside of -// |view_area| are black. The size and position of |view_area| -// must be even to align correctly with the color planes. -// Only YV12 format video frames are currently supported. -MEDIA_EXPORT void LetterboxYUV(VideoFrame* frame, - const gfx::Rect& view_area); +// Creates a border in |frame| such that all pixels outside of |view_area| are +// black. Only YV12 and ARGB format video frames are currently supported. If +// format is YV12, the size and position of |view_area| must be even to align +// correctly with the color planes. +MEDIA_EXPORT void LetterboxVideoFrame(VideoFrame* frame, + const gfx::Rect& view_area); // Rotates |src| plane by |rotation| degree with possible flipping vertically // and horizontally.
diff --git a/media/base/video_util_unittest.cc b/media/base/video_util_unittest.cc index bab5b34..f11828c0 100644 --- a/media/base/video_util_unittest.cc +++ b/media/base/video_util_unittest.cc
@@ -476,7 +476,7 @@ gfx::Size(40000, 30000), gfx::Size(0, 0)).IsEmpty()); } -TEST_F(VideoUtilTest, LetterboxYUV) { +TEST_F(VideoUtilTest, LetterboxVideoFrame) { int width = 40; int height = 30; gfx::Size size(width, height); @@ -491,7 +491,7 @@ width - left_margin - right_margin, height - top_margin - bottom_margin); FillYUV(frame.get(), 0x1, 0x2, 0x3); - LetterboxYUV(frame.get(), view_area); + LetterboxVideoFrame(frame.get(), view_area); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { bool inside = x >= view_area.x() &&
diff --git a/media/capture/video/fake_video_capture_device_factory.cc b/media/capture/video/fake_video_capture_device_factory.cc index 48578c92..ded8650 100644 --- a/media/capture/video/fake_video_capture_device_factory.cc +++ b/media/capture/video/fake_video_capture_device_factory.cc
@@ -242,6 +242,12 @@ } } +void FakeVideoCaptureDeviceFactory::GetCameraLocationsAsync( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback) { + base::ResetAndReturn(&result_callback).Run(std::move(device_descriptors)); +} + // static void FakeVideoCaptureDeviceFactory::ParseFakeDevicesConfigFromOptionsString( const std::string options_string,
diff --git a/media/capture/video/fake_video_capture_device_factory.h b/media/capture/video/fake_video_capture_device_factory.h index fdfe942..6c8f68b 100644 --- a/media/capture/video/fake_video_capture_device_factory.h +++ b/media/capture/video/fake_video_capture_device_factory.h
@@ -74,6 +74,9 @@ void GetSupportedFormats( const VideoCaptureDeviceDescriptor& device_descriptor, VideoCaptureFormats* supported_formats) override; + void GetCameraLocationsAsync( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback) override; int number_of_devices() { DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/media/capture/video/file_video_capture_device_factory.cc b/media/capture/video/file_video_capture_device_factory.cc index ff643d8..6205b57 100644 --- a/media/capture/video/file_video_capture_device_factory.cc +++ b/media/capture/video/file_video_capture_device_factory.cc
@@ -78,4 +78,10 @@ supported_formats->push_back(capture_format); } +void FileVideoCaptureDeviceFactory::GetCameraLocationsAsync( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback) { + base::ResetAndReturn(&result_callback).Run(std::move(device_descriptors)); +} + } // namespace media
diff --git a/media/capture/video/file_video_capture_device_factory.h b/media/capture/video/file_video_capture_device_factory.h index 8dfd3060b..0799e9c 100644 --- a/media/capture/video/file_video_capture_device_factory.h +++ b/media/capture/video/file_video_capture_device_factory.h
@@ -28,6 +28,9 @@ void GetSupportedFormats( const VideoCaptureDeviceDescriptor& device_descriptor, VideoCaptureFormats* supported_formats) override; + void GetCameraLocationsAsync( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback) override; }; } // namespace media
diff --git a/media/capture/video/video_capture_device_factory.cc b/media/capture/video/video_capture_device_factory.cc index 89f37c4..4dd4f7b 100644 --- a/media/capture/video/video_capture_device_factory.cc +++ b/media/capture/video/video_capture_device_factory.cc
@@ -69,4 +69,10 @@ } #endif +void VideoCaptureDeviceFactory::GetCameraLocationsAsync( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback) { + NOTIMPLEMENTED(); +} + } // namespace media
diff --git a/media/capture/video/video_capture_device_factory.h b/media/capture/video/video_capture_device_factory.h index 73a8c48..1cd174ff 100644 --- a/media/capture/video/video_capture_device_factory.h +++ b/media/capture/video/video_capture_device_factory.h
@@ -62,6 +62,16 @@ virtual void GetDeviceDescriptors( VideoCaptureDeviceDescriptors* device_descriptors) = 0; + // Gets the location of all cameras of a device asynchronously. + // Used for platforms where camera location enumeration is asynchronous + // operation, i.e. UWP API on Windows 10. + // This method should be called before allocating or starting a device. + using DeviceDescriptorsCallback = base::OnceCallback<void( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors)>; + virtual void GetCameraLocationsAsync( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback); + protected: base::ThreadChecker thread_checker_;
diff --git a/media/capture/video/video_capture_system_impl.cc b/media/capture/video/video_capture_system_impl.cc index 7f75104..98cbe01 100644 --- a/media/capture/video/video_capture_system_impl.cc +++ b/media/capture/video/video_capture_system_impl.cc
@@ -4,6 +4,9 @@ #include "media/capture/video/video_capture_system_impl.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "build/build_config.h" #include "media/base/bind_to_current_loop.h" namespace { @@ -68,27 +71,31 @@ void VideoCaptureSystemImpl::GetDeviceInfosAsync( DeviceInfoCallback result_callback) { DCHECK(thread_checker_.CalledOnValidThread()); - VideoCaptureDeviceDescriptors descriptors; - factory_->GetDeviceDescriptors(&descriptors); - // For devices for which we already have an entry in |devices_info_cache_|, - // we do not want to query the |factory_| for supported formats again. We - // simply copy them from |devices_info_cache_|. - std::vector<VideoCaptureDeviceInfo> new_devices_info_cache; - new_devices_info_cache.reserve(descriptors.size()); - for (const auto& descriptor : descriptors) { - if (auto* cached_info = LookupDeviceInfoFromId(descriptor.device_id)) { - new_devices_info_cache.push_back(*cached_info); - } else { - // Query for supported formats in order to create the entry. - VideoCaptureDeviceInfo device_info(descriptor); - factory_->GetSupportedFormats(descriptor, &device_info.supported_formats); - ConsolidateCaptureFormats(&device_info.supported_formats); - new_devices_info_cache.push_back(device_info); - } + + device_enum_request_queue_.push_back(std::move(result_callback)); + if (device_enum_request_queue_.size() == 1) { + ProcessDeviceInfoRequest(); + } +} + +void VideoCaptureSystemImpl::ProcessDeviceInfoRequest() { + DeviceEnumQueue::iterator request = device_enum_request_queue_.begin(); + if (request == device_enum_request_queue_.end()) { + return; } - devices_info_cache_.swap(new_devices_info_cache); - base::ResetAndReturn(&result_callback).Run(devices_info_cache_); + std::unique_ptr<VideoCaptureDeviceDescriptors> descriptors = + std::make_unique<VideoCaptureDeviceDescriptors>(); + factory_->GetDeviceDescriptors(descriptors.get()); + +#if defined(OS_WIN) + factory_->GetCameraLocationsAsync( + std::move(descriptors), + base::BindOnce(&VideoCaptureSystemImpl::DeviceInfosReady, + base::Unretained(this))); +#else + DeviceInfosReady(std::move(descriptors)); +#endif } // Creates a VideoCaptureDevice object. Returns NULL if something goes wrong. @@ -114,4 +121,32 @@ return &(*iter); } +void VideoCaptureSystemImpl::DeviceInfosReady( + std::unique_ptr<VideoCaptureDeviceDescriptors> descriptors) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(!device_enum_request_queue_.empty()); + // For devices for which we already have an entry in |devices_info_cache_|, + // we do not want to query the |factory_| for supported formats again. We + // simply copy them from |devices_info_cache_|. + std::vector<VideoCaptureDeviceInfo> new_devices_info_cache; + new_devices_info_cache.reserve(descriptors->size()); + for (const auto& descriptor : *descriptors) { + if (auto* cached_info = LookupDeviceInfoFromId(descriptor.device_id)) { + new_devices_info_cache.push_back(*cached_info); + } else { + // Query for supported formats in order to create the entry. + VideoCaptureDeviceInfo device_info(descriptor); + factory_->GetSupportedFormats(descriptor, &device_info.supported_formats); + ConsolidateCaptureFormats(&device_info.supported_formats); + new_devices_info_cache.push_back(device_info); + } + } + + devices_info_cache_.swap(new_devices_info_cache); + base::ResetAndReturn(&device_enum_request_queue_.front()) + .Run(devices_info_cache_); + + device_enum_request_queue_.pop_front(); + ProcessDeviceInfoRequest(); +} } // namespace media
diff --git a/media/capture/video/video_capture_system_impl.h b/media/capture/video/video_capture_system_impl.h index dfaaf418d..581979a 100644 --- a/media/capture/video/video_capture_system_impl.h +++ b/media/capture/video/video_capture_system_impl.h
@@ -23,12 +23,19 @@ const std::string& device_id) override; private: + using DeviceEnumQueue = std::list<DeviceInfoCallback>; + // Returns nullptr if no descriptor found. const VideoCaptureDeviceInfo* LookupDeviceInfoFromId( const std::string& device_id); + void ProcessDeviceInfoRequest(); + void DeviceInfosReady( + std::unique_ptr<VideoCaptureDeviceDescriptors> descriptors); + const std::unique_ptr<VideoCaptureDeviceFactory> factory_; std::vector<VideoCaptureDeviceInfo> devices_info_cache_; + DeviceEnumQueue device_enum_request_queue_; base::ThreadChecker thread_checker_; };
diff --git a/media/capture/video/win/video_capture_device_factory_win.cc b/media/capture/video/win/video_capture_device_factory_win.cc index 4475bbbe..863fdad6 100644 --- a/media/capture/video/win/video_capture_device_factory_win.cc +++ b/media/capture/video/win/video_capture_device_factory_win.cc
@@ -8,6 +8,9 @@ #include <mferror.h> #include <objbase.h> #include <stddef.h> +#include <windows.devices.enumeration.h> +#include <windows.foundation.collections.h> +#include <wrl.h> #include <wrl/client.h> #include "base/command_line.h" @@ -17,17 +20,26 @@ #include "base/single_thread_task_runner.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" +#include "base/win/core_winrt_util.h" #include "base/win/scoped_co_mem.h" #include "base/win/scoped_variant.h" +#include "base/win/windows_version.h" #include "media/base/media_switches.h" #include "media/base/win/mf_initializer.h" #include "media/capture/video/win/metrics.h" #include "media/capture/video/win/video_capture_device_mf_win.h" #include "media/capture/video/win/video_capture_device_win.h" +using namespace ABI::Windows::Devices::Enumeration; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace Microsoft::WRL; + using Descriptor = media::VideoCaptureDeviceDescriptor; using Descriptors = media::VideoCaptureDeviceDescriptors; +using base::win::GetActivationFactory; using base::win::ScopedCoMem; +using base::win::ScopedHString; using base::win::ScopedVariant; using Microsoft::WRL::ComPtr; @@ -53,6 +65,11 @@ BLACKLISTED_CAMERA_MAX = BLACKLISTED_CAMERA_EPOCCAM, }; +#define UWP_ENUM_ERROR_HANDLER(hr, err_log) \ + DLOG(WARNING) << err_log << logging::SystemErrorCodeToString(hr); \ + origin_task_runner_->PostTask(FROM_HERE, \ + base::BindOnce(device_info_callback, nullptr)) + // Blacklisted devices are identified by a characteristic prefix of the name. // This prefix is used case-insensitively. This list must be kept in sync with // |BlacklistedCameraNames|. @@ -390,9 +407,25 @@ } } +bool IsEnclosureLocationSupported() { + // DeviceInformation class is only available in Win10 onwards (v10.0.10240.0). + if (base::win::GetVersion() < base::win::VERSION_WIN10) { + DVLOG(1) << "DeviceInformation not supported before Windows 10"; + return false; + } + + if (!(base::win::ResolveCoreWinRTDelayload() && + ScopedHString::ResolveCoreWinRTStringDelayload())) { + DLOG(ERROR) << "Failed loading functions from combase.dll"; + return false; + } + + return true; +} + } // namespace -// Returns true iff the current platform supports the Media Foundation API +// Returns true if the current platform supports the Media Foundation API // and that the DLLs are available. On Vista this API is an optional download // but the API is advertised as a part of Windows 7 and onwards. However, // we've seen that the required DLLs are not available in some Win7 @@ -405,7 +438,9 @@ VideoCaptureDeviceFactoryWin::VideoCaptureDeviceFactoryWin() : use_media_foundation_( - base::FeatureList::IsEnabled(media::kMediaFoundationVideoCapture)) { + base::FeatureList::IsEnabled(media::kMediaFoundationVideoCapture)), + com_thread_("Windows Video Capture COM Thread"), + weak_ptr_factory_(this) { mf_enum_device_sources_func_ = PlatformSupportsMediaFoundation() ? MFEnumDeviceSources : nullptr; if (!PlatformSupportsMediaFoundation()) { @@ -421,6 +456,8 @@ } } +VideoCaptureDeviceFactoryWin::~VideoCaptureDeviceFactoryWin() = default; + std::unique_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryWin::CreateDevice( const Descriptor& device_descriptor) { DCHECK(thread_checker_.CalledOnValidThread()); @@ -435,7 +472,7 @@ break; } std::unique_ptr<VideoCaptureDevice> device( - new VideoCaptureDeviceMFWin(source)); + new VideoCaptureDeviceMFWin(device_descriptor, source)); DVLOG(1) << " MediaFoundation Device: " << device_descriptor.display_name(); if (static_cast<VideoCaptureDeviceMFWin*>(device.get())->Init()) @@ -460,6 +497,7 @@ void VideoCaptureDeviceFactoryWin::GetDeviceDescriptors( VideoCaptureDeviceDescriptors* device_descriptors) { DCHECK(thread_checker_.CalledOnValidThread()); + if (use_media_foundation_) { GetDeviceDescriptorsMediaFoundation(mf_enum_device_sources_func_, device_descriptors); @@ -468,6 +506,170 @@ } } +void VideoCaptureDeviceFactoryWin::GetCameraLocationsAsync( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (IsEnclosureLocationSupported()) { + origin_task_runner_ = base::ThreadTaskRunnerHandle::Get(); + com_thread_.init_com_with_mta(true); + com_thread_.Start(); + com_thread_.task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&VideoCaptureDeviceFactoryWin::EnumerateDevicesUWP, + base::Unretained(this), std::move(device_descriptors), + std::move(result_callback))); + } else { + DeviceInfoReady(std::move(device_descriptors), std::move(result_callback)); + } +} + +void VideoCaptureDeviceFactoryWin::EnumerateDevicesUWP( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback) { + DCHECK_GE(base::win::OSInfo::GetInstance()->version_number().build, 10240); + + VideoCaptureDeviceFactoryWin* factory = this; + scoped_refptr<base::SingleThreadTaskRunner> com_thread_runner = + com_thread_.task_runner(); + + // The |device_info_callback| created by base::BindRepeating() is copyable, + // which is necessary for the below lambda function of |callback| for the + // asynchronous operation. The reason is to permanently capture anything in a + // lambda, it must be copyable, merely movable is insufficient. + auto device_info_callback = base::BindRepeating( + &VideoCaptureDeviceFactoryWin::FoundAllDevicesUWP, + base::Unretained(factory), base::Passed(&device_descriptors), + base::Passed(&result_callback)); + auto callback = + Callback<IAsyncOperationCompletedHandler<DeviceInformationCollection*>>( + [factory, com_thread_runner, device_info_callback]( + IAsyncOperation<DeviceInformationCollection*>* operation, + AsyncStatus status) -> HRESULT { + com_thread_runner->PostTask( + FROM_HERE, base::BindOnce(device_info_callback, + base::Unretained(operation))); + return S_OK; + }); + + ComPtr<IDeviceInformationStatics> dev_info_statics; + HRESULT hr = GetActivationFactory< + IDeviceInformationStatics, + RuntimeClass_Windows_Devices_Enumeration_DeviceInformation>( + &dev_info_statics); + if (FAILED(hr)) { + UWP_ENUM_ERROR_HANDLER(hr, "DeviceInformation factory failed: "); + return; + } + + IAsyncOperation<DeviceInformationCollection*>* async_op; + hr = dev_info_statics->FindAllAsyncDeviceClass(DeviceClass_VideoCapture, + &async_op); + if (FAILED(hr)) { + UWP_ENUM_ERROR_HANDLER(hr, "Find all devices asynchronously failed: "); + return; + } + + hr = async_op->put_Completed(callback.Get()); + if (FAILED(hr)) { + UWP_ENUM_ERROR_HANDLER(hr, "Register async operation callback failed: "); + return; + } + + // Keep a reference to incomplete |asyn_op| for releasing later. + async_ops_.insert(async_op); +} + +void VideoCaptureDeviceFactoryWin::FoundAllDevicesUWP( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback, + IAsyncOperation<DeviceInformationCollection*>* operation) { + if (!operation) { + origin_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&VideoCaptureDeviceFactoryWin::DeviceInfoReady, + weak_ptr_factory_.GetWeakPtr(), + std::move(device_descriptors), + std::move(result_callback))); + return; + } + + ComPtr<IVectorView<DeviceInformation*>> devices; + operation->GetResults(devices.GetAddressOf()); + + unsigned int count = 0; + devices->get_Size(&count); + + for (unsigned int j = 0; j < count; ++j) { + ComPtr<IDeviceInformation> device_info; + HRESULT hr = devices->GetAt(j, device_info.GetAddressOf()); + if (SUCCEEDED(hr)) { + HSTRING id; + device_info->get_Id(&id); + + std::string device_id = ScopedHString(id).GetAsUTF8(); + transform(device_id.begin(), device_id.end(), device_id.begin(), + ::tolower); + const std::string model_id = GetDeviceModelId(device_id); + + ComPtr<IEnclosureLocation> enclosure_location; + hr = + device_info->get_EnclosureLocation(enclosure_location.GetAddressOf()); + if (FAILED(hr)) { + break; + } + + VideoFacingMode facing = VideoFacingMode::MEDIA_VIDEO_FACING_NONE; + if (enclosure_location) { + Panel panel; + enclosure_location->get_Panel(&panel); + switch (panel) { + case Panel_Unknown: + facing = VideoFacingMode::MEDIA_VIDEO_FACING_NONE; + break; + case Panel_Front: + facing = VideoFacingMode::MEDIA_VIDEO_FACING_USER; + break; + case Panel_Back: + facing = VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT; + break; + default: + facing = VideoFacingMode::MEDIA_VIDEO_FACING_NONE; + } + } + + for (Descriptor& descriptor : *device_descriptors) { + if (!descriptor.model_id.compare(model_id)) { + descriptor.facing = facing; + break; + } + } + } + } + + origin_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&VideoCaptureDeviceFactoryWin::DeviceInfoReady, + base::Unretained(this), std::move(device_descriptors), + std::move(result_callback))); + + auto it = async_ops_.find(operation); + DCHECK(it != async_ops_.end()); + (*it)->Release(); + async_ops_.erase(it); +} + +void VideoCaptureDeviceFactoryWin::DeviceInfoReady( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback) { + if (com_thread_.IsRunning()) { + com_thread_.Stop(); + } + + base::ResetAndReturn(&result_callback).Run(std::move(device_descriptors)); +} + void VideoCaptureDeviceFactoryWin::GetSupportedFormats( const Descriptor& device, VideoCaptureFormats* formats) {
diff --git a/media/capture/video/win/video_capture_device_factory_win.h b/media/capture/video/win/video_capture_device_factory_win.h index 64cf2a5c..91135b8 100644 --- a/media/capture/video/win/video_capture_device_factory_win.h +++ b/media/capture/video/win/video_capture_device_factory_win.h
@@ -8,11 +8,17 @@ #define MEDIA_CAPTURE_VIDEO_WIN_VIDEO_CAPTURE_DEVICE_FACTORY_WIN_H_ #include <mfidl.h> +#include <windows.devices.enumeration.h> + #include "base/macros.h" +#include "base/threading/thread.h" #include "media/capture/video/video_capture_device_factory.h" namespace media { +using ABI::Windows::Foundation::IAsyncOperation; +using ABI::Windows::Devices::Enumeration::DeviceInformationCollection; + // Extension of VideoCaptureDeviceFactory to create and manipulate Windows // devices, via either DirectShow or MediaFoundation APIs. class CAPTURE_EXPORT VideoCaptureDeviceFactoryWin @@ -21,7 +27,7 @@ static bool PlatformSupportsMediaFoundation(); VideoCaptureDeviceFactoryWin(); - ~VideoCaptureDeviceFactoryWin() override {} + ~VideoCaptureDeviceFactoryWin() override; using MFEnumDeviceSourcesFunc = decltype(&MFEnumDeviceSources); @@ -32,6 +38,9 @@ void GetSupportedFormats( const VideoCaptureDeviceDescriptor& device_descriptor, VideoCaptureFormats* supported_formats) override; + void GetCameraLocationsAsync( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback) override; void set_use_media_foundation_for_testing(bool use) { use_media_foundation_ = use; @@ -42,12 +51,29 @@ } private: + void EnumerateDevicesUWP( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback); + void FoundAllDevicesUWP( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback, + IAsyncOperation<DeviceInformationCollection*>* operation); + void DeviceInfoReady( + std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback); + bool use_media_foundation_; // In production code, when Media Foundation libraries are available, // |mf_enum_device_sources_func_| points to MFEnumDeviceSources. It enables // mock of Media Foundation API in unit tests. MFEnumDeviceSourcesFunc mf_enum_device_sources_func_ = nullptr; + // For calling WinRT methods on a COM initiated thread. + base::Thread com_thread_; + scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; + std::unordered_set<IAsyncOperation<DeviceInformationCollection*>*> async_ops_; + base::WeakPtrFactory<VideoCaptureDeviceFactoryWin> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactoryWin); };
diff --git a/media/capture/video/win/video_capture_device_mf_win.cc b/media/capture/video/win/video_capture_device_mf_win.cc index 7230966..198fa98 100644 --- a/media/capture/video/win/video_capture_device_mf_win.cc +++ b/media/capture/video/win/video_capture_device_mf_win.cc
@@ -394,7 +394,7 @@ base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(raw_time_stamp / 10); if (!sample) { - observer_->OnIncomingCapturedData(NULL, 0, 0, reference_time, timestamp); + observer_->OnIncomingCapturedData(NULL, 0, reference_time, timestamp); return S_OK; } @@ -408,8 +408,8 @@ DWORD length = 0, max_length = 0; BYTE* data = NULL; buffer->Lock(&data, &max_length, &length); - observer_->OnIncomingCapturedData(data, length, GetCameraRotation(), - reference_time, timestamp); + observer_->OnIncomingCapturedData(data, length, reference_time, + timestamp); buffer->Unlock(); } } @@ -553,13 +553,17 @@ return hr; } -VideoCaptureDeviceMFWin::VideoCaptureDeviceMFWin(ComPtr<IMFMediaSource> source) - : VideoCaptureDeviceMFWin(source, nullptr) {} +VideoCaptureDeviceMFWin::VideoCaptureDeviceMFWin( + const VideoCaptureDeviceDescriptor& device_descriptor, + ComPtr<IMFMediaSource> source) + : VideoCaptureDeviceMFWin(device_descriptor, source, nullptr) {} VideoCaptureDeviceMFWin::VideoCaptureDeviceMFWin( + const VideoCaptureDeviceDescriptor& device_descriptor, ComPtr<IMFMediaSource> source, ComPtr<IMFCaptureEngine> engine) - : create_mf_photo_callback_(base::BindRepeating(&CreateMFPhotoCallback)), + : facing_mode_(device_descriptor.facing), + create_mf_photo_callback_(base::BindRepeating(&CreateMFPhotoCallback)), is_initialized_(false), max_retry_count_(200), retry_delay_in_ms_(50), @@ -945,7 +949,6 @@ void VideoCaptureDeviceMFWin::OnIncomingCapturedData( const uint8_t* data, int length, - int rotation, base::TimeTicks reference_time, base::TimeDelta timestamp) { base::AutoLock lock(lock_); @@ -955,8 +958,8 @@ if (client_.get()) { client_->OnIncomingCapturedData( - data, length, selected_video_capability_->supported_format, rotation, - reference_time, timestamp); + data, length, selected_video_capability_->supported_format, + GetCameraRotation(facing_mode_), reference_time, timestamp); } while (!video_stream_take_photo_callbacks_.empty()) {
diff --git a/media/capture/video/win/video_capture_device_mf_win.h b/media/capture/video/win/video_capture_device_mf_win.h index c43b143b..a4a4acf 100644 --- a/media/capture/video/win/video_capture_device_mf_win.h +++ b/media/capture/video/win/video_capture_device_mf_win.h
@@ -41,8 +41,10 @@ VideoPixelFormat* format); explicit VideoCaptureDeviceMFWin( + const VideoCaptureDeviceDescriptor& device_descriptor, Microsoft::WRL::ComPtr<IMFMediaSource> source); explicit VideoCaptureDeviceMFWin( + const VideoCaptureDeviceDescriptor& device_descriptor, Microsoft::WRL::ComPtr<IMFMediaSource> source, Microsoft::WRL::ComPtr<IMFCaptureEngine> engine); @@ -64,7 +66,6 @@ // Captured new video data. void OnIncomingCapturedData(const uint8_t* data, int length, - int rotation, base::TimeTicks reference_time, base::TimeDelta timestamp); void OnEvent(IMFMediaEvent* media_event); @@ -110,6 +111,7 @@ void OnError(const base::Location& from_here, HRESULT hr); void OnError(const base::Location& from_here, const char* message); + VideoFacingMode facing_mode_; CreateMFPhotoCallbackCB create_mf_photo_callback_; scoped_refptr<MFVideoCallback> video_callback_; bool is_initialized_;
diff --git a/media/capture/video/win/video_capture_device_mf_win_unittest.cc b/media/capture/video/win/video_capture_device_mf_win_unittest.cc index 7ef9f343..cc7c0de 100644 --- a/media/capture/video/win/video_capture_device_mf_win_unittest.cc +++ b/media/capture/video/win/video_capture_device_mf_win_unittest.cc
@@ -809,11 +809,13 @@ class VideoCaptureDeviceMFWinTest : public ::testing::Test { protected: VideoCaptureDeviceMFWinTest() - : media_source_(new MockMFMediaSource()), + : descriptor_(VideoCaptureDeviceDescriptor()), + media_source_(new MockMFMediaSource()), engine_(new MockMFCaptureEngine()), client_(new MockClient()), image_capture_client_(new MockImageCaptureClient()), - device_(new VideoCaptureDeviceMFWin(media_source_, engine_)), + device_( + new VideoCaptureDeviceMFWin(descriptor_, media_source_, engine_)), capture_source_(new MockMFCaptureSource()), capture_preview_sink_(new MockCapturePreviewSink()), media_foundation_supported_( @@ -1022,6 +1024,7 @@ .WillRepeatedly(Invoke(get_device_media_type)); } + VideoCaptureDeviceDescriptor descriptor_; Microsoft::WRL::ComPtr<MockMFMediaSource> media_source_; Microsoft::WRL::ComPtr<MockMFCaptureEngine> engine_; std::unique_ptr<MockClient> client_;
diff --git a/media/capture/video/win/video_capture_device_utils_win.cc b/media/capture/video/win/video_capture_device_utils_win.cc index d0ce2c5..d661a62 100644 --- a/media/capture/video/win/video_capture_device_utils_win.cc +++ b/media/capture/video/win/video_capture_device_utils_win.cc
@@ -6,18 +6,27 @@ #include <iostream> +#include "base/win/windows_version.h" + namespace media { // Note: Because we can't find a solid way to detect camera location (front/back // or external USB camera) with Win32 APIs, assume it's always front camera when // auto rotation is enabled for now. -int GetCameraRotation() { +int GetCameraRotation(VideoFacingMode facing) { int rotation = 0; if (!IsAutoRotationEnabled()) { return rotation; } + // Before Win10, we can't distinguish if the selected camera is an internal or + // external one. So we assume it's internal and do the frame rotation if the + // auto rotation is enabled to cover most user cases. + if (!IsInternalCamera(facing)) { + return rotation; + } + // When display is only on external monitors, the auto-rotation state still // may be ENALBED on the target device. In that case, we shouldn't query the // display orientation and the built-in camera will be treated as an external @@ -77,6 +86,19 @@ return false; } +bool IsInternalCamera(VideoFacingMode facing) { + if (base::win::GetVersion() < base::win::VERSION_WIN10) { + return true; + } + + if (facing == MEDIA_VIDEO_FACING_USER || + facing == MEDIA_VIDEO_FACING_ENVIRONMENT) { + return true; + } + + return false; +} + bool HasActiveInternalDisplayDevice(DISPLAY_DEVICE* internal_display_device) { DISPLAY_DEVICE display_device; display_device.cb = sizeof(display_device);
diff --git a/media/capture/video/win/video_capture_device_utils_win.h b/media/capture/video/win/video_capture_device_utils_win.h index 56276260..84c6b1a 100644 --- a/media/capture/video/win/video_capture_device_utils_win.h +++ b/media/capture/video/win/video_capture_device_utils_win.h
@@ -7,13 +7,16 @@ #include <windows.h> +#include "media/base/video_facing.h" + namespace media { // Returns the rotation of the camera. Returns 0 if it's not a built-in camera, // or auto-rotation is not enabled, or only displays on external monitors. -int GetCameraRotation(); +int GetCameraRotation(VideoFacingMode facing); bool IsAutoRotationEnabled(); +bool IsInternalCamera(VideoFacingMode facing); // Returns true if target device has active internal display panel, e.g. the // screen attached to tablets or laptops, and stores its device info in
diff --git a/media/capture/video/win/video_capture_device_win.cc b/media/capture/video/win/video_capture_device_win.cc index b016957..2a562b36 100644 --- a/media/capture/video/win/video_capture_device_win.cc +++ b/media/capture/video/win/video_capture_device_win.cc
@@ -858,7 +858,8 @@ if (timestamp == kNoTimestamp) timestamp = base::TimeTicks::Now() - first_ref_time_; - client_->OnIncomingCapturedData(buffer, length, format, GetCameraRotation(), + client_->OnIncomingCapturedData(buffer, length, format, + GetCameraRotation(device_descriptor_.facing), base::TimeTicks::Now(), timestamp); while (!take_photo_callbacks_.empty()) {
diff --git a/media/cdm/stub/stub_cdm.cc b/media/cdm/stub/stub_cdm.cc deleted file mode 100644 index faf1ab2..0000000 --- a/media/cdm/stub/stub_cdm.cc +++ /dev/null
@@ -1,166 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/cdm/stub/stub_cdm.h" - -#include "base/logging.h" -#include "base/numerics/safe_conversions.h" -#include "base/strings/string_number_conversions.h" - -// Version number for this stub. The third number represents the -// cdm::ContentDecryptionModule version. -const char kStubCdmVersion[] = "1.4.8.0"; - -void INITIALIZE_CDM_MODULE() { -} - -void DeinitializeCdmModule() { -} - -void* CreateCdmInstance(int cdm_interface_version, - const char* /* key_system */, - uint32_t /* key_system_size */, - GetCdmHostFunc get_cdm_host_func, - void* user_data) { - DVLOG(1) << "CreateCdmInstance()"; - - if (cdm_interface_version != media::StubCdmInterface::kVersion) - return nullptr; - - media::StubCdmInterface::Host* host = - static_cast<media::StubCdmInterface::Host*>(get_cdm_host_func( - media::StubCdmInterface::Host::kVersion, user_data)); - if (!host) - return nullptr; - - return new media::StubCdm(host); -} - -const char* GetCdmVersion() { - return kStubCdmVersion; -} - -namespace media { - -StubCdm::StubCdm(Host* host) : host_(host), next_session_id_(0) { -} - -StubCdm::~StubCdm() { -} - -void StubCdm::Initialize(bool /* allow_distinctive_identifier */, - bool /* allow_persistent_state */) { -} - -void StubCdm::CreateSessionAndGenerateRequest( - uint32_t promise_id, - cdm::SessionType /* session_type */, - cdm::InitDataType /* init_data_type */, - const uint8_t* /* init_data */, - uint32_t /* init_data_size */) { - // Provide a dummy message (with a trivial session ID) to enable some testing - // and be consistent with existing testing without a license server. - std::string session_id(base::UintToString(next_session_id_++)); - host_->OnResolveNewSessionPromise( - promise_id, session_id.data(), - base::checked_cast<uint32_t>(session_id.length())); - host_->OnSessionMessage(session_id.data(), - base::checked_cast<uint32_t>(session_id.length()), - cdm::kLicenseRequest, nullptr, 0, nullptr, 0); -} - -void StubCdm::LoadSession(uint32_t promise_id, - cdm::SessionType /* session_type */, - const char* /* session_id */, - uint32_t /* session_id_length */) { - FailRequest(promise_id); -} - -void StubCdm::UpdateSession(uint32_t promise_id, - const char* /* session_id */, - uint32_t /* session_id_length */, - const uint8_t* /* response */, - uint32_t /* response_size */) { - FailRequest(promise_id); -} - -void StubCdm::CloseSession(uint32_t promise_id, - const char* /* session_id */, - uint32_t /* session_id_length */) { - FailRequest(promise_id); -} - -void StubCdm::RemoveSession(uint32_t promise_id, - const char* /* session_id */, - uint32_t /* session_id_length */) { - FailRequest(promise_id); -} - -void StubCdm::SetServerCertificate( - uint32_t promise_id, - const uint8_t* /* server_certificate_data */, - uint32_t /* server_certificate_data_size */) { - FailRequest(promise_id); -} - -void StubCdm::TimerExpired(void* /* context */) { -} - -cdm::Status StubCdm::Decrypt(const cdm::InputBuffer& /* encrypted_buffer */, - cdm::DecryptedBlock* /* decrypted_block */) { - return cdm::kDecryptError; -} - -cdm::Status StubCdm::InitializeAudioDecoder( - const cdm::AudioDecoderConfig& /* audio_decoder_config */) { - return cdm::kSuccess; -} - -cdm::Status StubCdm::InitializeVideoDecoder( - const cdm::VideoDecoderConfig& /* video_decoder_config */) { - return cdm::kSuccess; -} - -void StubCdm::ResetDecoder(cdm::StreamType /* decoder_type */) { -} - -void StubCdm::DeinitializeDecoder(cdm::StreamType /* decoder_type */) { -} - -cdm::Status StubCdm::DecryptAndDecodeFrame( - const cdm::InputBuffer& /* encrypted_buffer */, - cdm::VideoFrame* /* decoded_frame */) { - return cdm::kNoKey; -} - -cdm::Status StubCdm::DecryptAndDecodeSamples( - const cdm::InputBuffer& /* encrypted_buffer */, - cdm::AudioFrames* /* audio_frames */) { - return cdm::kNoKey; -} - -void StubCdm::Destroy() { - delete this; -} - -void StubCdm::OnPlatformChallengeResponse( - const cdm::PlatformChallengeResponse& /* response */) { - NOTREACHED(); -} - -void StubCdm::OnQueryOutputProtectionStatus( - cdm::QueryResult /* result */, - uint32_t /* link_mask */, - uint32_t /* output_protection_mask */) { - NOTREACHED(); -}; - -void StubCdm::FailRequest(uint32_t promise_id) { - std::string message("Operation not supported by stub CDM."); - host_->OnRejectPromise(promise_id, cdm::kInvalidAccessError, 0, - message.data(), - base::checked_cast<uint32_t>(message.length())); -} - -} // namespace media
diff --git a/media/cdm/stub/stub_cdm.h b/media/cdm/stub/stub_cdm.h deleted file mode 100644 index 8d7623a..0000000 --- a/media/cdm/stub/stub_cdm.h +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_CDM_STUB_STUB_CDM_H_ -#define MEDIA_CDM_STUB_STUB_CDM_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "media/cdm/api/content_decryption_module.h" - -namespace media { - -typedef cdm::ContentDecryptionModule_8 StubCdmInterface; - -// Dummy implementation of the cdm::ContentDecryptionModule interface. -class StubCdm : public StubCdmInterface { - public: - explicit StubCdm(Host* host); - ~StubCdm() override; - - // StubCdmInterface implementation. - void Initialize(bool allow_distinctive_identifier, - bool allow_persistent_state) override; - void CreateSessionAndGenerateRequest(uint32_t promise_id, - cdm::SessionType session_type, - cdm::InitDataType init_data_type, - const uint8_t* init_data, - uint32_t init_data_size) override; - void LoadSession(uint32_t promise_id, - cdm::SessionType session_type, - const char* session_id, - uint32_t session_id_length) override; - void UpdateSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_length, - const uint8_t* response, - uint32_t response_size) override; - void CloseSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_length) override; - void RemoveSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_length) override; - void SetServerCertificate(uint32_t promise_id, - const uint8_t* server_certificate_data, - uint32_t server_certificate_data_size) override; - void TimerExpired(void* context) override; - cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, - cdm::DecryptedBlock* decrypted_block) override; - cdm::Status InitializeAudioDecoder( - const cdm::AudioDecoderConfig& audio_decoder_config) override; - cdm::Status InitializeVideoDecoder( - const cdm::VideoDecoderConfig& video_decoder_config) override; - void DeinitializeDecoder(cdm::StreamType decoder_type) override; - void ResetDecoder(cdm::StreamType decoder_type) override; - cdm::Status DecryptAndDecodeFrame(const cdm::InputBuffer& encrypted_buffer, - cdm::VideoFrame* video_frame) override; - cdm::Status DecryptAndDecodeSamples(const cdm::InputBuffer& encrypted_buffer, - cdm::AudioFrames* audio_frames) override; - void Destroy() override; - void OnPlatformChallengeResponse( - const cdm::PlatformChallengeResponse& response) override; - void OnQueryOutputProtectionStatus(cdm::QueryResult result, - uint32_t link_mask, - uint32_t output_protection_mask) override; - - private: - // Helper function that rejects the promise specified by |promise_id|. - void FailRequest(uint32_t promise_id); - - Host* host_; - - uint32_t next_session_id_; - - DISALLOW_COPY_AND_ASSIGN(StubCdm); -}; - -} // namespace media - -#endif // MEDIA_CDM_STUB_STUB_CDM_H_
diff --git a/media/filters/PRESUBMIT.py b/media/filters/PRESUBMIT.py index 6cdf17c4..e8b1f08 100644 --- a/media/filters/PRESUBMIT.py +++ b/media/filters/PRESUBMIT.py
@@ -21,7 +21,7 @@ cl, [ 'luci.chromium.try:linux_optional_gpu_tests_rel', - 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'luci.chromium.try:mac_optional_gpu_tests_rel', 'master.tryserver.chromium.win:win_optional_gpu_tests_rel', 'master.tryserver.chromium.android:android_optional_gpu_tests_rel', ],
diff --git a/media/gpu/PRESUBMIT.py b/media/gpu/PRESUBMIT.py index fab19b6..6d49ed3 100644 --- a/media/gpu/PRESUBMIT.py +++ b/media/gpu/PRESUBMIT.py
@@ -21,7 +21,7 @@ cl, [ 'luci.chromium.try:linux_optional_gpu_tests_rel', - 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'luci.chromium.try:mac_optional_gpu_tests_rel', 'master.tryserver.chromium.win:win_optional_gpu_tests_rel', 'master.tryserver.chromium.android:android_optional_gpu_tests_rel', ],
diff --git a/net/cert/ct_policy_enforcer_unittest.cc b/net/cert/ct_policy_enforcer_unittest.cc index d39017f..906cfc9cb 100644 --- a/net/cert/ct_policy_enforcer_unittest.cc +++ b/net/cert/ct_policy_enforcer_unittest.cc
@@ -431,7 +431,7 @@ // Create a self-signed certificate with exactly the validity period. std::string cert_data; ASSERT_TRUE(x509_util::CreateSelfSignedCert( - private_key.get(), x509_util::DIGEST_SHA256, "CN=test", + private_key->key(), x509_util::DIGEST_SHA256, "CN=test", i * 10 + required_scts, start, end, &cert_data)); scoped_refptr<X509Certificate> cert( X509Certificate::CreateFromBytes(cert_data.data(), cert_data.size()));
diff --git a/net/cert/x509_util.cc b/net/cert/x509_util.cc index b055874..6d2ed5552 100644 --- a/net/cert/x509_util.cc +++ b/net/cert/x509_util.cc
@@ -202,10 +202,10 @@ std::string* der_cert) { std::unique_ptr<crypto::RSAPrivateKey> new_key( crypto::RSAPrivateKey::Create(kRSAKeyLength)); - if (!new_key.get()) + if (!new_key) return false; - bool success = CreateSelfSignedCert(new_key.get(), + bool success = CreateSelfSignedCert(new_key->key(), kSignatureDigestAlgorithm, subject, serial_number, @@ -218,7 +218,7 @@ return success; } -bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, +bool CreateSelfSignedCert(EVP_PKEY* key, DigestAlgorithm alg, const std::string& subject, uint32_t serial_number, @@ -256,7 +256,7 @@ !AddTime(&validity, not_valid_before) || !AddTime(&validity, not_valid_after) || !AddNameWithCommonName(&tbs_cert, common_name) || // subject - !EVP_marshal_public_key(&tbs_cert, key->key()) || // subjectPublicKeyInfo + !EVP_marshal_public_key(&tbs_cert, key) || // subjectPublicKeyInfo !CBB_finish(cbb.get(), &tbs_cert_bytes, &tbs_cert_len)) { return false; } @@ -275,8 +275,7 @@ !AddRSASignatureAlgorithm(&cert, alg) || !CBB_add_asn1(&cert, &signature, CBS_ASN1_BITSTRING) || !CBB_add_u8(&signature, 0 /* no unused bits */) || - !EVP_DigestSignInit(ctx.get(), nullptr, ToEVP(alg), nullptr, - key->key()) || + !EVP_DigestSignInit(ctx.get(), nullptr, ToEVP(alg), nullptr, key) || // Compute the maximum signature length. !EVP_DigestSign(ctx.get(), nullptr, &sig_len, tbs_cert_bytes, tbs_cert_len) ||
diff --git a/net/cert/x509_util.h b/net/cert/x509_util.h index 6f0b8b215..32639e3 100644 --- a/net/cert/x509_util.h +++ b/net/cert/x509_util.h
@@ -15,6 +15,7 @@ #include "base/strings/string_piece.h" #include "base/time/time.h" #include "net/base/net_export.h" +#include "third_party/boringssl/src/include/openssl/base.h" #include "third_party/boringssl/src/include/openssl/pool.h" namespace crypto { @@ -66,7 +67,7 @@ // Creates a self-signed certificate from a provided key, using the specified // hash algorithm. -NET_EXPORT bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, +NET_EXPORT bool CreateSelfSignedCert(EVP_PKEY* key, DigestAlgorithm alg, const std::string& subject, uint32_t serial_number,
diff --git a/net/cert/x509_util_unittest.cc b/net/cert/x509_util_unittest.cc index c5d6b36..cbaadc8 100644 --- a/net/cert/x509_util_unittest.cc +++ b/net/cert/x509_util_unittest.cc
@@ -137,7 +137,7 @@ std::string der_cert; ASSERT_TRUE(x509_util::CreateSelfSignedCert( - private_key.get(), x509_util::DIGEST_SHA256, "CN=subject", 1, + private_key->key(), x509_util::DIGEST_SHA256, "CN=subject", 1, base::Time::Now(), base::Time::Now() + base::TimeDelta::FromDays(1), &der_cert));
diff --git a/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc b/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc index 4ae3ab0a..23343c0 100644 --- a/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc +++ b/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
@@ -28,6 +28,7 @@ #include "net/quic/chromium/quic_chromium_packet_writer.h" #include "net/quic/chromium/quic_http_utils.h" #include "net/quic/chromium/quic_server_info.h" +#include "net/quic/chromium/quic_stream_factory.h" #include "net/quic/chromium/quic_test_packet_maker.h" #include "net/quic/chromium/test_task_runner.h" #include "net/quic/core/crypto/crypto_protocol.h"
diff --git a/net/quic/chromium/quic_chromium_packet_writer.cc b/net/quic/chromium/quic_chromium_packet_writer.cc index af3b7c0a..5786a7f0 100644 --- a/net/quic/chromium/quic_chromium_packet_writer.cc +++ b/net/quic/chromium/quic_chromium_packet_writer.cc
@@ -38,6 +38,32 @@ count, kMaxRetries + 1); } +const net::NetworkTrafficAnnotationTag kTrafficAnnotation = + net::DefineNetworkTrafficAnnotation("quic_chromium_packet_writer", R"( + semantics { + sender: "QUIC Packet Writer" + description: + "A QUIC packet is written to the wire based on a request from " + "a QUIC stream." + trigger: + "A request from QUIC stream." + data: "Any data sent by the stream." + destination: OTHER + destination_other: "Any destination choosen by the stream." + } + policy { + cookies_allowed: NO + setting: "This feature cannot be disabled in settings." + policy_exception_justification: + "Essential for network access." + } + comments: + "All requests that are received by QUIC streams have network traffic " + "annotation, but the annotation is not passed to the writer function " + "due to technial overheads. Please see QuicChromiumClientSession and " + "QuicChromiumClientStream classes for references." + )"); + } // namespace QuicChromiumPacketWriter::ReusableIOBuffer::ReusableIOBuffer(size_t capacity) @@ -108,34 +134,9 @@ WriteResult QuicChromiumPacketWriter::WritePacketToSocketImpl() { base::TimeTicks now = base::TimeTicks::Now(); - net::NetworkTrafficAnnotationTag traffic_annotation = - net::DefineNetworkTrafficAnnotation("quic_chromium_packet_writer", R"( - semantics { - sender: "QUIC Packet Writer" - description: - "A QUIC packet is written to the wire based on a request from " - "a QUIC stream." - trigger: - "A request from QUIC stream." - data: "Any data sent by the stream." - destination: OTHER - destination_other: "Any destination choosen by the stream." - } - policy { - cookies_allowed: NO - setting: "This feature cannot be disabled in settings." - policy_exception_justification: - "Essential for network access." - } - comments: - "All requests that are received by QUIC streams have network traffic " - "annotation, but the annotation is not passed to the writer function " - "due to technial overheads. Please see QuicChromiumClientSession and " - "QuicChromiumClientStream classes for references." - )"); int rv = socket_->Write(packet_.get(), packet_->size(), write_callback_, - traffic_annotation); + kTrafficAnnotation); if (MaybeRetryAfterWriteError(rv)) return WriteResult(WRITE_STATUS_BLOCKED, ERR_IO_PENDING);
diff --git a/net/quic/chromium/quic_http_stream_test.cc b/net/quic/chromium/quic_http_stream_test.cc index b1a0f683..4d68b36 100644 --- a/net/quic/chromium/quic_http_stream_test.cc +++ b/net/quic/chromium/quic_http_stream_test.cc
@@ -34,6 +34,7 @@ #include "net/quic/chromium/quic_chromium_packet_writer.h" #include "net/quic/chromium/quic_http_utils.h" #include "net/quic/chromium/quic_server_info.h" +#include "net/quic/chromium/quic_stream_factory.h" #include "net/quic/chromium/quic_test_packet_maker.h" #include "net/quic/chromium/test_task_runner.h" #include "net/quic/core/congestion_control/send_algorithm_interface.h"
diff --git a/net/quic/chromium/quic_proxy_client_socket_unittest.cc b/net/quic/chromium/quic_proxy_client_socket_unittest.cc index d1c489ea..cd205c9 100644 --- a/net/quic/chromium/quic_proxy_client_socket_unittest.cc +++ b/net/quic/chromium/quic_proxy_client_socket_unittest.cc
@@ -25,6 +25,7 @@ #include "net/quic/chromium/quic_chromium_packet_writer.h" #include "net/quic/chromium/quic_http_utils.h" #include "net/quic/chromium/quic_server_info.h" +#include "net/quic/chromium/quic_stream_factory.h" #include "net/quic/chromium/quic_test_packet_maker.h" #include "net/quic/chromium/test_task_runner.h" #include "net/quic/core/crypto/null_encrypter.h"
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h index 706c7199..041bd2e 100644 --- a/net/quic/chromium/quic_stream_factory.h +++ b/net/quic/chromium/quic_stream_factory.h
@@ -77,6 +77,14 @@ // When a connection is idle for 30 seconds it will be closed. const int kIdleConnectionTimeoutSeconds = 30; +// The default maximum time QUIC session could be on non-default network before +// migrate back to default network. +const int64_t kMaxTimeOnNonDefaultNetworkSecs = 128; + +// The default maximum number of migrations to non default network on path +// degrading per network. Used in chromium only. +const int64_t kMaxMigrationsToNonDefaultNetworkOnPathDegrading = 5; + enum QuicPlatformNotification { NETWORK_CONNECTED, NETWORK_MADE_DEFAULT,
diff --git a/net/quic/core/quic_constants.h b/net/quic/core/quic_constants.h index c1ac1f0..e61b4d3 100644 --- a/net/quic/core/quic_constants.h +++ b/net/quic/core/quic_constants.h
@@ -115,14 +115,6 @@ // The default timeout for a connection until the crypto handshake succeeds. const int64_t kMaxTimeForCryptoHandshakeSecs = 10; // 10 secs. -// The default maximum time QUIC session could be on non-default network before -// migrate back to default network. -const int64_t kMaxTimeOnNonDefaultNetworkSecs = 128; - -// The default maximum number of migrations to non default network on path -// degrading per network. -const int64_t kMaxMigrationsToNonDefaultNetworkOnPathDegrading = 5; - // Default limit on the number of undecryptable packets the connection buffers // before the CHLO/SHLO arrive. const size_t kDefaultMaxUndecryptablePackets = 10;
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc index b737ffe..e818616 100644 --- a/net/socket/client_socket_pool_manager.cc +++ b/net/socket/client_socket_pool_manager.cc
@@ -427,6 +427,8 @@ int InitSocketHandleForTlsConnect(const HostPortPair& endpoint, HttpNetworkSession* session, + int request_load_flags, + RequestPriority request_priority, const ProxyInfo& proxy_info, const SSLConfig& ssl_config_for_origin, const SSLConfig& ssl_config_for_proxy, @@ -436,8 +438,6 @@ const CompletionCallback& callback) { DCHECK(socket_handle); HttpRequestHeaders request_extra_headers; - int request_load_flags = 0; - RequestPriority request_priority = MEDIUM; return InitSocketPoolHelper( ClientSocketPoolManager::SSL_GROUP, endpoint, request_extra_headers, request_load_flags, request_priority, session, proxy_info,
diff --git a/net/socket/client_socket_pool_manager.h b/net/socket/client_socket_pool_manager.h index df54c05..8837701 100644 --- a/net/socket/client_socket_pool_manager.h +++ b/net/socket/client_socket_pool_manager.h
@@ -146,6 +146,7 @@ const OnHostResolutionCallback& resolution_callback, const CompletionCallback& callback); +// Deprecated: Please do not use this outside of //net and //services/network. // A helper method that uses the passed in proxy information to initialize a // ClientSocketHandle with the relevant socket pool. Use this method for // a raw socket connection to a host-port pair (that needs to tunnel through @@ -163,6 +164,7 @@ ClientSocketHandle* socket_handle, const CompletionCallback& callback); +// Deprecated: Please do not use this outside of //net and //services/network. // A helper method that uses the passed in proxy information to initialize a // ClientSocketHandle with the relevant socket pool. Use this method for // a raw socket connection with TLS negotiation to a host-port pair (that needs @@ -170,6 +172,8 @@ NET_EXPORT int InitSocketHandleForTlsConnect( const HostPortPair& host_port_pair, HttpNetworkSession* session, + int request_load_flags, + RequestPriority request_priority, const ProxyInfo& proxy_info, const SSLConfig& ssl_config_for_origin, const SSLConfig& ssl_config_for_proxy,
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index 85d9fc67..bad07ee 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc
@@ -1212,6 +1212,7 @@ int MockSSLClientSocket::Connect(const CompletionCallback& callback) { DCHECK(transport_->socket()->IsConnected()); + data_->is_connect_data_consumed = true; if (data_->connect.result == OK) connected_ = true; if (data_->connect.mode == ASYNC) {
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 906d6be..dd6a24d 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h
@@ -360,6 +360,9 @@ SSLSocketDataProvider(const SSLSocketDataProvider& other); ~SSLSocketDataProvider(); + // Returns whether MockConnect data has been consumed. + bool ConnectDataConsumed() const { return is_connect_data_consumed; } + // Result for Connect(). MockConnect connect; @@ -374,6 +377,8 @@ ChannelIDService* channel_id_service; base::Optional<NextProtoVector> next_protos_expected_in_ssl_config; + + bool is_connect_data_consumed = false; }; // Uses the sequence_number field in the mock reads and writes to
diff --git a/net/ssl/client_cert_identity_unittest.cc b/net/ssl/client_cert_identity_unittest.cc index fbd60d6..36a5583 100644 --- a/net/ssl/client_cert_identity_unittest.cc +++ b/net/ssl/client_cert_identity_unittest.cc
@@ -25,7 +25,7 @@ std::string der_cert; ASSERT_TRUE(x509_util::CreateSelfSignedCert( - key.get(), x509_util::DIGEST_SHA256, "CN=expired", 1, + key->key(), x509_util::DIGEST_SHA256, "CN=expired", 1, base::Time::UnixEpoch(), base::Time::UnixEpoch(), &der_cert)); cert = X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size()); ASSERT_TRUE(cert); @@ -34,7 +34,7 @@ const base::Time now = base::Time::Now(); ASSERT_TRUE(x509_util::CreateSelfSignedCert( - key.get(), x509_util::DIGEST_SHA256, "CN=not yet valid", 2, + key->key(), x509_util::DIGEST_SHA256, "CN=not yet valid", 2, now + base::TimeDelta::FromDays(10), now + base::TimeDelta::FromDays(15), &der_cert)); cert = X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size()); @@ -42,7 +42,7 @@ certs.push_back(std::make_unique<FakeClientCertIdentity>(cert, nullptr)); ASSERT_TRUE(x509_util::CreateSelfSignedCert( - key.get(), x509_util::DIGEST_SHA256, "CN=older cert", 3, + key->key(), x509_util::DIGEST_SHA256, "CN=older cert", 3, now - base::TimeDelta::FromDays(5), now + base::TimeDelta::FromDays(5), &der_cert)); cert = X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size()); @@ -50,7 +50,7 @@ certs.push_back(std::make_unique<FakeClientCertIdentity>(cert, nullptr)); ASSERT_TRUE(x509_util::CreateSelfSignedCert( - key.get(), x509_util::DIGEST_SHA256, "CN=newer cert", 2, + key->key(), x509_util::DIGEST_SHA256, "CN=newer cert", 2, now - base::TimeDelta::FromDays(3), now + base::TimeDelta::FromDays(5), &der_cert)); cert = X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size());
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc index 63e48b2..75b2e7a 100644 --- a/pdf/out_of_process_instance.cc +++ b/pdf/out_of_process_instance.cc
@@ -1821,6 +1821,10 @@ PostMessage(message); } +float OutOfProcessInstance::GetToolbarHeightInScreenCoords() { + return top_toolbar_height_in_viewport_coords_ * device_scale_; +} + void OutOfProcessInstance::ProcessPreviewPageInfo(const std::string& url, int dest_page_index) { DCHECK(IsPrintPreview());
diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h index 99b58b2..3c0a252 100644 --- a/pdf/out_of_process_instance.h +++ b/pdf/out_of_process_instance.h
@@ -147,6 +147,7 @@ void IsSelectingChanged(bool is_selecting) override; void SelectionChanged(const pp::Rect& left, const pp::Rect& right) override; void IsEditModeChanged(bool is_edit_mode) override; + float GetToolbarHeightInScreenCoords() override; // PreviewModeClient::Client implementation. void PreviewDocumentLoadComplete() override;
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h index 049c5b7..216a8f0 100644 --- a/pdf/pdf_engine.h +++ b/pdf/pdf_engine.h
@@ -270,6 +270,10 @@ // Sets edit mode state. virtual void IsEditModeChanged(bool is_edit_mode) {} + + // Gets the height of the top toolbar in screen coordinates. This is + // independent of whether it is hidden or not at the moment. + virtual float GetToolbarHeightInScreenCoords() = 0; }; // Factory method to create an instance of the PDF Engine.
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index 31e5d89..feacb2a 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -906,13 +906,58 @@ double* right, double* bottom) { PDFiumEngine* engine = static_cast<PDFiumEngine*>(param); - int page_index = engine->GetMostVisiblePage(); + int page_index = engine->GetVisiblePageIndex(page); + if (!engine->PageIndexInBounds(page_index)) { + *left = 0; + *right = 0; + *top = 0; + *bottom = 0; + return; + } + pp::Rect page_view_rect = engine->GetPageContentsRect(page_index); - *left = page_view_rect.x(); - *right = page_view_rect.right(); - *top = page_view_rect.y(); - *bottom = page_view_rect.bottom(); + float toolbar_height_in_screen_coords = + engine->GetToolbarHeightInScreenCoords(); + + float page_width = FPDF_GetPageWidth(page); + float page_height = FPDF_GetPageHeight(page); + + // To convert from a screen scale to a page scale, we multiply by + // (page_height / page_view_rect.height()) and + // (page_width / page_view_rect.width()), + // The base point of the page in screen coords is (page_view_rect.x(), + // page_view_rect.y()). + // Therefore, to convert an x position from screen to page + // coords, we use (page_width * (x - base_x) / page_view_rect.width()). + // For y positions, (page_height * (y - base_y) / page_view_rect.height()). + + // The top-most y position that can be relied to be visible on the screen is + // the bottom of the toolbar, which is y = toolbar_height_in_screen_coords. + float screen_top_in_page_coords = + page_height * (toolbar_height_in_screen_coords - page_view_rect.y()) / + page_view_rect.height(); + // The bottom-most y position that is visible on the screen is the bottom of + // the plugin area, which is y = engine->plugin_size_.height(). + float screen_bottom_in_page_coords = + page_height * (engine->plugin_size_.height() - page_view_rect.y()) / + page_view_rect.height(); + // The left-most x position that is visible on the screen is the left of the + // plugin area, which is x = 0. + float screen_left_in_page_coords = + page_width * (0 - page_view_rect.x()) / page_view_rect.width(); + // The right-most x position that is visible on the screen is the right of the + // plugin area, which is x = engine->plugin_size_.width(). + float screen_right_in_page_coords = + page_width * (engine->plugin_size_.width() - page_view_rect.x()) / + page_view_rect.width(); + + // Return the edge of the screen or of the page, since we're restricted to + // both. + *left = std::max(screen_left_in_page_coords, 0.0f); + *right = std::min(screen_right_in_page_coords, page_width); + *top = std::max(screen_top_in_page_coords, 0.0f); + *bottom = std::min(screen_bottom_in_page_coords, page_height); } int PDFiumEngine::Form_GetPlatform(FPDF_FORMFILLINFO* param, @@ -4039,6 +4084,10 @@ return index >= 0 && index < static_cast<int>(pages_.size()); } +float PDFiumEngine::GetToolbarHeightInScreenCoords() { + return client_->GetToolbarHeightInScreenCoords(); +} + void PDFiumEngine::Form_Invalidate(FPDF_FORMFILLINFO* param, FPDF_PAGE page, double left,
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h index c0a4833..1c115cc 100644 --- a/pdf/pdfium/pdfium_engine.h +++ b/pdf/pdfium/pdfium_engine.h
@@ -464,6 +464,10 @@ bool PageIndexInBounds(int index) const; + // Gets the height of the top toolbar in screen coordinates. This is + // independent of whether it is hidden or not at the moment. + float GetToolbarHeightInScreenCoords(); + void ScheduleTouchTimer(const pp::TouchInputEvent& event); void KillTouchTimer(int timer_id); void HandleLongPress(const pp::TouchInputEvent& event);
diff --git a/pdf/preview_mode_client.cc b/pdf/preview_mode_client.cc index c824fdaf..4bfa859 100644 --- a/pdf/preview_mode_client.cc +++ b/pdf/preview_mode_client.cc
@@ -167,6 +167,10 @@ void PreviewModeClient::CancelBrowserDownload() {} +float PreviewModeClient::GetToolbarHeightInScreenCoords() { + return 0.0f; +} + uint32_t PreviewModeClient::GetBackgroundColor() { NOTREACHED(); return 0;
diff --git a/pdf/preview_mode_client.h b/pdf/preview_mode_client.h index 807cf80..e1c06529 100644 --- a/pdf/preview_mode_client.h +++ b/pdf/preview_mode_client.h
@@ -74,6 +74,7 @@ void FormTextFieldFocusChange(bool in_focus) override; bool IsPrintPreview() override; void CancelBrowserDownload() override; + float GetToolbarHeightInScreenCoords() override; uint32_t GetBackgroundColor() override; private:
diff --git a/remoting/base/rsa_key_pair.cc b/remoting/base/rsa_key_pair.cc index 943c5636..1e2e84d 100644 --- a/remoting/base/rsa_key_pair.cc +++ b/remoting/base/rsa_key_pair.cc
@@ -97,7 +97,7 @@ std::string RsaKeyPair::GenerateCertificate() const { std::string der_cert; net::x509_util::CreateSelfSignedCert( - key_.get(), net::x509_util::DIGEST_SHA256, "CN=chromoting", + key_->key(), net::x509_util::DIGEST_SHA256, "CN=chromoting", base::RandInt(1, std::numeric_limits<int>::max()), base::Time::Now(), base::Time::Now() + base::TimeDelta::FromDays(1), &der_cert); return der_cert;
diff --git a/remoting/signaling/xmpp_signal_strategy.cc b/remoting/signaling/xmpp_signal_strategy.cc index 99fbc1a..1f09bf4 100644 --- a/remoting/signaling/xmpp_signal_strategy.cc +++ b/remoting/signaling/xmpp_signal_strategy.cc
@@ -190,7 +190,8 @@ net::SSLConfig(), GURL("https://" + net::HostPortPair(xmpp_server_config_.host, xmpp_server_config_.port) - .ToString())); + .ToString()), + false /*use_tls*/); int result = socket_->Connect(base::Bind( &Core::OnSocketConnected, base::Unretained(this)));
diff --git a/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.cc b/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.cc index f60837a..4c66319 100644 --- a/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.cc +++ b/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.cc
@@ -22,6 +22,15 @@ double* y, double* z, double* w) { + if (std::isnan(alpha_in_degrees)) { + // The RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer + // algorithm cannot measure rotation around the z-axis because it only + // measures the direction of Earth's gravitational field through the + // accelerometer. It sets |alpha| to NaN to reflect that. There is no + // analogue in the world of quaternions so we set |alpha| to 0 to choose + // an arbitrary fixed orientation around the z-axis. + alpha_in_degrees = 0.0; + } double alpha_in_radians = gfx::DegToRad(alpha_in_degrees); double beta_in_radians = gfx::DegToRad(beta_in_degrees); double gamma_in_radians = gfx::DegToRad(gamma_in_degrees);
diff --git a/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles_unittest.cc b/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles_unittest.cc index 039d5b58..2bd9b05a 100644 --- a/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles_unittest.cc +++ b/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <cmath> + #include "services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" @@ -82,6 +84,47 @@ EXPECT_NEAR(1.0, x * x + y * y + z * z + w * w, kEpsilon) << "on test value " << i; } + + // Test when alpha is NAN. + for (size_t i = 0; i < euler_angles_in_degrees_test_values.size(); ++i) { + if (euler_angles_in_degrees_test_values[i][0] != 0.0) { + // Here we need to test when alpha is NAN, it is considered the same as + // its value is 0.0 in + // OrientationQuaternionFusionAlgorithmUsingEulerAngles fusion sensor + // algorithm. So we reuse the test data entries in + // |euler_angles_in_degrees_test_values| whose alpha value is 0.0, and + // skip other test data that has non-zero alpha values. + continue; + } + + // alpha + reading.orientation_euler.z = NAN; + // beta + reading.orientation_euler.x = euler_angles_in_degrees_test_values[i][1]; + // gamma + reading.orientation_euler.y = euler_angles_in_degrees_test_values[i][2]; + + fake_fusion_sensor_->SetSensorReading(source_type, reading, + true /* sensor_reading_success */); + EXPECT_TRUE(fusion_algorithm_->GetFusedData(source_type, &fused_reading)); + + double x = fused_reading.orientation_quat.x; + double y = fused_reading.orientation_quat.y; + double z = fused_reading.orientation_quat.z; + double w = fused_reading.orientation_quat.w; + + EXPECT_NEAR(quaternions_test_values[i][0], x, kEpsilon) + << "on test value " << i; + EXPECT_NEAR(quaternions_test_values[i][1], y, kEpsilon) + << "on test value " << i; + EXPECT_NEAR(quaternions_test_values[i][2], z, kEpsilon) + << "on test value " << i; + EXPECT_NEAR(quaternions_test_values[i][3], w, kEpsilon) + << "on test value " << i; + + EXPECT_NEAR(1.0, x * x + y * y + z * z + w * w, kEpsilon) + << "on test value " << i; + } } } // namespace device
diff --git a/services/network/proxy_resolving_client_socket.cc b/services/network/proxy_resolving_client_socket.cc index 3442660..b6d30af 100644 --- a/services/network/proxy_resolving_client_socket.cc +++ b/services/network/proxy_resolving_client_socket.cc
@@ -31,13 +31,17 @@ ProxyResolvingClientSocket::ProxyResolvingClientSocket( net::HttpNetworkSession* network_session, const net::SSLConfig& ssl_config, - const GURL& url) + const GURL& url, + bool use_tls) : network_session_(network_session), + socket_handle_(std::make_unique<net::ClientSocketHandle>()), ssl_config_(ssl_config), proxy_resolve_request_(nullptr), url_(url), + use_tls_(use_tls), net_log_(net::NetLogWithSource::Make(network_session_->net_log(), net::NetLogSourceType::SOCKET)), + next_state_(STATE_NONE), weak_factory_(this) { // TODO(xunjieli): Handle invalid URLs more gracefully (at mojo API layer // or when the request is created). @@ -51,8 +55,8 @@ int ProxyResolvingClientSocket::Read(net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback) { - if (transport_.get() && transport_->socket()) - return transport_->socket()->Read(buf, buf_len, callback); + if (socket_handle_->socket()) + return socket_handle_->socket()->Read(buf, buf_len, callback); return net::ERR_SOCKET_NOT_CONNECTED; } @@ -61,21 +65,21 @@ int buf_len, const net::CompletionCallback& callback, const net::NetworkTrafficAnnotationTag& traffic_annotation) { - if (transport_.get() && transport_->socket()) - return transport_->socket()->Write(buf, buf_len, callback, - traffic_annotation); + if (socket_handle_->socket()) + return socket_handle_->socket()->Write(buf, buf_len, callback, + traffic_annotation); return net::ERR_SOCKET_NOT_CONNECTED; } int ProxyResolvingClientSocket::SetReceiveBufferSize(int32_t size) { - if (transport_.get() && transport_->socket()) - return transport_->socket()->SetReceiveBufferSize(size); + if (socket_handle_->socket()) + return socket_handle_->socket()->SetReceiveBufferSize(size); return net::ERR_SOCKET_NOT_CONNECTED; } int ProxyResolvingClientSocket::SetSendBufferSize(int32_t size) { - if (transport_.get() && transport_->socket()) - return transport_->socket()->SetSendBufferSize(size); + if (socket_handle_->socket()) + return socket_handle_->socket()->SetSendBufferSize(size); return net::ERR_SOCKET_NOT_CONNECTED; } @@ -83,29 +87,16 @@ const net::CompletionCallback& callback) { DCHECK(user_connect_callback_.is_null()); - // First try to resolve the proxy. - // TODO(xunjieli): Having a null ProxyDelegate is bad. Figure out how to - // interact with the new interface for proxy delegate. - // https://crbug.com/793071. - int net_error = network_session_->proxy_resolution_service()->ResolveProxy( - url_, "POST", &proxy_info_, - base::BindRepeating(&ProxyResolvingClientSocket::ConnectToProxy, - base::Unretained(this)), - &proxy_resolve_request_, nullptr /*proxy_delegate*/, net_log_); - if (net_error != net::ERR_IO_PENDING) { - // Defer execution of ConnectToProxy instead of calling it - // directly here for simplicity. From the caller's point of view, - // the connect always happens asynchronously. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&ProxyResolvingClientSocket::ConnectToProxy, - weak_factory_.GetWeakPtr(), net_error)); + next_state_ = STATE_PROXY_RESOLVE; + int result = DoLoop(net::OK); + if (result == net::ERR_IO_PENDING) { + user_connect_callback_ = callback; } - user_connect_callback_ = callback; - return net::ERR_IO_PENDING; + return result; } void ProxyResolvingClientSocket::Disconnect() { - CloseTransportSocket(); + CloseSocket(true /*close_connection*/); if (proxy_resolve_request_) { network_session_->proxy_resolution_service()->CancelRequest( proxy_resolve_request_); @@ -115,24 +106,24 @@ } bool ProxyResolvingClientSocket::IsConnected() const { - if (!transport_.get() || !transport_->socket()) + if (!socket_handle_->socket()) return false; - return transport_->socket()->IsConnected(); + return socket_handle_->socket()->IsConnected(); } bool ProxyResolvingClientSocket::IsConnectedAndIdle() const { - if (!transport_.get() || !transport_->socket()) + if (!socket_handle_->socket()) return false; - return transport_->socket()->IsConnectedAndIdle(); + return socket_handle_->socket()->IsConnectedAndIdle(); } int ProxyResolvingClientSocket::GetPeerAddress(net::IPEndPoint* address) const { - if (!transport_.get() || !transport_->socket()) { + if (!socket_handle_->socket()) { return net::ERR_SOCKET_NOT_CONNECTED; } if (proxy_info_.is_direct()) - return transport_->socket()->GetPeerAddress(address); + return socket_handle_->socket()->GetPeerAddress(address); net::IPAddress ip_address; if (!ip_address.AssignFromIPLiteral(url_.HostNoBrackets())) { @@ -146,44 +137,48 @@ int ProxyResolvingClientSocket::GetLocalAddress( net::IPEndPoint* address) const { - if (transport_.get() && transport_->socket()) - return transport_->socket()->GetLocalAddress(address); + if (socket_handle_->socket()) + return socket_handle_->socket()->GetLocalAddress(address); return net::ERR_SOCKET_NOT_CONNECTED; } const net::NetLogWithSource& ProxyResolvingClientSocket::NetLog() const { - if (transport_.get() && transport_->socket()) - return transport_->socket()->NetLog(); + if (socket_handle_->socket()) + return socket_handle_->socket()->NetLog(); return net_log_; } void ProxyResolvingClientSocket::SetSubresourceSpeculation() { - if (transport_.get() && transport_->socket()) - transport_->socket()->SetSubresourceSpeculation(); + if (socket_handle_->socket()) + socket_handle_->socket()->SetSubresourceSpeculation(); } void ProxyResolvingClientSocket::SetOmniboxSpeculation() { - if (transport_.get() && transport_->socket()) - transport_->socket()->SetOmniboxSpeculation(); + if (socket_handle_->socket()) + socket_handle_->socket()->SetOmniboxSpeculation(); } bool ProxyResolvingClientSocket::WasEverUsed() const { - if (transport_.get() && transport_->socket()) - return transport_->socket()->WasEverUsed(); + if (socket_handle_->socket()) + return socket_handle_->socket()->WasEverUsed(); return false; } bool ProxyResolvingClientSocket::WasAlpnNegotiated() const { + if (socket_handle_->socket()) + return socket_handle_->socket()->WasAlpnNegotiated(); return false; } net::NextProto ProxyResolvingClientSocket::GetNegotiatedProtocol() const { - if (transport_.get() && transport_->socket()) - return transport_->socket()->GetNegotiatedProtocol(); + if (socket_handle_->socket()) + return socket_handle_->socket()->GetNegotiatedProtocol(); return net::kProtoUnknown; } bool ProxyResolvingClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) { + if (socket_handle_->socket()) + return socket_handle_->socket()->GetSSLInfo(ssl_info); return false; } @@ -201,11 +196,67 @@ NOTIMPLEMENTED(); } -void ProxyResolvingClientSocket::ConnectToProxy(int net_error) { - proxy_resolve_request_ = nullptr; +void ProxyResolvingClientSocket::OnIOComplete(int result) { + DCHECK_NE(net::ERR_IO_PENDING, result); + int net_error = DoLoop(result); + if (net_error != net::ERR_IO_PENDING) + base::ResetAndReturn(&user_connect_callback_).Run(net_error); +} - DCHECK_NE(net_error, net::ERR_IO_PENDING); - if (net_error == net::OK) { +int ProxyResolvingClientSocket::DoLoop(int result) { + DCHECK_NE(next_state_, STATE_NONE); + int rv = result; + do { + State state = next_state_; + next_state_ = STATE_NONE; + switch (state) { + case STATE_PROXY_RESOLVE: + DCHECK_EQ(net::OK, rv); + rv = DoProxyResolve(); + break; + case STATE_PROXY_RESOLVE_COMPLETE: + rv = DoProxyResolveComplete(rv); + break; + case STATE_INIT_CONNECTION: + DCHECK_EQ(net::OK, rv); + rv = DoInitConnection(); + break; + case STATE_INIT_CONNECTION_COMPLETE: + rv = DoInitConnectionComplete(rv); + break; + case STATE_RESTART_TUNNEL_AUTH: + rv = DoRestartTunnelAuth(rv); + break; + case STATE_RESTART_TUNNEL_AUTH_COMPLETE: + rv = DoRestartTunnelAuthComplete(rv); + break; + default: + NOTREACHED() << "bad state"; + rv = net::ERR_FAILED; + break; + } + } while (rv != net::ERR_IO_PENDING && next_state_ != STATE_NONE); + return rv; +} + +int ProxyResolvingClientSocket::DoProxyResolve() { + next_state_ = STATE_PROXY_RESOLVE_COMPLETE; + // TODO(xunjieli): Having a null ProxyDelegate is bad. Figure out how to + // interact with the new interface for proxy delegate. + // https://crbug.com/793071. + // base::Unretained(this) is safe because resolution request is canceled when + // |proxy_resolve_request_| is destroyed. + return network_session_->proxy_resolution_service()->ResolveProxy( + url_, "POST", &proxy_info_, + base::BindRepeating(&ProxyResolvingClientSocket::OnIOComplete, + base::Unretained(this)), + &proxy_resolve_request_, nullptr /*proxy_delegate*/, net_log_); +} + +int ProxyResolvingClientSocket::DoProxyResolveComplete(int result) { + proxy_resolve_request_ = nullptr; + if (result == net::OK) { + next_state_ = STATE_INIT_CONNECTION; // Removes unsupported proxies from the list. Currently, this removes // just the SCHEME_QUIC proxy, which doesn't yet support tunneling. // TODO(xunjieli): Allow QUIC proxy once it supports tunneling. @@ -217,82 +268,119 @@ if (proxy_info_.is_empty()) { // No proxies/direct to choose from. This happens when we don't support // any of the proxies in the returned list. - net_error = net::ERR_NO_SUPPORTED_PROXIES; + result = net::ERR_NO_SUPPORTED_PROXIES; } } + return result; +} - if (net_error != net::OK) { - CloseTransportSocket(); - base::ResetAndReturn(&user_connect_callback_).Run(net_error); - return; - } +int ProxyResolvingClientSocket::DoInitConnection() { + DCHECK(!socket_handle_->socket()); - transport_.reset(new net::ClientSocketHandle); + next_state_ = STATE_INIT_CONNECTION_COMPLETE; + // Now that the proxy is resolved, issue a socket connect. net::HostPortPair host_port_pair = net::HostPortPair::FromURL(url_); // Ignore socket limit set by socket pool for this type of socket. int request_load_flags = net::LOAD_IGNORE_LIMITS; net::RequestPriority request_priority = net::MAXIMUM_PRIORITY; - net_error = net::InitSocketHandleForRawConnect( + // base::Unretained(this) is safe because request is canceled when + // |socket_handle_| is destroyed. + if (use_tls_) { + return net::InitSocketHandleForTlsConnect( + host_port_pair, network_session_, request_load_flags, request_priority, + proxy_info_, ssl_config_, ssl_config_, net::PRIVACY_MODE_DISABLED, + net_log_, socket_handle_.get(), + base::BindRepeating(&ProxyResolvingClientSocket::OnIOComplete, + base::Unretained(this))); + } + return net::InitSocketHandleForRawConnect( host_port_pair, network_session_, request_load_flags, request_priority, proxy_info_, ssl_config_, ssl_config_, net::PRIVACY_MODE_DISABLED, - net_log_, transport_.get(), - base::BindRepeating(&ProxyResolvingClientSocket::ConnectToProxyDone, + net_log_, socket_handle_.get(), + base::BindRepeating(&ProxyResolvingClientSocket::OnIOComplete, base::Unretained(this))); - if (net_error != net::ERR_IO_PENDING) { - // Since this method is always called asynchronously. it is OK to call - // ConnectToProxyDone synchronously. - ConnectToProxyDone(net_error); - } } -void ProxyResolvingClientSocket::ConnectToProxyDone(int net_error) { - if (net_error != net::OK) { - // If the connection fails, try another proxy. - net_error = ReconsiderProxyAfterError(net_error); +int ProxyResolvingClientSocket::DoInitConnectionComplete(int result) { + if (result == net::ERR_PROXY_AUTH_REQUESTED) { + if (use_tls_) { + // Put the in-progress HttpProxyClientSocket into |socket_handle_| to + // do tunnel auth. After auth completes, it's important to reset + // |socket_handle_|, so it doesn't have a HttpProxyClientSocket when the + // code expects an SSLClientSocket. The tunnel restart code is careful to + // put it back to the socket pool before returning control to the rest of + // this class. + socket_handle_.reset( + socket_handle_->release_pending_http_proxy_connection()); + } + next_state_ = STATE_RESTART_TUNNEL_AUTH; + return result; + } + + if (result != net::OK) { // ReconsiderProxyAfterError either returns an error (in which case it is // not reconsidering a proxy) or returns ERR_IO_PENDING if it is considering // another proxy. - DCHECK_NE(net_error, net::OK); - if (net_error == net::ERR_IO_PENDING) { - // Proxy reconsideration pending. Return. - return; - } - CloseTransportSocket(); - } else { - network_session_->proxy_resolution_service()->ReportSuccess(proxy_info_, - nullptr); + return ReconsiderProxyAfterError(result); } - base::ResetAndReturn(&user_connect_callback_).Run(net_error); + + network_session_->proxy_resolution_service()->ReportSuccess(proxy_info_, + nullptr); + return net::OK; } -void ProxyResolvingClientSocket::CloseTransportSocket() { - if (transport_.get() && transport_->socket()) - transport_->socket()->Disconnect(); - transport_.reset(); +int ProxyResolvingClientSocket::DoRestartTunnelAuth(int result) { + DCHECK_EQ(net::ERR_PROXY_AUTH_REQUESTED, result); + + net::ProxyClientSocket* proxy_socket = + static_cast<net::ProxyClientSocket*>(socket_handle_->socket()); + + if (proxy_socket->GetAuthController() && + proxy_socket->GetAuthController()->HaveAuth()) { + next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE; + // base::Unretained(this) is safe because |proxy_socket| is owned by this. + return proxy_socket->RestartWithAuth(base::BindRepeating( + &ProxyResolvingClientSocket::OnIOComplete, base::Unretained(this))); + } + // This socket is unusable if the underlying authentication handler doesn't + // already have credentials. It is possible to overcome this hurdle and + // finish the handshake if this class exposes an interface for an embedder to + // supply credentials. + CloseSocket(true /*close_connection*/); + return result; } -// This method reconsiders the proxy on certain errors. If it does -// reconsider a proxy it always returns ERR_IO_PENDING and posts a call to -// ConnectToProxy with the result of the reconsideration. +int ProxyResolvingClientSocket::DoRestartTunnelAuthComplete(int result) { + if (result == net::ERR_PROXY_AUTH_REQUESTED) { + // Handle multi-round auth challenge. + next_state_ = STATE_RESTART_TUNNEL_AUTH; + return result; + } + if (result == net::OK) { + CloseSocket(false /*close_connection*/); + // Now that the HttpProxyClientSocket is connected, release it as an idle + // socket into the pool and start the connection process from the beginning. + next_state_ = STATE_INIT_CONNECTION; + return net::OK; + } + CloseSocket(true /*close_connection*/); + return ReconsiderProxyAfterError(result); +} + +void ProxyResolvingClientSocket::CloseSocket(bool close_connection) { + if (close_connection && socket_handle_->socket()) + socket_handle_->socket()->Disconnect(); + socket_handle_->Reset(); +} + int ProxyResolvingClientSocket::ReconsiderProxyAfterError(int error) { + DCHECK(!socket_handle_->socket()); DCHECK(!proxy_resolve_request_); DCHECK_NE(error, net::OK); DCHECK_NE(error, net::ERR_IO_PENDING); - if (error == net::ERR_PROXY_AUTH_REQUESTED) { - net::ProxyClientSocket* proxy_socket = - static_cast<net::ProxyClientSocket*>(transport_->socket()); - - if (proxy_socket->GetAuthController()->HaveAuth()) { - return proxy_socket->RestartWithAuth( - base::BindRepeating(&ProxyResolvingClientSocket::ConnectToProxyDone, - base::Unretained(this))); - } - return error; - } - // Check if the error was a proxy failure. if (!net::CanFalloverToNextProxy(&error)) return error; @@ -307,14 +395,8 @@ if (!proxy_info_.Fallback(error, net_log_)) return error; - CloseTransportSocket(); - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&ProxyResolvingClientSocket::ConnectToProxy, - weak_factory_.GetWeakPtr(), net::OK)); - // Since we potentially have another try to go, set the return code code to - // ERR_IO_PENDING. - return net::ERR_IO_PENDING; + next_state_ = STATE_INIT_CONNECTION; + return net::OK; } } // namespace network
diff --git a/services/network/proxy_resolving_client_socket.h b/services/network/proxy_resolving_client_socket.h index 7aa6185..6616250 100644 --- a/services/network/proxy_resolving_client_socket.h +++ b/services/network/proxy_resolving_client_socket.h
@@ -50,10 +50,12 @@ // any sensitive data (like embedded usernames and passwords), and local data // (i.e. reference fragment) will be sanitized by // net::ProxyResolutionService::ResolveProxyHelper() before the url is - // disclosed to the proxy. |network_session| must outlive |this|. + // disclosed to the proxy. If |use_tls|, this will try to do a tls connect + // instead of a regular tcp connect. |network_session| must outlive |this|. ProxyResolvingClientSocket(net::HttpNetworkSession* network_session, const net::SSLConfig& ssl_config, - const GURL& url); + const GURL& url, + bool use_tls); ~ProxyResolvingClientSocket() override; // net::StreamSocket implementation. @@ -88,29 +90,53 @@ void ApplySocketTag(const net::SocketTag& tag) override; private: + enum State { + STATE_PROXY_RESOLVE, + STATE_PROXY_RESOLVE_COMPLETE, + STATE_INIT_CONNECTION, + STATE_INIT_CONNECTION_COMPLETE, + STATE_RESTART_TUNNEL_AUTH, + STATE_RESTART_TUNNEL_AUTH_COMPLETE, + STATE_DONE, + STATE_NONE, + }; + FRIEND_TEST_ALL_PREFIXES(ProxyResolvingClientSocketTest, ConnectToProxy); FRIEND_TEST_ALL_PREFIXES(ProxyResolvingClientSocketTest, ReadWriteErrors); + FRIEND_TEST_ALL_PREFIXES(ProxyResolvingClientSocketTest, + ResetSocketAfterTunnelAuth); - void ConnectToProxy(int net_error); - void ConnectToProxyDone(int net_error); + void OnIOComplete(int result); - void CloseTransportSocket(); + int DoLoop(int result); + int DoProxyResolve(); + int DoProxyResolveComplete(int result); + int DoInitConnection(); + int DoInitConnectionComplete(int result); + int DoRestartTunnelAuth(int result); + int DoRestartTunnelAuthComplete(int result); + + void CloseSocket(bool close_connection); + int ReconsiderProxyAfterError(int error); net::HttpNetworkSession* network_session_; - // The transport socket. - std::unique_ptr<net::ClientSocketHandle> transport_; + std::unique_ptr<net::ClientSocketHandle> socket_handle_; const net::SSLConfig ssl_config_; net::ProxyResolutionService::Request* proxy_resolve_request_; net::ProxyInfo proxy_info_; const GURL url_; + const bool use_tls_; + net::NetLogWithSource net_log_; // The callback passed to Connect(). net::CompletionCallback user_connect_callback_; + State next_state_; + base::WeakPtrFactory<ProxyResolvingClientSocket> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ProxyResolvingClientSocket);
diff --git a/services/network/proxy_resolving_client_socket_factory.cc b/services/network/proxy_resolving_client_socket_factory.cc index 1652aaa..8eaa859 100644 --- a/services/network/proxy_resolving_client_socket_factory.cc +++ b/services/network/proxy_resolving_client_socket_factory.cc
@@ -70,7 +70,8 @@ std::unique_ptr<ProxyResolvingClientSocket> ProxyResolvingClientSocketFactory::CreateSocket( const net::SSLConfig& ssl_config, - const GURL& url) { + const GURL& url, + bool use_tls) { // |request_context|'s HttpAuthCache might have updates. For example, a user // might have since entered proxy credentials. Clear the http auth of // |network_session_| and copy over the data from |request_context|'s auth @@ -83,7 +84,7 @@ ->http_auth_cache(); network_session_->http_auth_cache()->UpdateAllFrom(*other_auth_cache); return std::make_unique<ProxyResolvingClientSocket>(network_session_.get(), - ssl_config, url); + ssl_config, url, use_tls); } } // namespace network
diff --git a/services/network/proxy_resolving_client_socket_factory.h b/services/network/proxy_resolving_client_socket_factory.h index f722d06..cf0c726 100644 --- a/services/network/proxy_resolving_client_socket_factory.h +++ b/services/network/proxy_resolving_client_socket_factory.h
@@ -39,10 +39,10 @@ // doesn't need to explicitly sanitize the url, any sensitive data (like // embedded usernames and passwords), and local data (i.e. reference fragment) // will be sanitized by net::ProxyService::ResolveProxyHelper() before the url - // is disclosed to the proxy. - std::unique_ptr<ProxyResolvingClientSocket> CreateSocket( - const net::SSLConfig& ssl_config, - const GURL& url); + // is disclosed to the proxy. If |use_tls|, tls connect will be used in + // addition to tcp connect. + std::unique_ptr<ProxyResolvingClientSocket> + CreateSocket(const net::SSLConfig& ssl_config, const GURL& url, bool use_tls); private: std::unique_ptr<net::HttpNetworkSession> network_session_;
diff --git a/services/network/proxy_resolving_client_socket_unittest.cc b/services/network/proxy_resolving_client_socket_unittest.cc index 0ebd37a..ad24ac2 100644 --- a/services/network/proxy_resolving_client_socket_unittest.cc +++ b/services/network/proxy_resolving_client_socket_unittest.cc
@@ -20,6 +20,7 @@ #include "net/dns/mock_host_resolver.h" #include "net/proxy_resolution/mock_proxy_resolver.h" #include "net/proxy_resolution/proxy_config_service_fixed.h" +#include "net/proxy_resolution/proxy_config_with_annotation.h" #include "net/proxy_resolution/proxy_resolution_service.h" #include "net/socket/client_socket_pool_manager.h" #include "net/socket/socket_test_util.h" @@ -50,10 +51,13 @@ } // namespace -class ProxyResolvingClientSocketTest : public testing::Test { +class ProxyResolvingClientSocketTest + : public testing::Test, + public testing::WithParamInterface<bool> { protected: ProxyResolvingClientSocketTest() - : context_with_proxy_("PROXY bad:99; PROXY maybe:80; DIRECT") {} + : context_with_proxy_("PROXY bad:99; PROXY maybe:80; DIRECT"), + use_tls_(GetParam()) {} ~ProxyResolvingClientSocketTest() override {} @@ -65,12 +69,17 @@ base::test::ScopedTaskEnvironment scoped_task_environment_; TestURLRequestContextWithProxy context_with_proxy_; + const bool use_tls_; }; +INSTANTIATE_TEST_CASE_P(/* no prefix */, + ProxyResolvingClientSocketTest, + ::testing::Bool()); + // Tests that the global socket pool limit // (ClientSocketPoolManager::max_sockets_per_group) doesn't apply to this // type of sockets. -TEST_F(ProxyResolvingClientSocketTest, SocketLimitNotApply) { +TEST_P(ProxyResolvingClientSocketTest, SocketLimitNotApply) { const int kNumSockets = net::ClientSocketPoolManager::max_sockets_per_group( net::HttpNetworkSession::NORMAL_SOCKET_POOL) + 10; @@ -82,11 +91,15 @@ "Proxy-Connection: keep-alive\r\n\r\n")}; net::MockRead reads[] = {net::MockRead("HTTP/1.1 200 Success\r\n\r\n")}; std::vector<std::unique_ptr<net::StaticSocketDataProvider>> socket_data; + std::vector<std::unique_ptr<net::SSLSocketDataProvider>> ssl_data; for (int i = 0; i < kNumSockets; ++i) { socket_data.push_back(std::make_unique<net::StaticSocketDataProvider>( reads, arraysize(reads), writes, arraysize(writes))); socket_data[i]->set_connect_data(net::MockConnect(net::ASYNC, net::OK)); socket_factory.AddSocketDataProvider(socket_data[i].get()); + ssl_data.push_back( + std::make_unique<net::SSLSocketDataProvider>(net::ASYNC, net::OK)); + socket_factory.AddSSLSocketDataProvider(ssl_data[i].get()); } ProxyResolvingClientSocketFactory proxy_resolving_socket_factory( @@ -95,7 +108,7 @@ for (int i = 0; i < kNumSockets; ++i) { std::unique_ptr<ProxyResolvingClientSocket> socket = proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), - kDestination); + kDestination, use_tls_); net::TestCompletionCallback callback; int status = socket->Connect(callback.callback()); EXPECT_THAT(callback.GetResult(status), net::test::IsOk()); @@ -104,10 +117,11 @@ for (int i = 0; i < kNumSockets; ++i) { EXPECT_TRUE(socket_data[i]->AllReadDataConsumed()); EXPECT_TRUE(socket_data[i]->AllWriteDataConsumed()); + EXPECT_EQ(use_tls_, ssl_data[i]->ConnectDataConsumed()); } } -TEST_F(ProxyResolvingClientSocketTest, ConnectError) { +TEST_P(ProxyResolvingClientSocketTest, ConnectError) { const struct TestData { // Whether the error is encountered synchronously as opposed to // asynchronously. @@ -136,7 +150,7 @@ &socket_factory, context.get()); std::unique_ptr<ProxyResolvingClientSocket> socket = proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), - kDestination); + kDestination, use_tls_); net::TestCompletionCallback callback; int status = socket->Connect(callback.callback()); EXPECT_EQ(net::ERR_IO_PENDING, status); @@ -152,7 +166,7 @@ } // Tests that the connection is established to the proxy. -TEST_F(ProxyResolvingClientSocketTest, ConnectToProxy) { +TEST_P(ProxyResolvingClientSocketTest, ConnectToProxy) { const GURL kDestination("https://example.com:443"); // Use a different port than that of |kDestination|. const int kProxyPort = 8009; @@ -171,6 +185,9 @@ net::MockWrite("CONNECT example.com:443 HTTP/1.1\r\n" "Host: example.com:443\r\n" "Proxy-Connection: keep-alive\r\n\r\n")}; + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + socket_factory.AddSSLSocketDataProvider(&ssl_socket); + net::StaticSocketDataProvider socket_data(reads, arraysize(reads), writes, arraysize(writes)); net::IPEndPoint remote_addr(net::IPAddress(127, 0, 0, 1), @@ -183,7 +200,7 @@ &socket_factory, context.get()); std::unique_ptr<ProxyResolvingClientSocket> socket = proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), - kDestination); + kDestination, use_tls_); net::TestCompletionCallback callback; int status = socket->Connect(callback.callback()); EXPECT_EQ(net::ERR_IO_PENDING, status); @@ -196,16 +213,42 @@ // proxy, so call private member to make sure address is correct. EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, status); status = - socket->transport_->socket()->GetPeerAddress(&actual_remote_addr); + socket->socket_handle_->socket()->GetPeerAddress(&actual_remote_addr); } EXPECT_EQ(net::OK, status); EXPECT_EQ(remote_addr.ToString(), actual_remote_addr.ToString()); + EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed()); } } +TEST_P(ProxyResolvingClientSocketTest, SocketDestroyedBeforeConnectComplete) { + const GURL kDestination("https://example.com:443"); + net::StaticSocketDataProvider socket_data; + socket_data.set_connect_data(net::MockConnect(net::ASYNC, net::OK)); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + + net::MockClientSocketFactory socket_factory; + socket_factory.AddSocketDataProvider(&socket_data); + socket_factory.AddSSLSocketDataProvider(&ssl_socket); + + auto context = std::make_unique<TestURLRequestContextWithProxy>("DIRECT"); + + ProxyResolvingClientSocketFactory proxy_resolving_socket_factory( + &socket_factory, context.get()); + std::unique_ptr<ProxyResolvingClientSocket> socket = + proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), + kDestination, use_tls_); + net::TestCompletionCallback callback; + int status = socket->Connect(callback.callback()); + EXPECT_EQ(net::ERR_IO_PENDING, status); + socket.reset(); + // Makes sure there is no UAF and socket request is canceled properly. + base::RunLoop().RunUntilIdle(); +} + // Tests that connection itself is successful but an error occurred during // Read()/Write(). -TEST_F(ProxyResolvingClientSocketTest, ReadWriteErrors) { +TEST_P(ProxyResolvingClientSocketTest, ReadWriteErrors) { const GURL kDestination("http://example.com:80"); const struct TestData { // Whether there is a read error as opposed to a write error. @@ -254,12 +297,14 @@ socket_data.set_connect_data( net::MockConnect(net::ASYNC, net::OK, remote_addr)); net::MockClientSocketFactory socket_factory; + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + socket_factory.AddSSLSocketDataProvider(&ssl_socket); socket_factory.AddSocketDataProvider(&socket_data); ProxyResolvingClientSocketFactory proxy_resolving_socket_factory( &socket_factory, context.get()); std::unique_ptr<ProxyResolvingClientSocket> socket = proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), - kDestination); + kDestination, use_tls_); net::TestCompletionCallback callback; int status = socket->Connect(callback.callback()); EXPECT_EQ(net::ERR_IO_PENDING, status); @@ -272,7 +317,7 @@ // proxy, so call private member to make sure address is correct. EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, status); status = - socket->transport_->socket()->GetPeerAddress(&actual_remote_addr); + socket->socket_handle_->socket()->GetPeerAddress(&actual_remote_addr); } EXPECT_EQ(net::OK, status); EXPECT_EQ(remote_addr.ToString(), actual_remote_addr.ToString()); @@ -298,10 +343,11 @@ EXPECT_EQ(net::ERR_FAILED, read_write_result); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); + EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed()); } } -TEST_F(ProxyResolvingClientSocketTest, ReportsBadProxies) { +TEST_P(ProxyResolvingClientSocketTest, ReportsBadProxies) { const GURL kDestination("https://example.com:443"); net::MockClientSocketFactory socket_factory; @@ -319,12 +365,14 @@ arraysize(writes)); socket_data2.set_connect_data(net::MockConnect(net::ASYNC, net::OK)); socket_factory.AddSocketDataProvider(&socket_data2); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + socket_factory.AddSSLSocketDataProvider(&ssl_socket); ProxyResolvingClientSocketFactory proxy_resolving_socket_factory( &socket_factory, &context_with_proxy_); std::unique_ptr<ProxyResolvingClientSocket> socket = proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), - kDestination); + kDestination, use_tls_); net::TestCompletionCallback callback; int status = socket->Connect(callback.callback()); EXPECT_EQ(net::ERR_IO_PENDING, status); @@ -337,9 +385,127 @@ EXPECT_EQ(1u, retry_info.size()); net::ProxyRetryInfoMap::const_iterator iter = retry_info.find("bad:99"); EXPECT_TRUE(iter != retry_info.end()); + EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed()); } -TEST_F(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Lookup) { +TEST_P(ProxyResolvingClientSocketTest, ResetSocketAfterTunnelAuth) { + net::MockClientSocketFactory socket_factory; + const GURL kDestination("https://example.com:443"); + + // Initial connect without credentials. The server responds with a 407. + net::MockWrite kConnectWrites1[] = { + net::MockWrite("CONNECT example.com:443 HTTP/1.1\r\n" + "Host: example.com:443\r\n" + "Proxy-Connection: keep-alive\r\n" + "\r\n")}; + net::MockRead kConnectReads1[] = { + net::MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n" + "Proxy-Authenticate: Basic realm=\"test_realm\"\r\n" + "\r\n")}; + + net::StaticSocketDataProvider kSocketData1( + kConnectReads1, arraysize(kConnectReads1), kConnectWrites1, + arraysize(kConnectWrites1)); + socket_factory.AddSocketDataProvider(&kSocketData1); + + ProxyResolvingClientSocketFactory proxy_resolving_socket_factory( + &socket_factory, &context_with_proxy_); + std::unique_ptr<ProxyResolvingClientSocket> socket = + proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), + kDestination, use_tls_); + net::TestCompletionCallback callback; + int status = socket->Connect(callback.callback()); + EXPECT_THAT(callback.GetResult(status), + net::test::IsError(net::ERR_PROXY_AUTH_REQUESTED)); + // Make sure |socket_handle_| is closed appropriately. + EXPECT_FALSE(socket->socket_handle_->socket()); +} + +TEST_P(ProxyResolvingClientSocketTest, MultiroundAuth) { + net::MockClientSocketFactory socket_factory; + const GURL kDestination("https://example.com:443"); + + // Initial connect without credentials. The server responds with a 407. + net::MockWrite kConnectWrites1[] = { + net::MockWrite("CONNECT example.com:443 HTTP/1.1\r\n" + "Host: example.com:443\r\n" + "Proxy-Connection: keep-alive\r\n" + "\r\n")}; + net::MockRead kConnectReads1[] = { + net::MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n" + "Proxy-Authenticate: Basic realm=\"test_realm\"\r\n" + "\r\n")}; + + // Second connect attempt includes credentials for test_realm. + net::MockWrite kConnectWrites2[] = { + net::MockWrite("CONNECT example.com:443 HTTP/1.1\r\n" + "Host: example.com:443\r\n" + "Proxy-Connection: keep-alive\r\n" + "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==\r\n" + "\r\n")}; + net::MockRead kConnectReads2[] = { + net::MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n" + "Proxy-Authenticate: Basic realm=\"test_realm2\"\r\n" + "\r\n")}; + + // Third connect attempt include credentials for test_realm2. + net::MockWrite kConnectWrites3[] = { + net::MockWrite("CONNECT example.com:443 HTTP/1.1\r\n" + "Host: example.com:443\r\n" + "Proxy-Connection: keep-alive\r\n" + "Proxy-Authorization: Basic dXNlcjI6cGFzc3dvcmQy\r\n" + "\r\n")}; + net::MockRead kConnectReads3[] = { + net::MockRead("HTTP/1.1 200 Success\r\n\r\n")}; + + net::StaticSocketDataProvider kSocketData1( + kConnectReads1, arraysize(kConnectReads1), kConnectWrites1, + arraysize(kConnectWrites1)); + socket_factory.AddSocketDataProvider(&kSocketData1); + + net::StaticSocketDataProvider kSocketData2( + kConnectReads2, arraysize(kConnectReads2), kConnectWrites2, + arraysize(kConnectWrites2)); + socket_factory.AddSocketDataProvider(&kSocketData2); + net::StaticSocketDataProvider kSocketData3( + kConnectReads3, arraysize(kConnectReads3), kConnectWrites3, + arraysize(kConnectWrites3)); + socket_factory.AddSocketDataProvider(&kSocketData3); + + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + socket_factory.AddSSLSocketDataProvider(&ssl_socket); + + net::HttpAuthCache* auth_cache = + context_with_proxy_.http_transaction_factory() + ->GetSession() + ->http_auth_cache(); + + auth_cache->Add(GURL("http://bad:99"), "test_realm", + net::HttpAuth::AUTH_SCHEME_BASIC, + "Basic realm=\"test_realm\"", + net::AuthCredentials(base::ASCIIToUTF16("user"), + base::ASCIIToUTF16("password")), + std::string()); + + auth_cache->Add(GURL("http://bad:99"), "test_realm2", + net::HttpAuth::AUTH_SCHEME_BASIC, + "Basic realm=\"test_realm2\"", + net::AuthCredentials(base::ASCIIToUTF16("user2"), + base::ASCIIToUTF16("password2")), + std::string()); + + ProxyResolvingClientSocketFactory proxy_resolving_socket_factory( + &socket_factory, &context_with_proxy_); + std::unique_ptr<ProxyResolvingClientSocket> socket = + proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), + kDestination, use_tls_); + net::TestCompletionCallback callback; + int status = socket->Connect(callback.callback()); + EXPECT_THAT(callback.GetResult(status), net::test::IsOk()); + EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed()); +} + +TEST_P(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Lookup) { net::MockClientSocketFactory socket_factory; const GURL kDestination("https://example.com:443"); @@ -373,6 +539,8 @@ kConnectReads2, arraysize(kConnectReads2), kConnectWrites2, arraysize(kConnectWrites2)); socket_factory.AddSocketDataProvider(&kSocketData2); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + socket_factory.AddSSLSocketDataProvider(&ssl_socket); net::HttpAuthCache* auth_cache = context_with_proxy_.http_transaction_factory() @@ -393,16 +561,17 @@ &socket_factory, &context_with_proxy_); std::unique_ptr<ProxyResolvingClientSocket> socket = proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), - kDestination); + kDestination, use_tls_); net::TestCompletionCallback callback; int status = socket->Connect(callback.callback()); EXPECT_THAT(callback.GetResult(status), net::test::IsOk()); + EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed()); } // Make sure that if HttpAuthCache is updated e.g through normal URLRequests, // ProxyResolvingClientSocketFactory uses the latest cache for creating new // sockets. -TEST_F(ProxyResolvingClientSocketTest, FactoryUsesLatestHTTPAuthCache) { +TEST_P(ProxyResolvingClientSocketTest, FactoryUsesLatestHTTPAuthCache) { net::MockClientSocketFactory socket_factory; ProxyResolvingClientSocketFactory proxy_resolving_socket_factory( &socket_factory, &context_with_proxy_); @@ -449,16 +618,19 @@ kConnectReads, arraysize(kConnectReads), kConnectWrites, arraysize(kConnectWrites)); socket_factory.AddSocketDataProvider(&kSocketData); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + socket_factory.AddSSLSocketDataProvider(&ssl_socket); std::unique_ptr<ProxyResolvingClientSocket> socket = proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), - kDestination); + kDestination, use_tls_); net::TestCompletionCallback callback; int status = socket->Connect(callback.callback()); EXPECT_THAT(callback.GetResult(status), net::test::IsOk()); + EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed()); } -TEST_F(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Preemptive) { +TEST_P(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Preemptive) { net::MockClientSocketFactory socket_factory; const GURL kDestination("https://example.com:443"); @@ -476,6 +648,8 @@ kConnectReads, arraysize(kConnectReads), kConnectWrites, arraysize(kConnectWrites)); socket_factory.AddSocketDataProvider(&kSocketData); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + socket_factory.AddSSLSocketDataProvider(&ssl_socket); net::HttpAuthCache* auth_cache = context_with_proxy_.http_transaction_factory() @@ -493,14 +667,15 @@ &socket_factory, &context_with_proxy_); std::unique_ptr<ProxyResolvingClientSocket> socket = proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), - kDestination); + kDestination, use_tls_); net::TestCompletionCallback callback; int status = socket->Connect(callback.callback()); EXPECT_THAT(callback.GetResult(status), net::test::IsOk()); + EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed()); } -TEST_F(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_NoCredentials) { +TEST_P(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_NoCredentials) { net::MockClientSocketFactory socket_factory; const GURL kDestination("https://example.com:443"); @@ -524,7 +699,7 @@ &socket_factory, &context_with_proxy_); std::unique_ptr<ProxyResolvingClientSocket> socket = proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), - kDestination); + kDestination, use_tls_); net::TestCompletionCallback callback; int status = socket->Connect(callback.callback()); @@ -532,7 +707,7 @@ } // Make sure that url is sanitized before it is disclosed to the proxy. -TEST_F(ProxyResolvingClientSocketTest, URLSanitized) { +TEST_P(ProxyResolvingClientSocketTest, URLSanitized) { GURL url("http://username:password@www.example.com:79/?ref#hash#hash"); auto context = std::make_unique<net::TestURLRequestContext>(true); @@ -555,7 +730,8 @@ ProxyResolvingClientSocketFactory proxy_resolving_socket_factory( nullptr, context.get()); std::unique_ptr<ProxyResolvingClientSocket> socket = - proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), url); + proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), url, + use_tls_); net::TestCompletionCallback callback; int status = socket->Connect(callback.callback()); EXPECT_EQ(net::ERR_IO_PENDING, status); @@ -572,18 +748,57 @@ resolver.pending_jobs()[0]->url()); } +// Tests that socket is destroyed before proxy resolution can complete +// asynchronously. +TEST_P(ProxyResolvingClientSocketTest, + SocketDestroyedBeforeProxyResolutionCompletes) { + GURL url("http://www.example.com:79"); + + auto context = std::make_unique<net::TestURLRequestContext>(true); + net::ProxyConfig proxy_config; + proxy_config.set_pac_url(GURL("http://foopy/proxy.pac")); + proxy_config.set_pac_mandatory(true); + net::MockAsyncProxyResolver resolver; + auto proxy_resolver_factory = + std::make_unique<net::MockAsyncProxyResolverFactory>(false); + net::MockAsyncProxyResolverFactory* proxy_resolver_factory_raw = + proxy_resolver_factory.get(); + net::ProxyResolutionService service( + std::make_unique<net::ProxyConfigServiceFixed>( + net::ProxyConfigWithAnnotation(proxy_config, + TRAFFIC_ANNOTATION_FOR_TESTS)), + std::move(proxy_resolver_factory), nullptr); + context->set_proxy_resolution_service(&service); + context->Init(); + + ProxyResolvingClientSocketFactory proxy_resolving_socket_factory( + nullptr, context.get()); + std::unique_ptr<ProxyResolvingClientSocket> socket = + proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), url, + use_tls_); + net::TestCompletionCallback callback; + EXPECT_EQ(net::ERR_IO_PENDING, socket->Connect(callback.callback())); + socket.reset(); + ASSERT_EQ(1u, proxy_resolver_factory_raw->pending_requests().size()); + proxy_resolver_factory_raw->pending_requests()[0]->CompleteNowWithForwarder( + net::OK, &resolver); + base::RunLoop().RunUntilIdle(); +} + class ReconsiderProxyAfterErrorTest : public testing::Test, - public testing::WithParamInterface<::testing::tuple<bool, int>> { + public testing::WithParamInterface<::testing::tuple<bool, bool, int>> { public: ReconsiderProxyAfterErrorTest() : context_with_proxy_( - "HTTPS badproxy:99; HTTPS badfallbackproxy:98; DIRECT") {} + "HTTPS badproxy:99; HTTPS badfallbackproxy:98; DIRECT"), + use_tls_(::testing::get<0>(GetParam())) {} ~ReconsiderProxyAfterErrorTest() override {} base::test::ScopedTaskEnvironment scoped_task_environment_; TestURLRequestContextWithProxy context_with_proxy_; + const bool use_tls_; }; // List of errors that are used in the proxy resolution tests. @@ -600,12 +815,14 @@ INSTANTIATE_TEST_CASE_P( /* no prefix */, ReconsiderProxyAfterErrorTest, - testing::Combine(testing::Bool(), testing::ValuesIn(kProxyTestMockErrors))); + testing::Combine(testing::Bool(), + testing::Bool(), + testing::ValuesIn(kProxyTestMockErrors))); TEST_P(ReconsiderProxyAfterErrorTest, ReconsiderProxyAfterError) { net::IoMode io_mode = - ::testing::get<0>(GetParam()) ? net::SYNCHRONOUS : net::ASYNC; - const int mock_error = ::testing::get<1>(GetParam()); + ::testing::get<1>(GetParam()) ? net::SYNCHRONOUS : net::ASYNC; + const int mock_error = ::testing::get<2>(GetParam()); // Before starting the test, verify that there are no proxies marked as bad. ASSERT_TRUE(context_with_proxy_.proxy_resolution_service() @@ -628,13 +845,15 @@ net::StaticSocketDataProvider data3; data3.set_connect_data(net::MockConnect(io_mode, net::OK)); socket_factory.AddSocketDataProvider(&data3); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + socket_factory.AddSSLSocketDataProvider(&ssl_socket); const GURL kDestination("https://example.com:443"); ProxyResolvingClientSocketFactory proxy_resolving_socket_factory( &socket_factory, &context_with_proxy_); std::unique_ptr<ProxyResolvingClientSocket> socket = proxy_resolving_socket_factory.CreateSocket(net::SSLConfig(), - kDestination); + kDestination, use_tls_); net::TestCompletionCallback callback; int status = socket->Connect(callback.callback()); EXPECT_EQ(net::ERR_IO_PENDING, status); @@ -646,6 +865,7 @@ EXPECT_EQ(2u, retry_info.size()) << mock_error; EXPECT_NE(retry_info.end(), retry_info.find("https://badproxy:99")); EXPECT_NE(retry_info.end(), retry_info.find("https://badfallbackproxy:98")); + EXPECT_EQ(use_tls_, ssl_socket.ConnectDataConsumed()); } } // namespace network
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc index 26ed309f..4974dc19 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc
@@ -12,7 +12,6 @@ #include <base/strings/sys_string_conversions.h> #include <base/win/pe_image.h> #include <base/win/win_util.h> -#include "base/process/process_metrics.h" namespace memory_instrumentation { @@ -22,14 +21,12 @@ // Creating process metrics for child processes in mac or windows requires // additional information like ProcessHandle or port provider. DCHECK_EQ(base::kNullProcessId, pid); - auto process_metrics = base::ProcessMetrics::CreateCurrentProcessMetrics(); - size_t private_bytes = 0; - process_metrics->GetMemoryBytes(&private_bytes, nullptr); - dump->platform_private_footprint->private_bytes = private_bytes; - - PROCESS_MEMORY_COUNTERS pmc; - if (::GetProcessMemoryInfo(::GetCurrentProcess(), &pmc, sizeof(pmc))) { + PROCESS_MEMORY_COUNTERS_EX pmc; + if (::GetProcessMemoryInfo(::GetCurrentProcess(), + reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&pmc), + sizeof(pmc))) { + dump->platform_private_footprint->private_bytes = pmc.PrivateUsage; dump->resident_set_kb = pmc.WorkingSetSize / 1024; } return true;
diff --git a/services/shape_detection/PRESUBMIT.py b/services/shape_detection/PRESUBMIT.py index 6358b80..2b10dc13 100644 --- a/services/shape_detection/PRESUBMIT.py +++ b/services/shape_detection/PRESUBMIT.py
@@ -19,7 +19,7 @@ return output_api.EnsureCQIncludeTrybotsAreAdded( cl, [ - 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'luci.chromium.try:mac_optional_gpu_tests_rel', 'master.tryserver.chromium.win:win10_chromium_x64_rel_ng' ], 'Automatically added optional Mac GPU and Windows 10 tests to run on CQ.')
diff --git a/services/video_capture/test/mock_device_factory.cc b/services/video_capture/test/mock_device_factory.cc index c63ab2ab..206e2d0 100644 --- a/services/video_capture/test/mock_device_factory.cc +++ b/services/video_capture/test/mock_device_factory.cc
@@ -79,4 +79,10 @@ supported_formats->push_back(kSupportedFormat); } +void MockDeviceFactory::GetCameraLocationsAsync( + std::unique_ptr<media::VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback) { + base::ResetAndReturn(&result_callback).Run(std::move(device_descriptors)); +} + } // namespace video_capture
diff --git a/services/video_capture/test/mock_device_factory.h b/services/video_capture/test/mock_device_factory.h index 114853f..10eb472 100644 --- a/services/video_capture/test/mock_device_factory.h +++ b/services/video_capture/test/mock_device_factory.h
@@ -31,6 +31,9 @@ void GetSupportedFormats( const media::VideoCaptureDeviceDescriptor& device_descriptor, media::VideoCaptureFormats* supported_formats) override; + void GetCameraLocationsAsync( + std::unique_ptr<media::VideoCaptureDeviceDescriptors> device_descriptors, + DeviceDescriptorsCallback result_callback) override; private: std::map<media::VideoCaptureDeviceDescriptor, media::VideoCaptureDevice*>
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 918dac4..60c62dd 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -5415,7 +5415,7 @@ "device_type": "gce_x86" } ], - "hard_timeout": 60 + "hard_timeout": 120 }, "test": "gl_unittests" },
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 20644591..a454c8fe 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -1349,7 +1349,7 @@ "device_type": "hammerhead" } ], - "hard_timeout": 60, + "hard_timeout": 120, "output_links": [ { "link": [ @@ -3032,7 +3032,7 @@ "device_type": "hammerhead" } ], - "hard_timeout": 60, + "hard_timeout": 120, "output_links": [ { "link": [ @@ -4624,7 +4624,7 @@ } ], "expiration": 10800, - "hard_timeout": 60, + "hard_timeout": 120, "output_links": [ { "link": [ @@ -7771,7 +7771,7 @@ } ], "expiration": 10800, - "hard_timeout": 60, + "hard_timeout": 120, "output_links": [ { "link": [ @@ -12679,7 +12679,7 @@ } ], "expiration": 10800, - "hard_timeout": 60, + "hard_timeout": 120, "output_links": [ { "link": [ @@ -13076,7 +13076,7 @@ } ], "expiration": 10800, - "hard_timeout": 60, + "hard_timeout": 120, "output_links": [ { "link": [
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index 9c9ac6b..831b3f3 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -5746,7 +5746,7 @@ "device_type": "hammerhead" } ], - "hard_timeout": 60, + "hard_timeout": 120, "output_links": [ { "link": [
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter index f005267a..e15cde8 100644 --- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -55,10 +55,6 @@ -WebViewTests/WebViewTest.ClearData/1 -WebViewTests/WebViewTest.ClearDataCache/0 -WebViewTests/WebViewTest.ClearDataCache/1 --WebViewTests/WebViewTest.DownloadCookieIsolation_CrossSession/0 --WebViewTests/WebViewTest.DownloadCookieIsolation_CrossSession/1 --WebViewTests/WebViewTest.StoragePersistence/0 --WebViewTests/WebViewTest.StoragePersistence/1 -WebViewTests/WebViewTest.WebViewInBackgroundPage/0 -WebViewTests/WebViewTest.WebViewInBackgroundPage/1 # Need support for blocking cookies via content settings: @@ -310,12 +306,6 @@ -PPAPINaClPNaClNonSfiTest.FileRef2 -PPAPINaClPNaClNonSfiTest.URLLoader1 -# Session cookies tests are flaky. -# https://crbug.com/795417 --ContinueWhereILeftOffTest.SessionCookies --RestartTest.SessionCookies - - # Requires a replacement for ChromeNetworkDelegate. -VariationsHttpHeadersBrowserTest.TestStrippingHeadersFromResourceRequest @@ -327,12 +317,6 @@ # Fails because data: URL is not downloaded but navigated to. -BrowserActionApiTest.BrowserActionPopupDownload -# Flakes https://logs.chromium.org/v/?s=chromium%2Fbb%2Fchromium.linux%2FLinux_Tests%2F65822%2F%2B%2Frecipes%2Fsteps%2Fnetwork_service_browser_tests%2F0%2Flogs%2FNoSessionRestoreTest.PRE_CookiesClearedOnExit%2F0 --NoSessionRestoreTest.CookiesClearedOnExit - -# Flakes https://logs.chromium.org/v/?s=chromium%2Fbb%2Fchromium.linux%2FLinux_Tests%2F65817%2F%2B%2Frecipes%2Fsteps%2Fnetwork_service_browser_tests%2F0%2Flogs%2FRestartTest.CookiesClearedOnExit%2F0 --RestartTest.CookiesClearedOnExit - # Flaky in linux tests. # https://crbug.com/820995 -PlatformAppBrowserTest.Restrictions
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index b4210a1..253dd155 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -3086,7 +3086,7 @@ }, 'Marshmallow Tablet Tester': { 'swarming': { - 'hard_timeout': 60, + 'hard_timeout': 120, }, },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 1ad614be..f661656 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -274,7 +274,7 @@ # generation script is merged with this one, this should be promoted from # the Android-specific section. 'android_swarming': { - 'hard_timeout': 60, + 'hard_timeout': 120, }, }, 'mojo_test_apk': {
diff --git a/testing/libfuzzer/README.md b/testing/libfuzzer/README.md index 99a7aa9..df023d7 100644 --- a/testing/libfuzzer/README.md +++ b/testing/libfuzzer/README.md
@@ -10,7 +10,7 @@ *** This directory contains integration between [libFuzzer] and Chromium. -libFuzzer is an in-process coverage-driven evolutionary fuzzer. It helps +LibFuzzer is an in-process coverage-driven evolutionary fuzzing engine. It helps engineers to uncover potential security & stability problems earlier. *** note @@ -25,11 +25,11 @@ ## Documentation * [Getting Started Guide] walks you through all the steps necessary to create -your fuzzer and submit it to ClusterFuzz. -* [Efficient Fuzzer Guide] explains how to measure fuzzer effectiveness and +your fuzz target and submit it to ClusterFuzz. +* [Efficient Fuzzer Guide] explains how to measure fuzz target effectiveness and ways to improve it. * [Guide to libprotobuf-mutator] walks through the steps necessary to create a -fuzzer that libFuzzer gives mutated protobufs to as input (for developers +fuzz target that libFuzzer gives mutated protobufs to as input (for developers already familiar with libFuzzer). * [ClusterFuzz Integration] describes integration between ClusterFuzz and libFuzzer. @@ -39,7 +39,7 @@ ## Trophies * [ClusterFuzz Bugs] - issues found and automatically filed by ClusterFuzz. -* [Manual Bugs] - issues that were filed manually after running fuzzers. +* [Manual Bugs] - issues that were filed manually after running fuzz targets. * [Pdfium Bugs] - bugs found in pdfium by manual fuzzing. * [OSS Trophies] - bugs found with libFuzzer in open-source projects.
diff --git a/testing/libfuzzer/clusterfuzz.md b/testing/libfuzzer/clusterfuzz.md index 56b72053..c46c4df 100644 --- a/testing/libfuzzer/clusterfuzz.md +++ b/testing/libfuzzer/clusterfuzz.md
@@ -1,34 +1,34 @@ # libFuzzer and ClusterFuzz Integration ClusterFuzz is a distributed fuzzing infrastructure that automatically -executes libFuzzer tests on scale. +executes libFuzzer powered fuzzer tests on scale. Googlers can read more [here](https://goto.google.com/clusterfuzz). ## Status Links * [Buildbot] - status of all libFuzzer builds. -* [ClusterFuzz Fuzzer Status] - fuzzing metrics, links to crashes and coverage +* [ClusterFuzz Fuzzer Status] - fuzzing metrics, links to crashes and coverage reports. -* [ClusterFuzz libFuzzer Logs] - individual fuzzer run logs. -* [Corpus GCS Bucket] - current corpus for each fuzzer. Can be used to upload -bootstrapped corpus. +* [ClusterFuzz libFuzzer Logs] - individual fuzz target run logs. +* [Corpus GCS Bucket] - current corpus for each fuzz target. Can be used to +upload bootstrapped corpus. ## Integration Details The integration between libFuzzer and ClusterFuzz consists of: * Build rules definition in [fuzzer_test.gni]. -* [Buildbot] that automatically discovers fuzzers using `gn refs` facility, -builds fuzzers with multiple sanitizers and uploads binaries to a special -GCS bucket. Build bot recipe is defined in [chromium_libfuzzer.py]. -* ClusterFuzz downloads new binaries once a day and runs fuzzers continuously. -* Fuzzer run logs are uploaded to [ClusterFuzz libFuzzer Logs] GCS bucket. -* Fuzzing corpus is maintained for each fuzzer in [Corpus GCS Bucket]. Once a day, -corpus is minimized to reduce number of duplicates and/or reduce effect of -parasitic coverage. -* [ClusterFuzz Fuzzer Status] displays fuzzer runtime -metrics as well as provides links to crashes and coverage reports. +* [Buildbot] that automatically discovers fuzz targets using `gn refs`, builds +fuzz targets with multiple sanitizers and uploads binaries to a GCS bucket. +Recipe is defined in [chromium_libfuzzer.py]. +* ClusterFuzz downloads builds and runs fuzz targets continuously. +* Fuzz target run logs are uploaded to [ClusterFuzz libFuzzer Logs] GCS bucket. +* Fuzzing corpus is maintained for each fuzz target in [Corpus GCS Bucket]. Once +a day, the corpus is minimized to reduce number of duplicates and/or reduce +effect of parasitic coverage. +* [ClusterFuzz Fuzzer Status] displays fuzzer runtime metrics as well as +provides links to crashes and coverage reports. ## Corpus @@ -41,7 +41,7 @@ These corpus files are frequently modified during fuzzing sessions and can be deleted during corpus minimization. -A fuzzer has two input corpus directories, seed and general, but its output +A fuzz target has two input corpus directories, seed and general, but its output goes into general corpus directory. Seed corpus is read-only.
diff --git a/testing/libfuzzer/efficient_fuzzer.md b/testing/libfuzzer/efficient_fuzzer.md index bbde9ab..04b5dc7 100644 --- a/testing/libfuzzer/efficient_fuzzer.md +++ b/testing/libfuzzer/efficient_fuzzer.md
@@ -1,39 +1,124 @@ -# Efficient Fuzzer +# Efficient Fuzzer Guide -This document describes ways to determine your fuzzer efficiency and ways +This document describes ways to determine efficiency of a fuzz target and ways to improve it. ## Overview -Being a coverage-driven fuzzer, libFuzzer considers a certain input *interesting* -if it results in new code coverage. The set of all interesting inputs is called +Being a coverage-driven fuzzing engine, libFuzzer considers a certain input +*interesting* if it results in new code coverage, i.e. it reaches a code that +has not been reached before. The set of all interesting inputs is called *corpus*. Items in corpus are constantly mutated in search of new interesting inputs. Corpus can be shared across fuzzer runs and grows over time as new code is reached. -The following things are extremely effective for improving fuzzer efficiency, so we -*strongly recommend* them for any fuzzer: +There are several metrics you should look at to determine effectiveness of your +fuzz target: + +* [Execution Speed](#Execution-Speed) +* [Code Coverage](#Code-Coverage) +* [Corpus Size](#Corpus-Size) + +You can collect these metrics manually or take them from [ClusterFuzz status] +pages after a fuzz target is checked in Chromium repository. + +The following things are extremely useful for improving fuzzing efficiency, so +we *strongly recommend* them for any fuzz target: * [Seed Corpus](#Seed-Corpus) * [Fuzzer Dictionary](#Fuzzer-Dictionary) -There are several metrics you should look at to determine your fuzzer effectiveness: +There are other ways that are useful in some cases, but not always applicable: +* [Custom Options](#Custom-Options) +* [Custom Build](#Custom-Build) -* [Fuzzer Speed](#Fuzzer-Speed) -* [Corpus Size](#Corpus-Size) -* [Code Coverage](#Code-Coverage) -You can collect these metrics manually or take them from [ClusterFuzz status] -pages after a fuzzer is checked in Chromium repository. +## Execution Speed + +Fuzz target speed is calculated in executions per second. It is printed while a +fuzz target is running: + +``` +#19346 NEW cov: 2815 bits: 1082 indir: 43 units: 150 exec/s: 19346 L: 62 +``` + +Because libFuzzer performs randomized mutations, it is critical to have it run +as fast as possible to navigate through the large search space efficiently and +find interesting code paths. You should try to get to at least 1,000 exec/s from +your fuzz target locally before submitting it to the Chromium repository. + + +### Initialization/Cleanup + +Try to keep `LLVMFuzzerTestOneInput` function as simple as possible. If your +fuzzing function is too complex, it can bring down fuzzer execution speed OR it +can target very specific usecases and fail to account for unexpected scenarios. + +Prefer to use static initialization and shared resources rather than performing +setup and teardown on every single input. Checkout example on +[startup initialization] in libFuzzer documentation. + +You can skip freeing static resources. However, all resources allocated within +`LLVMFuzzerTestOneInput` function should be de-allocated since this function is +called millions of times during a fuzzing session. Otherwise, we will hit OOMs +frequently and reduce overall fuzzing efficiency. + + +### Memory Usage + +Avoid allocation of dynamic memory wherever possible. Memory instrumentation +works faster for stack-based and static objects, than for heap allocated ones. + +It is always a good idea to try different variants for your fuzz target locally, +and then submit the fastest implementation. + + +## Code Coverage + +[ClusterFuzz status] page provides source-level coverage report for fuzz targets +from recent runs. Looking at the report might provide an insight on how to +improve code coverage of a fuzz target. + +You can also generate source-level coverage report locally by running the +[coverage script] stored in Chromium repository. The script provides detailed +instructions as well as an usage example. + +Note that code coverage of a fuzz target **depends heavily** on the corpus +provided when running the target, i.e. code coverage report generated by a fuzz +target launched without any corpus would not make much sense. + +We encourage you to try out the [coverage script], as it usually generates a better +code coverage visualization compared to the coverage report hosted on +ClusterFuzz. +*NOTE: This is an experimental feature and an active area of work. We are +working on improving this process.* + + +## Corpus Size + +After running for a while, a fuzz target would reach a plateau and may stop +discovering new interesting inputs. Corpus for a reasonably complex target +should contain hundreds (if not thousands) of items. + +Too small of a corpus size indicates that fuzz target is hitting a code barrier +and is unable to get past it. Common cases of such issues include: checksums, +magic numbers, etc. The easiest way to diagnose this problem is to generate and +analyze a [coverage report](#Coverage). To fix the issue, you can: + +* Change the code (e.g. disable crc checks while fuzzing), see [Custom Build](#Custom-Build). +* Prepare or improve [seed corpus](#Seed-Corpus). +* Prepare or improve [fuzzer dictionary](#Fuzzer-Dictionary). +* Add [custom options](#Custom-Options). + ## Seed Corpus -Seed corpus is a set of *valid* and *interesting* inputs that serve as starting points -for a fuzzer. If one is not provided, a fuzzer would have to guess these inputs -from scratch, which can take an indefinite amount of time depending of the size -of inputs. +Seed corpus is a set of *valid* and *interesting* inputs that serve as starting +points for a fuzz target. If one is not provided, a fuzzing engine would have to +guess these inputs from scratch, which can take an indefinite amount of time +depending on size of the inputs and complexity of the target format. Seed corpus works especially well for strictly defined file formats and data transmission protocols. @@ -41,20 +126,23 @@ * For file format parsers, add valid files from your test suite. * For protocol parsers, add valid raw streams from test suite into separate files. -Other examples include a graphics library seed corpus, which would be a variety of -small PNG/JPG/GIF files. +Other examples include a graphics library seed corpus, which would be a variety +of small PNG/JPG/GIF files. -If you are running the fuzzer locally, you can pass a corpus directory as an argument: +If you are running a fuzz target locally, you can pass a corpus directory as an +argument: ``` ./out/libfuzzer/my_fuzzer ~/tmp/my_fuzzer_corpus ``` -While libFuzzer can start with an empty corpus, most fuzzers require a seed corpus -to be useful. The fuzzer would store all the interesting items it finds in that directory. +The fuzzer would store all the interesting inputs it finds in that directory. + +While libFuzzer can start with an empty corpus, seed corpus is always useful and +in many cases is able to increase code coverage by an order of magnitude. ClusterFuzz uses seed corpus defined in Chromium source repository. You need to -add a `seed_corpus` attribute to your fuzzer definition in BUILD.gn file: +add a `seed_corpus` attribute to your `fuzzer_test` definition in BUILD.gn file: ``` fuzzer_test("my_protocol_fuzzer") { @@ -77,9 +165,9 @@ All files found in these directories and their subdirectories will be archived into a `<my_fuzzer_name>_seed_corpus.zip` output archive. -If you can't store seed corpus in Chromium repository (e.g. it is too large, has -licensing issues, etc), you can upload the corpus to Google Cloud Storage bucket -used by ClusterFuzz: +If you can't store seed corpus in Chromium repository (e.g. it is too large, +cannot be open sourced, etc), you can upload the corpus to Google Cloud Storage +bucket used by ClusterFuzz: 1) Go to [Corpus GCS Bucket]. 2) Open directory named `<my_fuzzer_name>_static`. If the directory does not @@ -91,66 +179,12 @@ gsutil -m rsync <path_to_corpus> gs://clusterfuzz-corpus/libfuzzer/<my_fuzzer_name>_static ``` -## Fuzzer Dictionary - -It is very useful to provide fuzzer a set of *common words or values* that you -expect to find in the input. Adding a dictionary highly improves the efficiency of -finding new units and works especially well in certain usecases (e.g. fuzzing file -format decoders). - -To add a dictionary, first create a dictionary file. Dictionary file is a flat text file -where tokens are listed one per line in the format of name="value". The -alphanumeric name is ignored and can be omitted, although it is a convenient -way to document the meaning of a particular token. The value must appear in -quotes, with hex escaping (\xNN) applied to all non-printable, high-bit, or -otherwise problematic characters (\\ and \" shorthands are recognized too). -This syntax is similar to the one used by [AFL] fuzzing engine (-x option). - -An examples dictionary looks like: - -``` -# Lines starting with '#' and empty lines are ignored. - -# Adds "blah" word (w/o quotes) to the dictionary. -kw1="blah" -# Use \\ for backslash and \" for quotes. -kw2="\"ac\\dc\"" -# Use \xAB for hex values. -kw3="\xF7\xF8" -# Key name before '=' can be omitted: -"foo\x0Abar" -``` - -Make sure to test your dictionary by running your fuzzer locally: - -```bash -./out/libfuzzer/my_protocol_fuzzer -dict=<path_to_dict> <path_to_corpus> -``` - -If the dictionary is effective, you should see new units discovered in fuzzer output. - -To submit a dictionary to Chromium repository: - -1) Add the dictionary file in the same directory as your fuzz target, with name -`<my_fuzzer>.dict`. -2) Add `dict` attribute to fuzzer definition in BUILD.gn file: - -``` -fuzzer_test("my_protocol_fuzzer") { - ... - dict = "my_protocol_fuzzer.dict" -} -``` - -The dictionary will be used automatically by ClusterFuzz once it picks up a new -revision build. - ### Corpus Minimization -It's important to minimize seed corpus to a *small set of interesting inputs* before -uploading. The reason being that seed corpus is synced to all fuzzing bots for every -iteration, so it is important to keep it small both for fuzzing efficiency and to prevent -our bots from running out of disk space (should not exceed 1 Gb). +It's important to minimize seed corpus to a *small set of interesting inputs* +before uploading. The reason being that seed corpus is synced to all fuzzing +bots for every iteration, so it is important to keep it small both for fuzzing +efficiency and to prevent our bots from running out of disk space. The minimization can be done using `-merge=1` option of libFuzzer: @@ -166,125 +200,72 @@ a minimized corpus that gives the same code coverage as the initial `seed_corpus` directory. -## Fuzzer Speed -Fuzzer speed is calculated in executions per second. It is printed while the fuzzer -is running: + + +## Fuzzer Dictionary + +It is very useful to provide fuzz target with a set of *common words or values* +that you expect to find in the input. Adding a dictionary highly improves the +efficiency of finding new units and works especially well in certain usecases +(e.g. fuzzing file format decoders or text based protocols like XML). + +To add a dictionary, first create a dictionary file. This is a flat text file +where tokens are listed one per line in the format of `name="value"`, where +`name` is optional and can be omitted, although it is a convenient way to +document the meaning of a particular token. The value must appear in quotes, +with hex escaping (\xNN) applied to all non-printable, high-bit, or otherwise +problematic characters (\\ and \" shorthands are recognized too). This syntax is +similar to the one used by [AFL] fuzzing engine (-x option). + +An example dictionary looks like: ``` -#19346 NEW cov: 2815 bits: 1082 indir: 43 units: 150 exec/s: 19346 L: 62 +# Lines starting with '#' and empty lines are ignored. + +# Adds "blah" word (w/o quotes) to the dictionary. +kw1="blah" +# Use \\ for backslash and \" for quotes. +kw2="\"ac\\dc\"" +# Use \xAB for hex values. +kw3="\xF7\xF8" +# Key name before '=' can be omitted: +"foo\x0Abar" ``` -Because libFuzzer performs randomized mutations, it is critical to have it run as -fast as possible to navigate the large search space efficiently and find interesting -code paths. You should try to get to at least 1,000 exec/s from your fuzzer runs -locally before submitting the fuzzer to Chromium repository. Profile the fuzzer -using any standard tool to see where it spends its time. +Make sure to test your dictionary by running your fuzz target locally: - -### Initialization/Cleanup - -Try to keep `LLVMFuzzerTestOneInput` function as simple as possible. If your fuzzing -function is too complex, it can bring down fuzzer execution speed OR it might target -very specific usecases and fail to account for unexpected scenarios. - -Prefer to use static initialization and shared resources rather than bringing the -environment up and down on every single run. Otherwise, it will slow down -fuzzer speed on every run and its ability to find new interesting inputs. -Checkout example on [startup initialization] in libFuzzer documentation. - -Fuzzers don't have to shutdown gracefully. We either kill them or they crash -because memory sanitizer tool found a problem. You can skip freeing static -resources. - -All resources allocated within `LLVMFuzzerTestOneInput` function should be -de-allocated since this function is called millions of times during a fuzzing session. -Otherwise, we will hit OOMs frequently and reduce overall fuzzing efficiency. - - -### Memory Usage - -Avoid allocation of dynamic memory wherever possible. Memory instrumentation -works faster for stack-based and static objects, than for heap allocated ones. - -It is always a good idea to try different variants for your fuzzer locally, and then -submit the fastest implementation. - - -### Maximum Testcase Length - -You can control the maximum length of a test input using `-max_len` parameter -(see [custom options](#Custom-Options)). This parameter can often significantly -improve execution speed. Beware that you might miss coverage and unexpected -scenarios happening from longer size inputs. - -1) Define which `-max_len` value is reasonable for your target. For example, it -may be useless to fuzz an image decoder with too small value of testcase length. - -2) Increase the value defined on previous step. Check its influence on execution -speed of fuzzer. If speed doesn't drop significantly for long inputs, it is fine -to have some bigger value for `-max_len` or even skip it completely. - -In general, bigger `-max_len` value gives better coverage which is the main -priority for fuzzing. However, low execution speed may result in waste of -fuzzing resources and being unable to find interesting inputs in reasonable time. -If large inputs make the fuzzer too slow, you should adjust the value of `-max_len` -and find a trade-off between coverage and execution speed. - -*Note:* ClusterFuzz runs two different fuzzing engines (**LibFuzzer** and -**AFL**) using the same target functions. AFL doesn't support `-max_len` -parameter and may provide input of any length to the target. If your target has -an input length limit that you would like to *strictly enforce*, it's -recommended to add a sanity check to the beginning of your target function: - -``` -if (size > kSizeLimit) - return 0; +```bash +./out/libfuzzer/my_protocol_fuzzer -dict=<path_to_dict> <path_to_corpus> ``` -For more information check out the discussion in [issue 638836]. +If the dictionary is effective, you should see new units discovered in the +output. + +To submit a dictionary to Chromium repository: + +1) Add the dictionary file in the same directory as your fuzz target +2) Add `dict` attribute to `fuzzer_test` definition in BUILD.gn file: + +``` +fuzzer_test("my_protocol_fuzzer") { + ... + dict = "my_protocol_fuzzer.dict" +} +``` + +The dictionary will be used automatically by ClusterFuzz once it picks up a new +revision build. -## Code Coverage - -[ClusterFuzz status] page provides fuzzer source-level coverage report from -recent runs. Looking at the report might provide an insight to improve fuzzer -coverage. - -You can also generate source-level coverage report locally by running the -[coverage script] stored in Chromium repository. The script provides detailed -instructions as well as an usage example. - -We encourage you to try out the script, as it usually generates a better code -coverage visualization compared to the coverage report hosted on ClusterFuzz. -*NOTE: This is an experimental feature and an active area of work. We are -working on improving this process.* - - -## Corpus Size - -After running for a while, the fuzzer would reach a plateau and won't discover -new interesting inputs. Corpus for a reasonably complex functionality should -contain hundreds (if not thousands) of items. - -Too small of a corpus size indicates fuzzer is hitting a code barrier and is unable -to get past it. Common cases of such issues include: checksums, magic numbers, -etc. The easiest way to diagnose this problem is to generate and analyze a -[coverage report](#Coverage). To fix the issue, you can: - -* Change the code (e.g. disable crc checks while fuzzing). -* Prepare or improve [seed corpus](#Seed-Corpus). -* Prepare or improve [fuzzer dictionary](#Fuzzer-Dictionary). -* Add [custom options](#Custom-Options). - -### Custom Options +## Custom Options Custom options help to fine tune libFuzzer execution parameters and will also override the default values used by ClusterFuzz. Please read [libFuzzer options] page for detailed documentation on how these work. -Add the options needed in `libfuzzer_options` attribute to your fuzzer definition in -BUILD.gn file: +Add the options needed in `libfuzzer_options` attribute to your `fuzzer_test` +definition in BUILD.gn file: ``` fuzzer_test("my_protocol_fuzzer") { @@ -299,6 +280,18 @@ Please note that `dict` parameter should be provided [separately](#Fuzzer-Dictionary). All other options can be passed using `libfuzzer_options` property. + +## Custom Build + +If you need to change the code being tested by your fuzz target, you may use an +`#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` macro in your target code. + +Note that patching target code is not a preferred way of improving corresponding +fuzz target, but in some cases that might be the only way possible, e.g. when +there is no intended API to disable checksum verification, or when target code +uses random generator that affects reproducibility of crashes. + + [AFL]: http://lcamtuf.coredump.cx/afl/ [ClusterFuzz status]: clusterfuzz.md#Status-Links [Corpus GCS Bucket]: https://console.cloud.google.com/storage/clusterfuzz-corpus/libfuzzer
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn index 1038fd0d..a3006cf 100644 --- a/testing/libfuzzer/fuzzers/BUILD.gn +++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -130,15 +130,6 @@ libfuzzer_options = [ "max_len=1500" ] } -fuzzer_test("base_json_reader_fuzzer") { - sources = [ - "base_json_reader_fuzzer.cc", - ] - deps = [ - "//base", - ] -} - libpng_seed_corpuses = [ "//components/viz/test/data", "//third_party/WebKit/LayoutTests/images/png-suite/samples",
diff --git a/testing/libfuzzer/getting_started.md b/testing/libfuzzer/getting_started.md index 8a66569..44875fab 100644 --- a/testing/libfuzzer/getting_started.md +++ b/testing/libfuzzer/getting_started.md
@@ -7,8 +7,8 @@ This document will walk you through: * setting up your build enviroment. -* creating your first fuzzer. -* running the fuzzer and verifying its vitals. +* creating your first fuzz target. +* running the fuzz target and verifying its vitals. ## Configure Build @@ -33,14 +33,14 @@ | `is_ubsan_security=true` | enables [Undefined Behavior Sanitizer] to catch<sup>\[[*](reference.md#UBSan)\]</sup> undefined behavior like integer overflow. | | | it is possible to run libfuzzer without any sanitizers; *probably not what you want*.| - Fuzzers are built with minimal symbols by default, regardless of the value of -`is_debug` and `symbol_level`. However if you want to run the fuzzer under a +Fuzz targets are built with minimal symbols by default, regardless of the value +of `is_debug` and `symbol_level`. However if you want to run fuzz target under a debugger you can re-enable them by setting `sanitizer_keep_symbols=true`. To get the exact GN configuration that are used on our builders, see [Build Config]. -## Write Fuzzer Function +## Write Fuzz Target Create a new `<my_fuzzer>.cc` file and define a `LLVMFuzzerTestOneInput` function: @@ -54,10 +54,11 @@ } ``` -*Note*: You should create the fuzzer file `<my_fuzzer>.cc` next to the code that is being -tested and in the same directory as your other unit tests. Please do not use -`testing/libfuzzer/fuzzers` directory, this was a directory used for initial sample fuzzers and -is no longer recommended for any new fuzzers. +*Note*: You should create the fuzz target file `<my_fuzzer>.cc next to the code +that is being tested and in the same directory as your other unit tests. Please +do not use `testing/libfuzzer/fuzzers` directory, this was a directory used for +initial sample fuzz targets and is no longer recommended for landing new fuzz +targets. [quic_stream_factory_fuzzer.cc] is a good example of real-world fuzz target. @@ -73,7 +74,7 @@ } ``` -## Build and Run Fuzzer Locally +## Build and Run Fuzz Target Locally Build with ninja as usual and run: @@ -82,24 +83,29 @@ ./out/libfuzzer/url_parse_fuzzer ``` -Your fuzzer should produce output like this: +Your fuzz target should produce output like this: ``` -INFO: Seed: 1787335005 -INFO: -max_len is not provided, using 64 -INFO: PreferSmall: 1 -#0 READ units: 1 exec/s: 0 -#1 INITED cov: 2361 bits: 95 indir: 29 units: 1 exec/s: 0 -#2 NEW cov: 2710 bits: 359 indir: 36 units: 2 exec/s: 0 L: 64 MS: 0 +INFO: Seed: 1511722356 +INFO: Loaded 2 modules (115485 guards): 22572 [0x7fe8acddf560, 0x7fe8acdf5610), 92913 [0xaa05d0, 0xafb194), +INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes +INFO: A corpus is not provided, starting from an empty corpus +#2 INITED cov: 961 ft: 48 corp: 1/1b exec/s: 0 rss: 48Mb +#3 NEW cov: 986 ft: 70 corp: 2/104b exec/s: 0 rss: 48Mb L: 103/103 MS: 1 InsertRepeatedBytes- +#4 NEW cov: 989 ft: 74 corp: 3/106b exec/s: 0 rss: 48Mb L: 2/103 MS: 1 InsertByte- +#6 NEW cov: 991 ft: 76 corp: 4/184b exec/s: 0 rss: 48Mb L: 78/103 MS: 2 CopyPart-InsertRepeatedBytes- ``` -The `... NEW ...` line appears when libFuzzer finds new and interesting inputs. -The efficient fuzzer should be able to finds lots of them rather quickly. -The `... pulse ...` line will appear periodically to show the current status. +* `... NEW ...` line appears when libFuzzer finds new and interesting inputs. +* an efficient fuzz target should be able to finds lots of them rather quickly. +* `... pulse ...` line will appear periodically to show the current status. + +For more information about libFuzzer's output, please refer to [its own +documentation]. ### Symbolize Stacktrace -If your fuzzer crashes when running locally and you see non-symbolized +If your fuzz target crashes when running locally and you see non-symbolized stacktrace, make sure that you have directory containing `llvm-symbolizer` binary added in `$PATH`. The symbolizer binary is included in Chromium's Clang package located at `third_party/llvm-build/Release+Asserts/bin/` directory. @@ -112,35 +118,42 @@ ./fuzzer ./crash-input ``` -The same approach works with other sanitizers (e.g. `MSAN_OPTIONS`, `UBSAN_OPTIONS`, etc). +The same approach works with other sanitizers (e.g. `MSAN_OPTIONS`, +`UBSAN_OPTIONS`, etc). -## Improving Your Fuzzer +## Improving Your Fuzz Target -Your fuzzer may immediately discover interesting (i.e. crashing) inputs. +Your fuzz target may immediately discover interesting (i.e. crashing) inputs. To make it more efficient, several small steps can take you really far: * Create seed corpus. Add `seed_corpus = "src/fuzz-testcases/"` attribute -to your fuzzer targets and add example files in appropriate folder. Read more -in [Seed Corpus] section of efficient fuzzer guide. +to your fuzzer target and add example files in appropriate folder. Read more +in [Seed Corpus] section of the [Efficient Fuzzer Guide]. *Make sure corpus files are appropriately licensed.* * Create mutation dictionary. With a `dict = "protocol.dict"` attribute and `key=value` dicitionary file format, mutations can be more effective. -See [Fuzzer Dictionary] section of efficient fuzzer guide. -* Specify maximum testcase length. By default libFuzzer uses `-max_len=64` - (or takes the longest testcase in a corpus). ClusterFuzz takes -random value in range from `1` to `10000` for each fuzzing session and passes -that value to libFuzzers. If corpus contains testcases of size greater than -`max_len`, libFuzzer will use only first `max_len` bytes of such testcases. -See [Maximum Testcase Length] section of the efficient fuzzer guide. +See [Fuzzer Dictionary] section of the [Efficient Fuzzer Guide]. +* Specify testcase length limits. By default, libFuzzer uses `-max_len=4096` +or takes the longest testcase in the corpus if `-max_len` is not specified. +ClusterFuzz uses different strategies for different fuzzing sessions, including +different random values. Also, ClusterFuzz uses different fuzzing engines (e.g. +AFL that doesn't have `-max_len` option). If your target has an input length +limit that you would like to *strictly enforce*, add a sanity check to the +beginning of your target function: -## Disable noisy error message logging +```cpp +if (size < kMinInputLength || size > kMaxInputLength) + return 0; +``` -If the code that you are a fuzzing generates lot of error messages when +### Disable noisy error message logging + +If the code that you are fuzzing generates lot of error messages when encountering incorrect or invalid data, then you need to silence those errors -in the fuzzer. Otherwise, fuzzer will be slow and inefficient. +in the fuzz target. Otherwise, fuzz target will be slow and inefficient. -If the target uses the Chromium logging APIs, the best way to do that is to -override the environment used for logging in your fuzzer: +If the target uses Chromium logging APIs, the best way to do that is to +override the environment used for logging in your fuzz target: ```cpp struct Environment { @@ -152,20 +165,135 @@ Environment* env = new Environment(); ``` -## Submitting Fuzzer to ClusterFuzz +## Mutating Multiple Inputs + +By default, a fuzzing engine such as libFuzzer mutates a single input referenced +by `uint8_t* data, size_t size`. However, quite often an API under fuzz testing +accepts multiple arguments of various types rather than a single buffer. There +are three approaches for such cases: + +### 1) libprotobuf-mutator + +If you need to mutate multiple inputs of various types and length, please see +[Getting Started with libprotobuf-mutator in Chromium]. That approach allows +to mutate multiple inputs independently. + +**Caveats:** This approach requires an extra effort, but works with APIs and +data structures of any complexity. + +### 2) hash-based argument + +Another frequent case of an API under fuzz testing is a function that accepts a +buffer with data and some integer value meaning a bitwise combination of flags. +For such cases, we recommend to calculate a hash value from `(data, size)` and +use that value for fuzzing of an additional integer argument, for example: + +```cpp +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + std::string str = std::string(reinterpret_cast<const char*>(data), size); + std::size_t data_hash = std::hash<std::string>()(str); + APIToBeFuzzed(data, size, data_hash); + return 0; +} + +``` + +**Caveats:** Hash value derived from the data would be a random value rather +than a meaningful value controlled by fuzzing engine, i.e. a single bit mutation +would result in a completely different hash value that might lead to a new code +coverage, but the next mutation would generate another hash value and trigger +another code path, without providing a real guidance to the fuzzing engine. + +### 3) bytes taken from (data, size) + +You can extract one or more bytes from the data provided by fuzzing engine and +use that value for fuzzing other arguments of the target API or making other +decisions (e.g. number of iterations or attempts for calling some function). +Note that those bytes should not be used as data for any other arguments, e.g.: + +```cpp +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // Don't forget to enfoce minimal data length. + if (size < 1) + return 0; + + // Extract single byte for fuzzing "flags" value. + uint8_t flags = data[0]; + + // Wrong, there is a bias between flags and API input. + APIToBeFuzzed(data, size, flags); + + // Good, API input and flags are independent. + APIToBeFuzzed(data + 1, size - 1, flags); + + return 0; +} +``` + +This approach addresses the problem of the *hash-based argument* approach, but +has its own **caveats**: + +* If you extract any bytes from the input (either first or last ones), you +cannot use valid samples as seed corpus. In that case, you'll have to generate +seed corpus manually, i.e. append necessary bytes to the valid sample inputs. + +* Imagine that `APIToBeFuzzed()` had a bug, something like the following: + +```cpp +void APIToBeFuzzed(uint8_t* buffer, size_t length, uint8_t options) { + ... + if (options == 0x66) { + // Yes, looks ridiculous, but things like that did happen in the real world. + *(buffer - 1) = -1; + } + ... +} +``` + +assuming we used the fuzz target listed above, neither ASan nor other santizers +would detect a buffer underwrite vulnerability, as the byte addressed by +`buffer - 1` is actually a mapped memory allocated inside the fuzzing engine as +`data[0]`. + +To avoid issues like that one, we would have to allocate a separate buffer and +copy API input into it, or use a container object e.g.: + +```cpp +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // Don't forget to enfoce minimal data length. + if (size < 1) + return 0; + + // Extract single byte for fuzzing flags value. + uint8_t flags = data[0]; + + // Put API input into a separate container. + std::vector<uint8_t> buffer(data + 1, data + size); + + APIToBeFuzzed(buffer.data(), buffer.size(), flags); + + return 0; +} +``` + +There is [base::FuzzedDataProvider] class that might be helpful for writing +fuzz targets using that approach. + + +## Submitting Fuzz Target to ClusterFuzz ClusterFuzz builds and executes all `fuzzer_test` targets in the Chromium -repository. It is extremely important to submit a fuzzer into Chromium +repository. It is extremely important to land a fuzz target into Chromium repository so that ClusterFuzz can run it at scale. Do not rely on just -running fuzzing locally in your own environment, as it will catch far less -issues. It's crucial to run fuzzers continuously forever for catching +running fuzzers locally in your own environment, as it will catch far less +issues. It's crucial to run fuzz targets continuously forever for catching regressions and improving code coverage over time. ## Next Steps -* After your fuzzer is submitted, you should check [ClusterFuzz status] page in -a day or two. -* Check the [Efficient Fuzzer Guide] to better understand your fuzzer +* After your fuzz target is landed, you should check [ClusterFuzz status] page +in a day or two. +* Check the [Efficient Fuzzer Guide] to better understand your fuzz target performance and for optimization hints. @@ -173,10 +301,12 @@ [ClusterFuzz status]: clusterfuzz.md#Status-Links [Efficient Fuzzer Guide]: efficient_fuzzer.md [Fuzzer Dictionary]: efficient_fuzzer.md#Fuzzer-Dictionary -[Maximum Testcase Length]: efficient_fuzzer.md#Maximum-Testcase-Length [Memory Sanitizer]: http://clang.llvm.org/docs/MemorySanitizer.html [Seed Corpus]: efficient_fuzzer.md#Seed-Corpus [Undefined Behavior Sanitizer]: http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html [crbug/598448]: https://bugs.chromium.org/p/chromium/issues/detail?id=598448 [quic_stream_factory_fuzzer.cc]: https://cs.chromium.org/chromium/src/net/quic/chromium/quic_stream_factory_fuzzer.cc [Build Config]: reference.md#Builder-configurations +[its own documentation]: http://llvm.org/docs/LibFuzzer.html#output +[Getting Started with libprotobuf-mutator in Chromium]: libprotobuf-mutator.md +[base::FuzzedDataProvider]: https://cs.chromium.org/chromium/src/base/test/fuzzed_data_provider.h \ No newline at end of file
diff --git a/testing/libfuzzer/reference.md b/testing/libfuzzer/reference.md index aa6480e..04b3459c 100644 --- a/testing/libfuzzer/reference.md +++ b/testing/libfuzzer/reference.md
@@ -1,6 +1,6 @@ # libFuzzer Integration Reference -## Additional sanitizer configuration +## Additional Sanitizer Configuration ### MSan @@ -79,11 +79,13 @@ | Argument | Description | |----------|-------------| -| sources | **required** list of fuzzer test source files | -| deps | fuzzer dependencies | -| additional_configs | additional GN configurations to be used for compilation | -| dict | a dictionary file for the fuzzer | -| libfuzzer_options | runtime options file for the fuzzer. See [Fuzzer Runtime Options](#Fuzzer-Runtime-Options) | +| `sources` | **required** list of fuzzer test source files | +| `deps` | fuzzer dependencies | +| `additional_configs` | additional GN configurations to be used for compilation | +| `dict` | a dictionary file for the fuzzer | +| `libfuzzer_options` | runtime options file for the fuzzer. See [Fuzzer Runtime Options](#Fuzzer-Runtime-Options) | +| `seed_corpus` | single directory containing test inputs, parsed recursively | +| `seed_corpuses` | multiple directories with the same purpose as `seed_corpus` | ## Fuzzer Runtime Options
diff --git a/testing/trigger_scripts/PRESUBMIT.py b/testing/trigger_scripts/PRESUBMIT.py index d47132a..f4042bc 100644 --- a/testing/trigger_scripts/PRESUBMIT.py +++ b/testing/trigger_scripts/PRESUBMIT.py
@@ -40,7 +40,7 @@ cl, [ 'luci.chromium.try:linux_optional_gpu_tests_rel', - 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'luci.chromium.try:mac_optional_gpu_tests_rel', 'master.tryserver.chromium.win:win_optional_gpu_tests_rel', 'master.tryserver.chromium.android:android_optional_gpu_tests_rel', ],
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index b0c9d31..7689b43 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1586,38 +1586,19 @@ crbug.com/738493 http/tests/performance-timing/longtask-v2/longtask-executescript.html [ Skip ] # Expected failures during incremental implementation of mojo notification. -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworker-notification-event.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworker-notification-properties.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworker-notificationclick-event-action-reflection.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworker-notificationclick-event-data-reflection.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworker-notificationclick-event-reply-reflection.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworker-notificationclick-openwindow-crash.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworker-notificationclose-event-data-reflection.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-document-click.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-document-close.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-document-data-invalid.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-document-direction.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-document-fetch-resources.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-document-image-404.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-document-image-redirect-loop.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-document-image-redirect.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-document-image-slow-404.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-document-image-slow.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-get-close.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-get-empty.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-get-filter.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-get-from-service-worker.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-get-replacement.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-get.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-service-worker-click.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-service-worker-fetch-resources.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-service-worker-get-filter.html [ Skip ] crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-service-worker-get.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-service-worker-image-404.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-service-worker-image-redirect-loop.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-service-worker-image-redirect.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-service-worker-image-slow-404.html [ Skip ] -crbug.com/796991 virtual/mojo-notifications/http/tests/notifications/serviceworkerregistration-service-worker-image-slow.html [ Skip ] crbug.com/713587 external/wpt/css/css-ui/caret-color-006.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/animations/web-animations/animation-state-changes-negative-playback-rate.html b/third_party/WebKit/LayoutTests/animations/web-animations/animation-state-changes-negative-playback-rate.html index f5d57729..ec47fd65 100644 --- a/third_party/WebKit/LayoutTests/animations/web-animations/animation-state-changes-negative-playback-rate.html +++ b/third_party/WebKit/LayoutTests/animations/web-animations/animation-state-changes-negative-playback-rate.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> <title>Test play state changes for animations with a negative playback rate</title> -<link rel="help" href="http://w3c.github.io/web-animations/#play-state"> +<link rel="help" href="https://drafts.csswg.org/web-animations/#play-state"> <script src="../../external/wpt/web-animations/testcommon.js"></script> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script>
diff --git a/third_party/WebKit/LayoutTests/animations/web-animations/animation-state-changes-positive-playback-rate.html b/third_party/WebKit/LayoutTests/animations/web-animations/animation-state-changes-positive-playback-rate.html index db9910a8..0982146 100644 --- a/third_party/WebKit/LayoutTests/animations/web-animations/animation-state-changes-positive-playback-rate.html +++ b/third_party/WebKit/LayoutTests/animations/web-animations/animation-state-changes-positive-playback-rate.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> <title>Tests for discrete animation</title> -<link rel="help" href="https://w3c.github.io/web-animations/#play-state"> +<link rel="help" href="https://drafts.csswg.org/web-animations/#play-state"> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../external/wpt/web-animations/testcommon.js"></script>
diff --git a/third_party/WebKit/LayoutTests/animations/web-animations/the-effect-value-of-a-keyframe-effect.html b/third_party/WebKit/LayoutTests/animations/web-animations/the-effect-value-of-a-keyframe-effect.html index 5dc6253..5ddfb15 100644 --- a/third_party/WebKit/LayoutTests/animations/web-animations/the-effect-value-of-a-keyframe-effect.html +++ b/third_party/WebKit/LayoutTests/animations/web-animations/the-effect-value-of-a-keyframe-effect.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> <title>Keyframe handling tests</title> -<link rel="help" href="https://w3c.github.io/web-animations/#the-effect-value-of-a-keyframe-animation-effect"> +<link rel="help" href="https://drafts.csswg.org/web-animations/#the-effect-value-of-a-keyframe-animation-effect"> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../external/wpt/web-animations/testcommon.js"></script>
diff --git a/third_party/WebKit/LayoutTests/css3/blending/effect-background-blend-mode-expected.png b/third_party/WebKit/LayoutTests/css3/blending/effect-background-blend-mode-expected.png index 496856f..cb4f20a4 100644 --- a/third_party/WebKit/LayoutTests/css3/blending/effect-background-blend-mode-expected.png +++ b/third_party/WebKit/LayoutTests/css3/blending/effect-background-blend-mode-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/css3/blending/effect-background-blend-mode-stacking-expected.png b/third_party/WebKit/LayoutTests/css3/blending/effect-background-blend-mode-stacking-expected.png index 7c833e9..b28d641 100644 --- a/third_party/WebKit/LayoutTests/css3/blending/effect-background-blend-mode-stacking-expected.png +++ b/third_party/WebKit/LayoutTests/css3/blending/effect-background-blend-mode-stacking-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/css3/blending/effect-background-blend-mode-tiled-expected.png b/third_party/WebKit/LayoutTests/css3/blending/effect-background-blend-mode-tiled-expected.png index 6a85f94..7017949 100644 --- a/third_party/WebKit/LayoutTests/css3/blending/effect-background-blend-mode-tiled-expected.png +++ b/third_party/WebKit/LayoutTests/css3/blending/effect-background-blend-mode-tiled-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/css3/blending/mix-blend-mode-isolated-group-1-expected.png b/third_party/WebKit/LayoutTests/css3/blending/mix-blend-mode-isolated-group-1-expected.png index e84839d..11079957 100644 --- a/third_party/WebKit/LayoutTests/css3/blending/mix-blend-mode-isolated-group-1-expected.png +++ b/third_party/WebKit/LayoutTests/css3/blending/mix-blend-mode-isolated-group-1-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/css3/filters/nested-filter-expected.png b/third_party/WebKit/LayoutTests/css3/filters/nested-filter-expected.png index dcc6523..2dc9945 100644 --- a/third_party/WebKit/LayoutTests/css3/filters/nested-filter-expected.png +++ b/third_party/WebKit/LayoutTests/css3/filters/nested-filter-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 31fc301..4152679 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -172236,15 +172236,13 @@ {} ] ], - "IndexedDB/interfaces.html": [ + "IndexedDB/interfaces.any.js": [ [ - "/IndexedDB/interfaces.html", + "/IndexedDB/interfaces.any.html", {} - ] - ], - "IndexedDB/interfaces.worker.js": [ + ], [ - "/IndexedDB/interfaces.worker.html", + "/IndexedDB/interfaces.any.worker.html", {} ] ], @@ -248827,12 +248825,8 @@ "251a828d333bdd3face9d20a2a28ddf0c0ffeb49", "testharness" ], - "IndexedDB/interfaces.html": [ - "348a7350d749c4ea11d383d1f3e07e54a9d0d377", - "testharness" - ], - "IndexedDB/interfaces.worker.js": [ - "a74350d69819f73cf9f75ac636f8793f018ba2fd", + "IndexedDB/interfaces.any.js": [ + "df07f5da63c34969a24fe43bc4268418ab0a5132", "testharness" ], "IndexedDB/interleaved-cursors-common.js": [ @@ -369928,11 +369922,11 @@ "testharness" ], "streams/readable-byte-streams/general-expected.txt": [ - "b3e8e0de49f3f6b9fc0cc5dd7b6e5a53bbba291b", + "ee74445ee891ea959b53a27ac3a87fb4350228a1", "support" ], "streams/readable-byte-streams/general.dedicatedworker-expected.txt": [ - "b3e8e0de49f3f6b9fc0cc5dd7b6e5a53bbba291b", + "ee74445ee891ea959b53a27ac3a87fb4350228a1", "support" ], "streams/readable-byte-streams/general.dedicatedworker.html": [ @@ -369944,11 +369938,11 @@ "testharness" ], "streams/readable-byte-streams/general.js": [ - "a7262a490c4a913811c8d0c489b06a567a448fc6", + "ce3c72f3a552a6b9a42b4f37be7e6a053cad10a1", "support" ], "streams/readable-byte-streams/general.serviceworker.https-expected.txt": [ - "838c17c8c3a41156cf7cc48fed92cb9a6bc22046", + "4533c8b2f6c2af140f39328017d66728966730ab", "support" ], "streams/readable-byte-streams/general.serviceworker.https.html": [ @@ -369956,7 +369950,7 @@ "testharness" ], "streams/readable-byte-streams/general.sharedworker-expected.txt": [ - "b3e8e0de49f3f6b9fc0cc5dd7b6e5a53bbba291b", + "ee74445ee891ea959b53a27ac3a87fb4350228a1", "support" ], "streams/readable-byte-streams/general.sharedworker.html": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general-expected.txt index 3d6778f6..3644dc00 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 76 tests; 2 PASS, 74 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 77 tests; 2 PASS, 75 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS getReader({mode: "byob"}) throws on non-bytes streams FAIL ReadableStream with byte source can be constructed with no errors bytes type is not yet implemented FAIL getReader({mode}) must perform ToString() bytes type is not yet implemented @@ -32,6 +32,7 @@ FAIL ReadableStream with byte source: enqueue(), close(), getReader(), then read() bytes type is not yet implemented FAIL ReadableStream with byte source: Respond to pull() by enqueue() bytes type is not yet implemented FAIL ReadableStream with byte source: Respond to pull() by enqueue() asynchronously bytes type is not yet implemented +FAIL ReadableStream with byte source: Respond to multiple pull() by separate enqueue() bytes type is not yet implemented FAIL ReadableStream with byte source: read(view), then respond() bytes type is not yet implemented FAIL ReadableStream with byte source: read(view), then respond() with a transferred ArrayBuffer bytes type is not yet implemented FAIL ReadableStream with byte source: read(view), then respond() with too big value bytes type is not yet implemented
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.dedicatedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.dedicatedworker-expected.txt index 3d6778f6..3644dc00 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.dedicatedworker-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.dedicatedworker-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 76 tests; 2 PASS, 74 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 77 tests; 2 PASS, 75 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS getReader({mode: "byob"}) throws on non-bytes streams FAIL ReadableStream with byte source can be constructed with no errors bytes type is not yet implemented FAIL getReader({mode}) must perform ToString() bytes type is not yet implemented @@ -32,6 +32,7 @@ FAIL ReadableStream with byte source: enqueue(), close(), getReader(), then read() bytes type is not yet implemented FAIL ReadableStream with byte source: Respond to pull() by enqueue() bytes type is not yet implemented FAIL ReadableStream with byte source: Respond to pull() by enqueue() asynchronously bytes type is not yet implemented +FAIL ReadableStream with byte source: Respond to multiple pull() by separate enqueue() bytes type is not yet implemented FAIL ReadableStream with byte source: read(view), then respond() bytes type is not yet implemented FAIL ReadableStream with byte source: read(view), then respond() with a transferred ArrayBuffer bytes type is not yet implemented FAIL ReadableStream with byte source: read(view), then respond() with too big value bytes type is not yet implemented
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.js b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.js index 4207277d..39dd708 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.js +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.js
@@ -300,22 +300,28 @@ promise_test(() => { let pullCount = 0; let controller; - let byobRequest; - let viewDefined = false; - let viewInfo; + const byobRequests = []; const stream = new ReadableStream({ start(c) { controller = c; }, pull() { - byobRequest = controller.byobRequest; + const byobRequest = controller.byobRequest; const view = byobRequest.view; - viewDefined = view !== undefined; - viewInfo = extractViewInfo(view); - - view[0] = 0x01; - byobRequest.respond(1); + byobRequests[pullCount] = { + defined: byobRequest !== undefined, + viewDefined: view !== undefined, + viewInfo: extractViewInfo(view) + }; + if (pullCount === 0) { + view[0] = 0x01; + byobRequest.respond(1); + } else if (pullCount === 1) { + view[0] = 0x02; + view[1] = 0x03; + byobRequest.respond(2); + } ++pullCount; }, @@ -326,28 +332,52 @@ }); const reader = stream.getReader(); - const readPromise = reader.read(); - const ignoredReadPromise = reader.read(); + const p0 = reader.read(); + const p1 = reader.read(); assert_equals(pullCount, 0, 'No pull() as start() just finished and is not yet reflected to the state of the stream'); return Promise.resolve().then(() => { assert_equals(pullCount, 1, 'pull() must have been invoked once'); - assert_not_equals(byobRequest, undefined, 'byobRequest must not be undefined'); - assert_true(viewDefined, 'byobRequest.view must not be undefined'); - assert_equals(viewInfo.constructor, Uint8Array, 'view.constructor should be Uint8Array'); - assert_equals(viewInfo.bufferByteLength, 16, 'view.buffer.byteLength should be 16'); - assert_equals(viewInfo.byteOffset, 0, 'view.byteOffset should be 0'); - assert_equals(viewInfo.byteLength, 16, 'view.byteLength should be 16'); - return readPromise; + const byobRequest = byobRequests[0]; + assert_true(byobRequest.defined, 'first byobRequest must not be undefined'); + assert_true(byobRequest.viewDefined, 'first byobRequest.view must not be undefined'); + const viewInfo = byobRequest.viewInfo; + assert_equals(viewInfo.constructor, Uint8Array, 'first view.constructor should be Uint8Array'); + assert_equals(viewInfo.bufferByteLength, 16, 'first view.buffer.byteLength should be 16'); + assert_equals(viewInfo.byteOffset, 0, 'first view.byteOffset should be 0'); + assert_equals(viewInfo.byteLength, 16, 'first view.byteLength should be 16'); + + return p0; }).then(result => { - assert_not_equals(result.value, undefined); - assert_equals(result.value.constructor, Uint8Array); - assert_equals(result.value.buffer.byteLength, 16); - assert_equals(result.value.byteOffset, 0); - assert_equals(result.value.byteLength, 1); - assert_equals(result.value[0], 0x01); - assert_equals(pullCount, 1, 'pull() should only be invoked once'); + assert_equals(pullCount, 2, 'pull() must have been invoked twice'); + const value = result.value; + assert_not_equals(value, undefined, 'first read should have a value'); + assert_equals(value.constructor, Uint8Array, 'first value should be a Uint8Array'); + assert_equals(value.buffer.byteLength, 16, 'first value.buffer.byteLength should be 16'); + assert_equals(value.byteOffset, 0, 'first value.byteOffset should be 0'); + assert_equals(value.byteLength, 1, 'first value.byteLength should be 1'); + assert_equals(value[0], 0x01, 'first value[0] should be 0x01'); + const byobRequest = byobRequests[1]; + assert_true(byobRequest.defined, 'second byobRequest must not be undefined'); + assert_true(byobRequest.viewDefined, 'second byobRequest.view must not be undefined'); + const viewInfo = byobRequest.viewInfo; + assert_equals(viewInfo.constructor, Uint8Array, 'second view.constructor should be Uint8Array'); + assert_equals(viewInfo.bufferByteLength, 16, 'second view.buffer.byteLength should be 16'); + assert_equals(viewInfo.byteOffset, 0, 'second view.byteOffset should be 0'); + assert_equals(viewInfo.byteLength, 16, 'second view.byteLength should be 16'); + + return p1; + }).then(result => { + assert_equals(pullCount, 2, 'pull() should only be invoked twice'); + const value = result.value; + assert_not_equals(value, undefined, 'second read should have a value'); + assert_equals(value.constructor, Uint8Array, 'second value should be a Uint8Array'); + assert_equals(value.buffer.byteLength, 16, 'second value.buffer.byteLength should be 16'); + assert_equals(value.byteOffset, 0, 'second value.byteOffset should be 0'); + assert_equals(value.byteLength, 2, 'second value.byteLength should be 2'); + assert_equals(value[0], 0x02, 'second value[0] should be 0x02'); + assert_equals(value[1], 0x03, 'second value[1] should be 0x03'); }); }, 'ReadableStream with byte source: autoAllocateChunkSize'); @@ -387,12 +417,13 @@ const reader = stream.getReader(); return reader.read().then(result => { - assert_not_equals(result.value, undefined); - assert_equals(result.value.constructor, Uint8Array); - assert_equals(result.value.buffer.byteLength, 16); - assert_equals(result.value.byteOffset, 0); - assert_equals(result.value.byteLength, 1); - assert_equals(result.value[0], 0x01); + const value = result.value; + assert_not_equals(value, undefined, 'first read should have a value'); + assert_equals(value.constructor, Uint8Array, 'first value should be a Uint8Array'); + assert_equals(value.buffer.byteLength, 16, 'first value.buffer.byteLength should be 16'); + assert_equals(value.byteOffset, 0, 'first value.byteOffset should be 0'); + assert_equals(value.byteLength, 1, 'first value.byteLength should be 1'); + assert_equals(value[0], 0x01, 'first value[0] should be 0x01'); const byobRequest = byobRequests[0]; assert_true(byobRequest.defined, 'first byobRequest must not be undefined'); assert_true(byobRequest.viewDefined, 'first byobRequest.view must not be undefined'); @@ -406,13 +437,14 @@ const byobReader = stream.getReader({ mode: 'byob' }); return byobReader.read(new Uint8Array(32)); }).then(result => { - assert_not_equals(result.value, undefined); - assert_equals(result.value.constructor, Uint8Array); - assert_equals(result.value.buffer.byteLength, 32); - assert_equals(result.value.byteOffset, 0); - assert_equals(result.value.byteLength, 2); - assert_equals(result.value[0], 0x02); - assert_equals(result.value[1], 0x03); + const value = result.value; + assert_not_equals(value, undefined, 'second read should have a value'); + assert_equals(value.constructor, Uint8Array, 'second value should be a Uint8Array'); + assert_equals(value.buffer.byteLength, 32, 'second value.buffer.byteLength should be 32'); + assert_equals(value.byteOffset, 0, 'second value.byteOffset should be 0'); + assert_equals(value.byteLength, 2, 'second value.byteLength should be 2'); + assert_equals(value[0], 0x02, 'second value[0] should be 0x02'); + assert_equals(value[1], 0x03, 'second value[1] should be 0x03'); const byobRequest = byobRequests[1]; assert_true(byobRequest.defined, 'second byobRequest must not be undefined'); assert_true(byobRequest.viewDefined, 'second byobRequest.view must not be undefined'); @@ -693,7 +725,7 @@ }, type: 'bytes' }, { - highWaterMark: 256 + highWaterMark: 0 }); const reader = stream.getReader(); @@ -717,14 +749,63 @@ assert_equals(result[2].done, false, 'result[2].done'); assert_equals(result[2].value.byteLength, 1, 'result[2].value.byteLength'); assert_equals(byobRequest, undefined, 'byobRequest should be undefined'); - assert_equals(desiredSizes[0], 256, 'desiredSize on pull should be 256'); - assert_equals(desiredSizes[1], 256, 'desiredSize after 1st enqueue() should be 256'); - assert_equals(desiredSizes[2], 256, 'desiredSize after 2nd enqueue() should be 256'); + assert_equals(desiredSizes[0], 0, 'desiredSize on pull should be 0'); + assert_equals(desiredSizes[1], 0, 'desiredSize after 1st enqueue() should be 0'); + assert_equals(desiredSizes[2], 0, 'desiredSize after 2nd enqueue() should be 0'); assert_equals(pullCount, 1, 'pull() should only be called once'); }); }, 'ReadableStream with byte source: Respond to pull() by enqueue() asynchronously'); promise_test(() => { + let pullCount = 0; + + let byobRequest; + const desiredSizes = []; + + const stream = new ReadableStream({ + pull(c) { + byobRequest = c.byobRequest; + desiredSizes.push(c.desiredSize); + + if (pullCount < 3) { + c.enqueue(new Uint8Array(1)); + } else { + c.close(); + } + + ++pullCount; + }, + type: 'bytes' + }, { + highWaterMark: 256 + }); + + const reader = stream.getReader(); + + const p0 = reader.read(); + const p1 = reader.read(); + const p2 = reader.read(); + + assert_equals(pullCount, 0, 'No pull as start() just finished and is not yet reflected to the state of the stream'); + + return Promise.all([p0, p1, p2]).then(result => { + assert_equals(pullCount, 4, 'pullCount after completion of all read()s'); + + assert_equals(result[0].done, false, 'result[0].done'); + assert_equals(result[0].value.byteLength, 1, 'result[0].value.byteLength'); + assert_equals(result[1].done, false, 'result[1].done'); + assert_equals(result[1].value.byteLength, 1, 'result[1].value.byteLength'); + assert_equals(result[2].done, false, 'result[2].done'); + assert_equals(result[2].value.byteLength, 1, 'result[2].value.byteLength'); + assert_equals(byobRequest, undefined, 'byobRequest should be undefined'); + assert_equals(desiredSizes[0], 256, 'desiredSize on pull should be 256'); + assert_equals(desiredSizes[1], 256, 'desiredSize after 1st enqueue() should be 256'); + assert_equals(desiredSizes[2], 256, 'desiredSize after 2nd enqueue() should be 256'); + assert_equals(desiredSizes[3], 256, 'desiredSize after 3rd enqueue() should be 256'); + }); +}, 'ReadableStream with byte source: Respond to multiple pull() by separate enqueue()'); + +promise_test(() => { let controller; let pullCount = 0;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.serviceworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.serviceworker.https-expected.txt index bce9964..de4f914 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.serviceworker.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.serviceworker.https-expected.txt
@@ -32,6 +32,7 @@ FAIL ReadableStream with byte source: enqueue(), close(), getReader(), then read() bytes type is not yet implemented FAIL ReadableStream with byte source: Respond to pull() by enqueue() bytes type is not yet implemented FAIL ReadableStream with byte source: Respond to pull() by enqueue() asynchronously bytes type is not yet implemented +FAIL ReadableStream with byte source: Respond to multiple pull() by separate enqueue() bytes type is not yet implemented FAIL ReadableStream with byte source: read(view), then respond() bytes type is not yet implemented FAIL ReadableStream with byte source: read(view), then respond() with a transferred ArrayBuffer bytes type is not yet implemented FAIL ReadableStream with byte source: read(view), then respond() with too big value bytes type is not yet implemented
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.sharedworker-expected.txt index 3d6778f6..3644dc00 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.sharedworker-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.sharedworker-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 76 tests; 2 PASS, 74 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 77 tests; 2 PASS, 75 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS getReader({mode: "byob"}) throws on non-bytes streams FAIL ReadableStream with byte source can be constructed with no errors bytes type is not yet implemented FAIL getReader({mode}) must perform ToString() bytes type is not yet implemented @@ -32,6 +32,7 @@ FAIL ReadableStream with byte source: enqueue(), close(), getReader(), then read() bytes type is not yet implemented FAIL ReadableStream with byte source: Respond to pull() by enqueue() bytes type is not yet implemented FAIL ReadableStream with byte source: Respond to pull() by enqueue() asynchronously bytes type is not yet implemented +FAIL ReadableStream with byte source: Respond to multiple pull() by separate enqueue() bytes type is not yet implemented FAIL ReadableStream with byte source: read(view), then respond() bytes type is not yet implemented FAIL ReadableStream with byte source: read(view), then respond() with a transferred ArrayBuffer bytes type is not yet implemented FAIL ReadableStream with byte source: read(view), then respond() with too big value bytes type is not yet implemented
diff --git a/third_party/WebKit/LayoutTests/fast/backgrounds/svg-as-mask-expected.png b/third_party/WebKit/LayoutTests/fast/backgrounds/svg-as-mask-expected.png index a766be8..e991e62 100644 --- a/third_party/WebKit/LayoutTests/fast/backgrounds/svg-as-mask-expected.png +++ b/third_party/WebKit/LayoutTests/fast/backgrounds/svg-as-mask-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/svg/js-update-bounce-expected.png b/third_party/WebKit/LayoutTests/paint/invalidation/svg/js-update-bounce-expected.png index c7b22bf..a5cb355d 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/svg/js-update-bounce-expected.png +++ b/third_party/WebKit/LayoutTests/paint/invalidation/svg/js-update-bounce-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed-expected.png index cf07b3d6..103a4fc 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed2-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed2-expected.png index a1d97b3..d1bf01c6 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed2-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed2-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/reflection-in-composited-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/reflection-in-composited-expected.png index d8c2374..c349cfe3 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/reflection-in-composited-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/reflection-in-composited-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/inline-mask-overlay-image-outset-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/inline-mask-overlay-image-outset-expected.png index b0c4012..a83ce6b 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/inline-mask-overlay-image-outset-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/inline-mask-overlay-image-outset-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/transformed-mask-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css/transformed-mask-expected.png index d0519af..8c0517e2 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/css/transformed-mask-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/transformed-mask-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/reflections/opacity-reflection-transform-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/reflections/opacity-reflection-transform-expected.png index 3befae5..dd62f6d1 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/reflections/opacity-reflection-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/reflections/opacity-reflection-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-filter-all-expected.png index 2149dbc..b01938c 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-filter-all-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-filter-all-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/reflection/reflection-with-rotation-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/reflection/reflection-with-rotation-expected.png index 3feb84c7..f3c6567 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/reflection/reflection-with-rotation-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/reflection/reflection-with-rotation-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/as-background-image/svg-as-background-6-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/as-background-image/svg-as-background-6-expected.png index 576dbcb..ff38505 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/as-background-image/svg-as-background-6-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/as-background-image/svg-as-background-6-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-modify-container-in-target-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-modify-container-in-target-expected.png index 2569653c..188918b 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-modify-container-in-target-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-modify-container-in-target-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-modify-target-container-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-modify-target-container-expected.png index a1f6443..16615c3 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-modify-target-container-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-modify-target-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-g-containing-use-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-g-containing-use-expected.png index 417b7b4e..a9c4a082 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-g-containing-use-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-g-containing-use-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-g-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-g-expected.png index 76adf282..6be19ce 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-g-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-g-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-use-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-use-expected.png index 76adf282..6be19ce 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-use-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-use-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png index 9bbb5f1..8e3e4de 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png index 5b7d327f..e773019a 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/complex-text-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/complex-text-opacity-expected.png index bba29e1a..ffd72f9 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/complex-text-opacity-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/complex-text-opacity-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png new file mode 100644 index 0000000..5d54f98 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png new file mode 100644 index 0000000..6a8b794 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/fast/text/complex-text-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/fast/text/complex-text-opacity-expected.png index 07c88577..4440daa 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/fast/text/complex-text-opacity-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/fast/text/complex-text-opacity-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/svg/as-background-image/svg-as-background-6-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/svg/as-background-image/svg-as-background-6-expected.png index 8b0dcc3..16c5c3d 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/svg/as-background-image/svg-as-background-6-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/svg/as-background-image/svg-as-background-6-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed-expected.png index 6cf33580..5050e02e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed2-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed2-expected.png index d1898f9..a344d8c9 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed2-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed2-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/reflection-in-composited-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/reflection-in-composited-expected.png index 42a29d4..09073d2 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/reflection-in-composited-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/reflection-in-composited-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png index e2e8177..5a12b1f28 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/reflections/opacity-reflection-transform-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/reflections/opacity-reflection-transform-expected.png index 20409607..1498516 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/reflections/opacity-reflection-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/reflections/opacity-reflection-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/complex-text-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/text/complex-text-opacity-expected.png index 68aa2191..c79519f 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/complex-text-opacity-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/text/complex-text-opacity-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-filter-all-expected.png index fd971118..1dcba1c 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-filter-all-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-filter-all-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/reflection/reflection-with-rotation-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/reflection/reflection-with-rotation-expected.png index 9278f54..0b3c73a 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/reflection/reflection-with-rotation-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/reflection/reflection-with-rotation-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/svg-as-background-6-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/svg-as-background-6-expected.png index ef23439..7244078 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/svg-as-background-6-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/svg-as-background-6-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textProperties-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textProperties-expected.png index 8d0edd65..21b0f8d9 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textProperties-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textProperties-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-modify-container-in-target-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-modify-container-in-target-expected.png index a9f03fd9..55857de 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-modify-container-in-target-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-modify-container-in-target-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-modify-target-container-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-modify-target-container-expected.png index 028c56e2..152b1fd 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-modify-target-container-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-modify-target-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-g-containing-use-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-g-containing-use-expected.png index 5ddb6d8..cde12bc 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-g-containing-use-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-g-containing-use-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-g-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-g-expected.png index 2f6f213..ff435a5 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-g-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-g-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-use-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-use-expected.png index 2f6f213..ff435a5 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-use-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-use-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png index 59298bf..0279054 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png index 6a8b794..5d54f98 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed-expected.png index 54d8a6c..3349df3 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed2-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed2-expected.png index a80877f..19c47c13 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed2-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed2-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/reflection-in-composited-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/reflection-in-composited-expected.png index 81930342..6f6ae4c 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/reflection-in-composited-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/reflection-in-composited-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/borders/inline-mask-overlay-image-outset-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/borders/inline-mask-overlay-image-outset-expected.png index edf945e..b70efdb4c 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/borders/inline-mask-overlay-image-outset-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/borders/inline-mask-overlay-image-outset-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png index 7b3ffcb..ffe69da 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/reflections/opacity-reflection-transform-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/reflections/opacity-reflection-transform-expected.png index a2cc665..298a6a55 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/reflections/opacity-reflection-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/reflections/opacity-reflection-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-filter-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-filter-expected.png index 9f0c22b..1006e4e8 100644 --- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-filter-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-filter-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-filter-all-expected.png index be25732..cc8f2a8 100644 --- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-filter-all-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-filter-all-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/reflection/reflection-with-rotation-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/reflection/reflection-with-rotation-expected.png index 101baa2..62c820c 100644 --- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/reflection/reflection-with-rotation-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/reflection/reflection-with-rotation-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/render-groups-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/render-groups-01-b-expected.png index 6d38a78..2d01404 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/render-groups-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/render-groups-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/as-background-image/svg-as-background-6-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/as-background-image/svg-as-background-6-expected.png index 0642bf1..b2c78b2 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/as-background-image/svg-as-background-6-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/as-background-image/svg-as-background-6-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-modify-container-in-target-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-modify-container-in-target-expected.png index 504798d..7de0059 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-modify-container-in-target-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-modify-container-in-target-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-modify-target-container-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-modify-target-container-expected.png index 453140f2..7ae902f 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-modify-target-container-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-modify-target-container-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-g-containing-use-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-g-containing-use-expected.png index 21bf084..79bf3b4 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-g-containing-use-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-g-containing-use-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-g-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-g-expected.png index 1d343ff..0a27b6c3 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-g-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-g-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-use-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-use-expected.png index 1d343ff..0a27b6c3 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-use-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-use-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-filter-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-filter-expected.png index b2718f1..1131e67 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-filter-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-filter-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png index 281ce1b..a66da2f 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-filter-all-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-filter-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-filter-expected.png index 6482a48..c7ce59f 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-filter-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-filter-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png index 68d2136..37ee211 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/custom/group-opacity-expected.png b/third_party/WebKit/LayoutTests/svg/custom/group-opacity-expected.png index 8a858024..98607db 100644 --- a/third_party/WebKit/LayoutTests/svg/custom/group-opacity-expected.png +++ b/third_party/WebKit/LayoutTests/svg/custom/group-opacity-expected.png Binary files differ
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8BindingForCore.cpp b/third_party/WebKit/Source/bindings/core/v8/V8BindingForCore.cpp index a139bcb..351c9d8d 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8BindingForCore.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8BindingForCore.cpp
@@ -740,6 +740,8 @@ v8::Local<v8::Context> ToV8ContextEvenIfDetached(LocalFrame* frame, DOMWrapperWorld& world) { + // TODO(yukishiino): this method probably should not force context creation, + // but it does through WindowProxy() call. DCHECK(frame); return frame->WindowProxy(world)->ContextIfInitialized(); }
diff --git a/third_party/WebKit/Source/core/animation/Animation.idl b/third_party/WebKit/Source/core/animation/Animation.idl index 87ed0c8..dbce735 100644 --- a/third_party/WebKit/Source/core/animation/Animation.idl +++ b/third_party/WebKit/Source/core/animation/Animation.idl
@@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// https://w3c.github.io/web-animations/#animation +// https://drafts.csswg.org/web-animations/#animation enum AnimationPlayState { "idle", "pending", "running", "paused", "finished" };
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.h b/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.h index 8690e3c..60085ef0e 100644 --- a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.h +++ b/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.h
@@ -59,7 +59,7 @@ } // Represents the content of an Animation and its fractional timing state. -// http://w3c.github.io/web-animations/#animation-effect +// http://drafts.csswg.org/web-animations/#animation-effect class CORE_EXPORT AnimationEffectReadOnly : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); // Calls Attach/Detach, GetAnimation, UpdateInheritedTime.
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.idl b/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.idl index 5f46ae56..7c4a980 100644 --- a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.idl +++ b/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.idl
@@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// https://w3c.github.io/web-animations/#the-animationeffectreadonly-interface +// https://drafts.csswg.org/web-animations/#the-animationeffectreadonly-interface [ RuntimeEnabled=WebAnimationsAPI
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectTiming.idl b/third_party/WebKit/Source/core/animation/AnimationEffectTiming.idl index 502da5e..13f3633f 100644 --- a/third_party/WebKit/Source/core/animation/AnimationEffectTiming.idl +++ b/third_party/WebKit/Source/core/animation/AnimationEffectTiming.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#the-animationeffecttiming-interface +// https://drafts.csswg.org/web-animations/#the-animationeffecttiming-interface [ RuntimeEnabled=WebAnimationsAPI
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectTimingProperties.idl b/third_party/WebKit/Source/core/animation/AnimationEffectTimingProperties.idl index 005894a..bd71345a 100644 --- a/third_party/WebKit/Source/core/animation/AnimationEffectTimingProperties.idl +++ b/third_party/WebKit/Source/core/animation/AnimationEffectTimingProperties.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#the-animationeffecttimingproperties-dictionary +// https://drafts.csswg.org/web-animations/#the-animationeffecttimingproperties-dictionary enum FillMode { "none", "forwards", "backwards", "both", "auto" }; enum PlaybackDirection { "normal", "reverse", "alternate", "alternate-reverse" };
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.idl b/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.idl index 294bb70..2c00b09e 100644 --- a/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.idl +++ b/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#the-animationeffecttimingreadonly-interface +// https://drafts.csswg.org/web-animations/#the-animationeffecttimingreadonly-interface // TODO(suzyh): Use enums instead of DOMStrings where specced [
diff --git a/third_party/WebKit/Source/core/animation/AnimationTimeline.idl b/third_party/WebKit/Source/core/animation/AnimationTimeline.idl index dd32f96f..4d4d6ea 100644 --- a/third_party/WebKit/Source/core/animation/AnimationTimeline.idl +++ b/third_party/WebKit/Source/core/animation/AnimationTimeline.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#the-animationtimeline-interface +// https://drafts.csswg.org/web-animations/#the-animationtimeline-interface [ RuntimeEnabled=WebAnimationsAPI
diff --git a/third_party/WebKit/Source/core/animation/ComputedTimingProperties.idl b/third_party/WebKit/Source/core/animation/ComputedTimingProperties.idl index 1719f70e..9334d74 100644 --- a/third_party/WebKit/Source/core/animation/ComputedTimingProperties.idl +++ b/third_party/WebKit/Source/core/animation/ComputedTimingProperties.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#the-computedtimingproperties-dictionary +// https://drafts.csswg.org/web-animations/#the-computedtimingproperties-dictionary dictionary ComputedTimingProperties : AnimationEffectTimingProperties { unrestricted double endTime;
diff --git a/third_party/WebKit/Source/core/animation/DocumentAnimation.idl b/third_party/WebKit/Source/core/animation/DocumentAnimation.idl index 1ccdcc8..abefa7f 100644 --- a/third_party/WebKit/Source/core/animation/DocumentAnimation.idl +++ b/third_party/WebKit/Source/core/animation/DocumentAnimation.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#extensions-to-the-document-interface +// https://drafts.csswg.org/web-animations/#extensions-to-the-document-interface [ ImplementedAs=DocumentAnimation,
diff --git a/third_party/WebKit/Source/core/animation/DocumentTimeline.idl b/third_party/WebKit/Source/core/animation/DocumentTimeline.idl index 54f9faa3..8a5aed4 100644 --- a/third_party/WebKit/Source/core/animation/DocumentTimeline.idl +++ b/third_party/WebKit/Source/core/animation/DocumentTimeline.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#the-documenttimeline-interface +// https://drafts.csswg.org/web-animations/#the-documenttimeline-interface [ Constructor(optional DocumentTimelineOptions options),
diff --git a/third_party/WebKit/Source/core/animation/DocumentTimelineOptions.idl b/third_party/WebKit/Source/core/animation/DocumentTimelineOptions.idl index 6730f6e..d3ea63bc 100644 --- a/third_party/WebKit/Source/core/animation/DocumentTimelineOptions.idl +++ b/third_party/WebKit/Source/core/animation/DocumentTimelineOptions.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#dictdef-documenttimelineoptions +// https://drafts.csswg.org/web-animations/#dictdef-documenttimelineoptions dictionary DocumentTimelineOptions { DOMHighResTimeStamp originTime = 0;
diff --git a/third_party/WebKit/Source/core/animation/ElementAnimation.idl b/third_party/WebKit/Source/core/animation/ElementAnimation.idl index a029c1e..3e56e3d 100644 --- a/third_party/WebKit/Source/core/animation/ElementAnimation.idl +++ b/third_party/WebKit/Source/core/animation/ElementAnimation.idl
@@ -28,8 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// https://w3c.github.io/web-animations/#the-animatable-interface -// https://w3c.github.io/web-animations/#extensions-to-the-element-interface +// https://drafts.csswg.org/web-animations/#the-animatable-interface +// https://drafts.csswg.org/web-animations/#extensions-to-the-element-interface // TODO(dstockwell): This should be an Animatable interface, where Element // implements Animatable.
diff --git a/third_party/WebKit/Source/core/animation/Keyframe.h b/third_party/WebKit/Source/core/animation/Keyframe.h index 0d0211f..7c2192e0 100644 --- a/third_party/WebKit/Source/core/animation/Keyframe.h +++ b/third_party/WebKit/Source/core/animation/Keyframe.h
@@ -40,7 +40,7 @@ // an underlying value. If this is null, the keyframe effect composite // operation is used instead. // -// For spec details, refer to: http://w3c.github.io/web-animations/#keyframe +// For spec details, refer to: https://drafts.csswg.org/web-animations/#keyframe // // Implementation-wise the base Keyframe class captures the offset, composite // operation, and timing function. It is left to subclasses to define and store
diff --git a/third_party/WebKit/Source/core/animation/KeyframeAnimationOptions.idl b/third_party/WebKit/Source/core/animation/KeyframeAnimationOptions.idl index d83463e..1a62ca1 100644 --- a/third_party/WebKit/Source/core/animation/KeyframeAnimationOptions.idl +++ b/third_party/WebKit/Source/core/animation/KeyframeAnimationOptions.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#dictdef-keyframeanimationoptions +// https://drafts.csswg.org/web-animations/#dictdef-keyframeanimationoptions dictionary KeyframeAnimationOptions : KeyframeEffectOptions { DOMString id = "";
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffect.h b/third_party/WebKit/Source/core/animation/KeyframeEffect.h index cf9966f7..175b034 100644 --- a/third_party/WebKit/Source/core/animation/KeyframeEffect.h +++ b/third_party/WebKit/Source/core/animation/KeyframeEffect.h
@@ -43,7 +43,7 @@ class UnrestrictedDoubleOrKeyframeEffectOptions; // Represents the effect of an Animation on an Element's properties. -// http://w3c.github.io/web-animations/#keyframe-effect +// https://drafts.csswg.org/web-animations/#keyframe-effect class CORE_EXPORT KeyframeEffect final : public KeyframeEffectReadOnly { DEFINE_WRAPPERTYPEINFO();
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffect.idl b/third_party/WebKit/Source/core/animation/KeyframeEffect.idl index ee6b903..4d8aab90 100644 --- a/third_party/WebKit/Source/core/animation/KeyframeEffect.idl +++ b/third_party/WebKit/Source/core/animation/KeyframeEffect.idl
@@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// https://w3c.github.io/web-animations/#the-keyframeeffect-interfaces +// https://drafts.csswg.org/web-animations/#the-keyframeeffect-interfaces [ Constructor(Element? target, object? keyframes, optional (unrestricted double or KeyframeEffectOptions) options),
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectOptions.idl b/third_party/WebKit/Source/core/animation/KeyframeEffectOptions.idl index 0cb3f64..1fdcc6c 100644 --- a/third_party/WebKit/Source/core/animation/KeyframeEffectOptions.idl +++ b/third_party/WebKit/Source/core/animation/KeyframeEffectOptions.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#the-keyframeeffectoptions-dictionary +// https://drafts.csswg.org/web-animations/#the-keyframeeffectoptions-dictionary dictionary KeyframeEffectOptions : AnimationEffectTimingProperties { // TODO(alancutter): Implement iterationComposite
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.cpp b/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.cpp index 190a1f8..c731c83db 100644 --- a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.cpp +++ b/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.cpp
@@ -345,7 +345,7 @@ // consists of the normal keyframe data combined with the computed offset for // the given keyframe. // - // https://w3c.github.io/web-animations/#dom-keyframeeffectreadonly-getkeyframes + // https://drafts.csswg.org/web-animations/#dom-keyframeeffectreadonly-getkeyframes const KeyframeVector& keyframes = model_->GetFrames(); Vector<double> computed_offsets = KeyframeEffectModelBase::GetComputedOffsets(keyframes);
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.h b/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.h index 9c1dfd37..b7de7289 100644 --- a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.h +++ b/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.h
@@ -21,7 +21,7 @@ class UnrestrictedDoubleOrKeyframeEffectOptions; // Represents the effect of an Animation on an Element's properties. -// http://w3c.github.io/web-animations/#the-keyframeeffect-interfaces +// https://drafts.csswg.org/web-animations/#the-keyframeeffect-interfaces class CORE_EXPORT KeyframeEffectReadOnly : public AnimationEffectReadOnly { DEFINE_WRAPPERTYPEINFO();
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.idl b/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.idl index 72fc2ed..1f3d7c3 100644 --- a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.idl +++ b/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#the-keyframeeffect-interfaces +// https://drafts.csswg.org/web-animations/#the-keyframeeffect-interfaces enum CompositeOperation { "replace", "add", "accumulate" };
diff --git a/third_party/WebKit/Source/core/animation/TimingCalculations.h b/third_party/WebKit/Source/core/animation/TimingCalculations.h index 874c2db..2212692 100644 --- a/third_party/WebKit/Source/core/animation/TimingCalculations.h +++ b/third_party/WebKit/Source/core/animation/TimingCalculations.h
@@ -175,7 +175,7 @@ double iteration_time = fmod(scaled_active_time, iteration_duration); // This implements step 3 of - // http://w3c.github.io/web-animations/#calculating-the-simple-iteration-progress + // https://drafts.csswg.org/web-animations/#calculating-the-simple-iteration-progress if (iteration_time == 0 && phase == AnimationEffectReadOnly::kPhaseAfter && repeated_duration != 0 && scaled_active_time != 0) return iteration_duration;
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp index 2a79ae6..af084f2 100644 --- a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp +++ b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
@@ -1228,7 +1228,7 @@ } // Properties that affect animations are not allowed to be affected by -// animations. http://w3c.github.io/web-animations/#not-animatable-section +// animations. https://drafts.csswg.org/web-animations/#not-animatable-section bool CSSAnimations::IsAnimationAffectingProperty(const CSSProperty& property) { switch (property.PropertyID()) { case CSSPropertyAnimation:
diff --git a/third_party/WebKit/Source/core/events/AnimationPlaybackEvent.idl b/third_party/WebKit/Source/core/events/AnimationPlaybackEvent.idl index 7558260..b26c27d 100644 --- a/third_party/WebKit/Source/core/events/AnimationPlaybackEvent.idl +++ b/third_party/WebKit/Source/core/events/AnimationPlaybackEvent.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#the-animationplaybackevent-interface +// https://drafts.csswg.org/web-animations/#the-animationplaybackevent-interface [ Constructor(DOMString type, optional AnimationPlaybackEventInit eventInitDict),
diff --git a/third_party/WebKit/Source/core/events/AnimationPlaybackEventInit.idl b/third_party/WebKit/Source/core/events/AnimationPlaybackEventInit.idl index c8c82b1..bce162f 100644 --- a/third_party/WebKit/Source/core/events/AnimationPlaybackEventInit.idl +++ b/third_party/WebKit/Source/core/events/AnimationPlaybackEventInit.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/web-animations/#the-animationplaybackevent-interface +// https://drafts.csswg.org/web-animations/#the-animationplaybackevent-interface dictionary AnimationPlaybackEventInit : EventInit { double? currentTime = null;
diff --git a/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.cpp b/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.cpp index be4454f..68fd3aa 100644 --- a/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.cpp
@@ -200,12 +200,8 @@ DocumentLoader::SetUserActivated(); } -void WebDocumentLoaderImpl::SetIsAdSubframe(bool is_ad_subframe) { - GetSubresourceFilter()->SetIsAdSubframe(is_ad_subframe); -} - bool WebDocumentLoaderImpl::GetIsAdSubframe() const { - return GetSubresourceFilter()->GetIsAdSubframe(); + return GetSubresourceFilter()->GetIsAssociatedWithAdSubframe(); } void WebDocumentLoaderImpl::Trace(blink::Visitor* visitor) {
diff --git a/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.h b/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.h index a2a2abc..ca60add 100644 --- a/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.h +++ b/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.h
@@ -85,7 +85,6 @@ void SetSourceLocation(const WebSourceLocation&) override; void ResetSourceLocation() override; void SetUserActivated() override; - void SetIsAdSubframe(bool is_ad_subframe) override; bool GetIsAdSubframe() const override; static WebNavigationType ToWebNavigationType(NavigationType);
diff --git a/third_party/WebKit/Source/core/exported/WebDocumentSubresourceFilterTest.cpp b/third_party/WebKit/Source/core/exported/WebDocumentSubresourceFilterTest.cpp index db9ea7d..751519a 100644 --- a/third_party/WebKit/Source/core/exported/WebDocumentSubresourceFilterTest.cpp +++ b/third_party/WebKit/Source/core/exported/WebDocumentSubresourceFilterTest.cpp
@@ -53,6 +53,8 @@ return queried_subresource_paths_; } + bool GetIsAssociatedWithAdSubframe() const override { return false; } + private: std::vector<std::string> queried_subresource_paths_; bool allow_loads_;
diff --git a/third_party/WebKit/Source/core/exported/WebFrame.cpp b/third_party/WebKit/Source/core/exported/WebFrame.cpp index 17674e29..a641f8d0 100644 --- a/third_party/WebKit/Source/core/exported/WebFrame.cpp +++ b/third_party/WebKit/Source/core/exported/WebFrame.cpp
@@ -126,7 +126,7 @@ Frame* new_frame = ToCoreFrame(*frame); if (parent_ && old_frame->HasBeenActivated()) - new_frame->UpdateUserActivationInFrameTree(); + new_frame->NotifyUserActivationInLocalTree(); new_frame->GetWindowProxyManager()->SetGlobalProxies(global_proxies);
diff --git a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp index 31ccf93..4b0451f 100644 --- a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp +++ b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
@@ -12195,7 +12195,8 @@ // Simulate an input element focus leading to Element::focus() call with a // user gesture. - local_frame->SetHasReceivedUserGesture(); + Frame::NotifyUserActivation(local_frame->GetFrame(), + UserGestureToken::kNewGesture); local_frame->ExecuteScript( WebScriptSource("window.focus();" "document.querySelector('input').focus();"));
diff --git a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp index 6acc971..8bd852f 100644 --- a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp
@@ -331,7 +331,9 @@ } void WebRemoteFrameImpl::SetHasReceivedUserGesture() { - Frame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture); + RemoteFrame* frame = GetFrame(); + if (frame) + frame->NotifyUserActivationInLocalTree(); } void WebRemoteFrameImpl::ScrollRectToVisible(
diff --git a/third_party/WebKit/Source/core/exported/WebUserGestureIndicator.cpp b/third_party/WebKit/Source/core/exported/WebUserGestureIndicator.cpp index 60ef46b87..643a3c2e 100644 --- a/third_party/WebKit/Source/core/exported/WebUserGestureIndicator.cpp +++ b/third_party/WebKit/Source/core/exported/WebUserGestureIndicator.cpp
@@ -38,14 +38,14 @@ namespace blink { bool WebUserGestureIndicator::IsProcessingUserGesture(WebLocalFrame* frame) { - return Frame::HasTransientUserActivation(frame ? WebFrame::ToCoreFrame(*frame) - : nullptr); + return Frame::HasTransientUserActivation( + frame ? ToWebLocalFrameImpl(frame)->GetFrame() : nullptr); } bool WebUserGestureIndicator::IsProcessingUserGestureThreadSafe( WebLocalFrame* frame) { return Frame::HasTransientUserActivation( - frame ? WebFrame::ToCoreFrame(*frame) : nullptr, true); + frame ? ToWebLocalFrameImpl(frame)->GetFrame() : nullptr, true); } // TODO(csharrison): consumeUserGesture() and currentUserGestureToken() use @@ -53,13 +53,15 @@ // updating them if they are in any sort of critical path or called often. bool WebUserGestureIndicator::ConsumeUserGesture(WebLocalFrame* frame) { return Frame::ConsumeTransientUserActivation( - frame ? WebFrame::ToCoreFrame(*frame) : nullptr, true); + frame ? ToWebLocalFrameImpl(frame)->GetFrame() : nullptr, true); + + ; } bool WebUserGestureIndicator::ProcessedUserGestureSinceLoad( WebLocalFrame* frame) { DCHECK(frame); - return WebFrame::ToCoreFrame(*frame)->HasBeenActivated(); + return ToWebLocalFrameImpl(frame)->GetFrame()->HasBeenActivated(); } WebUserGestureToken WebUserGestureIndicator::CurrentUserGestureToken() {
diff --git a/third_party/WebKit/Source/core/frame/Frame.cpp b/third_party/WebKit/Source/core/frame/Frame.cpp index 7eac0e9f..24b49cc 100644 --- a/third_party/WebKit/Source/core/frame/Frame.cpp +++ b/third_party/WebKit/Source/core/frame/Frame.cpp
@@ -172,21 +172,21 @@ child_frames[i]->DidChangeVisibilityState(); } -// TODO(mustaq): Should be merged with NotifyUserActivation() below but -// not sure why this one doesn't update frame clients. Could be related to -// crbug.com/775930 . -void Frame::UpdateUserActivationInFrameTree() { +void Frame::NotifyUserActivationInLocalTree() { user_activation_state_.Activate(); - if (Frame* parent = Tree().Parent()) - parent->UpdateUserActivationInFrameTree(); + for (Frame* parent = Tree().Parent(); parent; + parent = parent->Tree().Parent()) { + parent->user_activation_state_.Activate(); + } } void Frame::NotifyUserActivation() { bool had_gesture = HasBeenActivated(); if (RuntimeEnabledFeatures::UserActivationV2Enabled() || !had_gesture) - UpdateUserActivationInFrameTree(); - if (IsLocalFrame()) - ToLocalFrame(this)->Client()->SetHasReceivedUserGesture(had_gesture); + NotifyUserActivationInLocalTree(); + + DCHECK(IsLocalFrame()); + ToLocalFrame(this)->Client()->SetHasReceivedUserGesture(had_gesture); } bool Frame::ConsumeTransientUserActivation() { @@ -203,7 +203,7 @@ // static std::unique_ptr<UserGestureIndicator> Frame::NotifyUserActivation( - Frame* frame, + LocalFrame* frame, UserGestureToken::Status status) { if (frame) frame->NotifyUserActivation(); @@ -211,7 +211,8 @@ } // static -bool Frame::HasTransientUserActivation(Frame* frame, bool checkIfMainThread) { +bool Frame::HasTransientUserActivation(LocalFrame* frame, + bool checkIfMainThread) { if (RuntimeEnabledFeatures::UserActivationV2Enabled()) { return frame ? frame->HasTransientUserActivation() : false; } @@ -222,7 +223,7 @@ } // static -bool Frame::ConsumeTransientUserActivation(Frame* frame, +bool Frame::ConsumeTransientUserActivation(LocalFrame* frame, bool checkIfMainThread) { if (RuntimeEnabledFeatures::UserActivationV2Enabled()) { return frame ? frame->ConsumeTransientUserActivation() : false;
diff --git a/third_party/WebKit/Source/core/frame/Frame.h b/third_party/WebKit/Source/core/frame/Frame.h index 2219f4fb..b0bfe04fc5 100644 --- a/third_party/WebKit/Source/core/frame/Frame.h +++ b/third_party/WebKit/Source/core/frame/Frame.h
@@ -140,7 +140,8 @@ virtual void DidChangeVisibilityState(); - void UpdateUserActivationInFrameTree(); + // This should never be called from outside Frame or WebFrame. + void NotifyUserActivationInLocalTree(); bool HasBeenActivated() const { return user_activation_state_.HasBeenActive(); @@ -159,8 +160,10 @@ // Creates a |UserGestureIndicator| that contains a |UserGestureToken| with // the given status. Also activates the user activation state of the // |LocalFrame| (provided it's non-null) and all its ancestors. + // + // TODO(mustaq): Move the user activation entry-points to LocalFrame. static std::unique_ptr<UserGestureIndicator> NotifyUserActivation( - Frame*, + LocalFrame*, UserGestureToken::Status = UserGestureToken::kPossiblyExistingGesture); // Returns the transient user activation state of the |LocalFrame|, provided @@ -171,7 +174,7 @@ // // TODO(mustaq): clarify/enforce the relation between the two params after // null-frame main-thread cases (crbug.com/730690) have been removed. - static bool HasTransientUserActivation(Frame*, + static bool HasTransientUserActivation(LocalFrame*, bool checkIfMainThread = false); // Consumes the transient user activation state of the |LocalFrame|, provided @@ -180,7 +183,7 @@ // // The |checkIfMainThread| parameter determines if the token based gestures // (legacy code) must be used in a thread-safe manner. - static bool ConsumeTransientUserActivation(Frame*, + static bool ConsumeTransientUserActivation(LocalFrame*, bool checkIfMainThread = false); bool IsAttached() const { @@ -211,7 +214,11 @@ Member<FrameOwner> owner_; Member<DOMWindow> dom_window_; + // A LocalFrame is the primary "owner" of the activation state. The state in + // a RemoteFrame serves as a cache for the corresponding LocalFrame state (to + // avoid double hops through the browser during reading). UserActivationState user_activation_state_; + bool has_received_user_gesture_before_nav_ = false; FrameLifecycle lifecycle_; @@ -223,6 +230,9 @@ private: // Activates the user activation state of this frame and all its ancestors. + // + // TODO(mustaq): Move the user activation (private) entry-points to + // LocalFrame. void NotifyUserActivation(); bool HasTransientUserActivation() {
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp index 9b33674..6ccc799 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -2222,7 +2222,7 @@ GetFrame()->DidSendResourceTimingInfoToParent(); } -void WebLocalFrameImpl::SetHasReceivedUserGesture() { +void WebLocalFrameImpl::NotifyUserActivation() { Frame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture); }
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h index d7d4c9f..fe164546 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h
@@ -285,7 +285,7 @@ bool IsLoading() const override; bool IsNavigationScheduledWithin(double interval) const override; void SetCommittedFirstRealLoad() override; - void SetHasReceivedUserGesture() override; + void NotifyUserActivation() override; void BlinkFeatureUsageReport(const std::set<int>& features) override; void MixedContentFound(const WebURL& main_resource_url, const WebURL& mixed_content_url,
diff --git a/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp b/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp index 595640d04..35f9ac7 100644 --- a/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp
@@ -392,8 +392,9 @@ static_cast<String>(FastGetAttribute(downloadAttr))); } request.SetRequestContext(WebURLRequest::kRequestContextHyperlink); - FrameLoadRequest frame_request(&GetDocument(), request, - getAttribute(targetAttr)); + FrameLoadRequest frame_request( + &GetDocument(), request, + hasAttribute(downloadAttr) ? g_null_atom : getAttribute(targetAttr)); frame_request.SetTriggeringEvent(event); if (HasRel(kRelationNoReferrer)) { frame_request.SetShouldSendReferrer(kNeverSendReferrer);
diff --git a/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp b/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp index ac90bd5..bc07cc9 100644 --- a/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp +++ b/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp
@@ -102,7 +102,10 @@ } LocalFrame* ConsoleMessage::Frame() const { - return frame_; + // Do not reference detached frames. + if (frame_ && frame_->Client()) + return frame_; + return nullptr; } Vector<DOMNodeId>& ConsoleMessage::Nodes() {
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGResourcesCycleSolver.cpp b/third_party/WebKit/Source/core/layout/svg/SVGResourcesCycleSolver.cpp index 7236c42..eda50207 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGResourcesCycleSolver.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGResourcesCycleSolver.cpp
@@ -33,15 +33,25 @@ SVGResourcesCycleSolver::~SVGResourcesCycleSolver() = default; -struct ActiveFrame { +class ScopedTraversalPath { + public: typedef SVGResourcesCycleSolver::ResourceSet ResourceSet; - ActiveFrame(ResourceSet& active_set, LayoutSVGResourceContainer* resource) - : active_set_(active_set), resource_(resource) { - active_set_.insert(resource_); + ScopedTraversalPath(ResourceSet& active_set) + : active_set_(active_set), resource_(nullptr) {} + ~ScopedTraversalPath() { + if (resource_) + active_set_.erase(resource_); } - ~ActiveFrame() { active_set_.erase(resource_); } + bool Enter(LayoutSVGResourceContainer* resource) { + if (!active_set_.insert(resource).is_new_entry) + return false; + resource_ = resource; + return true; + } + + private: ResourceSet& active_set_; LayoutSVGResourceContainer* resource_; }; @@ -53,11 +63,10 @@ if (dag_cache_.Contains(resource)) return false; - if (active_resources_.Contains(resource)) + ScopedTraversalPath scope(active_resources_); + if (!scope.Enter(resource)) return true; - ActiveFrame frame(active_resources_, resource); - LayoutObject* node = resource; while (node) { // Skip subtrees which are themselves resources. (They will be
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp index 181de90..d1286fef 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
@@ -101,8 +101,12 @@ class FixedPolicySubresourceFilter : public WebDocumentSubresourceFilter { public: - FixedPolicySubresourceFilter(LoadPolicy policy, int* filtered_load_counter) - : policy_(policy), filtered_load_counter_(filtered_load_counter) {} + FixedPolicySubresourceFilter(LoadPolicy policy, + int* filtered_load_counter, + bool is_associated_with_ad_subframe) + : policy_(policy), + filtered_load_counter_(filtered_load_counter), + is_associated_with_ad_subframe_(is_associated_with_ad_subframe) {} LoadPolicy GetLoadPolicy(const WebURL& resource_url, WebURLRequest::RequestContext) override { @@ -117,9 +121,14 @@ bool ShouldLogToConsole() override { return false; } + bool GetIsAssociatedWithAdSubframe() const override { + return is_associated_with_ad_subframe_; + } + private: const LoadPolicy policy_; int* filtered_load_counter_; + bool is_associated_with_ad_subframe_; }; class FrameFetchContextTest : public ::testing::Test { @@ -191,10 +200,12 @@ return filtered_load_callback_counter_; } - void SetFilterPolicy(WebDocumentSubresourceFilter::LoadPolicy policy) { + void SetFilterPolicy(WebDocumentSubresourceFilter::LoadPolicy policy, + bool is_associated_with_ad_subframe = false) { document->Loader()->SetSubresourceFilter(SubresourceFilter::Create( *document, std::make_unique<FixedPolicySubresourceFilter>( - policy, &filtered_load_callback_counter_))); + policy, &filtered_load_callback_counter_, + is_associated_with_ad_subframe))); } ResourceRequestBlockedReason CanRequest() { @@ -1255,8 +1266,8 @@ // is fetched from a frame that is tagged as an ad, then the subresource should // be tagged as well. TEST_F(FrameFetchContextSubresourceFilterTest, AdTaggingBasedOnFrame) { - SetFilterPolicy(WebDocumentSubresourceFilter::kAllow); - document->Loader()->GetSubresourceFilter()->SetIsAdSubframe(true); + SetFilterPolicy(WebDocumentSubresourceFilter::kAllow, + true /* is_associated_with_ad_subframe */); EXPECT_EQ(ResourceRequestBlockedReason::kNone, CanRequestAndVerifyIsAd(true)); EXPECT_EQ(0, GetFilteredLoadCallCount());
diff --git a/third_party/WebKit/Source/core/loader/SubresourceFilter.cpp b/third_party/WebKit/Source/core/loader/SubresourceFilter.cpp index d66fd8f..0a5262d 100644 --- a/third_party/WebKit/Source/core/loader/SubresourceFilter.cpp +++ b/third_party/WebKit/Source/core/loader/SubresourceFilter.cpp
@@ -45,8 +45,7 @@ ExecutionContext* execution_context, std::unique_ptr<WebDocumentSubresourceFilter> subresource_filter) : execution_context_(execution_context), - subresource_filter_(std::move(subresource_filter)), - is_ad_subframe_(false) {} + subresource_filter_(std::move(subresource_filter)) {} SubresourceFilter::~SubresourceFilter() = default; @@ -88,6 +87,10 @@ return load_policy != WebDocumentSubresourceFilter::kDisallow; } +bool SubresourceFilter::GetIsAssociatedWithAdSubframe() { + return subresource_filter_->GetIsAssociatedWithAdSubframe(); +} + bool SubresourceFilter::IsAdResource( const KURL& resource_url, WebURLRequest::RequestContext request_context) { @@ -102,7 +105,8 @@ // If the subresource cannot be identified as an ad via load_policy, check if // its frame is identified as an ad. - return load_policy != WebDocumentSubresourceFilter::kAllow || is_ad_subframe_; + return load_policy != WebDocumentSubresourceFilter::kAllow || + subresource_filter_->GetIsAssociatedWithAdSubframe(); } void SubresourceFilter::ReportLoad(
diff --git a/third_party/WebKit/Source/core/loader/SubresourceFilter.h b/third_party/WebKit/Source/core/loader/SubresourceFilter.h index 9a14cb4..2bcbe67 100644 --- a/third_party/WebKit/Source/core/loader/SubresourceFilter.h +++ b/third_party/WebKit/Source/core/loader/SubresourceFilter.h
@@ -36,11 +36,7 @@ SecurityViolationReportingPolicy); bool AllowWebSocketConnection(const KURL&); - void SetIsAdSubframe(bool is_ad_subframe) { - is_ad_subframe_ = is_ad_subframe; - } - - bool GetIsAdSubframe() { return is_ad_subframe_; } + bool GetIsAssociatedWithAdSubframe(); // Returns if |resource_url| is an ad resource. bool IsAdResource(const KURL& resource_url, WebURLRequest::RequestContext); @@ -56,7 +52,6 @@ Member<ExecutionContext> execution_context_; std::unique_ptr<WebDocumentSubresourceFilter> subresource_filter_; - bool is_ad_subframe_; // Save the last resource check's result in the single element cache. std::pair<std::pair<KURL, WebURLRequest::RequestContext>,
diff --git a/third_party/WebKit/Source/core/page/ContextMenuController.cpp b/third_party/WebKit/Source/core/page/ContextMenuController.cpp index 0f4803e..f838bf5d 100644 --- a/third_party/WebKit/Source/core/page/ContextMenuController.cpp +++ b/third_party/WebKit/Source/core/page/ContextMenuController.cpp
@@ -344,6 +344,7 @@ } else if (IsHTMLAudioElement(*media_element)) data.media_type = WebContextMenuData::kMediaTypeAudio; + data.suggested_filename = media_element->title(); if (media_element->error()) data.media_flags |= WebContextMenuData::kMediaInError; if (media_element->paused())
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp index 632b2db6..b5ed32b7 100644 --- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp +++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
@@ -180,13 +180,32 @@ bool PrePaintTreeWalk::NeedsTreeBuilderContextUpdate( const LayoutObject& object, const PrePaintTreeWalkContext& parent_context) { - return object.NeedsPaintPropertyUpdate() || - object.DescendantNeedsPaintPropertyUpdate() || - (parent_context.tree_builder_context && - parent_context.tree_builder_context->force_subtree_update) || - // If the object needs visual rect update, we should update tree - // builder context which is needed by visual rect update. - parent_context.paint_invalidator_context.NeedsVisualRectUpdate(object); + if (parent_context.tree_builder_context && + parent_context.tree_builder_context->force_subtree_update) { + return true; + } + // The following CHECKs are for debugging crbug.com/816810. + if (object.NeedsPaintPropertyUpdate()) { + CHECK(parent_context.tree_builder_context) << "NeedsPaintPropertyUpdate"; + return true; + } + if (object.DescendantNeedsPaintPropertyUpdate()) { + CHECK(parent_context.tree_builder_context) + << "DescendantNeedsPaintPropertyUpdate"; + return true; + } + if (parent_context.paint_invalidator_context.NeedsVisualRectUpdate(object)) { + // If the object needs visual rect update, we should update tree + // builder context which is needed by visual rect update. + if (object.NeedsPaintOffsetAndVisualRectUpdate()) { + CHECK(parent_context.tree_builder_context) + << "NeedsPaintOffsetAndVisualRectUpdate"; + } else { + CHECK(parent_context.tree_builder_context) << "kSubtreeVisualRectUpdate"; + } + return true; + } + return false; } void PrePaintTreeWalk::WalkInternal(const LayoutObject& object,
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h index f34a27b..380a8ae 100644 --- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h +++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h
@@ -40,8 +40,7 @@ ancestor_overflow_paint_layer( parent_context.ancestor_overflow_paint_layer) { if (needs_tree_builder_context || DCHECK_IS_ON()) { - // Speculative CHECK to debug crbug.com/816810. - CHECK(parent_context.tree_builder_context); + DCHECK(parent_context.tree_builder_context); tree_builder_context.emplace(*parent_context.tree_builder_context); } #if DCHECK_IS_ON()
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js b/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js index 4d1b3c3..3eacb7ac 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js
@@ -786,8 +786,12 @@ } _updateTabSlider() { - if (!this._currentTab || !this._sliderEnabled) + if (!this._sliderEnabled) return; + if (!this._currentTab) { + this._tabSlider.style.width = 0; + return; + } let left = 0; for (let i = 0; i < this._tabs.length && this._currentTab !== this._tabs[i]; i++) { if (this._tabs[i]._shown)
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/tabbedPane.css b/third_party/WebKit/Source/devtools/front_end/ui/tabbedPane.css index 62ba904e..fcbd3d8c 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/tabbedPane.css +++ b/third_party/WebKit/Source/devtools/front_end/ui/tabbedPane.css
@@ -251,8 +251,7 @@ border-left: 6px solid #666; } -.tabbed-pane-tab-slider, -.-theme-selection-color { +.tabbed-pane-tab-slider { height: 2px; position: absolute; bottom: -1px; @@ -262,7 +261,10 @@ transform-origin: 0 100%; transition: transform 150ms cubic-bezier(0, 0, 0.2, 1); visibility: hidden; - border-top: 1px solid var(--tab-selected-fg-color); +} + +:host-context(.-theme-with-dark-background) .tabbed-pane-tab-slider { + display: none; } @media (-webkit-min-device-pixel-ratio: 1.1) {
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp b/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp index 911b73f..e74476a 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp
@@ -78,7 +78,7 @@ br->PreviousSibling()->RoleValue()); } -TEST_F(AccessibilityTest, ComparisonOperators) { +TEST_F(AccessibilityTest, AXObjectComparisonOperators) { SetBodyInnerHTML(R"HTML(<input id='input' type='text' value='value'>" R"<p id='paragraph'>hello<br id='br'>there</p>" R"<button id='button'>button</button>)HTML");
diff --git a/third_party/WebKit/Source/modules/accessibility/AXPosition.cpp b/third_party/WebKit/Source/modules/accessibility/AXPosition.cpp index cd2c2e6..fa4e592 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXPosition.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXPosition.cpp
@@ -24,7 +24,7 @@ if (child.GetNode() && child.GetNode()->IsTextNode()) return CreateFirstPositionInContainerObject(child); - const AXObject* parent = child.ParentObject(); + const AXObject* parent = child.ParentObjectUnignored(); DCHECK(parent); AXPosition position(*parent); position.text_offset_or_child_index_ = child.IndexInParent(); @@ -39,7 +39,7 @@ if (child.GetNode() && child.GetNode()->IsTextNode()) return CreateLastPositionInContainerObject(child); - const AXObject* parent = child.ParentObject(); + const AXObject* parent = child.ParentObjectUnignored(); DCHECK(parent); AXPosition position(*parent); position.text_offset_or_child_index_ = child.IndexInParent() + 1; @@ -88,6 +88,8 @@ const AXObject& container, int offset, TextAffinity affinity) { + DCHECK(container.GetNode() && container.GetNode()->IsTextNode()) + << "Text positions should be anchored to a text node."; AXPosition position(container); position.text_offset_or_child_index_ = offset; position.affinity_ = affinity; @@ -248,25 +250,69 @@ } bool operator==(const AXPosition& a, const AXPosition& b) { - DCHECK(!a.IsValid() || !b.IsValid()); - return a.ContainerObject() == b.ContainerObject() && - a.ChildIndex() == b.ChildIndex() && a.TextOffset() == b.TextOffset() && - a.Affinity() == b.Affinity(); + DCHECK(a.IsValid() && b.IsValid()); + if (*a.ContainerObject() != *b.ContainerObject()) + return false; + if (a.IsTextPosition() && b.IsTextPosition()) + return a.TextOffset() == b.TextOffset() && a.Affinity() == b.Affinity(); + if (!a.IsTextPosition() && !b.IsTextPosition()) + return a.ChildIndex() == b.ChildIndex(); + NOTREACHED() << "AXPosition objects having the same container object should " + "have the same type."; + return false; } bool operator!=(const AXPosition& a, const AXPosition& b) { return !(a == b); } +bool operator<(const AXPosition& a, const AXPosition& b) { + DCHECK(a.IsValid() && b.IsValid()); + if (*a.ContainerObject() > *b.ContainerObject()) + return false; + if (*a.ContainerObject() < *b.ContainerObject()) + return true; + if (a.IsTextPosition() && b.IsTextPosition()) + return a.TextOffset() < b.TextOffset(); + if (!a.IsTextPosition() && !b.IsTextPosition()) + return a.ChildIndex() < b.ChildIndex(); + NOTREACHED() << "AXPosition objects having the same container object should " + "have the same type."; + return false; +} + +bool operator<=(const AXPosition& a, const AXPosition& b) { + return a < b || a == b; +} + +bool operator>(const AXPosition& a, const AXPosition& b) { + DCHECK(a.IsValid() && b.IsValid()); + if (*a.ContainerObject() < *b.ContainerObject()) + return false; + if (*a.ContainerObject() > *b.ContainerObject()) + return true; + if (a.IsTextPosition() && b.IsTextPosition()) + return a.TextOffset() > b.TextOffset(); + if (!a.IsTextPosition() && !b.IsTextPosition()) + return a.ChildIndex() > b.ChildIndex(); + NOTREACHED() << "AXPosition objects having the same container object should " + "have the same type."; + return false; +} + +bool operator>=(const AXPosition& a, const AXPosition& b) { + return a > b || a == b; +} + std::ostream& operator<<(std::ostream& ostream, const AXPosition& position) { if (!position.IsValid()) - return ostream << "Invalid position"; + return ostream << "Invalid AXPosition"; if (position.IsTextPosition()) { - return ostream << "Text position in " << position.ContainerObject() << ", " - << position.TextOffset(); + return ostream << "AX text position in " << position.ContainerObject() + << ", " << position.TextOffset(); } - return ostream << "Object anchored position in " << position.ContainerObject() - << ", " << position.ChildIndex(); + return ostream << "AX object anchored position in " + << position.ContainerObject() << ", " << position.ChildIndex(); } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/accessibility/AXPosition.h b/third_party/WebKit/Source/modules/accessibility/AXPosition.h index 93990fdc..95512d3 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXPosition.h +++ b/third_party/WebKit/Source/modules/accessibility/AXPosition.h
@@ -96,6 +96,10 @@ MODULES_EXPORT bool operator==(const AXPosition&, const AXPosition&); MODULES_EXPORT bool operator!=(const AXPosition&, const AXPosition&); +MODULES_EXPORT bool operator<(const AXPosition&, const AXPosition&); +MODULES_EXPORT bool operator<=(const AXPosition&, const AXPosition&); +MODULES_EXPORT bool operator>(const AXPosition&, const AXPosition&); +MODULES_EXPORT bool operator>=(const AXPosition&, const AXPosition&); MODULES_EXPORT std::ostream& operator<<(std::ostream&, const AXPosition&); } // namespace blink
diff --git a/third_party/WebKit/Source/modules/accessibility/AXPositionTest.cpp b/third_party/WebKit/Source/modules/accessibility/AXPositionTest.cpp index bf69bb3..e8e4f6b 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXPositionTest.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXPositionTest.cpp
@@ -133,6 +133,64 @@ TEST_F(AccessibilityTest, PositionFromPosition) {} // +// Test comparing two AXPosition objects based on their position in the +// accessibility tree. +// + +TEST_F(AccessibilityTest, AXPositionComparisonOperators) { + SetBodyInnerHTML(R"HTML(<input id='input' type='text' value='value'>" + R"<p id='paragraph'>hello<br>there</p>)HTML"); + + const AXObject* root = GetAXRootObject(); + ASSERT_NE(nullptr, root); + const auto root_first = + AXPosition::CreateFirstPositionInContainerObject(*root); + const auto root_last = AXPosition::CreateLastPositionInContainerObject(*root); + + const AXObject* input = GetAXObjectByElementId("input"); + ASSERT_NE(nullptr, input); + const auto input_before = AXPosition::CreatePositionBeforeObject(*input); + const auto input_after = AXPosition::CreatePositionAfterObject(*input); + + const AXObject* paragraph = GetAXObjectByElementId("paragraph"); + ASSERT_NE(nullptr, paragraph); + ASSERT_NE(nullptr, paragraph->FirstChild()); + ASSERT_NE(nullptr, paragraph->LastChild()); + const auto paragraph_before = + AXPosition::CreatePositionBeforeObject(*paragraph->FirstChild()); + const auto paragraph_after = + AXPosition::CreatePositionAfterObject(*paragraph->LastChild()); + const auto paragraph_start = + AXPosition::CreatePositionInTextObject(*paragraph->FirstChild(), 0); + const auto paragraph_end = + AXPosition::CreatePositionInTextObject(*paragraph->LastChild(), 5); + + EXPECT_TRUE(root_first == root_first); + EXPECT_TRUE(root_last == root_last); + EXPECT_FALSE(root_first != root_first); + EXPECT_TRUE(root_first != root_last); + + EXPECT_TRUE(root_first < root_last); + EXPECT_TRUE(root_first <= root_first); + EXPECT_TRUE(root_last > root_first); + EXPECT_TRUE(root_last >= root_last); + + EXPECT_TRUE(input_before == root_first); + EXPECT_TRUE(input_after > root_first); + EXPECT_TRUE(input_after >= root_first); + EXPECT_FALSE(input_before < root_first); + EXPECT_TRUE(input_before <= root_first); + + // + // Text positions. + // + + EXPECT_TRUE(paragraph_before == paragraph_start); + EXPECT_TRUE(paragraph_after == paragraph_end); + EXPECT_TRUE(paragraph_start < paragraph_end); +} + +// // Test converting to and from visible text with white space. // The accessibility tree is based on visible text with white space compressed, // vs. the DOM tree where white space is preserved.
diff --git a/third_party/WebKit/Source/modules/accessibility/AXSelection.cpp b/third_party/WebKit/Source/modules/accessibility/AXSelection.cpp index 1afcf7b..e68fc5a 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXSelection.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXSelection.cpp
@@ -127,7 +127,7 @@ } bool operator==(const AXSelection& a, const AXSelection& b) { - DCHECK(!a.IsValid() || !b.IsValid()); + DCHECK(a.IsValid() && b.IsValid()); return a.Base() == b.Base() && a.Extent() == b.Extent(); } @@ -137,8 +137,8 @@ std::ostream& operator<<(std::ostream& ostream, const AXSelection& selection) { if (!selection.IsValid()) - return ostream << "Invalid selection"; - return ostream << "Selection from " << selection.Base() << " to " + return ostream << "Invalid AXSelection"; + return ostream << "AXSelection from " << selection.Base() << " to " << selection.Extent(); }
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp index 43f314a8..7299ede 100644 --- a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp
@@ -618,6 +618,9 @@ SkPath sk_path = path.GetSkPath(); FloatRect bounds = path.BoundingRect(); + if (isnan(bounds.X()) || isnan(bounds.Y()) || isnan(bounds.Width()) || + isnan(bounds.Height())) + return; sk_path.setFillType(fill_type); if (paint_type == CanvasRenderingContext2DState::kStrokePaintType)
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.cpp index c0fc6a5..f7d348c5 100644 --- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.cpp +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.cpp
@@ -79,7 +79,7 @@ (event->PlatformTimeStamp() - TimeTicks()).InSecondsF()); request.SetInputPerfMetricReportPolicy( InputToLoadPerfMetricReportPolicy::kReportLink); - request.SetSuggestedFilename(String()); + request.SetSuggestedFilename(MediaElement().title()); request.SetRequestContext(WebURLRequest::kRequestContextDownload); request.SetRequestorOrigin(SecurityOrigin::Create(GetDocument().Url())); GetDocument().GetFrame()->Client()->DownloadURL(request);
diff --git a/third_party/WebKit/Source/modules/notifications/OWNERS b/third_party/WebKit/Source/modules/notifications/OWNERS index 20148c755..f3d5fb2 100644 --- a/third_party/WebKit/Source/modules/notifications/OWNERS +++ b/third_party/WebKit/Source/modules/notifications/OWNERS
@@ -1,4 +1,4 @@ -mvanouwerkerk@chromium.org +awdf@chromium.org peter@chromium.org # TEAM: platform-capabilities@chromium.org
diff --git a/third_party/WebKit/Source/modules/permissions/Permissions.cpp b/third_party/WebKit/Source/modules/permissions/Permissions.cpp index d72a12c..bfde48e 100644 --- a/third_party/WebKit/Source/modules/permissions/Permissions.cpp +++ b/third_party/WebKit/Source/modules/permissions/Permissions.cpp
@@ -189,7 +189,7 @@ PermissionDescriptorPtr descriptor_copy = descriptor->Clone(); Document* doc = ToDocumentOrNull(context); - Frame* frame = doc ? doc->GetFrame() : nullptr; + LocalFrame* frame = doc ? doc->GetFrame() : nullptr; GetService(ExecutionContext::From(script_state)) .RequestPermission( std::move(descriptor), @@ -267,7 +267,7 @@ internal_permissions_copy.push_back(descriptor->Clone()); Document* doc = ToDocumentOrNull(context); - Frame* frame = doc ? doc->GetFrame() : nullptr; + LocalFrame* frame = doc ? doc->GetFrame() : nullptr; GetService(ExecutionContext::From(script_state)) .RequestPermissions( std::move(internal_permissions),
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp index f08b4e8..d5b00fb5f 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp
@@ -80,7 +80,10 @@ DCHECK(Context()->IsAudioThread()); // Render and update the node state when the processor is ready with no error. - if (processor_ && !processor_->hasErrorOccured()) { + // We also need to check if the global scope is valid before we request + // the rendering in the AudioWorkletGlobalScope. + if (processor_ && !processor_->hasErrorOccured() && + Context()->CheckWorkletGlobalScopeOnRenderingThread()) { Vector<AudioBus*> input_buses; Vector<AudioBus*> output_buses; for (unsigned i = 0; i < NumberOfInputs(); ++i) {
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp index 3f8cc8a5..0087a97 100644 --- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
@@ -1036,4 +1036,11 @@ } } +bool BaseAudioContext::CheckWorkletGlobalScopeOnRenderingThread() { + DCHECK(!IsMainThread()); + + return worklet_backing_worker_thread_ && + worklet_backing_worker_thread_->GlobalScope(); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h index 1a68c59..4e17d180 100644 --- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h
@@ -346,6 +346,17 @@ // does not exist. void UpdateWorkletGlobalScopeOnRenderingThread(); + // In the shut-down process, the AudioWorkletGlobalScope can already be gone + // while the backing worker thread is still running. This is called by + // AudioWorkletHandler before it requests the render task to the processor + // which lives on the AudioWorkletGlobalScope. Returns true if there is a + // valid WorkletGloblaScope for the worklet-related task. + // + // TODO(hongchan): This is a short-term fix for https://crbug.com/822725. + // The lifetime of the render task should be managed by not the explicit + // context check but per-global-scope task queues. + bool CheckWorkletGlobalScopeOnRenderingThread(); + protected: enum ContextType { kRealtimeContext, kOfflineContext };
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp b/third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp index 44f2dbf..bcc8b05 100644 --- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp
@@ -653,7 +653,8 @@ // document previous received a user gesture. MAYBE_TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_DocumentReceivedGesture_Child) { - ChildDocument().GetFrame()->UpdateUserActivationInFrameTree(); + Frame::NotifyUserActivation(ChildDocument().GetFrame(), + UserGestureToken::kNewGesture); BaseAudioContext* audio_context = BaseAudioContext::Create( ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION); @@ -689,7 +690,8 @@ // document previous received a user gesture. MAYBE_TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_DocumentReceivedGesture_Main) { - GetDocument().GetFrame()->UpdateUserActivationInFrameTree(); + Frame::NotifyUserActivation(ChildDocument().GetFrame(), + UserGestureToken::kNewGesture); BaseAudioContext* audio_context = BaseAudioContext::Create( GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
diff --git a/third_party/WebKit/Source/modules/webgl/PRESUBMIT.py b/third_party/WebKit/Source/modules/webgl/PRESUBMIT.py index 2b84253..12569e2 100644 --- a/third_party/WebKit/Source/modules/webgl/PRESUBMIT.py +++ b/third_party/WebKit/Source/modules/webgl/PRESUBMIT.py
@@ -20,7 +20,7 @@ return output_api.EnsureCQIncludeTrybotsAreAdded( cl, ['luci.chromium.try:linux_optional_gpu_tests_rel', - 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'luci.chromium.try:mac_optional_gpu_tests_rel', 'master.tryserver.chromium.win:win_optional_gpu_tests_rel', 'master.tryserver.chromium.android:android_optional_gpu_tests_rel'], 'Automatically added optional GPU tests to run on CQ.')
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp index b480e95..8a25d09 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -105,14 +105,13 @@ contents_layer_(nullptr), contents_layer_id_(0), scrollable_area_(nullptr), - rendering_context3d_(0), - weak_ptr_factory_(this) { + rendering_context3d_(0) { #if DCHECK_IS_ON() client.VerifyNotPainting(); #endif layer_ = Platform::Current()->CompositorSupport()->CreateContentLayer(this); layer_->Layer()->SetDrawsContent(draws_content_ && contents_visible_); - layer_->Layer()->SetLayerClient(weak_ptr_factory_.GetWeakPtr()); + layer_->Layer()->SetLayerClient(this); UpdateTrackingRasterInvalidations(); } @@ -557,7 +556,7 @@ contents_layer_id_ = 0; return; } - contents_layer_->SetLayerClient(weak_ptr_factory_.GetWeakPtr()); + contents_layer_->SetLayerClient(this); contents_layer_id_ = contents_layer_->Id(); } @@ -1293,7 +1292,7 @@ void GraphicsLayer::AddLinkHighlight(LinkHighlight* link_highlight) { DCHECK(link_highlight && !link_highlights_.Contains(link_highlight)); link_highlights_.push_back(link_highlight); - link_highlight->Layer()->SetLayerClient(weak_ptr_factory_.GetWeakPtr()); + link_highlight->Layer()->SetLayerClient(this); UpdateChildList(); }
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h index af74800..048d9c2 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
@@ -28,7 +28,6 @@ #define GraphicsLayer_h #include <memory> -#include "base/memory/weak_ptr.h" #include "cc/layers/layer_client.h" #include "platform/PlatformExport.h" #include "platform/geometry/FloatPoint.h" @@ -431,8 +430,6 @@ std::unique_ptr<LayerState> layer_state_; std::unique_ptr<CompositedLayerRasterInvalidator> raster_invalidator_; - - base::WeakPtrFactory<GraphicsLayer> weak_ptr_factory_; }; // ObjectPaintInvalidatorWithContext::InvalidatePaintRectangleWithContext uses
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp index fd78bd0..3fc2f3052 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp
@@ -114,11 +114,15 @@ void ApplyTransform(const TransformPaintPropertyNode* target_transform) { if (target_transform == current_transform_) return; + cc_list_.push<cc::ConcatOp>(GetSkMatrix(target_transform)); + } - cc_list_.push<cc::ConcatOp>( - static_cast<SkMatrix>(TransformationMatrix::ToSkMatrix44( - GeometryMapper::SourceToDestinationProjection( - target_transform, current_transform_)))); + SkMatrix GetSkMatrix( + const TransformPaintPropertyNode* target_transform) const { + return AffineTransformToSkMatrix( + GeometryMapper::SourceToDestinationProjection(target_transform, + current_transform_) + .ToAffineTransform()); } void AppendRestore(size_t n) { @@ -128,6 +132,10 @@ cc_list_.EndPaintOfPairedEnd(); } + void UpdateEffectBounds(const FloatRect&, const TransformPaintPropertyNode*); + void PopToParentEffect(); + void PopClips(); + const PropertyTreeState& layer_state_; gfx::Vector2dF layer_offset_; @@ -152,12 +160,30 @@ }; Vector<StateEntry> state_stack_; + // This structure accumulates bounds of all chunks under an effect. When an + // effect starts, we emit a SaveLayerOp with null bounds starts, and push a + // new |EffectBoundsInfo| onto |effect_bounds_stack_|. When the effect ends, + // we update the bounds of the SaveLayerOp. + struct EffectBoundsInfo { + // The id of the SaveLayerOp for this effect. It's recorded when we push the + // SaveLayerOp for this effect, and used when this effect ends in + // UpdateSaveLayerBounds(). + size_t save_layer_id; + // The transform space when the SaveLayerOp was emitted. + const TransformPaintPropertyNode* transform; + // Records the bounds of the effect which initiated the entry. Note that + // the effect is not |this->effect| (which is the previous effect), but the + // |current_effect_| when this entry is the top of the stack. + FloatRect bounds; + }; + Vector<EffectBoundsInfo> effect_bounds_stack_; + cc::DisplayItemList& cc_list_; }; ConversionContext::~ConversionContext() { - for (auto& entry : state_stack_) - AppendRestore(entry.saved_count); + while (state_stack_.size()) + PopToParentEffect(); } void ConversionContext::SwitchToClip(const ClipPaintPropertyNode* target_clip) { @@ -298,13 +324,7 @@ #endif if (!state_stack_.size()) break; - - StateEntry& previous_state = state_stack_.back(); - AppendRestore(previous_state.saved_count); - current_transform_ = previous_state.transform; - current_clip_ = previous_state.clip; - current_effect_ = previous_state.effect; - state_stack_.pop_back(); + PopToParentEffect(); } // Step 2: Collect all effects between the target effect and the current @@ -325,37 +345,29 @@ // Step 3a: Before each effect can be applied, we must enter its output // clip first, or exit all clips if it doesn't have one. - if (sub_effect->OutputClip()) { + if (sub_effect->OutputClip()) SwitchToClip(sub_effect->OutputClip()); - } else { - while (state_stack_.size() && - state_stack_.back().type == StateEntry::kClip) { - StateEntry& previous_state = state_stack_.back(); - AppendRestore(previous_state.saved_count); - current_transform_ = previous_state.transform; - current_clip_ = previous_state.clip; - DCHECK_EQ(previous_state.effect, current_effect_); - state_stack_.pop_back(); - } - } + else + PopClips(); - // Step 3b: Apply non-spatial effects first, adjust CTM, then apply spatial - // effects. Strictly speaking the CTM shall be appled first, it is done - // in this particular order only to save one SaveOp. + // Step 3b: Apply effects. cc_list_.StartPaint(); - cc::PaintFlags flags; int saved_count = 0; + size_t save_layer_id = kNotFound; + const auto* target_transform = current_transform_; - auto save_layer_once = [this, &flags, &saved_count]() { - if (!saved_count) { - saved_count = 1; - cc_list_.push<cc::SaveLayerOp>(nullptr, &flags); - } - }; + // We always create separate effect nodes for normal effects and filter + // effects, so we can handle them separately. + bool has_filter = !sub_effect->Filter().IsEmpty(); + bool has_other_effects = sub_effect->Opacity() != 1.f || + sub_effect->BlendMode() != SkBlendMode::kSrcOver || + sub_effect->GetColorFilter() != kColorFilterNone; + DCHECK(!has_filter || !has_other_effects); - if (sub_effect->BlendMode() != SkBlendMode::kSrcOver || - sub_effect->Opacity() != 1.f || - sub_effect->GetColorFilter() != kColorFilterNone) { + if (!has_filter) { + // No need to adjust transform for non-filter effects because transform + // doesn't matter. + cc::PaintFlags flags; flags.setBlendMode(sub_effect->BlendMode()); // TODO(ajuma): This should really be rounding instead of flooring the // alpha value, but that breaks slimming paint reftests. @@ -363,38 +375,37 @@ static_cast<uint8_t>(gfx::ToFlooredInt(255 * sub_effect->Opacity()))); flags.setColorFilter(GraphicsContext::WebCoreColorFilterToSkiaColorFilter( sub_effect->GetColorFilter())); - save_layer_once(); - } - - const TransformPaintPropertyNode* target_transform = - sub_effect->LocalTransformSpace(); - if (current_transform_ != target_transform) { - save_layer_once(); - ApplyTransform(target_transform); - } - - if (sub_effect->Filter().IsEmpty()) { - save_layer_once(); + save_layer_id = cc_list_.push<cc::SaveLayerOp>(nullptr, &flags); + saved_count++; } else { + // Handle filter effect. Adjust transform first. + target_transform = sub_effect->LocalTransformSpace(); FloatPoint filter_origin = sub_effect->PaintOffset(); - if (filter_origin != FloatPoint()) { - save_layer_once(); - cc_list_.push<cc::TranslateOp>(filter_origin.X(), filter_origin.Y()); + if (current_transform_ != target_transform || + filter_origin != FloatPoint()) { + auto matrix = GetSkMatrix(target_transform); + matrix.preTranslate(filter_origin.X(), filter_origin.Y()); + cc_list_.push<cc::SaveOp>(); + cc_list_.push<cc::ConcatOp>(matrix); + saved_count++; } + // The size parameter is only used to computed the origin of zoom // operation, which we never generate. gfx::SizeF empty; cc::PaintFlags filter_flags; filter_flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter( sub_effect->Filter().AsCcFilterOperations(), empty)); - cc_list_.push<cc::SaveLayerOp>(nullptr, &filter_flags); + save_layer_id = cc_list_.push<cc::SaveLayerOp>(nullptr, &filter_flags); + if (filter_origin != FloatPoint()) cc_list_.push<cc::TranslateOp>(-filter_origin.X(), -filter_origin.Y()); - saved_count++; } - DCHECK(saved_count); + DCHECK_GT(saved_count, 0); + DCHECK_LE(saved_count, 2); + DCHECK_NE(save_layer_id, kNotFound); cc_list_.EndPaintOfPairedBegin(); // Step 3c: Adjust state and push previous state onto effect stack. @@ -403,12 +414,84 @@ state_stack_.emplace_back(StateEntry{StateEntry::PairedType::kEffect, saved_count, current_transform_, current_clip_, current_effect_}); + effect_bounds_stack_.emplace_back( + EffectBoundsInfo{save_layer_id, target_transform}); current_transform_ = target_transform; current_clip_ = input_clip; current_effect_ = sub_effect; } } +void ConversionContext::UpdateEffectBounds( + const FloatRect& bounds, + const TransformPaintPropertyNode* transform) { + if (effect_bounds_stack_.IsEmpty() || bounds.IsEmpty()) + return; + + auto& effect_bounds_info = effect_bounds_stack_.back(); + FloatRect mapped_bounds = bounds; + GeometryMapper::SourceToDestinationRect( + transform, effect_bounds_info.transform, mapped_bounds); + effect_bounds_info.bounds.Unite(mapped_bounds); +} + +// Pop clip states (if any) and one effect state (if any) on the top of the +// stack. Update the bounds of the SaveLayerOp of the effect. +void ConversionContext::PopToParentEffect() { + DCHECK(state_stack_.size()); + PopClips(); + if (state_stack_.IsEmpty()) + return; + + const auto& previous_state = state_stack_.back(); + DCHECK_EQ(previous_state.type, StateEntry::kEffect); + DCHECK_EQ(current_effect_->Parent(), previous_state.effect); + DCHECK_EQ(current_clip_, previous_state.clip); + + DCHECK(effect_bounds_stack_.size()); + const auto& bounds_info = effect_bounds_stack_.back(); + FloatRect bounds = bounds_info.bounds; + if (!bounds.IsEmpty()) { + if (current_effect_->Filter().IsEmpty()) { + cc_list_.UpdateSaveLayerBounds(bounds_info.save_layer_id, bounds); + } else { + // The bounds for the SaveLayerOp should be the source bounds before the + // filter is applied, in the space of the TranslateOp which was emitted + // before the SaveLayerOp. + auto save_layer_bounds = bounds; + save_layer_bounds.MoveBy(-current_effect_->PaintOffset()); + cc_list_.UpdateSaveLayerBounds(bounds_info.save_layer_id, + save_layer_bounds); + // We need to propagate the filtered bounds to the parent. + bounds = current_effect_->MapRect(bounds); + } + } + + effect_bounds_stack_.pop_back(); + current_effect_ = previous_state.effect; + + // Propagate the bounds to the parent effect. + UpdateEffectBounds(bounds, current_transform_); + + AppendRestore(previous_state.saved_count); + current_effect_ = previous_state.effect; + current_transform_ = previous_state.transform; + state_stack_.pop_back(); +} + +// Pop clip states on the top of the stack until the top is an effect state +// or the stack is empty. +void ConversionContext::PopClips() { + while (state_stack_.size() && state_stack_.back().type == StateEntry::kClip) { + const auto& previous_state = state_stack_.back(); + AppendRestore(previous_state.saved_count); + current_transform_ = previous_state.transform; + current_clip_ = previous_state.clip; + DCHECK_EQ(previous_state.effect, current_effect_); + state_stack_.pop_back(); + } +} + void ConversionContext::Convert(const Vector<const PaintChunk*>& paint_chunks, const DisplayItemList& display_items) { bool translated = false; @@ -478,6 +561,7 @@ } if (transformed) AppendRestore(1); + UpdateEffectBounds(chunk.bounds, chunk_state.Transform()); } if (translated) AppendRestore(1);
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayerTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayerTest.cpp index 0dde3ff..aad4ca3 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayerTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayerTest.cpp
@@ -28,6 +28,12 @@ } } // namespace cc +std::ostream& operator<<(std::ostream& os, const SkRect& rect) { + if (cc::PaintOp::IsUnsetRect(rect)) + return os << "(unset)"; + return os << blink::FloatRect(rect).ToString(); +} + namespace blink { namespace { @@ -39,9 +45,7 @@ PaintChunksToCcLayerTest() : ScopedSlimmingPaintV2ForTest(true) {} }; -// A simple matcher that only looks for a few ops, ignoring all else. -// Recognized ops: -// ClipPath, ClipRect, Concat, DrawRecord, Save, SaveLayer, Restore. +// Matches PaintOpTypes in a PaintRecord. class PaintRecordMatcher : public ::testing::MatcherInterface<const cc::PaintOpBuffer&> { public: @@ -55,51 +59,30 @@ bool MatchAndExplain( const cc::PaintOpBuffer& buffer, ::testing::MatchResultListener* listener) const override { - auto next = expected_ops_.begin(); - size_t op_idx = 0; - for (cc::PaintOpBuffer::Iterator it(&buffer); it; ++it, ++op_idx) { - cc::PaintOpType op = (*it)->GetType(); - switch (op) { - case cc::PaintOpType::ClipPath: - case cc::PaintOpType::ClipRect: - case cc::PaintOpType::ClipRRect: - case cc::PaintOpType::Concat: - case cc::PaintOpType::DrawRecord: - case cc::PaintOpType::Save: - case cc::PaintOpType::SaveLayer: - case cc::PaintOpType::Restore: - case cc::PaintOpType::Translate: - if (next == expected_ops_.end()) { - if (listener->IsInterested()) { - *listener << "unexpected op " << cc::PaintOpTypeToString(op) - << " at index " << op_idx << ", expecting end of list."; - } - return false; - } - if (*next == op) { - next++; - continue; - } - if (listener->IsInterested()) { - *listener << "unexpected op " << cc::PaintOpTypeToString(op) - << " at index " << op_idx << ", expecting " - << cc::PaintOpTypeToString(*next) << "(#" - << (next - expected_ops_.begin()) << ")."; - } - return false; - default: - continue; + size_t index = 0; + for (cc::PaintOpBuffer::Iterator it(&buffer); it; ++it, ++index) { + auto op = (*it)->GetType(); + if (index < expected_ops_.size() && expected_ops_[index] == op) + continue; + + if (listener->IsInterested()) { + *listener << "unexpected op " << op << " at index " << index << ","; + if (index < expected_ops_.size()) + *listener << " expecting " << expected_ops_[index] << "."; + else + *listener << " expecting end of list."; } + return false; } - if (next == expected_ops_.end()) + if (index == expected_ops_.size()) return true; if (listener->IsInterested()) { - *listener << "unexpected end of list, expecting " - << cc::PaintOpTypeToString(*next) << "(#" - << (next - expected_ops_.begin()) << ")."; + *listener << "unexpected end of list, expecting " << expected_ops_[index] + << " at index " << index << "."; } return false; } + void DescribeTo(::std::ostream* os) const override { *os << "["; bool first = true; @@ -108,7 +91,7 @@ first = false; else *os << ", "; - *os << cc::PaintOpTypeToString(op); + *os << op; } *os << "]"; } @@ -117,6 +100,30 @@ Vector<cc::PaintOpType> expected_ops_; }; +#define EXPECT_EFFECT_BOUNDS(x, y, width, height, op_buffer, index) \ + do { \ + const auto* save_layer = \ + (op_buffer).GetOpAtForTesting<cc::SaveLayerOp>(index); \ + ASSERT_NE(nullptr, save_layer); \ + EXPECT_EQ(FloatRect(x, y, width, height), FloatRect(save_layer->bounds)); \ + } while (false) + +#define EXPECT_TRANSFORM_MATRIX(transform, op_buffer, index) \ + do { \ + const auto* concat = (op_buffer).GetOpAtForTesting<cc::ConcatOp>(index); \ + ASSERT_NE(nullptr, concat); \ + EXPECT_EQ(transform, TransformationMatrix(concat->matrix)); \ + } while (false) + +#define EXPECT_TRANSLATE(x, y, op_buffer, index) \ + do { \ + const auto* translate = \ + (op_buffer).GetOpAtForTesting<cc::TranslateOp>(index); \ + ASSERT_NE(nullptr, translate); \ + EXPECT_EQ(x, translate->dx); \ + EXPECT_EQ(y, translate->dy); \ + } while (false) + // Convenient shorthands. const TransformPaintPropertyNode* t0() { return TransformPaintPropertyNode::Root(); @@ -141,23 +148,25 @@ // Add a paint chunk with a non-empty paint record and given property nodes. void AddChunk(const TransformPaintPropertyNode* t, const ClipPaintPropertyNode* c, - const EffectPaintPropertyNode* e) { + const EffectPaintPropertyNode* e, + const FloatRect& bounds = FloatRect(0, 0, 100, 100)) { auto record = sk_make_sp<PaintRecord>(); - record->push<cc::DrawRectOp>(SkRect::MakeXYWH(0, 0, 100, 100), - cc::PaintFlags()); - AddChunk(std::move(record), t, c, e); + record->push<cc::DrawRectOp>(bounds, cc::PaintFlags()); + AddChunk(std::move(record), t, c, e, bounds); } // Add a paint chunk with a given paint record and property nodes. void AddChunk(sk_sp<PaintRecord> record, const TransformPaintPropertyNode* t, const ClipPaintPropertyNode* c, - const EffectPaintPropertyNode* e) { + const EffectPaintPropertyNode* e, + const FloatRect& bounds = FloatRect(0, 0, 100, 100)) { size_t i = items.size(); items.AllocateAndConstruct<DrawingDisplayItem>( DefaultId().client, DefaultId().type, std::move(record)); chunks.emplace_back(i, i + 1, DefaultId(), PaintChunkProperties(PropertyTreeState(t, c, e))); + chunks.back().bounds = bounds; } Vector<const PaintChunk*> GetChunkList() const { @@ -173,8 +182,8 @@ scoped_refptr<EffectPaintPropertyNode> e1 = CreateOpacityOnlyEffect(e0(), 0.5f); TestChunks chunks; - chunks.AddChunk(t0(), c0(), e1.get()); - chunks.AddChunk(t0(), c0(), e1.get()); + chunks.AddChunk(t0(), c0(), e1.get(), FloatRect(0, 0, 50, 50)); + chunks.AddChunk(t0(), c0(), e1.get(), FloatRect(20, 20, 70, 70)); sk_sp<PaintRecord> output = PaintChunksToCcLayer::Convert( @@ -187,6 +196,7 @@ cc::PaintOpType::DrawRecord, // <p0/> cc::PaintOpType::DrawRecord, // <p1/> cc::PaintOpType::Restore})); // </e1> + EXPECT_EFFECT_BOUNDS(0, 0, 90, 90, *output, 0); } TEST_F(PaintChunksToCcLayerTest, EffectGroupingNested) { @@ -199,7 +209,7 @@ CreateOpacityOnlyEffect(e1.get(), 0.5f); TestChunks chunks; chunks.AddChunk(t0(), c0(), e2.get()); - chunks.AddChunk(t0(), c0(), e3.get()); + chunks.AddChunk(t0(), c0(), e3.get(), FloatRect(111, 222, 333, 444)); sk_sp<PaintRecord> output = PaintChunksToCcLayer::Convert( @@ -216,6 +226,62 @@ cc::PaintOpType::DrawRecord, // <p1/> cc::PaintOpType::Restore, // </e3> cc::PaintOpType::Restore})); // </e1> + EXPECT_EFFECT_BOUNDS(0, 0, 444, 666, *output, 0); + EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 1); + EXPECT_EFFECT_BOUNDS(111, 222, 333, 444, *output, 4); +} + +TEST_F(PaintChunksToCcLayerTest, EffectFilterGroupingNestedWithTransforms) { + // This test verifies nested effects with transforms are grouped properly. + auto t1 = TransformPaintPropertyNode::Create( + t0(), TransformationMatrix().Scale(2.f), FloatPoint3D()); + auto t2 = TransformPaintPropertyNode::Create( + t1.get(), TransformationMatrix().Translate(-50, -50), FloatPoint3D()); + auto e1 = EffectPaintPropertyNode::Create(e0(), t2.get(), c0(), ColorFilter(), + CompositorFilterOperations(), .5f, + SkBlendMode::kSrcOver); + CompositorFilterOperations filter; + filter.AppendBlurFilter(5); + auto e2 = EffectPaintPropertyNode::Create( + e1.get(), t2.get(), c0(), ColorFilter(), filter, 1.f, + SkBlendMode::kSrcOver, CompositingReason::kNone, CompositorElementId(), + FloatPoint(60, 60)); + CreateOpacityOnlyEffect(e1.get(), 0.5f); + TestChunks chunks; + chunks.AddChunk(t2.get(), c0(), e1.get(), FloatRect(0, 0, 50, 50)); + chunks.AddChunk(t1.get(), c0(), e2.get(), FloatRect(20, 20, 70, 70)); + + sk_sp<PaintRecord> output = + PaintChunksToCcLayer::Convert( + chunks.GetChunkList(), PropertyTreeState(t0(), c0(), e0()), + gfx::Vector2dF(), chunks.items, + cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer) + ->ReleaseAsRecord(); + EXPECT_THAT( + *output, + PaintRecordMatcher::Make( + {cc::PaintOpType::SaveLayer, // <e1> + cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1*t2> + cc::PaintOpType::DrawRecord, // <p1/> + cc::PaintOpType::Restore, // </t1*t2> + cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1*t2+e2_offset> + cc::PaintOpType::SaveLayer, // <e2> + cc::PaintOpType::Translate, // </e2_offset> + cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t2^-1> + cc::PaintOpType::DrawRecord, // <p2/> + cc::PaintOpType::Restore, // </t2^-1> + cc::PaintOpType::Restore, // </e2> + cc::PaintOpType::Restore, // </t1*t2> + cc::PaintOpType::Restore})); // </e1> + // t1(t2(chunk1.bounds + e2(t2^-1(chunk2.bounds)))) + EXPECT_EFFECT_BOUNDS(-100, -100, 310, 310, *output, 0); + EXPECT_TRANSFORM_MATRIX(t1->Matrix() * t2->Matrix(), *output, 2); + EXPECT_TRANSFORM_MATRIX((t1->Matrix() * t2->Matrix()).Translate(60, 60), + *output, 6); + // t2^-1(chunk2.bounds) - e2_offset + EXPECT_EFFECT_BOUNDS(10, 10, 70, 70, *output, 7); + EXPECT_TRANSLATE(-60, -60, *output, 8); + EXPECT_TRANSFORM_MATRIX(t2->Matrix().Inverse(), *output, 10); } TEST_F(PaintChunksToCcLayerTest, InterleavedClipEffect) { @@ -241,8 +307,8 @@ TestChunks chunks; chunks.AddChunk(t0(), c2.get(), e0()); chunks.AddChunk(t0(), c3.get(), e0()); - chunks.AddChunk(t0(), c4.get(), e2.get()); - chunks.AddChunk(t0(), c3.get(), e1.get()); + chunks.AddChunk(t0(), c4.get(), e2.get(), FloatRect(0, 0, 50, 50)); + chunks.AddChunk(t0(), c3.get(), e1.get(), FloatRect(20, 20, 70, 70)); chunks.AddChunk(t0(), c4.get(), e0()); sk_sp<PaintRecord> output = @@ -273,6 +339,8 @@ cc::PaintOpType::DrawRecord, // <p4/> cc::PaintOpType::Restore, // </c3+c4> cc::PaintOpType::Restore})); // </c1+c2> + EXPECT_EFFECT_BOUNDS(0, 0, 90, 90, *output, 7); + EXPECT_EFFECT_BOUNDS(0, 0, 50, 50, *output, 10); } TEST_F(PaintChunksToCcLayerTest, ClipSpaceInversion) { @@ -305,14 +373,13 @@ cc::PaintOpType::Restore})); // </c1 t1> } -TEST_F(PaintChunksToCcLayerTest, EffectSpaceInversion) { +TEST_F(PaintChunksToCcLayerTest, OpacityEffectSpaceInversion) { // This test verifies chunks that have a shallower transform state than // its effect can still be painted. The infamous CSS corner case: // <div style="overflow:scroll"> - // <div style="opacity:0.5"> - // <div style="position:absolute;">Transparent but not scroll - // along.</div> - // </div> + // <div style="opacity:0.5"> + // <div style="position:absolute;">Transparent but not scroll along.</div> + // </div> // </div> scoped_refptr<TransformPaintPropertyNode> t1 = TransformPaintPropertyNode::Create( @@ -322,6 +389,7 @@ SkBlendMode::kSrcOver); TestChunks chunks; chunks.AddChunk(t0(), c0(), e1.get()); + chunks.AddChunk(t1.get(), c0(), e1.get()); sk_sp<PaintRecord> output = PaintChunksToCcLayer::Convert( @@ -329,14 +397,57 @@ gfx::Vector2dF(), chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer) ->ReleaseAsRecord(); + EXPECT_THAT(*output, + PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer, // <e1> + cc::PaintOpType::DrawRecord, // <p0/> + cc::PaintOpType::Save, + cc::PaintOpType::Concat, // <t1> + cc::PaintOpType::DrawRecord, // <p1/> + cc::PaintOpType::Restore, // </t1> + cc::PaintOpType::Restore})); // </e1> + EXPECT_EFFECT_BOUNDS(0, 0, 200, 200, *output, 0); + EXPECT_TRANSFORM_MATRIX(t1->Matrix(), *output, 3); +} + +TEST_F(PaintChunksToCcLayerTest, FilterEffectSpaceInversion) { + // This test verifies chunks that have a shallower transform state than + // its effect can still be painted. The infamous CSS corner case: + // <div style="overflow:scroll"> + // <div style="filter:blur(1px)"> + // <div style="position:absolute;">Filtered but not scroll along.</div> + // </div> + // </div> + auto t1 = TransformPaintPropertyNode::Create( + t0(), TransformationMatrix().Scale(2.f), FloatPoint3D()); + CompositorFilterOperations filter; + filter.AppendBlurFilter(5); + auto e1 = EffectPaintPropertyNode::Create( + e0(), t1.get(), c0(), ColorFilter(), filter, 1.f, SkBlendMode::kSrcOver, + CompositingReason::kNone, CompositorElementId(), FloatPoint(66, 88)); + TestChunks chunks; + chunks.AddChunk(t0(), c0(), e1.get()); + + auto output = PaintChunksToCcLayer::Convert( + chunks.GetChunkList(), PropertyTreeState(t0(), c0(), e0()), + gfx::Vector2dF(), chunks.items, + cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer) + ->ReleaseAsRecord(); EXPECT_THAT( *output, PaintRecordMatcher::Make( - {cc::PaintOpType::SaveLayer, cc::PaintOpType::Concat, // <t1 e1> - cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1^-1> - cc::PaintOpType::DrawRecord, // <p0/> - cc::PaintOpType::Restore, // </t1^-1> - cc::PaintOpType::Restore})); // </e1 t1> + {cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1*e1_offset> + cc::PaintOpType::SaveLayer, // <e1> + cc::PaintOpType::Translate, // </e1_offset> + cc::PaintOpType::Save, cc::PaintOpType::Concat, // <t1^-1> + cc::PaintOpType::DrawRecord, // <p0/> + cc::PaintOpType::Restore, // </t1^-1> + cc::PaintOpType::Restore, // </e1> + cc::PaintOpType::Restore})); // </t1> + EXPECT_TRANSFORM_MATRIX(TransformationMatrix(t1->Matrix()).Translate(66, 88), + *output, 1); + EXPECT_EFFECT_BOUNDS(-66, -88, 50, 50, *output, 2); + EXPECT_TRANSLATE(-66, -88, *output, 3); + EXPECT_TRANSFORM_MATRIX(t1->Matrix().Inverse(), *output, 5); } TEST_F(PaintChunksToCcLayerTest, NonRootLayerSimple) { @@ -413,6 +524,7 @@ cc::PaintOpType::DrawRecord, // <p0/> cc::PaintOpType::Restore, // </c2> cc::PaintOpType::Restore})); // </e1> + EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0); } TEST_F(PaintChunksToCcLayerTest, @@ -444,6 +556,8 @@ cc::PaintOpType::Restore, // </c1> cc::PaintOpType::Restore, // </e2> cc::PaintOpType::Restore})); // </e1> + EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0); + EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 1); } TEST_F(PaintChunksToCcLayerTest, @@ -473,6 +587,7 @@ cc::PaintOpType::DrawRecord, // <p0/> cc::PaintOpType::Restore, // </c1> cc::PaintOpType::Restore})); // </e2> + EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0); } TEST_F(PaintChunksToCcLayerTest, @@ -499,6 +614,7 @@ PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer, // <e2> cc::PaintOpType::DrawRecord, // <p0/> cc::PaintOpType::Restore})); // </e2> + EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0); } TEST_F(PaintChunksToCcLayerTest, VisualRect) { @@ -643,6 +759,7 @@ cc::PaintOpType::SaveLayer, // <e1> cc::PaintOpType::Restore, // </e1> })); + EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0); } TEST_F(PaintChunksToCcLayerTest, CombineClips) {
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py index bb0351349..fd79812 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -107,8 +107,16 @@ [[CONTENT_SHELL_FONTS_DIR], 'Arimo-BoldItalic.ttf', None], [[CONTENT_SHELL_FONTS_DIR], 'Arimo-Italic.ttf', None], [[CONTENT_SHELL_FONTS_DIR], 'Arimo-Regular.ttf', None], + [[CONTENT_SHELL_FONTS_DIR], 'Cousine-Bold.ttf', None], + [[CONTENT_SHELL_FONTS_DIR], 'Cousine-BoldItalic.ttf', None], + [[CONTENT_SHELL_FONTS_DIR], 'Cousine-Italic.ttf', None], + [[CONTENT_SHELL_FONTS_DIR], 'Cousine-Regular.ttf', None], [[CONTENT_SHELL_FONTS_DIR], 'DejaVuSans.ttf', None], [[CONTENT_SHELL_FONTS_DIR], 'Garuda.ttf', None], + [[CONTENT_SHELL_FONTS_DIR], 'Gelasio-Bold.ttf', None], + [[CONTENT_SHELL_FONTS_DIR], 'Gelasio-BoldItalic.ttf', None], + [[CONTENT_SHELL_FONTS_DIR], 'Gelasio-Italic.ttf', None], + [[CONTENT_SHELL_FONTS_DIR], 'Gelasio-Regular.ttf', None], [[CONTENT_SHELL_FONTS_DIR], 'Lohit-Devanagari.ttf', None], [[CONTENT_SHELL_FONTS_DIR], 'Lohit-Gurmukhi.ttf', None], [[CONTENT_SHELL_FONTS_DIR], 'Lohit-Tamil.ttf', None],
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_copier.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_copier.py index 61f7e74..209550d 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_copier.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_copier.py
@@ -39,24 +39,22 @@ _log = logging.getLogger(__name__) +# Directory for imported tests relative to the layout tests base directory. +DEST_DIR_NAME = 'external' class TestCopier(object): - def __init__(self, host, source_repo_path, dest_dir_name='external'): + def __init__(self, host, source_repo_path): """Initializes variables to prepare for copying and converting files. Args: host: An instance of Host. source_repo_path: Path to the local checkout of web-platform-tests. - dest_dir_name: The name of the directory under the layout tests - directory where imported tests should be copied to. - TODO(qyearsley): This can be made into a constant. """ self.host = host assert self.host.filesystem.exists(source_repo_path) self.source_repo_path = source_repo_path - self.dest_dir_name = dest_dir_name self.filesystem = self.host.filesystem self.path_finder = PathFinder(self.filesystem) @@ -64,7 +62,7 @@ self.destination_directory = self.filesystem.normpath( self.filesystem.join( self.layout_tests_dir, - dest_dir_name, + DEST_DIR_NAME, self.filesystem.basename(self.source_repo_path))) self.import_in_place = (self.source_repo_path == self.destination_directory) self.dir_above_repo = self.filesystem.dirname(self.source_repo_path) @@ -100,7 +98,7 @@ dirs.remove(name) for path in paths_to_skip: - path_base = path.replace(self.dest_dir_name + '/', '') + path_base = path.replace(DEST_DIR_NAME + '/', '') path_base = path_base.replace(cur_dir, '') path_full = self.filesystem.join(root, path_base) if path_base in dirs:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_copier_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_copier_unittest.py index 8bc25913..e6aac52 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_copier_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_copier_unittest.py
@@ -51,7 +51,7 @@ host = MockHost() host.executive = MockExecutive(exception=ScriptError('error')) host.filesystem = MockFileSystem(files=FAKE_FILES) - copier = TestCopier(host, FAKE_SOURCE_REPO_DIR, 'destination') + copier = TestCopier(host, FAKE_SOURCE_REPO_DIR) copier.do_import() # No exception raised. def test_does_not_import_owner_files(self):
diff --git a/third_party/WebKit/public/platform/WebDocumentSubresourceFilter.h b/third_party/WebKit/public/platform/WebDocumentSubresourceFilter.h index 75770ef..8c85dbf9 100644 --- a/third_party/WebKit/public/platform/WebDocumentSubresourceFilter.h +++ b/third_party/WebKit/public/platform/WebDocumentSubresourceFilter.h
@@ -35,6 +35,8 @@ // Returns true if disallowed resource loads should be logged to the devtools // console. virtual bool ShouldLogToConsole() = 0; + + virtual bool GetIsAssociatedWithAdSubframe() const = 0; }; } // namespace blink
diff --git a/third_party/WebKit/public/platform/WebLayer.h b/third_party/WebKit/public/platform/WebLayer.h index 82b63b4..b9dd379 100644 --- a/third_party/WebKit/public/platform/WebLayer.h +++ b/third_party/WebKit/public/platform/WebLayer.h
@@ -241,7 +241,7 @@ virtual void SetSnapContainerData(base::Optional<cc::SnapContainerData>) = 0; // Sets the cc-side layer client. - virtual void SetLayerClient(base::WeakPtr<cc::LayerClient>) = 0; + virtual void SetLayerClient(cc::LayerClient*) = 0; // Gets the underlying cc layer. virtual const cc::Layer* CcLayer() const = 0;
diff --git a/third_party/WebKit/public/web/WebDocumentLoader.h b/third_party/WebKit/public/web/WebDocumentLoader.h index 53463bcf..19ec4cc 100644 --- a/third_party/WebKit/public/web/WebDocumentLoader.h +++ b/third_party/WebKit/public/web/WebDocumentLoader.h
@@ -144,8 +144,6 @@ // initiated loads that may have had a user activation from the browser UI. virtual void SetUserActivated() = 0; - // Sets if the document is an ad identified subframe. - virtual void SetIsAdSubframe(bool is_ad_subframe) = 0; virtual bool GetIsAdSubframe() const = 0; protected:
diff --git a/third_party/WebKit/public/web/WebFrame.h b/third_party/WebKit/public/web/WebFrame.h index 99e6346..df23b67 100644 --- a/third_party/WebKit/public/web/WebFrame.h +++ b/third_party/WebKit/public/web/WebFrame.h
@@ -204,9 +204,6 @@ void DetachFromParent(); #endif - // Mark this frame's document as having received a user gesture. - virtual void SetHasReceivedUserGesture() = 0; - protected: explicit WebFrame(WebTreeScopeType); virtual ~WebFrame();
diff --git a/third_party/WebKit/public/web/WebLocalFrame.h b/third_party/WebKit/public/web/WebLocalFrame.h index 37890c8..e0bc9bb 100644 --- a/third_party/WebKit/public/web/WebLocalFrame.h +++ b/third_party/WebKit/public/web/WebLocalFrame.h
@@ -157,6 +157,9 @@ // Sets the name of this frame. virtual void SetName(const WebString&) = 0; + // Notifies this frame about a user activation from the browser side. + virtual void NotifyUserActivation() = 0; + // Hierarchy ---------------------------------------------------------- // Returns true if the current frame is a local root.
diff --git a/third_party/WebKit/public/web/WebRemoteFrame.h b/third_party/WebKit/public/web/WebRemoteFrame.h index 743d787..0302926 100644 --- a/third_party/WebKit/public/web/WebRemoteFrame.h +++ b/third_party/WebKit/public/web/WebRemoteFrame.h
@@ -110,6 +110,10 @@ // owner. virtual void WillEnterFullscreen() = 0; + // Mark the document for the corresponding LocalFrame as having received a + // user gesture. + virtual void SetHasReceivedUserGesture() = 0; + virtual void SetHasReceivedUserGestureBeforeNavigation(bool value) = 0; // Scrolls the given rectangle into view. This kicks off the recursive scroll
diff --git a/third_party/WebKit/public/web/remote_objects.mojom b/third_party/WebKit/public/web/remote_objects.mojom index 753c1fa..803acdea 100644 --- a/third_party/WebKit/public/web/remote_objects.mojom +++ b/third_party/WebKit/public/web/remote_objects.mojom
@@ -41,6 +41,16 @@ EXCEPTION_THROWN, }; +union RemoteInvocationResultValue { + double number_value; + bool boolean_value; + mojo_base.mojom.String16 string_value; + SingletonJavaScriptValue singleton_value; +}; + struct RemoteInvocationResult { RemoteInvocationError error = OK; + + // Must be set if |error == OK|. + RemoteInvocationResultValue? value; };
diff --git a/third_party/closure_compiler/externs/quick_unlock_private.js b/third_party/closure_compiler/externs/quick_unlock_private.js index 4d7dd15..4229b89e 100644 --- a/third_party/closure_compiler/externs/quick_unlock_private.js +++ b/third_party/closure_compiler/externs/quick_unlock_private.js
@@ -72,6 +72,18 @@ chrome.quickUnlockPrivate.getAuthToken = function(accountPassword, onComplete) {}; /** + * Sets the lock screen enabled state. NOTE: The lock enabled state is reflected + * in the settings.enable_screen_lock pref, which can be read but not written + * using the settings_private API (which also provides policy information). This + * API must be used to change the pref. + * @param {string} token The token returned by $(ref:getAuthToken). + * @param {boolean} enabled + * @param {function():void=} onComplete + * @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-setLockScreenEnabled + */ +chrome.quickUnlockPrivate.setLockScreenEnabled = function(token, enabled, onComplete) {}; + +/** * Returns the set of quick unlock modes that are available for the user to use. * Some quick unlock modes may be disabled by policy. * @param {function(!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>):void} @@ -119,10 +131,10 @@ * @param {!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>} modes The quick * unlock modes that should be active. * @param {!Array<string>} credentials The associated credential for each mode. - * To keep the credential the same for the associated mode, pass an empty - * string. + * To keep the credential the same for the associated mode, pass an + * empty string. * @param {function():void} onComplete Called with true if the quick unlock - * state was updated, false otherwise. The update is treated as a single + * state was updated, false otherwise. The update is treated as a single * atomic operation. * @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-setModes */
diff --git a/third_party/closure_compiler/interfaces/quick_unlock_private_interface.js b/third_party/closure_compiler/interfaces/quick_unlock_private_interface.js index fc885a5..e8a060e4 100644 --- a/third_party/closure_compiler/interfaces/quick_unlock_private_interface.js +++ b/third_party/closure_compiler/interfaces/quick_unlock_private_interface.js
@@ -24,6 +24,18 @@ getAuthToken: assertNotReached, /** + * Sets the lock screen enabled state. NOTE: The lock enabled state is + * reflected in the settings.enable_screen_lock pref, which can be read but + * not written using the settings_private API (which also provides policy + * information). This API must be used to change the pref. + * @param {string} token The token returned by $(ref:getAuthToken). + * @param {boolean} enabled + * @param {function():void=} onComplete + * @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-setLockScreenEnabled + */ + setLockScreenEnabled: assertNotReached, + + /** * Returns the set of quick unlock modes that are available for the user to * use. Some quick unlock modes may be disabled by policy. * @param {function(!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>):void} @@ -71,11 +83,11 @@ * @param {!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>} modes The quick * unlock modes that should be active. * @param {!Array<string>} credentials The associated credential for each - * mode. To keep the credential the same for the associated mode, pass an - * empty string. + * mode. To keep the credential the same for the associated mode, pass + * an empty string. * @param {function():void} onComplete Called with true if the quick unlock - * state was updated, false otherwise. The update is treated as a single - * atomic operation. + * state was updated, false otherwise. The update is treated as a + * single atomic operation. * @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-setModes */ setModes: assertNotReached,
diff --git a/third_party/feed/BUILD.gn b/third_party/feed/BUILD.gn index 245da84a..e43cd8e60 100644 --- a/third_party/feed/BUILD.gn +++ b/third_party/feed/BUILD.gn
@@ -28,7 +28,7 @@ "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelChild.java", "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelCursor.java", "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelFeature.java", - "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelMutator.java", + "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelMutation.java", "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelProvider.java", "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelProviderFactory.java", "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelProviderObserver.java", @@ -54,6 +54,7 @@ "src/src/main/java/com/google/android/libraries/feed/basicstream/BasicStream.java", "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/StreamActionApiImpl.java", "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/StreamRecyclerViewAdapter.java", + "src/src/main/java/com/google/android/libraries/feed/common/Committer.java", "src/src/main/java/com/google/android/libraries/feed/common/Consumer.java", "src/src/main/java/com/google/android/libraries/feed/common/DateUtils.java", "src/src/main/java/com/google/android/libraries/feed/common/Dumpable.java", @@ -65,11 +66,13 @@ "src/src/main/java/com/google/android/libraries/feed/common/protoextensions/FeedExtensionRegistry.java", "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProvider.java", "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProviderFactory.java", + "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ChildBinding.java", + "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ChildStructureMutation.java", "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/CursorProvider.java", "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/FeatureChangeImpl.java", "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelChildBinder.java", "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelCursorImpl.java", - "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelMutatorImpl.java", + "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelMutationImpl.java", "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/UpdatableModelChild.java", "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/UpdatableModelFeature.java", "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/UpdatableModelToken.java", @@ -94,7 +97,6 @@ "src/src/main/java/com/google/android/libraries/feed/host/imageloader/ImageLoaderApi.java", "src/src/main/java/com/google/android/libraries/feed/host/logging/LoggingApi.java", "src/src/main/java/com/google/android/libraries/feed/host/scheduler/SchedulerApi.java", - "src/src/main/java/com/google/android/libraries/feed/host/storage/CommitResult.java", "src/src/main/java/com/google/android/libraries/feed/host/storage/InMemoryJournalStorage.java", "src/src/main/java/com/google/android/libraries/feed/host/storage/InMemoryKeyValuePairStorage.java", "src/src/main/java/com/google/android/libraries/feed/host/storage/JournalMutation.java",
diff --git a/third_party/feed/README.chromium b/third_party/feed/README.chromium index b60a0ed..56a0cf4e 100644 --- a/third_party/feed/README.chromium +++ b/third_party/feed/README.chromium
@@ -2,7 +2,7 @@ Short name: feed URL: https://chromium.googlesource.com/feed Version: 0 -Revision: 0ff595791bd7e6316f8bae206090dd2583f2cf27 +Revision: 089c8e9316ed3a2afd631ba2b773f13e69121dc7 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/polymer/v1_0/bower.json b/third_party/polymer/v1_0/bower.json index 712548cd..ae1dbc2 100644 --- a/third_party/polymer/v1_0/bower.json +++ b/third_party/polymer/v1_0/bower.json
@@ -14,7 +14,7 @@ "iron-fit-behavior": "PolymerElements/iron-fit-behavior#2.1.0", "iron-flex-layout": "PolymerElements/iron-flex-layout#1.3.1", "iron-form-element-behavior": "PolymerElements/iron-form-element-behavior#1.0.6", - "iron-icon": "PolymerElements/iron-icon#1.0.10", + "iron-icon": "PolymerElements/iron-icon#2.0.1", "iron-iconset-svg": "PolymerElements/iron-iconset-svg#2.1.1", "iron-icons": "PolymerElements/iron-icons#2.0.1", "iron-input": "PolymerElements/iron-input#1.0.10",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-icon/bower.json b/third_party/polymer/v1_0/components-chromium/iron-icon/bower.json index d19a748..98243f5e 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-icon/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-icon/bower.json
@@ -1,7 +1,7 @@ { "name": "iron-icon", "private": true, - "version": "1.0.10", + "version": "2.0.1", "license": "http://polymer.github.io/LICENSE.txt", "description": "An element that supports displaying an icon", "main": "iron-icon.html", @@ -19,17 +19,41 @@ }, "ignore": [], "dependencies": { - "iron-flex-layout": "polymerelements/iron-flex-layout#^1.0.0", - "iron-meta": "polymerelements/iron-meta#^1.0.0", - "polymer": "Polymer/polymer#^1.1.0" + "iron-flex-layout": "PolymerElements/iron-flex-layout#1 - 2", + "iron-meta": "PolymerElements/iron-meta#1 - 2", + "polymer": "Polymer/polymer#1.9 - 2" }, "devDependencies": { - "test-fixture": "polymerelements/test-fixture#^1.0.0", - "promise-polyfill": "polymerlabs/promise-polyfill#^1.0.0", - "iron-iconset": "polymerelements/iron-iconset#^1.0.0", - "iron-icons": "polymerelements/iron-icons#^1.0.0", - "iron-component-page": "polymerelements/iron-component-page#^1.0.0", - "web-component-tester": "^4.0.0", - "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" + "promise-polyfill": "polymerlabs/promise-polyfill#1 - 2", + "iron-iconset": "PolymerElements/iron-iconset#1 - 2", + "iron-icons": "PolymerElements/iron-icons#1 - 2", + "iron-component-page": "polymerelements/iron-component-page#1 - 2", + "web-component-tester": "^6.0.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0", + "iron-demo-helpers": "PolymerElements/iron-demo-helpers#1 - 2" + }, + "variants": { + "1.x": { + "dependencies": { + "iron-flex-layout": "polymerelements/iron-flex-layout#^1.0.0", + "iron-meta": "polymerelements/iron-meta#^1.0.0", + "polymer": "Polymer/polymer#^1.9" + }, + "devDependencies": { + "promise-polyfill": "polymerlabs/promise-polyfill#^1.0.0", + "iron-iconset": "polymerelements/iron-iconset#^1.0.0", + "iron-icons": "polymerelements/iron-icons#^1.0.0", + "iron-component-page": "polymerelements/iron-component-page#^1.0.0", + "web-component-tester": "^4.0.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", + "iron-demo-helpers": "PolymerElements/iron-demo-helpers#^1.2.5" + }, + "resolutions": { + "webcomponentsjs": "^0.7" + } + } + }, + "resolutions": { + "webcomponentsjs": "^1.0.0" } }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-icon/iron-icon-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-icon/iron-icon-extracted.js index 1f61c65..874116dc 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-icon/iron-icon-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/iron-icon/iron-icon-extracted.js
@@ -9,8 +9,7 @@ * `iconset_name:icon_name`. */ icon: { - type: String, - observer: '_iconChanged' + type: String }, /** @@ -18,8 +17,7 @@ * iconset. */ theme: { - type: String, - observer: '_updateIcon' + type: String }, /** @@ -28,20 +26,25 @@ * precedence over a given icon attribute. */ src: { - type: String, - observer: '_srcChanged' + type: String }, /** * @type {!Polymer.IronMeta} */ _meta: { - value: Polymer.Base.create('iron-meta', {type: 'iconset'}), - observer: '_updateIcon' + value: Polymer.Base.create('iron-meta', {type: 'iconset'}) } }, + observers: [ + '_updateIcon(_meta, isAttached)', + '_updateIcon(theme, isAttached)', + '_srcChanged(src, isAttached)', + '_iconChanged(icon, isAttached)' + ], + _DEFAULT_ICONSET: 'icons', _iconChanged: function(icon) {
diff --git a/third_party/polymer/v1_0/components-chromium/iron-icon/iron-icon.html b/third_party/polymer/v1_0/components-chromium/iron-icon/iron-icon.html index f611bd0..df5dd36 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-icon/iron-icon.html +++ b/third_party/polymer/v1_0/components-chromium/iron-icon/iron-icon.html
@@ -84,8 +84,8 @@ <template> <style> :host { - @apply(--layout-inline); - @apply(--layout-center-center); + @apply --layout-inline; + @apply --layout-center-center; position: relative; vertical-align: middle; @@ -95,7 +95,11 @@ width: var(--iron-icon-width, 24px); height: var(--iron-icon-height, 24px); - @apply(--iron-icon); + @apply --iron-icon; + } + + :host([hidden]) { + display: none; } </style> </template>
diff --git a/third_party/polymer/v1_0/components_summary.txt b/third_party/polymer/v1_0/components_summary.txt index 7838082c..5506162f 100644 --- a/third_party/polymer/v1_0/components_summary.txt +++ b/third_party/polymer/v1_0/components_summary.txt
@@ -72,9 +72,9 @@ Name: iron-icon Repository: https://github.com/PolymerElements/iron-icon.git -Tree: v1.0.10 -Revision: f4e146da4982ff96bb25db85290c09e8de4ec734 -Tree link: https://github.com/PolymerElements/iron-icon/tree/v1.0.10 +Tree: v2.0.1 +Revision: bfdf82f7c8eb4c205cb2d4af6996ffc98f41b1c1 +Tree link: https://github.com/PolymerElements/iron-icon/tree/v2.0.1 Name: iron-icons Repository: https://github.com/PolymerElements/iron-icons.git
diff --git a/third_party/test_fonts/BUILD.gn b/third_party/test_fonts/BUILD.gn index 1008d98..1d92bcb 100644 --- a/third_party/test_fonts/BUILD.gn +++ b/third_party/test_fonts/BUILD.gn
@@ -9,9 +9,17 @@ "test_fonts/Arimo-BoldItalic.ttf", "test_fonts/Arimo-Italic.ttf", "test_fonts/Arimo-Regular.ttf", + "test_fonts/Cousine-Bold.ttf", + "test_fonts/Cousine-BoldItalic.ttf", + "test_fonts/Cousine-Italic.ttf", + "test_fonts/Cousine-Regular.ttf", "test_fonts/DejaVuSans-Bold.ttf", "test_fonts/DejaVuSans.ttf", "test_fonts/Garuda.ttf", + "test_fonts/Gelasio-Bold.ttf", + "test_fonts/Gelasio-BoldItalic.ttf", + "test_fonts/Gelasio-Italic.ttf", + "test_fonts/Gelasio-Regular.ttf", "test_fonts/Lohit-Devanagari.ttf", "test_fonts/Lohit-Gurmukhi.ttf", "test_fonts/Lohit-Tamil.ttf",
diff --git a/third_party/test_fonts/LICENSE b/third_party/test_fonts/LICENSE index 23256c1..50738f4 100644 --- a/third_party/test_fonts/LICENSE +++ b/third_party/test_fonts/LICENSE
@@ -1,4 +1,8 @@ The SIL OPEN FONT LICENSE applies to the following files: +Gelasio-Bold.ttf +Gelasio-BoldItalic.ttf +Gelasio-Italic.ttf +Gelasio-Regular.ttf Lohit-Devanagari.ttf Lohit-Gurmukhi.ttf Lohit-Tamil.ttf @@ -743,6 +747,10 @@ Arimo-BoldItalic.ttf Arimo-Italic.ttf Arimo-Regular.ttf +Cousine-Bold.ttf +Cousine-BoldItalic.ttf +Cousine-Italic.ttf +Cousine-Regular.ttf Tinos-Bold.ttf Tinos-BoldItalic.ttf Tinos-Italic.ttf
diff --git a/third_party/test_fonts/README.chromium b/third_party/test_fonts/README.chromium index 2da72e9..f93c4eb4 100644 --- a/third_party/test_fonts/README.chromium +++ b/third_party/test_fonts/README.chromium
@@ -40,8 +40,16 @@ Arimo-BoldItalic.ttf https://github.com/google/fonts/tree/master/apache/arimo Arimo-Italic.ttf https://github.com/google/fonts/tree/master/apache/arimo Arimo-Regular.ttf https://github.com/google/fonts/tree/master/apache/arimo +Cousine-Bold.ttf https://github.com/google/fonts/tree/master/apache/cousine +Cousine-BoldItalic.ttf https://github.com/google/fonts/tree/master/apache/cousine +Cousine-Italic.ttf https://github.com/google/fonts/tree/master/apache/cousine +Cousine-Regular.ttf https://github.com/google/fonts/tree/master/apache/cousine DejaVuSans.ttf https://dejavu-fonts.github.io/Download.html Garuda.ttf https://linux.thai.net/projects/fonts-tlwg +Gelasio-Bold.ttf https://fontlibrary.org/en/font/gelasio +Gelasio-BoldItalic.ttf https://fontlibrary.org/en/font/gelasio +Gelasio-Italic.ttf https://fontlibrary.org/en/font/gelasio +Gelasio-Regular.ttf https://fontlibrary.org/en/font/gelasio Lohit-Devanagari.ttf https://pagure.io/lohit Lohit-Gurmukhi.ttf https://pagure.io/lohit Lohit-Tamil.ttf https://pagure.io/lohit
diff --git a/third_party/test_fonts/test_fonts.tar.gz.sha1 b/third_party/test_fonts/test_fonts.tar.gz.sha1 index 9a1b2230..1ecedbc 100644 --- a/third_party/test_fonts/test_fonts.tar.gz.sha1 +++ b/third_party/test_fonts/test_fonts.tar.gz.sha1
@@ -1 +1 @@ -e494bc9cb34c0dd6629fb783acb7e8bff422a8dd \ No newline at end of file +2c437fdc6f6ff8db8737d29bf32351985a9e102c \ No newline at end of file
diff --git a/third_party/widevine/cdm/BRANDING b/third_party/widevine/cdm/BRANDING deleted file mode 100644 index de89794..0000000 --- a/third_party/widevine/cdm/BRANDING +++ /dev/null
@@ -1,3 +0,0 @@ -PRODUCT_FULLNAME=Widevine Content Decryption Module Adapter -PRODUCT_SHORTNAME=Widevine CDM Adapter -PRODUCT_DESCRIPTION=Widevine Content Decryption Module Adapter enables the Widevine CDM to be used by Chrome.
diff --git a/third_party/widevine/cdm/BUILD.gn b/third_party/widevine/cdm/BUILD.gn index b5e3d54..bf66c97e 100644 --- a/third_party/widevine/cdm/BUILD.gn +++ b/third_party/widevine/cdm/BUILD.gn
@@ -4,9 +4,7 @@ import("//build/config/chrome_build.gni") import("//build/config/features.gni") -import("//chrome/process_version_rc_template.gni") import("//media/cdm/library_cdm/cdm_paths.gni") -import("//media/cdm/library_cdm/ppapi_cdm_adapter.gni") import("//media/media_options.gni") import("//third_party/widevine/cdm/widevine.gni") @@ -55,8 +53,9 @@ widevine_cdm_version_h_file = "widevine_cdm_version.h" } } else if (enable_widevine) { + # TODO(crbug.com/349182): Remove after we replace WIDEVINE_CDM_AVAILABLE with + # ENABLE_WIDEVINE build flag. widevine_cdm_version_h_file = "stub/widevine_cdm_version.h" - widevine_cdm_manifest_file = [ "stub/manifest.json" ] } else { # No branding, use the default one. widevine_cdm_version_h_file = "widevine_cdm_version.h" @@ -84,52 +83,9 @@ public_deps = [ ":version_h", # Forward permission to use version header. "//media:media_features", - "//ppapi/features", ] } -if (widevine_cdm_binary_files != []) { - copy("widevinecdm") { - sources = widevine_cdm_binary_files - outputs = [ - "$root_out_dir/$widevine_cdm_path/{{source_file_part}}", - ] - - # TODO(jrummell) - # 'COPY_PHASE_STRIP': 'NO', - } -} else if (enable_widevine && enable_library_cdms) { - assert(!is_chrome_branded, "Branded Chrome should have binary files to copy.") - assert(!is_android, "Android should not have enable_library_cdms.") - shared_library("widevinecdm") { - output_dir = "$root_out_dir/$widevine_cdm_path" - sources = [ - "//media/cdm/stub/stub_cdm.cc", - "//media/cdm/stub/stub_cdm.h", - ] - - defines = [ "CDM_IMPLEMENTATION" ] - - deps = [ - ":version_h", - "//base", - "//build/config:exe_and_shlib_deps", - ] - - if (is_posix && !is_mac) { - cflags = [ "-fvisibility=hidden" ] - } - - if (is_mac) { - ldflags = [ "-Wl,-install_name,@loader_path/libwidevinecdm.dylib" ] - } - } -} else { - group("widevinecdm") { - # NOP - } -} - if (widevine_cdm_manifest_file != []) { copy("widevine_cdm_manifest") { sources = widevine_cdm_manifest_file @@ -143,50 +99,29 @@ } } -if ((is_chrome_branded || enable_widevine) && enable_library_cdms) { - # Produce and compile the .rc file. - process_version_rc_template("widevinecdmadapter_resources") { - visibility = [ ":*" ] - sources = [ - "BRANDING", - "widevinecdmadapter.ver", - ] - output = "$target_gen_dir/widevinecdmadapter_version.rc" - } - - ppapi_cdm_adapter("widevinecdmadapter") { - defines = [] - output_dir = "$root_out_dir/$widevine_cdm_path" - deps = [ - ":version_h", - ":widevinecdm", - ":widevinecdmadapter_resources", - ] - data_deps = [ - ":widevine_cdm_manifest", - ":widevinecdm", +if (widevine_cdm_binary_files != []) { + copy("widevine_cdm_binary") { + sources = widevine_cdm_binary_files + outputs = [ + "$root_out_dir/$widevine_cdm_path/{{source_file_part}}", ] - if (is_linux) { - ldflags = - [ rebase_path("$root_out_dir/$widevine_cdm_path/libwidevinecdm.so", - root_build_dir) ] - } else if (is_win) { - ldflags = - [ rebase_path("$root_out_dir/$widevine_cdm_path/widevinecdm.dll.lib", - root_build_dir) ] - } else if (is_mac) { - ldflags = - [ rebase_path("$root_out_dir/$widevine_cdm_path/libwidevinecdm.dylib", - root_build_dir) ] - } + # TODO(jrummell) + # 'COPY_PHASE_STRIP': 'NO', } } else { - # Placeholder when we're not compiling the adapter. - group("widevinecdmadapter") { + group("widevine_cdm_binary") { + # NOP } } +group("cdm") { + public_deps = [ + ":widevine_cdm_binary", + ":widevine_cdm_manifest", + ] +} + # This target exists for tests to depend on that pulls in a runtime dependency # on the license server. source_set("widevine_test_license_server") {
diff --git a/third_party/widevine/cdm/stub/manifest.json b/third_party/widevine/cdm/stub/manifest.json deleted file mode 100644 index d466ccd..0000000 --- a/third_party/widevine/cdm/stub/manifest.json +++ /dev/null
@@ -1,29 +0,0 @@ -{ - "manifest_version": 2, - "name": "WidevineCdm", - "description": "Widevine Content Decryption Module Stub", - "offline_enabled": false, - "version": "0.0.0.000", - "minimum_chrome_version": "54.0.0.0", - "x-cdm-module-versions": "4", - "x-cdm-interface-versions": "8", - "x-cdm-host-versions": "8", - "x-cdm-codecs": "vp8,vp9.0,avc1", - "platforms": [ - { - "os": "win", - "arch": "x86", - "sub_package_path": "_platform_specific/win_x86/" - }, - { - "os": "win", - "arch": "x64", - "sub_package_path": "_platform_specific/win_x64/" - }, - { - "os": "mac", - "arch": "x64", - "sub_package_path": "_platform_specific/mac_x64/" - } - ] -}
diff --git a/third_party/widevine/cdm/widevine.gni b/third_party/widevine/cdm/widevine.gni index 78695ef..82a9362 100644 --- a/third_party/widevine/cdm/widevine.gni +++ b/third_party/widevine/cdm/widevine.gni
@@ -2,11 +2,20 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chrome_build.gni") +import("//media/media_options.gni") + declare_args() { - # Allow widevinecdmadapter to be built in Chromium. + # Allow Widevine key system support in Chromium. enable_widevine = false } +enable_widevine_cdm_host_verification = + (is_chrome_branded || enable_widevine) && enable_cdm_host_verification + +# Only bundle Widevine CDM in Google Chrome builds. +should_bundle_widevine_cdm = is_chrome_branded && enable_library_cdms + template("widevine_sign_file") { # For official builds, generate a signature file for |file| which will # be used by Widevine. If |signature_file| is not specified, the signature
diff --git a/third_party/widevine/cdm/widevinecdmadapter.ver b/third_party/widevine/cdm/widevinecdmadapter.ver deleted file mode 100644 index c0897720..0000000 --- a/third_party/widevine/cdm/widevinecdmadapter.ver +++ /dev/null
@@ -1,2 +0,0 @@ -INTERNAL_NAME=widevinecdmadapter_dll -ORIGINAL_FILENAME=widevinecdmadapter.dll
diff --git a/tools/bisect_repackage/bisect_repackage.py b/tools/bisect_repackage/bisect_repackage.py index 77e91e6..fd169ca 100644 --- a/tools/bisect_repackage/bisect_repackage.py +++ b/tools/bisect_repackage/bisect_repackage.py
@@ -47,7 +47,6 @@ 'icudtl.dat', 'libclearkeycdm.so', 'libwidevinecdm.so', - 'libwidevinecdmadapter.so', 'locales/', 'nacl_helper', 'nacl_helper_bootstrap',
diff --git a/tools/fuchsia/local-sdk.py b/tools/fuchsia/local-sdk.py index d9c842f4..cb3bb24 100755 --- a/tools/fuchsia/local-sdk.py +++ b/tools/fuchsia/local-sdk.py
@@ -34,13 +34,13 @@ def BuildForArch(arch): Run('scripts/build-zircon.sh', '-t', arch) Run('build/gn/gen.py', '--target_cpu=' + arch, - '--packages=garnet/packages/sdk', '--release') + '--packages=garnet/packages/sdk/base', '--release') Run('buildtools/ninja', '-C', 'out/release-' + arch) # Also build the deprecated bootfs-based image. # TODO(crbug.com/805057): Remove this once the bootfs path is turned down. build_dir_bootfs = 'out/release-' + arch + '-bootfs' Run('build/gn/gen.py', '--target_cpu=' + arch, - '--packages=garnet/packages/sdk_bootfs', '--release', + '--packages=garnet/packages/sdk/bootfs', '--release', '--args=bootfs_packages=true', '--build-dir='+build_dir_bootfs) Run('buildtools/ninja', '-C', build_dir_bootfs)
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index a1f7cc4..064a568 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -1381,6 +1381,7 @@ </action> <action name="Android.ChromeHome.OpenedByExpandButton"> + <obsolete>Unused as of 03/2018</obsolete> <owner>mdjones@chromium.org</owner> <owner>twellington@chromium.org</owner> <description> @@ -1389,6 +1390,7 @@ </action> <action name="Android.ChromeHome.OpenedByNTP"> + <obsolete>Unused as of 03/2018</obsolete> <owner>mdjones@chromium.org</owner> <owner>twellington@chromium.org</owner> <description> @@ -1397,6 +1399,7 @@ </action> <action name="Android.ChromeHome.OpenedByOmnibox"> + <obsolete>Unused as of 03/2018</obsolete> <owner>mdjones@chromium.org</owner> <owner>twellington@chromium.org</owner> <description> @@ -1405,6 +1408,7 @@ </action> <action name="Android.ChromeHome.OpenedByStartup"> + <obsolete>Unused as of 03/2018</obsolete> <owner>thildebr@chromium.org</owner> <description> The Chrome Home bottom sheet was automatically opened on startup after a @@ -11616,6 +11620,13 @@ </description> </action> +<action name="MobileDownloadRetryDownload"> + <owner>eugenebut@chromium.org</owner> + <description> + User attempted to retry downloading a file after the download failed. + </description> +</action> + <action name="MobileExternalNavigationDispatched"> <owner>mariakhomenko@chromium.org</owner> <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 1493c3e3..a1ca182b 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -1199,6 +1199,9 @@ </enum> <enum name="AppListEnableSource"> + <obsolete> + Deprecated 03/2018 with Mash AppList refactoring. + </obsolete> <int value="0" label="Not enabled (should never be recorded)"/> <int value="1" label="Packaged app installed from Web Store"/> <int value="2" label="Clicked app launcher link from the Web Store"/> @@ -14812,6 +14815,7 @@ <int value="1226" label="WEBRTCLOGGINGPRIVATE_STARTEVENTLOGGING"/> <int value="1227" label="VIRTUALKEYBOARDPRIVATE_SETCONTAINERBEHAVIOR"/> <int value="1228" label="QUICKUNLOCKPRIVATE_GETAUTHTOKEN"/> + <int value="1229" label="QUICKUNLOCKPRIVATE_SETLOCKSCREENENABLED"/> </enum> <enum name="ExtensionIconState"> @@ -23392,6 +23396,8 @@ <int value="61" label="SETUP_SINGLETON_RELEASED"/> <int value="62" label="DELETE_OLD_VERSIONS_SUCCESS"/> <int value="63" label="DELETE_OLD_VERSIONS_TOO_MANY_ATTEMPTS"/> + <int value="64" label="SAVE_DMTOKEN_FAILED"/> + <int value="65" label="SAVE_DMTOKEN_SUCCESS"/> </enum> <enum name="InstanceIDResult">
diff --git a/tools/metrics/histograms/extract_histograms.py b/tools/metrics/histograms/extract_histograms.py index 7c080e0a..c18e4ab 100644 --- a/tools/metrics/histograms/extract_histograms.py +++ b/tools/metrics/histograms/extract_histograms.py
@@ -54,9 +54,10 @@ """ import bisect -import datetime import copy +import datetime import logging +import re import xml.dom.minidom OWNER_FIELD_PLACEHOLDER = ( @@ -67,8 +68,8 @@ DEFAULT_BASE_HISTOGRAM_OBSOLETE_REASON = ( 'Base histogram. Use suffixes of this histogram instead.') -EXPIRY_DATE_PATTERN = "%Y/%m/%d" - +EXPIRY_DATE_PATTERN = "%Y-%m-%d" +EXPIRY_MILESTONE_RE = re.compile(r'M[0-9]{2,3}\Z') class Error(Exception): pass @@ -253,13 +254,13 @@ def _ValidateDateString(date_str): - """Check if |date_str| matches 'YYYY/MM/DD'. + """Check if |date_str| matches 'YYYY-MM-DD'. Args: date_str: string Returns: - True iff |date_str| matches 'YYYY/MM/DD' format. + True iff |date_str| matches 'YYYY-MM-DD' format. """ try: _ = datetime.datetime.strptime(date_str, EXPIRY_DATE_PATTERN).date() @@ -267,6 +268,9 @@ return False return True +def _ValidateMilestoneString(milestone_str): + """Check if |milestone_str| matches 'M*'.""" + return EXPIRY_MILESTONE_RE.match(milestone_str) is not None def _ProcessBaseHistogramAttribute(node, histogram_entry): if node.hasAttribute('base'): @@ -296,15 +300,17 @@ continue histograms[name] = histogram_entry = {} - # Handle expiry dates. - if histogram.hasAttribute('expiry_date'): - expiry_date_str = histogram.getAttribute('expiry_date') - if _ValidateDateString(expiry_date_str): - histogram_entry['expiry_date'] = expiry_date_str + # Handle expiry attribute. + if histogram.hasAttribute('expires_after'): + expiry_str = histogram.getAttribute('expires_after') + if _ValidateMilestoneString(expiry_str) or _ValidateDateString( + expiry_str): + histogram_entry['expires_after'] = expiry_str else: logging.error( - 'Expiry date of histogram %s does not match expected format: "%s",' - ' found %s.', name, EXPIRY_DATE_PATTERN, expiry_date_str) + 'Expiry of histogram %s does not match expected date format: "%s"' + ' or milestone format: M* found %s.', name, EXPIRY_DATE_PATTERN, + expiry_str) have_errors = True # Find <owner> tag.
diff --git a/tools/metrics/histograms/generate_expired_histograms_array.py b/tools/metrics/histograms/generate_expired_histograms_array.py index 9ce33a0..bbf283f 100755 --- a/tools/metrics/histograms/generate_expired_histograms_array.py +++ b/tools/metrics/histograms/generate_expired_histograms_array.py
@@ -14,7 +14,9 @@ import extract_histograms import merge_xml -_DATE_FILE_PATTERN = r".*MAJOR_BRANCH_DATE=(.+).*" +_DATE_FILE_RE = re.compile(r".*MAJOR_BRANCH_DATE=(.+).*") +_CURRENT_MILESTONE_RE = re.compile(r"MAJOR=([0-9]{2,3})\n") +_MILESTONE_EXPIRY_RE = re.compile(r"\AM([0-9]{2,3})") _SCRIPT_NAME = "generate_expired_histograms_array.py" _HASH_DATATYPE = "uint64_t" @@ -39,13 +41,15 @@ #endif // {include_guard} """ +_DATE_FORMAT_ERROR = "Unable to parse expiry {date} in histogram {name}." + class Error(Exception): pass -def _GetExpiredHistograms(histograms, base_date): - """Filters histograms to find expired ones. +def _GetExpiredHistograms(histograms, base_date, current_milestone): + """Filters histograms to find expired ones if date format is used. Args: histograms(Dict[str, Dict]): Histogram descriptions in the form @@ -60,39 +64,53 @@ """ expired_histograms_names = [] for name, content in histograms.items(): - if "obsolete" in content or "expiry_date" not in content: + if "obsolete" in content or "expires_after" not in content: continue - expiry_date_str = content["expiry_date"] - try: - expiry_date = datetime.datetime.strptime( - expiry_date_str, extract_histograms.EXPIRY_DATE_PATTERN).date() - except ValueError: - raise Error("Unable to parse expiry date {date} in histogram {name}.". - format(date=expiry_date_str, name=name)) - if expiry_date < base_date: - expired_histograms_names.append(name) + expiry_str = content["expires_after"] + + match = _MILESTONE_EXPIRY_RE.search(expiry_str) + if match: + # if there is match then expiry is in Chrome milsetone format. + if int(match.group(1)) < current_milestone: + expired_histograms_names.append(name) + else: + # if no match then we try the date format. + try: + expiry_date = datetime.datetime.strptime( + expiry_str, extract_histograms.EXPIRY_DATE_PATTERN).date() + except ValueError: + raise Error(_DATE_FORMAT_ERROR. + format(date=expiry_str, name=name)) + if expiry_date < base_date: + expired_histograms_names.append(name) return expired_histograms_names -def _GetBaseDate(content, pattern): +def _FindMatch(content, regex, group_num): + match_result = regex.search(content) + if not match_result: + raise Error("Unable to match {pattern} with provided content: {content}". + format(pattern=regex.pattern, content=content)) + return match_result.group(group_num) + + +def _GetBaseDate(content, regex): """Fetches base date from |content| to compare expiry dates with. Args: content: A string with the base date. - pattern(str): A regular expression that matches the base date. + regex: A regular expression object that matches the base date. Returns: A base date as datetime.date object. Raises: - Error if |content| doesn't match |pattern| or the matched date has invalid + Error if |content| doesn't match |regex| or the matched date has invalid format. """ - match_result = re.search(pattern, content) - if not match_result: - raise Error("Unable to match {pattern} with provided content: {content}". - format(pattern=pattern, content=content)) - base_date_str = match_result.group(1) + base_date_str = _FindMatch(content, regex, 1) + if not base_date_str: + return None try: base_date = datetime.datetime.strptime( base_date_str, extract_histograms.EXPIRY_DATE_PATTERN).date() @@ -102,6 +120,22 @@ format(date=base_date_str, content=content)) +def _GetCurrentMilestone(content, regex): + """Extracts current milestone from |content|. + + Args: + content: A string with the version information. + regex: A regular expression object that matches milestone. + + Returns: + A milestone as int. + + Raises: + Error if |content| doesn't match |regex|. + """ + return int(_FindMatch(content, regex, 1)) + + def _HashName(name): """Returns hash for the given histogram |name|.""" return "0x" + hashlib.md5(name).hexdigest()[:16] @@ -122,7 +156,6 @@ Args: header_filename: A filename of the generated header file. namespace: A namespace to contain generated array. - hash_datatype: Datatype of histogram names' hash. histograms_map(Dict[str, str]): A dictionary {hash: histogram_name}. Returns: @@ -153,8 +186,9 @@ arguments.inputs: A list of xml files with histogram descriptions. arguments.header_filename: A filename of the generated header file. arguments.namespace: A namespace to contain generated array. - arguments.hash_datatype: Datatype of histogram names' hash. arguments.output_dir: A directory to put the generated file. + arguments.major_branch_date_filepath: File path for base date. + arguments.milestone_filepath: File path for milestone information. Raises: Error if there is an error in input xml files. @@ -166,8 +200,13 @@ raise Error("Error parsing inputs.") with open(arguments.major_branch_date_filepath, "r") as date_file: file_content = date_file.read() - base_date = _GetBaseDate(file_content, _DATE_FILE_PATTERN) - expired_histograms_names = _GetExpiredHistograms(histograms, base_date) + base_date = _GetBaseDate(file_content, _DATE_FILE_RE) + with open(arguments.milestone_filepath, "r") as milestone_file: + file_content = milestone_file.read() + current_milestone = _GetCurrentMilestone(file_content, _CURRENT_MILESTONE_RE) + + expired_histograms_names = _GetExpiredHistograms( + histograms, base_date, current_milestone) expired_histograms_map = _GetHashToNameMap(expired_histograms_names) header_file_content = _GenerateHeaderFileContent( arguments.header_filename, arguments.namespace, @@ -200,9 +239,14 @@ arg_parser.add_argument( "--major_branch_date_filepath", "-d", - default="", + required=True, help="A path to the file with the base date.") arg_parser.add_argument( + "--milestone_filepath", + "-m", + required=True, + help="A path to the file with the milestone information.") + arg_parser.add_argument( "inputs", nargs="+", help="Paths to .xml files with histogram descriptions.")
diff --git a/tools/metrics/histograms/generate_expired_histograms_array_unittest.py b/tools/metrics/histograms/generate_expired_histograms_array_unittest.py index cee1c13..7747d88 100644 --- a/tools/metrics/histograms/generate_expired_histograms_array_unittest.py +++ b/tools/metrics/histograms/generate_expired_histograms_array_unittest.py
@@ -47,73 +47,86 @@ def testGetExpiredHistograms(self): histograms = { "FirstHistogram": { - "expiry_date": "2000/10/01" + "expires_after": "2000-10-01" }, "SecondHistogram": { - "expiry_date": "2002/10/01" + "expires_after": "2002-10-01" }, "ThirdHistogram": { - "expiry_date": "2001/10/01" + "expires_after": "2001-10-01" }, "FourthHistogram": {}, "FifthHistogram": { "obsolete": "Has expired.", - "expiry_date": "2000/10/01" - } + "expires_after": "2000-10-01" + }, + "SixthHistogram": { + "expires_after": "M22" + }, + "SeventhHistogram": { + "expires_after": "M60" + }, + "EigthHistogram": { + "expires_after": "M65" + }, } base_date = datetime.date(2001, 10, 1) + current_milestone = 60 expired_histograms_names = ( generate_expired_histograms_array._GetExpiredHistograms( - histograms, base_date)) + histograms, base_date, current_milestone)) - self.assertEqual(expired_histograms_names, ["FirstHistogram"]) + self.assertEqual(2, len(expired_histograms_names)) + self.assertIn("FirstHistogram", expired_histograms_names) + self.assertIn("SixthHistogram", expired_histograms_names) def testBadExpiryDate(self): histograms = { "FirstHistogram": { - "expiry_date": "2000/10/01" + "expires_after": "2000-10-01" }, "SecondHistogram": { - "expiry_date": "2000-10-01" - }, + "expires_after": "2000/10/01" + } } base_date = datetime.date(2000, 10, 01) + current_milestone = 60 with self.assertRaises(generate_expired_histograms_array.Error) as error: generate_expired_histograms_array._GetExpiredHistograms(histograms, - base_date) + base_date, current_milestone) self.assertEqual( - "Unable to parse expiry date 2000-10-01 in histogram SecondHistogram.", - str(error.exception)) + generate_expired_histograms_array._DATE_FORMAT_ERROR.format( + date="2000/10/01", name="SecondHistogram"), str(error.exception)) def testGetBaseDate(self): - pattern = generate_expired_histograms_array._DATE_FILE_PATTERN + regex = generate_expired_histograms_array._DATE_FILE_RE # Does not match the pattern. - content = "MAJOR_BRANCH__FAKE_DATE=2017/09/09" + content = "MAJOR_BRANCH__FAKE_DATE=2017-09-09" with self.assertRaises(generate_expired_histograms_array.Error): - generate_expired_histograms_array._GetBaseDate(content, pattern) + generate_expired_histograms_array._GetBaseDate(content, regex) # Has invalid format. - content = "MAJOR_BRANCH_DATE=2010-01-01" + content = "MAJOR_BRANCH_DATE=2010/01/01" with self.assertRaises(generate_expired_histograms_array.Error): - generate_expired_histograms_array._GetBaseDate(content, pattern) + generate_expired_histograms_array._GetBaseDate(content, regex) # Has invalid format. - content = "MAJOR_BRANCH_DATE=2010/20/02" + content = "MAJOR_BRANCH_DATE=2010-20-02" with self.assertRaises(generate_expired_histograms_array.Error): - generate_expired_histograms_array._GetBaseDate(content, pattern) + generate_expired_histograms_array._GetBaseDate(content, regex) # Has invalid date. - content = "MAJOR_BRANCH_DATE=2017/02/29" + content = "MAJOR_BRANCH_DATE=2017-02-29" with self.assertRaises(generate_expired_histograms_array.Error): - generate_expired_histograms_array._GetBaseDate(content, pattern) + generate_expired_histograms_array._GetBaseDate(content, regex) - content = "!!FOO!\nMAJOR_BRANCH_DATE=2010/01/01\n!FOO!!" - base_date = generate_expired_histograms_array._GetBaseDate(content, pattern) + content = "!!FOO!\nMAJOR_BRANCH_DATE=2010-01-01\n!FOO!!" + base_date = generate_expired_histograms_array._GetBaseDate(content, regex) self.assertEqual(base_date, datetime.date(2010, 01, 01)) def testGenerateHeaderFileContent(self):
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index e564e12..4b3ce9e 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -2214,6 +2214,9 @@ </histogram> <histogram name="Apps.AppListHowEnabled" enum="AppListEnableSource"> + <obsolete> + Deprecated 03/2018 with Mash AppList refactoring. + </obsolete> <owner>tapted@chromium.org</owner> <summary> The trigger that caused the app list to be enabled. Recorded when the user @@ -12213,6 +12216,16 @@ </summary> </histogram> +<histogram name="ContextMenu.UnexpectedFindElementResultHandlerMessage" + enum="BooleanHit"> + <owner>michaeldo@chromium.org</owner> + <summary> + Logged when an unexpected FindElementResultHandler message was received by + the application. An unexpected message may be sent by a malicious frame. + Only logged on iOS. + </summary> +</histogram> + <histogram name="Cookie.AgeForNonSecureCrossSiteRequest" units="days"> <owner>mkwst@chromium.org</owner> <summary> @@ -27237,6 +27250,9 @@ </histogram> <histogram name="GCM.ConnectedViaProxy" enum="Boolean"> + <obsolete> + Deprecated as of 03/2018 (M67). + </obsolete> <owner>zea@chromium.org</owner> <summary>Whether the GCM connection was made via a proxy or not.</summary> </histogram> @@ -87324,6 +87340,9 @@ </histogram> <histogram name="Startup.AppListFirstPaintColdStart" units="ms"> + <obsolete> + Deprecated 03/2018 with Mash AppList refactoring. + </obsolete> <owner>tapted@chromium.org</owner> <summary> Time for a newly created browser process to perform the first paint of the @@ -87333,6 +87352,9 @@ </histogram> <histogram name="Startup.AppListFirstPaintWarmStart" units="ms"> + <obsolete> + Deprecated 03/2018 with Mash AppList refactoring. + </obsolete> <owner>tapted@chromium.org</owner> <summary> Time for a running browser process to perform the first paint of the app @@ -104500,6 +104522,9 @@ </histogram_suffixes> <histogram_suffixes name="AppListFirstPaintWarmStartFast" separator=""> + <obsolete> + Deprecated 03/2018 with Mash AppList refactoring. + </obsolete> <suffix name="" label="Normal start."/> <suffix name="Fast" label="Fast start by skipping normal chrome.dll startup."/> @@ -106817,6 +106842,13 @@ <histogram_suffixes name="DrawQuadsType" separator="."> <suffix name="" label=""/> + <suffix name="Removed" + label="Captures only draw quads that have removed by draw occlusion."> + <obsolete> + Deprecated as of 03/2018. We'd learned enough from this metric and it + made no sense to keep it around. + </obsolete> + </suffix> <suffix name="Resized" label="Captures only draw quads that have changed size by draw occlusion.">
diff --git a/tools/metrics/histograms/print_style.py b/tools/metrics/histograms/print_style.py index ecf9a6f..218d1d6 100644 --- a/tools/metrics/histograms/print_style.py +++ b/tools/metrics/histograms/print_style.py
@@ -19,7 +19,7 @@ 'details': [], 'enum': ['name'], 'enums': [], - 'histogram': ['base', 'name', 'enum', 'units', 'expiry_date'], + 'histogram': ['base', 'name', 'enum', 'units', 'expires_after'], 'histogram-configuration': ['logsource'], 'histogram_suffixes': ['name', 'separator', 'ordering'], 'histogram_suffixes_list': [],
diff --git a/tools/roll_angle.py b/tools/roll_angle.py index 8928d08..4edc342bf 100755 --- a/tools/roll_angle.py +++ b/tools/roll_angle.py
@@ -18,11 +18,11 @@ "buildernames": ["win_optional_gpu_tests_rel"] }, { - "mastername": "master.tryserver.chromium.mac", + "mastername": "luci.chromium.try", "buildernames": ["mac_optional_gpu_tests_rel"] }, { - "mastername": "master.tryserver.chromium.linux", + "mastername": "luci.chromium.try", "buildernames": ["linux_optional_gpu_tests_rel"] }, {
diff --git a/tools/roll_swiftshader.py b/tools/roll_swiftshader.py index 5b4dd0e..3a938a8 100755 --- a/tools/roll_swiftshader.py +++ b/tools/roll_swiftshader.py
@@ -18,13 +18,16 @@ "buildernames": ["win_optional_gpu_tests_rel"] }, { - "mastername": "master.tryserver.chromium.mac", + "mastername": "luci.chromium.try", "buildernames": ["mac_optional_gpu_tests_rel"] }, { + "mastername": "luci.chromium.try", + "buildernames": ["linux_optional_gpu_tests_rel"] + }, + { "mastername": "master.tryserver.chromium.linux", - "buildernames": ["linux_optional_gpu_tests_rel", - "linux_chromium_cfi_rel_ng"] + "buildernames": ["linux_chromium_cfi_rel_ng"] }, { "mastername": "master.tryserver.chromium.android",
diff --git a/tools/roll_webgl_conformance.py b/tools/roll_webgl_conformance.py index f0fad65..bdc9988 100755 --- a/tools/roll_webgl_conformance.py +++ b/tools/roll_webgl_conformance.py
@@ -18,11 +18,11 @@ "buildernames": ["win_optional_gpu_tests_rel"] }, { - "mastername": "master.tryserver.chromium.mac", + "mastername": "luci.chromium.try", "buildernames": ["mac_optional_gpu_tests_rel"] }, { - "mastername": "master.tryserver.chromium.linux", + "mastername": "luci.chromium.try", "buildernames": ["linux_optional_gpu_tests_rel"] }, { @@ -32,7 +32,7 @@ # Include the ANGLE tryservers which run the WebGL conformance tests # in some non-default configurations. { - "mastername": "master.tryserver.chromium.angle", + "mastername": "luci.chromium.try", "buildernames": ["linux_angle_rel_ng"] }, {
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index a4ca6ad..9a5f703b 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -1044,6 +1044,8 @@ if (is_mac) { mac_framework_bundle("ui_unittests_framework") { testonly = true + framework_version = "U" + framework_contents = [ "Resources" ] deps = [ "//ui/resources:ui_test_pak_bundle_data", ]
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 5cfe98e6..1233687 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -113,8 +113,7 @@ device_scale_factor_(1.0f), cache_render_surface_requests_(0), deferred_paint_requests_(0), - trilinear_filtering_request_(0), - weak_ptr_factory_(this) { + trilinear_filtering_request_(0) { CreateCcLayer(); } @@ -141,8 +140,7 @@ device_scale_factor_(1.0f), cache_render_surface_requests_(0), deferred_paint_requests_(0), - trilinear_filtering_request_(0), - weak_ptr_factory_(this) { + trilinear_filtering_request_(0) { CreateCcLayer(); } @@ -630,7 +628,7 @@ DCHECK(child->cc_layer_); cc_layer_->AddChild(child->cc_layer_); } - cc_layer_->SetLayerClient(weak_ptr_factory_.GetWeakPtr()); + cc_layer_->SetLayerClient(this); cc_layer_->SetTransformOrigin(gfx::Point3F()); cc_layer_->SetContentsOpaque(fills_bounds_opaquely_); cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN); @@ -1265,7 +1263,7 @@ cc_layer_->SetTransformOrigin(gfx::Point3F()); cc_layer_->SetContentsOpaque(true); cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN); - cc_layer_->SetLayerClient(weak_ptr_factory_.GetWeakPtr()); + cc_layer_->SetLayerClient(this); cc_layer_->SetElementId(cc::ElementId(cc_layer_->id())); RecomputePosition(); }
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index 5a0eb3f..5127e11 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h
@@ -14,7 +14,6 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "base/observer_list.h" #include "cc/base/region.h" @@ -624,8 +623,6 @@ // layer. unsigned trilinear_filtering_request_; - base::WeakPtrFactory<Layer> weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(Layer); };
diff --git a/ui/events/ozone/device/device_manager_manual.cc b/ui/events/ozone/device/device_manager_manual.cc index 8010870a..0504b5e 100644 --- a/ui/events/ozone/device/device_manager_manual.cc +++ b/ui/events/ozone/device/device_manager_manual.cc
@@ -17,11 +17,11 @@ namespace { -const char kDevInput[] = "/dev/input"; +const base::FilePath::CharType kDevInput[] = FILE_PATH_LITERAL("/dev/input"); void ScanDevicesOnWorkerThread(std::vector<base::FilePath>* result) { - base::FileEnumerator file_enum(base::FilePath(FILE_PATH_LITERAL(kDevInput)), - false, base::FileEnumerator::FILES, + base::FileEnumerator file_enum(base::FilePath(kDevInput), false, + base::FileEnumerator::FILES, FILE_PATH_LITERAL("event*[0-9]")); for (base::FilePath path = file_enum.Next(); !path.empty(); path = file_enum.Next()) { @@ -58,7 +58,7 @@ } void DeviceManagerManual::StartWatching() { - if (!watcher_.Watch(base::FilePath(FILE_PATH_LITERAL(kDevInput)), false, + if (!watcher_.Watch(base::FilePath(kDevInput), false, base::Bind(&DeviceManagerManual::OnWatcherEvent, weak_ptr_factory_.GetWeakPtr()))) { LOG(ERROR) << "Failed to start FilePathWatcher";
diff --git a/ui/gfx/OWNERS b/ui/gfx/OWNERS index ad40b66f..e73caf84 100644 --- a/ui/gfx/OWNERS +++ b/ui/gfx/OWNERS
@@ -20,6 +20,9 @@ per-file interpolated_transform*=danakj@chromium.org per-file interpolated_transform*=vollick@chromium.org +# Skia geometry helpers. +per-file skia_util*=danakj@chromium.org + # GPU memory buffer and GpuFence interfaces. per-file gpu_fence*=reveman@chromium.org per-file gpu_memory_buffer*=reveman@chromium.org
diff --git a/ui/gfx/color_space.cc b/ui/gfx/color_space.cc index 77458c9..6ef4a870 100644 --- a/ui/gfx/color_space.cc +++ b/ui/gfx/color_space.cc
@@ -835,18 +835,16 @@ } // BT2020_CL is a special case. - // Basically we return a matrix that transforms RGB values - // to RYB values. (We replace the green component with the - // the luminance.) Later steps will compute the Cb & Cr values. + // Basically we return a matrix that transforms RYB values + // to YUV values. (Note that the green component have been replaced + // with the luminance.) case ColorSpace::MatrixID::BT2020_CL: { Kr = 0.2627f; Kb = 0.0593f; - float data[16] = { - 1.0f, 0.0f, 0.0f, 0.0f, // R - Kr, 1.0f - Kr - Kb, Kb, 0.0f, // Y - 0.0f, 0.0f, 1.0f, 0.0f, // B - 0.0f, 0.0f, 0.0f, 1.0f - }; + float data[16] = {1.0f, 0.0f, 0.0f, 0.0f, // R + Kr, 1.0f - Kr - Kb, Kb, 0.0f, // Y + 0.0f, 0.0f, 1.0f, 0.0f, // B + 0.0f, 0.0f, 0.0f, 1.0f}; matrix->setRowMajorf(data); return; }
diff --git a/ui/gfx/color_transform.cc b/ui/gfx/color_transform.cc index 0bbf3852..6aad90f 100644 --- a/ui/gfx/color_transform.cc +++ b/ui/gfx/color_transform.cc
@@ -275,8 +275,9 @@ gfx::ColorSpace GetDstColorSpace() const override { return dst_; }; void Transform(TriStim* colors, size_t num) const override { - for (const auto& step : steps_) + for (const auto& step : steps_) { step->Transform(colors, num); + } } bool CanGetShaderSource() const override; std::string GetShaderSource() const override; @@ -443,8 +444,6 @@ // ColorTransformPerChannelTransferFn implementation: float Evaluate(float v) const override { // Note that the sign-extension is performed by the caller. - if (v < 0.f) - return 0.f; return SkTransferFnEvalUnclamped(fn_, v); } void AppendTransferShaderSource(std::stringstream* result) const override { @@ -728,7 +727,7 @@ } else { V = R_Y / (2.0 * 0.4969); } - RYB[i] = ColorTransform::TriStim(RYB[i].y(), U, V); + RYB[i] = ColorTransform::TriStim(RYB[i].y(), U + 0.5, V + 0.5); } } @@ -756,11 +755,11 @@ return; for (size_t i = 0; i < num; i++) { float Y = YUV[i].x(); - float U = YUV[i].y(); - float V = YUV[i].z(); + float U = YUV[i].y() - 0.5; + float V = YUV[i].z() - 0.5; float B_Y, R_Y; if (U <= 0) { - B_Y = Y * (-2.0 * -0.9702); + B_Y = U * (-2.0 * -0.9702); } else { B_Y = U * (2.0 * 0.7910); } @@ -770,7 +769,7 @@ R_Y = V * (2.0 * 0.4969); } // Return an RYB value, later steps will fix it. - YUV[i] = ColorTransform::TriStim(R_Y + Y, YUV[i].x(), B_Y + Y); + YUV[i] = ColorTransform::TriStim(R_Y + Y, Y, B_Y + Y); } } bool CanAppendShaderSource() override { return true; } @@ -780,12 +779,12 @@ *hdr << "vec3 BT2020_YUV_to_RYB_Step" << step_index << "(vec3 color) {" << endl; *hdr << " float Y = color.x;" << endl; - *hdr << " float U = color.y;" << endl; - *hdr << " float V = color.z;" << endl; + *hdr << " float U = color.y - 0.5;" << endl; + *hdr << " float V = color.z - 0.5;" << endl; *hdr << " float B_Y = 0.0;" << endl; *hdr << " float R_Y = 0.0;" << endl; *hdr << " if (U <= 0.0) {" << endl; - *hdr << " B_Y = Y * (-2.0 * -0.9702);" << endl; + *hdr << " B_Y = U * (-2.0 * -0.9702);" << endl; *hdr << " } else {" << endl; *hdr << " B_Y = U * (2.0 * 0.7910);" << endl; *hdr << " }" << endl; @@ -838,8 +837,13 @@ steps_.push_back( std::make_unique<ColorTransformMatrix>(GetRangeAdjustMatrix(src))); - steps_.push_back( - std::make_unique<ColorTransformMatrix>(Invert(GetTransferMatrix(src)))); + if (src.matrix_ == ColorSpace::MatrixID::BT2020_CL) { + // BT2020 CL is a special case. + steps_.push_back(std::make_unique<ColorTransformFromBT2020CL>()); + } else { + steps_.push_back( + std::make_unique<ColorTransformMatrix>(Invert(GetTransferMatrix(src)))); + } // If the target color space is not defined, just apply the adjust and // tranfer matrices. This path is used by YUV to RGB color conversion @@ -860,7 +864,8 @@ if (src.matrix_ == ColorSpace::MatrixID::BT2020_CL) { // BT2020 CL is a special case. - steps_.push_back(std::make_unique<ColorTransformFromBT2020CL>()); + steps_.push_back( + std::make_unique<ColorTransformMatrix>(Invert(GetTransferMatrix(src)))); } steps_.push_back( std::make_unique<ColorTransformMatrix>(GetPrimaryTransform(src))); @@ -869,7 +874,8 @@ std::make_unique<ColorTransformMatrix>(Invert(GetPrimaryTransform(dst)))); if (dst.matrix_ == ColorSpace::MatrixID::BT2020_CL) { // BT2020 CL is a special case. - steps_.push_back(std::make_unique<ColorTransformToBT2020CL>()); + steps_.push_back( + std::make_unique<ColorTransformMatrix>(GetTransferMatrix(dst))); } SkColorSpaceTransferFn dst_from_linear_fn; @@ -880,8 +886,12 @@ steps_.push_back(std::make_unique<ColorTransformFromLinear>(dst.transfer_)); } - steps_.push_back( - std::make_unique<ColorTransformMatrix>(GetTransferMatrix(dst))); + if (dst.matrix_ == ColorSpace::MatrixID::BT2020_CL) { + steps_.push_back(std::make_unique<ColorTransformToBT2020CL>()); + } else { + steps_.push_back( + std::make_unique<ColorTransformMatrix>(GetTransferMatrix(dst))); + } steps_.push_back(std::make_unique<ColorTransformMatrix>( Invert(GetRangeAdjustMatrix(dst))));
diff --git a/ui/gfx/color_transform_unittest.cc b/ui/gfx/color_transform_unittest.cc index 3a668f9..c965b47d 100644 --- a/ui/gfx/color_transform_unittest.cc +++ b/ui/gfx/color_transform_unittest.cc
@@ -98,6 +98,36 @@ EXPECT_GT(tmp.z(), tmp.y()); } +TEST(SimpleColorSpace, BT2020CLtoBT2020RGB) { + ColorSpace bt2020cl( + ColorSpace::PrimaryID::BT2020, ColorSpace::TransferID::BT2020_10, + ColorSpace::MatrixID::BT2020_CL, ColorSpace::RangeID::LIMITED); + ColorSpace bt2020rgb(ColorSpace::PrimaryID::BT2020, + ColorSpace::TransferID::BT2020_10, + ColorSpace::MatrixID::RGB, ColorSpace::RangeID::FULL); + ColorSpace sRGB = ColorSpace::CreateSRGB(); + std::unique_ptr<ColorTransform> t(ColorTransform::NewColorTransform( + bt2020cl, bt2020rgb, ColorTransform::Intent::INTENT_ABSOLUTE)); + + ColorTransform::TriStim tmp(16.0f / 255.0f, 0.5f, 0.5f); + t->Transform(&tmp, 1); + EXPECT_NEAR(tmp.x(), 0.0f, 0.001f); + EXPECT_NEAR(tmp.y(), 0.0f, 0.001f); + EXPECT_NEAR(tmp.z(), 0.0f, 0.001f); + + tmp = ColorTransform::TriStim(235.0f / 255.0f, 0.5f, 0.5f); + t->Transform(&tmp, 1); + EXPECT_NEAR(tmp.x(), 1.0f, 0.001f); + EXPECT_NEAR(tmp.y(), 1.0f, 0.001f); + EXPECT_NEAR(tmp.z(), 1.0f, 0.001f); + + // Test a blue color + tmp = ColorTransform::TriStim(128.0f / 255.0f, 240.0f / 255.0f, 0.5f); + t->Transform(&tmp, 1); + EXPECT_GT(tmp.z(), tmp.x()); + EXPECT_GT(tmp.z(), tmp.y()); +} + TEST(SimpleColorSpace, TransferFnCancel) { ColorSpace::PrimaryID primary = ColorSpace::PrimaryID::BT709; ColorSpace::MatrixID matrix = ColorSpace::MatrixID::RGB;
diff --git a/ui/gfx/skia_util.cc b/ui/gfx/skia_util.cc index db2856f..4379e76c 100644 --- a/ui/gfx/skia_util.cc +++ b/ui/gfx/skia_util.cc
@@ -68,6 +68,10 @@ SkFloatToScalar(size.height())); } +SkISize SizeToSkISize(const Size& size) { + return SkISize::Make(size.width(), size.height()); +} + SizeF SkSizeToSizeF(const SkSize& size) { return SizeF(SkScalarToFloat(size.width()), SkScalarToFloat(size.height())); }
diff --git a/ui/gfx/skia_util.h b/ui/gfx/skia_util.h index 0c1f251..d0efa6b 100644 --- a/ui/gfx/skia_util.h +++ b/ui/gfx/skia_util.h
@@ -35,6 +35,7 @@ GFX_EXPORT SkRect RectFToSkRect(const RectF& rect); GFX_EXPORT RectF SkRectToRectF(const SkRect& rect); GFX_EXPORT SkSize SizeFToSkSize(const SizeF& size); +GFX_EXPORT SkISize SizeToSkISize(const Size& size); GFX_EXPORT SizeF SkSizeToSizeF(const SkSize& size); GFX_EXPORT Size SkISizeToSize(const SkISize& size);
diff --git a/ui/gl/PRESUBMIT.py b/ui/gl/PRESUBMIT.py index dd5141e6..01515c9 100644 --- a/ui/gl/PRESUBMIT.py +++ b/ui/gl/PRESUBMIT.py
@@ -24,7 +24,7 @@ cl, [ 'luci.chromium.try:linux_optional_gpu_tests_rel', - 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'luci.chromium.try:mac_optional_gpu_tests_rel', 'master.tryserver.chromium.win:win_optional_gpu_tests_rel', 'master.tryserver.chromium.android:android_optional_gpu_tests_rel', ],
diff --git a/ui/gl/init/gl_initializer_mac.cc b/ui/gl/init/gl_initializer_mac.cc index 91b2e0b..d45d7a1 100644 --- a/ui/gl/init/gl_initializer_mac.cc +++ b/ui/gl/init/gl_initializer_mac.cc
@@ -143,11 +143,7 @@ "Libraries/libswiftshader_libEGL.dylib"; bool InitializeStaticEGLInternal(GLImplementation implementation) { - base::FilePath module_path; - if (!PathService::Get(base::DIR_MODULE, &module_path)) { - return false; - } - + base::FilePath module_path = base::mac::FrameworkBundlePath(); base::FilePath glesv2_path; base::FilePath egl_path; if (implementation == kGLImplementationSwiftShaderGL) {
diff --git a/ui/ozone/common/egl_util.cc b/ui/ozone/common/egl_util.cc index 9a40d1d..86636c3f 100644 --- a/ui/ozone/common/egl_util.cc +++ b/ui/ozone/common/egl_util.cc
@@ -14,12 +14,16 @@ namespace ui { namespace { -const char kDefaultEglSoname[] = "libEGL.so.1"; -const char kDefaultGlesSoname[] = "libGLESv2.so.2"; +const base::FilePath::CharType kDefaultEglSoname[] = + FILE_PATH_LITERAL("libEGL.so.1"); +const base::FilePath::CharType kDefaultGlesSoname[] = + FILE_PATH_LITERAL("libGLESv2.so.2"); #if BUILDFLAG(ENABLE_SWIFTSHADER) -const char kGLESv2SwiftShaderLibraryName[] = "libGLESv2.so"; -const char kEGLSwiftShaderLibraryName[] = "libEGL.so"; +const base::FilePath::CharType kGLESv2SwiftShaderLibraryName[] = + FILE_PATH_LITERAL("libGLESv2.so"); +const base::FilePath::CharType kEGLSwiftShaderLibraryName[] = + FILE_PATH_LITERAL("libEGL.so"); #endif bool LoadEGLGLES2Bindings(const base::FilePath& egl_library_path, @@ -69,7 +73,7 @@ base::FilePath module_path; if (!PathService::Get(base::DIR_MODULE, &module_path)) return false; - module_path = module_path.Append("swiftshader/"); + module_path = module_path.Append(FILE_PATH_LITERAL("swiftshader/")); glesv2_path = module_path.Append(kGLESv2SwiftShaderLibraryName); egl_path = module_path.Append(kEGLSwiftShaderLibraryName);
diff --git a/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc b/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc index 607bf22..dc7b44a 100644 --- a/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc +++ b/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc
@@ -39,7 +39,7 @@ // ClientNativePixmapFactoryCast implementation: bool IsConfigurationSupported(gfx::BufferFormat format, gfx::BufferUsage usage) const override { - return format == gfx::BufferFormat::RGBA_8888 && + return format == gfx::BufferFormat::BGRA_8888 && usage == gfx::BufferUsage::SCANOUT; }
diff --git a/ui/ozone/platform/drm/host/drm_overlay_manager.cc b/ui/ozone/platform/drm/host/drm_overlay_manager.cc index dc0f75a1..d99d288 100644 --- a/ui/ozone/platform/drm/host/drm_overlay_manager.cc +++ b/ui/ozone/platform/drm/host/drm_overlay_manager.cc
@@ -61,11 +61,6 @@ continue; } - // Compositor doesn't have information about the total size of primary - // candidate. We get this information from display rect. - if (candidate.plane_z_order == 0) - candidate.buffer_size = gfx::ToNearestRect(candidate.display_rect).size(); - result_candidates.push_back(OverlaySurfaceCandidate(candidate)); // Start out hoping that we can have an overlay. result_candidates.back().overlay_handled = true;
diff --git a/ui/ozone/platform/headless/headless_surface_factory.cc b/ui/ozone/platform/headless/headless_surface_factory.cc index 6e64f51..bec0898 100644 --- a/ui/ozone/platform/headless/headless_surface_factory.cc +++ b/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -28,6 +28,8 @@ namespace { +const base::FilePath::CharType kDevNull[] = FILE_PATH_LITERAL("/dev/null"); + void WriteDataToFile(const base::FilePath& location, const SkBitmap& bitmap) { DCHECK(!location.empty()); std::vector<unsigned char> png_data; @@ -137,7 +139,7 @@ base::FilePath HeadlessSurfaceFactory::GetPathForWidget( gfx::AcceleratedWidget widget) { - if (base_path_.empty() || base_path_ == base::FilePath("/dev/null")) + if (base_path_.empty() || base_path_ == base::FilePath(kDevNull)) return base_path_; // Disambiguate multiple window output files with the window id. @@ -177,7 +179,7 @@ return; if (!DirectoryExists(base_path_) && !base::CreateDirectory(base_path_) && - base_path_ != base::FilePath("/dev/null")) + base_path_ != base::FilePath(kDevNull)) PLOG(FATAL) << "Unable to create output directory"; if (!base::PathIsWritable(base_path_))
diff --git a/ui/ozone/platform/headless/headless_window.cc b/ui/ozone/platform/headless/headless_window.cc index 3608ffa..2c038ad 100644 --- a/ui/ozone/platform/headless/headless_window.cc +++ b/ui/ozone/platform/headless/headless_window.cc
@@ -6,6 +6,7 @@ #include <string> +#include "build/build_config.h" #include "ui/events/platform/platform_event_source.h" #include "ui/ozone/platform/headless/headless_window_manager.h" #include "ui/platform_window/platform_window_delegate.h" @@ -16,12 +17,20 @@ HeadlessWindowManager* manager, const gfx::Rect& bounds) : delegate_(delegate), manager_(manager), bounds_(bounds) { +#if defined(OS_WIN) + widget_ = reinterpret_cast<gfx::AcceleratedWidget>(manager_->AddWindow(this)); +#else widget_ = manager_->AddWindow(this); +#endif delegate_->OnAcceleratedWidgetAvailable(widget_, 1.f); } HeadlessWindow::~HeadlessWindow() { +#if defined(OS_WIN) + manager_->RemoveWindow(reinterpret_cast<uint64_t>(widget_), this); +#else manager_->RemoveWindow(widget_, this); +#endif } gfx::Rect HeadlessWindow::GetBounds() {
diff --git a/ui/ozone/platform/wayland/fake_server.h b/ui/ozone/platform/wayland/fake_server.h index d1bcf94..a9286261 100644 --- a/ui/ozone/platform/wayland/fake_server.h +++ b/ui/ozone/platform/wayland/fake_server.h
@@ -25,7 +25,7 @@ // Base class for managing the life cycle of server objects. class ServerObject { public: - ServerObject(wl_resource* resource); + explicit ServerObject(wl_resource* resource); virtual ~ServerObject(); wl_resource* resource() { return resource_; } @@ -71,7 +71,7 @@ // Manage zxdg_toplevel for providing desktop UI. class MockXdgTopLevel : public MockXdgSurface { public: - MockXdgTopLevel(wl_resource* resource); + explicit MockXdgTopLevel(wl_resource* resource); ~MockXdgTopLevel() override; // TODO(msisov): mock other zxdg_toplevel specific methods once implementation @@ -85,7 +85,7 @@ // Manage client surface class MockSurface : public ServerObject { public: - MockSurface(wl_resource* resource); + explicit MockSurface(wl_resource* resource); ~MockSurface() override; static MockSurface* FromResource(wl_resource* resource); @@ -103,7 +103,7 @@ class MockPointer : public ServerObject { public: - MockPointer(wl_resource* resource); + explicit MockPointer(wl_resource* resource); ~MockPointer() override; private: @@ -112,7 +112,7 @@ class MockKeyboard : public ServerObject { public: - MockKeyboard(wl_resource* resource); + explicit MockKeyboard(wl_resource* resource); ~MockKeyboard() override; private:
diff --git a/ui/shell_dialogs/BUILD.gn b/ui/shell_dialogs/BUILD.gn index e5018b27..80b4c176 100644 --- a/ui/shell_dialogs/BUILD.gn +++ b/ui/shell_dialogs/BUILD.gn
@@ -89,6 +89,8 @@ mac_framework_bundle("shell_dialogs_unittests_bundle") { testonly = true + framework_version = "S" + framework_contents = [ "Resources" ] info_plist = "//ui/base/test/framework-Info.plist" deps = [ ":shell_dialogs_unittests_xibs",
diff --git a/ui/views/bubble/bubble_border.cc b/ui/views/bubble/bubble_border.cc index e2292a8f..8a539bed 100644 --- a/ui/views/bubble/bubble_border.cc +++ b/ui/views/bubble/bubble_border.cc
@@ -62,13 +62,12 @@ namespace { +// The border corner radius for material design bubble borders. +constexpr int kMaterialDesignCornerRadius = 2; + // The border is stroked at 1px, but for the purposes of reserving space we have // to deal in dip coordinates, so round up to 1dip. -const int kBorderThicknessDip = 1; - -bool UseMaterialDesign() { - return ui::MaterialDesignController::IsSecondaryUiMaterial(); -} +constexpr int kBorderThicknessDip = 1; // Utility functions for getting alignment points on the edge of a rectangle. gfx::Point CenterTop(const gfx::Rect& rect) { @@ -177,13 +176,7 @@ background_color_(color), use_theme_background_color_(false) { DCHECK(shadow_ < SHADOW_COUNT); - if (UseMaterialDesign()) { - // Harmony bubbles don't use arrows. - alignment_ = ALIGN_EDGE_TO_ANCHOR_EDGE; - arrow_paint_type_ = PAINT_NONE; - } else { - images_ = GetBorderImages(shadow_); - } + Init(); } BubbleBorder::~BubbleBorder() {} @@ -196,6 +189,11 @@ return blur + offset; } +void BubbleBorder::SetCornerRadius(int corner_radius) { + corner_radius_ = corner_radius; + Init(); +} + void BubbleBorder::set_paint_arrow(ArrowPaintType value) { if (UseMaterialDesign()) return; @@ -303,7 +301,9 @@ } int BubbleBorder::GetBorderCornerRadius() const { - return UseMaterialDesign() ? 2 : images_->corner_radius; + if (UseMaterialDesign()) + return corner_radius_.value_or(kMaterialDesignCornerRadius); + return images_->corner_radius; } int BubbleBorder::GetArrowOffset(const gfx::Size& border_size) const { @@ -338,6 +338,16 @@ images_->border_thickness = border_interior_thickness; } +void BubbleBorder::Init() { + if (UseMaterialDesign()) { + // Harmony bubbles don't use arrows. + alignment_ = ALIGN_EDGE_TO_ANCHOR_EDGE; + arrow_paint_type_ = PAINT_NONE; + } else { + images_ = GetBorderImages(shadow_); + } +} + void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) { if (UseMaterialDesign()) return PaintMd(view, canvas); @@ -561,6 +571,11 @@ return images_; } +bool BubbleBorder::UseMaterialDesign() const { + return ui::MaterialDesignController::IsSecondaryUiMaterial() || + corner_radius_.has_value(); +} + void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { if (border_->shadow() == BubbleBorder::NO_SHADOW_OPAQUE_BORDER) canvas->DrawColor(border_->background_color());
diff --git a/ui/views/bubble/bubble_border.h b/ui/views/bubble/bubble_border.h index 46531ed..68f4473c 100644 --- a/ui/views/bubble/bubble_border.h +++ b/ui/views/bubble/bubble_border.h
@@ -192,6 +192,9 @@ (canvas->sk_canvas()->*draw)(rect, GetBorderAndShadowFlags()); } + // Set the corner radius, enables Material Design. + void SetCornerRadius(int radius); + // Get or set the arrow type. void set_arrow(Arrow arrow) { arrow_ = arrow; } Arrow arrow() const { return arrow_; } @@ -266,6 +269,9 @@ // The border and arrow stroke size used in image assets, in pixels. static const int kStroke; + // Initializes the MD or non-MD BubbleBorder. + void Init(); + gfx::Size GetSizeForContentsSize(const gfx::Size& contents_size) const; gfx::ImageSkia* GetArrowImage() const; gfx::Rect GetArrowRect(const gfx::Rect& bounds) const; @@ -287,8 +293,14 @@ internal::BorderImages* GetImagesForTest() const; + // Whether to use material design. + bool UseMaterialDesign() const; + Arrow arrow_; int arrow_offset_; + // Corner radius for the bubble border. If supplied the border will use + // material design. + base::Optional<int> corner_radius_; ArrowPaintType arrow_paint_type_; BubbleAlignment alignment_; Shadow shadow_;
diff --git a/ui/views/controls/menu/menu_config.h b/ui/views/controls/menu/menu_config.h index a4ecc478..fb1ece4 100644 --- a/ui/views/controls/menu/menu_config.h +++ b/ui/views/controls/menu/menu_config.h
@@ -121,6 +121,18 @@ // Radius of the rounded corners of the menu border. Must be >= 0. int corner_radius; + // Radius of the rounded corners of the touchable menu border + int touchable_corner_radius; + + // Height of child MenuItemViews for touchable menus. + int touchable_menu_height; + + // Width of touchable menus. + int touchable_menu_width; + + // Vertical padding for touchable menus. + int vertical_touchable_menu_item_padding; + private: // Configures a MenuConfig as appropriate for the current platform. void Init();
diff --git a/ui/views/controls/menu/menu_config_chromeos.cc b/ui/views/controls/menu/menu_config_chromeos.cc index 75250e7c..f6e8fe7 100644 --- a/ui/views/controls/menu/menu_config_chromeos.cc +++ b/ui/views/controls/menu/menu_config_chromeos.cc
@@ -23,6 +23,10 @@ align_arrow_and_shortcut = true; offset_context_menus = true; corner_radius = 2; + touchable_corner_radius = 8; + touchable_menu_height = 36; + touchable_menu_width = 256; + vertical_touchable_menu_item_padding = 8; // In Ash, the border is provided by the shadow. use_outer_border = false;
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc index c30fb8e6..83a1a0f 100644 --- a/ui/views/controls/menu/menu_controller.cc +++ b/ui/views/controls/menu/menu_controller.cc
@@ -1929,8 +1929,8 @@ pref.set_width(std::max(pref.width(), state_.initial_bounds.width())); // Don't let the menu go too wide. - pref.set_width(std::min(pref.width(), - item->GetDelegate()->GetMaxWidthForMenu(item))); + pref.set_width( + std::min(pref.width(), item->GetDelegate()->GetMaxWidthForMenu(item))); if (!state_.monitor_bounds.IsEmpty()) pref.set_width(std::min(pref.width(), state_.monitor_bounds.width())); @@ -2161,6 +2161,28 @@ } submenu->GetScrollViewContainer()->SetBubbleArrowOffset( pref.width() / 2 - x + x_old); + } else if (state_.anchor == MENU_ANCHOR_BUBBLE_TOUCHABLE_ABOVE) { + // Align the left edges of the menu and anchor, and the bottom of the menu + // with the top of the anchor. + x = owner_bounds.origin().x(); + y = owner_bounds.origin().y() - pref.height(); + // Align the right of the container with the right of the app icon. + if (x + pref.width() > state_.monitor_bounds.width()) + x = owner_bounds.right() - pref.width(); + // Align the top of the menu with the bottom of the anchor. + if (y < 0) + y = owner_bounds.bottom(); + } else if (state_.anchor == MENU_ANCHOR_BUBBLE_TOUCHABLE_LEFT) { + // Align the right of the menu with the left of the anchor, and the top of + // the menu with the top of the anchor. + x = owner_bounds.origin().x() - pref.width(); + y = owner_bounds.origin().y(); + // Align the left of the menu with the right of the anchor. + if (x < 0) + x = owner_bounds.right(); + // Align the bottom of the menu to the bottom of the anchor. + if (y + pref.height() > state_.monitor_bounds.height()) + y = owner_bounds.bottom() - pref.height(); } else { if (state_.anchor == MENU_ANCHOR_BUBBLE_RIGHT) x = owner_bounds.right() - kBubbleTipSizeLeftRight;
diff --git a/ui/views/controls/menu/menu_controller.h b/ui/views/controls/menu/menu_controller.h index 1a056eb..7154724 100644 --- a/ui/views/controls/menu/menu_controller.h +++ b/ui/views/controls/menu/menu_controller.h
@@ -198,6 +198,11 @@ // Only used for testing. static void TurnOffMenuSelectionHoldForTest(); + void set_use_touchable_layout(bool use_touchable_layout) { + use_touchable_layout_ = use_touchable_layout; + } + bool use_touchable_layout() const { return use_touchable_layout_; } + private: friend class internal::MenuRunnerImpl; friend class test::MenuControllerTest; @@ -681,6 +686,9 @@ // Set to true if the menu item was selected by touch. bool item_selected_by_touch_ = false; + // Whether to use the touchable layout. + bool use_touchable_layout_ = false; + // During mouse event handling, this is the RootView to forward mouse events // to. We need this, because if we forward one event to it (e.g., mouse // pressed), subsequent events (like dragging) should also go to it, even if
diff --git a/ui/views/controls/menu/menu_host.cc b/ui/views/controls/menu/menu_host.cc index bcdd4af..d332a2d86 100644 --- a/ui/views/controls/menu/menu_host.cc +++ b/ui/views/controls/menu/menu_host.cc
@@ -116,7 +116,9 @@ const MenuController* menu_controller = submenu_->GetMenuItem()->GetMenuController(); const MenuConfig& menu_config = MenuConfig::instance(); - bool rounded_border = menu_controller && menu_config.corner_radius > 0; + bool rounded_border = + (menu_controller && menu_controller->use_touchable_layout()) || + (menu_controller && menu_config.corner_radius > 0); bool bubble_border = submenu_->GetScrollViewContainer() && submenu_->GetScrollViewContainer()->HasBubbleBorder(); params.shadow_type = bubble_border ? Widget::InitParams::SHADOW_TYPE_NONE
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc index 4cf7d61..a155298 100644 --- a/ui/views/controls/menu/menu_item_view.cc +++ b/ui/views/controls/menu/menu_item_view.cc
@@ -199,7 +199,9 @@ return anchor == MENU_ANCHOR_BUBBLE_LEFT || anchor == MENU_ANCHOR_BUBBLE_RIGHT || anchor == MENU_ANCHOR_BUBBLE_ABOVE || - anchor == MENU_ANCHOR_BUBBLE_BELOW; + anchor == MENU_ANCHOR_BUBBLE_BELOW || + anchor == MENU_ANCHOR_BUBBLE_TOUCHABLE_ABOVE || + anchor == MENU_ANCHOR_BUBBLE_TOUCHABLE_LEFT; } // static @@ -1012,6 +1014,15 @@ MenuItemDimensions dimensions; // Get the container height. dimensions.children_width = child_size.width(); + const MenuConfig& menu_config = MenuConfig::instance(); + + if (GetMenuController() && GetMenuController()->use_touchable_layout()) { + // MenuItemViews that use the touchable layout have fixed height and width. + dimensions.height = menu_config.touchable_menu_height; + dimensions.standard_width = menu_config.touchable_menu_width; + return dimensions; + } + dimensions.height = child_size.height(); // Adjust item content height if menu has both items with and without icons. // This way all menu items will have the same height.
diff --git a/ui/views/controls/menu/menu_runner.h b/ui/views/controls/menu/menu_runner.h index 56a53d9..88b4bb4 100644 --- a/ui/views/controls/menu/menu_runner.h +++ b/ui/views/controls/menu/menu_runner.h
@@ -95,6 +95,9 @@ // shelf uses the flag to continue dragging an item without lifting the // finger after the context menu of the item is opened. SEND_GESTURE_EVENTS_TO_OWNER = 1 << 7, + + // Whether to use the touchable layout for this context menu. + USE_TOUCHABLE_LAYOUT = 1 << 8, }; // Creates a new MenuRunner, which may use a native menu if available.
diff --git a/ui/views/controls/menu/menu_runner_impl.cc b/ui/views/controls/menu/menu_runner_impl.cc index 0004fe4..cd9ac6df 100644 --- a/ui/views/controls/menu/menu_runner_impl.cc +++ b/ui/views/controls/menu/menu_runner_impl.cc
@@ -128,6 +128,8 @@ controller->set_is_combobox((run_types & MenuRunner::COMBOBOX) != 0); controller->set_send_gesture_events_to_owner( (run_types & MenuRunner::SEND_GESTURE_EVENTS_TO_OWNER) != 0); + controller->set_use_touchable_layout( + (run_types & MenuRunner::USE_TOUCHABLE_LAYOUT) != 0); controller_ = controller->AsWeakPtr(); menu_->set_controller(controller_.get()); menu_->PrepareForRun(owns_controller_, has_mnemonics,
diff --git a/ui/views/controls/menu/menu_scroll_view_container.cc b/ui/views/controls/menu/menu_scroll_view_container.cc index 01069fe..2ab1fe6 100644 --- a/ui/views/controls/menu/menu_scroll_view_container.cc +++ b/ui/views/controls/menu/menu_scroll_view_container.cc
@@ -25,7 +25,7 @@ namespace { -static const int kBorderPaddingDueToRoundedCorners = 1; +static constexpr int kBorderPaddingDueToRoundedCorners = 1; // MenuScrollButton ------------------------------------------------------------ @@ -251,7 +251,10 @@ gfx::Rect bounds(0, 0, width(), height()); NativeTheme::ExtraParams extra; const MenuConfig& menu_config = MenuConfig::instance(); - extra.menu_background.corner_radius = menu_config.corner_radius; + extra.menu_background.corner_radius = + content_view_->GetMenuItem()->GetMenuController()->use_touchable_layout() + ? menu_config.touchable_corner_radius + : menu_config.corner_radius; GetNativeTheme()->Paint(canvas->sk_canvas(), NativeTheme::kMenuPopupBackground, NativeTheme::kNormal, bounds, extra); } @@ -300,9 +303,17 @@ } void MenuScrollViewContainer::CreateBubbleBorder() { - bubble_border_ = new BubbleBorder(arrow_, - BubbleBorder::SMALL_SHADOW, - SK_ColorWHITE); + bubble_border_ = + new BubbleBorder(arrow_, BubbleBorder::SMALL_SHADOW, SK_ColorWHITE); + if (content_view_->GetMenuItem() + ->GetMenuController() + ->use_touchable_layout()) { + const MenuConfig& menu_config = MenuConfig::instance(); + bubble_border_->SetCornerRadius(menu_config.touchable_corner_radius); + scroll_view_->GetContents()->SetBorder(CreateEmptyBorder( + gfx::Insets(menu_config.vertical_touchable_menu_item_padding, 0))); + } + SetBorder(std::unique_ptr<Border>(bubble_border_)); SetBackground(std::make_unique<BubbleBackground>(bubble_border_)); } @@ -318,6 +329,9 @@ return BubbleBorder::BOTTOM_CENTER; case MENU_ANCHOR_BUBBLE_BELOW: return BubbleBorder::TOP_CENTER; + case MENU_ANCHOR_BUBBLE_TOUCHABLE_ABOVE: + case MENU_ANCHOR_BUBBLE_TOUCHABLE_LEFT: + return BubbleBorder::FLOAT; default: return BubbleBorder::NONE; }
diff --git a/ui/views/controls/menu/menu_types.h b/ui/views/controls/menu/menu_types.h index 2f99222..d95ce0b 100644 --- a/ui/views/controls/menu/menu_types.h +++ b/ui/views/controls/menu/menu_types.h
@@ -21,7 +21,9 @@ MENU_ANCHOR_BUBBLE_LEFT, MENU_ANCHOR_BUBBLE_RIGHT, MENU_ANCHOR_BUBBLE_ABOVE, - MENU_ANCHOR_BUBBLE_BELOW + MENU_ANCHOR_BUBBLE_BELOW, + MENU_ANCHOR_BUBBLE_TOUCHABLE_ABOVE, + MENU_ANCHOR_BUBBLE_TOUCHABLE_LEFT }; } // namespace views
diff --git a/ui/views/controls/menu/submenu_view.cc b/ui/views/controls/menu/submenu_view.cc index b8926ded..9b244c9 100644 --- a/ui/views/controls/menu/submenu_view.cc +++ b/ui/views/controls/menu/submenu_view.cc
@@ -24,10 +24,10 @@ namespace { // Height of the drop indicator. This should be an even number. -const int kDropIndicatorHeight = 2; +constexpr int kDropIndicatorHeight = 2; // Color of the drop indicator. -const SkColor kDropIndicatorColor = SK_ColorBLACK; +constexpr SkColor kDropIndicatorColor = SK_ColorBLACK; } // namespace @@ -69,7 +69,7 @@ return false; } -int SubmenuView::GetMenuItemCount() { +int SubmenuView::GetMenuItemCount() const { int count = 0; for (int i = 0; i < child_count(); ++i) { if (child_at(i)->id() == MenuItemView::kMenuItemViewID) @@ -144,6 +144,8 @@ int max_complex_width = 0; // The max. width of items which contain a label and maybe an accelerator. int max_simple_width = 0; + // The minimum width of touchable items. + int touchable_minimum_width = 0; // We perform the size calculation in two passes. In the first pass, we // calculate the width of the menu. In the second, we calculate the height @@ -163,6 +165,7 @@ std::max(max_minor_text_width_, dimensions.minor_text_width); max_complex_width = std::max(max_complex_width, dimensions.standard_width + dimensions.children_width); + touchable_minimum_width = dimensions.standard_width; } else { max_complex_width = std::max(max_complex_width, child->GetPreferredSize().width()); @@ -178,6 +181,10 @@ insets.width(), minimum_preferred_width_ - 2 * insets.width())); + if (GetMenuItem()->GetMenuController() && + GetMenuItem()->GetMenuController()->use_touchable_layout()) + width = std::max(touchable_minimum_width, width); + // Then, the height for that width. int height = 0; int menu_item_width = width - insets.width();
diff --git a/ui/views/controls/menu/submenu_view.h b/ui/views/controls/menu/submenu_view.h index c17c944..9ba6933 100644 --- a/ui/views/controls/menu/submenu_view.h +++ b/ui/views/controls/menu/submenu_view.h
@@ -56,7 +56,7 @@ // Returns the number of child views that are MenuItemViews. // MenuItemViews are identified by ID. - int GetMenuItemCount(); + int GetMenuItemCount() const; // Returns the MenuItemView at the specified index. MenuItemView* GetMenuItemAt(int index);