diff --git a/DEPS b/DEPS index baabe7b..f2811e5 100644 --- a/DEPS +++ b/DEPS
@@ -96,11 +96,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': '694ebb348a4487840dcd5a84eb587a7706d50775', + 'skia_revision': '95e2b91d76d60ae69588ca700211146aabddbe5a', # 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': '2839e6855ad88a09f6a8a6a1eeaad98876ac6aa1', + 'v8_revision': '0cb7b82ecaab1aeb72ec695c0aaaeda26d3513b4', # 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. @@ -156,7 +156,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '39e3bc6ed30a6c1a1b99c8e82e2956f189b743c4', + 'catapult_revision': '3059fd7dba63773c249938b1b934b9c10143d684', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -269,7 +269,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '5ee7e2e3a845c5ca7e3d8a5a0d2ab4faddb52da5', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'dc1eae3b21358b4761a09e7c586bc69f3695eb6e', 'condition': 'checkout_ios', }, @@ -498,7 +498,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'abd74feb3dc42cfbb69fa139a5616470aa6f9bad', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '5c50bf92e6fb07f43093db44cc230ca8765d216b', 'condition': 'checkout_linux', }, @@ -523,7 +523,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '142a92ce8b834a412c16c0451ed8d434ea323e58', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '5e5f2d60353bb93898302458f37ae667d60c7b8e', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -860,7 +860,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '66d57768881fc6474a43b1b3903b9ecfbdcebf03', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'a6f6a3133cf76a54b2d9fa6c40605e6919c93d66', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index cde1f9b2..d1da1f06 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -92,8 +92,6 @@ "app_list/app_list_presenter_impl.h", "app_list/app_list_view_delegate_mash.cc", "app_list/app_list_view_delegate_mash.h", - "ash_constants.cc", - "ash_constants.h", "ash_export.h", "ash_layout_constants.cc", "ash_layout_constants.h",
diff --git a/ash/accessibility/accessibility_controller.h b/ash/accessibility/accessibility_controller.h index c49d1edd..1a9edb7 100644 --- a/ash/accessibility/accessibility_controller.h +++ b/ash/accessibility/accessibility_controller.h
@@ -7,8 +7,8 @@ #include <memory> -#include "ash/ash_constants.h" #include "ash/ash_export.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/interfaces/accessibility_controller.mojom.h" #include "ash/session/session_observer.h" #include "base/macros.h"
diff --git a/ash/accessibility/accessibility_controller_unittest.cc b/ash/accessibility/accessibility_controller_unittest.cc index 5888d25..e29d7955 100644 --- a/ash/accessibility/accessibility_controller_unittest.cc +++ b/ash/accessibility/accessibility_controller_unittest.cc
@@ -8,8 +8,8 @@ #include "ash/accessibility/accessibility_observer.h" #include "ash/accessibility/test_accessibility_controller_client.h" -#include "ash/ash_constants.h" #include "ash/magnifier/docked_magnifier_controller.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/config.h"
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index 6d8f66a..baa606e 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -181,12 +181,17 @@ void AppListControllerImpl::SetItemMetadata(const std::string& id, AppListItemMetadataPtr data) { app_list::AppListItem* item = model_.FindItem(id); - if (item) { - // data may not contain valid position. Preserve it in this case. - if (!data->position.IsValid()) - data->position = item->position(); - item->SetMetadata(std::move(data)); - } + if (!item) + return; + + // data may not contain valid position or icon. Preserve it in this case. + if (!data->position.IsValid()) + data->position = item->position(); + // Folder icon is generated on ash side and chrome side passes a null + // icon here. Skip it. + if (data->icon.isNull()) + data->icon = item->icon(); + item->SetMetadata(std::move(data)); } void AppListControllerImpl::SetItemIcon(const std::string& id,
diff --git a/ash/ash_constants.cc b/ash/ash_constants.cc deleted file mode 100644 index 07ca148..0000000 --- a/ash/ash_constants.cc +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/ash_constants.h" - -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/color_palette.h" - -namespace ash { - -const int kResizeAreaCornerSize = 16; -const int kResizeOutsideBoundsSize = 6; -const int kResizeOutsideBoundsScaleForTouch = 5; -const int kResizeInsideBoundsSize = 1; - -const SkColor kChromeOsBootColor = SkColorSetRGB(0xfe, 0xfe, 0xfe); - -const int kDefaultLargeCursorSize = 64; - -} // namespace ash
diff --git a/ash/assistant/ash_assistant_controller.cc b/ash/assistant/ash_assistant_controller.cc index 53304117..005aaf5 100644 --- a/ash/assistant/ash_assistant_controller.cc +++ b/ash/assistant/ash_assistant_controller.cc
@@ -124,8 +124,13 @@ void AshAssistantController::OnInteractionStateChanged( InteractionState interaction_state) { - if (interaction_state == InteractionState::kInactive) + if (interaction_state == InteractionState::kInactive) { assistant_interaction_model_.ClearInteraction(); + + // TODO(dmblack): Input modality should default back to the user's + // preferred input modality. + assistant_interaction_model_.SetInputModality(InputModality::kVoice); + } } void AshAssistantController::OnInteractionStarted() { @@ -147,8 +152,18 @@ void AshAssistantController::OnDialogPlateContentsChanged( const std::string& text) { - // TODO(dmblack): Close the mic if necessary. assistant_bubble_timer_.Stop(); + + if (text.empty()) { + // Note: This does not open the mic. It only updates the input modality to + // voice so that we will show the mic icon in the UI. + assistant_interaction_model_.SetInputModality(InputModality::kVoice); + } else { + // TODO(dmblack): Instruct the underlying service to stop any in flight + // voice interaction. + assistant_interaction_model_.SetInputModality(InputModality::kKeyboard); + assistant_interaction_model_.SetMicState(MicState::kClosed); + } } void AshAssistantController::OnDialogPlateContentsCommitted( @@ -159,6 +174,10 @@ assistant_interaction_model_.ClearInteraction(); assistant_interaction_model_.SetQuery(query); + // Note: This does not open the mic. It only updates the input modality to + // voice so that we will show the mic icon in the UI. + assistant_interaction_model_.SetInputModality(InputModality::kVoice); + DCHECK(assistant_); assistant_->SendTextQuery(text); } @@ -191,6 +210,8 @@ void AshAssistantController::OnSpeechRecognitionStarted() { assistant_interaction_model_.ClearInteraction(); + assistant_interaction_model_.SetInputModality(InputModality::kVoice); + assistant_interaction_model_.SetMicState(MicState::kOpen); } void AshAssistantController::OnSpeechRecognitionIntermediateResult( @@ -201,8 +222,7 @@ } void AshAssistantController::OnSpeechRecognitionEndOfUtterance() { - // TODO(dmblack): Handle. - NOTIMPLEMENTED(); + assistant_interaction_model_.SetMicState(MicState::kClosed); } void AshAssistantController::OnSpeechRecognitionFinalResult(
diff --git a/ash/assistant/ash_assistant_controller.h b/ash/assistant/ash_assistant_controller.h index 4d1d4e4..6e6f5c1 100644 --- a/ash/assistant/ash_assistant_controller.h +++ b/ash/assistant/ash_assistant_controller.h
@@ -38,7 +38,7 @@ void BindRequest(mojom::AshAssistantControllerRequest request); // Returns a reference to the underlying interaction model. - const AssistantInteractionModel* GetInteractionModel() const { + const AssistantInteractionModel* interaction_model() const { return &assistant_interaction_model_; }
diff --git a/ash/assistant/model/assistant_interaction_model.cc b/ash/assistant/model/assistant_interaction_model.cc index 901c30c..57a9460 100644 --- a/ash/assistant/model/assistant_interaction_model.cc +++ b/ash/assistant/model/assistant_interaction_model.cc
@@ -49,6 +49,14 @@ NotifyInputModalityChanged(); } +void AssistantInteractionModel::SetMicState(MicState mic_state) { + if (mic_state == mic_state_) + return; + + mic_state_ = mic_state; + NotifyMicStateChanged(); +} + void AssistantInteractionModel::AddUiElement( std::unique_ptr<AssistantUiElement> ui_element) { AssistantUiElement* ptr = ui_element.get(); @@ -89,9 +97,13 @@ } void AssistantInteractionModel::NotifyInputModalityChanged() { - for (AssistantInteractionModelObserver& observer : observers_) { + for (AssistantInteractionModelObserver& observer : observers_) observer.OnInputModalityChanged(input_modality_); - } +} + +void AssistantInteractionModel::NotifyMicStateChanged() { + for (AssistantInteractionModelObserver& observer : observers_) + observer.OnMicStateChanged(mic_state_); } void AssistantInteractionModel::NotifyUiElementAdded(
diff --git a/ash/assistant/model/assistant_interaction_model.h b/ash/assistant/model/assistant_interaction_model.h index a8c3c88d..87fbab16 100644 --- a/ash/assistant/model/assistant_interaction_model.h +++ b/ash/assistant/model/assistant_interaction_model.h
@@ -33,6 +33,12 @@ kInactive, }; +// Enumeration of interaction mic states. +enum class MicState { + kClosed, + kOpen, +}; + // TODO(dmblack): It is awkward to use this struct for both text and voice // queries. Break this out into a class and subclass TextQuery and VoiceQuery // respectively. @@ -66,21 +72,27 @@ void AddObserver(AssistantInteractionModelObserver* observer); void RemoveObserver(AssistantInteractionModelObserver* observer); + // Resets the interaction to its initial state. + void ClearInteraction(); + // Sets the interaction state. void SetInteractionState(InteractionState interaction_state); // Returns the interaction state. InteractionState interaction_state() const { return interaction_state_; } - // Resets the interaction to its initial state. - void ClearInteraction(); - // Updates the input modality for the interaction. void SetInputModality(InputModality input_modality); // Returns the input modality for the interaction. InputModality input_modality() const { return input_modality_; } + // Updates the mic state for the interaction. + void SetMicState(MicState mic_state); + + // Returns the mic state for the interaction. + MicState mic_state() const { return mic_state_; } + // Adds the specified |ui_element| that should be rendered for the // interaction. void AddUiElement(std::unique_ptr<AssistantUiElement> ui_element); @@ -107,6 +119,7 @@ private: void NotifyInteractionStateChanged(); void NotifyInputModalityChanged(); + void NotifyMicStateChanged(); void NotifyUiElementAdded(const AssistantUiElement* ui_element); void NotifyUiElementsCleared(); void NotifyQueryChanged(); @@ -116,6 +129,7 @@ InteractionState interaction_state_ = InteractionState::kInactive; InputModality input_modality_; + MicState mic_state_ = MicState::kClosed; Query query_; std::vector<std::string> suggestions_list_; std::vector<std::unique_ptr<AssistantUiElement>> ui_element_list_;
diff --git a/ash/assistant/model/assistant_interaction_model_observer.h b/ash/assistant/model/assistant_interaction_model_observer.h index feaf226..d0dffa1 100644 --- a/ash/assistant/model/assistant_interaction_model_observer.h +++ b/ash/assistant/model/assistant_interaction_model_observer.h
@@ -15,6 +15,7 @@ class AssistantUiElement; enum class InputModality; enum class InteractionState; +enum class MicState; struct Query; // An observer which receives notification of changes to an Assistant @@ -27,6 +28,9 @@ // Invoked when the input modality associated with the interaction is changed. virtual void OnInputModalityChanged(InputModality input_modality) {} + // Invoked when the mic state associated with the interaction is changed. + virtual void OnMicStateChanged(MicState mic_state) {} + // Invoked when a UI element associated with the interaction is added. virtual void OnUiElementAdded(const AssistantUiElement* ui_element) {}
diff --git a/ash/assistant/ui/assistant_bubble_view.cc b/ash/assistant/ui/assistant_bubble_view.cc index bab7564..7c2fa3a 100644 --- a/ash/assistant/ui/assistant_bubble_view.cc +++ b/ash/assistant/ui/assistant_bubble_view.cc
@@ -356,8 +356,8 @@ AssistantBubbleView::AssistantBubbleView( AshAssistantController* assistant_controller) : assistant_controller_(assistant_controller), - interaction_container_(new InteractionContainer( - assistant_controller->GetInteractionModel())), + interaction_container_( + new InteractionContainer(assistant_controller->interaction_model())), ui_element_container_(new UiElementContainer()), suggestions_container_(new SuggestionsContainer(this)), render_request_weak_factory_(this) { @@ -431,7 +431,7 @@ void AssistantBubbleView::OnInputModalityChanged(InputModality input_modality) { // If the query for the interaction is empty, we may need to update the prompt // to reflect the current input modality. - if (assistant_controller_->GetInteractionModel()->query().empty()) { + if (assistant_controller_->interaction_model()->query().empty()) { interaction_container_->ClearQuery(); } }
diff --git a/ash/assistant/ui/dialog_plate.cc b/ash/assistant/ui/dialog_plate.cc index ff5015e..177636d0 100644 --- a/ash/assistant/ui/dialog_plate.cc +++ b/ash/assistant/ui/dialog_plate.cc
@@ -29,9 +29,11 @@ constexpr SkColor kTextColorHint = SkColorSetA(SK_ColorBLACK, 0x42); constexpr SkColor kTextColorPrimary = SkColorSetA(SK_ColorBLACK, 0xDE); -// TODO(dmblack): Remove after removing placeholders. -// Placeholder. -constexpr SkColor kPlaceholderColor = SkColorSetA(SK_ColorBLACK, 0x1F); +// TODO(dmblack): Remove after implementing stateful icon. +// Background colors to represent icon states. +constexpr SkColor kKeyboardColor = SkColorSetRGB(0x4C, 0x8B, 0xF5); // Blue +constexpr SkColor kMicOpenColor = SkColorSetRGB(0xDD, 0x51, 0x44); // Red +constexpr SkColor kMicClosedColor = SkColorSetA(SK_ColorBLACK, 0x1F); // Grey // TODO(b/77638210): Replace with localized resource strings. constexpr char kHint[] = "Type a message"; @@ -66,11 +68,17 @@ // DialogPlate ----------------------------------------------------------------- DialogPlate::DialogPlate(AshAssistantController* assistant_controller) - : assistant_controller_(assistant_controller) { + : assistant_controller_(assistant_controller), icon_(new views::View()) { InitLayout(); + + // The Assistant controller indirectly owns the view hierarchy to which + // DialogPlate belongs, so is guaranteed to outlive it. + assistant_controller_->AddInteractionModelObserver(this); } -DialogPlate::~DialogPlate() = default; +DialogPlate::~DialogPlate() { + assistant_controller_->RemoveInteractionModelObserver(this); +} void DialogPlate::InitLayout() { SetBackground(views::CreateSolidBackground(kBackgroundColor)); @@ -99,12 +107,27 @@ layout->SetFlexForView(textfield, 1); // TODO(dmblack): Replace w/ stateful icon. - // Icon placeholder. - views::View* icon_placeholder = new views::View(); - icon_placeholder->SetBackground(std::make_unique<RoundRectBackground>( - kPlaceholderColor, kIconSizeDip / 2)); - icon_placeholder->SetPreferredSize(gfx::Size(kIconSizeDip, kIconSizeDip)); - AddChildView(icon_placeholder); + // Icon. + icon_->SetPreferredSize(gfx::Size(kIconSizeDip, kIconSizeDip)); + AddChildView(icon_); + + // TODO(dmblack): Remove once the icon has been replaced. Only needed to + // force the background for the initial state. + UpdateIcon(); +} + +void DialogPlate::OnInputModalityChanged(InputModality input_modality) { + // TODO(dmblack): When the stylus is selected we will hide the dialog plate + // and so should suspend any ongoing animations once the stateful icon is + // implemented. + if (input_modality == InputModality::kStylus) + return; + + UpdateIcon(); +} + +void DialogPlate::OnMicStateChanged(MicState mic_state) { + UpdateIcon(); } void DialogPlate::ContentsChanged(views::Textfield* textfield, @@ -135,4 +158,32 @@ return true; } +// TODO(dmblack): Revise this method to update the state of the stateful icon +// once it has been implemented. For the time being, we represent state by +// modifying the background color of the placeholder icon. +void DialogPlate::UpdateIcon() { + const AssistantInteractionModel* interaction_model = + assistant_controller_->interaction_model(); + + if (interaction_model->input_modality() == InputModality::kKeyboard) { + icon_->SetBackground(std::make_unique<RoundRectBackground>( + kKeyboardColor, kIconSizeDip / 2)); + SchedulePaint(); + return; + } + + switch (interaction_model->mic_state()) { + case MicState::kClosed: + icon_->SetBackground(std::make_unique<RoundRectBackground>( + kMicClosedColor, kIconSizeDip / 2)); + break; + case MicState::kOpen: + icon_->SetBackground(std::make_unique<RoundRectBackground>( + kMicOpenColor, kIconSizeDip / 2)); + break; + } + + SchedulePaint(); +} + } // namespace ash
diff --git a/ash/assistant/ui/dialog_plate.h b/ash/assistant/ui/dialog_plate.h index 9850a6b2..b550a54 100644 --- a/ash/assistant/ui/dialog_plate.h +++ b/ash/assistant/ui/dialog_plate.h
@@ -5,6 +5,7 @@ #ifndef ASH_ASSISTANT_UI_DIALOG_PLATE_H_ #define ASH_ASSISTANT_UI_DIALOG_PLATE_H_ +#include "ash/assistant/model/assistant_interaction_model_observer.h" #include "base/macros.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/view.h" @@ -13,11 +14,17 @@ class AshAssistantController; -class DialogPlate : public views::View, public views::TextfieldController { +class DialogPlate : public views::View, + public views::TextfieldController, + public AssistantInteractionModelObserver { public: explicit DialogPlate(AshAssistantController* assistant_controller); ~DialogPlate() override; + // AssistantInteractionModelObserver: + void OnInputModalityChanged(InputModality input_modality) override; + void OnMicStateChanged(MicState mic_state) override; + // views::TextfieldController: void ContentsChanged(views::Textfield* sender, const base::string16& new_contents) override; @@ -26,8 +33,10 @@ private: void InitLayout(); + void UpdateIcon(); AshAssistantController* const assistant_controller_; // Owned by Shell. + views::View* icon_; // Owned by view hierarchy. DISALLOW_COPY_AND_ASSIGN(DialogPlate); };
diff --git a/ash/autoclick/autoclick_controller.cc b/ash/autoclick/autoclick_controller.cc index c7be010..020f0cb55 100644 --- a/ash/autoclick/autoclick_controller.cc +++ b/ash/autoclick/autoclick_controller.cc
@@ -6,6 +6,7 @@ #include "ash/autoclick/common/autoclick_controller_common.h" #include "ash/autoclick/common/autoclick_controller_common_delegate.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/shell.h" #include "ash/wm/root_window_finder.h" @@ -26,8 +27,6 @@ return base::TimeDelta::FromMilliseconds(int64_t{kDefaultAutoclickDelayMs}); } -const int AutoclickController::kDefaultAutoclickDelayMs = 1000; - class AutoclickControllerImpl : public AutoclickController, public ui::EventHandler, public AutoclickControllerCommonDelegate,
diff --git a/ash/autoclick/autoclick_controller.h b/ash/autoclick/autoclick_controller.h index 3c99b30..5b64af5e 100644 --- a/ash/autoclick/autoclick_controller.h +++ b/ash/autoclick/autoclick_controller.h
@@ -30,10 +30,6 @@ static AutoclickController* CreateInstance(); - // The default wait time between last mouse movement and sending - // the autoclick. - static const int kDefaultAutoclickDelayMs; - // Gets the default wait time as a base::TimeDelta object. static base::TimeDelta GetDefaultAutoclickDelay();
diff --git a/ash/components/autoclick/autoclick_application.cc b/ash/components/autoclick/autoclick_application.cc index b4219f2..5f5ba8e 100644 --- a/ash/components/autoclick/autoclick_application.cc +++ b/ash/components/autoclick/autoclick_application.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/shell_window_ids.h" #include "base/bind_helpers.h" #include "base/macros.h" @@ -29,13 +30,6 @@ #include "ui/views/widget/widget_delegate.h" namespace autoclick { -namespace { - -// The default wait time between last mouse movement and sending -// the autoclick. -const int kDefaultAutoclickDelayMs = 1000; - -} // namespace // AutoclickUI handles events to the autoclick app. class AutoclickUI : public views::WidgetDelegateView, @@ -110,7 +104,8 @@ } autoclick_controller_common_ = std::make_unique<ash::AutoclickControllerCommon>( - base::TimeDelta::FromMilliseconds(kDefaultAutoclickDelayMs), this); + base::TimeDelta::FromMilliseconds(ash::kDefaultAutoclickDelayMs), + this); } void AutoclickApplication::OnBindInterface(
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.cc b/ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.cc index 6c8693b..f4930e2 100644 --- a/ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.cc +++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.cc
@@ -157,30 +157,45 @@ if (width <= 0) return; - // The width of |description_label_view_| and |shortcut_label_view_| as a - // ratio of its parent view's width. The unused width is to have some spacing - // in between the two views. - // These values are chosen to put all the bubble views in one line. - constexpr float kDescriptionViewPreferredWidthRatio = 0.29f; + // The max width of |shortcut_label_view_| as a ratio of its parent view's + // width. This value is chosen to put all the bubble views in one line. constexpr float kShortcutViewPreferredWidthRatio = 0.69f; - const int description_view_preferred_width = - width * kDescriptionViewPreferredWidthRatio; + // The minimum spacing between |description_label_view_| and + // |shortcut_label_view_|. + constexpr int kMinimumSpacing = 64; + const int shortcut_view_preferred_width = width * kShortcutViewPreferredWidthRatio; + const int shortcut_view_height = + shortcut_label_view_->GetHeightForWidth(shortcut_view_preferred_width); + + // Sets the bounds and layout in order to get the left most label in the + // |shortcut_label_view_|, which is used to calculate the preferred width for + // |description_label_view_|. + shortcut_label_view_->SetBounds(0, 0, shortcut_view_preferred_width, + shortcut_view_height); + DCHECK(shortcut_label_view_->has_children()); + // Labels in |shortcut_label_view_| are right aligned, so we need to find the + // minimum left coordinates of all the lables. + int min_left = shortcut_view_preferred_width; + for (int i = 0; i < shortcut_label_view_->child_count(); ++i) { + min_left = + std::min(min_left, shortcut_label_view_->child_at(i)->bounds().x()); + } + + // The width of |description_label_view_| will be dynamically adjusted to fill + // the spacing. + const int description_view_preferred_width = + width - (shortcut_view_preferred_width - min_left) - kMinimumSpacing; const int description_view_height = description_label_view_->GetHeightForWidth( description_view_preferred_width); - const int shortcut_view_height = - shortcut_label_view_->GetHeightForWidth(shortcut_view_preferred_width); // Sets the bounds and layout in order to get the center points of the views // making up the top lines in both the description and shortcut views. // We want the center of the top lines in both views to align with each other. description_label_view_->SetBounds(0, 0, description_view_preferred_width, description_view_height); - shortcut_label_view_->SetBounds(0, 0, shortcut_view_preferred_width, - shortcut_view_height); - DCHECK(shortcut_label_view_->has_children() && description_label_view_->has_children()); const int description_view_top_line_center_offset_y =
diff --git a/ash/components/shortcut_viewer_strings.grdp b/ash/components/shortcut_viewer_strings.grdp index 5b94efaa..1ee8445d 100644 --- a/ash/components/shortcut_viewer_strings.grdp +++ b/ash/components/shortcut_viewer_strings.grdp
@@ -97,10 +97,10 @@ <!-- Shortcuts descriptions --> <message name="IDS_KSV_DESCRIPTION_TOGGLE_DOCKED_MAGNIFIER" desc="Description of the command in keyboard shortcut viewer."> - Toggle the Docked Magnifier on or off. + Toggle the Docked Magnifier on or off </message> <message name="IDS_KSV_DESCRIPTION_TOGGLE_FULLSCREEN_MAGNIFIER" desc="Description of the command in keyboard shortcut viewer."> - Toggle the Fullscreen Magnifier on or off. + Toggle the Fullscreen Magnifier on or off </message> <message name="IDS_KSV_DESCRIPTION_LOCK_SCREEN" desc="Description of the command in keyboard shortcut viewer."> Lock screen
diff --git a/ash/content/display/screen_orientation_controller_chromeos_unittest.cc b/ash/content/display/screen_orientation_controller_chromeos_unittest.cc index dd50062..753e05f 100644 --- a/ash/content/display/screen_orientation_controller_chromeos_unittest.cc +++ b/ash/content/display/screen_orientation_controller_chromeos_unittest.cc
@@ -174,15 +174,15 @@ std::unique_ptr<content::WebContents> ScreenOrientationControllerTest::CreateWebContents() { - return base::WrapUnique(content::WebContentsTester::CreateTestWebContents( - ShellContentState::GetInstance()->GetActiveBrowserContext(), nullptr)); + return content::WebContentsTester::CreateTestWebContents( + ShellContentState::GetInstance()->GetActiveBrowserContext(), nullptr); } std::unique_ptr<content::WebContents> ScreenOrientationControllerTest::CreateSecondaryWebContents() { secondary_browser_context_.reset(new content::TestBrowserContext()); - return base::WrapUnique(content::WebContentsTester::CreateTestWebContents( - secondary_browser_context_.get(), nullptr)); + return content::WebContentsTester::CreateTestWebContents( + secondary_browser_context_.get(), nullptr); } void ScreenOrientationControllerTest::SetUp() {
diff --git a/ash/display/cursor_window_controller.cc b/ash/display/cursor_window_controller.cc index d7aa1a6..b028491a 100644 --- a/ash/display/cursor_window_controller.cc +++ b/ash/display/cursor_window_controller.cc
@@ -4,12 +4,12 @@ #include "ash/display/cursor_window_controller.h" -#include "ash/ash_constants.h" #include "ash/components/cursor/cursor_view.h" #include "ash/display/display_color_manager.h" #include "ash/display/mirror_window_controller.h" #include "ash/display/window_tree_host_manager.h" #include "ash/magnifier/magnification_controller.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/shell_window_ids.h"
diff --git a/ash/display/cursor_window_controller.h b/ash/display/cursor_window_controller.h index 3cbf6dc..9b1c6ce 100644 --- a/ash/display/cursor_window_controller.h +++ b/ash/display/cursor_window_controller.h
@@ -7,8 +7,8 @@ #include <memory> -#include "ash/ash_constants.h" #include "ash/ash_export.h" +#include "ash/public/cpp/ash_constants.h" #include "base/macros.h" #include "ui/aura/window.h" #include "ui/base/cursor/cursor.h"
diff --git a/ash/frame/caption_buttons/frame_caption_button.cc b/ash/frame/caption_buttons/frame_caption_button.cc index fe6c13e9..d357ba7 100644 --- a/ash/frame/caption_buttons/frame_caption_button.cc +++ b/ash/frame/caption_buttons/frame_caption_button.cc
@@ -4,7 +4,7 @@ #include "ash/frame/caption_buttons/frame_caption_button.h" -#include "ash/ash_constants.h" +#include "ash/public/cpp/ash_constants.h" #include "ui/gfx/animation/slide_animation.h" #include "ui/gfx/animation/throb_animation.h" #include "ui/gfx/canvas.h"
diff --git a/ash/frame/frame_border_hit_test.cc b/ash/frame/frame_border_hit_test.cc index d174386d..d3cf03b1 100644 --- a/ash/frame/frame_border_hit_test.cc +++ b/ash/frame/frame_border_hit_test.cc
@@ -4,8 +4,8 @@ #include "ash/frame/frame_border_hit_test.h" -#include "ash/ash_constants.h" #include "ash/frame/caption_buttons/frame_caption_button_container_view.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/shell_port.h" #include "ui/base/hit_test.h" #include "ui/views/widget/widget.h"
diff --git a/ash/login/ui/login_bubble.cc b/ash/login/ui/login_bubble.cc index ed4da72..b804f7f2 100644 --- a/ash/login/ui/login_bubble.cc +++ b/ash/login/ui/login_bubble.cc
@@ -7,7 +7,6 @@ #include <memory> #include <utility> -#include "ash/ash_constants.h" #include "ash/focus_cycler.h" #include "ash/login/ui/layout_util.h" #include "ash/login/ui/lock_screen.h" @@ -15,6 +14,7 @@ #include "ash/login/ui/login_button.h" #include "ash/login/ui/login_menu_view.h" #include "ash/login/ui/non_accessible_view.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h"
diff --git a/ash/login/ui/login_button.cc b/ash/login/ui/login_button.cc index bea98eff..9b1ae0f3 100644 --- a/ash/login/ui/login_button.cc +++ b/ash/login/ui/login_button.cc
@@ -4,7 +4,7 @@ #include "ash/login/ui/login_button.h" -#include "ash/ash_constants.h" +#include "ash/public/cpp/ash_constants.h" #include "ui/views/animation/flood_fill_ink_drop_ripple.h" #include "ui/views/animation/ink_drop_highlight.h" #include "ui/views/animation/ink_drop_impl.h"
diff --git a/ash/login/ui/login_pin_view.cc b/ash/login/ui/login_pin_view.cc index 443a5bd1..eec6593 100644 --- a/ash/login/ui/login_pin_view.cc +++ b/ash/login/ui/login_pin_view.cc
@@ -6,8 +6,8 @@ #include <memory> -#include "ash/ash_constants.h" #include "ash/login/ui/login_button.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/login_constants.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/strings/grit/ash_strings.h"
diff --git a/ash/login/ui/login_user_view.cc b/ash/login/ui/login_user_view.cc index 59aa0c5..3b3f768 100644 --- a/ash/login/ui/login_user_view.cc +++ b/ash/login/ui/login_user_view.cc
@@ -6,7 +6,6 @@ #include <memory> -#include "ash/ash_constants.h" #include "ash/login/ui/animated_rounded_image_view.h" #include "ash/login/ui/hover_notifier.h" #include "ash/login/ui/image_parser.h" @@ -15,6 +14,7 @@ #include "ash/login/ui/login_button.h" #include "ash/login/ui/non_accessible_view.h" #include "ash/login/ui/user_switch_flip_animation.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/login_constants.h" #include "ash/public/interfaces/user_info.mojom.h" #include "ash/resources/vector_icons/vector_icons.h"
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index 455bbdf0..11df2f3 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -30,6 +30,7 @@ "app_list/tokenized_string_match.cc", "app_list/tokenized_string_match.h", "app_types.h", + "ash_constants.h", "ash_features.cc", "ash_features.h", "ash_pref_names.cc",
diff --git a/ash/ash_constants.h b/ash/public/cpp/ash_constants.h similarity index 63% rename from ash/ash_constants.h rename to ash/public/cpp/ash_constants.h index fc30bec..0c42973 100644 --- a/ash/ash_constants.h +++ b/ash/public/cpp/ash_constants.h
@@ -2,10 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_ASH_CONSTANTS_H_ -#define ASH_ASH_CONSTANTS_H_ - -#include "ash/ash_export.h" +#ifndef ASH_PUBLIC_CPP_ASH_CONSTANTS_H_ +#define ASH_PUBLIC_CPP_ASH_CONSTANTS_H_ #include "third_party/skia/include/core/SkColor.h" @@ -15,25 +13,28 @@ // In the window corners, the resize areas don't actually expand bigger, but the // 16 px at the end of each edge triggers diagonal resizing. -ASH_EXPORT extern const int kResizeAreaCornerSize; +constexpr int kResizeAreaCornerSize = 16; // Ash windows do not have a traditional visible window frame. Window content // extends to the edge of the window. We consider a small region outside the // window bounds and an even smaller region overlapping the window to be the // "non-client" area and use it for resizing. -ASH_EXPORT extern const int kResizeOutsideBoundsSize; -ASH_EXPORT extern const int kResizeOutsideBoundsScaleForTouch; -ASH_EXPORT extern const int kResizeInsideBoundsSize; +constexpr int kResizeOutsideBoundsSize = 6; +constexpr int kResizeOutsideBoundsScaleForTouch = 5; +constexpr int kResizeInsideBoundsSize = 1; // Background color used for the Chrome OS boot splash screen. -extern const SkColor kChromeOsBootColor; +constexpr SkColor kChromeOsBootColor = SkColorSetRGB(0xfe, 0xfe, 0xfe); // The border color of keyboard focus for launcher items and system tray. constexpr SkColor kFocusBorderColor = SK_ColorTRANSPARENT; constexpr int kFocusBorderThickness = 0; -ASH_EXPORT extern const int kDefaultLargeCursorSize; +constexpr int kDefaultLargeCursorSize = 64; + +// The default wait time between last mouse movement and sending autoclick. +constexpr int kDefaultAutoclickDelayMs = 1000; } // namespace ash -#endif // ASH_ASH_CONSTANTS_H_ +#endif // ASH_PUBLIC_CPP_ASH_CONSTANTS_H_
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc index c25651585..9f297a2 100644 --- a/ash/root_window_controller.cc +++ b/ash/root_window_controller.cc
@@ -12,12 +12,12 @@ #include "ash/accessibility/accessibility_panel_layout_manager.h" #include "ash/accessibility/touch_exploration_controller.h" #include "ash/accessibility/touch_exploration_manager.h" -#include "ash/ash_constants.h" #include "ash/focus_cycler.h" #include "ash/high_contrast/high_contrast_controller.h" #include "ash/host/ash_window_tree_host.h" #include "ash/lock_screen_action/lock_screen_action_background_controller.h" #include "ash/login_status.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/config.h" #include "ash/public/cpp/shelf_types.h"
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc index b6cd2945c..afb0651 100644 --- a/ash/shelf/login_shelf_view.cc +++ b/ash/shelf/login_shelf_view.cc
@@ -7,13 +7,13 @@ #include <memory> #include <utility> -#include "ash/ash_constants.h" #include "ash/focus_cycler.h" #include "ash/lock_screen_action/lock_screen_action_background_controller.h" #include "ash/lock_screen_action/lock_screen_action_background_state.h" #include "ash/login/login_screen_controller.h" #include "ash/login/ui/lock_screen.h" #include "ash/login/ui/lock_window.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/root_window_controller.h" #include "ash/session/session_controller.h"
diff --git a/ash/shelf/shelf_button.cc b/ash/shelf/shelf_button.cc index afddd54..95b555d6 100644 --- a/ash/shelf/shelf_button.cc +++ b/ash/shelf/shelf_button.cc
@@ -7,7 +7,7 @@ #include <algorithm> #include <memory> -#include "ash/ash_constants.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/shelf/ink_drop_button_listener.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_constants.h"
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index 185fe63..2e6d3e6 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -7,9 +7,9 @@ #include <algorithm> #include <memory> -#include "ash/ash_constants.h" #include "ash/drag_drop/drag_image_view.h" #include "ash/metrics/user_metrics_recorder.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/shelf_item_delegate.h" #include "ash/public/cpp/shelf_model.h" #include "ash/scoped_root_window_for_new_windows.h"
diff --git a/ash/shell.cc b/ash/shell.cc index 7115bb5..fda0577 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -19,7 +19,6 @@ #include "ash/accessibility/accessibility_focus_ring_controller.h" #include "ash/accessibility/key_accessibility_enabler.h" #include "ash/app_list/app_list_controller_impl.h" -#include "ash/ash_constants.h" #include "ash/assistant/ash_assistant_controller.h" #include "ash/autoclick/autoclick_controller.h" #include "ash/cast_config_controller.h" @@ -66,6 +65,7 @@ #include "ash/multi_device_setup/multi_device_notification_presenter.h" #include "ash/new_window_controller.h" #include "ash/note_taking_controller.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/config.h"
diff --git a/ash/system/ime_menu/ime_menu_tray.cc b/ash/system/ime_menu/ime_menu_tray.cc index 3bb44a8..562517d 100644 --- a/ash/system/ime_menu/ime_menu_tray.cc +++ b/ash/system/ime_menu/ime_menu_tray.cc
@@ -5,8 +5,8 @@ #include "ash/system/ime_menu/ime_menu_tray.h" #include "ash/accessibility/accessibility_controller.h" -#include "ash/ash_constants.h" #include "ash/ime/ime_controller.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/root_window_controller.h" #include "ash/session/session_controller.h" #include "ash/shelf/shelf.h"
diff --git a/ash/system/tray/actionable_view.cc b/ash/system/tray/actionable_view.cc index 93b54129..65e4b0fa1 100644 --- a/ash/system/tray/actionable_view.cc +++ b/ash/system/tray/actionable_view.cc
@@ -4,7 +4,7 @@ #include "ash/system/tray/actionable_view.h" -#include "ash/ash_constants.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_item.h" #include "ash/system/tray/tray_constants.h"
diff --git a/ash/system/tray/system_menu_button.cc b/ash/system/tray/system_menu_button.cc index e45756a..7ec1b44 100644 --- a/ash/system/tray/system_menu_button.cc +++ b/ash/system/tray/system_menu_button.cc
@@ -4,7 +4,7 @@ #include "ash/system/tray/system_menu_button.h" -#include "ash/ash_constants.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_features.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/tray_constants.h"
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc index 3cc1862..7852b9e 100644 --- a/ash/system/tray/tray_background_view.cc +++ b/ash/system/tray/tray_background_view.cc
@@ -7,10 +7,10 @@ #include <algorithm> #include <memory> -#include "ash/ash_constants.h" #include "ash/focus_cycler.h" #include "ash/login/ui/lock_screen.h" #include "ash/login/ui/lock_window.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_constants.h"
diff --git a/ash/system/tray/tray_popup_utils.cc b/ash/system/tray/tray_popup_utils.cc index c7571196..9b309b0 100644 --- a/ash/system/tray/tray_popup_utils.cc +++ b/ash/system/tray/tray_popup_utils.cc
@@ -8,8 +8,8 @@ #include <memory> #include <utility> -#include "ash/ash_constants.h" #include "ash/ash_view_ids.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_features.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/session/session_controller.h"
diff --git a/ash/system/user/button_from_view.cc b/ash/system/user/button_from_view.cc index 2afb7f5..fa6b3f2e 100644 --- a/ash/system/user/button_from_view.cc +++ b/ash/system/user/button_from_view.cc
@@ -6,7 +6,7 @@ #include "ash/system/user/button_from_view.h" -#include "ash/ash_constants.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_features.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_popup_utils.h"
diff --git a/ash/test/ash_test_environment_content.cc b/ash/test/ash_test_environment_content.cc index 05c1547..b924426 100644 --- a/ash/test/ash_test_environment_content.cc +++ b/ash/test/ash_test_environment_content.cc
@@ -16,8 +16,8 @@ std::unique_ptr<content::WebContents> CreateWebContents( content::BrowserContext* browser_context) { - return base::WrapUnique(content::WebContentsTester::CreateTestWebContents( - browser_context, nullptr)); + return content::WebContentsTester::CreateTestWebContents(browser_context, + nullptr); } } // namespace
diff --git a/ash/wm/non_client_frame_controller.cc b/ash/wm/non_client_frame_controller.cc index 091ef45..308e183 100644 --- a/ash/wm/non_client_frame_controller.cc +++ b/ash/wm/non_client_frame_controller.cc
@@ -10,10 +10,10 @@ #include <string> #include <vector> -#include "ash/ash_constants.h" #include "ash/ash_layout_constants.h" #include "ash/frame/custom_frame_view_ash.h" #include "ash/frame/detached_title_area_renderer.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller_delegate.h" #include "ash/window_manager.h" #include "ash/wm/move_event_handler.h"
diff --git a/ash/wm/resize_handle_window_targeter.cc b/ash/wm/resize_handle_window_targeter.cc index 146be4b..03e5910 100644 --- a/ash/wm/resize_handle_window_targeter.cc +++ b/ash/wm/resize_handle_window_targeter.cc
@@ -4,7 +4,7 @@ #include "ash/wm/resize_handle_window_targeter.h" -#include "ash/ash_constants.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h" #include "ash/wm/window_state.h" #include "ui/aura/window.h"
diff --git a/ash/wm/resize_shadow_and_cursor_unittest.cc b/ash/wm/resize_shadow_and_cursor_unittest.cc index b479f1d..9153c4e 100644 --- a/ash/wm/resize_shadow_and_cursor_unittest.cc +++ b/ash/wm/resize_shadow_and_cursor_unittest.cc
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/ash_constants.h" #include "ash/frame/custom_frame_view_ash.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/wm/cursor_manager_test_api.h"
diff --git a/ash/wm/splitview/split_view_divider.cc b/ash/wm/splitview/split_view_divider.cc index 7b6558b..1f4a93c 100644 --- a/ash/wm/splitview/split_view_divider.cc +++ b/ash/wm/splitview/split_view_divider.cc
@@ -6,8 +6,8 @@ #include <memory> -#include "ash/ash_constants.h" #include "ash/display/screen_orientation_controller.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/shell.h" #include "ash/wm/overview/rounded_rect_view.h"
diff --git a/ash/wm/window_util.cc b/ash/wm/window_util.cc index 946477a..3a763d5 100644 --- a/ash/wm/window_util.cc +++ b/ash/wm/window_util.cc
@@ -7,7 +7,7 @@ #include <memory> #include <vector> -#include "ash/ash_constants.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/config.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/root_window_controller.h"
diff --git a/ash/wm/workspace/multi_window_resize_controller_unittest.cc b/ash/wm/workspace/multi_window_resize_controller_unittest.cc index f94350b..9ac4839 100644 --- a/ash/wm/workspace/multi_window_resize_controller_unittest.cc +++ b/ash/wm/workspace/multi_window_resize_controller_unittest.cc
@@ -4,8 +4,8 @@ #include "ash/wm/workspace/multi_window_resize_controller.h" -#include "ash/ash_constants.h" #include "ash/frame/custom_frame_view_ash.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/shell.h" #include "ash/shell_test_api.h" #include "ash/test/ash_test_base.h"
diff --git a/base/BUILD.gn b/base/BUILD.gn index 8d9a08e..5f04e581 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -729,6 +729,7 @@ "sha1.h", "single_thread_task_runner.h", "stl_util.h", + "strings/char_traits.h", "strings/latin1_string_conversions.cc", "strings/latin1_string_conversions.h", "strings/nullable_string16.cc", @@ -2306,6 +2307,7 @@ "sequenced_task_runner_unittest.cc", "sha1_unittest.cc", "stl_util_unittest.cc", + "strings/char_traits_unittest.cc", "strings/nullable_string16_unittest.cc", "strings/pattern_unittest.cc", "strings/safe_sprintf_unittest.cc",
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java b/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java index d39bf6ba..43ae2591 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java
@@ -13,11 +13,12 @@ import android.os.Looper; import org.chromium.base.Log; -import org.chromium.base.ObserverList; import org.chromium.base.VisibleForTesting; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; +import java.util.Queue; /** * This class is responsible for allocating and managing connections to child @@ -27,17 +28,6 @@ public class ChildConnectionAllocator { private static final String TAG = "ChildConnAllocator"; - /** Listener that clients can use to get notified when connections get allocated/freed. */ - public abstract static class Listener { - /** Called when a connection has been allocated, before it gets bound. */ - public void onConnectionAllocated( - ChildConnectionAllocator allocator, ChildProcessConnection connection) {} - - /** Called when a connection has been freed. */ - public void onConnectionFreed( - ChildConnectionAllocator allocator, ChildProcessConnection connection) {} - } - /** Factory interface. Used by tests to specialize created connections. */ @VisibleForTesting public interface ConnectionFactory { @@ -64,6 +54,9 @@ // Connections to services. Indices of the array correspond to the service numbers. private final ChildProcessConnection[] mChildProcessConnections; + // Runnable which will be called when allocator wants to allocate a new connection, but does + // not have any more free slots. May be null. + private final Runnable mFreeSlotCallback; private final String mPackageName; private final String mServiceClassName; private final boolean mBindToCaller; @@ -73,7 +66,7 @@ // The list of free (not bound) service indices. private final ArrayList<Integer> mFreeConnectionIndices; - private final ObserverList<Listener> mListeners = new ObserverList<>(); + private final Queue<Runnable> mPendingAllocations = new ArrayDeque<>(); private ConnectionFactory mConnectionFactory = new ConnectionFactoryImpl(); @@ -82,8 +75,9 @@ * AndroidManifest.xml. */ public static ChildConnectionAllocator create(Context context, Handler launcherHandler, - String packageName, String serviceClassName, String numChildServicesManifestKey, - boolean bindToCaller, boolean bindAsExternalService, boolean useStrongBinding) { + Runnable freeSlotCallback, String packageName, String serviceClassName, + String numChildServicesManifestKey, boolean bindToCaller, boolean bindAsExternalService, + boolean useStrongBinding) { int numServices = -1; PackageManager packageManager = context.getPackageManager(); try { @@ -109,28 +103,9 @@ throw new RuntimeException("Illegal meta data value: the child service doesn't exist"); } - return new ChildConnectionAllocator(launcherHandler, packageName, serviceClassName, - bindToCaller, bindAsExternalService, useStrongBinding, numServices); - } - - // TODO(jcivelli): remove this method once crbug.com/693484 has been addressed. - public static int getNumberOfServices( - Context context, String packageName, String numChildServicesManifestKey) { - int numServices = -1; - try { - PackageManager packageManager = context.getPackageManager(); - ApplicationInfo appInfo = - packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA); - if (appInfo.metaData != null) { - numServices = appInfo.metaData.getInt(numChildServicesManifestKey, -1); - } - } catch (PackageManager.NameNotFoundException e) { - throw new RuntimeException("Could not get application info", e); - } - if (numServices < 0) { - throw new RuntimeException("Illegal meta data value for number of child services"); - } - return numServices; + return new ChildConnectionAllocator(launcherHandler, freeSlotCallback, packageName, + serviceClassName, bindToCaller, bindAsExternalService, useStrongBinding, + numServices); } /** @@ -138,16 +113,18 @@ * instead of being retrieved from the AndroidManifest.xml. */ @VisibleForTesting - public static ChildConnectionAllocator createForTest(String packageName, - String serviceClassName, int serviceCount, boolean bindToCaller, + public static ChildConnectionAllocator createForTest(Runnable freeSlotCallback, + String packageName, String serviceClassName, int serviceCount, boolean bindToCaller, boolean bindAsExternalService, boolean useStrongBinding) { - return new ChildConnectionAllocator(new Handler(), packageName, serviceClassName, - bindToCaller, bindAsExternalService, useStrongBinding, serviceCount); + return new ChildConnectionAllocator(new Handler(), freeSlotCallback, packageName, + serviceClassName, bindToCaller, bindAsExternalService, useStrongBinding, + serviceCount); } - private ChildConnectionAllocator(Handler launcherHandler, String packageName, - String serviceClassName, boolean bindToCaller, boolean bindAsExternalService, - boolean useStrongBinding, int numChildServices) { + private ChildConnectionAllocator(Handler launcherHandler, Runnable freeSlotCallback, + String packageName, String serviceClassName, boolean bindToCaller, + boolean bindAsExternalService, boolean useStrongBinding, int numChildServices) { + mFreeSlotCallback = freeSlotCallback; mLauncherHandler = launcherHandler; assert isRunningOnLauncherThread(); mPackageName = packageName; @@ -242,10 +219,6 @@ context, serviceName, mBindToCaller, mBindAsExternalService, serviceBundle); mChildProcessConnections[slot] = connection; - for (Listener listener : mListeners) { - listener.onConnectionAllocated(this, connection); - } - connection.start(mUseStrongBinding, serviceCallbackWrapper); Log.d(TAG, "Allocator allocated and bound a connection, name: %s, slot: %d", mServiceClassName, slot); @@ -269,9 +242,20 @@ Log.d(TAG, "Allocator freed a connection, name: %s, slot: %d", mServiceClassName, slot); } - for (Listener listener : mListeners) { - listener.onConnectionFreed(this, connection); - } + if (mPendingAllocations.isEmpty()) return; + mPendingAllocations.remove().run(); + assert mFreeConnectionIndices.isEmpty(); + if (!mPendingAllocations.isEmpty() && mFreeSlotCallback != null) mFreeSlotCallback.run(); + } + + // Can only be called once all slots are full, ie when allocate returns null. + // The callback will be called when a slot becomes free, and should synchronous call + // allocate to take the slot. + public void queueAllocation(Runnable runnable) { + assert mFreeConnectionIndices.isEmpty(); + boolean wasEmpty = mPendingAllocations.isEmpty(); + mPendingAllocations.add(runnable); + if (wasEmpty && mFreeSlotCallback != null) mFreeSlotCallback.run(); } public String getPackageName() { @@ -291,16 +275,6 @@ return mChildProcessConnections.length; } - public void addListener(Listener listener) { - assert !mListeners.hasObserver(listener); - mListeners.addObserver(listener); - } - - public void removeListener(Listener listener) { - boolean removed = mListeners.removeObserver(listener); - assert removed; - } - public boolean isConnectionFromAllocator(ChildProcessConnection connection) { for (ChildProcessConnection existingConnection : mChildProcessConnections) { if (existingConnection == connection) return true;
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java index 556270e..7cdc852 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java
@@ -200,19 +200,9 @@ Log.d(TAG, "Failed to allocate a child connection (no queuing)."); return false; } - // No connection is available at this time. Add a listener so when one becomes - // available we can create the service. - mConnectionAllocator.addListener(new ChildConnectionAllocator.Listener() { - @Override - public void onConnectionFreed( - ChildConnectionAllocator allocator, ChildProcessConnection connection) { - assert allocator == mConnectionAllocator; - if (!allocator.isFreeConnectionAvailable()) return; - allocator.removeListener(this); - allocateAndSetupConnection( - serviceCallback, setupConnection, queueIfNoFreeConnection); - } - }); + mConnectionAllocator.queueAllocation( + () -> allocateAndSetupConnection( + serviceCallback, setupConnection, queueIfNoFreeConnection)); return false; }
diff --git a/base/android/junit/src/org/chromium/base/process_launcher/ChildConnectionAllocatorTest.java b/base/android/junit/src/org/chromium/base/process_launcher/ChildConnectionAllocatorTest.java index 4e24d05..5c5bca9 100644 --- a/base/android/junit/src/org/chromium/base/process_launcher/ChildConnectionAllocatorTest.java +++ b/base/android/junit/src/org/chromium/base/process_launcher/ChildConnectionAllocatorTest.java
@@ -132,9 +132,9 @@ public void setUp() { MockitoAnnotations.initMocks(this); - mAllocator = ChildConnectionAllocator.createForTest(TEST_PACKAGE_NAME, "AllocatorTest", - MAX_CONNECTION_NUMBER, true /* bindToCaller */, false /* bindAsExternalService */, - false /* useStrongBinding */); + mAllocator = ChildConnectionAllocator.createForTest(null, TEST_PACKAGE_NAME, + "AllocatorTest", MAX_CONNECTION_NUMBER, true /* bindToCaller */, + false /* bindAsExternalService */, false /* useStrongBinding */); mAllocator.setConnectionFactoryForTesting(mTestConnectionFactory); } @@ -144,9 +144,6 @@ assertFalse(mAllocator.anyConnectionAllocated()); assertEquals(MAX_CONNECTION_NUMBER, mAllocator.getNumberOfServices()); - ChildConnectionAllocator.Listener listener = mock(ChildConnectionAllocator.Listener.class); - mAllocator.addListener(listener); - ChildProcessConnection connection = mAllocator.allocate(null /* context */, null /* serviceBundle */, mServiceCallback); assertNotNull(connection); @@ -154,7 +151,6 @@ verify(connection, times(1)) .start(eq(false) /* useStrongBinding */, any(ChildProcessConnection.ServiceCallback.class)); - verify(listener, times(1)).onConnectionAllocated(mAllocator, connection); assertTrue(mAllocator.anyConnectionAllocated()); } @@ -177,6 +173,44 @@ null /* context */, null /* serviceBundle */, mServiceCallback)); } + @Test + @Feature({"ProcessManagement"}) + public void testQueueAllocation() { + Runnable freeConnectionCallback = mock(Runnable.class); + mAllocator = ChildConnectionAllocator.createForTest(freeConnectionCallback, + TEST_PACKAGE_NAME, "AllocatorTest", 1, true /* bindToCaller */, + false /* bindAsExternalService */, false /* useStrongBinding */); + mAllocator.setConnectionFactoryForTesting(mTestConnectionFactory); + // Occupy all slots. + ChildProcessConnection connection = + mAllocator.allocate(null /* context */, null /* serviceBundle */, mServiceCallback); + assertNotNull(connection); + assertFalse(mAllocator.isFreeConnectionAvailable()); + + final ChildProcessConnection newConnection[] = new ChildProcessConnection[2]; + Runnable allocate1 = () -> { + newConnection[0] = mAllocator.allocate( + null /* context */, null /* serviceBundle */, mServiceCallback); + }; + Runnable allocate2 = () -> { + newConnection[1] = mAllocator.allocate( + null /* context */, null /* serviceBundle */, mServiceCallback); + }; + mAllocator.queueAllocation(allocate1); + mAllocator.queueAllocation(allocate2); + verify(freeConnectionCallback, times(1)).run(); + assertNull(newConnection[0]); + + mTestConnectionFactory.simulateServiceProcessDying(); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + assertNotNull(newConnection[0]); + assertNull(newConnection[1]); + + mTestConnectionFactory.simulateServiceProcessDying(); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + assertNotNull(newConnection[1]); + } + /** * Tests that the connection is created with the useStrongBinding parameter specified in the * allocator. @@ -185,7 +219,7 @@ @Feature({"ProcessManagement"}) public void testStrongBindingParam() { for (boolean useStrongBinding : new boolean[] {true, false}) { - ChildConnectionAllocator allocator = ChildConnectionAllocator.createForTest( + ChildConnectionAllocator allocator = ChildConnectionAllocator.createForTest(null, TEST_PACKAGE_NAME, "AllocatorTest", MAX_CONNECTION_NUMBER, true /* bindToCaller */, false /* bindAsExternalService */, useStrongBinding); allocator.setConnectionFactoryForTesting(mTestConnectionFactory); @@ -242,12 +276,9 @@ } /** - * Tests that the allocator clears the connection when it fails to bind/process dies and that - * the listener gets invoked. + * Tests that the allocator clears the connection when it fails to bind/process dies. */ private void testFreeConnection(int callbackType) { - ChildConnectionAllocator.Listener listener = mock(ChildConnectionAllocator.Listener.class); - mAllocator.addListener(listener); ChildProcessConnection connection = mAllocator.allocate(null /* context */, null /* serviceBundle */, mServiceCallback); @@ -274,7 +305,6 @@ } ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); assertFalse(mAllocator.anyConnectionAllocated()); - verify(listener, times(1)).onConnectionFreed(mAllocator, connection); verify(mServiceCallback, never()).onChildStarted(); verify(mServiceCallback, times(onChildStartFailedExpectedCount)) .onChildStartFailed(connection);
diff --git a/base/memory/weak_ptr.cc b/base/memory/weak_ptr.cc index f7c8af6..d2a7d89 100644 --- a/base/memory/weak_ptr.cc +++ b/base/memory/weak_ptr.cc
@@ -70,9 +70,13 @@ WeakPtrBase::~WeakPtrBase() = default; WeakPtrBase::WeakPtrBase(const WeakReference& ref, uintptr_t ptr) - : ref_(ref), ptr_(ptr) {} + : ref_(ref), ptr_(ptr) { + DCHECK(ptr_); +} -WeakPtrFactoryBase::WeakPtrFactoryBase(uintptr_t ptr) : ptr_(ptr) {} +WeakPtrFactoryBase::WeakPtrFactoryBase(uintptr_t ptr) : ptr_(ptr) { + DCHECK(ptr_); +} WeakPtrFactoryBase::~WeakPtrFactoryBase() { ptr_ = 0;
diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h index a7be14af..34e7d2e 100644 --- a/base/memory/weak_ptr.h +++ b/base/memory/weak_ptr.h
@@ -307,7 +307,6 @@ ~WeakPtrFactory() = default; WeakPtr<T> GetWeakPtr() { - DCHECK(ptr_); return WeakPtr<T>(weak_reference_owner_.GetRef(), reinterpret_cast<T*>(ptr_)); }
diff --git a/base/strings/char_traits.h b/base/strings/char_traits.h new file mode 100644 index 0000000..6cfbad5af --- /dev/null +++ b/base/strings/char_traits.h
@@ -0,0 +1,90 @@ +// 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 BASE_STRINGS_CHAR_TRAITS_H_ +#define BASE_STRINGS_CHAR_TRAITS_H_ + +#include <stddef.h> + +namespace base { + +// constexpr version of http://en.cppreference.com/w/cpp/string/char_traits. +// This currently just implements the bits needed to support a (mostly) +// constexpr StringPiece. +// +// TODO(dcheng): Once we switch to C++17, most methods will become constexpr and +// we can switch over to using the one in the standard library. +template <typename T> +struct CharTraits { + // Performs a lexographical comparison of the first N characters of |s1| and + // |s2|. Returns 0 if equal, -1 if |s1| is less than |s2|, and 1 if |s1| is + // greater than |s2|. + static constexpr int compare(const T* s1, const T* s2, size_t n) noexcept; + + // Returns the length of |s|, assuming null termination (and not including the + // terminating null). + static constexpr size_t length(const T* s) noexcept; +}; + +template <typename T> +constexpr int CharTraits<T>::compare(const T* s1, + const T* s2, + size_t n) noexcept { + for (; n; --n, ++s1, ++s2) { + if (*s1 < *s2) + return -1; + if (*s1 > *s2) + return 1; + } + return 0; +} + +template <typename T> +constexpr size_t CharTraits<T>::length(const T* s) noexcept { + size_t i = 0; + for (; *s; ++s) + ++i; + return i; +} + +// char specialization of CharTraits that can use clang's constexpr instrinsics, +// where available. +template <> +struct CharTraits<char> { + static constexpr int compare(const char* s1, + const char* s2, + size_t n) noexcept; + static constexpr size_t length(const char* s) noexcept; +}; + +constexpr int CharTraits<char>::compare(const char* s1, + const char* s2, + size_t n) noexcept { +#if __has_feature(cxx_constexpr_string_builtins) + return __builtin_memcmp(s1, s2, n); +#else + for (; n; --n, ++s1, ++s2) { + if (*s1 < *s2) + return -1; + if (*s1 > *s2) + return 1; + } + return 0; +#endif +} + +constexpr size_t CharTraits<char>::length(const char* s) noexcept { +#if defined(__clang__) + return __builtin_strlen(s); +#else + size_t i = 0; + for (; *s; ++s) + ++i; + return i; +#endif +} + +} // namespace base + +#endif // BASE_STRINGS_CHAR_TRAITS_H_
diff --git a/base/strings/char_traits_unittest.cc b/base/strings/char_traits_unittest.cc new file mode 100644 index 0000000..31c421b --- /dev/null +++ b/base/strings/char_traits_unittest.cc
@@ -0,0 +1,32 @@ +// 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/strings/char_traits.h" +#include "base/strings/string16.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { + +TEST(CharTraitsTest, CharCompare) { + static_assert(CharTraits<char>::compare("abc", "def", 3) == -1, ""); + static_assert(CharTraits<char>::compare("def", "def", 3) == 0, ""); + static_assert(CharTraits<char>::compare("ghi", "def", 3) == 1, ""); +} + +TEST(CharTraitsTest, CharLength) { + static_assert(CharTraits<char>::length("") == 0, ""); + static_assert(CharTraits<char>::length("abc") == 3, ""); +} + +TEST(CharTraitsTest, Char16TCompare) { + static_assert(CharTraits<char16_t>::compare(u"abc", u"def", 3) == -1, ""); + static_assert(CharTraits<char16_t>::compare(u"def", u"def", 3) == 0, ""); + static_assert(CharTraits<char16_t>::compare(u"ghi", u"def", 3) == 1, ""); +} + +TEST(CharTraitsTest, Char16TLength) { + static_assert(CharTraits<char16_t>::length(u"abc") == 3, ""); +} + +} // namespace base
diff --git a/base/strings/string_piece.cc b/base/strings/string_piece.cc index c26bb36..c82a223 100644 --- a/base/strings/string_piece.cc +++ b/base/strings/string_piece.cc
@@ -44,7 +44,8 @@ if (x.size() != y.size()) return false; - return StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0; + return CharTraits<StringPiece::value_type>::compare(x.data(), y.data(), + x.size()) == 0; } std::ostream& operator<<(std::ostream& o, const StringPiece& piece) {
diff --git a/base/strings/string_piece.h b/base/strings/string_piece.h index 8a7d0d8..775ea7c 100644 --- a/base/strings/string_piece.h +++ b/base/strings/string_piece.h
@@ -29,6 +29,7 @@ #include "base/base_export.h" #include "base/logging.h" +#include "base/strings/char_traits.h" #include "base/strings/string16.h" #include "base/strings/string_piece_forward.h" @@ -176,9 +177,12 @@ // in a "const char*" or a "string" wherever a "StringPiece" is // expected (likewise for char16, string16, StringPiece16). constexpr BasicStringPiece() : ptr_(NULL), length_(0) {} - BasicStringPiece(const value_type* str) - : ptr_(str), - length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {} + // TODO(dcheng): Construction from nullptr is not allowed for + // std::basic_string_view, so remove the special handling for it. + // Note: This doesn't just use STRING_TYPE::traits_type::length(), since that + // isn't constexpr until C++17. + constexpr BasicStringPiece(const value_type* str) + : ptr_(str), length_(!str ? 0 : CharTraits<value_type>::length(str)) {} BasicStringPiece(const STRING_TYPE& str) : ptr_(str.data()), length_(str.size()) {} constexpr BasicStringPiece(const value_type* offset, size_type len) @@ -245,8 +249,8 @@ length_ -= n; } - int compare(const BasicStringPiece<STRING_TYPE>& x) const { - int r = wordmemcmp( + constexpr int compare(BasicStringPiece x) const noexcept { + int r = CharTraits<value_type>::compare( ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_)); if (r == 0) { if (length_ < x.length_) r = -1; @@ -275,12 +279,6 @@ size_type max_size() const { return length_; } size_type capacity() const { return length_; } - static int wordmemcmp(const value_type* p, - const value_type* p2, - size_type N) { - return STRING_TYPE::traits_type::compare(p, p2, N); - } - // Sets the value of the given string target type to be the current string. // This saves a temporary over doing |a = b.as_string()| void CopyToString(STRING_TYPE* target) const { @@ -296,16 +294,18 @@ } // Does "this" start with "x" - bool starts_with(const BasicStringPiece& x) const { - return ((this->length_ >= x.length_) && - (wordmemcmp(this->ptr_, x.ptr_, x.length_) == 0)); + constexpr bool starts_with(BasicStringPiece x) const noexcept { + return ( + (this->length_ >= x.length_) && + (CharTraits<value_type>::compare(this->ptr_, x.ptr_, x.length_) == 0)); } // Does "this" end with "x" - bool ends_with(const BasicStringPiece& x) const { + constexpr bool ends_with(BasicStringPiece x) const noexcept { return ((this->length_ >= x.length_) && - (wordmemcmp(this->ptr_ + (this->length_-x.length_), - x.ptr_, x.length_) == 0)); + (CharTraits<value_type>::compare( + this->ptr_ + (this->length_ - x.length_), x.ptr_, x.length_) == + 0)); } // find: Search for a character or substring at a given offset. @@ -395,7 +395,7 @@ } inline bool operator<(const StringPiece& x, const StringPiece& y) { - const int r = StringPiece::wordmemcmp( + const int r = CharTraits<StringPiece::value_type>::compare( x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); return ((r < 0) || ((r == 0) && (x.size() < y.size()))); } @@ -418,7 +418,8 @@ if (x.size() != y.size()) return false; - return StringPiece16::wordmemcmp(x.data(), y.data(), x.size()) == 0; + return CharTraits<StringPiece16::value_type>::compare(x.data(), y.data(), + x.size()) == 0; } inline bool operator!=(const StringPiece16& x, const StringPiece16& y) { @@ -426,7 +427,7 @@ } inline bool operator<(const StringPiece16& x, const StringPiece16& y) { - const int r = StringPiece16::wordmemcmp( + const int r = CharTraits<StringPiece16::value_type>::compare( x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); return ((r < 0) || ((r == 0) && (x.size() < y.size()))); }
diff --git a/base/strings/string_piece_unittest.cc b/base/strings/string_piece_unittest.cc index 40e21e9..17d0897 100644 --- a/base/strings/string_piece_unittest.cc +++ b/base/strings/string_piece_unittest.cc
@@ -706,4 +706,100 @@ ASSERT_EQ(empty, BasicStringPiece<TypeParam>(empty.begin(), empty.end())); } +TEST(StringPieceTest, ConstexprCtor) { + { + constexpr StringPiece piece; + std::ignore = piece; + } + + { + constexpr StringPiece piece("abc"); + std::ignore = piece; + } + + { + constexpr StringPiece piece("abc", 2); + std::ignore = piece; + } +} + +TEST(StringPieceTest, ConstexprData) { + { + constexpr StringPiece piece; + static_assert(piece.data() == nullptr, ""); + } + + { + constexpr StringPiece piece("abc"); + static_assert(piece.data()[0] == 'a', ""); + static_assert(piece.data()[1] == 'b', ""); + static_assert(piece.data()[2] == 'c', ""); + } + + { + constexpr StringPiece piece("def", 2); + static_assert(piece.data()[0] == 'd', ""); + static_assert(piece.data()[1] == 'e', ""); + } +} + +TEST(StringPieceTest, ConstexprSize) { + { + constexpr StringPiece piece; + static_assert(piece.size() == 0, ""); + } + + { + constexpr StringPiece piece("abc"); + static_assert(piece.size() == 3, ""); + } + + { + constexpr StringPiece piece("def", 2); + static_assert(piece.size() == 2, ""); + } +} + +TEST(StringPieceTest, Compare) { + constexpr StringPiece piece = "def"; + + static_assert(piece.compare("ab") == 1, ""); + static_assert(piece.compare("abc") == 1, ""); + static_assert(piece.compare("abcd") == 1, ""); + static_assert(piece.compare("de") == 1, ""); + static_assert(piece.compare("def") == 0, ""); + static_assert(piece.compare("defg") == -1, ""); + static_assert(piece.compare("gh") == -1, ""); + static_assert(piece.compare("ghi") == -1, ""); + static_assert(piece.compare("ghij") == -1, ""); +} + +TEST(StringPieceTest, StartsWith) { + constexpr StringPiece piece("abc"); + + static_assert(piece.starts_with(""), ""); + static_assert(piece.starts_with("a"), ""); + static_assert(piece.starts_with("ab"), ""); + static_assert(piece.starts_with("abc"), ""); + + static_assert(!piece.starts_with("b"), ""); + static_assert(!piece.starts_with("bc"), ""); + + static_assert(!piece.starts_with("abcd"), ""); +} + +TEST(StringPieceTest, EndsWith) { + constexpr StringPiece piece("abc"); + + static_assert(piece.ends_with(""), ""); + static_assert(piece.ends_with("c"), ""); + static_assert(piece.ends_with("bc"), ""); + static_assert(piece.ends_with("abc"), ""); + + static_assert(!piece.ends_with("a"), ""); + static_assert(!piece.ends_with("ab"), ""); + + static_assert(!piece.ends_with("abcd"), ""); +} + } // namespace base
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc b/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc index 67c1368..ec3f997 100644 --- a/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc +++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc
@@ -76,9 +76,8 @@ class SchedulerWorkerDelegate : public SchedulerWorker::Delegate { public: - SchedulerWorkerDelegate(const std::string& thread_name, - SchedulerWorker::ThreadLabel thread_label) - : thread_name_(thread_name), thread_label_(thread_label) {} + SchedulerWorkerDelegate(const std::string& thread_name) + : thread_name_(thread_name) {} void set_worker(SchedulerWorker* worker) { DCHECK(!worker_); @@ -92,10 +91,6 @@ worker_->WakeUp(); } - SchedulerWorker::ThreadLabel GetThreadLabel() const final { - return thread_label_; - } - void OnMainEntry(const SchedulerWorker* /* worker */) override { thread_ref_checker_.Set(); PlatformThread::SetName(thread_name_); @@ -154,7 +149,6 @@ private: const std::string thread_name_; - const SchedulerWorker::ThreadLabel thread_label_; // The SchedulerWorker that has |this| as a delegate. Must be set before // starting or posting a task to the SchedulerWorker, because it's used in @@ -177,9 +171,8 @@ class SchedulerWorkerCOMDelegate : public SchedulerWorkerDelegate { public: SchedulerWorkerCOMDelegate(const std::string& thread_name, - SchedulerWorker::ThreadLabel thread_label, TrackedRef<TaskTracker> task_tracker) - : SchedulerWorkerDelegate(thread_name, thread_label), + : SchedulerWorkerDelegate(thread_name), task_tracker_(std::move(task_tracker)) {} ~SchedulerWorkerCOMDelegate() override { DCHECK(!scoped_com_initializer_); } @@ -487,7 +480,7 @@ worker_name += "Shared"; worker_name += environment_params.name_suffix; worker = CreateAndRegisterSchedulerWorker<DelegateType>( - worker_name, thread_mode, environment_params.priority_hint); + worker_name, environment_params.priority_hint); new_worker = true; } started = started_; @@ -526,28 +519,18 @@ template <> std::unique_ptr<SchedulerWorkerDelegate> SchedulerSingleThreadTaskRunnerManager::CreateSchedulerWorkerDelegate< - SchedulerWorkerDelegate>(const std::string& name, - int id, - SingleThreadTaskRunnerThreadMode thread_mode) { + SchedulerWorkerDelegate>(const std::string& name, int id) { return std::make_unique<SchedulerWorkerDelegate>( - StringPrintf("TaskSchedulerSingleThread%s%d", name.c_str(), id), - thread_mode == SingleThreadTaskRunnerThreadMode::DEDICATED - ? SchedulerWorker::ThreadLabel::DEDICATED - : SchedulerWorker::ThreadLabel::SHARED); + StringPrintf("TaskSchedulerSingleThread%s%d", name.c_str(), id)); } #if defined(OS_WIN) template <> std::unique_ptr<SchedulerWorkerDelegate> SchedulerSingleThreadTaskRunnerManager::CreateSchedulerWorkerDelegate< - SchedulerWorkerCOMDelegate>(const std::string& name, - int id, - SingleThreadTaskRunnerThreadMode thread_mode) { + SchedulerWorkerCOMDelegate>(const std::string& name, int id) { return std::make_unique<SchedulerWorkerCOMDelegate>( StringPrintf("TaskSchedulerSingleThreadCOMSTA%s%d", name.c_str(), id), - thread_mode == SingleThreadTaskRunnerThreadMode::DEDICATED - ? SchedulerWorker::ThreadLabel::DEDICATED_COM - : SchedulerWorker::ThreadLabel::SHARED_COM, task_tracker_); } #endif // defined(OS_WIN) @@ -556,12 +539,11 @@ SchedulerWorker* SchedulerSingleThreadTaskRunnerManager::CreateAndRegisterSchedulerWorker( const std::string& name, - SingleThreadTaskRunnerThreadMode thread_mode, ThreadPriority priority_hint) { lock_.AssertAcquired(); int id = next_worker_id_++; std::unique_ptr<SchedulerWorkerDelegate> delegate = - CreateSchedulerWorkerDelegate<DelegateType>(name, id, thread_mode); + CreateSchedulerWorkerDelegate<DelegateType>(name, id); SchedulerWorkerDelegate* delegate_raw = delegate.get(); scoped_refptr<SchedulerWorker> worker = MakeRefCounted<SchedulerWorker>( priority_hint, std::move(delegate), task_tracker_);
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager.h b/base/task_scheduler/scheduler_single_thread_task_runner_manager.h index 80b081c..f0b99d73 100644 --- a/base/task_scheduler/scheduler_single_thread_task_runner_manager.h +++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager.h
@@ -98,13 +98,11 @@ template <typename DelegateType> std::unique_ptr<SchedulerWorkerDelegate> CreateSchedulerWorkerDelegate( const std::string& name, - int id, - SingleThreadTaskRunnerThreadMode thread_mode); + int id); template <typename DelegateType> SchedulerWorker* CreateAndRegisterSchedulerWorker( const std::string& name, - SingleThreadTaskRunnerThreadMode thread_mode, ThreadPriority priority_hint); template <typename DelegateType>
diff --git a/base/task_scheduler/scheduler_worker.cc b/base/task_scheduler/scheduler_worker.cc index 123b3849..7111522 100644 --- a/base/task_scheduler/scheduler_worker.cc +++ b/base/task_scheduler/scheduler_worker.cc
@@ -8,8 +8,6 @@ #include <utility> -#include "base/compiler_specific.h" -#include "base/debug/alias.h" #include "base/logging.h" #include "base/task_scheduler/task_tracker.h" #include "base/trace_event/trace_event.h" @@ -162,112 +160,6 @@ } void SchedulerWorker::ThreadMain() { - if (priority_hint_ == ThreadPriority::BACKGROUND) { - switch (delegate_->GetThreadLabel()) { - case ThreadLabel::POOLED: - RunBackgroundPooledWorker(); - return; - case ThreadLabel::SHARED: - RunBackgroundSharedWorker(); - return; - case ThreadLabel::DEDICATED: - RunBackgroundDedicatedWorker(); - return; -#if defined(OS_WIN) - case ThreadLabel::SHARED_COM: - RunBackgroundSharedCOMWorker(); - return; - case ThreadLabel::DEDICATED_COM: - RunBackgroundDedicatedCOMWorker(); - return; -#endif // defined(OS_WIN) - } - } - - switch (delegate_->GetThreadLabel()) { - case ThreadLabel::POOLED: - RunPooledWorker(); - return; - case ThreadLabel::SHARED: - RunSharedWorker(); - return; - case ThreadLabel::DEDICATED: - RunDedicatedWorker(); - return; -#if defined(OS_WIN) - case ThreadLabel::SHARED_COM: - RunSharedCOMWorker(); - return; - case ThreadLabel::DEDICATED_COM: - RunDedicatedCOMWorker(); - return; -#endif // defined(OS_WIN) - } -} - -NOINLINE void SchedulerWorker::RunPooledWorker() { - const int line_number = __LINE__; - RunWorker(); - base::debug::Alias(&line_number); -} - -NOINLINE void SchedulerWorker::RunBackgroundPooledWorker() { - const int line_number = __LINE__; - RunWorker(); - base::debug::Alias(&line_number); -} - -NOINLINE void SchedulerWorker::RunSharedWorker() { - const int line_number = __LINE__; - RunWorker(); - base::debug::Alias(&line_number); -} - -NOINLINE void SchedulerWorker::RunBackgroundSharedWorker() { - const int line_number = __LINE__; - RunWorker(); - base::debug::Alias(&line_number); -} - -NOINLINE void SchedulerWorker::RunDedicatedWorker() { - const int line_number = __LINE__; - RunWorker(); - base::debug::Alias(&line_number); -} - -NOINLINE void SchedulerWorker::RunBackgroundDedicatedWorker() { - const int line_number = __LINE__; - RunWorker(); - base::debug::Alias(&line_number); -} - -#if defined(OS_WIN) -NOINLINE void SchedulerWorker::RunSharedCOMWorker() { - const int line_number = __LINE__; - RunWorker(); - base::debug::Alias(&line_number); -} - -NOINLINE void SchedulerWorker::RunBackgroundSharedCOMWorker() { - const int line_number = __LINE__; - RunWorker(); - base::debug::Alias(&line_number); -} - -NOINLINE void SchedulerWorker::RunDedicatedCOMWorker() { - const int line_number = __LINE__; - RunWorker(); - base::debug::Alias(&line_number); -} - -NOINLINE void SchedulerWorker::RunBackgroundDedicatedCOMWorker() { - const int line_number = __LINE__; - RunWorker(); - base::debug::Alias(&line_number); -} -#endif // defined(OS_WIN) - -void SchedulerWorker::RunWorker() { DCHECK_EQ(self_, this); TRACE_EVENT_BEGIN0("task_scheduler", "SchedulerWorkerThread active");
diff --git a/base/task_scheduler/scheduler_worker.h b/base/task_scheduler/scheduler_worker.h index b964b59..62257cd 100644 --- a/base/task_scheduler/scheduler_worker.h +++ b/base/task_scheduler/scheduler_worker.h
@@ -44,19 +44,6 @@ : public RefCountedThreadSafe<SchedulerWorker>, public PlatformThread::Delegate { public: - // Labels this SchedulerWorker's association. This doesn't affect any logic - // but will add a stack frame labeling this thread for ease of stack trace - // identification. - enum class ThreadLabel { - POOLED, - SHARED, - DEDICATED, -#if defined(OS_WIN) - SHARED_COM, - DEDICATED_COM, -#endif // defined(OS_WIN) - }; - // Delegate interface for SchedulerWorker. All methods except // OnCanScheduleSequence() (inherited from CanScheduleSequenceObserver) are // called from the thread managed by the SchedulerWorker instance. @@ -64,10 +51,6 @@ public: ~Delegate() override = default; - // Returns the ThreadLabel the Delegate wants its SchedulerWorkers' stacks - // to be labeled with. - virtual ThreadLabel GetThreadLabel() const = 0; - // Called by |worker|'s thread when it enters its main function. virtual void OnMainEntry(const SchedulerWorker* worker) = 0; @@ -173,27 +156,6 @@ // PlatformThread::Delegate: void ThreadMain() override; - // Dummy frames to act as "RunLabeledWorker()" (see RunMain() below). Their - // impl is aliased to prevent compiler/linker from optimizing them out. - void RunPooledWorker(); - void RunBackgroundPooledWorker(); - void RunSharedWorker(); - void RunBackgroundSharedWorker(); - void RunDedicatedWorker(); - void RunBackgroundDedicatedWorker(); -#if defined(OS_WIN) - void RunSharedCOMWorker(); - void RunBackgroundSharedCOMWorker(); - void RunDedicatedCOMWorker(); - void RunBackgroundDedicatedCOMWorker(); -#endif // defined(OS_WIN) - - // The real main, invoked through : - // ThreadMain() -> RunLabeledWorker() -> RunWorker(). - // "RunLabeledWorker()" is a dummy frame based on ThreadLabel+ThreadPriority - // and used to easily identify threads in stack traces. - void RunWorker(); - // Self-reference to prevent destruction of |this| while the thread is alive. // Set in Start() before creating the thread. Reset in ThreadMain() before the // thread exits. No lock required because the first access occurs before the
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.cc b/base/task_scheduler/scheduler_worker_pool_impl.cc index eaed9c2..434f4d08 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl.cc +++ b/base/task_scheduler/scheduler_worker_pool_impl.cc
@@ -73,7 +73,6 @@ // SchedulerWorker::Delegate: void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override; - SchedulerWorker::ThreadLabel GetThreadLabel() const override; void OnMainEntry(const SchedulerWorker* worker) override; scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override; void DidRunTask() override; @@ -385,11 +384,6 @@ outer_->OnCanScheduleSequence(std::move(sequence)); } -SchedulerWorker::ThreadLabel -SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetThreadLabel() const { - return SchedulerWorker::ThreadLabel::POOLED; -} - void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::OnMainEntry( const SchedulerWorker* worker) { DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
diff --git a/base/task_scheduler/scheduler_worker_stack_unittest.cc b/base/task_scheduler/scheduler_worker_stack_unittest.cc index 8707874f..2908a558 100644 --- a/base/task_scheduler/scheduler_worker_stack_unittest.cc +++ b/base/task_scheduler/scheduler_worker_stack_unittest.cc
@@ -25,9 +25,6 @@ void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override { ADD_FAILURE() << "Unexpected call to OnCanScheduleSequence()."; } - SchedulerWorker::ThreadLabel GetThreadLabel() const override { - return SchedulerWorker::ThreadLabel::DEDICATED; - } void OnMainEntry(const SchedulerWorker* worker) override {} scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override { return nullptr;
diff --git a/base/task_scheduler/scheduler_worker_unittest.cc b/base/task_scheduler/scheduler_worker_unittest.cc index 71642bf..0127ad0d 100644 --- a/base/task_scheduler/scheduler_worker_unittest.cc +++ b/base/task_scheduler/scheduler_worker_unittest.cc
@@ -53,9 +53,6 @@ void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override { ADD_FAILURE() << "Unexpected call to OnCanScheduleSequence()."; } - SchedulerWorker::ThreadLabel GetThreadLabel() const override { - return SchedulerWorker::ThreadLabel::DEDICATED; - } void OnMainEntry(const SchedulerWorker* worker) override {} scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override { return nullptr;
diff --git a/base/task_scheduler/task_scheduler_impl_unittest.cc b/base/task_scheduler/task_scheduler_impl_unittest.cc index d3674f5d..89640cf 100644 --- a/base/task_scheduler/task_scheduler_impl_unittest.cc +++ b/base/task_scheduler/task_scheduler_impl_unittest.cc
@@ -13,7 +13,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/callback.h" -#include "base/debug/stack_trace.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/metrics/field_trial.h" @@ -642,83 +641,5 @@ EXPECT_TRUE(called_back); } -namespace { - -// Verifies that |query| is found on the current stack. Ignores failures if this -// configuration doesn't have symbols. -void VerifyHasStringOnStack(const std::string& query) { - const std::string stack = debug::StackTrace().ToString(); - SCOPED_TRACE(stack); - const bool found_on_stack = stack.find(query) != std::string::npos; - const bool stack_has_symbols = - stack.find("SchedulerWorker") != std::string::npos; - EXPECT_TRUE(found_on_stack || !stack_has_symbols) << query; -} - -} // namespace - -// Integration test that verifies that workers have a frame on their stacks -// which easily identifies the type of worker (useful to diagnose issues from -// logs without memory dumps). -TEST_F(TaskSchedulerImplTest, IdentifiableStacks) { - StartTaskScheduler(); - - scheduler_.CreateSequencedTaskRunnerWithTraits({})->PostTask( - FROM_HERE, BindOnce(&VerifyHasStringOnStack, "RunPooledWorker")); - scheduler_.CreateSequencedTaskRunnerWithTraits({TaskPriority::BACKGROUND}) - ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringOnStack, - "RunBackgroundPooledWorker")); - - scheduler_ - .CreateSingleThreadTaskRunnerWithTraits( - {}, SingleThreadTaskRunnerThreadMode::SHARED) - ->PostTask(FROM_HERE, - BindOnce(&VerifyHasStringOnStack, "RunSharedWorker")); - scheduler_ - .CreateSingleThreadTaskRunnerWithTraits( - {TaskPriority::BACKGROUND}, SingleThreadTaskRunnerThreadMode::SHARED) - ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringOnStack, - "RunBackgroundSharedWorker")); - - scheduler_ - .CreateSingleThreadTaskRunnerWithTraits( - {}, SingleThreadTaskRunnerThreadMode::DEDICATED) - ->PostTask(FROM_HERE, - BindOnce(&VerifyHasStringOnStack, "RunDedicatedWorker")); - scheduler_ - .CreateSingleThreadTaskRunnerWithTraits( - {TaskPriority::BACKGROUND}, - SingleThreadTaskRunnerThreadMode::DEDICATED) - ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringOnStack, - "RunBackgroundDedicatedWorker")); - -#if defined(OS_WIN) - scheduler_ - .CreateCOMSTATaskRunnerWithTraits( - {}, SingleThreadTaskRunnerThreadMode::SHARED) - ->PostTask(FROM_HERE, - BindOnce(&VerifyHasStringOnStack, "RunSharedCOMWorker")); - scheduler_ - .CreateCOMSTATaskRunnerWithTraits( - {TaskPriority::BACKGROUND}, SingleThreadTaskRunnerThreadMode::SHARED) - ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringOnStack, - "RunBackgroundSharedCOMWorker")); - - scheduler_ - .CreateCOMSTATaskRunnerWithTraits( - {}, SingleThreadTaskRunnerThreadMode::DEDICATED) - ->PostTask(FROM_HERE, - BindOnce(&VerifyHasStringOnStack, "RunDedicatedCOMWorker")); - scheduler_ - .CreateCOMSTATaskRunnerWithTraits( - {TaskPriority::BACKGROUND}, - SingleThreadTaskRunnerThreadMode::DEDICATED) - ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringOnStack, - "RunBackgroundDedicatedCOMWorker")); -#endif // defined(OS_WIN) - - scheduler_.FlushForTesting(); -} - } // namespace internal } // namespace base
diff --git a/base/test/OWNERS b/base/test/OWNERS index 8b59305..68077483 100644 --- a/base/test/OWNERS +++ b/base/test/OWNERS
@@ -1,10 +1,13 @@ per-file *task_scheduler*=file://base/task_scheduler/OWNERS -# Metrics-related test utilties: +# Metrics-related test utilites: per-file *histogram_tester*=file://base/metrics/OWNERS per-file *scoped_feature_list*=file://base/metrics/OWNERS per-file *user_action_tester*=file://base/metrics/OWNERS +# Tracing test utilities: +per-file trace_*=file://base/trace_event/OWNERS + # For Android-specific changes: per-file *android*=file://base/test/android/OWNERS per-file BUILD.gn=file://base/test/android/OWNERS
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java index 54ced40..d0b1850b 100644 --- a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java +++ b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java
@@ -134,7 +134,7 @@ if (sConnectionAllocator == null) { sConnectionAllocator = ChildConnectionAllocator.create( - ContextUtils.getApplicationContext(), sLauncherHandler, + ContextUtils.getApplicationContext(), sLauncherHandler, null, "org.chromium.native_test", "org.chromium.base.MultiprocessTestClientService", "org.chromium.native_test.NUM_TEST_CLIENT_SERVICES", false /* bindToCaller */, false /* bindAsExternalService */, false /* useStrongBinding */);
diff --git a/base/test/trace_event_analyzer.cc b/base/test/trace_event_analyzer.cc index a822aee..cab2899 100644 --- a/base/test/trace_event_analyzer.cc +++ b/base/test/trace_event_analyzer.cc
@@ -110,6 +110,19 @@ return false; } + dictionary->GetDouble("tdur", &thread_duration); + dictionary->GetDouble("tts", &thread_timestamp); + dictionary->GetString("scope", &scope); + dictionary->GetString("bind_id", &bind_id); + dictionary->GetBoolean("flow_out", &flow_out); + dictionary->GetBoolean("flow_in", &flow_in); + + const base::DictionaryValue* id2; + if (dictionary->GetDictionary("id2", &id2)) { + id2->GetString("global", &global_id2); + id2->GetString("local", &local_id2); + } + // For each argument, copy the type and create a trace_analyzer::TraceValue. for (base::DictionaryValue::Iterator it(*args); !it.IsAtEnd(); it.Advance()) {
diff --git a/base/test/trace_event_analyzer.h b/base/test/trace_event_analyzer.h index ea716bc3..dcdd2e4 100644 --- a/base/test/trace_event_analyzer.h +++ b/base/test/trace_event_analyzer.h
@@ -182,6 +182,14 @@ std::string category; std::string name; std::string id; + double thread_duration = 0.0; + double thread_timestamp = 0.0; + std::string scope; + std::string bind_id; + bool flow_out = false; + bool flow_in = false; + std::string global_id2; + std::string local_id2; // All numbers and bool values from TraceEvent args are cast to double. // bool becomes 1.0 (true) or 0.0 (false). @@ -507,7 +515,6 @@ // This is a recursive method that walks the query tree. bool Evaluate(const TraceEvent& event) const; - private: enum TraceEventMember { EVENT_INVALID, EVENT_PID, @@ -646,6 +653,7 @@ const Query& left() const; const Query& right() const; + private: QueryType type_; Operator operator_; scoped_refptr<QueryNode> left_;
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h index 4bf3e83..b1c67b1 100644 --- a/base/trace_event/trace_event_impl.h +++ b/base/trace_event/trace_event_impl.h
@@ -142,6 +142,10 @@ const char* name() const { return name_; } + unsigned char arg_type(size_t index) const { return arg_types_[index]; } + const char* arg_name(size_t index) const { return arg_names_[index]; } + const TraceValue& arg_value(size_t index) const { return arg_values_[index]; } + #if defined(OS_ANDROID) void SendToATrace(); #endif
diff --git a/build/fuchsia/sdk.sha1 b/build/fuchsia/sdk.sha1 index 9e97b7ae..c63be913 100644 --- a/build/fuchsia/sdk.sha1 +++ b/build/fuchsia/sdk.sha1
@@ -1 +1 @@ -5e56edb6c1a07d13fcab888cc5e2a753a61af349 \ No newline at end of file +f5a0f7997831243e9b67627a6616e9e928c20736 \ No newline at end of file
diff --git a/cc/animation/worklet_animation.cc b/cc/animation/worklet_animation.cc index 5a79260b..a905b94ce 100644 --- a/cc/animation/worklet_animation.cc +++ b/cc/animation/worklet_animation.cc
@@ -11,11 +11,13 @@ WorkletAnimation::WorkletAnimation( int id, const std::string& name, - std::unique_ptr<ScrollTimeline> scroll_timeline) + std::unique_ptr<ScrollTimeline> scroll_timeline, + bool is_controlling_instance) : SingleKeyframeEffectAnimation(id), name_(name), scroll_timeline_(std::move(scroll_timeline)), - last_current_time_(base::nullopt) {} + last_current_time_(base::nullopt), + is_impl_instance_(is_controlling_instance) {} WorkletAnimation::~WorkletAnimation() = default; @@ -24,7 +26,7 @@ const std::string& name, std::unique_ptr<ScrollTimeline> scroll_timeline) { return WrapRefCounted( - new WorkletAnimation(id, name, std::move(scroll_timeline))); + new WorkletAnimation(id, name, std::move(scroll_timeline), false)); } scoped_refptr<Animation> WorkletAnimation::CreateImplInstance() const { @@ -33,7 +35,7 @@ impl_timeline = scroll_timeline_->CreateImplInstance(); return WrapRefCounted( - new WorkletAnimation(id(), name(), std::move(impl_timeline))); + new WorkletAnimation(id(), name(), std::move(impl_timeline), true)); } void WorkletAnimation::SetLocalTime(base::TimeDelta local_time) { @@ -42,6 +44,10 @@ } void WorkletAnimation::Tick(base::TimeTicks monotonic_time) { + // Do not tick worklet animations on main thread. This should be removed if we + // skip ticking all animations on main thread in http://crbug.com/762717. + if (!is_impl_instance_) + return; // As the output of a WorkletAnimation is driven by a script-provided local // time, we don't want the underlying effect to participate in the normal // animations lifecycle. To avoid this we pause the underlying keyframe effect
diff --git a/cc/animation/worklet_animation.h b/cc/animation/worklet_animation.h index d98ee88..cdde572 100644 --- a/cc/animation/worklet_animation.h +++ b/cc/animation/worklet_animation.h
@@ -23,7 +23,8 @@ public: WorkletAnimation(int id, const std::string& name, - std::unique_ptr<ScrollTimeline> scroll_timeline); + std::unique_ptr<ScrollTimeline> scroll_timeline, + bool is_controlling_instance); static scoped_refptr<WorkletAnimation> Create( int id, const std::string& name, @@ -66,6 +67,8 @@ base::TimeDelta local_time_; base::Optional<double> last_current_time_; + + bool is_impl_instance_; }; } // namespace cc
diff --git a/cc/animation/worklet_animation_unittest.cc b/cc/animation/worklet_animation_unittest.cc index e112fb4..5e3020b 100644 --- a/cc/animation/worklet_animation_unittest.cc +++ b/cc/animation/worklet_animation_unittest.cc
@@ -75,6 +75,10 @@ worklet_animation_impl_->SetLocalTime(local_time); TickAnimationsTransferEvents(base::TimeTicks(), 0u); + + TestLayer* layer = + client_.FindTestLayer(element_id_, ElementListType::ACTIVE); + EXPECT_FALSE(layer->is_property_mutated(TargetProperty::OPACITY)); client_impl_.ExpectOpacityPropertyMutated( element_id_, ElementListType::ACTIVE, expected_opacity); }
diff --git a/cc/blink/web_layer_impl.cc b/cc/blink/web_layer_impl.cc index 8548d81a..6bc62e0 100644 --- a/cc/blink/web_layer_impl.cc +++ b/cc/blink/web_layer_impl.cc
@@ -36,12 +36,9 @@ namespace cc_blink { -WebLayerImpl::WebLayerImpl() - : layer_(Layer::Create()), contents_opaque_is_fixed_(false) {} +WebLayerImpl::WebLayerImpl() : layer_(Layer::Create()) {} -WebLayerImpl::WebLayerImpl(scoped_refptr<Layer> layer) - : layer_(layer), contents_opaque_is_fixed_(false) { -} +WebLayerImpl::WebLayerImpl(scoped_refptr<Layer> layer) : layer_(layer) {} WebLayerImpl::~WebLayerImpl() = default; @@ -129,8 +126,6 @@ } void WebLayerImpl::SetOpaque(bool opaque) { - if (contents_opaque_is_fixed_) - return; layer_->SetContentsOpaque(opaque); } @@ -369,10 +364,6 @@ return layer_.get(); } -void WebLayerImpl::SetContentsOpaqueIsFixed(bool fixed) { - contents_opaque_is_fixed_ = fixed; -} - void WebLayerImpl::SetHasWillChangeTransformHint(bool has_will_change) { layer_->SetHasWillChangeTransformHint(has_will_change); }
diff --git a/cc/blink/web_layer_impl.h b/cc/blink/web_layer_impl.h index 2c6107f..1f0f445 100644 --- a/cc/blink/web_layer_impl.h +++ b/cc/blink/web_layer_impl.h
@@ -52,7 +52,6 @@ void SetMaskLayer(blink::WebLayer* mask) override; void SetOpacity(float opacity) override; float Opacity() const override; - void SetContentsOpaqueIsFixed(bool fixed) override; void SetBlendMode(SkBlendMode blend_mode) override; SkBlendMode BlendMode() const override; @@ -129,8 +128,6 @@ protected: scoped_refptr<cc::Layer> layer_; - bool contents_opaque_is_fixed_; - private: DISALLOW_COPY_AND_ASSIGN(WebLayerImpl); };
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc index 3c898c8..3d73714 100644 --- a/cc/layers/layer_unittest.cc +++ b/cc/layers/layer_unittest.cc
@@ -65,6 +65,20 @@ grand_child->layer_tree_host()->LayerNeedsPushPropertiesForTesting( \ grand_child.get())); +#define EXECUTE_AND_VERIFY_SUBTREE_NOT_CHANGED(code_to_test) \ + code_to_test; \ + root->layer_tree_host()->BuildPropertyTreesForTesting(); \ + EXPECT_FALSE(root->subtree_property_changed()); \ + EXPECT_FALSE(root->layer_tree_host()->LayerNeedsPushPropertiesForTesting( \ + root.get())); \ + EXPECT_FALSE(child->subtree_property_changed()); \ + EXPECT_FALSE(child->layer_tree_host()->LayerNeedsPushPropertiesForTesting( \ + child.get())); \ + EXPECT_FALSE(grand_child->subtree_property_changed()); \ + EXPECT_FALSE( \ + grand_child->layer_tree_host()->LayerNeedsPushPropertiesForTesting( \ + grand_child.get())); + #define EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(code_to_test) \ code_to_test; \ EXPECT_FALSE(root->subtree_property_changed()); \
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc index 3b1e14c4..efac77af 100644 --- a/cc/tiles/gpu_image_decode_cache.cc +++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -1345,16 +1345,8 @@ image_info.minRowBytes()); // Set |pixmap| to the desired colorspace to decode into. - if (!SupportsColorSpaceConversion()) { - pixmap.setColorSpace(nullptr); - } else if (image_data->mode == DecodedDataMode::kCpu) { - pixmap.setColorSpace(draw_image.target_color_space().ToSkColorSpace()); - } else { - // For kGpu or kTransferCache images color conversion is handled during - // upload, so keep the original colorspace here. - pixmap.setColorSpace(sk_ref_sp(draw_image.paint_image().color_space())); - } - + pixmap.setColorSpace( + ColorSpaceForImageDecode(draw_image, image_data->mode)); if (!DrawAndScaleImage(draw_image, &pixmap)) { DLOG(ERROR) << "DrawAndScaleImage failed."; backing_memory->Unlock(); @@ -1514,14 +1506,24 @@ } size_t data_size = image_info.computeMinByteSize(); + + // We need to cache the result of color conversion on the cpu if the image + // will be color converted during the decode. + auto decode_color_space = ColorSpaceForImageDecode(draw_image, mode); + const bool cache_color_conversion_on_cpu = + decode_color_space && + !SkColorSpace::Equals(decode_color_space.get(), + draw_image.paint_image().color_space()); + // |is_bitmap_backed| specifies whether the image has pixel data which can // directly be used for the upload. This will be the case for non-lazy images // used at the original scale. In these cases, we don't internally cache any // cpu component for the image. - // However, if the image will be scaled, we consider it a lazy image and cache - // the scaled result in discardable memory. - const bool is_bitmap_backed = - !draw_image.paint_image().IsLazyGenerated() && mip_level == 0; + // However, if the image will be scaled or color converts on the cpu, we + // consider it a lazy image and cache the scaled result in discardable memory. + const bool is_bitmap_backed = !draw_image.paint_image().IsLazyGenerated() && + mip_level == 0 && + !cache_color_conversion_on_cpu; return base::WrapRefCounted(new ImageData( mode, data_size, draw_image.target_color_space(), CalculateDesiredFilterQuality(draw_image), mip_level, is_bitmap_backed)); @@ -1818,6 +1820,20 @@ } } +sk_sp<SkColorSpace> GpuImageDecodeCache::ColorSpaceForImageDecode( + const DrawImage& image, + DecodedDataMode mode) const { + if (!SupportsColorSpaceConversion()) + return nullptr; + + if (mode == DecodedDataMode::kCpu) + return image.target_color_space().ToSkColorSpace(); + + // For kGpu or kTransferCache images color conversion is handled during + // upload, so keep the original colorspace here. + return sk_ref_sp(image.paint_image().color_space()); +} + void GpuImageDecodeCache::CheckContextLockAcquiredIfNecessary() { if (!context_->GetLock()) return;
diff --git a/cc/tiles/gpu_image_decode_cache.h b/cc/tiles/gpu_image_decode_cache.h index 8063575..90374d7a 100644 --- a/cc/tiles/gpu_image_decode_cache.h +++ b/cc/tiles/gpu_image_decode_cache.h
@@ -426,6 +426,9 @@ void CheckContextLockAcquiredIfNecessary(); + sk_sp<SkColorSpace> ColorSpaceForImageDecode(const DrawImage& image, + DecodedDataMode mode) const; + // |persistent_cache_| represents the long-lived cache, keeping a certain // budget of ImageDatas alive even when their ref count reaches zero. using PersistentCache = base::HashingMRUCache<PaintImage::FrameKey,
diff --git a/cc/tiles/gpu_image_decode_cache_unittest.cc b/cc/tiles/gpu_image_decode_cache_unittest.cc index c304be03..91fc94f 100644 --- a/cc/tiles/gpu_image_decode_cache_unittest.cc +++ b/cc/tiles/gpu_image_decode_cache_unittest.cc
@@ -2301,6 +2301,36 @@ cache->UnrefImage(draw_image); } +TEST_P(GpuImageDecodeCacheTest, NonLazyImageLargeImageColorConverted) { + auto cache = CreateCache(); + const bool should_cache_sw_image = + cache->SupportsColorSpaceConversion() && !use_transfer_cache_; + + bool is_decomposable = true; + SkFilterQuality quality = kHigh_SkFilterQuality; + + PaintImage image = CreateBitmapImage(gfx::Size(10, 24000)); + DrawImage draw_image( + image, SkIRect::MakeWH(image.width(), image.height()), quality, + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), + PaintImage::kDefaultFrameIndex, gfx::ColorSpace::CreateDisplayP3D65()); + viz::ContextProvider::ScopedContextLock context_lock(context_provider()); + DecodedDrawImage decoded_draw_image = + EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image)); + EXPECT_TRUE(decoded_draw_image.image()); + EXPECT_TRUE(decoded_draw_image.is_budgeted()); + cache->DrawWithImageFinished(draw_image, decoded_draw_image); + // For non-lazy images color converted during scaling, cpu component should be + // cached. + auto sw_image = cache->GetSWImageDecodeForTesting(draw_image); + ASSERT_EQ(!!sw_image, should_cache_sw_image); + if (should_cache_sw_image) { + EXPECT_TRUE(SkColorSpace::Equals( + sw_image->colorSpace(), + gfx::ColorSpace::CreateDisplayP3D65().ToSkColorSpace().get())); + } +} + TEST_P(GpuImageDecodeCacheTest, NonLazyImageUploadDownscaled) { auto cache = CreateCache(); bool is_decomposable = true;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 6caae2e0..a8772a5c3 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -1892,6 +1892,12 @@ gfx::ScrollOffsetToVector2dF(active_tree_->TotalScrollOffset()); metadata.root_background_color = active_tree_->background_color(); metadata.is_scroll_offset_at_top = active_tree_->TotalScrollOffset().y() == 0; + metadata.device_scale_factor = active_tree_->painted_device_scale_factor() * + active_tree_->device_scale_factor(); + metadata.viewport_size_in_pixels = device_viewport_size(); + if (active_tree()->local_surface_id().is_valid()) + metadata.local_surface_id = active_tree()->local_surface_id(); + active_tree_->GetViewportSelection(&metadata.selection); metadata.is_mobile_optimized = IsMobileOptimized(active_tree_.get());
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 82d50cc8..4aab626 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -531,7 +531,9 @@ ManagedMemoryPolicy ActualManagedMemoryPolicy() const; void SetViewportSize(const gfx::Size& device_viewport_size); - gfx::Size device_viewport_size() const { return device_viewport_size_; } + const gfx::Size& device_viewport_size() const { + return device_viewport_size_; + } void SetViewportVisibleRect(const gfx::Rect& visible_rect); gfx::Rect viewport_visible_rect() const { return viewport_visible_rect_; }
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 410e493..34cc3a3 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -65,6 +65,7 @@ #include "components/viz/service/display/output_surface.h" #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/fake_output_surface.h" +#include "components/viz/test/test_gles2_interface.h" #include "components/viz/test/test_layer_tree_frame_sink.h" #include "components/viz/test/test_web_graphics_context_3d.h" #include "gpu/GLES2/gl2extchromium.h" @@ -8143,8 +8144,30 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSubmitFrameMetadata); +class VideoGLES2Interface : public viz::TestGLES2Interface { + public: + VideoGLES2Interface() = default; + + void InitializeTestContext(viz::TestWebGraphicsContext3D* context) override { + context->set_have_extension_egl_image(true); + } +}; + class LayerTreeHostTestSubmitFrameResources : public LayerTreeHostTest { protected: + std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + const viz::RendererSettings& renderer_settings, + double refresh_rate, + scoped_refptr<viz::ContextProvider> compositor_context_provider, + scoped_refptr<viz::RasterContextProvider> worker_context_provider) + override { + auto provider = viz::TestContextProvider::Create( + std::make_unique<VideoGLES2Interface>()); + return LayerTreeTest::CreateLayerTreeFrameSink( + renderer_settings, refresh_rate, std::move(provider), + std::move(worker_context_provider)); + } + void BeginTest() override { PostSetNeedsCommitToMainThread(); } DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc index 7aab1e5f..66d838c5 100644 --- a/cc/trees/layer_tree_host_unittest_context.cc +++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -34,6 +34,7 @@ #include "cc/trees/single_thread_proxy.h" #include "components/viz/common/resources/single_release_callback.h" #include "components/viz/test/test_context_provider.h" +#include "components/viz/test/test_gles2_interface.h" #include "components/viz/test/test_layer_tree_frame_sink.h" #include "components/viz/test/test_shared_bitmap_manager.h" #include "components/viz/test/test_web_graphics_context_3d.h" @@ -51,12 +52,27 @@ return base::TimeTicks() + base::TimeDelta::FromMicroseconds(micros); } +class IOSurfaceGLES2Interface : public viz::TestGLES2Interface { + public: + explicit IOSurfaceGLES2Interface(bool context_should_support_io_surface) + : context_should_support_io_surface_(context_should_support_io_surface) {} + + void InitializeTestContext(viz::TestWebGraphicsContext3D* context) override { + if (context_should_support_io_surface_) { + context->set_have_extension_io_surface(true); + context->set_have_extension_egl_image(true); + } + } + + private: + bool context_should_support_io_surface_; +}; + // These tests deal with losing the 3d graphics context. class LayerTreeHostContextTest : public LayerTreeTest { public: LayerTreeHostContextTest() : LayerTreeTest(), - context3d_(nullptr), times_to_fail_create_(0), times_to_lose_during_commit_(0), times_to_lose_during_draw_(0), @@ -72,15 +88,15 @@ void LoseContext() { // CreateDisplayLayerTreeFrameSink happens on a different thread, so lock - // context3d_ to make sure we don't set it to null after recreating it + // gl_ to make sure we don't set it to null after recreating it // there. - base::AutoLock lock(context3d_lock_); + base::AutoLock lock(gl_lock_); // For sanity-checking tests, they should only call this when the // context is not lost. - CHECK(context3d_); - context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, - GL_INNOCENT_CONTEXT_RESET_ARB); - context3d_ = nullptr; + CHECK(gl_); + gl_->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, + GL_INNOCENT_CONTEXT_RESET_ARB); + gl_ = nullptr; } std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( @@ -89,26 +105,22 @@ scoped_refptr<viz::ContextProvider> compositor_context_provider, scoped_refptr<viz::RasterContextProvider> worker_context_provider) override { - base::AutoLock lock(context3d_lock_); + base::AutoLock lock(gl_lock_); - std::unique_ptr<viz::TestWebGraphicsContext3D> compositor_context3d = - viz::TestWebGraphicsContext3D::Create(); - if (context_should_support_io_surface_) { - compositor_context3d->set_have_extension_io_surface(true); - compositor_context3d->set_have_extension_egl_image(true); - } - context3d_ = compositor_context3d.get(); + auto gl_owned = std::make_unique<IOSurfaceGLES2Interface>( + context_should_support_io_surface_); + gl_ = gl_owned.get(); + auto provider = viz::TestContextProvider::Create(std::move(gl_owned)); if (times_to_fail_create_) { --times_to_fail_create_; ExpectCreateToFail(); - context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, - GL_INNOCENT_CONTEXT_RESET_ARB); + gl_->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, + GL_INNOCENT_CONTEXT_RESET_ARB); } return LayerTreeTest::CreateLayerTreeFrameSink( - renderer_settings, refresh_rate, - viz::TestContextProvider::Create(std::move(compositor_context3d)), + renderer_settings, refresh_rate, std::move(provider), std::move(worker_context_provider)); } @@ -158,10 +170,10 @@ void ExpectCreateToFail() { ++times_to_expect_create_failed_; } protected: - // Protects use of context3d_ so LoseContext and + // Protects use of gl_ so LoseContext and // CreateDisplayLayerTreeFrameSink can both use it on different threads. - base::Lock context3d_lock_; - viz::TestWebGraphicsContext3D* context3d_; + base::Lock gl_lock_; + viz::TestGLES2Interface* gl_ = nullptr; int times_to_fail_create_; int times_to_lose_during_commit_; @@ -1008,7 +1020,7 @@ if (host_impl->active_tree()->source_frame_number() == 2) { // Lose the context after draw on the second commit. This will cause // a third commit to recover. - context3d_->set_times_bind_texture_succeeds(0); + gl_->set_times_bind_texture_succeeds(0); } return draw_result; } @@ -1480,7 +1492,7 @@ void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl, bool visible) override { if (!visible) { // All resources should have been evicted. - ASSERT_EQ(0u, context3d_->NumTextures()); + ASSERT_EQ(0u, gl_->NumTextures()); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource2_->id())); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource3_->id())); @@ -1500,7 +1512,7 @@ case 1: // The first two resources should have been created on LTHI after the // commit. - ASSERT_EQ(2u, context3d_->NumTextures()); + ASSERT_EQ(2u, gl_->NumTextures()); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource2_->id())); EXPECT_EQ(1, ui_resource_->resource_create_count); @@ -1508,7 +1520,7 @@ EXPECT_TRUE(impl->CanDraw()); // Evict all UI resources. This will trigger a commit. impl->EvictAllUIResources(); - ASSERT_EQ(0u, context3d_->NumTextures()); + ASSERT_EQ(0u, gl_->NumTextures()); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource2_->id())); EXPECT_EQ(1, ui_resource_->resource_create_count); @@ -1517,7 +1529,7 @@ break; case 2: // The first two resources should have been recreated. - ASSERT_EQ(2u, context3d_->NumTextures()); + ASSERT_EQ(2u, gl_->NumTextures()); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(2, ui_resource_->resource_create_count); EXPECT_EQ(1, ui_resource_->lost_resource_count); @@ -1529,7 +1541,7 @@ case 3: // The first resource should have been recreated after visibility was // restored. - ASSERT_EQ(2u, context3d_->NumTextures()); + ASSERT_EQ(2u, gl_->NumTextures()); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(3, ui_resource_->resource_create_count); EXPECT_EQ(2, ui_resource_->lost_resource_count);
diff --git a/cc/trees/render_frame_metadata.cc b/cc/trees/render_frame_metadata.cc index 9283520..2559925 100644 --- a/cc/trees/render_frame_metadata.cc +++ b/cc/trees/render_frame_metadata.cc
@@ -22,7 +22,10 @@ return rfm1.root_background_color != rfm2.root_background_color || rfm1.is_scroll_offset_at_top != rfm2.is_scroll_offset_at_top || rfm1.selection != rfm2.selection || - rfm1.is_mobile_optimized != rfm2.is_mobile_optimized; + rfm1.is_mobile_optimized != rfm2.is_mobile_optimized || + rfm1.device_scale_factor != rfm2.device_scale_factor || + rfm1.viewport_size_in_pixels != rfm2.viewport_size_in_pixels || + rfm1.local_surface_id != rfm2.local_surface_id; } RenderFrameMetadata& RenderFrameMetadata::operator=( @@ -36,7 +39,10 @@ root_background_color == other.root_background_color && is_scroll_offset_at_top == other.is_scroll_offset_at_top && selection == other.selection && - is_mobile_optimized == other.is_mobile_optimized; + is_mobile_optimized == other.is_mobile_optimized && + device_scale_factor == other.device_scale_factor && + viewport_size_in_pixels == other.viewport_size_in_pixels && + local_surface_id == other.local_surface_id; } bool RenderFrameMetadata::operator!=(const RenderFrameMetadata& other) {
diff --git a/cc/trees/render_frame_metadata.h b/cc/trees/render_frame_metadata.h index 98013a2..c76d498 100644 --- a/cc/trees/render_frame_metadata.h +++ b/cc/trees/render_frame_metadata.h
@@ -8,7 +8,9 @@ #include "base/optional.h" #include "cc/cc_export.h" #include "components/viz/common/quads/selection.h" +#include "components/viz/common/surfaces/local_surface_id.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/vector2d_f.h" #include "ui/gfx/selection_bound.h" @@ -55,6 +57,15 @@ // - page prevents zooming in or out (i.e. min and max page scale factors // are the same). bool is_mobile_optimized = false; + + // The device scale factor used to generate a CompositorFrame. + float device_scale_factor = 1.f; + + // The size of the viewport used to generate a CompositorFrame. + gfx::Size viewport_size_in_pixels; + + // The last viz::LocalSurfaceId used to submit a CompositorFrame. + base::Optional<viz::LocalSurfaceId> local_surface_id; }; } // namespace cc
diff --git a/chrome/VERSION b/chrome/VERSION index 610b552..bc1886a 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=68 MINOR=0 -BUILD=3421 +BUILD=3423 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ChromeHomeFeedbackSource.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ChromeHomeFeedbackSource.java deleted file mode 100644 index a9bf26da..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ChromeHomeFeedbackSource.java +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.feedback; - -import android.util.Pair; - -import org.chromium.base.CollectionUtil; -import org.chromium.base.VisibleForTesting; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.util.FeatureUtilities; - -import java.util.Map; - -/** Grabs feedback about the current opt-in/out state of Chrome Home. */ -class ChromeHomeFeedbackSource implements FeedbackSource { - /** A user visible string describing Chrome Home's current enabled state. */ - @VisibleForTesting - static final String CHROME_HOME_STATE_KEY = "Chrome Home State"; - private static final String CHROME_HOME_ENABLED_VALUE = "Enabled"; - private static final String CHROME_HOME_DISABLED_VALUE = "Disabled"; - - private final boolean mIsOffTheRecord; - - ChromeHomeFeedbackSource(Profile profile) { - mIsOffTheRecord = profile.isOffTheRecord(); - } - - @Override - public Map<String, String> getFeedback() { - if (mIsOffTheRecord) return null; - - String value = FeatureUtilities.isChromeHomeEnabled() ? CHROME_HOME_ENABLED_VALUE - : CHROME_HOME_DISABLED_VALUE; - - return CollectionUtil.newHashMap(Pair.create(CHROME_HOME_STATE_KEY, value)); - } -} \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java index 363cc24..6991b90 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java
@@ -80,7 +80,6 @@ sources.add(new VariationsFeedbackSource(profile)); sources.add(new DataReductionProxyFeedbackSource(profile)); sources.add(new HistogramFeedbackSource(profile)); - sources.add(new ChromeHomeFeedbackSource(profile)); sources.add(new LowEndDeviceFeedbackSource()); sources.add(new IMEFeedbackSource()); sources.add(new PermissionFeedbackSource()); @@ -225,4 +224,4 @@ CollectionUtil.forEach(mSynchronousSources, worker); CollectionUtil.forEach(mAsynchronousSources, worker); } -} \ No newline at end of file +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java index ae134398..355c3265 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java
@@ -112,8 +112,6 @@ public Boolean isContextMenuItemSupported(@ContextMenuItemId int menuItemId) { if (menuItemId == ContextMenuManager.ID_REMOVE) return null; - if (mCategory == KnownCategories.RECENT_TABS) return false; - if (mCategory == KnownCategories.DOWNLOADS) { if (menuItemId == ContextMenuManager.ID_OPEN_IN_INCOGNITO_TAB) return false; if (menuItemId == ContextMenuManager.ID_SAVE_FOR_OFFLINE) return false; @@ -137,7 +135,7 @@ navigationDelegate.navigateToRecentTabs(); break; case KnownCategories.PHYSICAL_WEB_PAGES_DEPRECATED: - case KnownCategories.RECENT_TABS: + case KnownCategories.RECENT_TABS_DEPRECATED: case KnownCategories.ARTICLES: default: Log.wtf(TAG, "'Empty State' action called for unsupported category: %d", mCategory);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java index 61f4be50..65bc4601 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java
@@ -242,30 +242,7 @@ @Override public boolean requiresExactOfflinePage() { - return isDownload() || isRecentTab(); - } - - public boolean isRecentTab() { - return mCategory == KnownCategories.RECENT_TABS; - } - - /** - * @return the corresponding recent tab id. May only be called if this snippet is a recent tab - * article. - */ - public int getRecentTabId() { - assert isRecentTab(); - return mRecentTabId; - } - - /** - * Sets tab id and offline page id for recent tab articles. May only be called if this snippet - * is a recent tab article. - */ - public void setRecentTabData(int tabId, long offlinePageId) { - assert isRecentTab(); - mRecentTabId = tabId; - setOfflinePageOfflineId(offlinePageId); + return isDownload(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java index 6594ff7..97d3923 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java
@@ -219,12 +219,6 @@ } @CalledByNative - private static void setRecentTabDataForSuggestion( - SnippetArticle suggestion, int tabId, long offlinePageId) { - suggestion.setRecentTabData(tabId, offlinePageId); - } - - @CalledByNative private static SuggestionsCategoryInfo createSuggestionsCategoryInfo(int category, String title, @ContentSuggestionsCardLayout int cardLayout, @ContentSuggestionsAdditionalAction int additionalAction, boolean showIfEmpty,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java index 505c95c..ad6c9fc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java
@@ -612,21 +612,11 @@ return nativeIsShowingDownloadButtonInErrorPage(mNativeOfflinePageBridge, webContents); } - /** Tells the native side that a new tab has been added for this profile. */ - void registerRecentTab(int tabId) { - nativeRegisterRecentTab(mNativeOfflinePageBridge, tabId); - } - /** Tells the native side that the tab of |webContents| will be closed. */ void willCloseTab(WebContents webContents) { nativeWillCloseTab(mNativeOfflinePageBridge, webContents); } - /** Tells the native side that a new tab has been removed for this profile. */ - void unregisterRecentTab(int tabId) { - nativeUnregisterRecentTab(mNativeOfflinePageBridge, tabId); - } - /** * Schedules to download a page from |url| and categorize under |nameSpace|. * The duplicate pages or requests will be checked. @@ -829,9 +819,7 @@ @VisibleForTesting native void nativeGetAllPages(long nativeOfflinePageBridge, List<OfflinePageItem> offlinePages, final Callback<List<OfflinePageItem>> callback); - private native void nativeRegisterRecentTab(long nativeOfflinePageBridge, int tabId); private native void nativeWillCloseTab(long nativeOfflinePageBridge, WebContents webContents); - private native void nativeUnregisterRecentTab(long nativeOfflinePageBridge, int tabId); @VisibleForTesting native void nativeGetRequestsInQueue(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java index 3ab6f42..3d45e94 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -689,11 +689,6 @@ @Override public void didAddTab(Tab tab, TabModel.TabLaunchType type) { tab.addObserver(sTabRestoreTracker); - - Profile profile = mTabModelSelector.getModel(tab.isIncognito()).getProfile(); - OfflinePageBridge bridge = OfflinePageBridge.getForProfile(profile); - if (bridge == null) return; - bridge.registerRecentTab(tab.getId()); } @Override @@ -712,10 +707,7 @@ OfflinePageBridge bridge = OfflinePageBridge.getForProfile(profile); if (bridge == null) return; - // First, unregister the tab with the UI. - bridge.unregisterRecentTab(tabId); - - // Then, delete any "Last N" offline pages as well. This is an optimization because + // Delete any "Last N" offline pages as well. This is an optimization because // the UI will no longer show the page, and the page would also be cleaned up by GC // given enough time. ClientId clientId =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsEventReporterBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsEventReporterBridge.java index 9b167d8..7cf2731 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsEventReporterBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsEventReporterBridge.java
@@ -61,9 +61,8 @@ case KnownCategories.BOOKMARKS: NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_BOOKMARKS_MANAGER); break; - // MORE button in both categories leads to the recent tabs manager + // MORE button leads to the recent tabs manager case KnownCategories.FOREIGN_TABS: - case KnownCategories.RECENT_TABS: NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_RECENT_TABS_MANAGER); break; case KnownCategories.DOWNLOADS:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java index 1f61d29f..1215d57 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java
@@ -27,10 +27,8 @@ import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabModelSelector; -import org.chromium.chrome.browser.tabmodel.TabModelUtils; import org.chromium.chrome.browser.tabmodel.document.TabDelegate; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.common.Referrer; @@ -119,13 +117,6 @@ return; } - if (article.isRecentTab()) { - assert windowOpenDisposition == WindowOpenDisposition.CURRENT_TAB; - boolean success = openRecentTabSnippet(article); - assert success; - return; - } - // We explicitly open an offline page only for offline page downloads or for prefetched // offline pages when Data Reduction Proxy is enabled. For all other // sections the URL is opened and it is up to Offline Pages whether to open its offline @@ -204,15 +195,6 @@ return loadingTab; } - private boolean openRecentTabSnippet(SnippetArticle article) { - TabModel tabModel = mTabModelSelector.getModel(false); - int tabId = article.getRecentTabId(); - int tabIndex = TabModelUtils.getTabIndexById(tabModel, tabId); - if (tabIndex == TabModel.INVALID_TAB_INDEX) return false; - TabModelUtils.setIndex(tabModel, tabIndex); - return true; - } - private void openUrlInNewWindow(LoadUrlParams loadUrlParams) { TabDelegate tabDelegate = new TabDelegate(false); tabDelegate.createTabInOtherWindow(loadUrlParams, mActivity, mHost.getParentId());
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 5e7fff4..e8c6bd97 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -448,7 +448,6 @@ "java/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitorDelegate.java", "java/src/org/chromium/chrome/browser/feedback/AsyncFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/AsyncFeedbackSourceAdapter.java", - "java/src/org/chromium/chrome/browser/feedback/ChromeHomeFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/ConnectivityChecker.java", "java/src/org/chromium/chrome/browser/feedback/ConnectivityFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/ConnectivityTask.java",
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfoTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfoTest.java index 3b25ea2..d30deb23 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfoTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfoTest.java
@@ -42,24 +42,6 @@ } @Test - public void testRecentTabContextMenu() { - SuggestionsCategoryInfo categoryInfo = - new CategoryInfoBuilder(KnownCategories.RECENT_TABS).build(); - assertThat( - categoryInfo.isContextMenuItemSupported(ContextMenuManager.ID_OPEN_IN_NEW_WINDOW), - is(false)); - assertThat(categoryInfo.isContextMenuItemSupported(ContextMenuManager.ID_OPEN_IN_NEW_TAB), - is(false)); - assertThat(categoryInfo.isContextMenuItemSupported( - ContextMenuManager.ID_OPEN_IN_INCOGNITO_TAB), - is(false)); - assertThat(categoryInfo.isContextMenuItemSupported(ContextMenuManager.ID_SAVE_FOR_OFFLINE), - is(false)); - assertThat( - categoryInfo.isContextMenuItemSupported(ContextMenuManager.ID_REMOVE), nullValue()); - } - - @Test public void testArticleContextMenu() { SuggestionsCategoryInfo categoryInfo = new CategoryInfoBuilder(KnownCategories.ARTICLES).build();
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index e09cead..3ecb095 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-68.0.3420.0_rc-r1.afdo.bz2 \ No newline at end of file +chromeos-chrome-amd64-68.0.3422.0_rc-r1.afdo.bz2 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index ba8fc60d..74a2e57 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2887,6 +2887,7 @@ "//services/ui/public/cpp/input_devices", "//services/ui/public/cpp/input_devices:input_device_controller", "//services/ui/public/interfaces", + "//services/ui/ws2:lib", "//ui/ozone", ] allow_circular_includes_from += [ "//chrome/browser/chromeos" ] @@ -3793,7 +3794,6 @@ "//components/offline_pages/core/background:background_offliner", "//components/offline_pages/core/downloads:offline_pages_ui_adapter", "//components/offline_pages/core/prefetch", - "//components/offline_pages/core/recent_tabs", "//components/offline_pages/core/renovations", "//components/offline_pages/core/request_header:request_header", ]
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index db2bd6a..fc9672c 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -209,8 +209,15 @@ ] specific_include_rules = { - "browser_process_platform_part_chromeos\.cc": [ - # AshService is necessary while Ash runs in process. + "ash_service_registry\.cc": [ + # The following are needed for classic mode to create the WindowService. + # Once Ash runs out of process no longer needed. + "+ash/content/content_gpu_support.h", + "+ash/shell.h", + "+ash/ws/window_service_delegate_impl.h", + "+services/ui/ws2/window_service.h", + + # Needed for classic mode. "+ash/ash_service.h", ], # TODO(mash): see bugs 768439 and 768395.
diff --git a/chrome/browser/android/ntp/ntp_snippets_bridge.cc b/chrome/browser/android/ntp/ntp_snippets_bridge.cc index 6d583d4c..b2921e1 100644 --- a/chrome/browser/android/ntp/ntp_snippets_bridge.cc +++ b/chrome/browser/android/ntp/ntp_snippets_bridge.cc
@@ -92,14 +92,6 @@ suggestion.download_suggestion_extra()->offline_page_id); } } - if (suggestion.id().category().IsKnownCategory( - KnownCategories::RECENT_TABS) && - suggestion.recent_tab_suggestion_extra() != nullptr) { - Java_SnippetsBridge_setRecentTabDataForSuggestion( - env, java_suggestion, - suggestion.recent_tab_suggestion_extra()->tab_id, - suggestion.recent_tab_suggestion_extra()->offline_page_id); - } } return result;
diff --git a/chrome/browser/ash_service_registry.cc b/chrome/browser/ash_service_registry.cc index 96e4a26..e3b6462 100644 --- a/chrome/browser/ash_service_registry.cc +++ b/chrome/browser/ash_service_registry.cc
@@ -4,13 +4,21 @@ #include "chrome/browser/ash_service_registry.h" +#include "ash/ash_service.h" #include "ash/components/quick_launch/public/mojom/constants.mojom.h" +#include "ash/content/content_gpu_support.h" #include "ash/public/interfaces/constants.mojom.h" +#include "ash/shell.h" +#include "ash/ws/window_service_delegate_impl.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" +#include "chrome/browser/chromeos/prefs/pref_connector_service.h" #include "components/services/font/public/interfaces/constants.mojom.h" #include "services/ui/public/interfaces/constants.mojom.h" +#include "services/ui/ws2/window_service.h" +#include "ui/base/ui_base_features.h" using content::ContentBrowserClient; @@ -23,42 +31,106 @@ const char* process_group; // If null, uses a separate process. }; -constexpr Service kServices[] = { +// Services shared between mash and non-mash configs. +constexpr Service kCommonServices[] = { {quick_launch::mojom::kServiceName, "Quick Launch", nullptr}, - {ui::mojom::kServiceName, "UI Service", kAshAndUiProcessGroup}, - {ash::mojom::kServiceName, "Ash Window Manager and Shell", - kAshAndUiProcessGroup}, {"autoclick_app", "Accessibility Autoclick", nullptr}, {"touch_hud_app", "Touch HUD", nullptr}, {font_service::mojom::kServiceName, "Font Service", nullptr}, }; -} // namespace +// Services unique to mash. Note that the non-mash case also has an Ash service, +// it's just registered differently (see RegisterInProcessServices()). +constexpr Service kMashServices[] = { + {ui::mojom::kServiceName, "UI Service", kAshAndUiProcessGroup}, + {ash::mojom::kServiceName, "Ash Window Manager and Shell", + kAshAndUiProcessGroup}, +}; -void RegisterOutOfProcessServices( - ContentBrowserClient::OutOfProcessServiceMap* services) { - for (const auto& service : kServices) { +void RegisterOutOfProcessServicesImpl( + const Service* services, + size_t num_services, + ContentBrowserClient::OutOfProcessServiceMap* services_map) { + for (size_t i = 0; i < num_services; ++i) { + const Service& service = services[i]; base::string16 display_name = base::ASCIIToUTF16(service.display_name); if (service.process_group) { - (*services)[service.name] = ContentBrowserClient::OutOfProcessServiceInfo( - display_name, service.process_group); + (*services_map)[service.name] = + ContentBrowserClient::OutOfProcessServiceInfo(display_name, + service.process_group); } else { - (*services)[service.name] = + (*services_map)[service.name] = ContentBrowserClient::OutOfProcessServiceInfo(display_name); } } } +std::unique_ptr<service_manager::Service> CreateEmbeddedWindowService() { + return std::make_unique<ui::ws2::WindowService>( + ash::Shell::Get()->window_service_delegate(), + std::make_unique<ash::ContentGpuSupport>()); +} + +} // namespace + +void RegisterOutOfProcessServices( + ContentBrowserClient::OutOfProcessServiceMap* services) { + if (base::FeatureList::IsEnabled(features::kMash)) { + RegisterOutOfProcessServicesImpl(kCommonServices, + base::size(kCommonServices), services); + RegisterOutOfProcessServicesImpl(kMashServices, base::size(kMashServices), + services); + } else { + RegisterOutOfProcessServicesImpl(kCommonServices, + base::size(kCommonServices), services); + } +} + +void RegisterInProcessServices( + content::ContentBrowserClient::StaticServiceMap* services) { + { + service_manager::EmbeddedServiceInfo info; + info.factory = + base::BindRepeating([]() -> std::unique_ptr<service_manager::Service> { + return std::make_unique<AshPrefConnector>(); + }); + info.task_runner = base::ThreadTaskRunnerHandle::Get(); + (*services)[ash::mojom::kPrefConnectorServiceName] = info; + } + + if (base::FeatureList::IsEnabled(features::kMash)) + return; + + (*services)[ash::mojom::kServiceName] = + ash::AshService::CreateEmbeddedServiceInfo(); + + service_manager::EmbeddedServiceInfo ui_service_info; + ui_service_info.factory = base::BindRepeating(&CreateEmbeddedWindowService); + ui_service_info.task_runner = base::ThreadTaskRunnerHandle::Get(); + (*services)[ui::mojom::kServiceName] = ui_service_info; +} + bool IsAshRelatedServiceName(const std::string& name) { - for (size_t i = 0; i < base::size(kServices); ++i) { - if (name == kServices[i].name) + for (const Service& service : kMashServices) { + if (name == service.name) + return true; + } + for (const Service& service : kCommonServices) { + if (name == service.name) return true; } return false; } std::string GetAshRelatedServiceLabel(const std::string& service_name) { - for (const Service& service : kServices) { + for (const Service& service : kMashServices) { + if (service_name == service.name) { + // Use the process group name when available because that makes it more + // obvious that multiple services are running in the same process. + return service.process_group ? service.process_group : service.name; + } + } + for (const Service& service : kCommonServices) { if (service_name == service.name) { // Use the process group name when available because that makes it more // obvious that multiple services are running in the same process.
diff --git a/chrome/browser/ash_service_registry.h b/chrome/browser/ash_service_registry.h index 0672c3f..91aef2e 100644 --- a/chrome/browser/ash_service_registry.h +++ b/chrome/browser/ash_service_registry.h
@@ -14,10 +14,14 @@ // Process group used for the ash service and the ui service. Visible for test. constexpr char kAshAndUiProcessGroup[] = "ash_and_ui"; -// Starts one of Mash's embedded services. +// Registers the set of Ash related services that run out of process. void RegisterOutOfProcessServices( content::ContentBrowserClient::OutOfProcessServiceMap* services); +// Registers the set of Ash related services that run in process. +void RegisterInProcessServices( + content::ContentBrowserClient::StaticServiceMap* services); + // Returns true if |name| identifies an Ash related service. bool IsAshRelatedServiceName(const std::string& name);
diff --git a/chrome/browser/ash_service_registry_unittest.cc b/chrome/browser/ash_service_registry_unittest.cc index dc80a75d..c2633e8 100644 --- a/chrome/browser/ash_service_registry_unittest.cc +++ b/chrome/browser/ash_service_registry_unittest.cc
@@ -6,11 +6,15 @@ #include "ash/public/interfaces/constants.mojom.h" #include "base/stl_util.h" +#include "base/test/scoped_feature_list.h" #include "content/public/browser/content_browser_client.h" #include "services/ui/public/interfaces/constants.mojom.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/ui_base_features.h" TEST(AshServiceRegistryTest, AshAndUiInSameProcess) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kMash); content::ContentBrowserClient::OutOfProcessServiceMap services; ash_service_registry::RegisterOutOfProcessServices(&services);
diff --git a/chrome/browser/browser_process_platform_part_chromeos.cc b/chrome/browser/browser_process_platform_part_chromeos.cc index f09f5088..0f464f1 100644 --- a/chrome/browser/browser_process_platform_part_chromeos.cc +++ b/chrome/browser/browser_process_platform_part_chromeos.cc
@@ -6,11 +6,11 @@ #include <utility> -#include "ash/ash_service.h" #include "ash/public/interfaces/constants.mojom.h" #include "base/logging.h" #include "base/time/default_tick_clock.h" #include "base/time/tick_clock.h" +#include "chrome/browser/ash_service_registry.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/ash_config.h" #include "chrome/browser/chromeos/chrome_service_name.h" @@ -18,7 +18,6 @@ #include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h" #include "chrome/browser/chromeos/net/delay_network_call.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" -#include "chrome/browser/chromeos/prefs/pref_connector_service.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/system/automatic_reboot_manager.h" @@ -28,7 +27,6 @@ #include "chrome/browser/chromeos/system/timezone_resolver_manager.h" #include "chrome/browser/chromeos/system/timezone_util.h" #include "chrome/browser/component_updater/cros_component_installer.h" -#include "chrome/browser/ui/ash/ash_util.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "chromeos/account_manager/account_manager_factory.h" @@ -182,22 +180,7 @@ void BrowserProcessPlatformPart::RegisterInProcessServices( content::ContentBrowserClient::StaticServiceMap* services) { - { - service_manager::EmbeddedServiceInfo info; - info.factory = base::Bind([] { - return std::unique_ptr<service_manager::Service>( - std::make_unique<AshPrefConnector>()); - }); - info.task_runner = base::ThreadTaskRunnerHandle::Get(); - services->insert( - std::make_pair(ash::mojom::kPrefConnectorServiceName, info)); - } - - if (!ash_util::IsRunningInMash()) { - services->insert( - std::make_pair(ash::mojom::kServiceName, - ash::AshService::CreateEmbeddedServiceInfo())); - } + ash_service_registry::RegisterInProcessServices(services); } chromeos::system::SystemClock* BrowserProcessPlatformPart::GetSystemClock() {
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 31968d2e..7fa08b7 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2079,6 +2079,12 @@ command_line->AppendSwitchASCII( switches::kMashServiceName, ash_service_registry::GetAshRelatedServiceLabel(identity.name())); + if (!base::FeatureList::IsEnabled(features::kMash)) { + // TODO(sky): this is necessary because WindowTreeClient only connects to + // the gpu related interfaces if Mash is set. + command_line->AppendSwitchASCII(switches::kEnableFeatures, + features::kMash.name); + } } #endif // TODO(sky): move to a whitelist, but currently the set of flags is rather @@ -3426,8 +3432,7 @@ l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_UNZIP_NAME); #if defined(OS_CHROMEOS) - if (base::FeatureList::IsEnabled(features::kMash)) - ash_service_registry::RegisterOutOfProcessServices(services); + ash_service_registry::RegisterOutOfProcessServices(services); #endif }
diff --git a/chrome/browser/chrome_content_browser_client_unittest.cc b/chrome/browser/chrome_content_browser_client_unittest.cc index 59fe529..f3830d91 100644 --- a/chrome/browser/chrome_content_browser_client_unittest.cc +++ b/chrome/browser/chrome_content_browser_client_unittest.cc
@@ -411,8 +411,6 @@ #if defined(OS_CHROMEOS) -// This behavior only matters on Chrome OS, which is why this isn't wrapped in -// ENABLE_MASH_PACKAGED_SERVICES (which is used for Linux Ozone). TEST(ChromeContentBrowserClientTest, ShouldTerminateOnServiceQuit) { const struct { std::string service_name;
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc index 080e5f8..a185c4c 100644 --- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc +++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -914,7 +914,8 @@ 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); + ASSERT_EQ(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, + user_context.GetUserType()); content::WindowedNotificationObserver profile_prepared_observer( chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, content::NotificationService::AllSources()); @@ -933,7 +934,8 @@ 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); + ASSERT_EQ(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, + user_context.GetUserType()); content::WindowedNotificationObserver profile_prepared_observer( chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, content::NotificationService::AllSources()); @@ -957,7 +959,8 @@ UserContext user_context(ad_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(ad_account_id_.GetUserEmail()); - user_context.SetUserType(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY); + ASSERT_EQ(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, + user_context.GetUserType()); content::WindowedNotificationObserver profile_prepared_observer( chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, @@ -986,7 +989,8 @@ 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); + ASSERT_EQ(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, + user_context.GetUserType()); content::WindowedNotificationObserver profile_prepared_observer( chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, content::NotificationService::AllSources()); @@ -1005,7 +1009,8 @@ 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); + ASSERT_EQ(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, + user_context.GetUserType()); existing_user_controller()->CompleteLogin(user_context); }
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc index 813e842d..61630bb 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker.cc +++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -693,7 +693,7 @@ return; } - UserContext user_context(active_user->GetAccountId()); + UserContext user_context(active_user->GetType(), active_user->GetAccountId()); if (!base::ContainsKey(matches, active_user->username_hash())) { OnFingerprintAuthFailure(*active_user); return;
diff --git a/chrome/browser/chromeos/login/lock/views_screen_locker.cc b/chrome/browser/chromeos/login/lock/views_screen_locker.cc index e6bb57fb..923ea9be 100644 --- a/chrome/browser/chromeos/login/lock/views_screen_locker.cc +++ b/chrome/browser/chromeos/login/lock/views_screen_locker.cc
@@ -179,8 +179,12 @@ user_context.SetKey(Key(key_type, std::string(), hashed_password)); user_context.SetIsUsingPin(authenticated_by_pin); user_context.SetSyncPasswordData(sync_password_data); - if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY) - user_context.SetUserType(user_manager::USER_TYPE_ACTIVE_DIRECTORY); + if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY && + (user_context.GetUserType() != + user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY)) { + LOG(FATAL) << "Incorrect Active Directory user type " + << user_context.GetUserType(); + } ScreenLocker::default_screen_locker()->Authenticate(user_context, std::move(callback)); UpdatePinKeyboardState(account_id);
diff --git a/chrome/browser/chromeos/login/login_utils_browsertest.cc b/chrome/browser/chromeos/login/login_utils_browsertest.cc index 493b7c8..36628166 100644 --- a/chrome/browser/chromeos/login/login_utils_browsertest.cc +++ b/chrome/browser/chromeos/login/login_utils_browsertest.cc
@@ -71,7 +71,7 @@ static_cast<LoginDisplayWebUI*>(controller->login_display()); ASSERT_TRUE(login_display); - login_display->ShowSigninScreenForCreds(username, "password"); + login_display->ShowSigninScreenForTest(username, "password", "[]"); // Wait for the session to start after submitting the credentials. This // will wait until all the background requests are done.
diff --git a/chrome/browser/chromeos/login/oobe_browsertest.cc b/chrome/browser/chromeos/login/oobe_browsertest.cc index 473f060..9441f05 100644 --- a/chrome/browser/chromeos/login/oobe_browsertest.cc +++ b/chrome/browser/chromeos/login/oobe_browsertest.cc
@@ -75,8 +75,9 @@ chrome::NOTIFICATION_SESSION_STARTED, content::NotificationService::AllSources()); - GetLoginDisplay()->ShowSigninScreenForCreds(OobeBaseTest::kFakeUserEmail, - OobeBaseTest::kFakeUserPassword); + GetLoginDisplay()->ShowSigninScreenForTest(OobeBaseTest::kFakeUserEmail, + OobeBaseTest::kFakeUserPassword, + OobeBaseTest::kEmptyUserServices); session_start_waiter.Wait(); }
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc index 6ed03fef..f9d476d 100644 --- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc +++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -121,10 +121,14 @@ constexpr char kTestAuthLSIDCookie1[] = "fake-auth-LSID-cookie-1"; constexpr char kTestAuthLSIDCookie2[] = "fake-auth-LSID-cookie-2"; -constexpr char kFirstSAMLUserEmail[] = "bob@example.com"; -constexpr char kSecondSAMLUserEmail[] = "alice@example.com"; -constexpr char kHTTPSAMLUserEmail[] = "carol@example.com"; -constexpr char kNonSAMLUserEmail[] = "dan@example.com"; +// Note: SAML account cannot be @gmail or @example.com account. The former by +// design, the latter because @example.com is used in another tests as regular +// user. So we use @corp.example.com and @example.test, so that we can handle +// it specially in embedded_setup_chromeos.html . +constexpr char kFirstSAMLUserEmail[] = "bob@corp.example.com"; +constexpr char kSecondSAMLUserEmail[] = "alice@corp.example.com"; +constexpr char kHTTPSAMLUserEmail[] = "carol@corp.example.com"; +constexpr char kNonSAMLUserEmail[] = "dan@corp.example.com"; constexpr char kDifferentDomainSAMLUserEmail[] = "eve@example.test"; constexpr char kFirstSAMLUserGaiaId[] = "bob-gaia"; @@ -133,8 +137,8 @@ constexpr char kNonSAMLUserGaiaId[] = "dan-gaia"; constexpr char kDifferentDomainSAMLUserGaiaId[] = "eve-gaia"; -constexpr char kIdPHost[] = "login.example.com"; -constexpr char kAdditionalIdPHost[] = "login2.example.com"; +constexpr char kIdPHost[] = "login.corp.example.com"; +constexpr char kAdditionalIdPHost[] = "login2.corp.example.com"; constexpr char kSAMLIdPCookieName[] = "saml"; constexpr char kSAMLIdPCookieValue1[] = "value-1"; @@ -332,7 +336,7 @@ kHTTPSAMLUserEmail, embedded_test_server()->base_url().Resolve("/SAML")); fake_gaia_->RegisterSamlUser(kDifferentDomainSAMLUserEmail, saml_idp_url); - fake_gaia_->RegisterSamlDomainRedirectUrl("example.com", saml_idp_url); + fake_gaia_->RegisterSamlDomainRedirectUrl("corp.example.com", saml_idp_url); OobeBaseTest::SetUpCommandLine(command_line); } @@ -372,7 +376,7 @@ SetupAuthFlowChangeListener(); content::DOMMessageQueue message_queue; // Start observe before SAML. - GetLoginDisplay()->ShowSigninScreenForCreds(gaia_email, ""); + GetLoginDisplay()->ShowSigninScreenForTest(gaia_email, "", "[]"); std::string message; ASSERT_TRUE(message_queue.WaitForMessage(&message)); @@ -638,9 +642,9 @@ session_start_waiter.Wait(); } -// Types |bob@example.com| into the GAIA login form but then authenticates as -// |alice@example.com| via SAML. Verifies that the logged-in user is correctly -// identified as Alice. +// Types |bob@corp.example.com| into the GAIA login form but then authenticates +// as |alice@corp.example.com| via SAML. Verifies that the logged-in user is +// correctly identified as Alice. // // Disabled since it's occasionally timed out: https://crbug.com/830322. #if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) @@ -651,12 +655,12 @@ #endif IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_UseAutenticatedUserEmailAddress) { fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); - // Type |bob@example.com| into the GAIA login form. + // Type |bob@corp.example.com| into the GAIA login form. StartSamlAndWaitForIdpPageLoad(kSecondSAMLUserEmail); - // Authenticate as alice@example.com via SAML (the |Email| provided here is - // irrelevant - the authenticated user's e-mail address that FakeGAIA - // reports was set via |SetFakeMergeSessionParams|. + // Authenticate as alice@corp.example.com via SAML (the |Email| provided here + // is irrelevant - the authenticated user's e-mail address that FakeGAIA + // reports was set via |SetFakeMergeSessionParams|). SetSignFormField("Email", "fake_user"); SetSignFormField("Password", "fake_password"); @@ -787,7 +791,7 @@ fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); WaitForSigninScreen(); - GetLoginDisplay()->ShowSigninScreenForCreds(kHTTPSAMLUserEmail, ""); + GetLoginDisplay()->ShowSigninScreenForTest(kHTTPSAMLUserEmail, "", "[]"); const GURL url = embedded_test_server()->base_url().Resolve("/SAML"); EXPECT_EQ(l10n_util::GetStringFUTF8(IDS_LOGIN_FATAL_ERROR_TEXT_INSECURE_URL, @@ -811,7 +815,7 @@ fake_saml_idp()->SetRefreshURL(url); WaitForSigninScreen(); - GetLoginDisplay()->ShowSigninScreenForCreds(kFirstSAMLUserEmail, ""); + GetLoginDisplay()->ShowSigninScreenForTest(kFirstSAMLUserEmail, "", "[]"); EXPECT_EQ(l10n_util::GetStringFUTF8(IDS_LOGIN_FATAL_ERROR_TEXT_INSECURE_URL, base::UTF8ToUTF16(url.spec())), @@ -1305,7 +1309,8 @@ SetupFakeGaiaForLogin(kNonSAMLUserEmail, "", kTestRefreshToken); // Log in without SAML. - GetLoginDisplay()->ShowSigninScreenForCreds(kNonSAMLUserEmail, "password"); + GetLoginDisplay()->ShowSigninScreenForTest(kNonSAMLUserEmail, "password", + "[]"); content::WindowedNotificationObserver( chrome::NOTIFICATION_SESSION_STARTED, @@ -1498,7 +1503,7 @@ fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); const GURL url1("https://google.com"); - const GURL url2("https://example.com"); + const GURL url2("https://corp.example.com"); const GURL url3("https://not-allowed.com"); SetLoginVideoCaptureAllowedUrls({url1, url2}); WaitForSigninScreen();
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager_browsertest.cc b/chrome/browser/chromeos/login/session/chrome_session_manager_browsertest.cc index d13771ee..b8833192 100644 --- a/chrome/browser/chromeos/login/session/chrome_session_manager_browsertest.cc +++ b/chrome/browser/chromeos/login/session/chrome_session_manager_browsertest.cc
@@ -105,7 +105,8 @@ LoginDisplayWebUI* login_display = static_cast<LoginDisplayWebUI*>( ExistingUserController::current_controller()->login_display()); - login_display->ShowSigninScreenForCreds(kTestUsers[0].email, "fake_password"); + login_display->ShowSigninScreenForTest(kTestUsers[0].email, "fake_password", + "[]"); session_start_waiter.Wait();
diff --git a/chrome/browser/chromeos/login/signin/device_id_browsertest.cc b/chrome/browser/chromeos/login/signin/device_id_browsertest.cc index 5d157905..b113f54 100644 --- a/chrome/browser/chromeos/login/signin/device_id_browsertest.cc +++ b/chrome/browser/chromeos/login/signin/device_id_browsertest.cc
@@ -111,7 +111,7 @@ fake_gaia_->UpdateMergeSessionParams(params); fake_gaia_->MapEmailToGaiaId(user_id, gaia_id); - GetLoginDisplay()->ShowSigninScreenForCreds(user_id, password); + GetLoginDisplay()->ShowSigninScreenForTest(user_id, password, "[]"); WaitForSessionStart(); }
diff --git a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc index 2ba818e..03b0bc4c 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
@@ -69,6 +69,7 @@ const char kTestEmail[] = "username@gmail.com"; const char kTestRawEmail[] = "User.Name@gmail.com"; const char kTestAccountPassword[] = "fake-password"; +const char kTestAccountServices[] = "[]"; const char kTestAuthCode[] = "fake-auth-code"; const char kTestGaiaUberToken[] = "fake-uber-token"; const char kTestAuthLoginAccessToken[] = "fake-access-token"; @@ -381,8 +382,8 @@ // Use capitalized and dotted user name on purpose to make sure // our email normalization kicks in. - GetLoginDisplay()->ShowSigninScreenForCreds(kTestRawEmail, - kTestAccountPassword); + GetLoginDisplay()->ShowSigninScreenForTest( + kTestRawEmail, kTestAccountPassword, kTestAccountServices); session_start_waiter.Wait(); if (wait_for_merge) { @@ -620,7 +621,8 @@ fake_gaia_->SetMergeSessionParams(params); // Simulate an online sign-in. - GetLoginDisplay()->ShowSigninScreenForCreds(kTestEmail, kTestAccountPassword); + GetLoginDisplay()->ShowSigninScreenForTest(kTestEmail, kTestAccountPassword, + kTestAccountServices); // User session should be terminated. termination_waiter.Wait();
diff --git a/chrome/browser/chromeos/login/signin/oauth2_token_initializer.cc b/chrome/browser/chromeos/login/signin/oauth2_token_initializer.cc index 00a988d3..2a2624e 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_token_initializer.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_token_initializer.cc
@@ -31,8 +31,12 @@ user_context_.SetAuthCode(std::string()); user_context_.SetRefreshToken(result.refresh_token); user_context_.SetAccessToken(result.access_token); - if (result.is_child_account) { - user_context_.SetUserType(user_manager::USER_TYPE_CHILD); + if (result.is_child_account && + user_context_.GetUserType() != user_manager::USER_TYPE_CHILD) { + LOG(FATAL) << "Incorrect child user type " << user_context_.GetUserType(); + } else if (user_context_.GetUserType() == user_manager::USER_TYPE_CHILD && + !result.is_child_account) { + LOG(FATAL) << "Incorrect non-child token for the child user."; } callback_.Run(true, user_context_); }
diff --git a/chrome/browser/chromeos/login/signin_partition_manager_unittest.cc b/chrome/browser/chromeos/login/signin_partition_manager_unittest.cc index 27b0a00..3f993ed 100644 --- a/chrome/browser/chromeos/login/signin_partition_manager_unittest.cc +++ b/chrome/browser/chromeos/login/signin_partition_manager_unittest.cc
@@ -80,10 +80,8 @@ signin_browser_context_ = std::make_unique<TestingProfile>(); - signin_ui_web_contents_ = base::WrapUnique<content::WebContents>( - content::WebContentsTester::CreateTestWebContents( - GetSigninProfile(), - content::SiteInstance::Create(GetSigninProfile()))); + signin_ui_web_contents_ = content::WebContentsTester::CreateTestWebContents( + GetSigninProfile(), content::SiteInstance::Create(GetSigninProfile())); GURL url(kEmbedderUrl); content::WebContentsTester::For(signin_ui_web_contents())
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc index 0f114b8..094b8818 100644 --- a/chrome/browser/chromeos/login/test/oobe_base_test.cc +++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -49,6 +49,7 @@ const char OobeBaseTest::kFakeUserEmail[] = "fake-email@gmail.com"; const char OobeBaseTest::kFakeUserPassword[] = "fake-password"; const char OobeBaseTest::kFakeUserGaiaId[] = "fake-gaiaId"; +const char OobeBaseTest::kEmptyUserServices[] = "[]"; const char OobeBaseTest::kFakeSIDCookie[] = "fake-SID-cookie"; const char OobeBaseTest::kFakeLSIDCookie[] = "fake-LSID-cookie";
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.h b/chrome/browser/chromeos/login/test/oobe_base_test.h index a59ce3c..397ad4a 100644 --- a/chrome/browser/chromeos/login/test/oobe_base_test.h +++ b/chrome/browser/chromeos/login/test/oobe_base_test.h
@@ -41,6 +41,7 @@ static const char kFakeUserEmail[]; static const char kFakeUserPassword[]; static const char kFakeUserGaiaId[]; + static const char kEmptyUserServices[]; // FakeGaia is configured to return these cookies for kFakeUserEmail. static const char kFakeSIDCookie[];
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc index 650b2a8b..7b729f37 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc +++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
@@ -219,8 +219,12 @@ user_context.SetKey(Key(chromeos::Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, std::string(), hashed_password)); user_context.SetSyncPasswordData(sync_password_data); - if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY) - user_context.SetUserType(user_manager::USER_TYPE_ACTIVE_DIRECTORY); + if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY && + (user_context.GetUserType() != + user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY)) { + LOG(FATAL) << "Incorrect Active Directory user type " + << user_context.GetUserType(); + } existing_user_controller_->Login(user_context, chromeos::SigninSpecifics()); }
diff --git a/chrome/browser/chromeos/login/ui/login_display_webui.cc b/chrome/browser/chromeos/login/ui/login_display_webui.cc index 044281d..324f91f 100644 --- a/chrome/browser/chromeos/login/ui/login_display_webui.cc +++ b/chrome/browser/chromeos/login/ui/login_display_webui.cc
@@ -267,10 +267,11 @@ SignInScreenController::Get()->SetWebUIHandler(webui_handler_); } -void LoginDisplayWebUI::ShowSigninScreenForCreds(const std::string& username, - const std::string& password) { +void LoginDisplayWebUI::ShowSigninScreenForTest(const std::string& username, + const std::string& password, + const std::string& services) { if (webui_handler_) - webui_handler_->ShowSigninScreenForCreds(username, password); + webui_handler_->ShowSigninScreenForTest(username, password, services); } bool LoginDisplayWebUI::IsShowGuest() const {
diff --git a/chrome/browser/chromeos/login/ui/login_display_webui.h b/chrome/browser/chromeos/login/ui/login_display_webui.h index db0a2ce..4a94cec 100644 --- a/chrome/browser/chromeos/login/ui/login_display_webui.h +++ b/chrome/browser/chromeos/login/ui/login_display_webui.h
@@ -72,8 +72,12 @@ void ShowUpdateRequiredScreen() override; void ShowWrongHWIDScreen() override; void SetWebUIHandler(LoginDisplayWebUIHandler* webui_handler) override; - virtual void ShowSigninScreenForCreds(const std::string& username, - const std::string& password); + // Should match the same method in SigninScreenHandler. + // |services| must be a valid JSON array. See SigninScreenHandler for + // detalis. + virtual void ShowSigninScreenForTest(const std::string& username, + const std::string& password, + const std::string& services); bool IsShowGuest() const override; bool IsShowUsers() const override; bool ShowUsersHasChanged() const override;
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc index 4a14489..85e09be 100644 --- a/chrome/browser/chromeos/login/webview_login_browsertest.cc +++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -240,6 +240,7 @@ chrome::NOTIFICATION_SESSION_STARTED, content::NotificationService::AllSources()); + SetSignFormField("services", "[]"); SetSignFormField("password", OobeBaseTest::kFakeUserPassword); ClickNext(); @@ -274,6 +275,7 @@ content::NotificationService::AllSources()); // Finish sign-up. + SetSignFormField("services", "[]"); SetSignFormField("password", OobeBaseTest::kFakeUserPassword); ClickNext();
diff --git a/chrome/browser/chromeos/policy/blocking_login_browsertest.cc b/chrome/browser/chromeos/policy/blocking_login_browsertest.cc index d0eff7e4..6ff96b7 100644 --- a/chrome/browser/chromeos/policy/blocking_login_browsertest.cc +++ b/chrome/browser/chromeos/policy/blocking_login_browsertest.cc
@@ -162,7 +162,7 @@ static_cast<LoginDisplayWebUI*>(controller->login_display()); ASSERT_TRUE(login_display); - login_display->ShowSigninScreenForCreds(username, "password"); + login_display->ShowSigninScreenForTest(username, "password", "[]"); // Wait for the session to start after submitting the credentials. This // will wait until all the background requests are done.
diff --git a/chrome/browser/chromeos/policy/force_maximize_on_first_run_chromeos_browsertest.cc b/chrome/browser/chromeos/policy/force_maximize_on_first_run_chromeos_browsertest.cc index 17519f4..63f4005 100644 --- a/chrome/browser/chromeos/policy/force_maximize_on_first_run_chromeos_browsertest.cc +++ b/chrome/browser/chromeos/policy/force_maximize_on_first_run_chromeos_browsertest.cc
@@ -56,7 +56,7 @@ IN_PROC_BROWSER_TEST_F(ForceMaximizeOnFirstRunTest, PRE_TwoRuns) { SetUpResolution(); SkipToLoginScreen(); - LogIn(kAccountId, kAccountPassword); + LogIn(kAccountId, kAccountPassword, kEmptyServices); // Check that the first browser window is maximized. const BrowserList* const browser_list = BrowserList::GetInstance(); @@ -81,7 +81,7 @@ content::WindowedNotificationObserver( chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, content::NotificationService::AllSources()).Wait(); - LogIn(kAccountId, kAccountPassword); + LogIn(kAccountId, kAccountPassword, kEmptyServices); const Browser* const browser = OpenNewBrowserWindow(); ASSERT_TRUE(browser); @@ -103,7 +103,7 @@ IN_PROC_BROWSER_TEST_F(ForceMaximizePolicyFalseTest, GeneralFirstRun) { SetUpResolution(); SkipToLoginScreen(); - LogIn(kAccountId, kAccountPassword); + LogIn(kAccountId, kAccountPassword, kEmptyServices); const BrowserList* const browser_list = BrowserList::GetInstance(); EXPECT_EQ(1U, browser_list->size());
diff --git a/chrome/browser/chromeos/policy/login_policy_test_base.cc b/chrome/browser/chromeos/policy/login_policy_test_base.cc index 54087881..29b9a6b 100644 --- a/chrome/browser/chromeos/policy/login_policy_test_base.cc +++ b/chrome/browser/chromeos/policy/login_policy_test_base.cc
@@ -32,6 +32,8 @@ const char LoginPolicyTestBase::kAccountPassword[] = "letmein"; const char LoginPolicyTestBase::kAccountId[] = "user@example.com"; +// Empty services list for userInfo. +const char LoginPolicyTestBase::kEmptyServices[] = "[]"; LoginPolicyTestBase::LoginPolicyTestBase() { set_open_about_blank_on_browser_launch(false); @@ -109,8 +111,9 @@ } void LoginPolicyTestBase::LogIn(const std::string& user_id, - const std::string& password) { - GetLoginDisplay()->ShowSigninScreenForCreds(user_id, password); + const std::string& password, + const std::string& services) { + GetLoginDisplay()->ShowSigninScreenForTest(user_id, password, services); content::WindowedNotificationObserver( chrome::NOTIFICATION_SESSION_STARTED,
diff --git a/chrome/browser/chromeos/policy/login_policy_test_base.h b/chrome/browser/chromeos/policy/login_policy_test_base.h index 6d17780..6ea6bafa 100644 --- a/chrome/browser/chromeos/policy/login_policy_test_base.h +++ b/chrome/browser/chromeos/policy/login_policy_test_base.h
@@ -41,10 +41,14 @@ } void SkipToLoginScreen(); - void LogIn(const std::string& user_id, const std::string& password); + // Should match ShowSigninScreenForTest method in SigninScreenHandler. + void LogIn(const std::string& user_id, + const std::string& password, + const std::string& services); static const char kAccountPassword[]; static const char kAccountId[]; + static const char kEmptyServices[]; private: void SetUpGaiaServerWithAccessTokens();
diff --git a/chrome/browser/chromeos/policy/restore_on_startup_browsertest_chromeos.cc b/chrome/browser/chromeos/policy/restore_on_startup_browsertest_chromeos.cc index 468fa4d7..fc01ba3 100644 --- a/chrome/browser/chromeos/policy/restore_on_startup_browsertest_chromeos.cc +++ b/chrome/browser/chromeos/policy/restore_on_startup_browsertest_chromeos.cc
@@ -56,7 +56,7 @@ } void RestoreOnStartupTestChromeOS::LogInAndVerifyStartUpURLs() { - LogIn(kAccountId, kAccountPassword); + LogIn(kAccountId, kAccountPassword, kEmptyServices); const BrowserList* const browser_list = BrowserList::GetInstance(); ASSERT_EQ(1U, browser_list->size());
diff --git a/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc b/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc index 7d31ea7..09b03b3c3 100644 --- a/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc +++ b/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc
@@ -370,7 +370,8 @@ // it waits for a user session start unconditionally, which will not happen if // chrome requests a restart to set user-session flags. SkipToLoginScreen(); - GetLoginDisplay()->ShowSigninScreenForCreds(kAccountId, kAccountPassword); + GetLoginDisplay()->ShowSigninScreenForTest(kAccountId, kAccountPassword, + kEmptyServices); // Wait for either the user session to start, or for restart to be requested // (whichever happens first).
diff --git a/chrome/browser/chromeos/policy/user_cloud_external_data_manager_browsertest.cc b/chrome/browser/chromeos/policy/user_cloud_external_data_manager_browsertest.cc index 2edefe79..1ae6551 100644 --- a/chrome/browser/chromeos/policy/user_cloud_external_data_manager_browsertest.cc +++ b/chrome/browser/chromeos/policy/user_cloud_external_data_manager_browsertest.cc
@@ -76,7 +76,7 @@ CloudExternalDataManagerBase::SetMaxExternalDataSizeForTesting(1000); SkipToLoginScreen(); - LogIn(kAccountId, kAccountPassword); + LogIn(kAccountId, kAccountPassword, kEmptyServices); Profile* profile = ProfileManager::GetActiveUserProfile(); ASSERT_TRUE(profile);
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc index 3ae2659..6afb8d8 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc +++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc
@@ -40,6 +40,9 @@ "eyAic2VydmljZXMiOiBbInVjYSJdIH0=" ".dummy-signature"; +// Services list for the child user. (This must be a correct JSON array.) +const char kChildServices[] = "[\"uca\"]"; + // Helper class that counts the number of notifications of the specified // type that have been received. class CountNotificationObserver : public content::NotificationObserver { @@ -98,7 +101,7 @@ user_manager::known_user::GetProfileRequiresPolicy(account_id)); SkipToLoginScreen(); - LogIn(kAccountId, kAccountPassword); + LogIn(kAccountId, kAccountPassword, kEmptyServices); // User should be marked as having a valid OAuth token. const user_manager::UserManager* const user_manager = @@ -134,7 +137,8 @@ CountNotificationObserver observer( chrome::NOTIFICATION_SESSION_STARTED, content::NotificationService::AllSources()); - GetLoginDisplay()->ShowSigninScreenForCreds(kAccountId, kAccountPassword); + GetLoginDisplay()->ShowSigninScreenForTest(kAccountId, kAccountPassword, + kEmptyServices); base::RunLoop().Run(); // Should not receive a SESSION_STARTED notification. ASSERT_EQ(0, observer.notification_count()); @@ -163,7 +167,7 @@ // Delete the policy file - this will cause a 500 error on policy requests. user_policy_helper()->DeletePolicyFile(); SkipToLoginScreen(); - LogIn(kAccountId, kAccountPassword); + LogIn(kAccountId, kAccountPassword, kEmptyServices); // User should be marked as having a valid OAuth token. const user_manager::UserManager* const user_manager = @@ -202,7 +206,7 @@ // Delete the policy file - this will cause a 500 error on policy requests. user_policy_helper()->DeletePolicyFile(); SkipToLoginScreen(); - LogIn(kAccountId, kAccountPassword); + LogIn(kAccountId, kAccountPassword, kEmptyServices); // User should be marked as having a valid OAuth token. EXPECT_EQ(user_manager::User::OAUTH2_TOKEN_STATUS_VALID, @@ -254,7 +258,7 @@ user_manager::known_user::GetProfileRequiresPolicy(account_id)); SkipToLoginScreen(); - LogIn(GetAccount(), kAccountPassword); + LogIn(GetAccount(), kAccountPassword, kEmptyServices); // User should be marked as having a valid OAuth token. const user_manager::UserManager* const user_manager = @@ -302,7 +306,7 @@ user_manager::known_user::GetProfileRequiresPolicy(account_id)); SkipToLoginScreen(); - LogIn(GetAccount(), kAccountPassword); + LogIn(GetAccount(), kAccountPassword, kChildServices); // User should be marked as having a valid OAuth token. const user_manager::UserManager* const user_manager =
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index 3f526a1..c849a15 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -6,8 +6,7 @@ #include <vector> -#include "ash/ash_constants.h" -#include "ash/autoclick/autoclick_controller.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_pref_names.h" #include "ash/shell.h" #include "base/command_line.h" @@ -217,9 +216,7 @@ ash::prefs::kAccessibilityAutoclickEnabled, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC); registry->RegisterIntegerPref( - ash::prefs::kAccessibilityAutoclickDelayMs, - static_cast<int>(ash::AutoclickController::GetDefaultAutoclickDelay() - .InMilliseconds()), + ash::prefs::kAccessibilityAutoclickDelayMs, ash::kDefaultAutoclickDelayMs, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC); registry->RegisterBooleanPref( ash::prefs::kAccessibilityVirtualKeyboardEnabled, false,
diff --git a/chrome/browser/devtools/inspector_protocol_config.json b/chrome/browser/devtools/inspector_protocol_config.json index 5260199..96b580a7 100644 --- a/chrome/browser/devtools/inspector_protocol_config.json +++ b/chrome/browser/devtools/inspector_protocol_config.json
@@ -19,7 +19,6 @@ { "domain": "Target", "include": [ "setRemoteLocations", "createBrowserContext", "createTarget", "disposeBrowserContext" ], - "async": ["disposeBrowserContext"], "include_events": [] }, {
diff --git a/chrome/browser/devtools/protocol/target_handler.cc b/chrome/browser/devtools/protocol/target_handler.cc index 20e42cd..cb544fe 100644 --- a/chrome/browser/devtools/protocol/target_handler.cc +++ b/chrome/browser/devtools/protocol/target_handler.cc
@@ -22,7 +22,6 @@ if (delegate) delegate->UpdateDeviceDiscovery(); registrations_.clear(); - BrowserList::RemoveObserver(this); } protocol::Response TargetHandler::SetRemoteLocations( @@ -112,49 +111,23 @@ }); } -void TargetHandler::DisposeBrowserContext( +protocol::Response TargetHandler::DisposeBrowserContext( const std::string& context_id, - std::unique_ptr<DisposeBrowserContextCallback> callback) { - if (pending_context_disposals_.find(context_id) != - pending_context_disposals_.end()) { - callback->sendFailure(protocol::Response::Error( - "Disposing of browser context " + context_id + " is already pending")); - return; - } + bool* out_success) { auto it = registrations_.find(context_id); if (it == registrations_.end()) { - callback->sendFailure(protocol::Response::Error( - "Failed to find browser context with id " + context_id)); - return; + return protocol::Response::Error("Failed to find browser context with id " + + context_id); } - - if (pending_context_disposals_.empty()) - BrowserList::AddObserver(this); - - pending_context_disposals_[context_id] = std::move(callback); Profile* profile = it->second->profile(); - BrowserList::CloseAllBrowsersWithIncognitoProfile( - profile, base::DoNothing(), base::DoNothing(), - true /* skip_beforeunload */); -} - -void TargetHandler::OnBrowserRemoved(Browser* browser) { - std::string context_id = browser->profile()->UniqueId(); - auto pending_disposal = pending_context_disposals_.find(context_id); - if (pending_disposal == pending_context_disposals_.end()) - return; - for (auto* opened_browser : *BrowserList::GetInstance()) { - if (opened_browser->profile() == browser->profile()) - return; + for (auto* browser : *BrowserList::GetInstance()) { + if (browser->profile() == profile && + !browser->IsAttemptingToCloseBrowser()) { + *out_success = false; + return protocol::Response::OK(); + } } - auto it = registrations_.find(context_id); - // We cannot delete immediately here: the profile might still be referenced - // during the browser tier-down process. - base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, - it->second.release()); registrations_.erase(it); - pending_disposal->second->sendSuccess(); - pending_context_disposals_.erase(pending_disposal); - if (pending_context_disposals_.empty()) - BrowserList::RemoveObserver(this); + *out_success = true; + return protocol::Response::OK(); }
diff --git a/chrome/browser/devtools/protocol/target_handler.h b/chrome/browser/devtools/protocol/target_handler.h index 268d899..bfff3d0 100644 --- a/chrome/browser/devtools/protocol/target_handler.h +++ b/chrome/browser/devtools/protocol/target_handler.h
@@ -11,14 +11,11 @@ #include "chrome/browser/devtools/protocol/forward.h" #include "chrome/browser/devtools/protocol/target.h" #include "chrome/browser/media/router/presentation/independent_otr_profile_manager.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_list_observer.h" #include "net/base/host_port_pair.h" using RemoteLocations = std::set<net::HostPortPair>; -class TargetHandler : public protocol::Target::Backend, - public BrowserListObserver { +class TargetHandler : public protocol::Target::Backend { public: explicit TargetHandler(protocol::UberDispatcher* dispatcher); ~TargetHandler() override; @@ -37,22 +34,16 @@ protocol::Maybe<std::string> browser_context_id, protocol::Maybe<bool> enable_begin_frame_control, std::string* out_target_id) override; - void DisposeBrowserContext( - const std::string& context_id, - std::unique_ptr<DisposeBrowserContextCallback> callback) override; + protocol::Response DisposeBrowserContext(const std::string& context_id, + bool* out_success) override; private: void OnOriginalProfileDestroyed(Profile* profile); - void OnBrowserRemoved(Browser* browser) override; - base::flat_map< std::string, std::unique_ptr<IndependentOTRProfileManager::OTRProfileRegistration>> registrations_; - base::flat_map<std::string, std::unique_ptr<DisposeBrowserContextCallback>> - pending_context_disposals_; - RemoteLocations remote_locations_; base::WeakPtrFactory<TargetHandler> weak_factory_;
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc index b11b31b..a58bf88 100644 --- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -6,9 +6,12 @@ #include <algorithm> #include <memory> +#include <set> +#include <vector> #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/json/json_string_value_serializer.h" #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/path_service.h" @@ -31,7 +34,6 @@ #include "components/proxy_config/proxy_config_pref_names.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_entry.h" -#include "content/public/browser/notification_source.h" #include "content/public/browser/render_frame_host.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" @@ -44,13 +46,13 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/extension_util.h" -#include "extensions/browser/notification_types.h" #include "extensions/browser/runtime_data.h" #include "extensions/common/api/declarative_net_request/constants.h" #include "extensions/common/api/declarative_net_request/test_utils.h" #include "extensions/common/constants.h" #include "extensions/common/extension_id.h" #include "extensions/common/url_pattern.h" +#include "extensions/test/extension_test_message_listener.h" #include "net/dns/mock_host_resolver.h" #include "net/test/spawned_test_server/spawned_test_server.h" #include "net/test/test_data_directory.h" @@ -184,6 +186,7 @@ kJSONRulesFilename, rules, hosts, has_background_script_); + ExtensionTestMessageListener listener("ready", false /*will_reply*/); const Extension* extension = nullptr; switch (GetParam()) { case ExtensionLoadType::PACKED: @@ -201,6 +204,10 @@ // Ensure the ruleset is also loaded on the IO thread. content::RunAllTasksUntilIdle(); + // Wait for the background page to load if needed. + if (has_background_script_) + WaitForBackgroundScriptToLoad(&listener, extension->id()); + // Ensure no load errors were reported. EXPECT_TRUE(LoadErrorReporter::GetInstance()->GetErrors()->empty()); @@ -220,7 +227,77 @@ {URLPattern::kAllUrlsPattern}); } + void WaitForBackgroundScriptToLoad(ExtensionTestMessageListener* listener, + const ExtensionId& extension_id) { + ASSERT_TRUE(listener->WaitUntilSatisfied()); + ASSERT_EQ(extension_id, listener->extension_id_for_message()); + } + + void AddWhitelistedPages(const ExtensionId& extension_id, + const std::vector<std::string>& patterns) { + UpdateWhitelistedPages(extension_id, patterns, "addWhitelistedPages"); + } + + void RemoveWhitelistedPages(const ExtensionId& extension_id, + const std::vector<std::string>& patterns) { + UpdateWhitelistedPages(extension_id, patterns, "removeWhitelistedPages"); + } + + // Verifies that the result of getWhitelistedPages call is the same as + // |expected_patterns|. + void VerifyGetWhitelistedPages( + const ExtensionId& extension_id, + const std::set<std::string>& expected_patterns) { + static constexpr char kScript[] = R"( + chrome.declarativeNetRequest.getWhitelistedPages(function(patterns) { + window.domAutomationController.send(chrome.runtime.lastError + ? 'error' + : JSON.stringify(patterns)); + }); + )"; + + const std::string result = + ExecuteScriptInBackgroundPage(extension_id, kScript); + ASSERT_NE("error", result); + + // Parse |result| as a list and deserialize it to a set of strings. + std::unique_ptr<base::Value> value = + JSONStringValueDeserializer(result).Deserialize( + nullptr /*error_code*/, nullptr /*error_message*/); + ASSERT_TRUE(value); + ASSERT_TRUE(value->is_list()); + std::set<std::string> patterns; + for (const auto& pattern_value : value->GetList()) { + ASSERT_TRUE(pattern_value.is_string()); + patterns.insert(pattern_value.GetString()); + } + + EXPECT_EQ(expected_patterns, patterns); + } + private: + void UpdateWhitelistedPages(const ExtensionId& extension_id, + const std::vector<std::string>& patterns, + const std::string& function_name) { + static constexpr char kScript[] = R"( + chrome.declarativeNetRequest.%s(%s, function() { + window.domAutomationController.send(chrome.runtime.lastError + ? 'error' + : 'success'); + }); + )"; + + // Serialize |patterns| to JSON. + std::unique_ptr<base::ListValue> list = ToListValue(patterns); + std::string json_string; + ASSERT_TRUE(JSONStringValueSerializer(&json_string).Serialize(*list)); + + EXPECT_EQ("success", ExecuteScriptInBackgroundPage( + extension_id, + base::StringPrintf(kScript, function_name.c_str(), + json_string.c_str()))); + } + base::ScopedTempDir temp_dir_; bool has_background_script_ = false; @@ -1106,7 +1183,7 @@ rules_2, "extension_2", {URLPattern::kAllUrlsPattern})); const std::string extension_id_2 = last_loaded_extension_id(); - auto get_manifest_url = [](const std::string& extension_id) { + auto get_manifest_url = [](const ExtensionId& extension_id) { return GURL(base::StringPrintf("%s://%s/manifest.json", extensions::kExtensionScheme, extension_id.c_str())); @@ -1137,37 +1214,13 @@ ASSERT_TRUE(dnr_extension); EXPECT_EQ("Test extension", dnr_extension->name()); - // Ensure the background page is ready before dispatching the script to it. - if (!ExtensionSystem::Get(profile())->runtime_data()->IsBackgroundPageReady( - dnr_extension)) { - content::WindowedNotificationObserver( - NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, - content::Source<Extension>(dnr_extension)) - .Wait(); - } + constexpr char kGoogleDotCom[] = "https://www.google.com/"; - // Whitelist "https://www.google.com/". - const char* script1 = R"( - chrome.declarativeNetRequest.addWhitelistedPages( - ['https://www.google.com/'], function() { - window.domAutomationController.send('success'); - }); - )"; - EXPECT_EQ("success", - ExecuteScriptInBackgroundPage(last_loaded_extension_id(), script1)); + // Whitelist |kGoogleDotCom|. + AddWhitelistedPages(dnr_extension->id(), {kGoogleDotCom}); // Ensure that the page was whitelisted. - const char* script2 = R"( - chrome.declarativeNetRequest.getWhitelistedPages(function(patterns) { - if (patterns.length === 1 && patterns[0] === 'https://www.google.com/') - window.domAutomationController.send('success'); - else - window.domAutomationController.send('error'); - }); - )"; - - EXPECT_EQ("success", - ExecuteScriptInBackgroundPage(last_loaded_extension_id(), script2)); + VerifyGetWhitelistedPages(dnr_extension->id(), {kGoogleDotCom}); } // Tests that the pages whitelisted using the page whitelisting API are @@ -1191,46 +1244,24 @@ ASSERT_TRUE(dnr_extension); // Ensure the background page is ready before dispatching the script to it. + // TODO(karandeepb): Remove the need to check IsBackgroundPageReady by + // creating the ExtensionTestMessageListener early. This should also ensure + // that the we start listening for messages from extension early enough to + // avoid any races. See crbug.com/838536. if (!ExtensionSystem::Get(profile())->runtime_data()->IsBackgroundPageReady( dnr_extension)) { - content::WindowedNotificationObserver( - NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, - content::Source<Extension>(dnr_extension)) - .Wait(); + ExtensionTestMessageListener listener("ready", false /*will_reply*/); + WaitForBackgroundScriptToLoad(&listener, dnr_extension->id()); } - const char* script1 = R"( - chrome.declarativeNetRequest.getWhitelistedPages(function(patterns) { - if (patterns.length === 1 && patterns[0] === "https://www.google.com/") - window.domAutomationController.send("success"); - else - window.domAutomationController.send("error"); - }); - )"; - ASSERT_EQ("success", - ExecuteScriptInBackgroundPage(dnr_extension->id(), script1)); + constexpr char kGoogleDotCom[] = "https://www.google.com/"; - // Remove "https://www.google.com/" from the whitelist. - const char* script2 = R"( - chrome.declarativeNetRequest.removeWhitelistedPages( - ["https://www.google.com/"], function() { - window.domAutomationController.send("success"); - }); - )"; - ASSERT_EQ("success", - ExecuteScriptInBackgroundPage(dnr_extension->id(), script2)); + VerifyGetWhitelistedPages(dnr_extension->id(), {kGoogleDotCom}); - // Ensure that the page was removed from the whitelist. - const char* script3 = R"( - chrome.declarativeNetRequest.getWhitelistedPages(function(patterns) { - if (patterns.length === 0) - window.domAutomationController.send("success"); - else - window.domAutomationController.send("error"); - }); - )"; - EXPECT_EQ("success", - ExecuteScriptInBackgroundPage(dnr_extension->id(), script3)); + // Remove |kGoogleDotCom| from the whitelist. + RemoveWhitelistedPages(dnr_extension->id(), {kGoogleDotCom}); + + VerifyGetWhitelistedPages(dnr_extension->id(), {}); } // Test fixture to verify that host permissions for the request url and the
diff --git a/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc b/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc index 2d8cb60..90c6838 100644 --- a/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc +++ b/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
@@ -96,8 +96,8 @@ // Add 3 web contentses to the browser. content::WebContents* web_contentses[arraysize(tab_urls)]; for (size_t i = 0; i < arraysize(tab_urls); ++i) { - std::unique_ptr<content::WebContents> web_contents = base::WrapUnique( - content::WebContentsTester::CreateTestWebContents(profile(), nullptr)); + std::unique_ptr<content::WebContents> web_contents = + content::WebContentsTester::CreateTestWebContents(profile(), nullptr); content::WebContents* raw_web_contents = web_contents.get(); web_contentses[i] = raw_web_contents; browser()->tab_strip_model()->AppendWebContents(std::move(web_contents), @@ -157,8 +157,8 @@ // Add 3 web contentses to the browser. content::WebContents* web_contentses[arraysize(tab_urls)]; for (size_t i = 0; i < arraysize(tab_urls); ++i) { - std::unique_ptr<content::WebContents> web_contents = base::WrapUnique( - content::WebContentsTester::CreateTestWebContents(profile(), nullptr)); + std::unique_ptr<content::WebContents> web_contents = + content::WebContentsTester::CreateTestWebContents(profile(), nullptr); content::WebContents* raw_web_contents = web_contents.get(); web_contentses[i] = raw_web_contents; browser()->tab_strip_model()->AppendWebContents(std::move(web_contents), @@ -248,8 +248,8 @@ .Build(); ASSERT_TRUE(extension); - std::unique_ptr<content::WebContents> web_contents = base::WrapUnique( - content::WebContentsTester::CreateTestWebContents(profile(), nullptr)); + std::unique_ptr<content::WebContents> web_contents = + content::WebContentsTester::CreateTestWebContents(profile(), nullptr); content::WebContents* raw_web_contents = web_contents.get(); ASSERT_TRUE(raw_web_contents); content::WebContentsTester* web_contents_tester =
diff --git a/chrome/browser/extensions/extension_protocols_unittest.cc b/chrome/browser/extensions/extension_protocols_unittest.cc index 475fccad..f1dddbc 100644 --- a/chrome/browser/extensions/extension_protocols_unittest.cc +++ b/chrome/browser/extensions/extension_protocols_unittest.cc
@@ -197,7 +197,7 @@ void SetUp() override { testing::Test::SetUp(); testing_profile_ = TestingProfile::Builder().Build(); - contents_.reset(CreateTestWebContents()); + contents_ = CreateTestWebContents(); extension_info_map_ = new InfoMap(); old_factory_ = resource_context_.GetRequestContext()->job_factory(); @@ -330,7 +330,7 @@ return GetResult(std::move(request), test_delegate_.request_status()); } - content::WebContents* CreateTestWebContents() { + std::unique_ptr<content::WebContents> CreateTestWebContents() { auto site_instance = content::SiteInstance::Create(browser_context()); return content::WebContentsTester::CreateTestWebContents( browser_context(), std::move(site_instance));
diff --git a/chrome/browser/extensions/webstore_inline_installer_unittest.cc b/chrome/browser/extensions/webstore_inline_installer_unittest.cc index 89143ed..163d71a7 100644 --- a/chrome/browser/extensions/webstore_inline_installer_unittest.cc +++ b/chrome/browser/extensions/webstore_inline_installer_unittest.cc
@@ -70,7 +70,7 @@ void WebstoreInlineInstallerTest::SetUp() { ChromeRenderViewHostTestHarness::SetUp(); - web_contents_.reset(CreateTestWebContents()); + web_contents_ = CreateTestWebContents(); } void WebstoreInlineInstallerTest::TearDown() {
diff --git a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc index 18232430..855bfa7 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
@@ -218,17 +218,18 @@ } void GeolocationPermissionContextTests::AddNewTab(const GURL& url) { - content::WebContents* new_tab = CreateTestWebContents(); - content::NavigationSimulator::NavigateAndCommitFromBrowser(new_tab, url); + std::unique_ptr<content::WebContents> new_tab = CreateTestWebContents(); + content::NavigationSimulator::NavigateAndCommitFromBrowser(new_tab.get(), + url); // Set up required helpers, and make this be as "tabby" as the code requires. #if BUILDFLAG(ENABLE_EXTENSIONS) - extensions::SetViewType(new_tab, extensions::VIEW_TYPE_TAB_CONTENTS); + extensions::SetViewType(new_tab.get(), extensions::VIEW_TYPE_TAB_CONTENTS); #endif - SetupRequestManager(new_tab); + SetupRequestManager(new_tab.get()); - extra_tabs_.push_back(base::WrapUnique(new_tab)); + extra_tabs_.push_back(std::move(new_tab)); } void GeolocationPermissionContextTests::CheckTabContentsState(
diff --git a/chrome/browser/lifetime/browser_close_manager.cc b/chrome/browser/lifetime/browser_close_manager.cc index cb42dd00..db0f58c 100644 --- a/chrome/browser/lifetime/browser_close_manager.cc +++ b/chrome/browser/lifetime/browser_close_manager.cc
@@ -177,7 +177,7 @@ // DestroyBrowser to make sure the browser is deleted and cleanup can // happen. while (browser->tab_strip_model()->count()) - delete browser->tab_strip_model()->GetWebContentsAt(0); + browser->tab_strip_model()->DetachWebContentsAt(0); browser->window()->DestroyBrowser(); // Destroying the browser should have removed it from the browser list. DCHECK(!base::ContainsValue(*BrowserList::GetInstance(), browser));
diff --git a/chrome/browser/media/router/presentation/presentation_service_delegate_impl_unittest.cc b/chrome/browser/media/router/presentation/presentation_service_delegate_impl_unittest.cc index 49b5890..41a8502 100644 --- a/chrome/browser/media/router/presentation/presentation_service_delegate_impl_unittest.cc +++ b/chrome/browser/media/router/presentation/presentation_service_delegate_impl_unittest.cc
@@ -248,18 +248,18 @@ content::WebContentsTester::CreateTestWebContents(incognito_profile, nullptr); } - return incognito_web_contents_; + return incognito_web_contents_.get(); } void TearDown() override { // We must delete the incognito WC first, as that triggers observers which // require RenderViewHost, etc., that in turn are deleted by // RenderViewHostTestHarness::TearDown(). - delete incognito_web_contents_; + incognito_web_contents_.reset(); PresentationServiceDelegateImplTest::TearDown(); } - content::WebContents* incognito_web_contents_; + std::unique_ptr<content::WebContents> incognito_web_contents_; }; TEST_F(PresentationServiceDelegateImplTest, AddScreenAvailabilityListener) {
diff --git a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc index 2be9c73..62e5f89 100644 --- a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc +++ b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
@@ -470,14 +470,14 @@ no_permissions_extension_ = AddMediaGalleriesApp("no", read_permissions, profile_.get()); - single_web_contents_.reset( - content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL)); + single_web_contents_ = + content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL); single_rph_ = rph_factory->ReleaseRPH(profile_.get()); - shared_web_contents1_.reset( - content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL)); - shared_web_contents2_.reset( - content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL)); + shared_web_contents1_ = + content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL); + shared_web_contents2_ = + content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL); shared_rph_ = rph_factory->ReleaseRPH(profile_.get()); }
diff --git a/chrome/browser/metrics/tab_stats_data_store_unittest.cc b/chrome/browser/metrics/tab_stats_data_store_unittest.cc index 672fcaf1..561fa34 100644 --- a/chrome/browser/metrics/tab_stats_data_store_unittest.cc +++ b/chrome/browser/metrics/tab_stats_data_store_unittest.cc
@@ -69,7 +69,7 @@ TEST_F(TabStatsDataStoreTest, TrackTabUsageDuringInterval) { std::vector<std::unique_ptr<content::WebContents>> web_contents_vec; for (size_t i = 0; i < 3; ++i) { - web_contents_vec.emplace_back(base::WrapUnique(CreateTestWebContents())); + web_contents_vec.emplace_back(CreateTestWebContents()); // Make sure that these WebContents are initially not visible. web_contents_vec.back()->WasHidden(); } @@ -142,12 +142,12 @@ // Make sure that the tab stats get properly copied when a tab is replaced. TabStatsDataStore::TabStateDuringInterval tab_stats_copy = interval_map->find(web_contents_id_vec[1])->second; - content::WebContents* new_contents = CreateTestWebContents(); + std::unique_ptr<content::WebContents> new_contents = CreateTestWebContents(); content::WebContents* old_contents = web_contents_vec[1].get(); - data_store_->OnTabReplaced(old_contents, new_contents); - EXPECT_EQ(data_store_->GetTabIDForTesting(new_contents).value(), + data_store_->OnTabReplaced(old_contents, new_contents.get()); + EXPECT_EQ(data_store_->GetTabIDForTesting(new_contents.get()).value(), web_contents_id_vec[1]); - web_contents_vec[1].reset(new_contents); + web_contents_vec[1] = std::move(new_contents); // |old_contents| is invalid starting from here. EXPECT_FALSE(data_store_->GetTabIDForTesting(old_contents)); auto iter = interval_map->find(web_contents_id_vec[1]);
diff --git a/chrome/browser/metrics/tab_stats_tracker_unittest.cc b/chrome/browser/metrics/tab_stats_tracker_unittest.cc index d7b25bf..ac41f6f 100644 --- a/chrome/browser/metrics/tab_stats_tracker_unittest.cc +++ b/chrome/browser/metrics/tab_stats_tracker_unittest.cc
@@ -40,9 +40,10 @@ ChromeRenderViewHostTestHarness* test_harness) { EXPECT_TRUE(test_harness); for (size_t i = 0; i < tab_count; ++i) { - content::WebContents* tab = test_harness->CreateTestWebContents(); - tab_stats_data_store()->OnTabAdded(tab); - tabs_.emplace_back(base::WrapUnique(tab)); + std::unique_ptr<content::WebContents> tab = + test_harness->CreateTestWebContents(); + tab_stats_data_store()->OnTabAdded(tab.get()); + tabs_.emplace_back(std::move(tab)); } return tab_stats_data_store()->tab_stats().total_tab_count; } @@ -291,7 +292,7 @@ std::vector<std::unique_ptr<content::WebContents>> web_contentses; for (size_t i = 0; i < 4; ++i) { - web_contentses.emplace_back(base::WrapUnique(CreateTestWebContents())); + web_contentses.emplace_back(CreateTestWebContents()); // Make sure that these WebContents are initially not visible. web_contentses[i]->WasHidden(); tab_stats_tracker_->OnInitialOrInsertedTab(web_contentses[i].get());
diff --git a/chrome/browser/notifications/notification_platform_bridge_win.cc b/chrome/browser/notifications/notification_platform_bridge_win.cc index 58c58a9..bea310bb 100644 --- a/chrome/browser/notifications/notification_platform_bridge_win.cc +++ b/chrome/browser/notifications/notification_platform_bridge_win.cc
@@ -825,7 +825,7 @@ NotificationLaunchId launch_id(base::UTF16ToUTF8( command_line.GetSwitchValueNative(switches::kNotificationLaunchId))); if (!launch_id.is_valid()) { - LogActivationStatus(ActivationStatus::ACTIVATION_INVALID_LAUNCH_ID); + LogActivationStatus(ActivationStatus::INVALID_LAUNCH_ID); return false; } @@ -852,11 +852,10 @@ std::string NotificationPlatformBridgeWin::GetProfileIdFromLaunchId( const base::string16& launch_id_str) { NotificationLaunchId launch_id(base::UTF16ToUTF8(launch_id_str)); - if (!launch_id.is_valid()) { - LogActivationStatus(ActivationStatus::GET_PROFILE_ID_INVALID_LAUNCH_ID); - return std::string(); - } - return launch_id.profile_id(); + + // The launch_id_invalid failure is logged via HandleActivation(). We don't + // re-log it here, which would skew the UMA failure metrics. + return launch_id.is_valid() ? launch_id.profile_id() : std::string(); } // static
diff --git a/chrome/browser/notifications/notification_platform_bridge_win_metrics.h b/chrome/browser/notifications/notification_platform_bridge_win_metrics.h index 1a0364e..3db596a 100644 --- a/chrome/browser/notifications/notification_platform_bridge_win_metrics.h +++ b/chrome/browser/notifications/notification_platform_bridge_win_metrics.h
@@ -114,8 +114,9 @@ // numeric values should never be reused. enum class ActivationStatus { SUCCESS = 0, - GET_PROFILE_ID_INVALID_LAUNCH_ID = 1, - ACTIVATION_INVALID_LAUNCH_ID = 2, + DEPRECATED_GET_PROFILE_ID_INVALID_LAUNCH_ID = 1, + DEPRECATED_ACTIVATION_INVALID_LAUNCH_ID = 2, + INVALID_LAUNCH_ID = 3, COUNT // Must be the final value. };
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc index 8d2293c..65787da2 100644 --- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc +++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -81,14 +81,12 @@ #include "chrome/browser/offline_pages/offline_page_model_factory.h" #include "chrome/browser/offline_pages/prefetch/prefetch_service_factory.h" #include "chrome/browser/offline_pages/request_coordinator_factory.h" -#include "components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.h" #include "components/ntp_snippets/remote/prefetched_pages_tracker_impl.h" #include "components/offline_pages/core/background/request_coordinator.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_model.h" #include "components/offline_pages/core/prefetch/prefetch_service.h" #include "components/offline_pages/core/prefetch/suggested_articles_observer.h" -#include "components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.h" #endif using bookmarks::BookmarkModel; @@ -107,7 +105,6 @@ using ntp_snippets::IsBookmarkProviderEnabled; using ntp_snippets::IsDownloadsProviderEnabled; using ntp_snippets::IsForeignSessionsProviderEnabled; -using ntp_snippets::IsRecentTabProviderEnabled; using ntp_snippets::PersistentScheduler; using ntp_snippets::PrefetchedPagesTracker; using ntp_snippets::RemoteSuggestionsDatabase; @@ -131,7 +128,6 @@ #if BUILDFLAG(ENABLE_OFFLINE_PAGES) using ntp_snippets::PrefetchedPagesTrackerImpl; -using ntp_snippets::RecentTabSuggestionsProvider; using offline_pages::OfflinePageModel; using offline_pages::OfflinePageModelFactory; using offline_pages::RequestCoordinator; @@ -154,23 +150,6 @@ #if BUILDFLAG(ENABLE_OFFLINE_PAGES) -void RegisterRecentTabProviderIfEnabled(ContentSuggestionsService* service, - Profile* profile, - OfflinePageModel* offline_page_model) { - if (!IsRecentTabProviderEnabled()) { - return; - } - - RequestCoordinator* request_coordinator = - RequestCoordinatorFactory::GetForBrowserContext(profile); - offline_pages::DownloadUIAdapter* ui_adapter = offline_pages:: - RecentTabsUIAdapterDelegate::GetOrCreateRecentTabsUIAdapter( - offline_page_model, request_coordinator); - auto provider = std::make_unique<RecentTabSuggestionsProvider>( - service, ui_adapter, profile->GetPrefs()); - service->RegisterProvider(std::move(provider)); -} - void RegisterWithPrefetching(ContentSuggestionsService* service, Profile* profile) { // There's a circular dependency between ContentSuggestionsService and @@ -497,7 +476,6 @@ #endif // OS_ANDROID #if BUILDFLAG(ENABLE_OFFLINE_PAGES) - RegisterRecentTabProviderIfEnabled(service, profile, offline_page_model); RegisterWithPrefetching(service, profile); #endif
diff --git a/chrome/browser/ntp_snippets/dependent_features.cc b/chrome/browser/ntp_snippets/dependent_features.cc index a0ca616..5ac907f 100644 --- a/chrome/browser/ntp_snippets/dependent_features.cc +++ b/chrome/browser/ntp_snippets/dependent_features.cc
@@ -46,14 +46,6 @@ ntp_snippets::kBookmarkSuggestionsFeature); } -bool IsRecentTabProviderEnabled() { - return !AreNtpShortcutsEnabled() && - base::FeatureList::IsEnabled( - ntp_snippets::kRecentOfflineTabSuggestionsFeature) && - base::FeatureList::IsEnabled( - offline_pages::kOffliningRecentPagesFeature); -} - bool IsForeignSessionsProviderEnabled() { return !AreNtpShortcutsEnabled() && base::FeatureList::IsEnabled(
diff --git a/chrome/browser/ntp_snippets/dependent_features.h b/chrome/browser/ntp_snippets/dependent_features.h index 801621e5..38a8b22 100644 --- a/chrome/browser/ntp_snippets/dependent_features.h +++ b/chrome/browser/ntp_snippets/dependent_features.h
@@ -17,8 +17,6 @@ bool IsBookmarkProviderEnabled(); -bool IsRecentTabProviderEnabled(); - bool IsPhysicalWebPageProviderEnabled(); bool IsForeignSessionsProviderEnabled();
diff --git a/chrome/browser/offline_pages/android/offline_page_bridge.cc b/chrome/browser/offline_pages/android/offline_page_bridge.cc index 8a5e2b5..fa9ce4f 100644 --- a/chrome/browser/offline_pages/android/offline_page_bridge.cc +++ b/chrome/browser/offline_pages/android/offline_page_bridge.cc
@@ -42,7 +42,6 @@ #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_model.h" #include "components/offline_pages/core/offline_page_types.h" -#include "components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.h" #include "components/offline_pages/core/request_header/offline_page_header.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/web_contents.h" @@ -821,19 +820,6 @@ request_ids, base::Bind(&OnRemoveRequestsDone, j_callback_ref)); } -void OfflinePageBridge::RegisterRecentTab(JNIEnv* env, - const JavaParamRef<jobject>& obj, - int tab_id) { - RequestCoordinator* request_coordinator = - RequestCoordinatorFactory::GetForBrowserContext(browser_context_); - - RecentTabsUIAdapterDelegate* ui_adapter_delegate = - RecentTabsUIAdapterDelegate::FromDownloadUIAdapter( - RecentTabsUIAdapterDelegate::GetOrCreateRecentTabsUIAdapter( - offline_page_model_, request_coordinator)); - ui_adapter_delegate->RegisterTab(tab_id); -} - void OfflinePageBridge::WillCloseTab( JNIEnv* env, const JavaParamRef<jobject>& obj, @@ -850,19 +836,6 @@ tab_helper->WillCloseTab(); } -void OfflinePageBridge::UnregisterRecentTab(JNIEnv* env, - const JavaParamRef<jobject>& obj, - int tab_id) { - RequestCoordinator* request_coordinator = - RequestCoordinatorFactory::GetForBrowserContext(browser_context_); - - RecentTabsUIAdapterDelegate* ui_adapter_delegate = - RecentTabsUIAdapterDelegate::FromDownloadUIAdapter( - RecentTabsUIAdapterDelegate::GetOrCreateRecentTabsUIAdapter( - offline_page_model_, request_coordinator)); - ui_adapter_delegate->UnregisterTab(tab_id); -} - void OfflinePageBridge::ScheduleDownload( JNIEnv* env, const JavaParamRef<jobject>& obj,
diff --git a/chrome/browser/offline_pages/android/offline_page_bridge.h b/chrome/browser/offline_pages/android/offline_page_bridge.h index 9e49a6a9..489c65f 100644 --- a/chrome/browser/offline_pages/android/offline_page_bridge.h +++ b/chrome/browser/offline_pages/android/offline_page_bridge.h
@@ -166,15 +166,9 @@ const base::android::JavaParamRef<jlongArray>& j_request_ids_array, const base::android::JavaParamRef<jobject>& j_callback_obj); - void RegisterRecentTab(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - int tab_id); void WillCloseTab(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jobject>& j_web_contents); - void UnregisterRecentTab(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - int tab_id); void ScheduleDownload( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj,
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index b7ba0b7..c4aafae 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -182,7 +182,6 @@ #include "components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h" #include "components/ntp_snippets/breaking_news/subscription_manager_impl.h" #include "components/ntp_snippets/category_rankers/click_based_category_ranker.h" -#include "components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.h" #include "components/ntp_tiles/popular_sites_impl.h" #else #include "chrome/browser/gcm/gcm_product_util.h" @@ -305,6 +304,9 @@ // Deprecated 4/2018. const char kDismissedPhysicalWebPageSuggestions[] = "ntp_suggestions.physical_web.dismissed_ids"; +// Deprecated 5/2018. +const char kDismissedRecentOfflineTabSuggestions[] = + "ntp_suggestions.offline_pages.recent_tabs.dismissed_ids"; #else // Deprecated 1/2018. const char kShowFirstRunBubbleOption[] = "show-first-run-bubble-option"; @@ -330,6 +332,7 @@ #if defined(OS_ANDROID) registry->RegisterListPref(kDismissedPhysicalWebPageSuggestions); + registry->RegisterListPref(kDismissedRecentOfflineTabSuggestions); #endif } @@ -589,7 +592,6 @@ DownloadSuggestionsProvider::RegisterProfilePrefs(registry); ntp_snippets::BreakingNewsGCMAppHandler::RegisterProfilePrefs(registry); ntp_snippets::ClickBasedCategoryRanker::RegisterProfilePrefs(registry); - ntp_snippets::RecentTabSuggestionsProvider::RegisterProfilePrefs(registry); ntp_snippets::SubscriptionManagerImpl::RegisterProfilePrefs(registry); OomInterventionDecider::RegisterProfilePrefs(registry); #endif // defined(OS_ANDROID) @@ -721,5 +723,8 @@ #if defined(OS_ANDROID) // Added 4/2018 profile_prefs->ClearPref(kDismissedPhysicalWebPageSuggestions); + + // Added 5/2018 + profile_prefs->ClearPref(kDismissedRecentOfflineTabSuggestions); #endif // defined(OS_ANDROID) }
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index a54aa04..aae0c8e 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc
@@ -1095,11 +1095,6 @@ } void PrerenderManager::DeleteOldWebContents() { - for (WebContents* web_contents : old_web_contents_list_) { - // TODO(dominich): should we use Instant Unload Handler here? - // Or should |old_web_contents_list_| contain unique_ptrs? - delete web_contents; - } old_web_contents_list_.clear(); } @@ -1149,7 +1144,7 @@ void PrerenderManager::ScheduleDeleteOldWebContents( std::unique_ptr<WebContents> tab, OnCloseWebContentsDeleter* deleter) { - old_web_contents_list_.push_back(tab.release()); + old_web_contents_list_.push_back(std::move(tab)); PostCleanupTask(); if (!deleter)
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h index 10f37d8f..c5d7f27 100644 --- a/chrome/browser/prerender/prerender_manager.h +++ b/chrome/browser/prerender/prerender_manager.h
@@ -576,7 +576,7 @@ // Track time of last prerender to limit prerender spam. base::TimeTicks last_prerender_start_time_; - std::vector<content::WebContents*> old_web_contents_list_; + std::vector<std::unique_ptr<content::WebContents>> old_web_contents_list_; std::vector<std::unique_ptr<OnCloseWebContentsDeleter>> on_close_web_contents_deleters_;
diff --git a/chrome/browser/printing/background_printing_manager.cc b/chrome/browser/printing/background_printing_manager.cc index 003944a..14fb359 100644 --- a/chrome/browser/printing/background_printing_manager.cc +++ b/chrome/browser/printing/background_printing_manager.cc
@@ -31,7 +31,6 @@ private: void RenderProcessGone(base::TerminationStatus status) override; - void WebContentsDestroyed() override; BackgroundPrintingManager* manager_; }; @@ -46,9 +45,6 @@ base::TerminationStatus status) { manager_->DeletePreviewContents(web_contents()); } -void BackgroundPrintingManager::Observer::WebContentsDestroyed() { - manager_->DeletePreviewContents(web_contents()); -} BackgroundPrintingManager::BackgroundPrintingManager() { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -64,27 +60,31 @@ } void BackgroundPrintingManager::OwnPrintPreviewDialog( - WebContents* preview_dialog) { + std::unique_ptr<WebContents> preview_dialog) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(PrintPreviewDialogController::IsPrintPreviewURL( preview_dialog->GetURL())); - CHECK(!HasPrintPreviewDialog(preview_dialog)); + CHECK(!HasPrintPreviewDialog(preview_dialog.get())); - printing_contents_map_[preview_dialog] = - std::make_unique<Observer>(this, preview_dialog); + WebContents* raw_preview_dialog = preview_dialog.get(); + PrintingContents printing_contents; + printing_contents.observer = + std::make_unique<Observer>(this, raw_preview_dialog); + printing_contents.contents = std::move(preview_dialog); + printing_contents_map_[raw_preview_dialog] = std::move(printing_contents); // Watch for print jobs finishing. Everything else is watched for by the // Observer. TODO(avi, cait): finish the job of removing this last // notification. registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED, - content::Source<WebContents>(preview_dialog)); + content::Source<WebContents>(raw_preview_dialog)); // Activate the initiator. PrintPreviewDialogController* dialog_controller = PrintPreviewDialogController::GetInstance(); if (!dialog_controller) return; - WebContents* initiator = dialog_controller->GetInitiator(preview_dialog); + WebContents* initiator = dialog_controller->GetInitiator(raw_preview_dialog); if (!initiator) return; initiator->GetDelegate()->ActivateContents(initiator); @@ -131,12 +131,15 @@ // Stop all observation ... registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED, content::Source<WebContents>(preview_contents)); + std::unique_ptr<WebContents> contents_to_delete = + std::move(i->second.contents); printing_contents_map_.erase(i); // ... and mortally wound the contents. Deletion immediately is not a good // idea in case this was triggered by |preview_contents| far up the // callstack. (Trace where the NOTIFICATION_PRINT_JOB_RELEASED comes from.) - base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, preview_contents); + base::ThreadTaskRunnerHandle::Get()->DeleteSoon( + FROM_HERE, std::move(contents_to_delete)); } std::set<content::WebContents*> BackgroundPrintingManager::CurrentContentSet() { @@ -152,4 +155,12 @@ return base::ContainsKey(printing_contents_map_, preview_dialog); } +BackgroundPrintingManager::PrintingContents::PrintingContents() = default; +BackgroundPrintingManager::PrintingContents::~PrintingContents() = default; +BackgroundPrintingManager::PrintingContents::PrintingContents( + PrintingContents&&) = default; +BackgroundPrintingManager::PrintingContents& +BackgroundPrintingManager::PrintingContents::operator=(PrintingContents&&) = + default; + } // namespace printing
diff --git a/chrome/browser/printing/background_printing_manager.h b/chrome/browser/printing/background_printing_manager.h index ea211ad..2042a23 100644 --- a/chrome/browser/printing/background_printing_manager.h +++ b/chrome/browser/printing/background_printing_manager.h
@@ -36,7 +36,8 @@ // Takes ownership of |preview_dialog| and deletes it when |preview_dialog| // finishes printing. This removes |preview_dialog| from its ConstrainedDialog // and hides it from the user. - void OwnPrintPreviewDialog(content::WebContents* preview_dialog); + void OwnPrintPreviewDialog( + std::unique_ptr<content::WebContents> preview_dialog); // Returns true if |printing_contents_map_| contains |preview_dialog|. bool HasPrintPreviewDialog(content::WebContents* preview_dialog); @@ -60,9 +61,21 @@ void DeletePreviewContents(content::WebContents* preview_contents); // A map from print preview WebContentses (managed by - // BackgroundPrintingManager) to the Observers that observe them. - std::map<content::WebContents*, std::unique_ptr<Observer>> - printing_contents_map_; + // BackgroundPrintingManager) to the Observers that observe them and the owned + // version of the WebContents. + struct PrintingContents { + PrintingContents(); + ~PrintingContents(); + PrintingContents(PrintingContents&&); + PrintingContents& operator=(PrintingContents&&); + + std::unique_ptr<content::WebContents> contents; + std::unique_ptr<Observer> observer; + + private: + DISALLOW_COPY_AND_ASSIGN(PrintingContents); + }; + std::map<content::WebContents*, PrintingContents> printing_contents_map_; content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/resource_coordinator/background_tab_navigation_throttle_unittest.cc b/chrome/browser/resource_coordinator/background_tab_navigation_throttle_unittest.cc index 26144af4..c78a7f61 100644 --- a/chrome/browser/resource_coordinator/background_tab_navigation_throttle_unittest.cc +++ b/chrome/browser/resource_coordinator/background_tab_navigation_throttle_unittest.cc
@@ -95,7 +95,7 @@ std::unique_ptr<content::WebContents> opener; if (!no_opener_) { - opener.reset(CreateTestWebContents()); + opener = CreateTestWebContents(); content::WebContentsTester::For(web_contents())->SetOpener(opener.get()); }
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc index 6802a3ff..9c06117 100644 --- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc
@@ -237,7 +237,7 @@ private: std::unique_ptr<content::WebContents> CreateAndNavigateWebContents() { std::unique_ptr<content::WebContents> web_contents = - base::WrapUnique(CreateTestWebContents()); + CreateTestWebContents(); // Commit an URL to allow discarding. content::WebContentsTester::For(web_contents.get()) ->NavigateAndCommit(GURL("https://www.example.com")); @@ -320,7 +320,7 @@ TabLifecycleUnitExternal* tab_lifecycle_unit_external = source_->GetTabLifecycleUnitExternal(original_web_contents); std::unique_ptr<content::WebContents> new_web_contents = - base::WrapUnique(CreateTestWebContents()); + CreateTestWebContents(); content::WebContents* raw_new_web_contents = new_web_contents.get(); std::unique_ptr<content::WebContents> original_web_contents_deleter = tab_strip_model_->ReplaceWebContentsAt(1, std::move(new_web_contents));
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc index 694939d..7d2f440d 100644 --- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
@@ -74,7 +74,7 @@ ChromeRenderViewHostTestHarness::SetUp(); std::unique_ptr<content::WebContents> test_web_contents = - base::WrapUnique(CreateTestWebContents()); + CreateTestWebContents(); web_contents_ = test_web_contents.get(); // Commit an URL to allow discarding. content::WebContentsTester::For(web_contents_) @@ -86,7 +86,7 @@ web_contents_->WasHidden(); std::unique_ptr<content::WebContents> second_web_contents = - base::WrapUnique(CreateTestWebContents()); + CreateTestWebContents(); content::WebContents* raw_second_web_contents = second_web_contents.get(); tab_strip_model_->AppendWebContents(std::move(second_web_contents), false); raw_second_web_contents->WasHidden();
diff --git a/chrome/browser/resource_coordinator/tab_load_tracker_unittest.cc b/chrome/browser/resource_coordinator/tab_load_tracker_unittest.cc index c47138f..cfa49164 100644 --- a/chrome/browser/resource_coordinator/tab_load_tracker_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_load_tracker_unittest.cc
@@ -96,9 +96,9 @@ void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); - contents1_.reset(CreateTestWebContents()); - contents2_.reset(CreateTestWebContents()); - contents3_.reset(CreateTestWebContents()); + contents1_ = CreateTestWebContents(); + contents2_ = CreateTestWebContents(); + contents3_ = CreateTestWebContents(); tracker_.AddObserver(&observer_); }
diff --git a/chrome/browser/resource_coordinator/tab_manager_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_unittest.cc index 7b84b37d..8a89957 100644 --- a/chrome/browser/resource_coordinator/tab_manager_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_unittest.cc
@@ -157,8 +157,7 @@ } std::unique_ptr<WebContents> CreateWebContents() { - std::unique_ptr<WebContents> web_contents = - base::WrapUnique(CreateTestWebContents()); + std::unique_ptr<WebContents> web_contents = CreateTestWebContents(); // Commit an URL to allow discarding. content::WebContentsTester::For(web_contents.get()) ->NavigateAndCommit(GURL("https://www.example.com")); @@ -170,7 +169,7 @@ tab_manager_ = g_browser_process->GetTabManager(); } - void TearDown() override { + void ResetState() { // NavigationHandles and NavigationThrottles must be deleted before the // associated WebContents. nav_handle1_.reset(); @@ -186,6 +185,10 @@ contents1_.reset(); contents2_.reset(); contents3_.reset(); + } + + void TearDown() override { + ResetState(); task_runner_->RunUntilIdle(); scoped_context_.reset(); @@ -195,12 +198,12 @@ void PrepareTabs(const char* url1 = kTestUrl, const char* url2 = kTestUrl, const char* url3 = kTestUrl) { - nav_handle1_ = CreateTabAndNavigation(url1); - nav_handle2_ = CreateTabAndNavigation(url2); - nav_handle3_ = CreateTabAndNavigation(url3); - contents1_ = base::WrapUnique(nav_handle1_->GetWebContents()); - contents2_ = base::WrapUnique(nav_handle2_->GetWebContents()); - contents3_ = base::WrapUnique(nav_handle3_->GetWebContents()); + contents1_ = CreateTestWebContents(); + nav_handle1_ = CreateTabAndNavigation(url1, contents1_.get()); + contents2_ = CreateTestWebContents(); + nav_handle2_ = CreateTabAndNavigation(url2, contents2_.get()); + contents3_ = CreateTestWebContents(); + nav_handle3_ = CreateTabAndNavigation(url3, contents3_.get()); contents1_->WasHidden(); contents2_->WasHidden(); @@ -258,8 +261,9 @@ } protected: - std::unique_ptr<NavigationHandle> CreateTabAndNavigation(const char* url) { - content::WebContents* web_contents = CreateTestWebContents(); + std::unique_ptr<NavigationHandle> CreateTabAndNavigation( + const char* url, + content::WebContents* web_contents) { TabUIHelper::CreateForWebContents(web_contents); return content::NavigationHandle::CreateNavigationHandleForTesting( GURL(url), web_contents->GetMainFrame()); @@ -705,6 +709,7 @@ EXPECT_FALSE(tab_manager1.IsNavigationDelayedForTest(nav_handle1_.get())); EXPECT_TRUE(tab_manager1.IsNavigationDelayedForTest(nav_handle2_.get())); EXPECT_TRUE(tab_manager1.IsNavigationDelayedForTest(nav_handle3_.get())); + ResetState(); TabManager tab_manager2; tab_manager2.SetLoadingSlotsForTest(2); @@ -712,6 +717,7 @@ EXPECT_FALSE(tab_manager2.IsNavigationDelayedForTest(nav_handle1_.get())); EXPECT_FALSE(tab_manager2.IsNavigationDelayedForTest(nav_handle2_.get())); EXPECT_TRUE(tab_manager2.IsNavigationDelayedForTest(nav_handle3_.get())); + ResetState(); TabManager tab_manager3; tab_manager3.SetLoadingSlotsForTest(3);
diff --git a/chrome/browser/resource_coordinator/tab_manager_web_contents_data_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_web_contents_data_unittest.cc index a48f671..9f613299 100644 --- a/chrome/browser/resource_coordinator/tab_manager_web_contents_data_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_web_contents_data_unittest.cc
@@ -45,8 +45,8 @@ TabManager::WebContentsData* CreateWebContentsAndTabData( std::unique_ptr<WebContents>* web_contents) { - web_contents->reset( - WebContentsTester::CreateTestWebContents(browser_context(), nullptr)); + *web_contents = + WebContentsTester::CreateTestWebContents(browser_context(), nullptr); TabManager::WebContentsData::CreateForWebContents(web_contents->get()); return TabManager::WebContentsData::FromWebContents(web_contents->get()); }
diff --git a/chrome/browser/resources/gaia_auth_host/authenticator.js b/chrome/browser/resources/gaia_auth_host/authenticator.js index 76c58c3..f926d3cb 100644 --- a/chrome/browser/resources/gaia_auth_host/authenticator.js +++ b/chrome/browser/resources/gaia_auth_host/authenticator.js
@@ -704,7 +704,9 @@ return; } // TODO(https://crbug.com/837107): remove this once API is fully stabilized. - if (!this.services_ && !this.email_.endsWith('@gmail.com')) { + // @example.com is used in tests. + if (!this.services_ && !this.email_.endsWith('@gmail.com') && + !this.email_.endsWith('@example.com')) { console.warn('Forcing empty services.'); this.services_ = []; }
diff --git a/chrome/browser/resources/print_preview/new/app.html b/chrome/browser/resources/print_preview/new/app.html index 7cb5fa0d..292cf56 100644 --- a/chrome/browser/resources/print_preview/new/app.html +++ b/chrome/browser/resources/print_preview/new/app.html
@@ -79,61 +79,64 @@ <print-preview-destination-settings id="destinationSettings" destination="[[destination_]]" destination-store="[[destinationStore_]]" - invitation-store="[[invitationStore_]]" + invitation-store="[[invitationStore_]]" class="settings-section" disabled="[[controlsDisabled_]]" state="[[state]]" recent-destinations="[[recentDestinations_]]" user-info="{{userInfo_}}" available> </print-preview-destination-settings> <print-preview-pages-settings settings="{{settings}}" - document-info="[[documentInfo_]]" disabled="[[controlsDisabled_]]" + document-info="[[documentInfo_]]" + class="settings-section" disabled="[[controlsDisabled_]]" available="[[settings.pages.available]]"> </print-preview-pages-settings> <print-preview-copies-settings settings="{{settings}}" - disabled="[[controlsDisabled_]]" + class="settings-section" disabled="[[controlsDisabled_]]" available="[[settings.copies.available]]"> </print-preview-copies-settings> <print-preview-layout-settings settings="{{settings}}" - disabled="[[controlsDisabled_]]" + class="settings-section" disabled="[[controlsDisabled_]]" available="[[settings.layout.available]]"> </print-preview-layout-settings> <print-preview-color-settings settings="{{settings}}" - disabled="[[controlsDisabled_]]" + class="settings-section" disabled="[[controlsDisabled_]]" available="[[settings.color.available]]"> </print-preview-color-settings> <print-preview-more-settings settings-expanded="{{settingsExpanded_}}" - disabled="[[controlsDisabled_]]" + class="settings-section" disabled="[[controlsDisabled_]]" available="[[shouldShowMoreSettings_]]"> </print-preview-more-settings> <print-preview-media-size-settings settings="{{settings}}" capability="[[destination_.capabilities.printer.media_size]]" - disabled="[[controlsDisabled_]]" + class="settings-section" disabled="[[controlsDisabled_]]" available="[[settings.mediaSize.available]]" collapsible> </print-preview-media-size-settings> <print-preview-margins-settings settings="{{settings}}" - disabled="[[controlsDisabled_]]" + class="settings-section" disabled="[[controlsDisabled_]]" available="[[settings.margins.available]]" collapsible> </print-preview-margins-settings> <print-preview-dpi-settings settings="{{settings}}" capability="[[destination_.capabilities.printer.dpi]]" - disabled="[[controlsDisabled_]]" + class="settings-section" disabled="[[controlsDisabled_]]" available="[[settings.dpi.available]]" collapsible> </print-preview-dpi-settings> <print-preview-scaling-settings settings="{{settings}}" - document-info="[[documentInfo_]]" disabled="[[controlsDisabled_]]" + document-info="[[documentInfo_]]" class="settings-section" + disabled="[[controlsDisabled_]]" available="[[settings.scaling.available]]" collapsible> </print-preview-scaling-settings> <print-preview-other-options-settings settings="{{settings}}" - disabled="[[controlsDisabled_]]" + class="settings-section" disabled="[[controlsDisabled_]]" available="[[settings.otherOptions.available]]" collapsible> </print-preview-other-options-settings> <print-preview-advanced-options-settings settings="{{settings}}" + class="settings-section" destination="[[destination_]]" disabled="[[controlsDisabled_]]" available="[[settings.vendorItems.available]]" collapsible> </print-preview-advanced-options-settings> <if expr="not chromeos"> <print-preview-link-container destination="[[destination_]]" app-kiosk-mode="[[isInAppKioskMode_]]" - disabled="[[controlsDisabled_]]" available + disabled="[[controlsDisabled_]]" <if expr="is_macosx"> on-open-pdf-in-preview="onOpenPdfInPreview_" </if>
diff --git a/chrome/browser/resources/print_preview/new/app.js b/chrome/browser/resources/print_preview/new/app.js index ee0eae5..b8412aaf 100644 --- a/chrome/browser/resources/print_preview/new/app.js +++ b/chrome/browser/resources/print_preview/new/app.js
@@ -542,15 +542,16 @@ /** Changes the visibility of settings sections. */ updateSettingsVisibility_: function() { - Array.from(this.$.settingsSections.children).forEach(section => { - if (!section.available || - (section.collapsible && this.shouldShowMoreSettings_ && - !this.settingsExpanded_)) { - section.hide(); - return; - } - section.show(); - }); + Array.from(this.shadowRoot.querySelectorAll('.settings-section')) + .forEach(section => { + if (!section.available || + (section.collapsible && this.shouldShowMoreSettings_ && + !this.settingsExpanded_)) { + section.hide(); + return; + } + section.show(); + }); }, /** @private */
diff --git a/chrome/browser/resources/print_preview/new/compiled_resources2.gyp b/chrome/browser/resources/print_preview/new/compiled_resources2.gyp index 818f1d97..dd5aeaa9 100644 --- a/chrome/browser/resources/print_preview/new/compiled_resources2.gyp +++ b/chrome/browser/resources/print_preview/new/compiled_resources2.gyp
@@ -208,7 +208,6 @@ '../data/compiled_resources2.gyp:destination', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', - 'settings_section_behavior', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], },
diff --git a/chrome/browser/resources/print_preview/new/link_container.html b/chrome/browser/resources/print_preview/new/link_container.html index 48b03a85..5fca983 100644 --- a/chrome/browser/resources/print_preview/new/link_container.html +++ b/chrome/browser/resources/print_preview/new/link_container.html
@@ -6,7 +6,6 @@ <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="../data/destination.html"> <link rel="import" href="print_preview_shared_css.html"> -<link rel="import" href="settings_section_behavior.html"> <link rel="import" href="throbber_css.html"> <dom-module id="print-preview-link-container">
diff --git a/chrome/browser/resources/print_preview/new/link_container.js b/chrome/browser/resources/print_preview/new/link_container.js index 9dd09a6..235de40a 100644 --- a/chrome/browser/resources/print_preview/new/link_container.js +++ b/chrome/browser/resources/print_preview/new/link_container.js
@@ -5,8 +5,6 @@ Polymer({ is: 'print-preview-link-container', - behaviors: [print_preview_new.SettingsSectionBehavior], - properties: { appKioskMode: Boolean,
diff --git a/chrome/browser/resources/settings/a11y_page/tts_subpage.html b/chrome/browser/resources/settings/a11y_page/tts_subpage.html index 903655a..c76c59b 100644 --- a/chrome/browser/resources/settings/a11y_page/tts_subpage.html +++ b/chrome/browser/resources/settings/a11y_page/tts_subpage.html
@@ -91,11 +91,14 @@ <div id="extension_name_[[index]]" class="start"> [[extension.name]] </div> - <paper-button on-click="onManageTtsEngineSettingsClick_" - aria-describedby="extension_name_[[index]]" - hidden="[[!extension.options_page]]"> - $i18n{settings} - </paper-button> + <a href="[[extension.optionsPage]]" + tabindex=-1 + target="_blank" + hidden="[[!extension.optionsPage]]"> + <paper-button aria-describedby="extension_name_[[index]]"> + $i18n{settings} + </paper-button> + </a> </div> </template> <div class="settings-box block continuation">
diff --git a/chrome/browser/resources/settings/a11y_page/tts_subpage.js b/chrome/browser/resources/settings/a11y_page/tts_subpage.js index 437d10d..503e31f9 100644 --- a/chrome/browser/resources/settings/a11y_page/tts_subpage.js +++ b/chrome/browser/resources/settings/a11y_page/tts_subpage.js
@@ -110,14 +110,6 @@ }); }, - /** - * Function to navigate to the options page for an extension. - * @param {TtsHandlerExtension} engine - * @private */ - onManageTtsEngineSettingsClick_: function(engine) { - window.open(engine.optionsPage, '_blank'); - }, - /** @private */ onPreviewTtsClick_: function() { let utter = new window.SpeechSynthesisUtterance();
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html index e5d2cb8..e2718951 100644 --- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html +++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
@@ -1,9 +1,9 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="../icons.html"> <link rel="import" href="../prefs/prefs.html"> @@ -43,13 +43,12 @@ </paper-icon-button-light> </template> <div class="separator"></div> - <paper-toggle-button id="enableBluetooth" + <cr-toggle id="enableBluetooth" checked="{{bluetoothToggleState_}}" disabled$= "[[!isToggleEnabled_(adapterState_, stateChangeInProgress_)]]" - on-click="stopTap_" aria-label="$i18n{bluetoothToggleA11yLabel}"> - </paper-toggle-button> + </cr-toggle> </div> </neon-animatable>
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js index 73b88de..8b67451 100644 --- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js +++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
@@ -192,14 +192,6 @@ * @param {!Event} e * @private */ - stopTap_: function(e) { - e.stopPropagation(); - }, - - /** - * @param {!Event} e - * @private - */ onSubpageArrowTap_: function(e) { this.openSubpage_(); e.stopPropagation();
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html index 018a505..a8de158 100644 --- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html +++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
@@ -2,10 +2,10 @@ <link rel="import" href="chrome://resources/cr_components/chromeos/bluetooth_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/cr_scrollable_behavior.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="../icons.html"> <link rel="import" href="../settings_shared_css.html"> @@ -44,12 +44,11 @@ [[getOnOffString_(bluetoothToggleState, '$i18nPolymer{deviceOn}', '$i18nPolymer{deviceOff}')]] </div> - <paper-toggle-button id="enableBluetooth" + <cr-toggle id="enableBluetooth" checked="{{bluetoothToggleState}}" disabled$="[[!isToggleEnabled_(adapterState, stateChangeInProgress)]]" - aria-label="$i18n{bluetoothToggleA11yLabel}" - on-click="stopTap_"> - </paper-toggle-button> + aria-label="$i18n{bluetoothToggleA11yLabel}"> + </cr-toggle> </div> <!-- Paired device list -->
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js index 6890575..476a450 100644 --- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js +++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
@@ -370,14 +370,6 @@ * @param {!Event} event * @private */ - stopTap_: function(event) { - event.stopPropagation(); - }, - - /** - * @param {!Event} event - * @private - */ onEnableTap_: function(event) { if (this.isToggleEnabled_()) this.bluetoothToggleState = !this.bluetoothToggleState;
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.html b/chrome/browser/resources/settings/internet_page/internet_detail_page.html index 2ad6b0f..18c697e4 100644 --- a/chrome/browser/resources/settings/internet_page/internet_detail_page.html +++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
@@ -9,6 +9,7 @@ <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_icon.html"> <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html"> <link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html"> <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior.html"> @@ -18,7 +19,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="../controls/settings_toggle_button.html"> <link rel="import" href="../prefs/prefs.html"> <link rel="import" href="../route.html"> @@ -41,7 +41,7 @@ -webkit-margin-end: 10px; } - paper-toggle-button { + cr-toggle { -webkit-margin-start: var(--settings-control-label-spacing); } @@ -141,10 +141,10 @@ <cr-policy-network-indicator property="[[networkProperties.Priority]]"> </cr-policy-network-indicator> - <paper-toggle-button checked="{{preferNetwork_}}" + <cr-toggle checked="{{preferNetwork_}}" disabled="[[isNetworkPolicyEnforced(networkProperties.Priority)]]" aria-labelledby="preferNetworkToggleLabel"> - </paper-toggle-button> + </cr-toggle> </div> </template> <!-- Autoconnect. --> @@ -156,11 +156,11 @@ <cr-policy-network-indicator property="[[getManagedAutoConnect_(networkProperties)]]"> </cr-policy-network-indicator> - <paper-toggle-button checked="{{autoConnect_}}" + <cr-toggle checked="{{autoConnect_}}" disabled="[[!enableAutoConnect_(networkProperties, globalPolicy)]]" aria-labelledby="autoConnectToggleLabel"> - </paper-toggle-button> + </cr-toggle> </div> </template> <!-- Data roaming (Cellular only). -->
diff --git a/chrome/browser/resources/settings/internet_page/internet_subpage.html b/chrome/browser/resources/settings/internet_page/internet_subpage.html index 91b79a02..2889a2e 100644 --- a/chrome/browser/resources/settings/internet_page/internet_subpage.html +++ b/chrome/browser/resources/settings/internet_page/internet_subpage.html
@@ -1,11 +1,11 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_list.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="../settings_shared_css.html"> <dom-module id="settings-internet-subpage"> @@ -89,12 +89,12 @@ on-click="onAddButtonTap_" tabindex$="[[tabindex]]"> </button> </paper-icon-button-light> - <paper-toggle-button id="deviceEnabledButton" + <cr-toggle id="deviceEnabledButton" aria-label$="[[getToggleA11yString_(deviceState)]]" checked="[[deviceIsEnabled_(deviceState)]]" disabled="[[!enableToggleIsEnabled_(deviceState)]]" - on-click="onDeviceEnabledTap_"> - </paper-toggle-button> + on-change="onDeviceEnabledChange_"> + </cr-toggle> </div> </template> @@ -215,13 +215,13 @@ $i18n{internetToggleTetherSubtext} </div> </div> - <paper-toggle-button id="tetherEnabledButton" + <cr-toggle id="tetherEnabledButton" aria-label="$i18n{internetToggleTetherLabel}" aria-describedby="tetherSecondary" checked="[[deviceIsEnabled_(tetherDeviceState)]]" disabled="[[!tetherToggleIsEnabled_(deviceState, tetherDeviceState)]]"> - </paper-toggle-button> + </cr-toggle> </div> </template> </template>
diff --git a/chrome/browser/resources/settings/internet_page/internet_subpage.js b/chrome/browser/resources/settings/internet_page/internet_subpage.js index 919eed9..336b50c 100644 --- a/chrome/browser/resources/settings/internet_page/internet_subpage.js +++ b/chrome/browser/resources/settings/internet_page/internet_subpage.js
@@ -455,14 +455,12 @@ * @param {!Event} event * @private */ - onDeviceEnabledTap_: function(event) { + onDeviceEnabledChange_: function(event) { assert(this.deviceState); this.fire('device-enabled-toggled', { enabled: !this.deviceIsEnabled_(this.deviceState), type: this.deviceState.Type }); - // Make sure this does not propagate to onDetailsTap_. - event.stopPropagation(); }, /**
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.html b/chrome/browser/resources/settings/internet_page/network_summary_item.html index d45bd71..1d16847 100644 --- a/chrome/browser/resources/settings/internet_page/network_summary_item.html +++ b/chrome/browser/resources/settings/internet_page/network_summary_item.html
@@ -2,11 +2,11 @@ <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_siminfo.html"> <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_icon.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="../settings_page/settings_subpage.html"> <link rel="import" href="../settings_shared_css.html"> @@ -74,12 +74,12 @@ <template is="dom-if" if="[[enableToggleIsVisible_(deviceState)]]"> <div class="separator"></div> - <paper-toggle-button id="deviceEnabledButton" + <cr-toggle id="deviceEnabledButton" aria-label$="[[getToggleA11yString_(deviceState)]]" checked="[[deviceIsEnabled_(deviceState)]]" disabled="[[!enableToggleIsEnabled_(deviceState)]]" - on-click="onDeviceEnabledTap_"> - </paper-toggle-button> + on-change="onDeviceEnabledChange_"> + </cr-toggle> </template> </div> </template>
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.js b/chrome/browser/resources/settings/internet_page/network_summary_item.js index 7963ca5..ab3be60 100644 --- a/chrome/browser/resources/settings/internet_page/network_summary_item.js +++ b/chrome/browser/resources/settings/internet_page/network_summary_item.js
@@ -327,13 +327,11 @@ * @param {!Event} event * @private */ - onDeviceEnabledTap_: function(event) { + onDeviceEnabledChange_: function(event) { const deviceIsEnabled = this.deviceIsEnabled_(this.deviceState); const type = this.deviceState ? this.deviceState.Type : ''; this.fire( 'device-enabled-toggled', {enabled: !deviceIsEnabled, type: type}); - // Make sure this does not propagate to onDetailsTap_. - event.stopPropagation(); }, /**
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html index 1b64c43..baa02f9 100644 --- a/chrome/browser/resources/settings/settings_menu/settings_menu.html +++ b/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -61,6 +61,7 @@ } #advancedButton:focus { + box-shadow: none; outline: none; }
diff --git a/chrome/browser/resources/snippets_internals/snippets_internals.html b/chrome/browser/resources/snippets_internals/snippets_internals.html index 318d0512..43869fec 100644 --- a/chrome/browser/resources/snippets_internals/snippets_internals.html +++ b/chrome/browser/resources/snippets_internals/snippets_internals.html
@@ -26,9 +26,6 @@ <td class="name">Article Suggestions enabled <td id="flag-article-suggestions" class="value"> <tr> - <td class="name">Recent Tab Suggestions enabled - <td id="flag-recent-offline-tab-suggestions" class="value"> - <tr> <td class="name">Offlining Recent Tabs enabled <td id="flag-offlining-recent-pages-feature" class="value"> <tr>
diff --git a/chrome/browser/sessions/session_restore_observer_unittest.cc b/chrome/browser/sessions/session_restore_observer_unittest.cc index 6cf1097f..5d6e13e 100644 --- a/chrome/browser/sessions/session_restore_observer_unittest.cc +++ b/chrome/browser/sessions/session_restore_observer_unittest.cc
@@ -77,7 +77,7 @@ // testing::Test: void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); - SetContents(CreateRestoredWebContents().release()); + SetContents(CreateRestoredWebContents()); restored_tabs_.emplace_back(web_contents(), false, false, false); }
diff --git a/chrome/browser/sync/sessions/sync_sessions_web_contents_router_unittest.cc b/chrome/browser/sync/sessions/sync_sessions_web_contents_router_unittest.cc index ddad919..d133eb2a 100644 --- a/chrome/browser/sync/sessions/sync_sessions_web_contents_router_unittest.cc +++ b/chrome/browser/sync/sessions/sync_sessions_web_contents_router_unittest.cc
@@ -33,8 +33,8 @@ router_ = SyncSessionsWebContentsRouterFactory::GetInstance()->GetForProfile( &profile_); - test_contents_.reset( - content::WebContentsTester::CreateTestWebContents(&profile_, nullptr)); + test_contents_ = + content::WebContentsTester::CreateTestWebContents(&profile_, nullptr); } SyncSessionsWebContentsRouter* router() { return router_; }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index e0ec670..38caa0b 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1486,8 +1486,6 @@ "tabs/tab_strip_model_stats_recorder.h", "tabs/tab_utils.cc", "tabs/tab_utils.h", - "tabs/web_contents_closer.cc", - "tabs/web_contents_closer.h", "tabs/window_activity_watcher.cc", "tabs/window_activity_watcher.h", "tabs/window_features.cc",
diff --git a/chrome/browser/ui/ash/chrome_keyboard_ui_unittest.cc b/chrome/browser/ui/ash/chrome_keyboard_ui_unittest.cc index ab13bf8f..5ca1e30 100644 --- a/chrome/browser/ui/ash/chrome_keyboard_ui_unittest.cc +++ b/chrome/browser/ui/ash/chrome_keyboard_ui_unittest.cc
@@ -41,8 +41,7 @@ // A test for crbug.com/734534 TEST_F(ChromeKeyboardUITest, DoesNotCrashWhenParentDoesNotExist) { - std::unique_ptr<content::WebContents> contents = - base::WrapUnique(CreateTestWebContents()); + std::unique_ptr<content::WebContents> contents = CreateTestWebContents(); TestChromeKeyboardUI keyboard_ui(std::move(contents)); EXPECT_FALSE(keyboard_ui.HasContentsWindow());
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc index 3ad42cd..6d760f9 100644 --- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
@@ -131,8 +131,8 @@ GetMenuModelCallback callback) { ChromeLauncherController* controller = ChromeLauncherController::instance(); const ash::ShelfItem* item = controller->GetItem(shelf_id()); - std::move(callback).Run( - LauncherContextMenu::Create(controller, item, display_id)); + context_menu_ = LauncherContextMenu::Create(controller, item, display_id); + context_menu_->GetMenuModel(std::move(callback)); } void AppShortcutLauncherItemController::ExecuteCommand(bool from_context_menu,
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h index f9c5f83..a4bc33bf 100644 --- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h +++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_UI_ASH_LAUNCHER_APP_SHORTCUT_LAUNCHER_ITEM_CONTROLLER_H_ #define CHROME_BROWSER_UI_ASH_LAUNCHER_APP_SHORTCUT_LAUNCHER_ITEM_CONTROLLER_H_ +#include <memory> #include <string> #include <vector> @@ -24,6 +25,8 @@ class Extension; } +class LauncherContextMenu; + // Item controller for an app shortcut. // If the associated app is a platform or ARC app, launching the app replaces // this instance with an AppWindowLauncherItemController to handle the app's @@ -101,6 +104,8 @@ // The cached list of open app web contents shown in an application menu. std::vector<content::WebContents*> app_menu_items_; + std::unique_ptr<LauncherContextMenu> context_menu_; + DISALLOW_COPY_AND_ASSIGN(AppShortcutLauncherItemController); };
diff --git a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc index 0da56398..fc62492 100644 --- a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc
@@ -106,8 +106,8 @@ GetMenuModelCallback callback) { ChromeLauncherController* controller = ChromeLauncherController::instance(); const ash::ShelfItem* item = controller->GetItem(shelf_id()); - std::move(callback).Run( - LauncherContextMenu::Create(controller, item, display_id)); + context_menu_ = LauncherContextMenu::Create(controller, item, display_id); + context_menu_->GetMenuModel(std::move(callback)); } void AppWindowLauncherItemController::Close() {
diff --git a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h index 7b40962..a50c0c17 100644 --- a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h +++ b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_ASH_LAUNCHER_APP_WINDOW_LAUNCHER_ITEM_CONTROLLER_H_ #include <list> +#include <memory> #include <string> #include "ash/public/cpp/shelf_item_delegate.h" @@ -21,6 +22,8 @@ class BaseWindow; } +class LauncherContextMenu; + // This is a ShelfItemDelegate for abstract app windows (extension or ARC). // There is one instance per app, per launcher id. For apps with multiple // windows, each item controller keeps track of all windows associated with the @@ -101,6 +104,8 @@ // Scoped list of observed windows (for removal on destruction) ScopedObserver<aura::Window, aura::WindowObserver> observed_windows_; + std::unique_ptr<LauncherContextMenu> context_menu_; + DISALLOW_COPY_AND_ASSIGN(AppWindowLauncherItemController); };
diff --git a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc index 39557ca6..3663855 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h" -#include <memory> #include <utility> #include "base/strings/utf_string_conversions.h" @@ -59,8 +58,8 @@ GetMenuModelCallback callback) { ChromeLauncherController* controller = ChromeLauncherController::instance(); const ash::ShelfItem* item = controller->GetItem(shelf_id()); - std::move(callback).Run( - LauncherContextMenu::Create(controller, item, display_id)); + context_menu_ = LauncherContextMenu::Create(controller, item, display_id); + context_menu_->GetMenuModel(std::move(callback)); } void ArcAppDeferredLauncherItemController::Close() {
diff --git a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h index fcd5cf1..d8b8d604 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h +++ b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include <memory> #include <string> #include "ash/public/cpp/shelf_item_delegate.h" @@ -15,6 +16,7 @@ #include "base/time/time.h" class ArcAppDeferredLauncherController; +class LauncherContextMenu; // ArcAppDeferredLauncherItemController displays the icon of the ARC app that // cannot be launched immediately (due to ARC not being ready) on Chrome OS' @@ -57,6 +59,8 @@ base::WeakPtr<ArcAppDeferredLauncherController> host_; const base::Time start_time_; + std::unique_ptr<LauncherContextMenu> context_menu_; + DISALLOW_COPY_AND_ASSIGN(ArcAppDeferredLauncherItemController); };
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 b846b08..b0675324 100644 --- a/chrome/browser/ui/ash/launcher/arc_launcher_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/arc_launcher_context_menu.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/ui/ash/launcher/arc_launcher_context_menu.h" +#include <memory> +#include <utility> + #include "ash/public/cpp/shelf_item.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" @@ -17,13 +20,17 @@ ChromeLauncherController* controller, const ash::ShelfItem* item, int64_t display_id) - : LauncherContextMenu(controller, item, display_id) { - Init(); + : LauncherContextMenu(controller, item, display_id) {} + +ArcLauncherContextMenu::~ArcLauncherContextMenu() = default; + +void ArcLauncherContextMenu::GetMenuModel(GetMenuModelCallback callback) { + auto menu_model = std::make_unique<ui::SimpleMenuModel>(this); + BuildMenu(menu_model.get()); + std::move(callback).Run(std::move(menu_model)); } -ArcLauncherContextMenu::~ArcLauncherContextMenu() {} - -void ArcLauncherContextMenu::Init() { +void ArcLauncherContextMenu::BuildMenu(ui::SimpleMenuModel* menu_model) { const ArcAppListPrefs* arc_list_prefs = ArcAppListPrefs::Get(controller()->profile()); DCHECK(arc_list_prefs); @@ -40,16 +47,19 @@ const bool app_is_open = controller()->IsOpen(item().id); if (!app_is_open) { DCHECK(app_info->launchable); - AddContextMenuOption(MENU_OPEN_NEW, IDS_APP_CONTEXT_MENU_ACTIVATE_ARC); + AddContextMenuOption(menu_model, MENU_OPEN_NEW, + IDS_APP_CONTEXT_MENU_ACTIVATE_ARC); if (!features::IsTouchableAppContextMenuEnabled()) - AddSeparator(ui::NORMAL_SEPARATOR); + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); } if (!app_id.has_shelf_group_id() && app_info->launchable) - AddPinMenu(); + AddPinMenu(menu_model); - if (app_is_open) - AddContextMenuOption(MENU_CLOSE, IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + if (app_is_open) { + AddContextMenuOption(menu_model, MENU_CLOSE, + IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + } if (!features::IsTouchableAppContextMenuEnabled()) - AddSeparator(ui::NORMAL_SEPARATOR); + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); }
diff --git a/chrome/browser/ui/ash/launcher/arc_launcher_context_menu.h b/chrome/browser/ui/ash/launcher/arc_launcher_context_menu.h index 58ea7490..5c7aaee 100644 --- a/chrome/browser/ui/ash/launcher/arc_launcher_context_menu.h +++ b/chrome/browser/ui/ash/launcher/arc_launcher_context_menu.h
@@ -16,8 +16,11 @@ int64_t display_id); ~ArcLauncherContextMenu() override; + // LauncherContextMenu: + void GetMenuModel(GetMenuModelCallback callback) override; + private: - void Init(); + void BuildMenu(ui::SimpleMenuModel* menu_model); DISALLOW_COPY_AND_ASSIGN(ArcLauncherContextMenu); };
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc index 80481d6f..15cd340 100644 --- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
@@ -248,8 +248,8 @@ GetMenuModelCallback callback) { ChromeLauncherController* controller = ChromeLauncherController::instance(); const ash::ShelfItem* item = controller->GetItem(shelf_id()); - std::move(callback).Run( - LauncherContextMenu::Create(controller, item, display_id)); + context_menu_ = LauncherContextMenu::Create(controller, item, display_id); + context_menu_->GetMenuModel(std::move(callback)); } void BrowserShortcutLauncherItemController::ExecuteCommand(
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h index b93253d..c811c66 100644 --- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h +++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_UI_ASH_LAUNCHER_BROWSER_SHORTCUT_LAUNCHER_ITEM_CONTROLLER_H_ #define CHROME_BROWSER_UI_ASH_LAUNCHER_BROWSER_SHORTCUT_LAUNCHER_ITEM_CONTROLLER_H_ +#include <memory> + #include "ash/public/cpp/shelf_item_delegate.h" #include "base/macros.h" #include "base/scoped_observer.h" @@ -19,6 +21,8 @@ class WebContents; } +class LauncherContextMenu; + // Shelf item delegate for a browser shortcut; only one such item should exist. // This item shows an application menu that lists open browser windows or tabs. class BrowserShortcutLauncherItemController : public ash::ShelfItemDelegate, @@ -76,6 +80,8 @@ // Observer for browser windows closing events. ScopedObserver<BrowserList, BrowserListObserver> browser_list_observer_; + std::unique_ptr<LauncherContextMenu> context_menu_; + DISALLOW_COPY_AND_ASSIGN(BrowserShortcutLauncherItemController); };
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc index 559eba3b..6a4ef1f 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -22,6 +22,7 @@ #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/bind_test_util.h" #include "chrome/browser/apps/app_browsertest_util.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/extension_apitest.h" @@ -340,8 +341,20 @@ return LauncherContextMenu::Create(controller_, &item, display_id); } - bool IsItemPresentInMenu(LauncherContextMenu* menu, int command_id) { - return menu->GetIndexOfCommandId(command_id) != -1; + bool IsItemPresentInMenu(LauncherContextMenu* launcher_context_menu, + int command_id) { + base::RunLoop run_loop; + std::unique_ptr<ui::MenuModel> menu; + launcher_context_menu->GetMenuModel(base::BindLambdaForTesting( + [&](std::unique_ptr<ui::MenuModel> created_menu) { + menu = std::move(created_menu); + run_loop.Quit(); + })); + run_loop.Run(); + ui::MenuModel* menu_ptr = menu.get(); + int index = 0; + return ui::MenuModel::GetModelAndIndexForCommandId(command_id, &menu_ptr, + &index); } ChromeLauncherController* controller_ = nullptr;
diff --git a/chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.cc b/chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.cc index 77afe7b..5bc1cb1d 100644 --- a/chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.h" +#include <memory> +#include <utility> + #include "ash/public/cpp/shelf_item.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" @@ -15,26 +18,33 @@ ChromeLauncherController* controller, const ash::ShelfItem* item, int64_t display_id) - : LauncherContextMenu(controller, item, display_id) { - Init(); + : LauncherContextMenu(controller, item, display_id) {} + +CrostiniShelfContextMenu::~CrostiniShelfContextMenu() = default; + +void CrostiniShelfContextMenu::GetMenuModel(GetMenuModelCallback callback) { + auto menu_model = std::make_unique<ui::SimpleMenuModel>(this); + BuildMenu(menu_model.get()); + std::move(callback).Run(std::move(menu_model)); } -CrostiniShelfContextMenu::~CrostiniShelfContextMenu() {} - -void CrostiniShelfContextMenu::Init() { +void CrostiniShelfContextMenu::BuildMenu(ui::SimpleMenuModel* menu_model) { const crostini::CrostiniRegistryService* registry_service = crostini::CrostiniRegistryServiceFactory::GetForProfile( controller()->profile()); std::unique_ptr<crostini::CrostiniRegistryService::Registration> registration = registry_service->GetRegistration(item().id.app_id); if (registration) - AddPinMenu(); + AddPinMenu(menu_model); - if (controller()->IsOpen(item().id)) - AddItemWithStringId(MENU_CLOSE, IDS_LAUNCHER_CONTEXT_MENU_CLOSE); - else - AddItemWithStringId(MENU_OPEN_NEW, IDS_APP_CONTEXT_MENU_ACTIVATE_ARC); + if (controller()->IsOpen(item().id)) { + menu_model->AddItemWithStringId(MENU_CLOSE, + IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + } else { + menu_model->AddItemWithStringId(MENU_OPEN_NEW, + IDS_APP_CONTEXT_MENU_ACTIVATE_ARC); + } if (!features::IsTouchableAppContextMenuEnabled()) - AddSeparator(ui::NORMAL_SEPARATOR); + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); }
diff --git a/chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.h b/chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.h index 0ca6fc2..6d6928c 100644 --- a/chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.h +++ b/chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.h
@@ -16,8 +16,11 @@ int64_t display_id); ~CrostiniShelfContextMenu() override; + // LauncherContextMenu: + void GetMenuModel(GetMenuModelCallback callback) override; + private: - void Init(); + void BuildMenu(ui::SimpleMenuModel* menu_model); DISALLOW_COPY_AND_ASSIGN(CrostiniShelfContextMenu); };
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 d59b17b..356eb5c7 100644 --- a/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/ash/launcher/extension_launcher_context_menu.h" +#include <utility> + #include "ash/scoped_root_window_for_new_windows.h" // mash-ok #include "ash/shell.h" // mash-ok #include "base/bind.h" @@ -36,15 +38,19 @@ ChromeLauncherController* controller, const ash::ShelfItem* item, int64_t display_id) - : LauncherContextMenu(controller, item, display_id) { - Init(); + : LauncherContextMenu(controller, item, display_id) {} + +ExtensionLauncherContextMenu::~ExtensionLauncherContextMenu() = default; + +void ExtensionLauncherContextMenu::GetMenuModel(GetMenuModelCallback callback) { + auto menu_model = std::make_unique<ui::SimpleMenuModel>(this); + BuildMenu(menu_model.get()); + std::move(callback).Run(std::move(menu_model)); } -ExtensionLauncherContextMenu::~ExtensionLauncherContextMenu() {} - -void ExtensionLauncherContextMenu::Init() { +void ExtensionLauncherContextMenu::BuildMenu(ui::SimpleMenuModel* menu_model) { extension_items_.reset(new extensions::ContextMenuMatcher( - controller()->profile(), this, this, + controller()->profile(), this, menu_model, base::Bind(MenuItemHasLauncherContext))); if (item().type == ash::TYPE_PINNED_APP || item().type == ash::TYPE_APP) { // V1 apps can be started from the menu - but V2 apps should not. @@ -53,56 +59,61 @@ GetLaunchType() == extensions::LAUNCH_TYPE_REGULAR) ? IDS_APP_LIST_CONTEXT_MENU_NEW_TAB : IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW; - AddContextMenuOption(MENU_OPEN_NEW, string_id); + AddContextMenuOption(menu_model, MENU_OPEN_NEW, string_id); if (!features::IsTouchableAppContextMenuEnabled()) - AddSeparator(ui::NORMAL_SEPARATOR); + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); } - AddPinMenu(); + AddPinMenu(menu_model); - if (controller()->IsOpen(item().id)) - AddContextMenuOption(MENU_CLOSE, IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + if (controller()->IsOpen(item().id)) { + AddContextMenuOption(menu_model, MENU_CLOSE, + IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + } if (!controller()->IsPlatformApp(item().id) && item().type == ash::TYPE_PINNED_APP) { if (!features::IsTouchableAppContextMenuEnabled()) - AddSeparator(ui::NORMAL_SEPARATOR); + menu_model->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 // option to launch the hosted app as a tab. - AddContextMenuOption(LAUNCH_TYPE_WINDOW, + AddContextMenuOption(menu_model, LAUNCH_TYPE_WINDOW, IDS_APP_CONTEXT_MENU_OPEN_WINDOW); } else { - AddContextMenuOption(LAUNCH_TYPE_REGULAR_TAB, + AddContextMenuOption(menu_model, LAUNCH_TYPE_REGULAR_TAB, IDS_APP_CONTEXT_MENU_OPEN_REGULAR); - AddContextMenuOption(LAUNCH_TYPE_PINNED_TAB, + AddContextMenuOption(menu_model, LAUNCH_TYPE_PINNED_TAB, IDS_APP_CONTEXT_MENU_OPEN_PINNED); - AddContextMenuOption(LAUNCH_TYPE_WINDOW, + AddContextMenuOption(menu_model, LAUNCH_TYPE_WINDOW, IDS_APP_CONTEXT_MENU_OPEN_WINDOW); // Even though the launch type is Full Screen it is more accurately // described as Maximized in Ash. - AddContextMenuOption(LAUNCH_TYPE_FULLSCREEN, + AddContextMenuOption(menu_model, LAUNCH_TYPE_FULLSCREEN, IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED); } } } else if (item().type == ash::TYPE_BROWSER_SHORTCUT) { - AddContextMenuOption(MENU_NEW_WINDOW, IDS_APP_LIST_NEW_WINDOW); + AddContextMenuOption(menu_model, MENU_NEW_WINDOW, IDS_APP_LIST_NEW_WINDOW); if (!controller()->profile()->IsGuestSession()) { - AddContextMenuOption(MENU_NEW_INCOGNITO_WINDOW, + AddContextMenuOption(menu_model, MENU_NEW_INCOGNITO_WINDOW, IDS_APP_LIST_NEW_INCOGNITO_WINDOW); } if (!BrowserShortcutLauncherItemController(controller()->shelf_model()) .IsListOfActiveBrowserEmpty()) { - AddContextMenuOption(MENU_CLOSE, IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + AddContextMenuOption(menu_model, MENU_CLOSE, + IDS_LAUNCHER_CONTEXT_MENU_CLOSE); } } else if (item().type == ash::TYPE_DIALOG) { - AddContextMenuOption(MENU_CLOSE, IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + AddContextMenuOption(menu_model, MENU_CLOSE, + IDS_LAUNCHER_CONTEXT_MENU_CLOSE); } else if (controller()->IsOpen(item().id)) { - AddContextMenuOption(MENU_CLOSE, IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + AddContextMenuOption(menu_model, MENU_CLOSE, + IDS_LAUNCHER_CONTEXT_MENU_CLOSE); } if (!features::IsTouchableAppContextMenuEnabled()) - AddSeparator(ui::NORMAL_SEPARATOR); + menu_model->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()) { @@ -110,7 +121,7 @@ extension_items_->AppendExtensionItems(app_key, base::string16(), &index, false); // is_action_menu if (!features::IsTouchableAppContextMenuEnabled()) - AddSeparator(ui::NORMAL_SEPARATOR); + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); } } }
diff --git a/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.h b/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.h index c6125878f..e726c2c9 100644 --- a/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.h +++ b/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.h
@@ -23,13 +23,16 @@ int64_t display_id); ~ExtensionLauncherContextMenu() override; + // LauncherContextMenu overrides: + void GetMenuModel(GetMenuModelCallback callback) override; + // ui::SimpleMenuModel::Delegate overrides: bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; void ExecuteCommand(int command_id, int event_flags) override; private: - void Init(); + void BuildMenu(ui::SimpleMenuModel* menu_model); // Helpers to get and set the launch type for the extension item. extensions::LaunchType GetLaunchType() const;
diff --git a/chrome/browser/ui/ash/launcher/internal_app_shelf_context_menu.cc b/chrome/browser/ui/ash/launcher/internal_app_shelf_context_menu.cc index ebd60d8..a687c13c 100644 --- a/chrome/browser/ui/ash/launcher/internal_app_shelf_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/internal_app_shelf_context_menu.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/ui/ash/launcher/internal_app_shelf_context_menu.h" +#include <memory> +#include <utility> + #include "ash/public/cpp/shelf_item.h" #include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" @@ -14,27 +17,34 @@ ChromeLauncherController* controller, const ash::ShelfItem* item, int64_t display_id) - : LauncherContextMenu(controller, item, display_id) { - Init(); + : LauncherContextMenu(controller, item, display_id) {} + +void InternalAppShelfContextMenu::GetMenuModel(GetMenuModelCallback callback) { + auto menu_model = std::make_unique<ui::SimpleMenuModel>(this); + BuildMenu(menu_model.get()); + std::move(callback).Run(std::move(menu_model)); } -void InternalAppShelfContextMenu::Init() { +void InternalAppShelfContextMenu::BuildMenu(ui::SimpleMenuModel* menu_model) { const bool app_is_open = controller()->IsOpen(item().id); if (!app_is_open) { - AddContextMenuOption(MENU_OPEN_NEW, IDS_APP_CONTEXT_MENU_ACTIVATE_ARC); + AddContextMenuOption(menu_model, MENU_OPEN_NEW, + IDS_APP_CONTEXT_MENU_ACTIVATE_ARC); if (!features::IsTouchableAppContextMenuEnabled()) - AddSeparator(ui::NORMAL_SEPARATOR); + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); } const auto* internal_app = app_list::FindInternalApp(item().id.app_id); DCHECK(internal_app); if (internal_app->show_in_launcher) - AddPinMenu(); + AddPinMenu(menu_model); - if (app_is_open) - AddContextMenuOption(MENU_CLOSE, IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + if (app_is_open) { + AddContextMenuOption(menu_model, MENU_CLOSE, + IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + } // Default menu items, e.g. "Autohide shelf" are appended. Adding a separator. if (!features::IsTouchableAppContextMenuEnabled()) - AddSeparator(ui::NORMAL_SEPARATOR); + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); }
diff --git a/chrome/browser/ui/ash/launcher/internal_app_shelf_context_menu.h b/chrome/browser/ui/ash/launcher/internal_app_shelf_context_menu.h index dbc7db2..4d6402a6 100644 --- a/chrome/browser/ui/ash/launcher/internal_app_shelf_context_menu.h +++ b/chrome/browser/ui/ash/launcher/internal_app_shelf_context_menu.h
@@ -14,11 +14,13 @@ InternalAppShelfContextMenu(ChromeLauncherController* controller, const ash::ShelfItem* item, int64_t display_id); - ~InternalAppShelfContextMenu() override = default; + // LauncherContextMenu: + void GetMenuModel(GetMenuModelCallback callback) override; + private: - void Init(); + void BuildMenu(ui::SimpleMenuModel* menu_model); DISALLOW_COPY_AND_ASSIGN(InternalAppShelfContextMenu); };
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc index 1b3f351..7950321 100644 --- a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
@@ -65,14 +65,13 @@ LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller, const ash::ShelfItem* item, int64_t display_id) - : ui::SimpleMenuModel(this), - controller_(controller), + : controller_(controller), item_(item ? *item : ash::ShelfItem()), display_id_(display_id) { DCHECK_NE(display_id, display::kInvalidDisplayId); } -LauncherContextMenu::~LauncherContextMenu() {} +LauncherContextMenu::~LauncherContextMenu() = default; bool LauncherContextMenu::IsCommandIdChecked(int command_id) const { DCHECK(command_id < MENU_ITEM_COUNT); @@ -125,7 +124,7 @@ } } -void LauncherContextMenu::AddPinMenu() { +void LauncherContextMenu::AddPinMenu(ui::SimpleMenuModel* menu_model) { // Expect a valid ShelfID to add pin/unpin menu item. DCHECK(!item_.id.IsNull()); int menu_pin_string_id; @@ -144,7 +143,7 @@ NOTREACHED(); return; } - AddContextMenuOption(MENU_PIN, menu_pin_string_id); + AddContextMenuOption(menu_model, MENU_PIN, menu_pin_string_id); } bool LauncherContextMenu::ExecuteCommonCommand(int command_id, @@ -160,11 +159,13 @@ } } -void LauncherContextMenu::AddContextMenuOption(MenuItem type, int string_id) { +void LauncherContextMenu::AddContextMenuOption(ui::SimpleMenuModel* menu_model, + MenuItem type, + int string_id) { const gfx::VectorIcon& icon = GetMenuItemVectorIcon(type, string_id); if (features::IsTouchableAppContextMenuEnabled() && !icon.is_empty()) { const views::MenuConfig& menu_config = views::MenuConfig::instance(); - AddItemWithStringIdAndIcon( + menu_model->AddItemWithStringIdAndIcon( type, string_id, gfx::CreateVectorIcon(icon, menu_config.touchable_icon_size, menu_config.touchable_icon_color)); @@ -173,10 +174,10 @@ // If the MenuType is a Check item. if (type == LAUNCH_TYPE_REGULAR_TAB || type == LAUNCH_TYPE_PINNED_TAB || type == LAUNCH_TYPE_WINDOW || type == LAUNCH_TYPE_FULLSCREEN) { - AddCheckItemWithStringId(type, string_id); + menu_model->AddCheckItemWithStringId(type, string_id); return; } - AddItemWithStringId(type, string_id); + menu_model->AddItemWithStringId(type, string_id); } const gfx::VectorIcon& LauncherContextMenu::GetMenuItemVectorIcon(
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.h b/chrome/browser/ui/ash/launcher/launcher_context_menu.h index 79c8dbbb..9ba683f 100644 --- a/chrome/browser/ui/ash/launcher/launcher_context_menu.h +++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.h
@@ -13,8 +13,7 @@ class ChromeLauncherController; // A base class for browser, extension, and ARC shelf item context menus. -class LauncherContextMenu : public ui::SimpleMenuModel, - public ui::SimpleMenuModel::Delegate { +class LauncherContextMenu : public ui::SimpleMenuModel::Delegate { public: // Menu item command ids, used by subclasses and tests. // These are used in histograms, do not remove/renumber entries. Only add at @@ -43,6 +42,10 @@ const ash::ShelfItem* item, int64_t display_id); + using GetMenuModelCallback = + base::OnceCallback<void(std::unique_ptr<ui::MenuModel>)>; + virtual void GetMenuModel(GetMenuModelCallback callback) = 0; + // ui::SimpleMenuModel::Delegate overrides: bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; @@ -57,13 +60,15 @@ const ash::ShelfItem& item() const { return item_; } // Add menu item for pin/unpin. - void AddPinMenu(); + void AddPinMenu(ui::SimpleMenuModel* menu_model); // Helper method to execute common commands. Returns true if handled. bool ExecuteCommonCommand(int command_id, int event_flags); // Helper method to add touchable or normal context menu options. - void AddContextMenuOption(MenuItem type, int string_id); + void AddContextMenuOption(ui::SimpleMenuModel* menu_model, + MenuItem type, + int string_id); // Helper method to get the gfx::VectorIcon for a |type|. Returns an empty // gfx::VectorIcon if there is no icon for this |type|.
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc index 2fe061b..3baca9532 100644 --- a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc +++ b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/ash/launcher/launcher_context_menu.h" #include <memory> +#include <utility> #include "ash/public/cpp/shelf_item.h" #include "ash/public/cpp/shelf_model.h" @@ -61,8 +62,8 @@ class LauncherContextMenuTest : public ash::AshTestBase { protected: - - LauncherContextMenuTest() {} + LauncherContextMenuTest() = default; + ~LauncherContextMenuTest() override = default; void SetUp() override { arc_test_.SetUp(&profile_); @@ -98,6 +99,19 @@ return widget; } + std::unique_ptr<ui::MenuModel> GetMenuModel( + LauncherContextMenu* launcher_context_menu) { + base::RunLoop run_loop; + std::unique_ptr<ui::MenuModel> menu; + launcher_context_menu->GetMenuModel(base::BindLambdaForTesting( + [&](std::unique_ptr<ui::MenuModel> created_menu) { + menu = std::move(created_menu); + run_loop.Quit(); + })); + run_loop.Run(); + return menu; + } + std::unique_ptr<ui::MenuModel> GetContextMenu( ash::ShelfItemDelegate* item_delegate, int64_t display_id) { @@ -145,22 +159,26 @@ NewIncognitoWindowMenuIsDisabledWhenIncognitoModeOff) { const int64_t display_id = GetPrimaryDisplay().id(); // Initially, "New Incognito window" should be enabled. - std::unique_ptr<LauncherContextMenu> menu = + std::unique_ptr<LauncherContextMenu> launcher_context_menu = CreateLauncherContextMenu(ash::TYPE_BROWSER_SHORTCUT, display_id); + std::unique_ptr<ui::MenuModel> menu = + GetMenuModel(launcher_context_menu.get()); ASSERT_TRUE(IsItemPresentInMenu( menu.get(), LauncherContextMenu::MENU_NEW_INCOGNITO_WINDOW)); - EXPECT_TRUE( - menu->IsCommandIdEnabled(LauncherContextMenu::MENU_NEW_INCOGNITO_WINDOW)); + EXPECT_TRUE(launcher_context_menu->IsCommandIdEnabled( + LauncherContextMenu::MENU_NEW_INCOGNITO_WINDOW)); // Disable Incognito mode. IncognitoModePrefs::SetAvailability(profile()->GetPrefs(), IncognitoModePrefs::DISABLED); - menu = CreateLauncherContextMenu(ash::TYPE_BROWSER_SHORTCUT, display_id); + launcher_context_menu = + CreateLauncherContextMenu(ash::TYPE_BROWSER_SHORTCUT, display_id); + menu = GetMenuModel(launcher_context_menu.get()); // The item should be disabled. ASSERT_TRUE(IsItemPresentInMenu( menu.get(), LauncherContextMenu::MENU_NEW_INCOGNITO_WINDOW)); - EXPECT_FALSE( - menu->IsCommandIdEnabled(LauncherContextMenu::MENU_NEW_INCOGNITO_WINDOW)); + EXPECT_FALSE(launcher_context_menu->IsCommandIdEnabled( + LauncherContextMenu::MENU_NEW_INCOGNITO_WINDOW)); } // Verifies that "New window" menu item in the launcher context @@ -169,19 +187,25 @@ NewWindowMenuIsDisabledWhenIncognitoModeForced) { const int64_t display_id = GetPrimaryDisplay().id(); // Initially, "New window" should be enabled. - std::unique_ptr<LauncherContextMenu> menu = + std::unique_ptr<LauncherContextMenu> launcher_context_menu = CreateLauncherContextMenu(ash::TYPE_BROWSER_SHORTCUT, display_id); + std::unique_ptr<ui::MenuModel> menu = + GetMenuModel(launcher_context_menu.get()); ASSERT_TRUE( IsItemPresentInMenu(menu.get(), LauncherContextMenu::MENU_NEW_WINDOW)); - EXPECT_TRUE(menu->IsCommandIdEnabled(LauncherContextMenu::MENU_NEW_WINDOW)); + EXPECT_TRUE(launcher_context_menu->IsCommandIdEnabled( + LauncherContextMenu::MENU_NEW_WINDOW)); // Disable Incognito mode. IncognitoModePrefs::SetAvailability(profile()->GetPrefs(), IncognitoModePrefs::FORCED); - menu = CreateLauncherContextMenu(ash::TYPE_BROWSER_SHORTCUT, display_id); + launcher_context_menu = + CreateLauncherContextMenu(ash::TYPE_BROWSER_SHORTCUT, display_id); + menu = GetMenuModel(launcher_context_menu.get()); ASSERT_TRUE( IsItemPresentInMenu(menu.get(), LauncherContextMenu::MENU_NEW_WINDOW)); - EXPECT_FALSE(menu->IsCommandIdEnabled(LauncherContextMenu::MENU_NEW_WINDOW)); + EXPECT_FALSE(launcher_context_menu->IsCommandIdEnabled( + LauncherContextMenu::MENU_NEW_WINDOW)); } // Verifies that "Close" is not shown in context menu if no browser window is @@ -189,8 +213,10 @@ TEST_F(LauncherContextMenuTest, DesktopShellLauncherContextMenuVerifyCloseItem) { const int64_t display_id = GetPrimaryDisplay().id(); - std::unique_ptr<LauncherContextMenu> menu = + std::unique_ptr<LauncherContextMenu> launcher_context_menu = CreateLauncherContextMenu(ash::TYPE_BROWSER_SHORTCUT, display_id); + std::unique_ptr<ui::MenuModel> menu = + GetMenuModel(launcher_context_menu.get()); ASSERT_FALSE( IsItemPresentInMenu(menu.get(), LauncherContextMenu::MENU_CLOSE)); } @@ -402,13 +428,17 @@ std::vector<arc::mojom::AppInfo>(arc_test().fake_apps().begin(), arc_test().fake_apps().begin() + 1)); const std::string app_id = ArcAppTest::GetAppId(arc_test().fake_apps()[0]); + const ash::ShelfID shelf_id(app_id); controller()->PinAppWithID(app_id); - const ash::ShelfItem* item = controller()->GetItem(ash::ShelfID(app_id)); + const ash::ShelfItem* item = controller()->GetItem(shelf_id); ASSERT_TRUE(item); + ash::ShelfItemDelegate* item_delegate = + model()->GetShelfItemDelegate(shelf_id); + ASSERT_TRUE(item_delegate); int64_t primary_id = GetPrimaryDisplay().id(); - std::unique_ptr<LauncherContextMenu> menu = - std::make_unique<ArcLauncherContextMenu>(controller(), item, primary_id); + std::unique_ptr<ui::MenuModel> menu = + GetContextMenu(item_delegate, primary_id); // Test that there are 4 items in an ARC app context menu. EXPECT_EQ(4, menu->GetItemCount()); @@ -456,10 +486,12 @@ const ash::ShelfItem* item = controller()->GetItem(ash::ShelfID(app_id)); ASSERT_TRUE(item); + ash::ShelfItemDelegate* item_delegate = + model()->GetShelfItemDelegate(shelf_id); + ASSERT_TRUE(item_delegate); int64_t primary_id = GetPrimaryDisplay().id(); - std::unique_ptr<LauncherContextMenu> menu = - std::make_unique<InternalAppShelfContextMenu>(controller(), item, - primary_id); + std::unique_ptr<ui::MenuModel> menu = + GetContextMenu(item_delegate, primary_id); const int expected_options_num = internal_app.show_in_launcher ? 4 : 2; EXPECT_EQ(expected_options_num, menu->GetItemCount());
diff --git a/chrome/browser/ui/browser_list.cc b/chrome/browser/ui/browser_list.cc index 53044f1..b171e8d 100644 --- a/chrome/browser/ui/browser_list.cc +++ b/chrome/browser/ui/browser_list.cc
@@ -36,15 +36,6 @@ return browsers_to_close; } -BrowserList::BrowserVector GetIncognitoBrowsersToClose(Profile* profile) { - BrowserList::BrowserVector browsers_to_close; - for (auto* browser : *BrowserList::GetInstance()) { - if (browser->profile() == profile) - browsers_to_close.push_back(browser); - } - return browsers_to_close; -} - } // namespace // static @@ -163,18 +154,6 @@ } // static -void BrowserList::CloseAllBrowsersWithIncognitoProfile( - Profile* profile, - const CloseCallback& on_close_success, - const CloseCallback& on_close_aborted, - bool skip_beforeunload) { - DCHECK(profile->IsOffTheRecord()); - TryToCloseBrowserList(GetIncognitoBrowsersToClose(profile), on_close_success, - on_close_aborted, profile->GetPath(), - skip_beforeunload); -} - -// static void BrowserList::TryToCloseBrowserList(const BrowserVector& browsers_to_close, const CloseCallback& on_close_success, const CloseCallback& on_close_aborted,
diff --git a/chrome/browser/ui/browser_list.h b/chrome/browser/ui/browser_list.h index 31248f31..80d883f 100644 --- a/chrome/browser/ui/browser_list.h +++ b/chrome/browser/ui/browser_list.h
@@ -108,14 +108,6 @@ const CloseCallback& on_close_aborted, bool skip_beforeunload); - // Similarly to CloseAllBrowsersWithProfile, but DCHECK's that profile is - // Off-the-Record and doesn't close browsers with the original profile. - static void CloseAllBrowsersWithIncognitoProfile( - Profile* profile, - const CloseCallback& on_close_success, - const CloseCallback& on_close_aborted, - bool skip_beforeunload); - // Returns true if at least one incognito session is active across all // desktops. static bool IsIncognitoSessionActive();
diff --git a/chrome/browser/ui/browser_unittest.cc b/chrome/browser/ui/browser_unittest.cc index 0a75853..c7a826ea 100644 --- a/chrome/browser/ui/browser_unittest.cc +++ b/chrome/browser/ui/browser_unittest.cc
@@ -28,8 +28,8 @@ // Caller owns the memory. std::unique_ptr<WebContents> CreateTestWebContents() { - return base::WrapUnique(WebContentsTester::CreateTestWebContents( - profile(), SiteInstance::Create(profile()))); + return WebContentsTester::CreateTestWebContents( + profile(), SiteInstance::Create(profile())); } private:
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer_unittest.cc b/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer_unittest.cc index 9a119c5f..3bb931d9e 100644 --- a/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer_unittest.cc +++ b/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer_unittest.cc
@@ -174,8 +174,8 @@ }; void ChromeOmniboxNavigationObserverTest::SetUp() { - web_contents_.reset(content::WebContentsTester::CreateTestWebContents( - profile(), content::SiteInstance::Create(profile()))); + web_contents_ = content::WebContentsTester::CreateTestWebContents( + profile(), content::SiteInstance::Create(profile())); InfoBarService::CreateForWebContents(web_contents_.get());
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc index 036dd56f..5f293551 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc
@@ -127,8 +127,8 @@ ~ManagePasswordsBubbleModelTest() override = default; void SetUp() override { - test_web_contents_.reset( - content::WebContentsTester::CreateTestWebContents(&profile_, nullptr)); + test_web_contents_ = + content::WebContentsTester::CreateTestWebContents(&profile_, nullptr); mock_delegate_.reset(new testing::NiceMock<PasswordsModelDelegateMock>); ON_CALL(*mock_delegate_, GetPasswordFormMetricsRecorder()) .WillByDefault(Return(nullptr));
diff --git a/chrome/browser/ui/passwords/password_manager_porter_unittest.cc b/chrome/browser/ui/passwords/password_manager_porter_unittest.cc index dd947b6..4c2ae0b 100644 --- a/chrome/browser/ui/passwords/password_manager_porter_unittest.cc +++ b/chrome/browser/ui/passwords/password_manager_porter_unittest.cc
@@ -191,8 +191,8 @@ void SetUp() override { password_manager_porter_.reset(new TestPasswordManagerPorter()); profile_.reset(new TestingProfile()); - web_contents_.reset(content::WebContentsTester::CreateTestWebContents( - profile_.get(), nullptr)); + web_contents_ = content::WebContentsTester::CreateTestWebContents( + profile_.get(), nullptr); // SelectFileDialog::SetFactory is responsible for freeing the memory // associated with a new factory. selected_file_ = base::FilePath(kNullFileName);
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index ee0887f..24d14ba4 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -15,6 +15,7 @@ #include "base/metrics/user_metrics.h" #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/browser_shutdown.h" #include "chrome/browser/defaults.h" #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/ui/tab_contents/core_tab_helper.h" @@ -26,6 +27,7 @@ #include "chrome/common/url_constants.h" #include "components/feature_engagement/buildflags.h" #include "components/web_modal/web_contents_modal_dialog_manager.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" @@ -39,6 +41,81 @@ namespace { +// CloseTracker is used when closing a set of WebContents. It listens for +// deletions of the WebContents and removes from the internal set any time one +// is deleted. +class CloseTracker { + public: + using Contents = base::span<content::WebContents* const>; + + explicit CloseTracker(const Contents& contents); + ~CloseTracker(); + + // Returns true if there is another WebContents in the Tracker. + bool HasNext() const; + + // Returns the next WebContents, or NULL if there are no more. + content::WebContents* Next(); + + private: + class DeletionObserver : public content::WebContentsObserver { + public: + DeletionObserver(CloseTracker* parent, content::WebContents* web_contents) + : WebContentsObserver(web_contents), parent_(parent) {} + + private: + // WebContentsObserver: + void WebContentsDestroyed() override { + parent_->OnWebContentsDestroyed(this); + } + + CloseTracker* parent_; + + DISALLOW_COPY_AND_ASSIGN(DeletionObserver); + }; + + void OnWebContentsDestroyed(DeletionObserver* observer); + + using Observers = std::vector<std::unique_ptr<DeletionObserver>>; + Observers observers_; + + DISALLOW_COPY_AND_ASSIGN(CloseTracker); +}; + +CloseTracker::CloseTracker(const Contents& contents) { + observers_.reserve(contents.size()); + for (content::WebContents* current : contents) + observers_.push_back(std::make_unique<DeletionObserver>(this, current)); +} + +CloseTracker::~CloseTracker() { + DCHECK(observers_.empty()); +} + +bool CloseTracker::HasNext() const { + return !observers_.empty(); +} + +content::WebContents* CloseTracker::Next() { + if (observers_.empty()) + return nullptr; + + DeletionObserver* observer = observers_[0].get(); + content::WebContents* web_contents = observer->web_contents(); + observers_.erase(observers_.begin()); + return web_contents; +} + +void CloseTracker::OnWebContentsDestroyed(DeletionObserver* observer) { + for (auto i = observers_.begin(); i != observers_.end(); ++i) { + if (observer == i->get()) { + observers_.erase(i); + return; + } + } + NOTREACHED() << "WebContents destroyed that wasn't in the list"; +} + // Returns true if the specified transition is one of the types that cause the // opener relationships for the tab in which the transition occurred to be // forgotten. This is generally any navigation that isn't a link click (i.e. @@ -1167,7 +1244,7 @@ for (auto& observer : observers_) observer.WillCloseAllTabs(); } - const bool closed_all = CloseWebContentses(this, items, close_types); + const bool closed_all = CloseWebContentses(items, close_types); if (!ref) return closed_all; if (closing_all && !closed_all) { @@ -1177,6 +1254,67 @@ return closed_all; } +bool TabStripModel::CloseWebContentses( + base::span<content::WebContents* const> items, + uint32_t close_types) { + if (items.empty()) + return true; + + CloseTracker close_tracker(items); + + // We only try the fast shutdown path if the whole browser process is *not* + // shutting down. Fast shutdown during browser termination is handled in + // browser_shutdown::OnShutdownStarting. + if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) { + // Construct a map of processes to the number of associated tabs that are + // closing. + base::flat_map<content::RenderProcessHost*, size_t> processes; + for (content::WebContents* contents : items) { + if (ShouldRunUnloadListenerBeforeClosing(contents)) + continue; + content::RenderProcessHost* process = + contents->GetMainFrame()->GetProcess(); + ++processes[process]; + } + + // Try to fast shutdown the tabs that can close. + for (const auto& pair : processes) + pair.first->FastShutdownIfPossible(pair.second, false); + } + + // We now return to our regularly scheduled shutdown procedure. + bool closed_all = true; + while (close_tracker.HasNext()) { + content::WebContents* closing_contents = close_tracker.Next(); + if (!ContainsWebContents(closing_contents)) + continue; + + CoreTabHelper* core_tab_helper = + CoreTabHelper::FromWebContents(closing_contents); + core_tab_helper->OnCloseStarted(); + + // Update the explicitly closed state. If the unload handlers cancel the + // close the state is reset in Browser. We don't update the explicitly + // closed state if already marked as explicitly closed as unload handlers + // call back to this if the close is allowed. + if (!closing_contents->GetClosedByUserGesture()) { + closing_contents->SetClosedByUserGesture( + close_types & TabStripModel::CLOSE_USER_GESTURE); + } + + if (RunUnloadListenerBeforeClosing(closing_contents)) { + closed_all = false; + continue; + } + + OnWillDeleteWebContents(closing_contents, close_types); + + delete closing_contents; + } + + return closed_all; +} + WebContents* TabStripModel::GetWebContentsAtImpl(int index) const { CHECK(ContainsIndex(index)) << "Failed to find: " << index << " in: " << count() << " entries.";
diff --git a/chrome/browser/ui/tabs/tab_strip_model.h b/chrome/browser/ui/tabs/tab_strip_model.h index 1a88899..67adfb7a 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.h +++ b/chrome/browser/ui/tabs/tab_strip_model.h
@@ -17,7 +17,6 @@ #include "base/observer_list.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "chrome/browser/ui/tabs/tab_strip_model_order_controller.h" -#include "chrome/browser/ui/tabs/web_contents_closer.h" #include "ui/base/models/list_selection_model.h" #include "ui/base/page_transition_types.h" @@ -56,7 +55,7 @@ // its bookkeeping when such events happen. // //////////////////////////////////////////////////////////////////////////////// -class TabStripModel : public WebContentsCloseDelegate { +class TabStripModel { public: // Used to specify what should happen when the tab is closed. enum CloseTypes { @@ -122,7 +121,7 @@ // Construct a TabStripModel with a delegate to help it do certain things // (see the TabStripModelDelegate documentation). |delegate| cannot be NULL. explicit TabStripModel(TabStripModelDelegate* delegate, Profile* profile); - ~TabStripModel() override; + ~TabStripModel(); // Retrieves the TabStripModelDelegate associated with this TabStripModel. TabStripModelDelegate* delegate() const { return delegate_; } @@ -438,13 +437,11 @@ kUserGesture, }; - // WebContentsCloseDelegate: - bool ContainsWebContents(content::WebContents* contents) override; + bool ContainsWebContents(content::WebContents* contents); void OnWillDeleteWebContents(content::WebContents* contents, - uint32_t close_types) override; - bool RunUnloadListenerBeforeClosing(content::WebContents* contents) override; - bool ShouldRunUnloadListenerBeforeClosing( - content::WebContents* contents) override; + uint32_t close_types); + bool RunUnloadListenerBeforeClosing(content::WebContents* contents); + bool ShouldRunUnloadListenerBeforeClosing(content::WebContents* contents); int ConstrainInsertionIndex(int index, bool pinned_tab); @@ -483,6 +480,17 @@ bool InternalCloseTabs(base::span<content::WebContents* const> items, uint32_t close_types); + // |close_types| is a bitmask of the types in CloseTypes. + // Returns true if all the tabs have been deleted. A return value of false + // means some portion (potentially none) of the WebContents were deleted. + // WebContents not deleted by this function are processing unload handlers + // which may eventually be deleted based on the results of the unload handler. + // Additionally processing the unload handlers may result in needing to show + // UI for the WebContents. See UnloadController for details on how unload + // handlers are processed. + bool CloseWebContentses(base::span<content::WebContents* const> items, + uint32_t close_types); + // Gets the WebContents at an index. Does no bounds checking. content::WebContents* GetWebContentsAtImpl(int index) const;
diff --git a/chrome/browser/ui/tabs/tab_strip_model_stats_recorder_unittest.cc b/chrome/browser/ui/tabs/tab_strip_model_stats_recorder_unittest.cc index 06cec9f..18fad1b 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_stats_recorder_unittest.cc +++ b/chrome/browser/ui/tabs/tab_strip_model_stats_recorder_unittest.cc
@@ -44,13 +44,15 @@ HistogramTester tester; // Insert the first tab. - WebContents* contents1 = CreateTestWebContents(); - tabstrip.InsertWebContentsAt(0, base::WrapUnique(contents1), + std::unique_ptr<WebContents> contents1 = CreateTestWebContents(); + WebContents* raw_contents1 = contents1.get(); + tabstrip.InsertWebContentsAt(0, std::move(contents1), TabStripModel::ADD_ACTIVE); // Deactivate the first tab by inserting new tab. - WebContents* contents2 = CreateTestWebContents(); - tabstrip.InsertWebContentsAt(1, base::WrapUnique(contents2), + std::unique_ptr<WebContents> contents2 = CreateTestWebContents(); + WebContents* raw_contents2 = contents2.get(); + tabstrip.InsertWebContentsAt(1, std::move(contents2), TabStripModel::ADD_ACTIVE); tester.ExpectUniqueSample( @@ -58,7 +60,7 @@ static_cast<int>(TabStripModelStatsRecorder::TabState::INACTIVE), 1); // Reactivate the first tab. - tabstrip.ActivateTabAt(tabstrip.GetIndexOfWebContents(contents1), true); + tabstrip.ActivateTabAt(tabstrip.GetIndexOfWebContents(raw_contents1), true); tester.ExpectUniqueSample( "Tabs.StateTransfer.Target_Active", @@ -71,12 +73,11 @@ // Replace the contents of the first tab. // TabStripModeStatsRecorder should follow WebContents change. - std::unique_ptr<WebContents> contents3 = - base::WrapUnique(CreateTestWebContents()); + std::unique_ptr<WebContents> contents3 = CreateTestWebContents(); tabstrip.ReplaceWebContentsAt(0, std::move(contents3)); // Close the inactive second tab. - tabstrip.CloseWebContentsAt(tabstrip.GetIndexOfWebContents(contents2), + tabstrip.CloseWebContentsAt(tabstrip.GetIndexOfWebContents(raw_contents2), TabStripModel::CLOSE_USER_GESTURE | TabStripModel::CLOSE_CREATE_HISTORICAL_TAB); @@ -107,18 +108,15 @@ HistogramTester tester; // Create a tab in strip 1. - WebContents* contents1 = CreateTestWebContents(); - tabstrip1.InsertWebContentsAt(0, base::WrapUnique(contents1), + tabstrip1.InsertWebContentsAt(0, CreateTestWebContents(), TabStripModel::ADD_ACTIVE); // Create a tab in strip 2. - WebContents* contents2 = CreateTestWebContents(); - tabstrip2.InsertWebContentsAt(0, base::WrapUnique(contents2), + tabstrip2.InsertWebContentsAt(0, CreateTestWebContents(), TabStripModel::ADD_ACTIVE); // Create another tab in strip 1. - WebContents* contents3 = CreateTestWebContents(); - tabstrip1.InsertWebContentsAt(1, base::WrapUnique(contents3), + tabstrip1.InsertWebContentsAt(1, CreateTestWebContents(), TabStripModel::ADD_ACTIVE); tester.ExpectUniqueSample( @@ -126,8 +124,7 @@ static_cast<int>(TabStripModelStatsRecorder::TabState::INACTIVE), 1); // Create another tab in strip 2. - WebContents* contents4 = CreateTestWebContents(); - tabstrip2.InsertWebContentsAt(1, base::WrapUnique(contents4), + tabstrip2.InsertWebContentsAt(1, CreateTestWebContents(), TabStripModel::ADD_ACTIVE); tester.ExpectUniqueSample( @@ -178,19 +175,19 @@ HistogramTester tester; // Create first tab - WebContents* contents0 = CreateTestWebContents(); - tabstrip.InsertWebContentsAt(0, base::WrapUnique(contents0), + std::unique_ptr<WebContents> contents0 = CreateTestWebContents(); + WebContents* raw_contents0 = contents0.get(); + tabstrip.InsertWebContentsAt(0, std::move(contents0), TabStripModel::ADD_ACTIVE); // Add 9 more tabs and activate them for (int i = 1; i < 10; ++i) { - WebContents* contents = CreateTestWebContents(); - tabstrip.InsertWebContentsAt(1, base::WrapUnique(contents), + tabstrip.InsertWebContentsAt(1, CreateTestWebContents(), TabStripModel::ADD_ACTIVE); } // Reactivate the first tab - tabstrip.ActivateTabAt(tabstrip.GetIndexOfWebContents(contents0), true); + tabstrip.ActivateTabAt(tabstrip.GetIndexOfWebContents(raw_contents0), true); tester.ExpectUniqueSample( "Tabs.StateTransfer.NumberOfOtherTabsActivatedBeforeMadeActive", 9, 1); @@ -210,22 +207,25 @@ HistogramTester tester; // Create tab 0, 1, 2 - WebContents* contents0 = CreateTestWebContents(); - WebContents* contents1 = CreateTestWebContents(); - WebContents* contents2 = CreateTestWebContents(); - tabstrip.InsertWebContentsAt(0, base::WrapUnique(contents0), + std::unique_ptr<WebContents> contents0 = CreateTestWebContents(); + WebContents* raw_contents0 = contents0.get(); + std::unique_ptr<WebContents> contents1 = CreateTestWebContents(); + WebContents* raw_contents1 = contents1.get(); + std::unique_ptr<WebContents> contents2 = CreateTestWebContents(); + WebContents* raw_contents2 = contents2.get(); + tabstrip.InsertWebContentsAt(0, std::move(contents0), TabStripModel::ADD_ACTIVE); - tabstrip.InsertWebContentsAt(1, base::WrapUnique(contents1), + tabstrip.InsertWebContentsAt(1, std::move(contents1), TabStripModel::ADD_ACTIVE); - tabstrip.InsertWebContentsAt(2, base::WrapUnique(contents2), + tabstrip.InsertWebContentsAt(2, std::move(contents2), TabStripModel::ADD_ACTIVE); // Switch between tabs {0,1} for 5 times, then switch to tab 2 for (int i = 0; i < 5; ++i) { - tabstrip.ActivateTabAt(tabstrip.GetIndexOfWebContents(contents0), true); - tabstrip.ActivateTabAt(tabstrip.GetIndexOfWebContents(contents1), true); + tabstrip.ActivateTabAt(tabstrip.GetIndexOfWebContents(raw_contents0), true); + tabstrip.ActivateTabAt(tabstrip.GetIndexOfWebContents(raw_contents1), true); } - tabstrip.ActivateTabAt(tabstrip.GetIndexOfWebContents(contents2), true); + tabstrip.ActivateTabAt(tabstrip.GetIndexOfWebContents(raw_contents2), true); EXPECT_THAT( tester.GetAllSamples(
diff --git a/chrome/browser/ui/tabs/web_contents_closer.cc b/chrome/browser/ui/tabs/web_contents_closer.cc deleted file mode 100644 index 503f9ae..0000000 --- a/chrome/browser/ui/tabs/web_contents_closer.cc +++ /dev/null
@@ -1,156 +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 "chrome/browser/ui/tabs/web_contents_closer.h" - -#include <memory> - -#include "chrome/browser/browser_shutdown.h" -#include "chrome/browser/ui/tab_contents/core_tab_helper.h" -#include "chrome/browser/ui/tab_contents/core_tab_helper_delegate.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_observer.h" - -namespace { - -// CloseTracker is used when closing a set of WebContents. It listens for -// deletions of the WebContents and removes from the internal set any time one -// is deleted. -class CloseTracker { - public: - using Contents = base::span<content::WebContents* const>; - - explicit CloseTracker(const Contents& contents); - ~CloseTracker(); - - // Returns true if there is another WebContents in the Tracker. - bool HasNext() const; - - // Returns the next WebContents, or NULL if there are no more. - content::WebContents* Next(); - - private: - class DeletionObserver : public content::WebContentsObserver { - public: - DeletionObserver(CloseTracker* parent, content::WebContents* web_contents) - : WebContentsObserver(web_contents), parent_(parent) {} - - private: - // WebContentsObserver: - void WebContentsDestroyed() override { - parent_->OnWebContentsDestroyed(this); - } - - CloseTracker* parent_; - - DISALLOW_COPY_AND_ASSIGN(DeletionObserver); - }; - - void OnWebContentsDestroyed(DeletionObserver* observer); - - using Observers = std::vector<std::unique_ptr<DeletionObserver>>; - Observers observers_; - - DISALLOW_COPY_AND_ASSIGN(CloseTracker); -}; - -CloseTracker::CloseTracker(const Contents& contents) { - observers_.reserve(contents.size()); - for (content::WebContents* current : contents) - observers_.push_back(std::make_unique<DeletionObserver>(this, current)); -} - -CloseTracker::~CloseTracker() { - DCHECK(observers_.empty()); -} - -bool CloseTracker::HasNext() const { - return !observers_.empty(); -} - -content::WebContents* CloseTracker::Next() { - if (observers_.empty()) - return nullptr; - - DeletionObserver* observer = observers_[0].get(); - content::WebContents* web_contents = observer->web_contents(); - observers_.erase(observers_.begin()); - return web_contents; -} - -void CloseTracker::OnWebContentsDestroyed(DeletionObserver* observer) { - for (auto i = observers_.begin(); i != observers_.end(); ++i) { - if (observer == i->get()) { - observers_.erase(i); - return; - } - } - NOTREACHED() << "WebContents destroyed that wasn't in the list"; -} - -} // namespace - -bool CloseWebContentses(WebContentsCloseDelegate* delegate, - base::span<content::WebContents* const> items, - uint32_t close_types) { - if (items.empty()) - return true; - - CloseTracker close_tracker(items); - - // We only try the fast shutdown path if the whole browser process is *not* - // shutting down. Fast shutdown during browser termination is handled in - // browser_shutdown::OnShutdownStarting. - if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) { - // Construct a map of processes to the number of associated tabs that are - // closing. - base::flat_map<content::RenderProcessHost*, size_t> processes; - for (content::WebContents* contents : items) { - if (delegate->ShouldRunUnloadListenerBeforeClosing(contents)) - continue; - content::RenderProcessHost* process = - contents->GetMainFrame()->GetProcess(); - ++processes[process]; - } - - // Try to fast shutdown the tabs that can close. - for (const auto& pair : processes) - pair.first->FastShutdownIfPossible(pair.second, false); - } - - // We now return to our regularly scheduled shutdown procedure. - bool closed_all = true; - while (close_tracker.HasNext()) { - content::WebContents* closing_contents = close_tracker.Next(); - if (!delegate->ContainsWebContents(closing_contents)) - continue; - - CoreTabHelper* core_tab_helper = - CoreTabHelper::FromWebContents(closing_contents); - core_tab_helper->OnCloseStarted(); - - // Update the explicitly closed state. If the unload handlers cancel the - // close the state is reset in Browser. We don't update the explicitly - // closed state if already marked as explicitly closed as unload handlers - // call back to this if the close is allowed. - if (!closing_contents->GetClosedByUserGesture()) { - closing_contents->SetClosedByUserGesture( - close_types & TabStripModel::CLOSE_USER_GESTURE); - } - - if (delegate->RunUnloadListenerBeforeClosing(closing_contents)) { - closed_all = false; - continue; - } - - delegate->OnWillDeleteWebContents(closing_contents, close_types); - - delete closing_contents; - } - - return closed_all; -}
diff --git a/chrome/browser/ui/tabs/web_contents_closer.h b/chrome/browser/ui/tabs/web_contents_closer.h deleted file mode 100644 index 4b459500..0000000 --- a/chrome/browser/ui/tabs/web_contents_closer.h +++ /dev/null
@@ -1,49 +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 CHROME_BROWSER_UI_TABS_WEB_CONTENTS_CLOSER_H_ -#define CHROME_BROWSER_UI_TABS_WEB_CONTENTS_CLOSER_H_ - -#include <stdint.h> - -#include "base/containers/span.h" - -namespace content { -class WebContents; -} - -class WebContentsCloseDelegate { - public: - // Returns true if the delegate still contains the tab. - virtual bool ContainsWebContents(content::WebContents* contents) = 0; - - // Called right befor deleting |contents|. Gives the delegate a change to do - // last minute cleaning. |close_types| is the |close_types| supplied to - // CloseWebContentses(). - virtual void OnWillDeleteWebContents(content::WebContents* contents, - uint32_t close_types) = 0; - - // These mirror that of TabStripModelDelegate, see it for details. - virtual bool RunUnloadListenerBeforeClosing( - content::WebContents* contents) = 0; - virtual bool ShouldRunUnloadListenerBeforeClosing( - content::WebContents* contents) = 0; - - protected: - virtual ~WebContentsCloseDelegate() {} -}; - -// |close_types| is a bitmask of the types in TabStripModel::CloseTypes. -// Returns true if all the tabs have been deleted. A return value of false means -// some portion (potentially none) of the WebContents were deleted. WebContents -// not deleted by this function are processing unload handlers which may -// eventually be deleted based on the results of the unload handler. -// Additionally processing the unload handlers may result in needing to show UI -// for the WebContents. See UnloadController for details on how unload handlers -// are processed. -bool CloseWebContentses(WebContentsCloseDelegate* delegate, - base::span<content::WebContents* const> items, - uint32_t close_types); - -#endif // CHROME_BROWSER_UI_TABS_WEB_CONTENTS_CLOSER_H_
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc index 051600e..c4539e5 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
@@ -7,9 +7,9 @@ #include <utility> #include "apps/ui/views/app_window_frame_view.h" -#include "ash/ash_constants.h" #include "ash/frame/custom_frame_view_ash.h" #include "ash/public/cpp/app_types.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h" #include "ash/public/cpp/shell_window_ids.h"
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index 0d9e6b2..83cc1409 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -6,7 +6,6 @@ #include <algorithm> -#include "ash/ash_constants.h" #include "ash/ash_layout_constants.h" #include "ash/frame/caption_buttons/frame_back_button.h" #include "ash/frame/caption_buttons/frame_caption_button_container_view.h" @@ -15,6 +14,7 @@ #include "ash/frame/frame_header_origin_text.h" #include "ash/frame/frame_header_util.h" #include "ash/public/cpp/app_types.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/window_properties.h"
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index eaa1ed3..4fa8ce4 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -6,12 +6,12 @@ #include <string> -#include "ash/ash_constants.h" #include "ash/ash_layout_constants.h" #include "ash/frame/caption_buttons/frame_caption_button.h" #include "ash/frame/caption_buttons/frame_caption_button_container_view.h" #include "ash/frame/default_frame_header.h" #include "ash/frame/frame_header.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h" #include "ash/public/cpp/vector_icons/vector_icons.h"
diff --git a/chrome/browser/ui/views/frame/browser_root_view.cc b/chrome/browser/ui/views/frame/browser_root_view.cc index 090c230..d544c9ec 100644 --- a/chrome/browser/ui/views/frame/browser_root_view.cc +++ b/chrome/browser/ui/views/frame/browser_root_view.cc
@@ -90,7 +90,11 @@ } // namespace BrowserRootView::DropInfo::DropInfo() = default; -BrowserRootView::DropInfo::~DropInfo() = default; + +BrowserRootView::DropInfo::~DropInfo() { + if (target) + target->HandleDragExited(); +} // static const char BrowserRootView::kViewClassName[] = @@ -161,7 +165,7 @@ drop_info_->target->HandleDragExited(); drop_info_->target = drop_target; - if (!drop_info_->file_supported || !drop_info_->url.is_valid() || + if (!drop_info_->file_supported || drop_info_->url.SchemeIs(url::kJavaScriptScheme)) { drop_info_->index.reset(); } else { @@ -179,11 +183,6 @@ } void BrowserRootView::OnDragExited() { - if (drop_info_ && drop_info_->target) { - drop_info_->target->HandleDragExited(); - drop_info_->target = nullptr; - } - drop_info_.reset(); } @@ -193,6 +192,10 @@ if (!drop_info_) return ui::DragDropTypes::DRAG_NONE; + // Ensure we call HandleDragExited() on |drop_info_|'s |target| when this + // function returns. + std::unique_ptr<DropInfo> drop_info = std::move(drop_info_); + // Extract the URL and create a new ui::OSExchangeData containing the URL. We // do this as the TabStrip doesn't know about the autocomplete edit and needs // to know about it to handle 'paste and go'. @@ -204,15 +207,15 @@ // Do nothing if the file was unsupported, the URL is invalid, or this is a // javascript: URL (prevent self-xss). The URL may have been changed after - // |drop_info_| was created. - if (!drop_info_->file_supported || !url.is_valid() || + // |drop_info| was created. + if (!drop_info->file_supported || !url.is_valid() || url.SchemeIs(url::kJavaScriptScheme)) return ui::DragDropTypes::DRAG_NONE; NavigateParams params(browser_view_->browser(), url, ui::PAGE_TRANSITION_LINK); - params.tabstrip_index = drop_info_->index->value; - if (drop_info_->index->drop_before) { + params.tabstrip_index = drop_info->index->value; + if (drop_info->index->drop_before) { base::RecordAction(UserMetricsAction("Tab_DropURLBetweenTabs")); params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; } else { @@ -220,7 +223,7 @@ params.disposition = WindowOpenDisposition::CURRENT_TAB; Browser* browser = browser_view_->browser(); TabStripModel* model = browser->tab_strip_model(); - params.source_contents = model->GetWebContentsAt(drop_info_->index->value); + params.source_contents = model->GetWebContentsAt(drop_info->index->value); } params.window_action = NavigateParams::SHOW_WINDOW;
diff --git a/chrome/browser/ui/views/frame/browser_root_view.h b/chrome/browser/ui/views/frame/browser_root_view.h index 7435881..c4942a98 100644 --- a/chrome/browser/ui/views/frame/browser_root_view.h +++ b/chrome/browser/ui/views/frame/browser_root_view.h
@@ -72,6 +72,8 @@ void OnMouseExited(const ui::MouseEvent& event) override; private: + FRIEND_TEST_ALL_PREFIXES(BrowserRootViewBrowserTest, ClearDropInfo); + // Used during a drop session of a url. Tracks the position of the drop. struct DropInfo { DropInfo();
diff --git a/chrome/browser/ui/views/frame/browser_root_view_browsertest.cc b/chrome/browser/ui/views/frame/browser_root_view_browsertest.cc new file mode 100644 index 0000000..35086013 --- /dev/null +++ b/chrome/browser/ui/views/frame/browser_root_view_browsertest.cc
@@ -0,0 +1,54 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/frame/browser_root_view.h" + +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/views/scoped_macviews_browser_mode.h" +#include "ui/base/dragdrop/drag_drop_types.h" +#include "ui/base/dragdrop/drop_target_event.h" +#include "ui/base/dragdrop/os_exchange_data.h" + +class BrowserRootViewBrowserTest : public InProcessBrowserTest { + public: + BrowserRootViewBrowserTest() = default; + + BrowserRootView* browser_root_view() { + BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); + return static_cast<BrowserRootView*>( + browser_view->GetWidget()->GetRootView()); + } + + private: + test::ScopedMacViewsBrowserMode views_mode_{true}; + + DISALLOW_COPY_AND_ASSIGN(BrowserRootViewBrowserTest); +}; + +// Clear drop info after performing drop. http://crbug.com/838791 +IN_PROC_BROWSER_TEST_F(BrowserRootViewBrowserTest, ClearDropInfo) { + ui::OSExchangeData data; + data.SetURL(GURL("http://www.chromium.org/"), base::string16()); + ui::DropTargetEvent event(data, gfx::Point(), gfx::Point(), + ui::DragDropTypes::DRAG_COPY); + + BrowserRootView* root_view = browser_root_view(); + root_view->OnDragUpdated(event); + root_view->OnPerformDrop(event); + EXPECT_FALSE(root_view->drop_info_); +} + +// Make sure plain string is droppable. http://crbug.com/838794 +IN_PROC_BROWSER_TEST_F(BrowserRootViewBrowserTest, PlainString) { + ui::OSExchangeData data; + data.SetString(base::ASCIIToUTF16("Plain string")); + ui::DropTargetEvent event(data, gfx::Point(), gfx::Point(), + ui::DragDropTypes::DRAG_COPY); + + BrowserRootView* root_view = browser_root_view(); + EXPECT_NE(ui::DragDropTypes::DRAG_NONE, root_view->OnDragUpdated(event)); + EXPECT_NE(ui::DragDropTypes::DRAG_NONE, root_view->OnPerformDrop(event)); +}
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 dd900e8..1561645 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
@@ -49,7 +49,7 @@ void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); - web_contents_.reset(CreateTestWebContents()); + web_contents_ = CreateTestWebContents(); display_observer_ = std::make_unique<TestWebContentsDisplayObserverView>( web_contents_.get(), base::BindRepeating(&MockCallback::OnDisplayChanged,
diff --git a/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.cc index 684dfbfe..7c863b5 100644 --- a/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.cc
@@ -111,8 +111,6 @@ user_context.SetKey(key); user_context.SetAuthFlow(UserContext::AUTH_FLOW_ACTIVE_DIRECTORY); user_context.SetIsUsingOAuth(false); - user_context.SetUserType( - user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY); LoginDisplayHost::default_host()->CompleteLogin(user_context); break; }
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc index 28dee8d..479ab976 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -16,6 +16,7 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/sys_info.h" #include "base/task_scheduler/post_task.h" @@ -662,8 +663,6 @@ user_context.SetKey(key); user_context.SetAuthFlow(UserContext::AUTH_FLOW_ACTIVE_DIRECTORY); user_context.SetIsUsingOAuth(false); - user_context.SetUserType( - user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY); LoginDisplayHost::default_host()->CompleteLogin(user_context); break; } @@ -898,12 +897,14 @@ } void GaiaScreenHandler::ShowSigninScreenForTest(const std::string& username, - const std::string& password) { + const std::string& password, + const std::string& services) { VLOG(2) << "ShowSigninScreenForTest for user " << username << ", frame_state=" << frame_state(); test_user_ = username; test_pass_ = password; + test_services_ = services; test_expects_complete_login_ = true; // Submit login form for test if gaia is ready. If gaia is loading, login @@ -927,6 +928,16 @@ "document.getElementById('nextButton').click();"; frame->ExecuteJavaScriptForTests(base::ASCIIToUTF16(code)); + if (!test_services_.empty()) { + // Prefix each doublequote with backslash, so that it will remain correct + // JSON after assigning to the element property. + std::string escaped_services; + base::ReplaceChars(test_services_, "\"", "\\\"", &escaped_services); + code = "document.getElementById('services').value = \"" + escaped_services + + "\";"; + frame->ExecuteJavaScriptForTests(base::ASCIIToUTF16(code)); + } + if (!test_pass_.empty()) { code = "document.getElementById('password').value = '" + test_pass_ + "';"; code += "document.getElementById('nextButton').click();";
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h index 287881d8..ca864555 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -159,8 +159,10 @@ const authpolicy::ActiveDirectoryAccountInfo& account_info); // Show sign-in screen for the given credentials. + // Should match the same method in SigninScreenHandler. void ShowSigninScreenForTest(const std::string& username, - const std::string& password); + const std::string& password, + const std::string& services); // Attempts login for test. void SubmitLoginFormForTest(); @@ -252,6 +254,8 @@ // Test credentials. std::string test_user_; std::string test_pass_; + // Test result of userInfo. + std::string test_services_; bool test_expects_complete_login_ = false; // True if proxy doesn't allow access to google.com/generate_204.
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc index 3af82c2..02b21f3 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -1073,10 +1073,10 @@ core_oobe_view_->ShowPasswordChangedScreen(show_password_error, email); } -void SigninScreenHandler::ShowSigninScreenForCreds( - const std::string& username, - const std::string& password) { - gaia_screen_handler_->ShowSigninScreenForTest(username, password); +void SigninScreenHandler::ShowSigninScreenForTest(const std::string& username, + const std::string& password, + const std::string& services) { + gaia_screen_handler_->ShowSigninScreenForTest(username, password, services); } void SigninScreenHandler::ShowWhitelistCheckFailedError() { @@ -1212,7 +1212,19 @@ DCHECK_EQ(account_id.GetUserEmail(), gaia::SanitizeEmail(account_id.GetUserEmail())); - UserContext user_context(account_id); + const user_manager::User* user = + user_manager::UserManager::Get()->FindUser(account_id); + DCHECK(user); + user_manager::UserType user_type = user_manager::UserType::USER_TYPE_REGULAR; + if (!user) { + LOG(ERROR) << "HandleAuthenticateUser: User not found! account type=" + << AccountId::AccountTypeToString(account_id.GetAccountType()); + if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY) + user_type = user_manager::USER_TYPE_ACTIVE_DIRECTORY; + } else { + user_type = user->GetType(); + } + UserContext user_context(user_type, account_id); user_context.SetKey(Key(password)); // Only save the password for enterprise users. See https://crbug.com/386606. const bool is_enterprise_managed = g_browser_process->platform_part() @@ -1222,17 +1234,13 @@ user_context.SetPasswordKey(Key(password)); } user_context.SetIsUsingPin(authenticated_by_pin); - const user_manager::User* user = - user_manager::UserManager::Get()->FindUser(account_id); - DCHECK(user); - if (!user) { - LOG(ERROR) << "HandleAuthenticateUser: User not found! account type=" - << AccountId::AccountTypeToString(account_id.GetAccountType()); - } else { - user_context.SetUserType(user->GetType()); + if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY && + (user_context.GetUserType() != + user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY)) { + LOG(FATAL) << "Incorrect Active Directory user type " + << user_context.GetUserType(); } - if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY) - user_context.SetUserType(user_manager::USER_TYPE_ACTIVE_DIRECTORY); + delegate_->Login(user_context, SigninSpecifics()); UpdatePinKeyboardState(account_id);
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h index c801908..3d9bda5 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -115,8 +115,11 @@ virtual void ShowPasswordChangedDialog(bool show_password_error, const std::string& email) = 0; // Show sign-in screen for the given credentials. - virtual void ShowSigninScreenForCreds(const std::string& username, - const std::string& password) = 0; + // |services| - list of services returned by userInfo call as JSON array. + // Should be empty array for regular user: "[]". + virtual void ShowSigninScreenForTest(const std::string& username, + const std::string& password, + const std::string& services) = 0; virtual void ShowWhitelistCheckFailedError() = 0; virtual void ShowUnrecoverableCrypthomeErrorDialog() = 0; virtual void LoadUsers(const user_manager::UserList& users, @@ -342,8 +345,9 @@ void ShowPasswordChangedDialog(bool show_password_error, const std::string& email) override; void ShowErrorScreen(LoginDisplay::SigninError error_id) override; - void ShowSigninScreenForCreds(const std::string& username, - const std::string& password) override; + void ShowSigninScreenForTest(const std::string& username, + const std::string& password, + const std::string& services) override; void ShowWhitelistCheckFailedError() override; void ShowUnrecoverableCrypthomeErrorDialog() override; void LoadUsers(const user_manager::UserList& users,
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 785966a2..3c401ca 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -781,7 +781,7 @@ delegate->ReleaseWebContents(); DCHECK_EQ(preview_dialog, preview_contents.get()); background_printing_manager->OwnPrintPreviewDialog( - preview_contents.release()); + std::move(preview_contents)); OnClosePrintPreviewDialog(); }
diff --git a/chrome/browser/ui/webui/snippets_internals/snippets_internals_message_handler.cc b/chrome/browser/ui/webui/snippets_internals/snippets_internals_message_handler.cc index e1ebaeb..738860b 100644 --- a/chrome/browser/ui/webui/snippets_internals/snippets_internals_message_handler.cc +++ b/chrome/browser/ui/webui/snippets_internals/snippets_internals_message_handler.cc
@@ -54,7 +54,6 @@ using ntp_snippets::CategoryStatus; using ntp_snippets::ContentSuggestion; using ntp_snippets::IsBookmarkProviderEnabled; -using ntp_snippets::IsRecentTabProviderEnabled; using ntp_snippets::KnownCategories; using ntp_snippets::RemoteSuggestion; using ntp_snippets::RemoteSuggestionsProvider; @@ -94,17 +93,6 @@ entry->Set("downloadSuggestionExtra", std::move(value)); } - if (suggestion.recent_tab_suggestion_extra()) { - const auto& extra = *suggestion.recent_tab_suggestion_extra(); - auto value = std::make_unique<base::DictionaryValue>(); - value->SetInteger("tabID", extra.tab_id); - value->SetString( - "offlinePageID", - base::StringPrintf("0x%016llx", static_cast<long long unsigned int>( - extra.offline_page_id))); - entry->Set("recentTabSuggestionExtra", std::move(value)); - } - if (suggestion.notification_extra()) { const auto& extra = *suggestion.notification_extra(); auto value = std::make_unique<base::DictionaryValue>(); @@ -425,8 +413,6 @@ "flag-article-suggestions", base::FeatureList::IsEnabled(ntp_snippets::kArticleSuggestionsFeature)); - SendBoolean("flag-recent-offline-tab-suggestions", - IsRecentTabProviderEnabled()); SendBoolean("flag-offlining-recent-pages-feature", base::FeatureList::IsEnabled( offline_pages::kOffliningRecentPagesFeature));
diff --git a/chrome/browser/ui/webui/web_dialog_web_contents_delegate_unittest.cc b/chrome/browser/ui/webui/web_dialog_web_contents_delegate_unittest.cc index b3d3f6a..5d7dea32 100644 --- a/chrome/browser/ui/webui/web_dialog_web_contents_delegate_unittest.cc +++ b/chrome/browser/ui/webui/web_dialog_web_contents_delegate_unittest.cc
@@ -89,8 +89,8 @@ } TEST_F(WebDialogWebContentsDelegateTest, AddNewContentsForegroundTabTest) { - std::unique_ptr<WebContents> contents = base::WrapUnique( - WebContentsTester::CreateTestWebContents(profile(), NULL)); + std::unique_ptr<WebContents> contents = + WebContentsTester::CreateTestWebContents(profile(), NULL); test_web_contents_delegate_->AddNewContents( NULL, std::move(contents), WindowOpenDisposition::NEW_FOREGROUND_TAB, gfx::Rect(), false, NULL);
diff --git a/chrome/browser/unload_browsertest.cc b/chrome/browser/unload_browsertest.cc index d78d3a3..ff81d2c9 100644 --- a/chrome/browser/unload_browsertest.cc +++ b/chrome/browser/unload_browsertest.cc
@@ -14,7 +14,6 @@ #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/net/url_request_mock_util.h" -#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_list.h" @@ -963,35 +962,6 @@ } IN_PROC_BROWSER_TEST_F(FastUnloadTest, - BrowserListForceCloseWithIncognitoProfileCloseProfiles) { - Profile* otr_profile = browser()->profile()->GetOffTheRecordProfile(); - Browser* otr_browser1 = CreateBrowser(otr_profile); - Browser* otr_browser2 = CreateBrowser(otr_profile); - content::WindowedNotificationObserver otr_browser1_observer( - chrome::NOTIFICATION_BROWSER_CLOSED, - content::Source<Browser>(otr_browser1)); - content::WindowedNotificationObserver otr_browser2_observer( - chrome::NOTIFICATION_BROWSER_CLOSED, - content::Source<Browser>(otr_browser2)); - UnloadResults unload_results; - BrowserList::CloseAllBrowsersWithIncognitoProfile( - otr_profile, - base::BindRepeating(&UnloadResults::AddSuccess, - base::Unretained(&unload_results)), - base::BindRepeating(&UnloadResults::AddAbort, - base::Unretained(&unload_results)), - true); - // Incognito browsers should be closed. - otr_browser1_observer.Wait(); - otr_browser2_observer.Wait(); - // Browser with original profile should not close. - EXPECT_EQ(1, browser()->tab_strip_model()->count()); - - EXPECT_EQ(1, unload_results.get_successes()); - EXPECT_EQ(0, unload_results.get_aborts()); -} - -IN_PROC_BROWSER_TEST_F(FastUnloadTest, BrowserListForceCloseAfterNormalCloseWithFastUnload) { NavigateToDataURL(BEFORE_UNLOAD_HTML, "beforeunload"); PrepareForDialog(browser());
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 635ba1a..78bdbc1 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1480,6 +1480,7 @@ "../browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc", "../browser/ui/views/extensions/media_galleries_dialog_views_browsertest.cc", "../browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc", + "../browser/ui/views/frame/browser_root_view_browsertest.cc", "../browser/ui/views/frame/browser_view_browsertest.cc", "../browser/ui/views/hung_renderer_view_browsertest.cc", "../browser/ui/views/location_bar/location_bar_view_browsertest.cc",
diff --git a/chrome/test/data/webui/cr_elements/cr_checkbox_test.js b/chrome/test/data/webui/cr_elements/cr_checkbox_test.js index d81c0e7..2d8d9827 100644 --- a/chrome/test/data/webui/cr_elements/cr_checkbox_test.js +++ b/chrome/test/data/webui/cr_elements/cr_checkbox_test.js
@@ -8,14 +8,14 @@ setup(function() { PolymerTest.clearBody(); document.body.innerHTML = ` - <cr-checkbox id="checkbox"> - <div id="label">label - <a id="link">link</a> + <cr-checkbox> + <div>label + <a>link</a> </div> </cr-checkbox> `; - checkbox = document.getElementById('checkbox'); + checkbox = document.querySelector('cr-checkbox'); assertNotChecked(); }); @@ -143,7 +143,7 @@ }); assertNotChecked(); - link = document.getElementById('link'); + link = document.querySelector('a'); link.click(); assertNotChecked(); @@ -153,4 +153,29 @@ // Wait 1 cycle to make sure change-event was not fired. setTimeout(done); }); + + test('InitializingWithTabindex', function() { + PolymerTest.clearBody(); + document.body.innerHTML = ` + <cr-checkbox id="checkbox" tabindex="-1"></cr-checkbox> + `; + + checkbox = document.querySelector('cr-checkbox'); + + // Should not override tabindex if it is initialized. + assertEquals(-1, checkbox.tabIndex); + }); + + + test('InitializingWithDisabled', function() { + PolymerTest.clearBody(); + document.body.innerHTML = ` + <cr-checkbox id="checkbox" disabled></cr-checkbox> + `; + + checkbox = document.querySelector('cr-checkbox'); + + // Initializing with disabled should make tabindex="-1". + assertEquals(-1, checkbox.tabIndex); + }); });
diff --git a/chrome/test/data/webui/print_preview/advanced_dialog_test.js b/chrome/test/data/webui/print_preview/advanced_dialog_test.js new file mode 100644 index 0000000..4beff9f --- /dev/null +++ b/chrome/test/data/webui/print_preview/advanced_dialog_test.js
@@ -0,0 +1,83 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.define('advanced_dialog_test', function() { + /** @enum {string} */ + const TestNames = { + AdvancedSettings1Option: 'advanced settings 1 option', + AdvancedSettings2Options: 'advanced settings 2 options', + }; + + const suiteName = 'AdvancedDialogTest'; + suite(suiteName, function() { + /** @type {?PrintPreviewAdvancedSettingsDialogElement} */ + let dialog = null; + + /** @type {?print_preview.Destination} */ + let destination = null; + + /** @type {string} */ + let printerId = 'FooDevice'; + + /** @type {string} */ + let printerName = 'FooName'; + + /** @override */ + setup(function() { + // Create destination + destination = new print_preview.Destination( + printerId, print_preview.DestinationType.GOOGLE, + print_preview.DestinationOrigin.COOKIES, printerName, + true /* isRecent */, + print_preview.DestinationConnectionStatus.ONLINE); + PolymerTest.clearBody(); + dialog = document.createElement('print-preview-advanced-dialog'); + }); + + /** + * Verifies that the search box is shown or hidden based on the number + * of capabilities and that the correct number of items are created. + * @param {number} count The number of vendor capabilities the printer + * should have. + */ + function testListWithItemCount(count) { + const template = + print_preview_test_utils.getCddTemplateWithAdvancedSettings( + count, printerId, printerName); + destination.capabilities = template.capabilities; + dialog.destination = destination; + + document.body.appendChild(dialog); + dialog.show(); + Polymer.dom.flush(); + + // Search box should be hidden if there is only 1 item. + const searchBox = dialog.$.searchBox; + assertEquals(count == 1, searchBox.hidden); + + // Verify item is displayed. + const vendorItems = template.capabilities.printer.vendor_capability; + const items = dialog.shadowRoot.querySelectorAll( + 'print-preview-advanced-settings-item'); + assertEquals(count, items.length); + } + + // Tests that the search box does not appear when there is only one option, + // and that the vendor item is correctly displayed. + test(assert(TestNames.AdvancedSettings1Option), function() { + testListWithItemCount(1); + }); + + // Tests that the search box appears when there are two options, and that + // the items are correctly displayed. + test(assert(TestNames.AdvancedSettings2Options), function() { + testListWithItemCount(2); + }); + }); + + return { + suiteName: suiteName, + TestNames: TestNames, + }; +});
diff --git a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js index d63a2e5..a93aed8 100644 --- a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js +++ b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js
@@ -519,3 +519,33 @@ function() { this.runMochaTest(destination_dialog_test.TestNames.PrinterList); }); + +PrintPreviewAdvancedDialogTest = class extends NewPrintPreviewTest { + /** @override */ + get browsePreload() { + return 'chrome://print/new/advanced_settings_dialog.html'; + } + + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + 'print_preview_test_utils.js', + 'advanced_dialog_test.js', + ]); + } + + /** @override */ + get suiteName() { + return advanced_dialog_test.suiteName; + } +}; + +TEST_F('PrintPreviewAdvancedDialogTest', 'AdvancedSettings1Option', + function() { + this.runMochaTest(advanced_dialog_test.TestNames.AdvancedSettings1Option); +}); + +TEST_F('PrintPreviewAdvancedDialogTest', 'AdvancedSettings2Options', + function() { + this.runMochaTest(advanced_dialog_test.TestNames.AdvancedSettings2Options); +});
diff --git a/chrome/test/data/webui/print_preview/print_preview_test_utils.js b/chrome/test/data/webui/print_preview/print_preview_test_utils.js index c324d80d..fe08bba 100644 --- a/chrome/test/data/webui/print_preview/print_preview_test_utils.js +++ b/chrome/test/data/webui/print_preview/print_preview_test_utils.js
@@ -86,6 +86,51 @@ } /** + * @param {number} numSettings + * @param {string} printerId + * @param {string=} opt_printerName Defaults to an empty string. + * @return {!print_preview.PrinterCapabilitiesResponse} + */ + function getCddTemplateWithAdvancedSettings( + numSettings, printerId, opt_printerName) { + const template = + print_preview_test_utils.getCddTemplate(printerId, opt_printerName); + if (numSettings < 1) + return template; + + template.capabilities.printer.vendor_capability = [{ + display_name: 'Print Area', + id: 'Print Area', + type: 'SELECT', + select_cap: { + option: [ + {display_name: 'A4', value: 4, is_default: true}, + {display_name: 'A6', value: 6}, + {display_name: 'A7', value: 7}, + ], + }, + }]; + + if (numSettings < 2) + return template; + + // Add new capability. + template.capabilities.printer.vendor_capability.push({ + display_name: 'Paper Type', + id: 'Paper Type', + type: 'SELECT', + select_cap: { + option: [ + {display_name: 'Standard', value: 0, is_default: true}, + {display_name: 'Recycled', value: 1}, + {display_name: 'Special', value: 2} + ] + } + }); + return template; + } + + /** * Creates a destination with a certificate status tag. * @param {string} id Printer id * @param {string} name Printer display name @@ -189,6 +234,7 @@ return { getDefaultInitialSettings: getDefaultInitialSettings, getCddTemplate: getCddTemplate, + getCddTemplateWithAdvancedSettings: getCddTemplateWithAdvancedSettings, getDefaultMediaSize: getDefaultMediaSize, getDefaultOrientation: getDefaultOrientation, createDestinationWithCertificateStatus:
diff --git a/chrome/test/data/webui/print_preview/print_preview_tests.js b/chrome/test/data/webui/print_preview/print_preview_tests.js index 6c9b9b17..32e3b37 100644 --- a/chrome/test/data/webui/print_preview/print_preview_tests.js +++ b/chrome/test/data/webui/print_preview/print_preview_tests.js
@@ -202,27 +202,6 @@ } /** - * @param {string} printerId - * @return {!Object} - */ - function getCddTemplateWithAdvancedSettings(printerId) { - const template = print_preview_test_utils.getCddTemplate(printerId); - template.capabilities.printer.vendor_capability = [{ - display_name: 'Print Area', - id: 'Print Area', - type: 'SELECT', - select_cap: { - option: [ - {display_name: 'A4', value: 4, is_default: true}, - {display_name: 'A6', value: 6}, - {display_name: 'A7', value: 7}, - ], - }, - }]; - return template; - } - - /** * Even though animation duration and delay is set to zero, it is necessary to * wait until the animation has finished. * @return {!Promise} A promise firing when the animation is done. @@ -1253,7 +1232,9 @@ // Test advanced settings with 1 capability (should not display settings // search box). test('AdvancedSettings1Option', function() { - const device = getCddTemplateWithAdvancedSettings('FooDevice'); + const device = + print_preview_test_utils.getCddTemplateWithAdvancedSettings( + 1, 'FooDevice'); return setupSettingsAndDestinationsWithCapabilities(device) .then(function() { startAdvancedSettingsTest(device); @@ -1264,24 +1245,12 @@ }); }); - // Test advanced settings with 2 capabilities (should have settings search // box). test('AdvancedSettings2Options', function() { - const device = getCddTemplateWithAdvancedSettings('FooDevice'); - // Add new capability. - device.capabilities.printer.vendor_capability.push({ - display_name: 'Paper Type', - id: 'Paper Type', - type: 'SELECT', - select_cap: { - option: [ - {display_name: 'Standard', value: 0, is_default: true}, - {display_name: 'Recycled', value: 1}, - {display_name: 'Special', value: 2} - ] - } - }); + const device = + print_preview_test_utils.getCddTemplateWithAdvancedSettings( + 2, 'FooDevice'); return setupSettingsAndDestinationsWithCapabilities(device) .then(function() { startAdvancedSettingsTest(device);
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 7ee235ff..ea66bbc5 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -10645.0.0 \ No newline at end of file +10651.0.0 \ No newline at end of file
diff --git a/chromeos/components/tether/host_scan_scheduler_impl.cc b/chromeos/components/tether/host_scan_scheduler_impl.cc index 2220577..0d17098 100644 --- a/chromeos/components/tether/host_scan_scheduler_impl.cc +++ b/chromeos/components/tether/host_scan_scheduler_impl.cc
@@ -86,7 +86,7 @@ } void HostScanSchedulerImpl::ScheduleScan() { - EnsureScan(); + AttemptScan(); } void HostScanSchedulerImpl::DefaultNetworkChanged(const NetworkState* network) { @@ -102,12 +102,12 @@ // NetworkStateHandlerObservers are finished running. Processing the // network change immediately can cause crashes; see https://crbug.com/800370. task_runner_->PostTask(FROM_HERE, - base::BindOnce(&HostScanSchedulerImpl::EnsureScan, + base::BindOnce(&HostScanSchedulerImpl::AttemptScan, weak_ptr_factory_.GetWeakPtr())); } void HostScanSchedulerImpl::ScanRequested() { - EnsureScan(); + AttemptScan(); } void HostScanSchedulerImpl::ScanFinished() { @@ -142,7 +142,7 @@ delay_scan_after_unlock_timer_->Start( FROM_HERE, base::TimeDelta::FromSeconds(kNumSecondsToDelayScanAfterUnlock), - base::Bind(&HostScanSchedulerImpl::EnsureScan, + base::Bind(&HostScanSchedulerImpl::AttemptScan, weak_ptr_factory_.GetWeakPtr())); } @@ -158,10 +158,18 @@ task_runner_ = test_task_runner; } -void HostScanSchedulerImpl::EnsureScan() { +void HostScanSchedulerImpl::AttemptScan() { + // If already scanning, there is nothing to do. if (host_scanner_->IsScanActive()) return; + // If the screen is locked, a host scan should not occur. A scan during the + // lock screen could cause bad interactions with EasyUnlock. See + // https://crbug.com/763604. + // Note: Once the SecureChannel API is available, this check can be removed. + if (session_manager_->IsScreenLocked()) + return; + // If the timer is running, this new scan is part of the same batch as the // previous scan, so the timer should be stopped (it will be restarted after // the new scan finishes). If the timer is not running, the new scan is part
diff --git a/chromeos/components/tether/host_scan_scheduler_impl.h b/chromeos/components/tether/host_scan_scheduler_impl.h index d8cd7c6..3e5ab26 100644 --- a/chromeos/components/tether/host_scan_scheduler_impl.h +++ b/chromeos/components/tether/host_scan_scheduler_impl.h
@@ -63,7 +63,7 @@ private: friend class HostScanSchedulerImplTest; - void EnsureScan(); + void AttemptScan(); bool IsTetherNetworkConnectingOrConnected(); void LogHostScanBatchMetric();
diff --git a/chromeos/components/tether/host_scan_scheduler_impl_unittest.cc b/chromeos/components/tether/host_scan_scheduler_impl_unittest.cc index 8b35b59a..4cae5d13 100644 --- a/chromeos/components/tether/host_scan_scheduler_impl_unittest.cc +++ b/chromeos/components/tether/host_scan_scheduler_impl_unittest.cc
@@ -191,12 +191,18 @@ VerifyScanDuration(5u /* expected_num_sections */); } -TEST_F(HostScanSchedulerImplTest, ScansWhenDeviceUnlocked) { +TEST_F(HostScanSchedulerImplTest, TestDeviceLockAndUnlock) { // Lock the screen. This should not trigger a scan. SetScreenLockedState(true /* is_locked */); EXPECT_EQ(0u, fake_host_scanner_->num_scans_started()); EXPECT_FALSE(mock_delay_scan_after_unlock_timer_->IsRunning()); + // Try to start a scan. Because the screen is locked, this should not actually + // cause a scan to be started. + host_scan_scheduler_->ScheduleScan(); + EXPECT_EQ(0u, fake_host_scanner_->num_scans_started()); + EXPECT_FALSE(mock_delay_scan_after_unlock_timer_->IsRunning()); + // Unlock the screen. A scan should not yet have been started, but the timer // should have. SetScreenLockedState(false /* is_locked */);
diff --git a/chromeos/login/auth/extended_authenticator.h b/chromeos/login/auth/extended_authenticator.h index cfef8e59..89e937d 100644 --- a/chromeos/login/auth/extended_authenticator.h +++ b/chromeos/login/auth/extended_authenticator.h
@@ -15,8 +15,6 @@ #include "chromeos/chromeos_export.h" #include "chromeos/cryptohome/cryptohome_parameters.h" -class AccountId; - namespace chromeos { class AuthStatusConsumer; @@ -70,16 +68,6 @@ virtual void AuthenticateToCheck(const UserContext& context, const base::Closure& success_callback) = 0; - // This call will create and mount the home dir for |account_id| with the - // given |keys| if the home dir is missing. If the home dir exists already, a - // mount attempt will be performed using the first key in |keys| for - // authentication. Note that all |keys| should have been transformed from - // plain text already. - // This method does not alter them. - virtual void CreateMount(const AccountId& account_id, - const std::vector<cryptohome::KeyDefinition>& keys, - const ResultCallback& success_callback) = 0; - // Attempts to add a new |key| for the user identified/authorized by // |context|. If a key with the same label already exists, the behavior // depends on the |replace_existing| flag. If the flag is set, the old key is
diff --git a/chromeos/login/auth/extended_authenticator_impl.cc b/chromeos/login/auth/extended_authenticator_impl.cc index 7f4a6d5..06fcdc5 100644 --- a/chromeos/login/auth/extended_authenticator_impl.cc +++ b/chromeos/login/auth/extended_authenticator_impl.cc
@@ -82,33 +82,6 @@ success_callback)); } -void ExtendedAuthenticatorImpl::CreateMount( - const AccountId& account_id, - const std::vector<cryptohome::KeyDefinition>& keys, - const ResultCallback& success_callback) { - RecordStartMarker("MountEx"); - - cryptohome::Identification id(account_id); - cryptohome::MountRequest mount; - for (size_t i = 0; i < keys.size(); i++) { - cryptohome::KeyDefinitionToKey(keys[i], mount.mutable_create()->add_keys()); - } - UserContext context(account_id); - Key key(keys.front().secret); - key.SetLabel(keys.front().label); - context.SetKey(key); - cryptohome::AuthorizationRequest auth; - cryptohome::Key* auth_key = auth.mutable_key(); - if (!key.GetLabel().empty()) { - auth_key->mutable_data()->set_label(key.GetLabel()); - } - auth_key->set_secret(key.GetSecret()); - DBusThreadManager::Get()->GetCryptohomeClient()->MountEx( - id, auth, mount, - base::BindOnce(&ExtendedAuthenticatorImpl::OnMountComplete, this, - "MountEx", context, success_callback)); -} - void ExtendedAuthenticatorImpl::AddKey(const UserContext& context, const cryptohome::KeyDefinition& key, bool clobber_if_exists,
diff --git a/chromeos/login/auth/extended_authenticator_impl.h b/chromeos/login/auth/extended_authenticator_impl.h index 7c086da..2b88201 100644 --- a/chromeos/login/auth/extended_authenticator_impl.h +++ b/chromeos/login/auth/extended_authenticator_impl.h
@@ -17,8 +17,6 @@ #include "chromeos/login/auth/extended_authenticator.h" #include "third_party/cros_system_api/dbus/service_constants.h" -class AccountId; - namespace chromeos { class AuthStatusConsumer; @@ -36,9 +34,6 @@ const ResultCallback& success_callback) override; void AuthenticateToCheck(const UserContext& context, const base::Closure& success_callback) override; - void CreateMount(const AccountId& account_id, - const std::vector<cryptohome::KeyDefinition>& keys, - const ResultCallback& success_callback) override; void AddKey(const UserContext& context, const cryptohome::KeyDefinition& key, bool clobber_if_exists,
diff --git a/chromeos/login/auth/fake_extended_authenticator.cc b/chromeos/login/auth/fake_extended_authenticator.cc index 656e164..3824690 100644 --- a/chromeos/login/auth/fake_extended_authenticator.cc +++ b/chromeos/login/auth/fake_extended_authenticator.cc
@@ -64,13 +64,6 @@ AuthFailure(AuthFailure::UNLOCK_FAILED)); } -void FakeExtendedAuthenticator::CreateMount( - const AccountId& account_id, - const std::vector<cryptohome::KeyDefinition>& keys, - const ResultCallback& success_callback) { - NOTREACHED(); -} - void FakeExtendedAuthenticator::AddKey(const UserContext& context, const cryptohome::KeyDefinition& key, bool replace_existing,
diff --git a/chromeos/login/auth/fake_extended_authenticator.h b/chromeos/login/auth/fake_extended_authenticator.h index ee48944..39a58a4 100644 --- a/chromeos/login/auth/fake_extended_authenticator.h +++ b/chromeos/login/auth/fake_extended_authenticator.h
@@ -10,8 +10,6 @@ #include "chromeos/login/auth/extended_authenticator.h" #include "chromeos/login/auth/user_context.h" -class AccountId; - namespace chromeos { class AuthFailure; @@ -29,9 +27,6 @@ const ResultCallback& success_callback) override; void AuthenticateToCheck(const UserContext& context, const base::Closure& success_callback) override; - void CreateMount(const AccountId& account_id, - const std::vector<cryptohome::KeyDefinition>& keys, - const ResultCallback& success_callback) override; void AddKey(const UserContext& context, const cryptohome::KeyDefinition& key, bool replace_existing,
diff --git a/chromeos/login/auth/login_performer.cc b/chromeos/login/auth/login_performer.cc index 570a9b4d..31fe394 100644 --- a/chromeos/login/auth/login_performer.cc +++ b/chromeos/login/auth/login_performer.cc
@@ -182,7 +182,10 @@ gaia::ExtractDomainName(user_context.GetAccountId().GetUserEmail())); user_context_ = user_context; - user_context_.SetUserType(user_manager::USER_TYPE_SUPERVISED); + if (user_context_.GetUserType() != user_manager::USER_TYPE_SUPERVISED) { + LOG(FATAL) << "Incorrect supervised user type " + << user_context_.GetUserType(); + } if (RunTrustedCheck(base::Bind(&LoginPerformer::TrustedLoginAsSupervisedUser, weak_factory_.GetWeakPtr(),
diff --git a/chromeos/login/auth/user_context.cc b/chromeos/login/auth/user_context.cc index 8447f06..1e58b8c9 100644 --- a/chromeos/login/auth/user_context.cc +++ b/chromeos/login/auth/user_context.cc
@@ -3,19 +3,35 @@ // found in the LICENSE file. #include "chromeos/login/auth/user_context.h" +#include "components/user_manager/user_manager.h" #include "components/user_manager/user_names.h" namespace chromeos { +namespace { + +user_manager::UserType CalculateUserType(const AccountId& account_id) { + // UserManager is not initialized in unit tests. + if (!user_manager::UserManager::IsInitialized()) + return user_manager::USER_TYPE_REGULAR; + + if (user_manager::UserManager::Get()->IsSupervisedAccountId(account_id)) + return user_manager::USER_TYPE_SUPERVISED; + + if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY) + return user_manager::USER_TYPE_ACTIVE_DIRECTORY; + + return user_manager::USER_TYPE_REGULAR; +} + +} // anonymous namespace + UserContext::UserContext() : account_id_(EmptyAccountId()) {} UserContext::UserContext(const UserContext& other) = default; UserContext::UserContext(const AccountId& account_id) - : account_id_(account_id) { - account_id_.SetUserEmail( - user_manager::CanonicalizeUserID(account_id.GetUserEmail())); -} + : UserContext(CalculateUserType(account_id), account_id) {} UserContext::UserContext(user_manager::UserType user_type, const AccountId& account_id) @@ -183,10 +199,6 @@ auth_flow_ = auth_flow; } -void UserContext::SetUserType(user_manager::UserType user_type) { - user_type_ = user_type; -} - void UserContext::SetPublicSessionLocale(const std::string& locale) { public_session_locale_ = locale; }
diff --git a/chromeos/login/auth/user_context.h b/chromeos/login/auth/user_context.h index c279e975..26d1f7e 100644 --- a/chromeos/login/auth/user_context.h +++ b/chromeos/login/auth/user_context.h
@@ -95,7 +95,6 @@ void SetIsUsingPin(bool is_using_pin); void SetIsForcingDircrypto(bool is_forcing_dircrypto); void SetAuthFlow(AuthFlow auth_flow); - void SetUserType(user_manager::UserType user_type); void SetPublicSessionLocale(const std::string& locale); void SetPublicSessionInputMethod(const std::string& input_method); void SetDeviceId(const std::string& device_id);
diff --git a/components/assist_ranker/print_example_preprocessor_config.py b/components/assist_ranker/print_example_preprocessor_config.py new file mode 100755 index 0000000..5e35a0f1 --- /dev/null +++ b/components/assist_ranker/print_example_preprocessor_config.py
@@ -0,0 +1,97 @@ +#!/usr/bin/env python2 + +# 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. + +"""Dumps info from a ExamplePreprocessorConfig protobuf file. + +Prints feature names, types, and bucket values. +""" + +import os +import sys +import textwrap +from enum import Enum +from google.protobuf import text_format + +class FeatureType(Enum): + CATEGORICAL = 'categorical' + BUCKETED = 'bucketed' + SCALAR = 'scalar' + + +def ReadConfig(pb_file): + """Parses the protobuf containing the example preprocessor config.""" + import example_preprocessor_pb2 + config = example_preprocessor_pb2.ExamplePreprocessorConfig() + with open(pb_file) as pb: + config.ParseFromString(pb.read()) + return config + + +def PrintExamplePreprocessorConfig(pb_file): + """Prints the features listed the example preprocessor config.""" + config = ReadConfig(pb_file) + + features = set() + for feature_index in sorted(config.feature_indices): + # For string or string list feature types, remove the "_value" suffix to get + # the base name. + name_parts = feature_index.split('_') + base_name = name_parts[0] + # Skip additional values of the same base name. + if base_name in features: + continue + + features.add(base_name) + if len(name_parts) == 1: + feature_type = FeatureType.SCALAR + elif base_name in config.bucketizers: + feature_type = FeatureType.BUCKETED + else: + feature_type = FeatureType.CATEGORICAL + description = '* %s (%s)' % (base_name, feature_type.value) + + if feature_type == FeatureType.BUCKETED: + description += ':\n\t' + boundaries = config.bucketizers[base_name].boundaries + bucket_str = ', '.join(['%.1f' % bucket for bucket in boundaries]) + + # Indent description by a tab and wrap text. + max_len = 80 - 8 # Leave at least 8 columns for tab width. + description += ('\n\t').join(textwrap.wrap(bucket_str, max_len)) + print description + return 0 + + +def Main(args): + if len(args) != 2: + print 'Usage: %s <out_dir> <path/to/example_preprocessor_config.pb>' % ( + __file__) + return 1 + + out_dir = args[0] + if not os.path.isdir(out_dir): + print 'Could not find out directory: %s' % out_dir + return 1 + + pb_file = args[1] + if not os.path.isfile(pb_file): + print 'Protobuf file not found: %s' % pb_file + return 1 + + proto_dir = os.path.join(out_dir, 'pyproto/components/assist_ranker/proto') + if not os.path.isdir(proto_dir): + print 'Proto directory not found: %s' % proto_dir + print 'Build the "components/assist_ranker/proto" target' + print ' (usually built with chrome)' + return 1 + + # Allow importing the ExamplePreprocessorConfig proto definition. + sys.path.insert(0, proto_dir) + PrintExamplePreprocessorConfig(pb_file) + + +if __name__ == '__main__': + sys.exit(Main(sys.argv[1:]))
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn index 8bb028d..ebf5410 100644 --- a/components/cronet/android/BUILD.gn +++ b/components/cronet/android/BUILD.gn
@@ -1555,7 +1555,6 @@ deps = [ ":api_static_checks", ":copy_cronet_java8_jars", - ":cronet_maven_modules", ":cronet_package_copy", ":cronet_package_copy_native_lib", ":cronet_package_copy_native_lib_unstripped",
diff --git a/components/guest_view/browser/guest_view_manager_unittest.cc b/components/guest_view/browser/guest_view_manager_unittest.cc index 654efcb..45ebeda 100644 --- a/components/guest_view/browser/guest_view_manager_unittest.cc +++ b/components/guest_view/browser/guest_view_manager_unittest.cc
@@ -27,8 +27,7 @@ ~GuestViewManagerTest() override {} std::unique_ptr<WebContents> CreateWebContents() { - return std::unique_ptr<WebContents>( - WebContentsTester::CreateTestWebContents(browser_context(), nullptr)); + return WebContentsTester::CreateTestWebContents(browser_context(), nullptr); } private:
diff --git a/components/ntp_snippets/BUILD.gn b/components/ntp_snippets/BUILD.gn index c431ec90..12cc9175 100644 --- a/components/ntp_snippets/BUILD.gn +++ b/components/ntp_snippets/BUILD.gn
@@ -69,8 +69,6 @@ "logger.h", "ntp_snippets_constants.cc", "ntp_snippets_constants.h", - "offline_pages/recent_tab_suggestions_provider.cc", - "offline_pages/recent_tab_suggestions_provider.h", "pref_names.cc", "pref_names.h", "pref_util.cc", @@ -156,8 +154,6 @@ "//components/metrics", "//components/ntp_snippets/remote/proto", "//components/offline_pages/core", - "//components/offline_pages/core/downloads:offline_pages_ui_adapter", - "//components/offline_pages/core/recent_tabs", "//components/reading_list/core", "//components/sessions", "//components/strings", @@ -216,7 +212,6 @@ "contextual/contextual_suggestions_metrics_reporter_unittest.cc", "contextual/contextual_suggestions_ukm_entry_unittest.cc", "logger_unittest.cc", - "offline_pages/recent_tab_suggestions_provider_unittest.cc", "reading_list/reading_list_suggestions_provider_unittest.cc", "remote/cached_image_fetcher_unittest.cc", "remote/json_request_unittest.cc", @@ -257,8 +252,6 @@ "//components/offline_pages/core", "//components/offline_pages/core:test_support", "//components/offline_pages/core/background:test_support", - "//components/offline_pages/core/downloads:offline_pages_ui_adapter", - "//components/offline_pages/core/recent_tabs", "//components/prefs:test_support", "//components/reading_list/core", "//components/sessions",
diff --git a/components/ntp_snippets/category.h b/components/ntp_snippets/category.h index 506d51f..d421049 100644 --- a/components/ntp_snippets/category.h +++ b/components/ntp_snippets/category.h
@@ -20,7 +20,7 @@ // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp.snippets enum class KnownCategories { // Pages recently downloaded during normal navigation. - RECENT_TABS, + RECENT_TABS_DEPRECATED, // Pages downloaded by the user for offline consumption. DOWNLOADS,
diff --git a/components/ntp_snippets/category_rankers/click_based_category_ranker_unittest.cc b/components/ntp_snippets/category_rankers/click_based_category_ranker_unittest.cc index c8e8843..bdc779d1 100644 --- a/components/ntp_snippets/category_rankers/click_based_category_ranker_unittest.cc +++ b/components/ntp_snippets/category_rankers/click_based_category_ranker_unittest.cc
@@ -609,9 +609,6 @@ // Make sure we have the default order. EXPECT_TRUE(CompareCategories( Category::FromKnownCategory(KnownCategories::DOWNLOADS), - Category::FromKnownCategory(KnownCategories::RECENT_TABS))); - EXPECT_TRUE(CompareCategories( - Category::FromKnownCategory(KnownCategories::RECENT_TABS), Category::FromKnownCategory(KnownCategories::FOREIGN_TABS))); EXPECT_TRUE(CompareCategories( Category::FromKnownCategory(KnownCategories::FOREIGN_TABS), @@ -642,22 +639,22 @@ ShouldResumePromotionAfter2WeeksSinceDismissal) { const Category downloads = Category::FromKnownCategory(KnownCategories::DOWNLOADS); - const Category recent_tabs = - Category::FromKnownCategory(KnownCategories::RECENT_TABS); - ASSERT_TRUE(CompareCategories(downloads, recent_tabs)); + const Category foreign_tabs = + Category::FromKnownCategory(KnownCategories::FOREIGN_TABS); + ASSERT_TRUE(CompareCategories(downloads, foreign_tabs)); - SetPromotedCategoryVariationParam(recent_tabs.id()); + SetPromotedCategoryVariationParam(foreign_tabs.id()); ResetRanker(base::DefaultClock::GetInstance()); - ASSERT_TRUE(CompareCategories(recent_tabs, downloads)); + ASSERT_TRUE(CompareCategories(foreign_tabs, downloads)); - ranker()->OnCategoryDismissed(recent_tabs); - ASSERT_FALSE(CompareCategories(recent_tabs, downloads)); + ranker()->OnCategoryDismissed(foreign_tabs); + ASSERT_FALSE(CompareCategories(foreign_tabs, downloads)); // Simulate a little over 2 weeks of time passing. base::SimpleTestClock test_clock; test_clock.SetNow(base::Time::Now() + base::TimeDelta::FromDays(15)); ResetRanker(&test_clock); - EXPECT_TRUE(CompareCategories(recent_tabs, downloads)); + EXPECT_TRUE(CompareCategories(foreign_tabs, downloads)); } TEST_F(ClickBasedCategoryRankerTest,
diff --git a/components/ntp_snippets/category_rankers/constant_category_ranker.cc b/components/ntp_snippets/category_rankers/constant_category_ranker.cc index 40c7e1e4b..00a6ae3 100644 --- a/components/ntp_snippets/category_rankers/constant_category_ranker.cc +++ b/components/ntp_snippets/category_rankers/constant_category_ranker.cc
@@ -124,7 +124,6 @@ case CategoryOrderChoice::GENERAL: categories.push_back(KnownCategories::READING_LIST); categories.push_back(KnownCategories::DOWNLOADS); - categories.push_back(KnownCategories::RECENT_TABS); categories.push_back(KnownCategories::FOREIGN_TABS); categories.push_back(KnownCategories::BOOKMARKS); categories.push_back(KnownCategories::ARTICLES); @@ -135,7 +134,6 @@ categories.push_back(KnownCategories::DOWNLOADS); categories.push_back(KnownCategories::BOOKMARKS); - categories.push_back(KnownCategories::RECENT_TABS); categories.push_back(KnownCategories::FOREIGN_TABS); break; }
diff --git a/components/ntp_snippets/content_suggestion.cc b/components/ntp_snippets/content_suggestion.cc index c3919f7c..5dd75b9 100644 --- a/components/ntp_snippets/content_suggestion.cc +++ b/components/ntp_snippets/content_suggestion.cc
@@ -57,12 +57,6 @@ download_suggestion_extra_ = std::move(download_suggestion_extra); } -void ContentSuggestion::set_recent_tab_suggestion_extra( - std::unique_ptr<RecentTabSuggestionExtra> recent_tab_suggestion_extra) { - DCHECK(id_.category().IsKnownCategory(KnownCategories::RECENT_TABS)); - recent_tab_suggestion_extra_ = std::move(recent_tab_suggestion_extra); -} - void ContentSuggestion::set_reading_list_suggestion_extra( std::unique_ptr<ReadingListSuggestionExtra> reading_list_suggestion_extra) { DCHECK(id_.category().IsKnownCategory(KnownCategories::READING_LIST));
diff --git a/components/ntp_snippets/content_suggestion.h b/components/ntp_snippets/content_suggestion.h index b6cf3f4..0dca371 100644 --- a/components/ntp_snippets/content_suggestion.h +++ b/components/ntp_snippets/content_suggestion.h
@@ -40,14 +40,6 @@ bool is_download_asset = false; }; -// Contains additional data which is only available for recent tab suggestions. -struct RecentTabSuggestionExtra { - // Corresponding tab identifier. - int tab_id; - // Underlying offline page identifier. - int64_t offline_page_id = 0; -}; - // ReadingListSuggestionExtra contains additional data which is only available // for Reading List suggestions. struct ReadingListSuggestionExtra { @@ -163,14 +155,6 @@ void set_download_suggestion_extra( std::unique_ptr<DownloadSuggestionExtra> download_suggestion_extra); - // Extra information for recent tab suggestions. Only available for - // KnownCategories::RECENT_TABS suggestions. - RecentTabSuggestionExtra* recent_tab_suggestion_extra() const { - return recent_tab_suggestion_extra_.get(); - } - void set_recent_tab_suggestion_extra( - std::unique_ptr<RecentTabSuggestionExtra> recent_tab_suggestion_extra); - // Extra information for reading list suggestions. Only available for // KnownCategories::READING_LIST suggestions. ReadingListSuggestionExtra* reading_list_suggestion_extra() const { @@ -213,7 +197,6 @@ base::string16 publisher_name_; float score_; std::unique_ptr<DownloadSuggestionExtra> download_suggestion_extra_; - std::unique_ptr<RecentTabSuggestionExtra> recent_tab_suggestion_extra_; std::unique_ptr<ReadingListSuggestionExtra> reading_list_suggestion_extra_; std::unique_ptr<NotificationExtra> notification_extra_;
diff --git a/components/ntp_snippets/content_suggestions_metrics.cc b/components/ntp_snippets/content_suggestions_metrics.cc index 6c0fe3d5..2b7e3ca 100644 --- a/components/ntp_snippets/content_suggestions_metrics.cc +++ b/components/ntp_snippets/content_suggestions_metrics.cc
@@ -81,7 +81,7 @@ // sync with ContentSuggestionsCategory in histograms.xml. enum class HistogramCategories { EXPERIMENTAL, - RECENT_TABS, + RECENT_TABS_DEPRECATED, DOWNLOADS, BOOKMARKS, PHYSICAL_WEB_PAGES_DEPRECATED, @@ -104,8 +104,6 @@ // listed here. auto known_category = static_cast<KnownCategories>(category.id()); switch (known_category) { - case KnownCategories::RECENT_TABS: - return HistogramCategories::RECENT_TABS; case KnownCategories::DOWNLOADS: return HistogramCategories::DOWNLOADS; case KnownCategories::BOOKMARKS: @@ -118,6 +116,7 @@ return HistogramCategories::READING_LIST; case KnownCategories::CONTEXTUAL: return HistogramCategories::CONTEXTUAL; + case KnownCategories::RECENT_TABS_DEPRECATED: case KnownCategories::PHYSICAL_WEB_PAGES_DEPRECATED: case KnownCategories::LOCAL_CATEGORIES_COUNT: case KnownCategories::REMOTE_CATEGORIES_OFFSET: @@ -133,8 +132,6 @@ std::string GetCategorySuffix(Category category) { HistogramCategories histogram_category = GetHistogramCategory(category); switch (histogram_category) { - case HistogramCategories::RECENT_TABS: - return "RecentTabs"; case HistogramCategories::DOWNLOADS: return "Downloads"; case HistogramCategories::BOOKMARKS: @@ -149,6 +146,7 @@ return "ReadingList"; case HistogramCategories::CONTEXTUAL: return "Contextual"; + case HistogramCategories::RECENT_TABS_DEPRECATED: case HistogramCategories::PHYSICAL_WEB_PAGES_DEPRECATED: case HistogramCategories::COUNT: NOTREACHED();
diff --git a/components/ntp_snippets/features.cc b/components/ntp_snippets/features.cc index 2fd237d2..5c3942e 100644 --- a/components/ntp_snippets/features.cc +++ b/components/ntp_snippets/features.cc
@@ -32,7 +32,6 @@ &kKeepPrefetchedContentSuggestions, &kNotificationsFeature, &kPublisherFaviconsFromNewServerFeature, - &kRecentOfflineTabSuggestionsFeature, &kRemoteSuggestionsBackendFeature, nullptr}; @@ -45,9 +44,6 @@ const base::Feature kBookmarkSuggestionsFeature{ "NTPBookmarkSuggestions", base::FEATURE_ENABLED_BY_DEFAULT}; -const base::Feature kRecentOfflineTabSuggestionsFeature{ - "NTPOfflinePageSuggestions", base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kIncreasedVisibility{"NTPSnippetsIncreasedVisibility", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/components/ntp_snippets/features.h b/components/ntp_snippets/features.h index b2dda46..8b4ac0e 100644 --- a/components/ntp_snippets/features.h +++ b/components/ntp_snippets/features.h
@@ -33,7 +33,6 @@ // helpers in chrome/browser/ntp_snippets/dependent_features.h instead. extern const base::Feature kBookmarkSuggestionsFeature; -extern const base::Feature kRecentOfflineTabSuggestionsFeature; extern const base::Feature kForeignSessionsSuggestionsFeature; ////////////////////////////////////////////////////////////////////////////////
diff --git a/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.cc b/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.cc deleted file mode 100644 index 8c64425f..0000000 --- a/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.cc +++ /dev/null
@@ -1,329 +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. - -#include "components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.h" - -#include <algorithm> -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_task_runner_handle.h" -#include "components/ntp_snippets/features.h" -#include "components/ntp_snippets/pref_names.h" -#include "components/ntp_snippets/pref_util.h" -#include "components/offline_pages/core/client_policy_controller.h" -#include "components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/prefs/pref_service.h" -#include "components/strings/grit/components_strings.h" -#include "components/variations/variations_associated_data.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/gfx/image/image.h" - -using offline_pages::ClientId; -using offline_pages::DownloadUIAdapter; - -namespace ntp_snippets { - -namespace { - -const int kDefaultMaxSuggestionsCount = 5; - -const char* kMaxSuggestionsCountParamName = "recent_tabs_max_count"; - -int GetMaxSuggestionsCount() { - return variations::GetVariationParamByFeatureAsInt( - kRecentOfflineTabSuggestionsFeature, kMaxSuggestionsCountParamName, - kDefaultMaxSuggestionsCount); -} - -struct OrderUIItemsByMostRecentlyCreatedFirst { - bool operator()(const OfflineItem& left, const OfflineItem& right) const { - return left.creation_time > right.creation_time; - } -}; - -struct OrderUIItemsByUrlAndThenMostRecentlyCreatedFirst { - bool operator()(const OfflineItem& left, const OfflineItem& right) const { - if (left.page_url != right.page_url) { - return left.page_url < right.page_url; - } - return left.creation_time > right.creation_time; - } -}; - -} // namespace - -RecentTabSuggestionsProvider::RecentTabSuggestionsProvider( - ContentSuggestionsProvider::Observer* observer, - offline_pages::DownloadUIAdapter* ui_adapter, - PrefService* pref_service) - : ContentSuggestionsProvider(observer), - category_status_(CategoryStatus::AVAILABLE_LOADING), - provided_category_( - Category::FromKnownCategory(KnownCategories::RECENT_TABS)), - recent_tabs_ui_adapter_(ui_adapter), - pref_service_(pref_service), - weak_ptr_factory_(this) { - observer->OnCategoryStatusChanged(this, provided_category_, category_status_); - recent_tabs_ui_adapter_->AddObserver(this); -} - -RecentTabSuggestionsProvider::~RecentTabSuggestionsProvider() { - recent_tabs_ui_adapter_->RemoveObserver(this); -} - -CategoryStatus RecentTabSuggestionsProvider::GetCategoryStatus( - Category category) { - if (category == provided_category_) { - return category_status_; - } - NOTREACHED() << "Unknown category " << category.id(); - return CategoryStatus::NOT_PROVIDED; -} - -CategoryInfo RecentTabSuggestionsProvider::GetCategoryInfo(Category category) { - DCHECK_EQ(provided_category_, category); - return CategoryInfo( - l10n_util::GetStringUTF16(IDS_NTP_RECENT_TAB_SUGGESTIONS_SECTION_HEADER), - ContentSuggestionsCardLayout::MINIMAL_CARD, - ContentSuggestionsAdditionalAction::NONE, - /*show_if_empty=*/false, - l10n_util::GetStringUTF16(IDS_NTP_RECENT_TAB_SUGGESTIONS_SECTION_EMPTY)); -} - -void RecentTabSuggestionsProvider::DismissSuggestion( - const ContentSuggestion::ID& suggestion_id) { - DCHECK_EQ(provided_category_, suggestion_id.category()); - std::set<std::string> dismissed_ids = ReadDismissedIDsFromPrefs(); - dismissed_ids.insert(suggestion_id.id_within_category()); - StoreDismissedIDsToPrefs(dismissed_ids); -} - -void RecentTabSuggestionsProvider::FetchSuggestionImage( - const ContentSuggestion::ID& suggestion_id, - ImageFetchedCallback callback) { - // TODO(vitaliii): Fetch proper thumbnail from OfflinePageModel once it's - // available there. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), gfx::Image())); -} - -void RecentTabSuggestionsProvider::FetchSuggestionImageData( - const ContentSuggestion::ID& suggestion_id, - ImageDataFetchedCallback callback) { - // TODO(vitaliii): Fetch proper thumbnail from OfflinePageModel once it's - // available there. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), std::string())); -} - -void RecentTabSuggestionsProvider::Fetch( - const Category& category, - const std::set<std::string>& known_suggestion_ids, - FetchDoneCallback callback) { - LOG(DFATAL) << "RecentTabSuggestionsProvider has no |Fetch| functionality!"; - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce( - std::move(callback), - Status(StatusCode::PERMANENT_ERROR, - "RecentTabSuggestionsProvider has no |Fetch| functionality!"), - std::vector<ContentSuggestion>())); -} - -void RecentTabSuggestionsProvider::ClearHistory( - base::Time begin, - base::Time end, - const base::Callback<bool(const GURL& url)>& filter) { - ClearDismissedSuggestionsForDebugging(provided_category_); - FetchRecentTabs(); -} - -void RecentTabSuggestionsProvider::ClearCachedSuggestions() { - // Ignored. -} - -void RecentTabSuggestionsProvider::GetDismissedSuggestionsForDebugging( - Category category, - DismissedSuggestionsCallback callback) { - DCHECK_EQ(provided_category_, category); - recent_tabs_ui_adapter_->GetAllItems(base::BindOnce( - &RecentTabSuggestionsProvider::OnGetDismissedSuggestionsForDebuggingDone, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); -} - -void RecentTabSuggestionsProvider::OnGetDismissedSuggestionsForDebuggingDone( - DismissedSuggestionsCallback callback, - const std::vector<OfflineItem>& offline_items) { - std::set<std::string> dismissed_ids = ReadDismissedIDsFromPrefs(); - std::vector<ContentSuggestion> suggestions; - for (const OfflineItem& item : offline_items) { - int64_t offline_page_id = - recent_tabs_ui_adapter_->GetOfflineIdByGuid(item.id.id); - if (!dismissed_ids.count(base::IntToString(offline_page_id))) { - continue; - } - - suggestions.push_back(ConvertUIItem(item)); - } - - std::move(callback).Run(std::move(suggestions)); -} - -void RecentTabSuggestionsProvider::ClearDismissedSuggestionsForDebugging( - Category category) { - DCHECK_EQ(provided_category_, category); - StoreDismissedIDsToPrefs(std::set<std::string>()); - FetchRecentTabs(); -} - -// static -void RecentTabSuggestionsProvider::RegisterProfilePrefs( - PrefRegistrySimple* registry) { - registry->RegisterListPref(prefs::kDismissedRecentOfflineTabSuggestions); -} - -//////////////////////////////////////////////////////////////////////////////// -// Private methods - -void RecentTabSuggestionsProvider::OnItemsAdded( - const std::vector<OfflineItem>& items) { - FetchRecentTabs(); -} - -void RecentTabSuggestionsProvider::OnItemUpdated(const OfflineItem& item) { - FetchRecentTabs(); -} - -void RecentTabSuggestionsProvider::OnItemRemoved(const ContentId& id) { - // Because we never switch to NOT_PROVIDED dynamically, there can be no open - // UI containing an invalidated suggestion unless the status is something - // other than NOT_PROVIDED, so only notify invalidation in that case. - if (category_status_ != CategoryStatus::NOT_PROVIDED) { - InvalidateSuggestion(id.id); - } -} - -void RecentTabSuggestionsProvider::FetchRecentTabs() { - recent_tabs_ui_adapter_->GetAllItems( - base::BindOnce(&RecentTabSuggestionsProvider::OnFetchRecentTabsDone, - weak_ptr_factory_.GetWeakPtr())); -} - -void RecentTabSuggestionsProvider::OnFetchRecentTabsDone( - const std::vector<OfflineItem>& offline_items) { - NotifyStatusChanged(CategoryStatus::AVAILABLE); - std::set<std::string> old_dismissed_ids = ReadDismissedIDsFromPrefs(); - std::set<std::string> new_dismissed_ids; - std::vector<OfflineItem> non_dismissed_items; - - for (const OfflineItem& item : offline_items) { - std::string offline_page_id = base::IntToString( - recent_tabs_ui_adapter_->GetOfflineIdByGuid(item.id.id)); - if (old_dismissed_ids.count(offline_page_id)) { - new_dismissed_ids.insert(offline_page_id); - } else { - non_dismissed_items.push_back(item); - } - } - - observer()->OnNewSuggestions( - this, provided_category_, - GetMostRecentlyCreatedWithoutDuplicates(non_dismissed_items)); - if (new_dismissed_ids.size() != old_dismissed_ids.size()) { - StoreDismissedIDsToPrefs(new_dismissed_ids); - } -} - -void RecentTabSuggestionsProvider::NotifyStatusChanged( - CategoryStatus new_status) { - DCHECK_NE(CategoryStatus::NOT_PROVIDED, category_status_); - if (category_status_ == new_status) { - return; - } - category_status_ = new_status; - observer()->OnCategoryStatusChanged(this, provided_category_, new_status); -} - -ContentSuggestion RecentTabSuggestionsProvider::ConvertUIItem( - const OfflineItem& ui_item) const { - // UI items have the Tab ID embedded in the GUID and the offline ID is - // available by querying. - int64_t offline_page_id = - recent_tabs_ui_adapter_->GetOfflineIdByGuid(ui_item.id.id); - ContentSuggestion suggestion( - provided_category_, base::IntToString(offline_page_id), ui_item.page_url); - suggestion.set_title(base::UTF8ToUTF16(ui_item.title)); - suggestion.set_publish_date(ui_item.creation_time); - suggestion.set_publisher_name(base::UTF8ToUTF16(ui_item.page_url.host())); - auto extra = std::make_unique<RecentTabSuggestionExtra>(); - int tab_id; - bool success = base::StringToInt(ui_item.id.id, &tab_id); - DCHECK(success); - extra->tab_id = tab_id; - extra->offline_page_id = offline_page_id; - suggestion.set_recent_tab_suggestion_extra(std::move(extra)); - - return suggestion; -} - -std::vector<ContentSuggestion> -RecentTabSuggestionsProvider::GetMostRecentlyCreatedWithoutDuplicates( - std::vector<OfflineItem>& ui_items) const { - // |std::unique| only removes duplicates that immediately follow each other. - // Thus, first, we have to sort by URL and creation time and only then remove - // duplicates and sort the remaining items by creation time. - std::sort(ui_items.begin(), ui_items.end(), - OrderUIItemsByUrlAndThenMostRecentlyCreatedFirst()); - std::vector<OfflineItem>::iterator new_end = - std::unique(ui_items.begin(), ui_items.end(), - [](const OfflineItem& left, const OfflineItem& right) { - return left.page_url == right.page_url; - }); - ui_items.erase(new_end, ui_items.end()); - std::sort(ui_items.begin(), ui_items.end(), - OrderUIItemsByMostRecentlyCreatedFirst()); - std::vector<ContentSuggestion> suggestions; - for (const OfflineItem& ui_item : ui_items) { - suggestions.push_back(ConvertUIItem(ui_item)); - if (static_cast<int>(suggestions.size()) == GetMaxSuggestionsCount()) { - break; - } - } - return suggestions; -} - -void RecentTabSuggestionsProvider::InvalidateSuggestion( - const std::string& ui_item_guid) { - std::string offline_page_id = base::IntToString( - recent_tabs_ui_adapter_->GetOfflineIdByGuid(ui_item_guid)); - observer()->OnSuggestionInvalidated( - this, ContentSuggestion::ID(provided_category_, offline_page_id)); - - std::set<std::string> dismissed_ids = ReadDismissedIDsFromPrefs(); - auto it = dismissed_ids.find(offline_page_id); - if (it != dismissed_ids.end()) { - dismissed_ids.erase(it); - StoreDismissedIDsToPrefs(dismissed_ids); - } -} - -std::set<std::string> RecentTabSuggestionsProvider::ReadDismissedIDsFromPrefs() - const { - return prefs::ReadDismissedIDsFromPrefs( - *pref_service_, prefs::kDismissedRecentOfflineTabSuggestions); -} - -void RecentTabSuggestionsProvider::StoreDismissedIDsToPrefs( - const std::set<std::string>& dismissed_ids) { - prefs::StoreDismissedIDsToPrefs(pref_service_, - prefs::kDismissedRecentOfflineTabSuggestions, - dismissed_ids); -} - -} // namespace ntp_snippets
diff --git a/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.h b/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.h deleted file mode 100644 index 2c8c11e..0000000 --- a/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.h +++ /dev/null
@@ -1,119 +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 COMPONENTS_NTP_SNIPPETS_OFFLINE_PAGES_RECENT_TAB_SUGGESTIONS_PROVIDER_H_ -#define COMPONENTS_NTP_SNIPPETS_OFFLINE_PAGES_RECENT_TAB_SUGGESTIONS_PROVIDER_H_ - -#include <set> -#include <string> -#include <vector> - -#include "base/callback_forward.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/time/time.h" -#include "components/ntp_snippets/category.h" -#include "components/ntp_snippets/category_status.h" -#include "components/ntp_snippets/content_suggestion.h" -#include "components/ntp_snippets/content_suggestions_provider.h" -#include "components/offline_pages/core/downloads/download_ui_adapter.h" -#include "components/offline_pages/core/offline_page_model.h" - -class PrefRegistrySimple; -class PrefService; - -using ContentId = offline_items_collection::ContentId; -using OfflineItem = offline_items_collection::OfflineItem; -using OfflineContentProvider = offline_items_collection::OfflineContentProvider; - -namespace ntp_snippets { - -// Provides recent tabs content suggestions from the offline pages model. -class RecentTabSuggestionsProvider : public ContentSuggestionsProvider, - public OfflineContentProvider::Observer { - public: - RecentTabSuggestionsProvider(ContentSuggestionsProvider::Observer* observer, - offline_pages::DownloadUIAdapter* ui_adapter, - PrefService* pref_service); - ~RecentTabSuggestionsProvider() override; - - // ContentSuggestionsProvider implementation. - CategoryStatus GetCategoryStatus(Category category) override; - CategoryInfo GetCategoryInfo(Category category) override; - void DismissSuggestion(const ContentSuggestion::ID& suggestion_id) override; - void FetchSuggestionImage(const ContentSuggestion::ID& suggestion_id, - ImageFetchedCallback callback) override; - void FetchSuggestionImageData(const ContentSuggestion::ID& suggestion_id, - ImageDataFetchedCallback callback) override; - void Fetch(const Category& category, - const std::set<std::string>& known_suggestion_ids, - FetchDoneCallback callback) override; - void ClearHistory( - base::Time begin, - base::Time end, - const base::Callback<bool(const GURL& url)>& filter) override; - void ClearCachedSuggestions() override; - void GetDismissedSuggestionsForDebugging( - Category category, - DismissedSuggestionsCallback callback) override; - void ClearDismissedSuggestionsForDebugging(Category category) override; - - static void RegisterProfilePrefs(PrefRegistrySimple* registry); - - private: - friend class RecentTabSuggestionsProviderTestNoLoad; - - // OfflineContentProvider::Observer implementation. - void OnItemsAdded(const std::vector<OfflineItem>& items) override; - void OnItemRemoved(const ContentId& id) override; - void OnItemUpdated(const OfflineItem& item) override; - - // Updates the |category_status_| of the |provided_category_| and notifies the - // |observer_|, if necessary. - void NotifyStatusChanged(CategoryStatus new_status); - - // Manually requests all Recent Tabs UI items and updates the suggestions. - void FetchRecentTabs(); - void OnFetchRecentTabsDone(const std::vector<OfflineItem>& offline_items); - - void OnGetDismissedSuggestionsForDebuggingDone( - DismissedSuggestionsCallback callback, - const std::vector<OfflineItem>& offline_items); - - // Converts an OfflineItem to a ContentSuggestion for the - // |provided_category_|. - ContentSuggestion ConvertUIItem(const OfflineItem& ui_item) const; - - // Removes duplicates for the same URL leaving only the most recently created - // items, returns at most |GetMaxSuggestionsCount()| ContentSuggestions - // corresponding to the remaining items, sorted by creation time (newer - // first). - std::vector<ContentSuggestion> GetMostRecentlyCreatedWithoutDuplicates( - std::vector<OfflineItem>& ui_items) const; - - // Fires the |OnSuggestionInvalidated| event for the suggestion corresponding - // to the given |offline_id| and deletes it from the dismissed IDs list, if - // necessary. - void InvalidateSuggestion(const std::string& ui_item_guid); - - // Reads dismissed IDs from Prefs. - std::set<std::string> ReadDismissedIDsFromPrefs() const; - - // Writes |dismissed_ids| into Prefs. - void StoreDismissedIDsToPrefs(const std::set<std::string>& dismissed_ids); - - CategoryStatus category_status_; - const Category provided_category_; - offline_pages::DownloadUIAdapter* recent_tabs_ui_adapter_; - - PrefService* pref_service_; - - base::WeakPtrFactory<RecentTabSuggestionsProvider> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(RecentTabSuggestionsProvider); -}; - -} // namespace ntp_snippets - -#endif // COMPONENTS_NTP_SNIPPETS_OFFLINE_PAGES_RECENT_TAB_SUGGESTIONS_PROVIDER_H_
diff --git a/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc b/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc deleted file mode 100644 index 504a61f..0000000 --- a/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc +++ /dev/null
@@ -1,464 +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. - -#include "components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.h" - -#include <memory> -#include <string> -#include <vector> - -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/strings/string_number_conversions.h" -#include "base/test/test_simple_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "components/ntp_snippets/category.h" -#include "components/ntp_snippets/content_suggestions_provider.h" -#include "components/ntp_snippets/mock_content_suggestions_provider_observer.h" -#include "components/ntp_snippets/offline_pages/offline_pages_test_utils.h" -#include "components/offline_pages/core/background/request_coordinator_stub_taco.h" -#include "components/offline_pages/core/client_namespace_constants.h" -#include "components/offline_pages/core/downloads/download_ui_adapter.h" -#include "components/offline_pages/core/offline_page_item.h" -#include "components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.h" -#include "components/prefs/testing_pref_service.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ntp_snippets::test::CaptureDismissedSuggestions; -using ntp_snippets::test::FakeOfflinePageModel; -using offline_pages::ClientId; -using offline_pages::MultipleOfflinePageItemCallback; -using offline_pages::OfflinePageItem; -using testing::_; -using testing::IsEmpty; -using testing::Mock; -using testing::Property; -using testing::SizeIs; - -namespace ntp_snippets { - -namespace { - -const int64_t kSystemDownloadId = 0; - -OfflinePageItem CreateDummyRecentTab(int offline_id) { - // This is used to assign unique tab IDs to pages. Since offline IDs are - // typically small integers like 1, 2, 3 etc, we start at 1001 to ensure that - // they are different, and can catch bugs where offline page ID is used in - // place of tab ID and vice versa. - std::string tab_id = base::IntToString(offline_id + 1000); - ClientId client_id(offline_pages::kLastNNamespace, tab_id); - return test::CreateDummyOfflinePageItem(offline_id, client_id); -} - -std::vector<OfflinePageItem> CreateDummyRecentTabs( - const std::vector<int>& ids) { - std::vector<OfflinePageItem> result; - for (int id : ids) { - result.push_back(CreateDummyRecentTab(id)); - } - return result; -} - -OfflinePageItem CreateDummyRecentTab(int id, base::Time time) { - OfflinePageItem item = CreateDummyRecentTab(id); - item.creation_time = time; - item.last_access_time = time; - return item; -} - -void GetAllItemsDummyCallback(const std::vector<OfflineItem>& items) {} - -} // namespace - -class RecentTabSuggestionsProviderTestNoLoad : public testing::Test { - public: - RecentTabSuggestionsProviderTestNoLoad() - : task_runner_(new base::TestSimpleTaskRunner()), - task_runner_handle_(task_runner_), - pref_service_(new TestingPrefServiceSimple()) { - RecentTabSuggestionsProvider::RegisterProfilePrefs( - pref_service()->registry()); - - taco_ = std::make_unique<offline_pages::RequestCoordinatorStubTaco>(); - taco_->CreateRequestCoordinator(); - - ui_adapter_ = offline_pages::RecentTabsUIAdapterDelegate:: - GetOrCreateRecentTabsUIAdapter(&model_, taco_->request_coordinator()); - delegate_ = - offline_pages::RecentTabsUIAdapterDelegate::FromDownloadUIAdapter( - ui_adapter_); - provider_ = std::make_unique<RecentTabSuggestionsProvider>( - &observer_, ui_adapter_, pref_service()); - // Force adapter to load its cache. - ui_adapter_->GetAllItems(base::BindOnce(&GetAllItemsDummyCallback)); - provider_->FetchRecentTabs(); - } - - Category recent_tabs_category() { - return Category::FromKnownCategory(KnownCategories::RECENT_TABS); - } - - ContentSuggestion::ID GetDummySuggestionId(int id) { - return ContentSuggestion::ID(recent_tabs_category(), base::IntToString(id)); - } - - void AddTabAndOfflinePageToModel(const OfflinePageItem& item) { - AddTab(offline_pages::RecentTabsUIAdapterDelegate::TabIdFromClientId( - item.client_id)); - AddOfflinePageToModel(item); - } - - void AddTab(int tab_id) { delegate_->RegisterTab(tab_id); } - - void RemoveTab(int tab_id) { delegate_->UnregisterTab(tab_id); } - - void AddOfflinePageToModel(const OfflinePageItem& item) { - ui_adapter_->OfflinePageAdded(&model_, item); - } - - void FireOfflinePageDeleted(const OfflinePageItem& item) { - int tab_id = offline_pages::RecentTabsUIAdapterDelegate::TabIdFromClientId( - item.client_id); - RemoveTab(tab_id); - ui_adapter_->OfflinePageDeleted( - offline_pages::OfflinePageModel::DeletedPageInfo( - item.offline_id, kSystemDownloadId, item.client_id, - "" /* request_origin */)); - } - - std::set<std::string> ReadDismissedIDsFromPrefs() { - return provider_->ReadDismissedIDsFromPrefs(); - } - - RecentTabSuggestionsProvider* provider() { return provider_.get(); } - MockContentSuggestionsProviderObserver* observer() { return &observer_; } - TestingPrefServiceSimple* pref_service() { return pref_service_.get(); } - base::TestSimpleTaskRunner* task_runner() { return task_runner_.get(); } - - private: - FakeOfflinePageModel model_; - offline_pages::DownloadUIAdapter* ui_adapter_; - offline_pages::RecentTabsUIAdapterDelegate* delegate_; - scoped_refptr<base::TestSimpleTaskRunner> task_runner_; - base::ThreadTaskRunnerHandle task_runner_handle_; - std::unique_ptr<offline_pages::RequestCoordinatorStubTaco> taco_; - MockContentSuggestionsProviderObserver observer_; - std::unique_ptr<TestingPrefServiceSimple> pref_service_; - // Last so that the dependencies are deleted after the provider. - std::unique_ptr<RecentTabSuggestionsProvider> provider_; - - DISALLOW_COPY_AND_ASSIGN(RecentTabSuggestionsProviderTestNoLoad); -}; - -// Test that always loads the model before the start of the test. -class RecentTabSuggestionsProviderTest - : public RecentTabSuggestionsProviderTestNoLoad { - public: - RecentTabSuggestionsProviderTest() = default; - - void SetUp() override { - // The UI adapter always fires asynchronously upon loading, so we want to - // run past that moment before each test. Expect a call to hide warnings. - EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(1); - task_runner()->RunUntilIdle(); - Mock::VerifyAndClearExpectations(observer()); - } - - private: - DISALLOW_COPY_AND_ASSIGN(RecentTabSuggestionsProviderTest); -}; - -TEST_F(RecentTabSuggestionsProviderTest, ShouldConvertToSuggestions) { - EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(2); - EXPECT_CALL( - *observer(), - OnNewSuggestions( - _, recent_tabs_category(), - UnorderedElementsAre( - Property(&ContentSuggestion::url, GURL("http://dummy.com/1")), - Property(&ContentSuggestion::url, GURL("http://dummy.com/2")), - Property(&ContentSuggestion::url, GURL("http://dummy.com/3"))))); - - auto recent_tabs_list = CreateDummyRecentTabs({1, 2, 3}); - for (OfflinePageItem& recent_tab : recent_tabs_list) { - AddTabAndOfflinePageToModel(recent_tab); - } - task_runner()->RunUntilIdle(); -} - -TEST_F(RecentTabSuggestionsProviderTest, ShouldSortByCreationTime) { - base::Time now = base::Time::Now(); - base::Time yesterday = now - base::TimeDelta::FromDays(1); - base::Time tomorrow = now + base::TimeDelta::FromDays(1); - - std::vector<OfflinePageItem> offline_pages = { - CreateDummyRecentTab(1, now), CreateDummyRecentTab(2, yesterday), - CreateDummyRecentTab(3, tomorrow)}; - - EXPECT_CALL( - *observer(), - OnNewSuggestions(_, recent_tabs_category(), - ElementsAre(Property(&ContentSuggestion::url, - GURL("http://dummy.com/1"))))); - AddTabAndOfflinePageToModel(CreateDummyRecentTab(1, now)); - task_runner()->RunUntilIdle(); - - EXPECT_CALL( - *observer(), - OnNewSuggestions( - _, recent_tabs_category(), - ElementsAre( - Property(&ContentSuggestion::url, GURL("http://dummy.com/1")), - Property(&ContentSuggestion::url, GURL("http://dummy.com/2"))))); - AddTabAndOfflinePageToModel(CreateDummyRecentTab(2, yesterday)); - task_runner()->RunUntilIdle(); - - offline_pages[1].last_access_time = - offline_pages[0].last_access_time + base::TimeDelta::FromHours(1); - - EXPECT_CALL( - *observer(), - OnNewSuggestions( - _, recent_tabs_category(), - ElementsAre( - Property(&ContentSuggestion::url, GURL("http://dummy.com/3")), - Property(&ContentSuggestion::url, GURL("http://dummy.com/1")), - Property(&ContentSuggestion::url, GURL("http://dummy.com/2"))))); - AddTabAndOfflinePageToModel(CreateDummyRecentTab(3, tomorrow)); - task_runner()->RunUntilIdle(); -} - -TEST_F(RecentTabSuggestionsProviderTest, ShouldDeliverCorrectCategoryInfo) { - EXPECT_EQ( - ContentSuggestionsAdditionalAction::NONE, - provider()->GetCategoryInfo(recent_tabs_category()).additional_action()); -} - -// TODO(vitaliii): Break this test into multiple tests. Currently if it fails, -// it takes long time to find which part of it actually fails. -TEST_F(RecentTabSuggestionsProviderTest, ShouldDismiss) { - EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(3); - auto recent_tabs_list = CreateDummyRecentTabs({1, 2, 3}); - for (OfflinePageItem& recent_tab : recent_tabs_list) { - AddTabAndOfflinePageToModel(recent_tab); - } - task_runner()->RunUntilIdle(); - - // Dismiss 2 and 3. - EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(0); - provider()->DismissSuggestion(GetDummySuggestionId(2)); - provider()->DismissSuggestion(GetDummySuggestionId(3)); - Mock::VerifyAndClearExpectations(observer()); - - // They should disappear from the reported suggestions. - EXPECT_CALL( - *observer(), - OnNewSuggestions( - _, recent_tabs_category(), - UnorderedElementsAre( - Property(&ContentSuggestion::url, GURL("http://dummy.com/1")), - Property(&ContentSuggestion::url, GURL("http://dummy.com/4"))))); - - AddTabAndOfflinePageToModel(CreateDummyRecentTab(4)); - task_runner()->RunUntilIdle(); - Mock::VerifyAndClearExpectations(observer()); - - // And appear in the dismissed suggestions. - std::vector<ContentSuggestion> dismissed_suggestions; - provider()->GetDismissedSuggestionsForDebugging( - recent_tabs_category(), - base::Bind(&CaptureDismissedSuggestions, &dismissed_suggestions)); - task_runner()->RunUntilIdle(); - EXPECT_THAT( - dismissed_suggestions, - UnorderedElementsAre( - Property(&ContentSuggestion::url, GURL("http://dummy.com/2")), - Property(&ContentSuggestion::url, GURL("http://dummy.com/3")))); - - // Clear dismissed suggestions. - provider()->ClearDismissedSuggestionsForDebugging(recent_tabs_category()); - task_runner()->RunUntilIdle(); - - // They should be gone from the dismissed suggestions. - dismissed_suggestions.clear(); - provider()->GetDismissedSuggestionsForDebugging( - recent_tabs_category(), - base::Bind(&CaptureDismissedSuggestions, &dismissed_suggestions)); - task_runner()->RunUntilIdle(); - EXPECT_THAT(dismissed_suggestions, IsEmpty()); - - // And appear in the reported suggestions for the category again. - EXPECT_CALL(*observer(), - OnNewSuggestions(_, recent_tabs_category(), SizeIs(5))); - AddTabAndOfflinePageToModel(CreateDummyRecentTab(5)); - task_runner()->RunUntilIdle(); - Mock::VerifyAndClearExpectations(observer()); -} - -TEST_F(RecentTabSuggestionsProviderTest, - ShouldInvalidateWhenOfflinePageDeleted) { - EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(3); - std::vector<OfflinePageItem> offline_pages = CreateDummyRecentTabs({1, 2, 3}); - for (OfflinePageItem& recent_tab : offline_pages) - AddTabAndOfflinePageToModel(recent_tab); - task_runner()->RunUntilIdle(); - - // Invalidation of suggestion 2 should be forwarded. - EXPECT_CALL(*observer(), OnSuggestionInvalidated(_, GetDummySuggestionId(2))); - FireOfflinePageDeleted(offline_pages[1]); -} - -TEST_F(RecentTabSuggestionsProviderTest, ShouldClearDismissedOnInvalidate) { - EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(3); - std::vector<OfflinePageItem> offline_pages = CreateDummyRecentTabs({1, 2, 3}); - for (OfflinePageItem& recent_tab : offline_pages) - AddTabAndOfflinePageToModel(recent_tab); - task_runner()->RunUntilIdle(); - EXPECT_THAT(ReadDismissedIDsFromPrefs(), IsEmpty()); - - provider()->DismissSuggestion(GetDummySuggestionId(2)); - EXPECT_THAT(ReadDismissedIDsFromPrefs(), SizeIs(1)); - - FireOfflinePageDeleted(offline_pages[1]); - EXPECT_THAT(ReadDismissedIDsFromPrefs(), IsEmpty()); -} - -TEST_F(RecentTabSuggestionsProviderTest, ShouldClearDismissedOnFetch) { - EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(3); - std::vector<OfflinePageItem> offline_pages = CreateDummyRecentTabs({1, 2, 3}); - for (OfflinePageItem& recent_tab : offline_pages) - AddTabAndOfflinePageToModel(recent_tab); - task_runner()->RunUntilIdle(); - - provider()->DismissSuggestion(GetDummySuggestionId(2)); - provider()->DismissSuggestion(GetDummySuggestionId(3)); - EXPECT_THAT(ReadDismissedIDsFromPrefs(), SizeIs(2)); - - FireOfflinePageDeleted(offline_pages[0]); - FireOfflinePageDeleted(offline_pages[2]); - EXPECT_THAT(ReadDismissedIDsFromPrefs(), SizeIs(1)); - - FireOfflinePageDeleted(offline_pages[1]); - EXPECT_THAT(ReadDismissedIDsFromPrefs(), IsEmpty()); -} - -TEST_F(RecentTabSuggestionsProviderTest, ShouldNotShowSameUrlMutlipleTimes) { - base::Time now = base::Time::Now(); - base::Time yesterday = now - base::TimeDelta::FromDays(1); - base::Time tomorrow = now + base::TimeDelta::FromDays(1); - std::vector<OfflinePageItem> offline_pages = { - CreateDummyRecentTab(1, yesterday), CreateDummyRecentTab(2, now), - CreateDummyRecentTab(3, tomorrow)}; - - // We leave IDs different, but make the URLs the same. - offline_pages[2].url = offline_pages[0].url; - - AddTabAndOfflinePageToModel(offline_pages[0]); - AddTabAndOfflinePageToModel(offline_pages[1]); - task_runner()->RunUntilIdle(); - Mock::VerifyAndClearExpectations(observer()); - EXPECT_CALL(*observer(), - OnNewSuggestions( - _, recent_tabs_category(), - UnorderedElementsAre( - Property(&ContentSuggestion::publish_date, now), - Property(&ContentSuggestion::publish_date, tomorrow)))); - - AddTabAndOfflinePageToModel(offline_pages[2]); - task_runner()->RunUntilIdle(); -} - -TEST_F(RecentTabSuggestionsProviderTest, - ShouldNotFetchIfAddedOfflinePageIsNotRecentTab) { - // It should not fetch when not a recent tab is added, thus, it should not - // report the first recent tab (which it is not aware about). - EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(0); - AddOfflinePageToModel(ntp_snippets::test::CreateDummyOfflinePageItem( - 2, offline_pages::kDefaultNamespace)); -} - -TEST_F(RecentTabSuggestionsProviderTest, - ShouldInvalidateSuggestionWhenTabGone) { - OfflinePageItem first_tab = CreateDummyRecentTab(1); - AddTabAndOfflinePageToModel(first_tab); - task_runner()->RunUntilIdle(); - Mock::VerifyAndClearExpectations(observer()); - - EXPECT_CALL(*observer(), OnSuggestionInvalidated(_, GetDummySuggestionId(1))) - .Times(1); - RemoveTab(offline_pages::RecentTabsUIAdapterDelegate::TabIdFromClientId( - first_tab.client_id)); - // Removing an unknown tab should not cause extra invalidations. - RemoveTab(42); -} - -TEST_F(RecentTabSuggestionsProviderTest, ShouldNotShowPagesWithoutTab) { - EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(0); - // The provider is not notified about the first recent tab yet (no tab). - OfflinePageItem first_tab = CreateDummyRecentTab(1); - AddOfflinePageToModel(first_tab); - - Mock::VerifyAndClearExpectations(observer()); - EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(1); - EXPECT_CALL( - *observer(), - OnNewSuggestions( - _, recent_tabs_category(), - UnorderedElementsAre( - Property(&ContentSuggestion::url, GURL("http://dummy.com/1")), - Property(&ContentSuggestion::url, GURL("http://dummy.com/2"))))); - - AddTab(offline_pages::RecentTabsUIAdapterDelegate::TabIdFromClientId( - first_tab.client_id)); - OfflinePageItem second_tab = CreateDummyRecentTab(2); - AddTabAndOfflinePageToModel(second_tab); - task_runner()->RunUntilIdle(); - - Mock::VerifyAndClearExpectations(observer()); - - EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(0); - // |RemoveTab| by itself doesn't cause OnNewSuggestions to be called. - RemoveTab(offline_pages::RecentTabsUIAdapterDelegate::TabIdFromClientId( - second_tab.client_id)); - Mock::VerifyAndClearExpectations(observer()); - - // But when we get another tab, OnNewSuggestions will be called. - EXPECT_CALL( - *observer(), - OnNewSuggestions( - _, recent_tabs_category(), - UnorderedElementsAre( - Property(&ContentSuggestion::url, GURL("http://dummy.com/1")), - Property(&ContentSuggestion::url, GURL("http://dummy.com/3"))))); - - AddTabAndOfflinePageToModel(CreateDummyRecentTab(3)); - task_runner()->RunUntilIdle(); -} - -// The following test uses a different fixture that does not automatically pump -// the event loop in SetUp, which means that until |RunUntilIdle| is called, the -// UI adapter will not be loaded (and should not fire any events). - -TEST_F(RecentTabSuggestionsProviderTestNoLoad, ShouldFetchOnLoad) { - // Tabs are added to the model before the UI adapter is loaded, so there - // should only be a single |OnNewSuggestions| call, at load time. - EXPECT_CALL( - *observer(), - OnNewSuggestions( - _, recent_tabs_category(), - UnorderedElementsAre( - Property(&ContentSuggestion::url, GURL("http://dummy.com/1")), - Property(&ContentSuggestion::url, GURL("http://dummy.com/2"))))); - - AddTabAndOfflinePageToModel(CreateDummyRecentTab(1)); - AddTabAndOfflinePageToModel(CreateDummyRecentTab(2)); - // The provider is not notified about the recent tabs yet. - task_runner()->RunUntilIdle(); - // However, it must return both tabs when the model is loaded. -} - -} // namespace ntp_snippets
diff --git a/components/ntp_snippets/pref_names.cc b/components/ntp_snippets/pref_names.cc index 3ae3397..f9dc7d3 100644 --- a/components/ntp_snippets/pref_names.cc +++ b/components/ntp_snippets/pref_names.cc
@@ -57,8 +57,6 @@ "ntp_suggestions.foreign_sessions.dismissed_ids"; const char kDismissedOfflinePageDownloadSuggestions[] = "ntp_suggestions.downloads.offline_pages.dismissed_ids"; -const char kDismissedRecentOfflineTabSuggestions[] = - "ntp_suggestions.offline_pages.recent_tabs.dismissed_ids"; const char kDismissedCategories[] = "ntp_suggestions.dismissed_categories";
diff --git a/components/ntp_snippets/pref_names.h b/components/ntp_snippets/pref_names.h index ac4f3765..7e26cc8 100644 --- a/components/ntp_snippets/pref_names.h +++ b/components/ntp_snippets/pref_names.h
@@ -69,7 +69,6 @@ extern const char kDismissedAssetDownloadSuggestions[]; extern const char kDismissedForeignSessionsSuggestions[]; extern const char kDismissedOfflinePageDownloadSuggestions[]; -extern const char kDismissedRecentOfflineTabSuggestions[]; extern const char kDismissedCategories[];
diff --git a/components/ntp_snippets/remote/remote_suggestion_unittest.cc b/components/ntp_snippets/remote/remote_suggestion_unittest.cc index 118d019..868bb0b 100644 --- a/components/ntp_snippets/remote/remote_suggestion_unittest.cc +++ b/components/ntp_snippets/remote/remote_suggestion_unittest.cc
@@ -281,7 +281,6 @@ EXPECT_THAT(sugg.publisher_name(), Eq(base::UTF8ToUTF16("Foo News"))); EXPECT_THAT(sugg.score(), Eq(9001)); EXPECT_THAT(sugg.download_suggestion_extra(), IsNull()); - EXPECT_THAT(sugg.recent_tab_suggestion_extra(), IsNull()); EXPECT_THAT(sugg.notification_extra(), IsNull()); EXPECT_THAT(sugg.fetch_date(), Eq(fetch_date)); } @@ -306,7 +305,6 @@ EXPECT_THAT(sugg.publisher_name(), Eq(base::UTF8ToUTF16("Foo News"))); EXPECT_THAT(sugg.score(), Eq(9001)); EXPECT_THAT(sugg.download_suggestion_extra(), IsNull()); - EXPECT_THAT(sugg.recent_tab_suggestion_extra(), IsNull()); ASSERT_THAT(sugg.notification_extra(), NotNull()); EXPECT_THAT(sugg.notification_extra()->deadline.ToJavaTime(), Eq(1467291697000));
diff --git a/components/offline_pages/content/background_loader/background_loader_contents_stub.cc b/components/offline_pages/content/background_loader/background_loader_contents_stub.cc index c5df23d..9941397c 100644 --- a/components/offline_pages/content/background_loader/background_loader_contents_stub.cc +++ b/components/offline_pages/content/background_loader/background_loader_contents_stub.cc
@@ -13,9 +13,9 @@ BackgroundLoaderContentsStub::BackgroundLoaderContentsStub( content::BrowserContext* browser_context) : BackgroundLoaderContents(), is_loading_(false) { - BackgroundLoaderContents::web_contents_.reset( + BackgroundLoaderContents::web_contents_ = content::WebContentsTester::CreateTestWebContents(browser_context, - nullptr)); + nullptr); web_contents_.get()->SetDelegate(this); }
diff --git a/components/offline_pages/core/BUILD.gn b/components/offline_pages/core/BUILD.gn index bd8d10f9..b2f88908 100644 --- a/components/offline_pages/core/BUILD.gn +++ b/components/offline_pages/core/BUILD.gn
@@ -191,7 +191,6 @@ ":switches", ":test_support", "prefetch:unit_tests", - "recent_tabs:unit_tests", "renovations:unit_tests", "//base", "//base/test:test_support",
diff --git a/components/offline_pages/core/model/offline_page_model_taskified.cc b/components/offline_pages/core/model/offline_page_model_taskified.cc index 0c7605a..a9a580f 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified.cc +++ b/components/offline_pages/core/model/offline_page_model_taskified.cc
@@ -619,6 +619,9 @@ .pages_allowed_per_url != kUnlimitedPages) { RemovePagesMatchingUrlAndNamespace(page_attempted); } + offline_event_logger_.RecordPageSaved(page_attempted.client_id.name_space, + page_attempted.url.spec(), + page_attempted.offline_id); } ScheduleMaintenanceTasks(); } @@ -647,6 +650,7 @@ "OfflinePages.DeletePageCount", model_utils::ToNamespaceEnum(info.client_id.name_space), OfflinePagesNamespaceEnumeration::RESULT_COUNT); + offline_event_logger_.RecordPageDeleted(info.offline_id); for (Observer& observer : observers_) observer.OfflinePageDeleted(info); if (info.system_download_id != 0)
diff --git a/components/offline_pages/core/offline_page_model_event_logger.cc b/components/offline_pages/core/offline_page_model_event_logger.cc index 695d355..63ae0ba 100644 --- a/components/offline_pages/core/offline_page_model_event_logger.cc +++ b/components/offline_pages/core/offline_page_model_event_logger.cc
@@ -18,20 +18,4 @@ RecordActivity("Page with ID " + id_str + " has been deleted"); } -void OfflinePageModelEventLogger::RecordPageExpired(int64_t offline_id) { - std::string id_str = std::to_string(offline_id); - RecordActivity("Page with ID " + id_str + " has been expired"); -} - -void OfflinePageModelEventLogger::RecordStoreClearError() { - RecordActivity("Offline store clear failed"); -} - -void OfflinePageModelEventLogger::RecordStoreCleared() { - RecordActivity("Offline store cleared"); -} - -void OfflinePageModelEventLogger::RecordStoreReloadError() { - RecordActivity("There was an error reloading the offline store"); -} } // namespace offline_pages
diff --git a/components/offline_pages/core/offline_page_model_event_logger.h b/components/offline_pages/core/offline_page_model_event_logger.h index ae3a05a6..f976dd2 100644 --- a/components/offline_pages/core/offline_page_model_event_logger.h +++ b/components/offline_pages/core/offline_page_model_event_logger.h
@@ -19,18 +19,6 @@ // Records that a page with |offline_id| has been deleted. void RecordPageDeleted(int64_t offline_id); - - // Records that a page with |offline_id| has been expired. - void RecordPageExpired(int64_t offline_id); - - // Records that the offline store has been cleared. - void RecordStoreCleared(); - - // Records that there was an error when clearing the offline store. - void RecordStoreClearError(); - - // Records that there was an error when reloading the offline store. - void RecordStoreReloadError(); }; } // namespace offline_pages
diff --git a/components/offline_pages/core/offline_page_model_event_logger_unittest.cc b/components/offline_pages/core/offline_page_model_event_logger_unittest.cc index 5f7b690..d416c938 100644 --- a/components/offline_pages/core/offline_page_model_event_logger_unittest.cc +++ b/components/offline_pages/core/offline_page_model_event_logger_unittest.cc
@@ -17,11 +17,6 @@ const char kPageSaved[] = "http://www.wikipedia.org is saved at last_n with id 12345"; const char kPageDeleted[] = "Page with ID 12345 has been deleted"; -const char kPageExpired[] = "Page with ID 12345 has been expired"; -const char kRecordStoreClearError[] = "Offline store clear failed"; -const char kRecordStoreCleared[] = "Offline store cleared"; -const char kRecordStoreReloadError[] = - "There was an error reloading the offline store"; } // namespace @@ -30,21 +25,13 @@ std::vector<std::string> log; logger.SetIsLogging(true); - logger.RecordStoreCleared(); logger.RecordPageSaved(kNamespace, kUrl, kOfflineId); logger.RecordPageDeleted(kOfflineId); - logger.RecordPageExpired(kOfflineId); - logger.RecordStoreClearError(); - logger.RecordStoreReloadError(); logger.GetLogs(&log); - EXPECT_EQ(6u, log.size()); - EXPECT_EQ(std::string(kRecordStoreCleared), log[5].substr(kTimeLength)); - EXPECT_EQ(std::string(kPageSaved), log[4].substr(kTimeLength)); - EXPECT_EQ(std::string(kPageDeleted), log[3].substr(kTimeLength)); - EXPECT_EQ(std::string(kPageExpired), log[2].substr(kTimeLength)); - EXPECT_EQ(std::string(kRecordStoreClearError), log[1].substr(kTimeLength)); - EXPECT_EQ(std::string(kRecordStoreReloadError), log[0].substr(kTimeLength)); + EXPECT_EQ(2u, log.size()); + EXPECT_EQ(std::string(kPageSaved), log[1].substr(kTimeLength)); + EXPECT_EQ(std::string(kPageDeleted), log[0].substr(kTimeLength)); } TEST(OfflinePageModelEventLoggerTest, DoesNotRecordWhenLoggingIsOff) { @@ -52,12 +39,8 @@ std::vector<std::string> log; logger.SetIsLogging(false); - logger.RecordStoreCleared(); logger.RecordPageSaved(kNamespace, kUrl, kOfflineId); logger.RecordPageDeleted(kOfflineId); - logger.RecordPageExpired(kOfflineId); - logger.RecordStoreClearError(); - logger.RecordStoreReloadError(); logger.GetLogs(&log); EXPECT_EQ(0u, log.size()); @@ -69,7 +52,7 @@ logger.SetIsLogging(true); for (size_t i = 0; i < kMaxLogCount + 1; ++i) { - logger.RecordStoreCleared(); + logger.RecordPageSaved(kNamespace, kUrl, kOfflineId); } logger.GetLogs(&log);
diff --git a/components/offline_pages/core/recent_tabs/BUILD.gn b/components/offline_pages/core/recent_tabs/BUILD.gn deleted file mode 100644 index fa8f938a..0000000 --- a/components/offline_pages/core/recent_tabs/BUILD.gn +++ /dev/null
@@ -1,39 +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. - -if (is_android) { - import("//build/config/android/rules.gni") -} - -source_set("recent_tabs") { - sources = [ - "recent_tabs_ui_adapter_delegate.cc", - "recent_tabs_ui_adapter_delegate.h", - ] - - deps = [ - "//base", - "//components/offline_pages/core", - "//components/offline_pages/core/downloads:offline_pages_ui_adapter", - "//url", - ] -} - -source_set("unit_tests") { - testonly = true - sources = [ - "recent_tabs_ui_adapter_delegate_unittest.cc", - ] - - deps = [ - ":recent_tabs", - "//base", - "//base/test:test_support", - "//components/offline_pages/core", - "//components/offline_pages/core:test_support", - "//components/offline_pages/core/background:test_support", - "//components/offline_pages/core/downloads:offline_pages_ui_adapter", - "//testing/gtest", - ] -}
diff --git a/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.cc b/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.cc deleted file mode 100644 index 0db7cda..0000000 --- a/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.cc +++ /dev/null
@@ -1,101 +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. - -#include "components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.h" - -#include "base/bind.h" -#include "base/memory/ptr_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/threading/thread_task_runner_handle.h" -#include "components/offline_pages/core/client_policy_controller.h" -#include "components/offline_pages/core/offline_page_model.h" -#include "components/offline_pages/core/thumbnail_decoder.h" - -namespace offline_pages { - -namespace { -const char kRecentTabsUIAdapterKey[] = "recent-tabs-download-ui-adapter"; -} // namespace - -RecentTabsUIAdapterDelegate::RecentTabsUIAdapterDelegate( - OfflinePageModel* model) - : model_(model) {} - -RecentTabsUIAdapterDelegate::~RecentTabsUIAdapterDelegate() = default; - -offline_pages::DownloadUIAdapter* -RecentTabsUIAdapterDelegate::GetOrCreateRecentTabsUIAdapter( - offline_pages::OfflinePageModel* offline_page_model, - offline_pages::RequestCoordinator* request_coordinator) { - offline_pages::DownloadUIAdapter* recent_tabs_ui_adapter = - static_cast<DownloadUIAdapter*>( - offline_page_model->GetUserData(kRecentTabsUIAdapterKey)); - - if (!recent_tabs_ui_adapter) { - auto delegate = - std::make_unique<RecentTabsUIAdapterDelegate>(offline_page_model); - recent_tabs_ui_adapter = - new DownloadUIAdapter(nullptr, offline_page_model, request_coordinator, - nullptr, std::move(delegate)); - offline_page_model->SetUserData(kRecentTabsUIAdapterKey, - base::WrapUnique(recent_tabs_ui_adapter)); - } - - return recent_tabs_ui_adapter; -} - -// static -RecentTabsUIAdapterDelegate* RecentTabsUIAdapterDelegate::FromDownloadUIAdapter( - DownloadUIAdapter* ui_adapter) { - return static_cast<RecentTabsUIAdapterDelegate*>(ui_adapter->delegate()); -} - -// static -int RecentTabsUIAdapterDelegate::TabIdFromClientId(const ClientId& client_id) { - int tab_id = 0; - bool convert_result = base::StringToInt(client_id.id, &tab_id); - DCHECK(convert_result); - return tab_id; -} - -bool RecentTabsUIAdapterDelegate::IsVisibleInUI(const ClientId& client_id) { - return IsRecentTab(client_id); -} - -bool RecentTabsUIAdapterDelegate::IsTemporarilyHiddenInUI( - const ClientId& client_id) { - return active_tabs_.count(TabIdFromClientId(client_id)) == 0; -} - -void RecentTabsUIAdapterDelegate::SetUIAdapter(DownloadUIAdapter* adapter) { - ui_adapter_ = adapter; -} - -void RecentTabsUIAdapterDelegate::RegisterTab(int tab_id) { - DCHECK(ui_adapter_); - if (active_tabs_.count(tab_id) > 0) - return; - active_tabs_.insert(tab_id); - ui_adapter_->TemporaryHiddenStatusChanged(ClientIdFromTabId(tab_id)); -} - -void RecentTabsUIAdapterDelegate::UnregisterTab(int tab_id) { - DCHECK(ui_adapter_); - if (active_tabs_.count(tab_id) == 0) - return; - active_tabs_.erase(tab_id); - ui_adapter_->TemporaryHiddenStatusChanged(ClientIdFromTabId(tab_id)); -} - -// static -ClientId RecentTabsUIAdapterDelegate::ClientIdFromTabId(int tab_id) { - return ClientId(kLastNNamespace, base::IntToString(tab_id)); -} - -bool RecentTabsUIAdapterDelegate::IsRecentTab(const ClientId& page) { - return model_->GetPolicyController()->IsShownAsRecentlyVisitedSite( - page.name_space); -} - -} // namespace offline_pages
diff --git a/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.h b/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.h deleted file mode 100644 index 212e423..0000000 --- a/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.h +++ /dev/null
@@ -1,86 +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 COMPONENTS_OFFLINE_PAGES_CORE_RECENT_TABS_RECENT_TABS_UI_ADAPTER_DELEGATE_H_ -#define COMPONENTS_OFFLINE_PAGES_CORE_RECENT_TABS_RECENT_TABS_UI_ADAPTER_DELEGATE_H_ - -#include <map> -#include <memory> -#include <string> -#include <vector> - -#include "base/observer_list.h" -#include "base/supports_user_data.h" -#include "components/offline_pages/core/client_namespace_constants.h" -#include "components/offline_pages/core/downloads/download_ui_adapter.h" -#include "components/offline_pages/core/offline_page_model.h" -#include "components/offline_pages/core/offline_page_types.h" -#include "url/gurl.h" - -namespace offline_pages { - -// Keeps track of all the tabs open for the profile, and restricts its view of -// the offline pages to only those that have an open tab. This begins -// observation early, as soon as the first Tab is created, and even before that -// tab gets a web contents. -// -// In this UI adapter, |guid| represents the tab ID for a given page. -class RecentTabsUIAdapterDelegate : public DownloadUIAdapter::Delegate { - public: - explicit RecentTabsUIAdapterDelegate(OfflinePageModel* model); - ~RecentTabsUIAdapterDelegate() override; - - static DownloadUIAdapter* GetOrCreateRecentTabsUIAdapter( - OfflinePageModel* offline_page_model, - RequestCoordinator* request_coordinator); - static RecentTabsUIAdapterDelegate* FromDownloadUIAdapter( - DownloadUIAdapter* adapter); - // This extracts the tab ID out of the |id| field of the client ID using a - // string conversion. Crashes if conversion fails. - static int TabIdFromClientId(const ClientId& client_id); - - // This override returns true if the client ID is shown on the NTP as a recent - // tab. This is determined by policy. - bool IsVisibleInUI(const ClientId& client_id) override; - // This returns true if there does not exist a tab ID for the given client ID. - bool IsTemporarilyHiddenInUI(const ClientId& client_id) override; - // Sets our reference to the UI adapter so we can notify it of visibility - // changes. - void SetUIAdapter(DownloadUIAdapter* ui_adapter) override; - void OpenItem(const OfflineItem& item, int64_t offline_id) override {} - - // Register/UnregisterTab add and remove tab IDs from the list. These - // functions can be called before a page actually exists with the given tab - // ID. - // Note that these change temporary visibility and therefore |set_ui_adapter| - // must be called before either of these functions. - void RegisterTab(int tab_id); - void UnregisterTab(int tab_id); - - private: - // Constructs the client ID assuming that we use the Last N namespace. - // - // TODO(dewittj): Make this more resilient to adding more namespaces. - static ClientId ClientIdFromTabId(int tab_id); - - // Checks a client ID for proper namespace and ID format to be shown in the - // Downloads Home UI. - bool IsRecentTab(const ClientId& page); - - // Always valid, this class is owned by DownloadUIAdapter, which is owned by - // Offline Page Model. - OfflinePageModel* model_; - - // This is set by the UI adapter itself. - DownloadUIAdapter* ui_adapter_ = nullptr; - - // The tabs we've seen. - std::unordered_set<int> active_tabs_; - - DISALLOW_COPY_AND_ASSIGN(RecentTabsUIAdapterDelegate); -}; - -} // namespace offline_pages - -#endif // COMPONENTS_OFFLINE_PAGES_CORE_RECENT_TABS_RECENT_TABS_UI_ADAPTER_DELEGATE_H_
diff --git a/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate_unittest.cc b/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate_unittest.cc deleted file mode 100644 index 90e4f5b..0000000 --- a/components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate_unittest.cc +++ /dev/null
@@ -1,123 +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 "components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.h" - -#include <stdint.h> - -#include <map> -#include <memory> -#include <string> -#include <vector> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/files/file_path.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/test/test_mock_time_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "components/offline_pages/core/background/request_coordinator_stub_taco.h" -#include "components/offline_pages/core/client_namespace_constants.h" -#include "components/offline_pages/core/client_policy_controller.h" -#include "components/offline_pages/core/downloads/download_ui_adapter.h" -#include "components/offline_pages/core/stub_offline_page_model.h" -#include "components/offline_pages/core/thumbnail_decoder.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace offline_pages { - -namespace { -static const char kTestGuid1[] = "1"; -static const char kTestGuid2[] = "2"; -static const char kTestBadGuid[] = "ccccccc-cccc-0ccc-0ccc-ccccccccccc0"; -static const ClientId kTestClientIdOtherNamespace(kAsyncNamespace, kTestGuid1); -static const ClientId kTestClientIdOtherGuid(kLastNNamespace, kTestBadGuid); -static const ClientId kTestClientId1(kLastNNamespace, kTestGuid1); -static const ClientId kTestClientId2(kLastNNamespace, kTestGuid2); - -// Creates mock versions for OfflinePageModel, RequestCoordinator and their -// dependencies, then passes them to DownloadUIAdapter for testing. -// Note that initially the OfflienPageModel is not "loaded". PumpLoop() will -// load it, firing ItemsLoaded callback to the Adapter. Hence some tests -// start from PumpLoop() right away if they don't need to test this. -class RecentTabsUIAdapterDelegateTest : public testing::Test { - public: - RecentTabsUIAdapterDelegateTest(); - ~RecentTabsUIAdapterDelegateTest() override; - - // Runs until all of the tasks that are not delayed are gone from the task - // queue. - void PumpLoop(); - - RequestCoordinator* request_coordinator() { - return request_coordinator_taco_->request_coordinator(); - } - - StubOfflinePageModel model; - RecentTabsUIAdapterDelegate* adapter_delegate; - std::unique_ptr<DownloadUIAdapter> adapter; - - private: - std::unique_ptr<RequestCoordinatorStubTaco> request_coordinator_taco_; - scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; - base::ThreadTaskRunnerHandle task_runner_handle_; -}; - -RecentTabsUIAdapterDelegateTest::RecentTabsUIAdapterDelegateTest() - : task_runner_(new base::TestMockTimeTaskRunner()), - task_runner_handle_(task_runner_) { - request_coordinator_taco_ = std::make_unique<RequestCoordinatorStubTaco>(); - request_coordinator_taco_->CreateRequestCoordinator(); - - auto delegate = std::make_unique<RecentTabsUIAdapterDelegate>(&model); - adapter_delegate = delegate.get(); - - adapter = std::make_unique<DownloadUIAdapter>( - nullptr, &model, request_coordinator_taco_->request_coordinator(), - nullptr, std::move(delegate)); -} - -RecentTabsUIAdapterDelegateTest::~RecentTabsUIAdapterDelegateTest() = default; - -void RecentTabsUIAdapterDelegateTest::PumpLoop() { - task_runner_->RunUntilIdle(); -} - -TEST_F(RecentTabsUIAdapterDelegateTest, TabIdFromClientId) { - EXPECT_EQ(1, RecentTabsUIAdapterDelegate::TabIdFromClientId(kTestClientId1)); - EXPECT_EQ(2, RecentTabsUIAdapterDelegate::TabIdFromClientId(kTestClientId2)); -} - -TEST_F(RecentTabsUIAdapterDelegateTest, IsVisibleInUI) { - EXPECT_FALSE(adapter_delegate->IsVisibleInUI(kTestClientIdOtherNamespace)); - EXPECT_TRUE(adapter_delegate->IsVisibleInUI(kTestClientId1)); - EXPECT_TRUE(adapter_delegate->IsVisibleInUI(kTestClientId2)); -} - -TEST_F(RecentTabsUIAdapterDelegateTest, IsTemporarilyHiddenInUI) { - adapter_delegate->RegisterTab(3); - adapter_delegate->RegisterTab(4); - - EXPECT_TRUE(adapter_delegate->IsTemporarilyHiddenInUI(kTestClientId1)); - EXPECT_TRUE(adapter_delegate->IsTemporarilyHiddenInUI(kTestClientId2)); - - adapter_delegate->RegisterTab(1); - EXPECT_FALSE(adapter_delegate->IsTemporarilyHiddenInUI(kTestClientId1)); - EXPECT_TRUE(adapter_delegate->IsTemporarilyHiddenInUI(kTestClientId2)); - - adapter_delegate->RegisterTab(2); - EXPECT_FALSE(adapter_delegate->IsTemporarilyHiddenInUI(kTestClientId1)); - EXPECT_FALSE(adapter_delegate->IsTemporarilyHiddenInUI(kTestClientId2)); - - adapter_delegate->UnregisterTab(2); - EXPECT_FALSE(adapter_delegate->IsTemporarilyHiddenInUI(kTestClientId1)); - EXPECT_TRUE(adapter_delegate->IsTemporarilyHiddenInUI(kTestClientId2)); -} - -} // namespace -} // namespace offline_pages
diff --git a/components/security_interstitials/core/common/resources/interstitial_common.css b/components/security_interstitials/core/common/resources/interstitial_common.css index bb1ca4f..76380d9 100644 --- a/components/security_interstitials/core/common/resources/interstitial_common.css +++ b/components/security_interstitials/core/common/resources/interstitial_common.css
@@ -268,9 +268,9 @@ (min-width: 421px) and (min-height: 240px) and (max-height: 560px) { body .nav-wrapper { - background: #f7f7f7; + background: #fff; bottom: 0; - box-shadow: 0 -22px 40px rgb(247, 247, 247); + box-shadow: 0 -22px 40px #fff; left: 0; margin: 0 auto; max-width: 736px;
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc index 0992c87..4470265 100644 --- a/components/viz/service/display/display.cc +++ b/components/viz/service/display/display.cc
@@ -98,6 +98,9 @@ surface_manager_->AddObserver(scheduler_.get()); output_surface_->BindToClient(this); + if (output_surface_->software_device()) + output_surface_->software_device()->BindToClient(this); + InitializeRenderer(); // This depends on assumptions that Display::Initialize will happen on the @@ -575,6 +578,12 @@ return it->second; } +void Display::SoftwareDeviceUpdatedCALayerParams( + const gfx::CALayerParams& ca_layer_params) { + if (client_) + client_->DisplayDidReceiveCALayerParams(ca_layer_params); +} + void Display::ForceImmediateDrawAndSwapIfPossible() { if (scheduler_) scheduler_->ForceImmediateSwapIfPossible(); @@ -633,10 +642,12 @@ // Skip quad if it is a RenderPassDrawQuad because RenderPassDrawQuad is a // special type of DrawQuad where the visible_rect of shared quad state is // not entirely covered by draw quads in it; or the DrawQuad size is - // smaller than the kMinimumDrawOcclusionSize. + // smaller than the kMinimumDrawOcclusionSize; or the DrawQuad is inside + // a 3d objects. if (quad->material == ContentDrawQuadBase::Material::RENDER_PASS || (quad->visible_rect.width() <= minimum_draw_occlusion_width && - quad->visible_rect.height() <= minimum_draw_occlusion_height)) { + quad->visible_rect.height() <= minimum_draw_occlusion_height) || + quad->shared_quad_state->sorting_context_id != 0) { ++quad; continue; }
diff --git a/components/viz/service/display/display.h b/components/viz/service/display/display.h index e15a341..4b7d805 100644 --- a/components/viz/service/display/display.h +++ b/components/viz/service/display/display.h
@@ -19,6 +19,7 @@ #include "components/viz/common/surfaces/surface_id.h" #include "components/viz/service/display/display_scheduler.h" #include "components/viz/service/display/output_surface_client.h" +#include "components/viz/service/display/software_output_device_client.h" #include "components/viz/service/display/surface_aggregator.h" #include "components/viz/service/surfaces/latest_local_surface_id_lookup_delegate.h" #include "components/viz/service/surfaces/surface_manager.h" @@ -57,7 +58,8 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient, public OutputSurfaceClient, public ContextLostObserver, - public LatestLocalSurfaceIdLookupDelegate { + public LatestLocalSurfaceIdLookupDelegate, + public SoftwareOutputDeviceClient { public: // The |begin_frame_source| and |scheduler| may be null (together). In that // case, DrawAndSwap must be called externally when needed. @@ -121,6 +123,10 @@ LocalSurfaceId GetSurfaceAtAggregation( const FrameSinkId& frame_sink_id) const override; + // SoftwareOutputDeviceClient implementation + void SoftwareDeviceUpdatedCALayerParams( + const gfx::CALayerParams& ca_layer_params) override; + bool has_scheduler() const { return !!scheduler_; } DirectRenderer* renderer_for_testing() const { return renderer_.get(); }
diff --git a/components/viz/service/display/display_unittest.cc b/components/viz/service/display/display_unittest.cc index 6bfb8aa..eb7d432 100644 --- a/components/viz/service/display/display_unittest.cc +++ b/components/viz/service/display/display_unittest.cc
@@ -2074,6 +2074,62 @@ TearDownDisplay(); } +// Test if draw occlusion skips 3d objects. https://crbug.com/833748 +TEST_F(DisplayTest, CompositorFrameZTranslate) { + RendererSettings settings; + settings.kMinimumDrawOcclusionSize.set_width(0); + SetUpDisplay(settings, TestWebGraphicsContext3D::Create()); + + StubDisplayClient client; + display_->Initialize(&client, manager_.surface_manager()); + + CompositorFrame frame = MakeDefaultCompositorFrame(); + gfx::Rect rect1(0, 0, 100, 100); + gfx::Rect rect2(0, 0, 200, 100); + + gfx::Transform translate_back; + translate_back.Translate3d(0, 0, 100); + bool is_clipped = false; + bool are_contents_opaque = true; + float opacity = 1.f; + SharedQuadState* shared_quad_state = + frame.render_pass_list.front()->CreateAndAppendSharedQuadState(); + auto* quad = frame.render_pass_list.front() + ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>(); + SharedQuadState* shared_quad_state2 = + frame.render_pass_list.front()->CreateAndAppendSharedQuadState(); + auto* quad2 = frame.render_pass_list.front() + ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>(); + + // 2 rects inside of 3d object is completely overlapping. + // +-----+ + // | | + // +-----+ + { + shared_quad_state->SetAll(translate_back, rect1, rect1, rect1, is_clipped, + are_contents_opaque, opacity, + SkBlendMode::kSrcOver, 1); + shared_quad_state2->SetAll(gfx::Transform(), rect1, rect1, rect1, + is_clipped, are_contents_opaque, opacity, + SkBlendMode::kSrcOver, 1); + + quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false); + quad2->SetNew(shared_quad_state2, rect2, rect1, SK_ColorBLACK, false); + EXPECT_EQ(2u, frame.render_pass_list.front()->quad_list.size()); + display_->RemoveOverdrawQuads(&frame); + // Since both |quad| and |quad2| are inside of a 3d object, DrawOcclusion + // will not be applied to them. + EXPECT_EQ(2u, frame.render_pass_list.front()->quad_list.size()); + EXPECT_EQ(rect1.ToString(), frame.render_pass_list.front() + ->quad_list.ElementAt(0) + ->rect.ToString()); + EXPECT_EQ(rect2.ToString(), frame.render_pass_list.front() + ->quad_list.ElementAt(1) + ->rect.ToString()); + } + TearDownDisplay(); +} + TEST_F(DisplayTest, CompositorFrameWithTranslateTransformer) { RendererSettings settings; settings.kMinimumDrawOcclusionSize.set_width(0);
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc index e1a55fad..c8d5cb9d3 100644 --- a/components/viz/service/display/gl_renderer_unittest.cc +++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -655,38 +655,45 @@ EXPECT_TRUE(renderer_->stencil_enabled()); } -class ForbidSynchronousCallContext : public TestWebGraphicsContext3D { +class ForbidSynchronousCallGLES2Interface : public TestGLES2Interface { public: - ForbidSynchronousCallContext() {} + ForbidSynchronousCallGLES2Interface() = default; - void getAttachedShaders(GLuint program, + void GetAttachedShaders(GLuint program, GLsizei max_count, GLsizei* count, GLuint* shaders) override { ADD_FAILURE(); } - GLint getAttribLocation(GLuint program, const GLchar* name) override { + + GLint GetAttribLocation(GLuint program, const GLchar* name) override { ADD_FAILURE(); return 0; } - void getBooleanv(GLenum pname, GLboolean* value) override { ADD_FAILURE(); } - void getBufferParameteriv(GLenum target, + + void GetBooleanv(GLenum pname, GLboolean* value) override { ADD_FAILURE(); } + + void GetBufferParameteriv(GLenum target, GLenum pname, GLint* value) override { ADD_FAILURE(); } - GLenum getError() override { + + GLenum GetError() override { ADD_FAILURE(); return GL_NO_ERROR; } - void getFloatv(GLenum pname, GLfloat* value) override { ADD_FAILURE(); } - void getFramebufferAttachmentParameteriv(GLenum target, + + void GetFloatv(GLenum pname, GLfloat* value) override { ADD_FAILURE(); } + + void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* value) override { ADD_FAILURE(); } - void getIntegerv(GLenum pname, GLint* value) override { + + void GetIntegerv(GLenum pname, GLint* value) override { if (pname == GL_MAX_TEXTURE_SIZE) { // MAX_TEXTURE_SIZE is cached client side, so it's OK to query. *value = 1024; @@ -697,64 +704,66 @@ // We allow querying the shader compilation and program link status in debug // mode, but not release. - void getProgramiv(GLuint program, GLenum pname, GLint* value) override { -#ifndef NDEBUG - *value = 1; -#else + void GetProgramiv(GLuint program, GLenum pname, GLint* value) override { ADD_FAILURE(); -#endif } - void getShaderiv(GLuint shader, GLenum pname, GLint* value) override { -#ifndef NDEBUG - *value = 1; -#else + void GetShaderiv(GLuint shader, GLenum pname, GLint* value) override { ADD_FAILURE(); -#endif } - void getRenderbufferParameteriv(GLenum target, + void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* value) override { ADD_FAILURE(); } - void getShaderPrecisionFormat(GLenum shadertype, + void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) override { ADD_FAILURE(); } - void getTexParameterfv(GLenum target, GLenum pname, GLfloat* value) override { + + void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* value) override { ADD_FAILURE(); } - void getTexParameteriv(GLenum target, GLenum pname, GLint* value) override { + + void GetTexParameteriv(GLenum target, GLenum pname, GLint* value) override { ADD_FAILURE(); } - void getUniformfv(GLuint program, GLint location, GLfloat* value) override { + + void GetUniformfv(GLuint program, GLint location, GLfloat* value) override { ADD_FAILURE(); } - void getUniformiv(GLuint program, GLint location, GLint* value) override { + + void GetUniformiv(GLuint program, GLint location, GLint* value) override { ADD_FAILURE(); } - GLint getUniformLocation(GLuint program, const GLchar* name) override { + + GLint GetUniformLocation(GLuint program, const GLchar* name) override { ADD_FAILURE(); return 0; } - void getVertexAttribfv(GLuint index, GLenum pname, GLfloat* value) override { + + void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* value) override { ADD_FAILURE(); } - void getVertexAttribiv(GLuint index, GLenum pname, GLint* value) override { + + void GetVertexAttribiv(GLuint index, GLenum pname, GLint* value) override { ADD_FAILURE(); } - GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname) override { + + void GetVertexAttribPointerv(GLuint index, + GLenum pname, + void** pointer) override { ADD_FAILURE(); - return 0; } }; + TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) { - auto context = std::make_unique<ForbidSynchronousCallContext>(); - auto provider = TestContextProvider::Create(std::move(context)); + auto gl_owned = std::make_unique<ForbidSynchronousCallGLES2Interface>(); + auto provider = TestContextProvider::Create(std::move(gl_owned)); provider->BindToCurrentThread(); cc::FakeOutputSurfaceClient output_surface_client; @@ -811,22 +820,26 @@ resource_provider.get()); } -class ClearCountingContext : public TestWebGraphicsContext3D { +class ClearCountingGLES2Interface : public TestGLES2Interface { public: - ClearCountingContext() { test_capabilities_.discard_framebuffer = true; } + ClearCountingGLES2Interface() = default; - MOCK_METHOD3(discardFramebufferEXT, + void InitializeTestContext(TestWebGraphicsContext3D* context) override { + context->set_have_discard_framebuffer(true); + } + + MOCK_METHOD3(DiscardFramebufferEXT, void(GLenum target, GLsizei numAttachments, const GLenum* attachments)); - MOCK_METHOD1(clear, void(GLbitfield mask)); + MOCK_METHOD1(Clear, void(GLbitfield mask)); }; TEST_F(GLRendererTest, OpaqueBackground) { - std::unique_ptr<ClearCountingContext> context_owned(new ClearCountingContext); - ClearCountingContext* context = context_owned.get(); + auto gl_owned = std::make_unique<ClearCountingGLES2Interface>(); + ClearCountingGLES2Interface* gl = gl_owned.get(); - auto provider = TestContextProvider::Create(std::move(context_owned)); + auto provider = TestContextProvider::Create(std::move(gl_owned)); provider->BindToCurrentThread(); cc::FakeOutputSurfaceClient output_surface_client; @@ -854,23 +867,23 @@ // On DEBUG builds, render passes with opaque background clear to blue to // easily see regions that were not drawn on the screen. - EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _)) + EXPECT_CALL(*gl, DiscardFramebufferEXT(GL_FRAMEBUFFER, _, _)) .With(Args<2, 1>(ElementsAre(GL_COLOR_EXT))) .Times(1); #ifdef NDEBUG - EXPECT_CALL(*context, clear(_)).Times(0); + EXPECT_CALL(*gl, Clear(_)).Times(0); #else - EXPECT_CALL(*context, clear(_)).Times(1); + EXPECT_CALL(*gl, Clear(_)).Times(1); #endif DrawFrame(&renderer, viewport_size); - Mock::VerifyAndClearExpectations(context); + Mock::VerifyAndClearExpectations(gl); } TEST_F(GLRendererTest, TransparentBackground) { - std::unique_ptr<ClearCountingContext> context_owned(new ClearCountingContext); - ClearCountingContext* context = context_owned.get(); + auto gl_owned = std::make_unique<ClearCountingGLES2Interface>(); + ClearCountingGLES2Interface* gl = gl_owned.get(); - auto provider = TestContextProvider::Create(std::move(context_owned)); + auto provider = TestContextProvider::Create(std::move(gl_owned)); provider->BindToCurrentThread(); cc::FakeOutputSurfaceClient output_surface_client; @@ -896,18 +909,18 @@ gfx::Transform(), cc::FilterOperations()); root_pass->has_transparent_background = true; - EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, 1, _)).Times(1); - EXPECT_CALL(*context, clear(_)).Times(1); + EXPECT_CALL(*gl, DiscardFramebufferEXT(GL_FRAMEBUFFER, 1, _)).Times(1); + EXPECT_CALL(*gl, Clear(_)).Times(1); DrawFrame(&renderer, viewport_size); - Mock::VerifyAndClearExpectations(context); + Mock::VerifyAndClearExpectations(gl); } TEST_F(GLRendererTest, OffscreenOutputSurface) { - std::unique_ptr<ClearCountingContext> context_owned(new ClearCountingContext); - ClearCountingContext* context = context_owned.get(); + auto gl_owned = std::make_unique<ClearCountingGLES2Interface>(); + ClearCountingGLES2Interface* gl = gl_owned.get(); - auto provider = TestContextProvider::Create(std::move(context_owned)); + auto provider = TestContextProvider::Create(std::move(gl_owned)); provider->BindToCurrentThread(); cc::FakeOutputSurfaceClient output_surface_client; @@ -931,26 +944,29 @@ cc::AddRenderPass(&render_passes_in_draw_order_, 1, gfx::Rect(viewport_size), gfx::Transform(), cc::FilterOperations()); - EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _)) + EXPECT_CALL(*gl, DiscardFramebufferEXT(GL_FRAMEBUFFER, _, _)) .With(Args<2, 1>(ElementsAre(GL_COLOR_ATTACHMENT0))) .Times(1); - EXPECT_CALL(*context, clear(_)).Times(AnyNumber()); + EXPECT_CALL(*gl, Clear(_)).Times(AnyNumber()); DrawFrame(&renderer, viewport_size); - Mock::VerifyAndClearExpectations(context); + Mock::VerifyAndClearExpectations(gl); } -class TextureStateTrackingContext : public TestWebGraphicsContext3D { +class TextureStateTrackingGLES2Interface : public TestGLES2Interface { public: - TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM) { - test_capabilities_.egl_image_external = true; + TextureStateTrackingGLES2Interface() : active_texture_(GL_INVALID_ENUM) {} + + void InitializeTestContext(TestWebGraphicsContext3D* context) override { + context->set_have_extension_egl_image(true); } - MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token)); - MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param)); - MOCK_METHOD4(drawElements, - void(GLenum mode, GLsizei count, GLenum type, GLintptr offset)); + MOCK_METHOD1(WaitSyncTokenCHROMIUM, void(const GLbyte* sync_token)); + MOCK_METHOD3(TexParameteri, void(GLenum target, GLenum pname, GLint param)); + MOCK_METHOD4( + DrawElements, + void(GLenum mode, GLsizei count, GLenum type, const void* indices)); - void activeTexture(GLenum texture) override { + void ActiveTexture(GLenum texture) override { EXPECT_NE(texture, active_texture_); active_texture_ = texture; } @@ -962,11 +978,10 @@ }; TEST_F(GLRendererTest, ActiveTextureState) { - std::unique_ptr<TextureStateTrackingContext> context_owned( - new TextureStateTrackingContext); - TextureStateTrackingContext* context = context_owned.get(); + auto gl_owned = std::make_unique<TextureStateTrackingGLES2Interface>(); + TextureStateTrackingGLES2Interface* gl = gl_owned.get(); - auto provider = TestContextProvider::Create(std::move(context_owned)); + auto provider = TestContextProvider::Create(std::move(gl_owned)); provider->BindToCurrentThread(); cc::FakeOutputSurfaceClient output_surface_client; @@ -987,13 +1002,12 @@ renderer.SetVisible(true); // During initialization we are allowed to set any texture parameters. - EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber()); + EXPECT_CALL(*gl, TexParameteri(_, _, _)).Times(AnyNumber()); - std::unique_ptr<TextureStateTrackingContext> child_context_owned( - new TextureStateTrackingContext); + auto child_gl_owned = std::make_unique<TextureStateTrackingGLES2Interface>(); auto child_context_provider = - TestContextProvider::Create(std::move(child_context_owned)); + TestContextProvider::Create(std::move(child_gl_owned)); child_context_provider->BindToCurrentThread(); auto child_resource_provider = cc::FakeResourceProvider::CreateLayerTreeResourceProvider( @@ -1012,7 +1026,7 @@ // Set up expected texture filter state transitions that match the quads // created in AppendOneOfEveryQuadType(). - Mock::VerifyAndClearExpectations(context); + Mock::VerifyAndClearExpectations(gl); { InSequence sequence; // The verified flush flag will be set by @@ -1024,43 +1038,45 @@ // (with mailbox), resource2, resource3, resource4, resource9, resource10, // resource11, resource12. resource8 has its own mailbox mailbox_sync_token. // The rest resources share a common default sync token. - EXPECT_CALL(*context, waitSyncToken(_)).Times(2); - EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(mailbox_sync_token))) + EXPECT_CALL(*gl, WaitSyncTokenCHROMIUM(_)).Times(2); + EXPECT_CALL(*gl, + WaitSyncTokenCHROMIUM(MatchesSyncToken(mailbox_sync_token))) .Times(1); - EXPECT_CALL(*context, waitSyncToken(_)).Times(7); + EXPECT_CALL(*gl, WaitSyncTokenCHROMIUM(_)).Times(7); // yuv_quad is drawn with the default linear filter. - EXPECT_CALL(*context, drawElements(_, _, _, _)); + EXPECT_CALL(*gl, DrawElements(_, _, _, _)); // tile_quad is drawn with GL_NEAREST because it is not transformed or // scaled. - EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST)); - EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST)); + EXPECT_CALL( + *gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + EXPECT_CALL( + *gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); // The remaining quads also use GL_LINEAR because nearest neighbor // filtering is currently only used with tile quads. - EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(8); + EXPECT_CALL(*gl, DrawElements(_, _, _, _)).Times(8); } gfx::Size viewport_size(100, 100); DrawFrame(&renderer, viewport_size); - Mock::VerifyAndClearExpectations(context); + Mock::VerifyAndClearExpectations(gl); } -class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D { +class NoClearRootRenderPassMockGLES2Interface : public TestGLES2Interface { public: - MOCK_METHOD1(clear, void(GLbitfield mask)); - MOCK_METHOD4(drawElements, - void(GLenum mode, GLsizei count, GLenum type, GLintptr offset)); + MOCK_METHOD1(Clear, void(GLbitfield mask)); + MOCK_METHOD4( + DrawElements, + void(GLenum mode, GLsizei count, GLenum type, const void* indices)); }; TEST_F(GLRendererTest, ShouldClearRootRenderPass) { - std::unique_ptr<NoClearRootRenderPassMockContext> mock_context_owned( - new NoClearRootRenderPassMockContext); - NoClearRootRenderPassMockContext* mock_context = mock_context_owned.get(); + auto mock_gl_owned = + std::make_unique<NoClearRootRenderPassMockGLES2Interface>(); + NoClearRootRenderPassMockGLES2Interface* mock_gl = mock_gl_owned.get(); - auto provider = TestContextProvider::Create(std::move(mock_context_owned)); + auto provider = TestContextProvider::Create(std::move(mock_gl_owned)); provider->BindToCurrentThread(); cc::FakeOutputSurfaceClient output_surface_client; @@ -1105,17 +1121,15 @@ #endif // First render pass is not the root one, clearing should happen. - EXPECT_CALL(*mock_context, clear(clear_bits)).Times(AtLeast(1)); + EXPECT_CALL(*mock_gl, Clear(clear_bits)).Times(AtLeast(1)); Expectation first_render_pass = - EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(1); + EXPECT_CALL(*mock_gl, DrawElements(_, _, _, _)).Times(1); // The second render pass is the root one, clearing should be prevented. - EXPECT_CALL(*mock_context, clear(clear_bits)) - .Times(0) - .After(first_render_pass); + EXPECT_CALL(*mock_gl, Clear(clear_bits)).Times(0).After(first_render_pass); - EXPECT_CALL(*mock_context, drawElements(_, _, _, _)) + EXPECT_CALL(*mock_gl, DrawElements(_, _, _, _)) .Times(AnyNumber()) .After(first_render_pass); @@ -1124,7 +1138,7 @@ // In multiple render passes all but the root pass should clear the // framebuffer. - Mock::VerifyAndClearExpectations(&mock_context); + Mock::VerifyAndClearExpectations(&mock_gl); } class ScissorTestOnClearCheckingGLES2Interface : public TestGLES2Interface { @@ -2213,9 +2227,9 @@ SingleOverlayValidator validator_; }; -class WaitSyncTokenCountingContext : public TestWebGraphicsContext3D { +class WaitSyncTokenCountingGLES2Interface : public TestGLES2Interface { public: - MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token)); + MOCK_METHOD1(WaitSyncTokenCHROMIUM, void(const GLbyte* sync_token)); }; class MockOverlayScheduler { @@ -2229,11 +2243,10 @@ }; TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) { - std::unique_ptr<WaitSyncTokenCountingContext> context_owned( - new WaitSyncTokenCountingContext); - WaitSyncTokenCountingContext* context = context_owned.get(); + auto gl_owned = std::make_unique<WaitSyncTokenCountingGLES2Interface>(); + WaitSyncTokenCountingGLES2Interface* gl = gl_owned.get(); - auto provider = TestContextProvider::Create(std::move(context_owned)); + auto provider = TestContextProvider::Create(std::move(gl_owned)); provider->BindToCurrentThread(); MockOverlayScheduler overlay_scheduler; @@ -2328,7 +2341,8 @@ // Verify that overlay_quad actually gets turned into an overlay, and even // though it's not drawn, that its sync point is waited on. - EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))).Times(1); + EXPECT_CALL(*gl, WaitSyncTokenCHROMIUM(MatchesSyncToken(sync_token))) + .Times(1); EXPECT_CALL( overlay_scheduler,
diff --git a/components/viz/service/display/shader.cc b/components/viz/service/display/shader.cc index d7cd218..62bab35 100644 --- a/components/viz/service/display/shader.cc +++ b/components/viz/service/display/shader.cc
@@ -11,6 +11,7 @@ #include <vector> #include "base/logging.h" +#include "base/strings/char_traits.h" #include "base/strings/stringprintf.h" #include "components/viz/service/display/static_geometry_binding.h" #include "gpu/command_buffer/client/gles2_interface.h" @@ -18,29 +19,18 @@ #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/size.h" -constexpr bool ConstexprEqual(const char* a, const char* b, size_t length) { - for (size_t i = 0; i < length; i++) { - if (a[i] != b[i]) - return false; - } - return true; -} - constexpr base::StringPiece StripLambda(base::StringPiece shader) { - // Must contain at least "[]() {}" and trailing null (included in size). - // TODO(jbroman): Simplify this once we're in a post-C++17 world, where - // starts_with and ends_with can easily be made constexpr. - DCHECK(shader.size() >= 7); // NOLINT - DCHECK(ConstexprEqual(shader.data(), "[]() {", 6)); + // Must contain at least "[]() {}". + DCHECK(shader.starts_with("[]() {")); + DCHECK(shader.ends_with("}")); shader.remove_prefix(6); - DCHECK(shader[shader.size() - 1] == '}'); // NOLINT shader.remove_suffix(1); return shader; } // Shaders are passed in with lambda syntax, which tricks clang-format into // handling them correctly. StripLambda removes this. -#define SHADER0(Src) StripLambda(base::StringPiece(#Src, sizeof(#Src) - 1)) +#define SHADER0(Src) StripLambda(#Src) #define HDR(x) \ do { \
diff --git a/components/viz/service/display/software_output_device.cc b/components/viz/service/display/software_output_device.cc index 7f8e8fd..bc611f86 100644 --- a/components/viz/service/display/software_output_device.cc +++ b/components/viz/service/display/software_output_device.cc
@@ -13,6 +13,12 @@ SoftwareOutputDevice::SoftwareOutputDevice() = default; SoftwareOutputDevice::~SoftwareOutputDevice() = default; +void SoftwareOutputDevice::BindToClient(SoftwareOutputDeviceClient* client) { + DCHECK(client); + DCHECK(!client_); + client_ = client; +} + void SoftwareOutputDevice::Resize(const gfx::Size& viewport_pixel_size, float scale_factor) { if (viewport_pixel_size_ == viewport_pixel_size)
diff --git a/components/viz/service/display/software_output_device.h b/components/viz/service/display/software_output_device.h index 63e233d..396a67bc 100644 --- a/components/viz/service/display/software_output_device.h +++ b/components/viz/service/display/software_output_device.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "components/viz/service/display/software_output_device_client.h" #include "components/viz/service/viz_service_export.h" #include "third_party/skia/include/core/SkSurface.h" #include "ui/gfx/geometry/rect.h" @@ -18,10 +19,12 @@ namespace gfx { class VSyncProvider; -} +} // namespace gfx namespace viz { +class SoftwareOutputDeviceClient; + // This is a "tear-off" class providing software drawing support to // OutputSurface, such as to a platform-provided window framebuffer. class VIZ_SERVICE_EXPORT SoftwareOutputDevice { @@ -29,6 +32,9 @@ SoftwareOutputDevice(); virtual ~SoftwareOutputDevice(); + // This may be called only once, and requires a non-nullptr argument. + void BindToClient(SoftwareOutputDeviceClient* client); + // Discards any pre-existing backing buffers and allocates memory for a // software device of |size|. This must be called before the // |SoftwareOutputDevice| can be used in other ways. @@ -56,6 +62,7 @@ virtual gfx::VSyncProvider* GetVSyncProvider(); protected: + SoftwareOutputDeviceClient* client_ = nullptr; gfx::Size viewport_pixel_size_; gfx::Rect damage_rect_; sk_sp<SkSurface> surface_;
diff --git a/components/viz/service/display/software_output_device_client.h b/components/viz/service/display/software_output_device_client.h new file mode 100644 index 0000000..695354d2 --- /dev/null +++ b/components/viz/service/display/software_output_device_client.h
@@ -0,0 +1,26 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_SOFTWARE_OUTPUT_DEVICE_CLIENT_H_ +#define COMPONENTS_VIZ_SERVICE_DISPLAY_SOFTWARE_OUTPUT_DEVICE_CLIENT_H_ + +namespace gfx { +struct CALayerParams; +} // namespace gfx + +namespace viz { + +class SoftwareOutputDeviceClient { + public: + virtual ~SoftwareOutputDeviceClient() {} + + // Specify the CALayer parameters used to display the content drawn by this + // device on macOS. + virtual void SoftwareDeviceUpdatedCALayerParams( + const gfx::CALayerParams& ca_layer_params) = 0; +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_SOFTWARE_OUTPUT_DEVICE_CLIENT_H_
diff --git a/components/viz/service/display_embedder/gpu_display_provider.cc b/components/viz/service/display_embedder/gpu_display_provider.cc index bdd3ac6..945e379 100644 --- a/components/viz/service/display_embedder/gpu_display_provider.cc +++ b/components/viz/service/display_embedder/gpu_display_provider.cc
@@ -205,25 +205,13 @@ if (headless_) return std::make_unique<SoftwareOutputDevice>(); -#if defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) - gfx::AcceleratedWidget widget = surface_handle; -#endif - #if defined(OS_WIN) if (!output_device_backing_) output_device_backing_ = std::make_unique<OutputDeviceBacking>(); return std::make_unique<SoftwareOutputDeviceWin>(output_device_backing_.get(), - widget); + surface_handle); #elif defined(OS_MACOSX) - // TODO(crbug.com/730660): What do we do to get something we can draw to? Can - // we use an IO surface? Can we use CA layers and overlays like we do for gpu - // compositing? See https://crrev.com/c/792295 to no longer have - // GpuSurfaceTracker. Part of the SoftwareOutputDeviceMac::EndPaint probably - // needs to move to the browser process, and we need to set up transport of an - // IO surface to here? - NOTIMPLEMENTED(); - (void)widget; - return nullptr; + return std::make_unique<SoftwareOutputDeviceMac>(); #elif defined(OS_ANDROID) // Android does not do software compositing, so we can't get here. NOTREACHED(); @@ -232,11 +220,11 @@ ui::SurfaceFactoryOzone* factory = ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone(); std::unique_ptr<ui::SurfaceOzoneCanvas> surface_ozone = - factory->CreateCanvasForWidget(widget); + factory->CreateCanvasForWidget(surface_handle); CHECK(surface_ozone); return std::make_unique<SoftwareOutputDeviceOzone>(std::move(surface_ozone)); #elif defined(USE_X11) - return std::make_unique<SoftwareOutputDeviceX11>(widget); + return std::make_unique<SoftwareOutputDeviceX11>(surface_handle); #endif }
diff --git a/components/viz/service/display_embedder/software_output_device_mac.cc b/components/viz/service/display_embedder/software_output_device_mac.cc index 79211e9..db7a80d2 100644 --- a/components/viz/service/display_embedder/software_output_device_mac.cc +++ b/components/viz/service/display_embedder/software_output_device_mac.cc
@@ -7,7 +7,7 @@ #include "base/mac/foundation_util.h" #include "base/trace_event/trace_event.h" #include "third_party/skia/include/core/SkCanvas.h" -#include "ui/accelerated_widget_mac/ca_layer_frame_sink.h" +#include "ui/gfx/ca_layer_params.h" #include "ui/gfx/mac/io_surface.h" #include "ui/gfx/skia_util.h" @@ -16,8 +16,7 @@ SoftwareOutputDeviceMac::Buffer::Buffer() = default; SoftwareOutputDeviceMac::Buffer::~Buffer() = default; -SoftwareOutputDeviceMac::SoftwareOutputDeviceMac(gfx::AcceleratedWidget widget) - : widget_(widget) {} +SoftwareOutputDeviceMac::SoftwareOutputDeviceMac() {} SoftwareOutputDeviceMac::~SoftwareOutputDeviceMac() {} @@ -178,17 +177,14 @@ } current_paint_canvas_.reset(); - if (widget_ != gfx::kNullAcceleratedWidget) { + if (client_) { gfx::CALayerParams ca_layer_params; ca_layer_params.is_empty = false; ca_layer_params.scale_factor = scale_factor_; ca_layer_params.pixel_size = pixel_size_; ca_layer_params.io_surface_mach_port.reset( IOSurfaceCreateMachPort(current_paint_buffer_->io_surface)); - ui::CALayerFrameSink* ca_layer_frame_sink = - ui::CALayerFrameSink::FromAcceleratedWidget(widget_); - if (ca_layer_frame_sink) - ca_layer_frame_sink->UpdateCALayerTree(ca_layer_params); + client_->SoftwareDeviceUpdatedCALayerParams(ca_layer_params); } current_paint_buffer_ = nullptr;
diff --git a/components/viz/service/display_embedder/software_output_device_mac.h b/components/viz/service/display_embedder/software_output_device_mac.h index 7329763..5b6160e 100644 --- a/components/viz/service/display_embedder/software_output_device_mac.h +++ b/components/viz/service/display_embedder/software_output_device_mac.h
@@ -14,7 +14,6 @@ #include "components/viz/service/viz_service_export.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkRegion.h" -#include "ui/gfx/native_widget_types.h" class SkCanvas; @@ -22,7 +21,7 @@ class VIZ_SERVICE_EXPORT SoftwareOutputDeviceMac : public SoftwareOutputDevice { public: - explicit SoftwareOutputDeviceMac(gfx::AcceleratedWidget widget); + SoftwareOutputDeviceMac(); ~SoftwareOutputDeviceMac() override; // SoftwareOutputDevice implementation. @@ -56,7 +55,6 @@ void UpdateAndCopyBufferDamage(Buffer* previous_paint_buffer, const SkRegion& new_damage_rect); - gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget; gfx::Size pixel_size_; float scale_factor_ = 1;
diff --git a/components/viz/service/display_embedder/software_output_device_mac_unittest.mm b/components/viz/service/display_embedder/software_output_device_mac_unittest.mm index ed0b8ad..7bb4d73e 100644 --- a/components/viz/service/display_embedder/software_output_device_mac_unittest.mm +++ b/components/viz/service/display_embedder/software_output_device_mac_unittest.mm
@@ -12,8 +12,7 @@ namespace { TEST(SoftwareOutputDeviceMacTest, Basics) { - std::unique_ptr<SoftwareOutputDeviceMac> device( - new SoftwareOutputDeviceMac(gfx::kNullAcceleratedWidget)); + auto device = std::make_unique<SoftwareOutputDeviceMac>(); gfx::Size pixel_size(512, 512); float scale_factor = 1;
diff --git a/components/viz/test/test_gles2_interface.cc b/components/viz/test/test_gles2_interface.cc index 1ce6737..fca1560 100644 --- a/components/viz/test/test_gles2_interface.cc +++ b/components/viz/test/test_gles2_interface.cc
@@ -380,10 +380,18 @@ return GL_NO_ERROR; } +size_t TestGLES2Interface::NumTextures() const { + return test_context_->NumTextures(); +} + void TestGLES2Interface::set_test_context(TestWebGraphicsContext3D* context) { DCHECK(!test_context_); test_context_ = context; InitializeTestContext(test_context_); } +void TestGLES2Interface::set_times_bind_texture_succeeds(int times) { + test_context_->set_times_bind_texture_succeeds(times); +} + } // namespace viz
diff --git a/components/viz/test/test_gles2_interface.h b/components/viz/test/test_gles2_interface.h index eb7f76a..ab470fe 100644 --- a/components/viz/test/test_gles2_interface.h +++ b/components/viz/test/test_gles2_interface.h
@@ -5,6 +5,8 @@ #ifndef COMPONENTS_VIZ_TEST_TEST_GLES2_INTERFACE_H_ #define COMPONENTS_VIZ_TEST_TEST_GLES2_INTERFACE_H_ +#include <stddef.h> + #include "gpu/command_buffer/client/gles2_interface_stub.h" namespace viz { @@ -159,7 +161,10 @@ void LoseContextCHROMIUM(GLenum current, GLenum other) override; GLenum GetGraphicsResetStatusKHR() override; + size_t NumTextures() const; + void set_test_context(TestWebGraphicsContext3D* context); + void set_times_bind_texture_succeeds(int times); protected: virtual void InitializeTestContext(TestWebGraphicsContext3D* context) {}
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc index 2749fcd1..c527f86 100644 --- a/content/browser/child_process_launcher.cc +++ b/content/browser/child_process_launcher.cc
@@ -160,13 +160,6 @@ ChildProcessLauncherHelper::ResetRegisteredFilesForTesting(); } -#if defined(OS_ANDROID) -// static -size_t ChildProcessLauncher::GetNumberOfRendererSlots() { - return ChildProcessLauncherHelper::GetNumberOfRendererSlots(); -} -#endif // OS_ANDROID - ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest( Client* client) { Client* ret = client_;
diff --git a/content/browser/child_process_launcher.h b/content/browser/child_process_launcher.h index c40e71b..0478755 100644 --- a/content/browser/child_process_launcher.h +++ b/content/browser/child_process_launcher.h
@@ -152,11 +152,6 @@ // support multiple shell context creation in unit_tests. static void ResetRegisteredFilesForTesting(); -#if defined(OS_ANDROID) - // Temporary until crbug.com/693484 is fixed. - static size_t GetNumberOfRendererSlots(); -#endif // OS_ANDROID - private: friend class internal::ChildProcessLauncherHelper;
diff --git a/content/browser/child_process_launcher_helper.h b/content/browser/child_process_launcher_helper.h index f7a66ff..bdec81b 100644 --- a/content/browser/child_process_launcher_helper.h +++ b/content/browser/child_process_launcher_helper.h
@@ -179,7 +179,6 @@ void OnChildProcessStarted(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, jint handle); - static size_t GetNumberOfRendererSlots(); #endif // OS_ANDROID private:
diff --git a/content/browser/child_process_launcher_helper_android.cc b/content/browser/child_process_launcher_helper_android.cc index ee267ce..1c6c7db 100644 --- a/content/browser/child_process_launcher_helper_android.cc +++ b/content/browser/child_process_launcher_helper_android.cc
@@ -241,13 +241,6 @@ PostLaunchOnLauncherThread(std::move(process), launch_result); } -// static -size_t ChildProcessLauncherHelper::GetNumberOfRendererSlots() { - return static_cast<size_t>( - Java_ChildProcessLauncherHelper_getNumberOfRendererSlots( - AttachCurrentThread())); -} - } // namespace internal } // namespace content
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index 917b514..1bde18a 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -255,7 +255,7 @@ #elif defined(USE_X11) return std::make_unique<viz::SoftwareOutputDeviceX11>(widget); #elif defined(OS_MACOSX) - return std::make_unique<viz::SoftwareOutputDeviceMac>(widget); + return std::make_unique<viz::SoftwareOutputDeviceMac>(); #else NOTREACHED(); return std::unique_ptr<viz::SoftwareOutputDevice>();
diff --git a/content/browser/devtools/protocol/target_handler.cc b/content/browser/devtools/protocol/target_handler.cc index 73fcc5e..7a3e181 100644 --- a/content/browser/devtools/protocol/target_handler.cc +++ b/content/browser/devtools/protocol/target_handler.cc
@@ -392,7 +392,8 @@ return Response::Error("Not supported"); } -Response TargetHandler::DisposeBrowserContext(const std::string& context_id) { +Response TargetHandler::DisposeBrowserContext(const std::string& context_id, + bool* out_success) { return Response::Error("Not supported"); }
diff --git a/content/browser/devtools/protocol/target_handler.h b/content/browser/devtools/protocol/target_handler.h index 8b6212e4..6bb18ca 100644 --- a/content/browser/devtools/protocol/target_handler.h +++ b/content/browser/devtools/protocol/target_handler.h
@@ -63,7 +63,8 @@ Response CloseTarget(const std::string& target_id, bool* out_success) override; Response CreateBrowserContext(std::string* out_context_id) override; - Response DisposeBrowserContext(const std::string& context_id) override; + Response DisposeBrowserContext(const std::string& context_id, + bool* out_success) override; Response CreateTarget(const std::string& url, Maybe<int> width, Maybe<int> height,
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc index 034a62f..e013d96a 100644 --- a/content/browser/frame_host/navigation_controller_impl_unittest.cc +++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -4054,7 +4054,7 @@ contents()->CommitPendingNavigation(); std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); other_controller.CopyStateFrom(controller, true); @@ -4103,7 +4103,7 @@ EXPECT_EQ(instance1, instance2); std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); other_contents->NavigateAndCommit(url3); other_contents->ExpectSetHistoryOffsetAndLength(2, 3); @@ -4141,7 +4141,7 @@ contents()->CommitPendingNavigation(); std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); other_contents->NavigateAndCommit(url3); other_contents->ExpectSetHistoryOffsetAndLength(1, 2); @@ -4169,7 +4169,7 @@ NavigateAndCommit(url2); std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); other_contents->NavigateAndCommit(url3); other_contents->NavigateAndCommit(url4); @@ -4199,7 +4199,7 @@ NavigateAndCommit(url2); std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); other_contents->NavigateAndCommit(url3); other_contents->NavigateAndCommit(url4); @@ -4233,7 +4233,7 @@ contents()->CommitPendingNavigation(); std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); other_contents->NavigateAndCommit(url3); other_controller.LoadURL( @@ -4267,7 +4267,7 @@ NavigateAndCommit(url1); std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); other_contents->NavigateAndCommit(url2a); // Simulate a client redirect, which has the same page ID as entry 2a. @@ -4308,7 +4308,7 @@ controller.GoBack(); std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); other_contents->NavigateAndCommit(url3); other_contents->ExpectSetHistoryOffsetAndLength(2, 3); @@ -4395,7 +4395,7 @@ NavigateAndCommit(url3); std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); other_contents->NavigateAndCommit(url4); other_contents->ExpectSetHistoryOffsetAndLength(2, 3); @@ -4436,7 +4436,7 @@ EXPECT_EQ(instance1, instance2); std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); other_contents->NavigateAndCommit(url3); other_contents->ExpectSetHistoryOffsetAndLength(1, 2); @@ -4479,7 +4479,7 @@ NavigateAndCommit(url3); std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); other_contents->NavigateAndCommit(url4); other_contents->ExpectSetHistoryOffsetAndLength(2, 3); @@ -4521,7 +4521,7 @@ // Create a WebContents with restored entries. std::unique_ptr<TestWebContents> source_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& source_controller = source_contents->GetController(); source_controller.Restore(entries.size() - 1,
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc index 46d42a11..bd71bd6 100644 --- a/content/browser/frame_host/render_frame_host_manager_unittest.cc +++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -763,19 +763,19 @@ class RenderViewHostDestroyer : public WebContentsObserver { public: RenderViewHostDestroyer(RenderViewHost* render_view_host, - WebContents* web_contents) + std::unique_ptr<WebContents> web_contents) : WebContentsObserver(WebContents::FromRenderViewHost(render_view_host)), render_view_host_(render_view_host), - web_contents_(web_contents) {} + web_contents_(std::move(web_contents)) {} void RenderViewDeleted(RenderViewHost* render_view_host) override { if (render_view_host == render_view_host_) - delete web_contents_; + web_contents_.reset(); } private: RenderViewHost* render_view_host_; - WebContents* web_contents_; + std::unique_ptr<WebContents> web_contents_; DISALLOW_COPY_AND_ASSIGN(RenderViewHostDestroyer); }; @@ -797,11 +797,11 @@ // Create one more tab and navigate to kUrl1. web_contents is not // wrapped as scoped_ptr since it intentionally deleted by destroyer // below as part of this test. - TestWebContents* web_contents = + std::unique_ptr<TestWebContents> web_contents = TestWebContents::Create(browser_context(), ntp_rfh->GetSiteInstance()); web_contents->NavigateAndCommit(kUrl1); RenderViewHostDestroyer destroyer(ntp_rfh->GetRenderViewHost(), - web_contents); + std::move(web_contents)); // This causes the first tab to navigate to kUrl2, which destroys // the ntp_rfh in ShutdownRenderViewHostsInSiteInstance(). When
diff --git a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc index 799a17c..6fcf2a7 100644 --- a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc +++ b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -147,8 +147,7 @@ browser_context_.reset(new TestBrowserContext); MockRenderProcessHost* process_host = new MockRenderProcessHost(browser_context_.get()); - web_contents_.reset( - TestWebContents::Create(browser_context_.get(), nullptr)); + web_contents_ = TestWebContents::Create(browser_context_.get(), nullptr); // We don't own the BPG, the WebContents does. browser_plugin_guest_ = new TestBrowserPluginGuest( web_contents_.get(), &browser_plugin_guest_delegate_);
diff --git a/content/browser/loader/resource_loader_unittest.cc b/content/browser/loader/resource_loader_unittest.cc index 0fcaeed..469e35d2 100644 --- a/content/browser/loader/resource_loader_unittest.cc +++ b/content/browser/loader/resource_loader_unittest.cc
@@ -471,8 +471,8 @@ browser_context_.reset(new TestBrowserContext()); scoped_refptr<SiteInstance> site_instance = SiteInstance::Create(browser_context_.get()); - web_contents_.reset( - TestWebContents::Create(browser_context_.get(), site_instance.get())); + web_contents_ = + TestWebContents::Create(browser_context_.get(), site_instance.get()); SetUpResourceLoaderForUrl(test_redirect_url()); }
diff --git a/content/browser/media/media_source_browsertest.cc b/content/browser/media/media_source_browsertest.cc index e5571a3b..5e3cb000 100644 --- a/content/browser/media/media_source_browsertest.cc +++ b/content/browser/media/media_source_browsertest.cc
@@ -24,14 +24,12 @@ #endif const char kWebMVideoOnly[] = "video/webm; codecs=\"vp8\""; const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\""; - -#if BUILDFLAG(USE_PROPRIETARY_CODECS) const char kMp4FlacAudioOnly[] = "audio/mp4; codecs=\"flac\""; -#if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) +#if BUILDFLAG(USE_PROPRIETARY_CODECS) && \ + BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) const char kMp2tAudioVideo[] = "video/mp2t; codecs=\"mp4a.40.2, avc1.42E01E\""; #endif -#endif namespace content { @@ -51,7 +49,6 @@ command_line->AppendSwitchASCII( switches::kAutoplayPolicy, switches::autoplay::kNoUserGestureRequiredPolicy); - scoped_feature_list_.InitAndDisableFeature(media::kMseFlacInIsobmff); } protected: @@ -121,12 +118,11 @@ true); } -IN_PROC_BROWSER_TEST_F(MediaSourceTest, - Playback_AudioOnly_FLAC_MP4_Unsupported) { - // The feature is disabled by test setup, so verify playback failure. - TestSimplePlayback("bear-flac_frag.mp4", kMp4FlacAudioOnly, media::kFailed); +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) + +IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_AudioOnly_FLAC_MP4) { + TestSimplePlayback("bear-flac_frag.mp4", kMp4FlacAudioOnly, media::kEnded); } -#endif #if BUILDFLAG(USE_PROPRIETARY_CODECS) #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) @@ -136,24 +132,4 @@ #endif #endif -#if BUILDFLAG(USE_PROPRIETARY_CODECS) -class MediaSourceFlacInIsobmffTest : public content::MediaSourceTest { - public: - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitchASCII( - switches::kAutoplayPolicy, - switches::autoplay::kNoUserGestureRequiredPolicy); - - // Enable MSE FLAC-in-MP4 feature. - scoped_feature_list_.InitAndEnableFeature(media::kMseFlacInIsobmff); - } -}; - -IN_PROC_BROWSER_TEST_F(MediaSourceFlacInIsobmffTest, - Playback_AudioOnly_FLAC_MP4_Supported) { - // The feature is enabled by test setup, so verify playback success. - TestSimplePlayback("bear-flac_frag.mp4", kMp4FlacAudioOnly, media::kEnded); -} -#endif - } // namespace content
diff --git a/content/browser/media/session/audio_focus_manager_unittest.cc b/content/browser/media/session/audio_focus_manager_unittest.cc index a0bb13d1..459ce508 100644 --- a/content/browser/media/session/audio_focus_manager_unittest.cc +++ b/content/browser/media/session/audio_focus_manager_unittest.cc
@@ -102,7 +102,7 @@ session->AbandonSystemAudioFocusIfNeeded(); } - WebContents* CreateWebContents() { + std::unique_ptr<WebContents> CreateWebContents() { return TestWebContents::Create(browser_context_.get(), SiteInstance::SiteInstance::Create(browser_context_.get())); }
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h index 1fbbedd..7f0ce8a 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.h +++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -197,12 +197,6 @@ gfx::Size dfh_size_dip_; display::Display dfh_display_; - // The viz::ParentLocalSurfaceIdAllocator for the ui::Compositor dispenses - // viz::LocalSurfaceIds that are renderered into by the ui::Compositor. - viz::ParentLocalSurfaceIdAllocator compositor_local_surface_id_allocator_; - gfx::Size compositor_size_pixels_; - float compositor_scale_factor_ = 1.f; - // Used to disable screen updates while resizing (because frames are drawn in // the GPU process, they can end up appearing on-screen before our window // resizes).
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm index b83bbad5..c1c7a42 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.mm +++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -75,6 +75,8 @@ ui::AcceleratedWidgetMac* accelerated_widget_mac() { return accelerated_widget_mac_.get(); } + const gfx::Size pixel_size() const { return size_pixels_; } + float scale_factor() const { return scale_factor_; } // Suspend will prevent the compositor from producing new frames. This should // be called to avoid creating spurious frames while changing state. @@ -82,6 +84,20 @@ void Suspend(); void Unsuspend(); + // Update the compositor's surface information, set |root_layer| to be the + // compositor root layer, and resize |root_layer|. + void UpdateSurfaceAndUnsuspend(const gfx::Size& size_pixels, + float scale_factor, + ui::Layer* root_layer); + // Invalidate the compositor's surface information. + void InvalidateSurface(); + + // The viz::ParentLocalSurfaceIdAllocator for the ui::Compositor dispenses + // viz::LocalSurfaceIds that are renderered into by the ui::Compositor. + viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_; + gfx::Size size_pixels_; + float scale_factor_ = 1.f; + private: RecyclableCompositorMac(); @@ -129,6 +145,32 @@ compositor_suspended_lock_ = nullptr; } +void RecyclableCompositorMac::UpdateSurfaceAndUnsuspend( + const gfx::Size& size_pixels, + float scale_factor, + ui::Layer* root_layer) { + if (size_pixels != size_pixels_ || scale_factor != scale_factor_) { + size_pixels_ = size_pixels; + scale_factor_ = scale_factor; + compositor()->SetScaleAndSize(scale_factor_, size_pixels_, + local_surface_id_allocator_.GenerateId()); + } + compositor()->SetRootLayer(root_layer); + root_layer->SetBounds( + gfx::Rect(gfx::ConvertSizeToDIP(scale_factor, size_pixels))); + Unsuspend(); +} + +void RecyclableCompositorMac::InvalidateSurface() { + size_pixels_ = gfx::Size(); + scale_factor_ = 1.f; + local_surface_id_allocator_.Invalidate(); + compositor()->SetScaleAndSize( + scale_factor_, size_pixels_, + local_surface_id_allocator_.GetCurrentLocalSurfaceId()); + compositor()->SetRootLayer(nullptr); +} + void RecyclableCompositorMac::OnCompositingDidCommit( ui::Compositor* compositor_that_did_commit) { DCHECK_EQ(compositor_that_did_commit, compositor()); @@ -353,7 +395,6 @@ // Transition HasNoCompositor -> HasDetachedCompositor. if (state_ == HasNoCompositor && new_state != HasNoCompositor) { recyclable_compositor_ = RecyclableCompositorMac::Create(); - recyclable_compositor_->compositor()->SetRootLayer(root_layer_.get()); recyclable_compositor_->compositor()->SetBackgroundColor(background_color_); recyclable_compositor_->compositor()->SetDisplayColorSpace( dfh_display_.color_space()); @@ -372,17 +413,9 @@ // now (if one is not ready, the compositor will unsuspend on first surface // activation). if (delegated_frame_host_->HasSavedFrame()) { - if (compositor_scale_factor_ != dfh_display_.device_scale_factor() || - compositor_size_pixels_ != dfh_size_pixels_) { - compositor_scale_factor_ = dfh_display_.device_scale_factor(); - compositor_size_pixels_ = dfh_size_pixels_; - root_layer_->SetBounds(gfx::Rect(gfx::ConvertSizeToDIP( - compositor_scale_factor_, compositor_size_pixels_))); - recyclable_compositor_->compositor()->SetScaleAndSize( - compositor_scale_factor_, compositor_size_pixels_, - compositor_local_surface_id_allocator_.GenerateId()); - } - recyclable_compositor_->Unsuspend(); + recyclable_compositor_->UpdateSurfaceAndUnsuspend( + dfh_size_pixels_, dfh_display_.device_scale_factor(), + root_layer_.get()); } state_ = HasAttachedCompositor; @@ -403,13 +436,7 @@ // Transition HasDetachedCompositor -> HasNoCompositor. if (state_ == HasDetachedCompositor && new_state == HasNoCompositor) { recyclable_compositor_->accelerated_widget_mac()->ResetNSView(); - compositor_scale_factor_ = 1.f; - compositor_size_pixels_ = gfx::Size(); - compositor_local_surface_id_allocator_.Invalidate(); - recyclable_compositor_->compositor()->SetScaleAndSize( - compositor_scale_factor_, compositor_size_pixels_, - compositor_local_surface_id_allocator_.GetCurrentLocalSurfaceId()); - recyclable_compositor_->compositor()->SetRootLayer(nullptr); + recyclable_compositor_->InvalidateSurface(); RecyclableCompositorMac::Recycle(std::move(recyclable_compositor_)); state_ = HasNoCompositor; } @@ -469,27 +496,17 @@ if (!recyclable_compositor_) return; - recyclable_compositor_->Unsuspend(); - - // Resize the compositor to match the current frame size, if needed. - if (compositor_size_pixels_ == surface_info.size_in_pixels() && - compositor_scale_factor_ == surface_info.device_scale_factor()) { - return; - } - compositor_size_pixels_ = surface_info.size_in_pixels(); - compositor_scale_factor_ = surface_info.device_scale_factor(); - root_layer_->SetBounds(gfx::Rect(gfx::ConvertSizeToDIP( - compositor_scale_factor_, compositor_size_pixels_))); - recyclable_compositor_->compositor()->SetScaleAndSize( - compositor_scale_factor_, compositor_size_pixels_, - compositor_local_surface_id_allocator_.GenerateId()); + recyclable_compositor_->UpdateSurfaceAndUnsuspend( + surface_info.size_in_pixels(), surface_info.device_scale_factor(), + root_layer_.get()); // Disable screen updates until the frame of the new size appears (because the // content is drawn in the GPU process, it may change before we want it to). if (repaint_state_ == RepaintState::Paused) { bool compositor_is_nsview_size = - compositor_size_pixels_ == dfh_size_pixels_ && - compositor_scale_factor_ == dfh_display_.device_scale_factor(); + recyclable_compositor_->pixel_size() == dfh_size_pixels_ && + recyclable_compositor_->scale_factor() == + dfh_display_.device_scale_factor(); if (compositor_is_nsview_size || repaint_auto_resize_enabled_) { NSDisableScreenUpdates(); repaint_state_ = RepaintState::ScreenUpdatesDisabled;
diff --git a/content/browser/renderer_host/frame_sink_provider_impl.cc b/content/browser/renderer_host/frame_sink_provider_impl.cc index 8b1215bfdb..b984d94 100644 --- a/content/browser/renderer_host/frame_sink_provider_impl.cc +++ b/content/browser/renderer_host/frame_sink_provider_impl.cc
@@ -27,7 +27,21 @@ void FrameSinkProviderImpl::CreateForWidget( int32_t widget_id, viz::mojom::CompositorFrameSinkRequest compositor_frame_sink_request, - viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client, + viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client) { + RenderWidgetHostImpl* render_widget_host_impl = + RenderWidgetHostImpl::FromID(process_id_, widget_id); + if (!render_widget_host_impl) { + DLOG(ERROR) << "No RenderWidgetHost exists with id " << widget_id + << " in process " << process_id_; + return; + } + render_widget_host_impl->RequestCompositorFrameSink( + std::move(compositor_frame_sink_request), + std::move(compositor_frame_sink_client)); +} + +void FrameSinkProviderImpl::RegisterRenderFrameMetadataObserver( + int32_t widget_id, mojom::RenderFrameMetadataObserverClientRequest render_frame_metadata_observer_client_request, mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer) { @@ -38,9 +52,7 @@ << " in process " << process_id_; return; } - render_widget_host_impl->RequestCompositorFrameSink( - std::move(compositor_frame_sink_request), - std::move(compositor_frame_sink_client), + render_widget_host_impl->RegisterRenderFrameMetadataObserver( std::move(render_frame_metadata_observer_client_request), std::move(render_frame_metadata_observer)); }
diff --git a/content/browser/renderer_host/frame_sink_provider_impl.h b/content/browser/renderer_host/frame_sink_provider_impl.h index e717c44..05949c53 100644 --- a/content/browser/renderer_host/frame_sink_provider_impl.h +++ b/content/browser/renderer_host/frame_sink_provider_impl.h
@@ -25,7 +25,10 @@ void CreateForWidget( int32_t widget_id, viz::mojom::CompositorFrameSinkRequest compositor_frame_sink_request, - viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client, + viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client) + override; + void RegisterRenderFrameMetadataObserver( + int32_t widget_id, mojom::RenderFrameMetadataObserverClientRequest render_frame_metadata_observer_client_request, mojom::RenderFrameMetadataObserverPtr observer) override;
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 d16a615..c0aec90 100644 --- a/content/browser/renderer_host/render_frame_metadata_provider_impl.cc +++ b/content/browser/renderer_host/render_frame_metadata_provider_impl.cc
@@ -66,6 +66,12 @@ void RenderFrameMetadataProviderImpl::OnRenderFrameMetadataChanged( uint32_t frame_token, const cc::RenderFrameMetadata& metadata) { + if (metadata.local_surface_id != last_local_surface_id_) { + last_local_surface_id_ = metadata.local_surface_id; + for (Observer& observer : observers_) + observer.OnLocalSurfaceIdChanged(metadata); + } + // Both RenderFrameMetadataProviderImpl and FrameTokenMessageQueue are owned // by the same RenderWidgetHostImpl. During shutdown the queue is cleared // without running the callbacks.
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 48ab56154..fb101fb 100644 --- a/content/browser/renderer_host/render_frame_metadata_provider_impl.h +++ b/content/browser/renderer_host/render_frame_metadata_provider_impl.h
@@ -67,6 +67,8 @@ cc::RenderFrameMetadata last_render_frame_metadata_; + base::Optional<viz::LocalSurfaceId> last_local_surface_id_; + // Not owned. FrameTokenMessageQueue* const frame_token_message_queue_;
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index ece068e..ddda2189 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1273,13 +1273,7 @@ // On Android we don't maintain a limit of renderer process hosts - we are // happy with keeping a lot of these, as long as the number of live renderer // processes remains reasonable, and on Android the OS takes care of that. - // TODO(boliu): This is a short term workaround before ChildProcessLauncher - // can actively kill child processes in LRU order. Bug and process is tracked - // in crbug.com/693484. Note this workaround is not perfect and still has - // corner case problems. - static const size_t kNumRendererSlots = - ChildProcessLauncher::GetNumberOfRendererSlots(); - return kNumRendererSlots; + return std::numeric_limits<size_t>::max(); #endif #if defined(OS_CHROMEOS) // On Chrome OS new renderer processes are very cheap and there's no OS
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h index b8906bb6..ff8cef7 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.h +++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -38,10 +38,6 @@ class UkmRecorder; } -namespace viz { -class LocalSurfaceId; -} - namespace content { class BrowserAccessibilityManager; @@ -80,10 +76,8 @@ bool width_changed) {} // The contents auto-resized and the container should match it. - virtual void ResizeDueToAutoResize( - RenderWidgetHostImpl* render_widget_host, - const gfx::Size& new_size, - const viz::LocalSurfaceId& local_surface_id) {} + virtual void ResizeDueToAutoResize(RenderWidgetHostImpl* render_widget_host, + const gfx::Size& new_size) {} // Callback to give the browser a chance to handle the specified keyboard // event before sending it to the renderer. See enum for details on return
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 4f629c96..35e004dc 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -2141,47 +2141,42 @@ void RenderWidgetHostImpl::OnResizeOrRepaintACK( const ViewHostMsg_ResizeOrRepaint_ACK_Params& params) { - TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnResizeOrRepaintACK"); - - // Update our knowledge of the RenderWidget's size. - current_size_ = params.view_size; - - resize_ack_pending_ = false; - - DCHECK(!params.view_size.IsEmpty()); - - DidCompleteResizeOrRepaint(params); - - if (auto_resize_enabled_ && view_) { - viz::ScopedSurfaceIdAllocator scoped_allocator = - view_->ResizeDueToAutoResize(params.view_size, - *params.child_allocated_local_surface_id); - - if (delegate_) { - delegate_->ResizeDueToAutoResize( - this, params.view_size, *params.child_allocated_local_surface_id); - } - } + DidUpdateVisualProperties(params.view_size, + params.child_allocated_local_surface_id); } -void RenderWidgetHostImpl::DidCompleteResizeOrRepaint( - const ViewHostMsg_ResizeOrRepaint_ACK_Params& params) { +void RenderWidgetHostImpl::DidUpdateVisualProperties( + const gfx::Size& viewport_size_in_dip, + const base::Optional<viz::LocalSurfaceId>& + child_allocated_local_surface_id) { TRACE_EVENT0("renderer_host", - "RenderWidgetHostImpl::DidCompleteResizeOrRepaint"); + "RenderWidgetHostImpl::DidUpdateVisualProperties"); + + // Update our knowledge of the RenderWidget's size. + DCHECK(!viewport_size_in_dip.IsEmpty()); + // TODO(fsamuel): The fact that we translate the viewport_size from pixels + // to DIP is concerning. This could result in invariants violations. + current_size_ = viewport_size_in_dip; + + resize_ack_pending_ = false; NotificationService::current()->Notify( NOTIFICATION_RENDER_WIDGET_HOST_DID_COMPLETE_RESIZE_OR_REPAINT, Source<RenderWidgetHost>(this), NotificationService::NoDetails()); - // We don't need to update the view if the view is hidden. We must do this - // early return after the ACK is sent, however, or the renderer will not send - // us more data. - if (is_hidden_) - return; - // If we got an ack, then perhaps we have another change of visual properties // to send? - SynchronizeVisualProperties(); + if (!is_hidden_) + SynchronizeVisualProperties(); + + if (auto_resize_enabled_ && view_) { + viz::ScopedSurfaceIdAllocator scoped_allocator = + view_->ResizeDueToAutoResize(viewport_size_in_dip, + *child_allocated_local_surface_id); + + if (delegate_) + delegate_->ResizeDueToAutoResize(this, viewport_size_in_dip); + } } void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) { @@ -2743,13 +2738,7 @@ void RenderWidgetHostImpl::RequestCompositorFrameSink( viz::mojom::CompositorFrameSinkRequest compositor_frame_sink_request, - viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client, - mojom::RenderFrameMetadataObserverClientRequest - render_frame_metadata_observer_client_request, - mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer) { - render_frame_metadata_provider_.Bind( - std::move(render_frame_metadata_observer_client_request), - std::move(render_frame_metadata_observer)); + viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client) { if (enable_viz_) { // Connects the viz process end of CompositorFrameSink message pipes. The // renderer compositor may request a new CompositorFrameSink on context @@ -2785,6 +2774,15 @@ renderer_compositor_frame_sink_ = std::move(compositor_frame_sink_client); } +void RenderWidgetHostImpl::RegisterRenderFrameMetadataObserver( + mojom::RenderFrameMetadataObserverClientRequest + render_frame_metadata_observer_client_request, + mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer) { + render_frame_metadata_provider_.Bind( + std::move(render_frame_metadata_observer_client_request), + std::move(render_frame_metadata_observer)); +} + bool RenderWidgetHostImpl::HasGestureStopped() { return !input_router_->HasPendingEvents(); } @@ -3102,4 +3100,13 @@ touch_emulator_->SetDoubleTapSupportForPageEnabled(!is_mobile_optimized); } +void RenderWidgetHostImpl::OnLocalSurfaceIdChanged( + const cc::RenderFrameMetadata& metadata) { + if (!enable_surface_synchronization_) + return; + gfx::Size viewport_size_in_dip = gfx::ScaleToCeiledSize( + metadata.viewport_size_in_pixels, 1.f / metadata.device_scale_factor); + DidUpdateVisualProperties(viewport_size_in_dip, metadata.local_surface_id); +} + } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 7cae9ef7..57dacf6 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -609,7 +609,9 @@ void RequestCompositorFrameSink( viz::mojom::CompositorFrameSinkRequest compositor_frame_sink_request, - viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client, + viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client); + + void RegisterRenderFrameMetadataObserver( mojom::RenderFrameMetadataObserverClientRequest render_frame_metadata_observer_client_request, mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer); @@ -817,9 +819,10 @@ void OnFrameSwapMessagesReceived(uint32_t frame_token, std::vector<IPC::Message> messages); - // Called after resize or repaint has completed in the renderer. - void DidCompleteResizeOrRepaint( - const ViewHostMsg_ResizeOrRepaint_ACK_Params& params); + // Called when visual properties have changed in the renderer. + void DidUpdateVisualProperties(const gfx::Size& viewport_size_in_dip, + const base::Optional<viz::LocalSurfaceId>& + child_allocated_local_surface_id); // Give key press listeners a chance to handle this key press. This allow // widgets that don't have focus to still handle key presses. @@ -885,6 +888,8 @@ // RenderFrameMetadataProvider::Observer implementation. void OnRenderFrameMetadataChanged() override; void OnRenderFrameSubmission() override {} + void OnLocalSurfaceIdChanged( + const cc::RenderFrameMetadata& metadata) override; // true if a renderer has once been valid. We use this flag to display a sad // tab only when we lose our renderer and not if a paint occurs during
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc index e3d8341..4156c085 100644 --- a/content/browser/renderer_host/render_widget_host_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -719,7 +719,9 @@ std::move(render_frame_metadata_observer_client_info)); host_->RequestCompositorFrameSink( - std::move(sink_request), std::move(renderer_compositor_frame_sink_ptr_), + std::move(sink_request), + std::move(renderer_compositor_frame_sink_ptr_)); + host_->RegisterRenderFrameMetadataObserver( std::move(render_frame_metadata_observer_client_request), std::move(renderer_render_frame_metadata_observer_ptr)); }
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 dc00f30..7dad684b 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -111,6 +111,9 @@ void RenderWidgetHostViewBase::OnRenderFrameSubmission() {} +void RenderWidgetHostViewBase::OnLocalSurfaceIdChanged( + const cc::RenderFrameMetadata& metadata) {} + void RenderWidgetHostViewBase::SetBackgroundColorToDefault() { SetBackgroundColor(SK_ColorWHITE); }
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 a7dd53e..cd7fba6d 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -150,6 +150,8 @@ // RenderFrameMetadataProvider::Observer void OnRenderFrameMetadataChanged() override; void OnRenderFrameSubmission() override; + void OnLocalSurfaceIdChanged( + const cc::RenderFrameMetadata& metadata) override; void SetPopupType(blink::WebPopupType popup_type);
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 6cd9b0f..eed2f40e 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -11700,6 +11700,60 @@ EXPECT_LE(compositing_rect.y(), expected_offset + 2); } +// Verify that OOPIF select element popup menu coordinates account for scroll +// offset in containers embedding frame. +IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, PopupMenuInTallIframeTest) { + GURL main_url(embedded_test_server()->GetURL( + "/frame_tree/page_with_tall_positioned_frame.html")); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + + FrameTreeNode* root = web_contents()->GetFrameTree()->root(); + FrameTreeNode* child_node = root->child_at(0); + GURL site_url(embedded_test_server()->GetURL( + "baz.com", "/site_isolation/page-with-select.html")); + NavigateFrameToURL(child_node, site_url); + + scoped_refptr<UpdateViewportIntersectionMessageFilter> filter = + new UpdateViewportIntersectionMessageFilter(); + root->current_frame_host()->GetProcess()->AddFilter(filter.get()); + + // Position the select element so that it is out of the viewport, then scroll + // it into view. + EXPECT_TRUE(ExecuteScript( + child_node, "document.querySelector('select').style.top='2000px';")); + EXPECT_TRUE(ExecuteScript(root, "window.scrollTo(0, 1900);")); + + // Wait for a viewport intersection update to be dispatched to the child, and + // ensure it is processed by the browser before continuing. + filter->Wait(); + { + // This yields the UI thread in order to ensure that the new viewport + // intersection is sent to the to child renderer before the mouse click + // below. + base::RunLoop loop; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + loop.QuitClosure()); + loop.Run(); + } + + scoped_refptr<ShowWidgetMessageFilter> show_widget_filter = + new ShowWidgetMessageFilter(); + child_node->current_frame_host()->GetProcess()->AddFilter( + show_widget_filter.get()); + + SimulateMouseClick(child_node->current_frame_host()->GetRenderWidgetHost(), + 55, 2005); + + // Dismiss the popup. + SimulateMouseClick(child_node->current_frame_host()->GetRenderWidgetHost(), 1, + 1); + + // The test passes if this wait returns, indicating that the popup was + // scrolled into view and the OOPIF renderer displayed it. Other tests verify + // the correctness of popup menu coordinates. + show_widget_filter->Wait(); +} + namespace { // Helper class to intercept DidCommitProvisionalLoad messages and inject a
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc index 4ccf2aa..e4fc772b 100644 --- a/content/browser/site_per_process_hit_test_browsertest.cc +++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -3219,76 +3219,6 @@ CreateContextMenuTestHelper(shell(), embedded_test_server()); } -class ShowWidgetMessageFilter : public content::BrowserMessageFilter { - public: - ShowWidgetMessageFilter() -#if defined(OS_MACOSX) || defined(OS_ANDROID) - : content::BrowserMessageFilter(FrameMsgStart), -#else - : content::BrowserMessageFilter(ViewMsgStart), -#endif - message_loop_runner_(new content::MessageLoopRunner) { - } - - bool OnMessageReceived(const IPC::Message& message) override { - IPC_BEGIN_MESSAGE_MAP(ShowWidgetMessageFilter, message) -#if defined(OS_MACOSX) || defined(OS_ANDROID) - IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup) -#else - IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget) -#endif - IPC_END_MESSAGE_MAP() - return false; - } - - gfx::Rect last_initial_rect() const { return initial_rect_; } - - int last_routing_id() const { return routing_id_; } - - void Wait() { - initial_rect_ = gfx::Rect(); - routing_id_ = MSG_ROUTING_NONE; - message_loop_runner_->Run(); - } - - void Reset() { - initial_rect_ = gfx::Rect(); - routing_id_ = MSG_ROUTING_NONE; - message_loop_runner_ = new content::MessageLoopRunner; - } - - private: - ~ShowWidgetMessageFilter() override {} - - void OnShowWidget(int route_id, const gfx::Rect& initial_rect) { - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::BindOnce(&ShowWidgetMessageFilter::OnShowWidgetOnUI, this, - route_id, initial_rect)); - } - -#if defined(OS_MACOSX) || defined(OS_ANDROID) - void OnShowPopup(const FrameHostMsg_ShowPopup_Params& params) { - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&ShowWidgetMessageFilter::OnShowWidgetOnUI, this, - MSG_ROUTING_NONE, params.bounds)); - } -#endif - - void OnShowWidgetOnUI(int route_id, const gfx::Rect& initial_rect) { - initial_rect_ = initial_rect; - routing_id_ = route_id; - message_loop_runner_->Quit(); - } - - scoped_refptr<content::MessageLoopRunner> message_loop_runner_; - gfx::Rect initial_rect_; - int routing_id_; - - DISALLOW_COPY_AND_ASSIGN(ShowWidgetMessageFilter); -}; - // Test that clicking a select element in an out-of-process iframe creates // a popup menu in the correct position. IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, PopupMenuTest) {
diff --git a/content/browser/web_contents/aura/gesture_nav_simple_unittest.cc b/content/browser/web_contents/aura/gesture_nav_simple_unittest.cc index 9864bef..f3da97e 100644 --- a/content/browser/web_contents/aura/gesture_nav_simple_unittest.cc +++ b/content/browser/web_contents/aura/gesture_nav_simple_unittest.cc
@@ -19,16 +19,24 @@ // A subclass of TestWebContents that offers a fake content window. class GestureNavTestWebContents : public TestWebContents { public: + explicit GestureNavTestWebContents( + BrowserContext* browser_context, + std::unique_ptr<aura::Window> fake_native_view, + std::unique_ptr<aura::Window> fake_contents_window) + : TestWebContents(browser_context), + fake_native_view_(std::move(fake_native_view)), + fake_contents_window_(std::move(fake_contents_window)) {} ~GestureNavTestWebContents() override {} - static GestureNavTestWebContents* Create( + static std::unique_ptr<GestureNavTestWebContents> Create( BrowserContext* browser_context, scoped_refptr<SiteInstance> instance, std::unique_ptr<aura::Window> fake_native_view, std::unique_ptr<aura::Window> fake_contents_window) { - auto* web_contents = new GestureNavTestWebContents( - browser_context, std::move(fake_native_view), - std::move(fake_contents_window)); + std::unique_ptr<GestureNavTestWebContents> web_contents = + std::make_unique<GestureNavTestWebContents>( + browser_context, std::move(fake_native_view), + std::move(fake_contents_window)); web_contents->Init( WebContents::CreateParams(browser_context, std::move(instance))); return web_contents; @@ -41,15 +49,6 @@ return fake_contents_window_.get(); } - protected: - explicit GestureNavTestWebContents( - BrowserContext* browser_context, - std::unique_ptr<aura::Window> fake_native_view, - std::unique_ptr<aura::Window> fake_contents_window) - : TestWebContents(browser_context), - fake_native_view_(std::move(fake_native_view)), - fake_contents_window_(std::move(fake_contents_window)) {} - private: std::unique_ptr<aura::Window> fake_native_view_; std::unique_ptr<aura::Window> fake_contents_window_;
diff --git a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc index 64c159c..a592c0b7 100644 --- a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc +++ b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
@@ -71,16 +71,25 @@ // A subclass of TestWebContents that offers a fake content window. class OverscrollTestWebContents : public TestWebContents { public: + explicit OverscrollTestWebContents( + BrowserContext* browser_context, + std::unique_ptr<aura::Window> fake_native_view, + std::unique_ptr<aura::Window> fake_contents_window) + : TestWebContents(browser_context), + fake_native_view_(std::move(fake_native_view)), + fake_contents_window_(std::move(fake_contents_window)), + is_being_destroyed_(false) {} ~OverscrollTestWebContents() override {} - static OverscrollTestWebContents* Create( + static std::unique_ptr<OverscrollTestWebContents> Create( BrowserContext* browser_context, scoped_refptr<SiteInstance> instance, std::unique_ptr<aura::Window> fake_native_view, std::unique_ptr<aura::Window> fake_contents_window) { - OverscrollTestWebContents* web_contents = new OverscrollTestWebContents( - browser_context, std::move(fake_native_view), - std::move(fake_contents_window)); + std::unique_ptr<OverscrollTestWebContents> web_contents = + std::make_unique<OverscrollTestWebContents>( + browser_context, std::move(fake_native_view), + std::move(fake_contents_window)); web_contents->Init( WebContents::CreateParams(browser_context, std::move(instance))); return web_contents; @@ -100,16 +109,6 @@ bool IsBeingDestroyed() const override { return is_being_destroyed_; } - protected: - explicit OverscrollTestWebContents( - BrowserContext* browser_context, - std::unique_ptr<aura::Window> fake_native_view, - std::unique_ptr<aura::Window> fake_contents_window) - : TestWebContents(browser_context), - fake_native_view_(std::move(fake_native_view)), - fake_contents_window_(std::move(fake_contents_window)), - is_being_destroyed_(false) {} - private: std::unique_ptr<aura::Window> fake_native_view_; std::unique_ptr<aura::Window> fake_contents_window_;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 3a9d68d..189b3f0 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -266,8 +266,7 @@ std::unique_ptr<WebContents> WebContents::Create( const WebContents::CreateParams& params) { - return base::WrapUnique( - WebContentsImpl::CreateWithOpener(params, FindOpenerRFH(params))); + return WebContentsImpl::CreateWithOpener(params, FindOpenerRFH(params)); } std::unique_ptr<WebContents> WebContents::CreateWithSessionStorage( @@ -643,14 +642,15 @@ SetDelegate(nullptr); } -WebContentsImpl* WebContentsImpl::CreateWithOpener( +std::unique_ptr<WebContentsImpl> WebContentsImpl::CreateWithOpener( const WebContents::CreateParams& params, RenderFrameHostImpl* opener_rfh) { TRACE_EVENT0("browser", "WebContentsImpl::CreateWithOpener"); FrameTreeNode* opener = nullptr; if (opener_rfh) opener = opener_rfh->frame_tree_node(); - WebContentsImpl* new_contents = new WebContentsImpl(params.browser_context); + std::unique_ptr<WebContentsImpl> new_contents( + new WebContentsImpl(params.browser_context)); new_contents->SetOpenerForNewContents(opener, params.opener_suppressed); // If the opener is sandboxed, a new popup must inherit the opener's sandbox @@ -684,7 +684,7 @@ if (params.guest_delegate) { // This makes |new_contents| act as a guest. // For more info, see comment above class BrowserPluginGuest. - BrowserPluginGuest::Create(new_contents, params.guest_delegate); + BrowserPluginGuest::Create(new_contents.get(), params.guest_delegate); // We are instantiating a WebContents for browser plugin. Set its subframe // bit to true. new_contents->is_subframe_ = true; @@ -1701,7 +1701,7 @@ if (opener) opener_rfh = opener->current_frame_host(); std::unique_ptr<WebContentsImpl> tc = - base::WrapUnique(CreateWithOpener(create_params, opener_rfh)); + CreateWithOpener(create_params, opener_rfh); tc->GetController().CopyStateFrom(controller_, true); for (auto& observer : observers_) observer.DidCloneToNewWebContents(this, tc.get()); @@ -2941,8 +2941,7 @@ void WebContentsImpl::ResizeDueToAutoResize( RenderWidgetHostImpl* render_widget_host, - const gfx::Size& new_size, - const viz::LocalSurfaceId& local_surface_id) { + const gfx::Size& new_size) { if (render_widget_host != GetRenderViewHost()->GetWidget()) return;
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index ef7ca07..a5cfbff9 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -137,7 +137,7 @@ ~WebContentsImpl() override; - static WebContentsImpl* CreateWithOpener( + static std::unique_ptr<WebContentsImpl> CreateWithOpener( const WebContents::CreateParams& params, RenderFrameHostImpl* opener_rfh); @@ -696,10 +696,8 @@ void RenderWidgetWasResized(RenderWidgetHostImpl* render_widget_host, const ScreenInfo& screen_info, bool width_changed) override; - void ResizeDueToAutoResize( - RenderWidgetHostImpl* render_widget_host, - const gfx::Size& new_size, - const viz::LocalSurfaceId& local_surface_id) override; + void ResizeDueToAutoResize(RenderWidgetHostImpl* render_widget_host, + const gfx::Size& new_size) override; gfx::Size GetAutoResizeSize() override; void ResetAutoResizeSize() override; KeyboardEventProcessingResult PreHandleKeyboardEvent(
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc index a3e61b4..c4067cf5 100644 --- a/content/browser/web_contents/web_contents_impl_unittest.cc +++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -2582,7 +2582,7 @@ // Create another NavigationController. GURL url3("http://foo2"); std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); other_contents->NavigateAndCommit(url3); other_contents->ExpectSetHistoryOffsetAndLength(1, 2); @@ -2607,7 +2607,7 @@ // Create another NavigationController. std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); NavigationControllerImpl& other_controller = other_contents->GetController(); // Navigate it to url2. @@ -2657,7 +2657,7 @@ // Create and navigate another WebContents. std::unique_ptr<TestWebContents> other_contents( - static_cast<TestWebContents*>(CreateTestWebContents())); + static_cast<TestWebContents*>(CreateTestWebContents().release())); TestWebContentsObserver other_observer(other_contents.get()); other_contents->NavigateAndCommit(url_normalized); @@ -2670,7 +2670,7 @@ // crash. TEST_F(WebContentsImplTest, PendingContentsDestroyed) { std::unique_ptr<WebContentsImpl> other_contents( - static_cast<WebContentsImpl*>(CreateTestWebContents())); + static_cast<WebContentsImpl*>(CreateTestWebContents().release())); content::TestWebContents* raw_other_contents = static_cast<TestWebContents*>(other_contents.get()); contents()->AddPendingContents(std::move(other_contents)); @@ -2687,7 +2687,7 @@ TEST_F(WebContentsImplTest, PendingContentsShown) { std::unique_ptr<WebContents> other_contents( - static_cast<WebContents*>(CreateTestWebContents())); + static_cast<WebContents*>(CreateTestWebContents().release())); content::WebContents* raw_other_contents = other_contents.get(); content::TestWebContents* test_web_contents = static_cast<content::TestWebContents*>(other_contents.get());
diff --git a/content/common/external_ipc_dumper.cc b/content/common/external_ipc_dumper.cc index ec04130..f9ab7e69 100644 --- a/content/common/external_ipc_dumper.cc +++ b/content/common/external_ipc_dumper.cc
@@ -27,6 +27,7 @@ namespace content { +NO_SANITIZE("cfi-icall") IPC::ChannelProxy::OutgoingMessageFilter* LoadExternalIPCDumper( const base::FilePath& dump_directory) { base::FilePath module_path;
diff --git a/content/common/frame_sink_provider.mojom b/content/common/frame_sink_provider.mojom index ad84346d..003f761e 100644 --- a/content/common/frame_sink_provider.mojom +++ b/content/common/frame_sink_provider.mojom
@@ -1,3 +1,7 @@ +// 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. + module content.mojom; import "content/common/render_frame_metadata.mojom"; @@ -11,7 +15,10 @@ CreateForWidget( int32 widget_id, viz.mojom.CompositorFrameSink& compositor_frame_sink_request, - viz.mojom.CompositorFrameSinkClient compositor_frame_sink_client, + viz.mojom.CompositorFrameSinkClient compositor_frame_sink_client); + + RegisterRenderFrameMetadataObserver( + int32 widget_id, RenderFrameMetadataObserverClient& render_frame_metadata_observer_client_request, RenderFrameMetadataObserver render_frame_metadata_observer);
diff --git a/content/common/render_frame_metadata.mojom b/content/common/render_frame_metadata.mojom index 94748c6..3558eae 100644 --- a/content/common/render_frame_metadata.mojom +++ b/content/common/render_frame_metadata.mojom
@@ -4,6 +4,7 @@ module content.mojom; +import "services/viz/public/interfaces/compositing/local_surface_id.mojom"; import "services/viz/public/interfaces/compositing/selection.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; @@ -32,6 +33,15 @@ // - page prevents zooming in or out (i.e. min and max page scale factors // are the same). bool is_mobile_optimized; + + // The device scale factor used to generate CompositorFrame. + float device_scale_factor; + + // The size of the viewport used to generate a CompositorFrame. + gfx.mojom.Size viewport_size_in_pixels; + + // The last viz::LocalSurfaceId used to submit a CompositorFrame. + viz.mojom.LocalSurfaceId? local_surface_id; }; // This interface is provided by the renderer. It can optionally enable
diff --git a/content/common/render_frame_metadata_struct_traits.cc b/content/common/render_frame_metadata_struct_traits.cc index 2c2927c..00b3b1cf 100644 --- a/content/common/render_frame_metadata_struct_traits.cc +++ b/content/common/render_frame_metadata_struct_traits.cc
@@ -18,8 +18,11 @@ out->root_background_color = data.root_background_color(); out->is_scroll_offset_at_top = data.is_scroll_offset_at_top(); out->is_mobile_optimized = data.is_mobile_optimized(); + out->device_scale_factor = data.device_scale_factor(); return data.ReadRootScrollOffset(&out->root_scroll_offset) && - data.ReadSelection(&out->selection); + data.ReadSelection(&out->selection) && + data.ReadViewportSizeInPixels(&out->viewport_size_in_pixels) && + data.ReadLocalSurfaceId(&out->local_surface_id); } } // namespace mojo
diff --git a/content/common/render_frame_metadata_struct_traits.h b/content/common/render_frame_metadata_struct_traits.h index 74aac781..06d5181 100644 --- a/content/common/render_frame_metadata_struct_traits.h +++ b/content/common/render_frame_metadata_struct_traits.h
@@ -8,6 +8,7 @@ #include "base/optional.h" #include "cc/trees/render_frame_metadata.h" #include "content/common/render_frame_metadata.mojom-shared.h" +#include "services/viz/public/cpp/compositing/local_surface_id_struct_traits.h" namespace mojo { @@ -37,6 +38,20 @@ return metadata.is_mobile_optimized; } + static float device_scale_factor(const cc::RenderFrameMetadata& metadata) { + return metadata.device_scale_factor; + } + + static const gfx::Size& viewport_size_in_pixels( + const cc::RenderFrameMetadata& metadata) { + return metadata.viewport_size_in_pixels; + } + + static const base::Optional<viz::LocalSurfaceId>& local_surface_id( + const cc::RenderFrameMetadata& metadata) { + return metadata.local_surface_id; + } + static bool Read(content::mojom::RenderFrameMetadataDataView data, cc::RenderFrameMetadata* out); };
diff --git a/content/public/android/java/src/org/chromium/content/browser/BindingManager.java b/content/public/android/java/src/org/chromium/content/browser/BindingManager.java index 6d6ea3c..1f6bc66 100644 --- a/content/public/android/java/src/org/chromium/content/browser/BindingManager.java +++ b/content/public/android/java/src/org/chromium/content/browser/BindingManager.java
@@ -29,7 +29,4 @@ /** Called when the embedding application is brought to foreground. */ void onBroughtToForeground(); - - /** Releases all moderate bindings. */ - void releaseAllModerateBindings(); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java b/content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java index c981be40..eeacfb4 100644 --- a/content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java
@@ -168,10 +168,4 @@ assert LauncherThread.runningOnLauncherThread(); removeConnection(connection); } - - @Override - public void releaseAllModerateBindings() { - assert LauncherThread.runningOnLauncherThread(); - removeAllConnections(); - } }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java index 7d50494..4428041 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java
@@ -214,11 +214,10 @@ ? new GpuProcessCallback() : null; - ChildProcessLauncherHelper processLauncher = new ChildProcessLauncherHelper( + ChildProcessLauncherHelper helper = new ChildProcessLauncherHelper( nativePointer, commandLine, filesToBeMapped, sandboxed, binderCallback); - processLauncher.mLauncher.start( - true /* doSetupConnection */, true /* queueIfNoFreeConnection */); - return processLauncher; + helper.start(); + return helper; } /** @@ -327,7 +326,7 @@ if (!sandboxed) { if (sPrivilegedChildConnectionAllocator == null) { sPrivilegedChildConnectionAllocator = - ChildConnectionAllocator.create(context, LauncherThread.getHandler(), + ChildConnectionAllocator.create(context, LauncherThread.getHandler(), null, packageName, PRIVILEGED_SERVICES_NAME, NUM_PRIVILEGED_SERVICES_KEY, bindToCaller, bindAsExternalService, true /* useStrongBinding */); } @@ -339,20 +338,28 @@ "Create a new ChildConnectionAllocator with package name = %s," + " sandboxed = true", packageName); + Runnable freeSlotRunnable = () -> { + ChildProcessConnection lowestRank = + sSandboxedChildConnectionRanking.getLowestRankedConnection(); + if (lowestRank != null) { + lowestRank.kill(); + } + }; + ChildConnectionAllocator connectionAllocator = null; if (sSandboxedServicesCountForTesting != -1) { // Testing case where allocator settings are overriden. String serviceName = !TextUtils.isEmpty(sSandboxedServicesNameForTesting) ? sSandboxedServicesNameForTesting : SandboxedProcessService.class.getName(); - connectionAllocator = ChildConnectionAllocator.createForTest(packageName, - serviceName, sSandboxedServicesCountForTesting, bindToCaller, + connectionAllocator = ChildConnectionAllocator.createForTest(freeSlotRunnable, + packageName, serviceName, sSandboxedServicesCountForTesting, bindToCaller, bindAsExternalService, false /* useStrongBinding */); } else { - connectionAllocator = - ChildConnectionAllocator.create(context, LauncherThread.getHandler(), - packageName, SANDBOXED_SERVICES_NAME, NUM_SANDBOXED_SERVICES_KEY, - bindToCaller, bindAsExternalService, false /* useStrongBinding */); + connectionAllocator = ChildConnectionAllocator.create(context, + LauncherThread.getHandler(), freeSlotRunnable, packageName, + SANDBOXED_SERVICES_NAME, NUM_SANDBOXED_SERVICES_KEY, bindToCaller, + bindAsExternalService, false /* useStrongBinding */); } if (sSandboxedServiceFactoryForTesting != null) { connectionAllocator.setConnectionFactoryForTesting( @@ -361,25 +368,6 @@ sSandboxedChildConnectionAllocator = connectionAllocator; sSandboxedChildConnectionRanking = new ChildProcessRanking( sSandboxedChildConnectionAllocator.getNumberOfServices()); - - final ChildConnectionAllocator finalConnectionAllocator = connectionAllocator; - connectionAllocator.addListener(new ChildConnectionAllocator.Listener() { - @Override - public void onConnectionAllocated( - ChildConnectionAllocator allocator, ChildProcessConnection connection) { - assert connection != null; - assert allocator == finalConnectionAllocator; - if (!allocator.isFreeConnectionAvailable()) { - // Proactively releases all the moderate bindings once all the sandboxed - // services are allocated, which will be very likely to have some of them - // killed by OOM killer. - BindingManager manager = getBindingManager(); - if (manager != null) { - manager.releaseAllModerateBindings(); - } - } - } - }); } return sSandboxedChildConnectionAllocator; } @@ -407,6 +395,10 @@ } } + private void start() { + mLauncher.start(true /* doSetupConnection */, true /* queueIfNoFreeConnection */); + } + /** * @return The type of process as specified in the command line at * {@link ContentSwitches#SWITCH_PROCESS_TYPE}. @@ -548,25 +540,6 @@ } } - @CalledByNative - private static int getNumberOfRendererSlots() { - assert ThreadUtils.runningOnUiThread(); - if (sSandboxedServicesCountForTesting != -1) { - return sSandboxedServicesCountForTesting; - } - - final Context context = ContextUtils.getApplicationContext(); - final String packageName = ChildProcessCreationParams.getPackageNameForService(); - try { - return ChildConnectionAllocator.getNumberOfServices( - context, packageName, NUM_SANDBOXED_SERVICES_KEY); - } catch (RuntimeException e) { - // Unittest packages do not declare services. Some tests require a realistic number - // to test child process policies, so pick a high-ish number here. - return 65535; - } - } - // Can be called on a number of threads, including launcher, and binder. private static native void nativeOnChildProcessStarted( long nativeChildProcessLauncherHelper, int pid);
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherIntegrationTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherIntegrationTest.java index e86212d..db6c180 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherIntegrationTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherIntegrationTest.java
@@ -137,4 +137,36 @@ } }); } + + @Test + @MediumTest + public void testIntentionalKillToFreeServiceSlot() throws Throwable { + final TestChildProcessConnectionFactory factory = new TestChildProcessConnectionFactory(); + final List<TestChildProcessConnection> connections = factory.getConnections(); + ChildProcessLauncherHelper.setSandboxServicesSettingsForTesting( + factory, 1, null /* use default service name */); + // Doing a cross-domain navigation would need to kill the first process in order to create + // the second process. + + ContentShellActivity activity = mActivityTestRule.launchContentShellWithUrlSync( + "content/test/data/android/vsync.html"); + NavigationController navigationController = + mActivityTestRule.getWebContents().getNavigationController(); + TestCallbackHelperContainer testCallbackHelperContainer = + new TestCallbackHelperContainer(activity.getActiveWebContents()); + + mActivityTestRule.loadUrl(navigationController, testCallbackHelperContainer, + new LoadUrlParams(UrlUtils.getIsolatedTestFileUrl( + "content/test/data/android/geolocation.html"))); + mActivityTestRule.loadUrl( + navigationController, testCallbackHelperContainer, new LoadUrlParams("data:,foo")); + + ChildProcessLauncherTestUtils.runOnLauncherThreadBlocking(new Runnable() { + @Override + public void run() { + Assert.assertEquals(2, connections.size()); + Assert.assertTrue(connections.get(0).isKilledByUs()); + } + }); + } }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java index 7dd0c570..54c9470 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java
@@ -107,9 +107,9 @@ public ChildConnectionAllocator call() { Context context = InstrumentationRegistry.getTargetContext(); return ChildConnectionAllocator.create(context, LauncherThread.getHandler(), - SERVICE_PACKAGE_NAME, SERVICE_NAME, SERVICE_COUNT_META_DATA_KEY, - false /* bindToCaller */, false /* bindAsExternalService */, - false /* useStrongBinding */); + null, SERVICE_PACKAGE_NAME, SERVICE_NAME, + SERVICE_COUNT_META_DATA_KEY, false /* bindToCaller */, + false /* bindAsExternalService */, false /* useStrongBinding */); } }); } @@ -356,7 +356,7 @@ new Callable<ChildConnectionAllocator>() { @Override public ChildConnectionAllocator call() { - return ChildConnectionAllocator.createForTest( + return ChildConnectionAllocator.createForTest(null, "org.chromium.wrong_package", "WrongService", 2 /* serviceCount */, false /* bindToCaller */, false /* bindAsExternalService */,
diff --git a/content/public/android/junit/src/org/chromium/content/browser/BindingManagerImplTest.java b/content/public/android/junit/src/org/chromium/content/browser/BindingManagerImplTest.java index c0a6e8f..0d38b31 100644 --- a/content/public/android/junit/src/org/chromium/content/browser/BindingManagerImplTest.java +++ b/content/public/android/junit/src/org/chromium/content/browser/BindingManagerImplTest.java
@@ -188,33 +188,6 @@ } } - /** - * Verifies that BindingManager.releaseAllModerateBindings() drops all the moderate bindings. - */ - @Test - @Feature({"ProcessManagement"}) - public void testModerateBindingDropOnReleaseAllModerateBindings() { - final BindingManagerImpl manager = mManager; - - ChildProcessConnection[] connections = new ChildProcessConnection[4]; - for (int i = 0; i < connections.length; i++) { - connections[i] = createTestChildProcessConnection(i + 1 /* pid */, manager); - } - - // Verify that each connection has a moderate binding after binding and releasing a strong - // binding. - for (ChildProcessConnection connection : connections) { - Assert.assertTrue(connection.isModerateBindingBound()); - } - - // Call BindingManager.releaseAllModerateBindings() and verify that all the moderate - // bindings drop. - manager.releaseAllModerateBindings(); - for (ChildProcessConnection connection : connections) { - Assert.assertFalse(connection.isModerateBindingBound()); - } - } - /* * Test that Chrome is sent to the background, that the initially added moderate bindings are * removed and are not re-added when Chrome is brought back to the foreground.
diff --git a/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java b/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java index 7386ba7..1e5f786 100644 --- a/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java +++ b/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java
@@ -40,7 +40,7 @@ // A connection allocator not used to create connections. private final ChildConnectionAllocator mWrongConnectionAllocator = - ChildConnectionAllocator.createForTest("org.chromium.test", "TestServiceName", + ChildConnectionAllocator.createForTest(null, "org.chromium.test", "TestServiceName", 3 /* serviceCount */, false /* bindToCaller */, false /* bindAsExternalService */, false /* useStrongBinding */); @@ -87,7 +87,7 @@ LauncherThread.setCurrentThreadAsLauncherThread(); mConnectionAllocator = - ChildConnectionAllocator.createForTest("org.chromium.test.spare_connection", + ChildConnectionAllocator.createForTest(null, "org.chromium.test.spare_connection", "TestServiceName", 5 /* serviceCount */, false /* bindToCaller */, false /* bindAsExternalService */, false /* useStrongBinding */); mConnectionAllocator.setConnectionFactoryForTesting(mTestConnectionFactory);
diff --git a/content/public/browser/render_frame_metadata_provider.h b/content/public/browser/render_frame_metadata_provider.h index b64eedd..25b86d3 100644 --- a/content/public/browser/render_frame_metadata_provider.h +++ b/content/public/browser/render_frame_metadata_provider.h
@@ -31,6 +31,14 @@ virtual void OnRenderFrameMetadataChanged() = 0; virtual void OnRenderFrameSubmission() = 0; + + // Called to indicate that the viz::LocalSurfaceId within the + // RenderFrameMetadata has changed. For production builds, this means that + // the child_sequence_number of the viz::LocalSurfaceId has changed. For + // unit tests, this means that any part of the viz::LocalSurfaceId has + // changed. + virtual void OnLocalSurfaceIdChanged( + const cc::RenderFrameMetadata& metadata) = 0; }; RenderFrameMetadataProvider() = default;
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 229ff2a..bb2802b 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -1930,6 +1930,9 @@ Quit(); } +void RenderFrameSubmissionObserver::OnLocalSurfaceIdChanged( + const cc::RenderFrameMetadata& metadata) {} + MainThreadFrameObserver::MainThreadFrameObserver( RenderWidgetHost* render_widget_host) : render_widget_host_(render_widget_host),
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index efce49b..e2954ad2 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -738,6 +738,8 @@ // RenderFrameMetadataProvider::Observer void OnRenderFrameMetadataChanged() override; void OnRenderFrameSubmission() override; + void OnLocalSurfaceIdChanged( + const cc::RenderFrameMetadata& metadata) override; // If true then the next OnRenderFrameSubmission will cancel the blocking // |run_loop_| otherwise the blocking will continue until the next
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc index fed8cfb..66f556e 100644 --- a/content/public/test/test_renderer_host.cc +++ b/content/public/test/test_renderer_host.cc
@@ -217,15 +217,17 @@ } void RenderViewHostTestHarness::DeleteContents() { - SetContents(nullptr); + contents_.reset(); } -void RenderViewHostTestHarness::SetContents(WebContents* contents) { - contents_.reset(contents); +void RenderViewHostTestHarness::SetContents( + std::unique_ptr<WebContents> contents) { + contents_ = std::move(contents); } -WebContents* RenderViewHostTestHarness::CreateTestWebContents() { - // Make sure we ran SetUp() already. +std::unique_ptr<WebContents> +RenderViewHostTestHarness::CreateTestWebContents() { +// Make sure we ran SetUp() already. #if defined(OS_WIN) DCHECK(ole_initializer_ != NULL); #endif @@ -283,7 +285,7 @@ if (IsBrowserSideNavigationEnabled()) BrowserSideNavigationTearDown(); - SetContents(nullptr); + DeleteContents(); #if defined(USE_AURA) aura_test_helper_->TearDown(); ui::TerminateContextFactoryForTests();
diff --git a/content/public/test/test_renderer_host.h b/content/public/test/test_renderer_host.h index 5e899b2b..7c4655c 100644 --- a/content/public/test/test_renderer_host.h +++ b/content/public/test/test_renderer_host.h
@@ -228,11 +228,11 @@ // Sets the current WebContents for tests that want to alter it. Takes // ownership of the WebContents passed. - void SetContents(WebContents* contents); + void SetContents(std::unique_ptr<WebContents> contents); // Creates a new test-enabled WebContents. Ownership passes to the // caller. - WebContents* CreateTestWebContents(); + std::unique_ptr<WebContents> CreateTestWebContents(); // Cover for |contents()->NavigateAndCommit(url)|. See // WebContentsTester::NavigateAndCommit for details.
diff --git a/content/public/test/web_contents_tester.cc b/content/public/test/web_contents_tester.cc index df76c6f..6c3cf24 100644 --- a/content/public/test/web_contents_tester.cc +++ b/content/public/test/web_contents_tester.cc
@@ -23,7 +23,7 @@ } // static -WebContents* WebContentsTester::CreateTestWebContents( +std::unique_ptr<WebContents> WebContentsTester::CreateTestWebContents( BrowserContext* browser_context, scoped_refptr<SiteInstance> instance) { return TestWebContents::Create(browser_context, std::move(instance));
diff --git a/content/public/test/web_contents_tester.h b/content/public/test/web_contents_tester.h index 2aac5fb..b1c7190 100644 --- a/content/public/test/web_contents_tester.h +++ b/content/public/test/web_contents_tester.h
@@ -63,7 +63,7 @@ static WebContentsTester* For(WebContents* contents); // Creates a WebContents enabled for testing. - static WebContents* CreateTestWebContents( + static std::unique_ptr<WebContents> CreateTestWebContents( BrowserContext* browser_context, scoped_refptr<SiteInstance> instance);
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc index 3fb5462..e2cf1e3 100644 --- a/content/renderer/browser_plugin/browser_plugin.cc +++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -857,9 +857,11 @@ return web_layer_.get(); } -void BrowserPlugin::SetLayer(std::unique_ptr<blink::WebLayer> web_layer) { - if (container_) - container_->SetWebLayer(web_layer.get()); +void BrowserPlugin::SetLayer(std::unique_ptr<blink::WebLayer> web_layer, + bool prevent_contents_opaque_changes) { + if (container_) { + container_->SetWebLayer(web_layer.get(), prevent_contents_opaque_changes); + } web_layer_ = std::move(web_layer); }
diff --git a/content/renderer/browser_plugin/browser_plugin.h b/content/renderer/browser_plugin/browser_plugin.h index c24d895..67ed581 100644 --- a/content/renderer/browser_plugin/browser_plugin.h +++ b/content/renderer/browser_plugin/browser_plugin.h
@@ -218,7 +218,8 @@ // ChildFrameCompositor: blink::WebLayer* GetLayer() override; - void SetLayer(std::unique_ptr<blink::WebLayer> web_layer) override; + void SetLayer(std::unique_ptr<blink::WebLayer> web_layer, + bool prevent_contents_opaque_changes) override; SkBitmap* GetSadPageBitmap() override; // This indicates whether this BrowserPlugin has been attached to a
diff --git a/content/renderer/child_frame_compositing_helper.cc b/content/renderer/child_frame_compositing_helper.cc index 620cab0..78bccec 100644 --- a/content/renderer/child_frame_compositing_helper.cc +++ b/content/renderer/child_frame_compositing_helper.cc
@@ -66,8 +66,10 @@ } } + bool prevent_contents_opaque_changes = false; child_frame_compositor_->SetLayer( - std::make_unique<cc_blink::WebLayerImpl>(crashed_layer)); + std::make_unique<cc_blink::WebLayerImpl>(crashed_layer), + prevent_contents_opaque_changes); } void ChildFrameCompositingHelper::SetPrimarySurfaceId( @@ -87,19 +89,18 @@ surface_layer_->SetPrimarySurfaceId(surface_id, deadline); surface_layer_->SetFallbackSurfaceId(fallback_surface_id_); - std::unique_ptr<cc_blink::WebLayerImpl> layer( - new cc_blink::WebLayerImpl(surface_layer_)); - // TODO(lfg): Investigate if it's possible to propagate the information about - // the child surface's opacity. https://crbug.com/629851. - layer->SetOpaque(false); - layer->SetContentsOpaqueIsFixed(true); - child_frame_compositor_->SetLayer(std::move(layer)); + auto layer_owned = std::make_unique<cc_blink::WebLayerImpl>(surface_layer_); + auto* layer = layer_owned.get(); + + // TODO(lfg): Investigate if it's possible to propagate the information + // about the child surface's opacity. https://crbug.com/629851. + bool prevent_contents_opaque_changes = true; + child_frame_compositor_->SetLayer(std::move(layer_owned), + prevent_contents_opaque_changes); UpdateVisibility(true); - static_cast<cc_blink::WebLayerImpl*>(child_frame_compositor_->GetLayer()) - ->layer() - ->SetBounds(frame_size_in_dip); + layer->SetBounds(frame_size_in_dip); } void ChildFrameCompositingHelper::SetFallbackSurfaceId(
diff --git a/content/renderer/child_frame_compositing_helper_unittest.cc b/content/renderer/child_frame_compositing_helper_unittest.cc index b84e214..aec2de79 100644 --- a/content/renderer/child_frame_compositing_helper_unittest.cc +++ b/content/renderer/child_frame_compositing_helper_unittest.cc
@@ -22,7 +22,8 @@ blink::WebLayer* GetLayer() override { return web_layer_.get(); } - void SetLayer(std::unique_ptr<blink::WebLayer> web_layer) override { + void SetLayer(std::unique_ptr<blink::WebLayer> web_layer, + bool prevent_contents_opaque_changes) override { web_layer_ = std::move(web_layer); }
diff --git a/content/renderer/child_frame_compositor.h b/content/renderer/child_frame_compositor.h index cee6610..7466f2a 100644 --- a/content/renderer/child_frame_compositor.h +++ b/content/renderer/child_frame_compositor.h
@@ -19,7 +19,8 @@ virtual blink::WebLayer* GetLayer() = 0; // Passes ownership of a blink::WebLayer to the ChildFrameCompositor. - virtual void SetLayer(std::unique_ptr<blink::WebLayer> web_layer) = 0; + virtual void SetLayer(std::unique_ptr<blink::WebLayer> web_layer, + bool prevent_contents_opaque_changes) = 0; // Returns a sad page bitmap used when the child frame has crashed. virtual SkBitmap* GetSadPageBitmap() = 0;
diff --git a/content/renderer/media/stream/webmediaplayer_ms.cc b/content/renderer/media/stream/webmediaplayer_ms.cc index 7e045d07d..7b379d2 100644 --- a/content/renderer/media/stream/webmediaplayer_ms.cc +++ b/content/renderer/media/stream/webmediaplayer_ms.cc
@@ -962,7 +962,7 @@ // Opacity can be changed during the session without resetting // |video_weblayer_|. - video_weblayer_->layer()->SetContentsOpaque(is_opaque); + video_weblayer_->SetOpaque(is_opaque); } void WebMediaPlayerMS::OnRotationChanged(media::VideoRotation video_rotation, @@ -974,8 +974,7 @@ std::unique_ptr<cc_blink::WebLayerImpl> rotated_weblayer = base::WrapUnique(new cc_blink::WebLayerImpl( cc::VideoLayer::Create(compositor_.get(), video_rotation))); - rotated_weblayer->layer()->SetContentsOpaque(is_opaque); - rotated_weblayer->SetContentsOpaqueIsFixed(true); + rotated_weblayer->SetOpaque(is_opaque); get_client()->SetWebLayer(rotated_weblayer.get()); video_weblayer_ = std::move(rotated_weblayer); }
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc index 67cc02c..71e1ef90 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -2209,7 +2209,7 @@ if (texture_layer_ || compositor_layer_) { if (!layer_bound_to_fullscreen_) - container_->SetWebLayer(nullptr); + container_->SetWebLayer(nullptr, false); else if (fullscreen_container_) fullscreen_container_->SetLayer(nullptr); web_layer_.reset(); @@ -2241,8 +2241,7 @@ // wants to do, and that lets it not recreate a context if // wmode=transparent was specified. opaque = opaque || fullscreen_container_; - layer->layer()->SetContentsOpaque(opaque); - layer->SetContentsOpaqueIsFixed(true); + layer->SetOpaque(opaque); web_layer_ = std::move(layer); } else if (want_compositor_layer) { compositor_layer_ = bound_compositor_->layer(); @@ -2253,7 +2252,7 @@ if (fullscreen_container_) { fullscreen_container_->SetLayer(web_layer_.get()); } else { - container_->SetWebLayer(web_layer_.get()); + container_->SetWebLayer(web_layer_.get(), true); } if (is_flash_plugin_) { web_layer_->CcLayer()->SetMayContainVideo(true);
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index f375cfa..6ef8d1fd 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -869,9 +869,10 @@ return web_layer_.get(); } -void RenderFrameProxy::SetLayer(std::unique_ptr<blink::WebLayer> web_layer) { +void RenderFrameProxy::SetLayer(std::unique_ptr<blink::WebLayer> web_layer, + bool prevent_contents_opaque_changes) { if (web_frame()) - web_frame()->SetWebLayer(web_layer.get()); + web_frame()->SetWebLayer(web_layer.get(), prevent_contents_opaque_changes); web_layer_ = std::move(web_layer); }
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h index 00184f9..69ba3d4 100644 --- a/content/renderer/render_frame_proxy.h +++ b/content/renderer/render_frame_proxy.h
@@ -266,7 +266,8 @@ // ChildFrameCompositor: blink::WebLayer* GetLayer() override; - void SetLayer(std::unique_ptr<blink::WebLayer> web_layer) override; + void SetLayer(std::unique_ptr<blink::WebLayer> web_layer, + bool prevent_contents_opaque_changes) override; SkBitmap* GetSadPageBitmap() override; const viz::LocalSurfaceId& GetLocalSurfaceId() const;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 980248d..366e92c 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -2051,6 +2051,9 @@ ->RequestLayerTreeFrameSink( gpu_->CreateContextProvider(std::move(channel)), GetGpuMemoryBufferManager(), callback); + frame_sink_provider_->RegisterRenderFrameMetadataObserver( + routing_id, std::move(render_frame_metadata_observer_client_request), + std::move(render_frame_metadata_observer_ptr)); return; } #endif @@ -2065,8 +2068,9 @@ DCHECK(!layout_test_mode()); frame_sink_provider_->CreateForWidget( routing_id, std::move(compositor_frame_sink_request), - std::move(compositor_frame_sink_client), - std::move(render_frame_metadata_observer_client_request), + std::move(compositor_frame_sink_client)); + frame_sink_provider_->RegisterRenderFrameMetadataObserver( + routing_id, std::move(render_frame_metadata_observer_client_request), std::move(render_frame_metadata_observer_ptr)); callback.Run(std::make_unique<viz::ClientLayerTreeFrameSink>( nullptr, nullptr, ¶ms)); @@ -2155,8 +2159,9 @@ #endif frame_sink_provider_->CreateForWidget( routing_id, std::move(compositor_frame_sink_request), - std::move(compositor_frame_sink_client), - std::move(render_frame_metadata_observer_client_request), + std::move(compositor_frame_sink_client)); + frame_sink_provider_->RegisterRenderFrameMetadataObserver( + routing_id, std::move(render_frame_metadata_observer_client_request), std::move(render_frame_metadata_observer_ptr)); params.gpu_memory_buffer_manager = GetGpuMemoryBufferManager(); callback.Run(std::make_unique<viz::ClientLayerTreeFrameSink>(
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index eac38ae2..b502b84 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -818,7 +818,7 @@ // Ack the resize if we have to, so that the next time we're visible we get a // fresh VisualProperties right away; otherwise we'll start painting based on // a stale VisualProperties. - DidResizeOrRepaintAck(); + DidUpdateVisualProperties(); } void RenderWidget::OnWasShown(bool needs_repainting, @@ -971,7 +971,7 @@ } void RenderWidget::DidCommitCompositorFrame() { - DidResizeOrRepaintAck(); + DidUpdateVisualProperties(); } void RenderWidget::DidCompletePageScaleAnimation() {} @@ -2528,19 +2528,24 @@ widget_binding_.Bind(std::move(request)); } -void RenderWidget::DidResizeOrRepaintAck() { +bool RenderWidget::IsSurfaceSynchronizationEnabled() const { + return compositor_ && compositor_->IsSurfaceSynchronizationEnabled(); +} + +void RenderWidget::DidUpdateVisualProperties() { if (!needs_visual_properties_ack_ || size_.IsEmpty()) return; - ViewHostMsg_ResizeOrRepaint_ACK_Params params; - params.view_size = size_; - if (child_local_surface_id_allocator_.GetCurrentLocalSurfaceId().is_valid()) { - params.child_allocated_local_surface_id = + if (!IsSurfaceSynchronizationEnabled()) { + ViewHostMsg_ResizeOrRepaint_ACK_Params params; + params.view_size = size_; + const viz::LocalSurfaceId& local_surface_id = child_local_surface_id_allocator_.GetCurrentLocalSurfaceId(); - DCHECK(params.child_allocated_local_surface_id.value().is_valid()); + if (local_surface_id.is_valid()) + params.child_allocated_local_surface_id = local_surface_id; + Send(new ViewHostMsg_ResizeOrRepaint_ACK(routing_id_, params)); } - Send(new ViewHostMsg_ResizeOrRepaint_ACK(routing_id_, params)); needs_visual_properties_ack_ = false; }
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 94b0896..10126bd 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -484,7 +484,9 @@ TTFAP_5MIN_AFTER_BACKGROUNDED, }; - void DidResizeOrRepaintAck(); + bool IsSurfaceSynchronizationEnabled() const; + + void DidUpdateVisualProperties(); base::WeakPtr<RenderWidget> AsWeakPtr();
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc index 90863d1d..fe60df56 100644 --- a/content/renderer/render_widget_unittest.cc +++ b/content/renderer/render_widget_unittest.cc
@@ -417,14 +417,7 @@ // Issue an auto-resize. widget()->DidAutoResize(auto_size); - widget()->sink()->ClearMessages(); widget()->DidCommitCompositorFrame(); - const IPC::Message* message = widget()->sink()->GetUniqueMessageMatching( - ViewHostMsg_ResizeOrRepaint_ACK::ID); - ASSERT_TRUE(message); - ViewHostMsg_ResizeOrRepaint_ACK::Param params; - ViewHostMsg_ResizeOrRepaint_ACK::Read(message, ¶ms); - EXPECT_EQ(auto_size, std::get<0>(params).view_size); // Issue another auto-resize but keep it in-flight. constexpr gfx::Size auto_size2(200, 200);
diff --git a/content/shell/renderer/layout_test/blink_test_helpers.cc b/content/shell/renderer/layout_test/blink_test_helpers.cc index 47609d7..af6f7427 100644 --- a/content/shell/renderer/layout_test/blink_test_helpers.cc +++ b/content/shell/renderer/layout_test/blink_test_helpers.cc
@@ -8,6 +8,8 @@ #include "base/files/file_util.h" #include "base/path_service.h" #include "base/stl_util.h" +#include "base/strings/string_piece.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "content/public/common/content_switches.h" @@ -33,20 +35,19 @@ // Note that this isn't applied to external/wpt because tests in external/wpt // are accessed via http. WebURL RewriteAbsolutePathInCsswgTest(const std::string& utf8_url) { - const char kFileScheme[] = "file:///"; - const int kFileSchemeLen = base::size(kFileScheme) - 1; - if (utf8_url.compare(0, kFileSchemeLen, kFileScheme, kFileSchemeLen) != 0) + static constexpr base::StringPiece kFileScheme = "file:///"; + if (!base::StartsWith(utf8_url, kFileScheme, base::CompareCase::SENSITIVE)) return WebURL(); if (utf8_url.find("/LayoutTests/") != std::string::npos) return WebURL(); #if defined(OS_WIN) // +3 for a drive letter, :, and /. - const int kFileSchemeAndDriveLen = kFileSchemeLen + 3; + static constexpr size_t kFileSchemeAndDriveLen = kFileScheme.size() + 3; if (utf8_url.size() <= kFileSchemeAndDriveLen) return WebURL(); std::string path = utf8_url.substr(kFileSchemeAndDriveLen); #else - std::string path = utf8_url.substr(kFileSchemeLen); + std::string path = utf8_url.substr(kFileScheme.size()); #endif base::FilePath new_path = content::GetWebKitRootDirFilePath() .Append(FILE_PATH_LITERAL("LayoutTests/")) @@ -179,30 +180,28 @@ return WebURL(GURL(utf8_url)); } - const char kGenPrefix[] = "file:///gen/"; - const int kGenPrefixLen = base::size(kGenPrefix) - 1; + static constexpr base::StringPiece kGenPrefix = "file:///gen/"; // Map "file:///gen/" to "file://<build directory>/gen/". - if (!utf8_url.compare(0, kGenPrefixLen, kGenPrefix, kGenPrefixLen)) { + if (base::StartsWith(utf8_url, kGenPrefix, base::CompareCase::SENSITIVE)) { base::FilePath gen_directory_path = GetBuildDirectory().Append(FILE_PATH_LITERAL("gen/")); std::string new_url = std::string("file://") + gen_directory_path.AsUTF8Unsafe() + - utf8_url.substr(kGenPrefixLen); + utf8_url.substr(kGenPrefix.size()); return WebURL(GURL(new_url)); } - const char kPrefix[] = "file:///tmp/LayoutTests/"; - const int kPrefixLen = base::size(kPrefix) - 1; + static constexpr base::StringPiece kPrefix = "file:///tmp/LayoutTests/"; - if (utf8_url.compare(0, kPrefixLen, kPrefix, kPrefixLen)) + if (!base::StartsWith(utf8_url, kPrefix, base::CompareCase::SENSITIVE)) return WebURL(GURL(utf8_url)); base::FilePath replace_path = GetWebKitRootDirFilePath().Append(FILE_PATH_LITERAL("LayoutTests/")); std::string utf8_path = replace_path.AsUTF8Unsafe(); std::string new_url = - std::string("file://") + utf8_path + utf8_url.substr(kPrefixLen); + std::string("file://") + utf8_path + utf8_url.substr(kPrefix.size()); return WebURL(GURL(new_url)); }
diff --git a/content/shell/test_runner/test_plugin.cc b/content/shell/test_runner/test_plugin.cc index cfe56dd..cfe063c 100644 --- a/content/shell/test_runner/test_plugin.cc +++ b/content/shell/test_runner/test_plugin.cc
@@ -187,8 +187,9 @@ return false; layer_ = cc::TextureLayer::CreateForMailbox(this); - web_layer_ = base::WrapUnique(new cc_blink::WebLayerImpl(layer_)); - container_->SetWebLayer(web_layer_.get()); + web_layer_ = std::make_unique<cc_blink::WebLayerImpl>(layer_); + bool prevent_contents_opaque_changes = false; + container_->SetWebLayer(web_layer_.get(), prevent_contents_opaque_changes); if (re_request_touch_events_) { container_->RequestTouchEventType( blink::WebPluginContainer::kTouchEventRequestTypeSynthesizedMouse); @@ -204,7 +205,7 @@ if (layer_.get()) layer_->ClearTexture(); if (container_) - container_->SetWebLayer(nullptr); + container_->SetWebLayer(nullptr, false); web_layer_.reset(); layer_ = nullptr; DestroyScene();
diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc index 6e93d9c..f55ffd18 100644 --- a/content/test/content_browser_test_utils_internal.cc +++ b/content/test/content_browser_test_utils_internal.cc
@@ -22,8 +22,8 @@ #include "content/browser/frame_host/render_frame_host_delegate.h" #include "content/browser/frame_host/render_frame_proxy_host.h" #include "content/browser/renderer_host/delegated_frame_host.h" -#include "content/common/frame_messages.h" #include "content/common/frame_visual_properties.h" +#include "content/common/view_messages.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" @@ -397,4 +397,63 @@ return static_cast<bad_message::BadMessageReason>(bucket.min); } +ShowWidgetMessageFilter::ShowWidgetMessageFilter() +#if defined(OS_MACOSX) || defined(OS_ANDROID) + : content::BrowserMessageFilter(FrameMsgStart), +#else + : content::BrowserMessageFilter(ViewMsgStart), +#endif + message_loop_runner_(new content::MessageLoopRunner) { +} + +ShowWidgetMessageFilter::~ShowWidgetMessageFilter() {} + +bool ShowWidgetMessageFilter::OnMessageReceived(const IPC::Message& message) { + IPC_BEGIN_MESSAGE_MAP(ShowWidgetMessageFilter, message) +#if defined(OS_MACOSX) || defined(OS_ANDROID) + IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup) +#else + IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget) +#endif + IPC_END_MESSAGE_MAP() + return false; +} + +void ShowWidgetMessageFilter::Wait() { + initial_rect_ = gfx::Rect(); + routing_id_ = MSG_ROUTING_NONE; + message_loop_runner_->Run(); +} + +void ShowWidgetMessageFilter::Reset() { + initial_rect_ = gfx::Rect(); + routing_id_ = MSG_ROUTING_NONE; + message_loop_runner_ = new content::MessageLoopRunner; +} + +void ShowWidgetMessageFilter::OnShowWidget(int route_id, + const gfx::Rect& initial_rect) { + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::BindOnce(&ShowWidgetMessageFilter::OnShowWidgetOnUI, this, route_id, + initial_rect)); +} + +#if defined(OS_MACOSX) || defined(OS_ANDROID) +void ShowWidgetMessageFilter::OnShowPopup( + const FrameHostMsg_ShowPopup_Params& params) { + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&ShowWidgetMessageFilter::OnShowWidgetOnUI, this, + MSG_ROUTING_NONE, params.bounds)); +} +#endif + +void ShowWidgetMessageFilter::OnShowWidgetOnUI(int route_id, + const gfx::Rect& initial_rect) { + initial_rect_ = initial_rect; + routing_id_ = route_id; + message_loop_runner_->Quit(); +} + } // namespace content
diff --git a/content/test/content_browser_test_utils_internal.h b/content/test/content_browser_test_utils_internal.h index b1505ecd..bb0260e 100644 --- a/content/test/content_browser_test_utils_internal.h +++ b/content/test/content_browser_test_utils_internal.h
@@ -21,11 +21,14 @@ #include "base/optional.h" #include "base/run_loop.h" #include "base/test/histogram_tester.h" +#include "build/build_config.h" #include "content/browser/bad_message.h" +#include "content/common/frame_messages.h" #include "content/public/browser/resource_dispatcher_host_delegate.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/common/file_chooser_params.h" #include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_utils.h" #include "url/gurl.h" namespace content { @@ -217,6 +220,38 @@ DISALLOW_COPY_AND_ASSIGN(RenderProcessHostKillWaiter); }; +class ShowWidgetMessageFilter : public content::BrowserMessageFilter { + public: + ShowWidgetMessageFilter(); + + bool OnMessageReceived(const IPC::Message& message) override; + + gfx::Rect last_initial_rect() const { return initial_rect_; } + + int last_routing_id() const { return routing_id_; } + + void Wait(); + + void Reset(); + + private: + ~ShowWidgetMessageFilter() override; + + void OnShowWidget(int route_id, const gfx::Rect& initial_rect); + +#if defined(OS_MACOSX) || defined(OS_ANDROID) + void OnShowPopup(const FrameHostMsg_ShowPopup_Params& params); +#endif + + void OnShowWidgetOnUI(int route_id, const gfx::Rect& initial_rect); + + scoped_refptr<content::MessageLoopRunner> message_loop_runner_; + gfx::Rect initial_rect_; + int routing_id_; + + DISALLOW_COPY_AND_ASSIGN(ShowWidgetMessageFilter); +}; + } // namespace content #endif // CONTENT_TEST_CONTENT_BROWSER_TEST_UTILS_INTERNAL_H_
diff --git a/content/test/mock_render_widget_host_delegate.cc b/content/test/mock_render_widget_host_delegate.cc index 21b765ec..9d2404e 100644 --- a/content/test/mock_render_widget_host_delegate.cc +++ b/content/test/mock_render_widget_host_delegate.cc
@@ -16,8 +16,7 @@ void MockRenderWidgetHostDelegate::ResizeDueToAutoResize( RenderWidgetHostImpl* render_widget_host, - const gfx::Size& new_size, - const viz::LocalSurfaceId& local_surface_id) {} + const gfx::Size& new_size) {} KeyboardEventProcessingResult MockRenderWidgetHostDelegate::PreHandleKeyboardEvent(
diff --git a/content/test/mock_render_widget_host_delegate.h b/content/test/mock_render_widget_host_delegate.h index 63afaf1..048ff0de 100644 --- a/content/test/mock_render_widget_host_delegate.h +++ b/content/test/mock_render_widget_host_delegate.h
@@ -33,10 +33,8 @@ } // RenderWidgetHostDelegate: - void ResizeDueToAutoResize( - RenderWidgetHostImpl* render_widget_host, - const gfx::Size& new_size, - const viz::LocalSurfaceId& local_surface_id) override; + void ResizeDueToAutoResize(RenderWidgetHostImpl* render_widget_host, + const gfx::Size& new_size) override; KeyboardEventProcessingResult PreHandleKeyboardEvent( const NativeWebKeyboardEvent& event) override; void ExecuteEditCommand(const std::string& command,
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc index 19b8d6f33..b4c52cc2 100644 --- a/content/test/test_web_contents.cc +++ b/content/test/test_web_contents.cc
@@ -61,9 +61,11 @@ } } -TestWebContents* TestWebContents::Create(BrowserContext* browser_context, - scoped_refptr<SiteInstance> instance) { - TestWebContents* test_web_contents = new TestWebContents(browser_context); +std::unique_ptr<TestWebContents> TestWebContents::Create( + BrowserContext* browser_context, + scoped_refptr<SiteInstance> instance) { + std::unique_ptr<TestWebContents> test_web_contents( + new TestWebContents(browser_context)); test_web_contents->Init(CreateParams(browser_context, std::move(instance))); return test_web_contents; } @@ -262,8 +264,8 @@ } std::unique_ptr<WebContents> TestWebContents::Clone() { - std::unique_ptr<WebContentsImpl> contents = base::WrapUnique( - Create(GetBrowserContext(), SiteInstance::Create(GetBrowserContext()))); + std::unique_ptr<WebContentsImpl> contents = + Create(GetBrowserContext(), SiteInstance::Create(GetBrowserContext())); contents->GetController().CopyStateFrom(controller_, true); return contents; }
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h index 9e2285f1f..42e76c93 100644 --- a/content/test/test_web_contents.h +++ b/content/test/test_web_contents.h
@@ -44,8 +44,9 @@ public: ~TestWebContents() override; - static TestWebContents* Create(BrowserContext* browser_context, - scoped_refptr<SiteInstance> instance); + static std::unique_ptr<TestWebContents> Create( + BrowserContext* browser_context, + scoped_refptr<SiteInstance> instance); static TestWebContents* Create(const CreateParams& params); // WebContentsImpl overrides (returning the same values, but in Test* types)
diff --git a/content/test/test_web_contents_factory.cc b/content/test/test_web_contents_factory.cc index d27e6a8..f271518 100644 --- a/content/test/test_web_contents_factory.cc +++ b/content/test/test_web_contents_factory.cc
@@ -30,8 +30,8 @@ WebContents* TestWebContentsFactory::CreateWebContents( BrowserContext* context) { - web_contents_.push_back(base::WrapUnique( - WebContentsTester::CreateTestWebContents(context, nullptr))); + web_contents_.push_back( + WebContentsTester::CreateTestWebContents(context, nullptr)); DCHECK(web_contents_.back()); return web_contents_.back().get(); }
diff --git a/extensions/browser/api/declarative/rules_registry.cc b/extensions/browser/api/declarative/rules_registry.cc index 8a53ab2..b84cc3a1 100644 --- a/extensions/browser/api/declarative/rules_registry.cc +++ b/extensions/browser/api/declarative/rules_registry.cc
@@ -87,7 +87,7 @@ ready_(/*signaled=*/!cache_delegate), // Immediately ready if no cache // delegate to wait for. last_generated_rule_identifier_id_(0), - weak_ptr_factory_(browser_context_ ? this : NULL) { + weak_ptr_factory_(this) { if (cache_delegate) { cache_delegate_ = cache_delegate->GetWeakPtr(); cache_delegate->Init(this);
diff --git a/extensions/common/api/declarative_net_request/test_utils.cc b/extensions/common/api/declarative_net_request/test_utils.cc index 77b7606..be77366 100644 --- a/extensions/common/api/declarative_net_request/test_utils.cc +++ b/extensions/common/api/declarative_net_request/test_utils.cc
@@ -156,9 +156,9 @@ JSONFileValueSerializer(extension_dir.Append(json_rules_filepath)) .Serialize(rules); - // Persists an empty background script if needed. + // Persists a background script if needed. if (has_background_script) { - std::string content; + std::string content = "chrome.test.sendMessage('ready');"; CHECK_EQ(static_cast<int>(content.length()), base::WriteFile(extension_dir.Append(kBackgroundScriptFilepath), content.c_str(), content.length()));
diff --git a/extensions/common/api/declarative_net_request/test_utils.h b/extensions/common/api/declarative_net_request/test_utils.h index 46610ca..877e086 100644 --- a/extensions/common/api/declarative_net_request/test_utils.h +++ b/extensions/common/api/declarative_net_request/test_utils.h
@@ -84,8 +84,10 @@ // Writes the declarative |rules| in the given |extension_dir| together with the // manifest file. |hosts| specifies the host permissions, the extensions should -// have. If |has_background_script| is true, an empty background script -// ("background.js") will also be persisted for the extension. +// have. If |has_background_script| is true, a background script +// ("background.js") will also be persisted for the extension. Clients can +// listen in to the "ready" message from the background page to detect its +// loading. void WriteManifestAndRuleset( const base::FilePath& extension_dir, const base::FilePath::CharType* json_rules_filepath,
diff --git a/extensions/test/extension_test_message_listener.cc b/extensions/test/extension_test_message_listener.cc index 6119574..20167d5 100644 --- a/extensions/test/extension_test_message_listener.cc +++ b/extensions/test/extension_test_message_listener.cc
@@ -76,6 +76,7 @@ satisfied_ = false; failed_ = false; message_.clear(); + extension_id_for_message_.clear(); replied_ = false; } @@ -89,13 +90,19 @@ // extension. extensions::TestSendMessageFunction* function = content::Source<extensions::TestSendMessageFunction>(source).ptr(); + + std::string sender_extension_id; + if (function->extension()) + sender_extension_id = function->extension_id(); + if (satisfied_ || - (!extension_id_.empty() && function->extension_id() != extension_id_)) { + (!extension_id_.empty() && sender_extension_id != extension_id_)) { return; } // We should have an empty message if we're not already satisfied. CHECK(message_.empty()); + CHECK(extension_id_for_message_.empty()); std::pair<std::string, bool*>* message_details = content::Details<std::pair<std::string, bool*>>(details).ptr(); @@ -106,6 +113,7 @@ // empty string. *message_details->second = true; message_ = message; + extension_id_for_message_ = sender_extension_id; satisfied_ = true; failed_ = (message_ == failure_message_);
diff --git a/extensions/test/extension_test_message_listener.h b/extensions/test/extension_test_message_listener.h index 596632b9..4a728001 100644 --- a/extensions/test/extension_test_message_listener.h +++ b/extensions/test/extension_test_message_listener.h
@@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "extensions/common/extension_id.h" namespace extensions { class TestSendMessageFunction; @@ -94,7 +95,8 @@ ~ExtensionTestMessageListener() override; // This returns true immediately if we've already gotten the expected - // message, or waits until it arrives. + // message, or waits until it arrives. Once this returns true, message() and + // extension_id_for_message() accessors can be used. // Returns false if the wait is interrupted and we still haven't gotten the // message, or if the message was equal to |failure_message_|. bool WaitUntilSatisfied() WARN_UNUSED_RESULT; @@ -127,6 +129,10 @@ const std::string& message() const { return message_; } + const extensions::ExtensionId& extension_id_for_message() const { + return extension_id_for_message_; + } + private: // Implements the content::NotificationObserver interface. void Observe(int type, @@ -167,6 +173,9 @@ // If we received a message that was the failure message. bool failed_; + // The extension id from which |message_| was received. + extensions::ExtensionId extension_id_for_message_; + // The function we need to reply to. scoped_refptr<extensions::TestSendMessageFunction> function_; };
diff --git a/google_apis/test/embedded_setup_chromeos.html b/google_apis/test/embedded_setup_chromeos.html index 339bcb1..150402b 100644 --- a/google_apis/test/embedded_setup_chromeos.html +++ b/google_apis/test/embedded_setup_chromeos.html
@@ -65,9 +65,22 @@ passwordBytes: password, keyType: 'KEY_TYPE_PASSWORD_PLAIN'} }, '/'); - var msg = { + var services = document.getElementById("services").value; + if (services) { + services = JSON.parse(services); + if (!services) + services = "Failed to parse test services JSON."; + } else if (email.endsWith('@corp.example.com') || + email.endsWith('@example.test')) { + // SAML tests. + services = []; + } else { + services = "Services are not set for testing."; + } + + msg = { 'method': 'userInfo', - 'services': [], + 'services': services, }; gaia.chromeOSLogin.parent_webview_.postMessage(msg, gaia.chromeOSLogin.parent_webview_url_); @@ -140,6 +153,7 @@ <div id="page2" hidden> Password <input id="password" name="password" type="password" spellcheck="false" autocomplete="off" formnovalidate=""> + <input id="services" name="services" type="text" spellcheck="false" autocomplete="off" formnovalidate=""> </div><br> <div id='nextButton' onclick='goNext();'>Next</div> </body>
diff --git a/headless/lib/browser/headless_devtools_client_impl.cc b/headless/lib/browser/headless_devtools_client_impl.cc index 66ff3f3..5bcd2d1 100644 --- a/headless/lib/browser/headless_devtools_client_impl.cc +++ b/headless/lib/browser/headless_devtools_client_impl.cc
@@ -200,11 +200,24 @@ NOTREACHED() << "Badly formed event parameters"; return false; } - it->second.Run(*result_dict); + // DevTools assumes event handling is async so we must post a task here or + // we risk breaking things. + browser_main_thread_->PostTask( + FROM_HERE, + base::BindOnce(&HeadlessDevToolsClientImpl::DispatchEventTask, + weak_ptr_factory_.GetWeakPtr(), + std::move(owning_message), &it->second, result_dict)); } return true; } +void HeadlessDevToolsClientImpl::DispatchEventTask( + std::unique_ptr<base::Value> owning_message, + const EventHandler* event_handler, + const base::DictionaryValue* result_dict) { + event_handler->Run(*result_dict); +} + void HeadlessDevToolsClientImpl::AgentHostClosed( content::DevToolsAgentHost* agent_host) { DCHECK_EQ(agent_host_, agent_host);
diff --git a/headless/lib/browser/protocol/target_handler.cc b/headless/lib/browser/protocol/target_handler.cc index 6c80576..f4e5537 100644 --- a/headless/lib/browser/protocol/target_handler.cc +++ b/headless/lib/browser/protocol/target_handler.cc
@@ -82,21 +82,16 @@ return Response::OK(); } -Response TargetHandler::DisposeBrowserContext(const std::string& context_id) { +Response TargetHandler::DisposeBrowserContext(const std::string& context_id, + bool* out_success) { HeadlessBrowserContext* context = browser()->GetBrowserContextForId(context_id); - if (!context) - return Response::InvalidParams("browserContextId"); - - std::vector<HeadlessWebContents*> web_contents = context->GetAllWebContents(); - while (!web_contents.empty()) { - for (auto* wc : web_contents) - wc->Close(); - // Since HeadlessWebContents::Close spawns a nested run loop to await - // closing, new web_contents could be opened. We need to re-query pages and - // close them too. - web_contents = context->GetAllWebContents(); + *out_success = false; + if (context && context != browser()->GetDefaultBrowserContext() && + context->GetAllWebContents().empty()) { + *out_success = true; + context->Close(); } return Response::OK(); }
diff --git a/headless/lib/browser/protocol/target_handler.h b/headless/lib/browser/protocol/target_handler.h index f1100b4e..0f5a182 100644 --- a/headless/lib/browser/protocol/target_handler.h +++ b/headless/lib/browser/protocol/target_handler.h
@@ -28,7 +28,8 @@ Response CloseTarget(const std::string& target_id, bool* out_success) override; Response CreateBrowserContext(std::string* out_context_id) override; - Response DisposeBrowserContext(const std::string& context_id) override; + Response DisposeBrowserContext(const std::string& context_id, + bool* out_success) override; private: DISALLOW_COPY_AND_ASSIGN(TargetHandler);
diff --git a/headless/lib/headless_devtools_client_browsertest.cc b/headless/lib/headless_devtools_client_browsertest.cc index 9cd9553..6a3beb52 100644 --- a/headless/lib/headless_devtools_client_browsertest.cc +++ b/headless/lib/headless_devtools_client_browsertest.cc
@@ -513,6 +513,7 @@ void OnDisposeBrowserContextResult( std::unique_ptr<target::DisposeBrowserContextResult> result) { + EXPECT_TRUE(result->GetSuccess()); FinishAsynchronousTest(); } @@ -522,27 +523,16 @@ HEADLESS_ASYNC_DEVTOOLED_TEST_F(TargetDomainCreateAndDeleteBrowserContextTest); -class TargetDomainDisposeContextSucceedsIfInUse - : public target::Observer, - public HeadlessAsyncDevTooledBrowserTest { +class TargetDomainDisposeContextFailsIfInUse + : public HeadlessAsyncDevTooledBrowserTest { void RunDevTooledTest() override { EXPECT_TRUE(embedded_test_server()->Start()); + EXPECT_EQ(1u, GetAllWebContents(browser()).size()); - - devtools_client_->GetTarget()->AddObserver(this); - devtools_client_->GetTarget()->SetDiscoverTargets( - target::SetDiscoverTargetsParams::Builder().SetDiscover(true).Build(), - base::BindOnce(&TargetDomainDisposeContextSucceedsIfInUse:: - OnDiscoverTargetsEnabled, - base::Unretained(this))); - } - - void OnDiscoverTargetsEnabled( - std::unique_ptr<target::SetDiscoverTargetsResult> result) { devtools_client_->GetTarget()->GetExperimental()->CreateBrowserContext( target::CreateBrowserContextParams::Builder().Build(), base::BindOnce( - &TargetDomainDisposeContextSucceedsIfInUse::OnContextCreated, + &TargetDomainDisposeContextFailsIfInUse::OnContextCreated, base::Unretained(this))); } @@ -556,7 +546,7 @@ .SetBrowserContextId(context_id_) .Build(), base::BindOnce( - &TargetDomainDisposeContextSucceedsIfInUse::OnCreateTargetResult, + &TargetDomainDisposeContextFailsIfInUse::OnCreateTargetResult, base::Unretained(this))); } @@ -564,38 +554,54 @@ std::unique_ptr<target::CreateTargetResult> result) { page_id_ = result->GetTargetId(); - destroyed_targets_.clear(); devtools_client_->GetTarget()->GetExperimental()->DisposeBrowserContext( target::DisposeBrowserContextParams::Builder() .SetBrowserContextId(context_id_) .Build(), - base::BindOnce(&TargetDomainDisposeContextSucceedsIfInUse:: + base::BindOnce(&TargetDomainDisposeContextFailsIfInUse:: OnDisposeBrowserContextResult, base::Unretained(this))); } - void OnTargetDestroyed(const target::TargetDestroyedParams& params) override { - destroyed_targets_.push_back(params.GetTargetId()); - } - void OnDisposeBrowserContextResult( std::unique_ptr<target::DisposeBrowserContextResult> result) { - EXPECT_EQ(destroyed_targets_.size(), 1u); - EXPECT_EQ(destroyed_targets_[0], page_id_); - devtools_client_->GetTarget()->RemoveObserver(this); + EXPECT_FALSE(result->GetSuccess()); + + // Close the page and try again. + devtools_client_->GetTarget()->GetExperimental()->CloseTarget( + target::CloseTargetParams::Builder().SetTargetId(page_id_).Build(), + base::BindOnce( + &TargetDomainDisposeContextFailsIfInUse::OnCloseTargetResult, + base::Unretained(this))); + } + + void OnCloseTargetResult(std::unique_ptr<target::CloseTargetResult> result) { + EXPECT_TRUE(result->GetSuccess()); + + devtools_client_->GetTarget()->GetExperimental()->DisposeBrowserContext( + target::DisposeBrowserContextParams::Builder() + .SetBrowserContextId(context_id_) + .Build(), + base::BindOnce(&TargetDomainDisposeContextFailsIfInUse:: + OnDisposeBrowserContextResult2, + base::Unretained(this))); + } + + void OnDisposeBrowserContextResult2( + std::unique_ptr<target::DisposeBrowserContextResult> result) { + EXPECT_TRUE(result->GetSuccess()); FinishAsynchronousTest(); } private: - std::vector<std::string> destroyed_targets_; std::string context_id_; std::string page_id_; }; -HEADLESS_ASYNC_DEVTOOLED_TEST_F(TargetDomainDisposeContextSucceedsIfInUse); +HEADLESS_ASYNC_DEVTOOLED_TEST_F(TargetDomainDisposeContextFailsIfInUse); class TargetDomainCreateTwoContexts : public HeadlessAsyncDevTooledBrowserTest, - public target::Observer, + public target::ExperimentalObserver, public page::Observer { public: void RunDevTooledTest() override { @@ -606,15 +612,7 @@ devtools_client_->GetPage()->Enable(run_loop.QuitClosure()); run_loop.Run(); - devtools_client_->GetTarget()->AddObserver(this); - devtools_client_->GetTarget()->SetDiscoverTargets( - target::SetDiscoverTargetsParams::Builder().SetDiscover(true).Build(), - base::BindOnce(&TargetDomainCreateTwoContexts::OnDiscoverTargetsEnabled, - base::Unretained(this))); - } - - void OnDiscoverTargetsEnabled( - std::unique_ptr<target::SetDiscoverTargetsResult> result) { + devtools_client_->GetTarget()->GetExperimental()->AddObserver(this); devtools_client_->GetTarget()->GetExperimental()->CreateBrowserContext( target::CreateBrowserContextParams::Builder().Build(), base::BindOnce(&TargetDomainCreateTwoContexts::OnContextOneCreated, @@ -811,18 +809,18 @@ EXPECT_EQ("", value_value->GetString()) << "Page 2 should not share cookies from page one"; - devtools_client_->GetTarget()->GetExperimental()->DisposeBrowserContext( - target::DisposeBrowserContextParams::Builder() - .SetBrowserContextId(context_id_one_) + devtools_client_->GetTarget()->GetExperimental()->CloseTarget( + target::CloseTargetParams::Builder() + .SetTargetId(page_id_one_) .Build(), - base::BindOnce(&TargetDomainCreateTwoContexts::OnCloseContext, + base::BindOnce(&TargetDomainCreateTwoContexts::OnCloseTarget, base::Unretained(this))); - devtools_client_->GetTarget()->GetExperimental()->DisposeBrowserContext( - target::DisposeBrowserContextParams::Builder() - .SetBrowserContextId(context_id_two_) + devtools_client_->GetTarget()->GetExperimental()->CloseTarget( + target::CloseTargetParams::Builder() + .SetTargetId(page_id_two_) .Build(), - base::BindOnce(&TargetDomainCreateTwoContexts::OnCloseContext, + base::BindOnce(&TargetDomainCreateTwoContexts::OnCloseTarget, base::Unretained(this))); devtools_client_->GetTarget()->GetExperimental()->RemoveObserver(this); @@ -830,17 +828,33 @@ } } - void OnTargetDestroyed(const target::TargetDestroyedParams& params) override { - ++page_close_count_; + void OnCloseTarget(std::unique_ptr<target::CloseTargetResult> result) { + page_close_count_++; + + if (page_close_count_ < 2) + return; + + devtools_client_->GetTarget()->GetExperimental()->DisposeBrowserContext( + target::DisposeBrowserContextParams::Builder() + .SetBrowserContextId(context_id_one_) + .Build(), + base::BindOnce(&TargetDomainCreateTwoContexts::OnCloseContext, + base::Unretained(this))); + + devtools_client_->GetTarget()->GetExperimental()->DisposeBrowserContext( + target::DisposeBrowserContextParams::Builder() + .SetBrowserContextId(context_id_two_) + .Build(), + base::BindOnce(&TargetDomainCreateTwoContexts::OnCloseContext, + base::Unretained(this))); } void OnCloseContext( std::unique_ptr<target::DisposeBrowserContextResult> result) { + EXPECT_TRUE(result->GetSuccess()); if (++context_closed_count_ < 2) return; - EXPECT_EQ(page_close_count_, 2); - devtools_client_->GetTarget()->RemoveObserver(this); FinishAsynchronousTest(); }
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg index 05ff2bf..85cc6e88 100644 --- a/infra/config/global/cr-buildbucket.cfg +++ b/infra/config/global/cr-buildbucket.cfg
@@ -1256,6 +1256,11 @@ } builders { mixins: "android-try" + name: "android_clang_dbg_recipe" + dimensions: "os:Ubuntu-14.04" + } + builders { + mixins: "android-try" name: "android_compile_dbg" dimensions: "os:Ubuntu-14.04" }
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm index b1ebdbf..ba67c33b 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm
@@ -23,8 +23,8 @@ #import "ios/chrome/browser/ui/bookmarks/bookmark_mediator.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_model_bridge_observer.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" -#import "ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item.h" -#import "ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item.h" +#import "ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_parent_folder_item.h" +#import "ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_text_field_item.h" #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" #import "ios/chrome/browser/ui/icons/chrome_icon.h" #import "ios/chrome/browser/ui/image_util/image_util.h" @@ -74,7 +74,7 @@ @interface BookmarkEditViewController ()<BookmarkFolderViewControllerDelegate, BookmarkModelBridgeObserver, - BookmarkTextFieldItemDelegate, + LegacyBookmarkTextFieldItemDelegate, TextFieldValidation> { // Flag to ignore bookmark model changes notifications. BOOL _ignoresBookmarkModelChanges; @@ -108,9 +108,9 @@ @property(nonatomic, strong) UIBarButtonItem* doneItem; // CollectionViewItem-s from the collection. -@property(nonatomic, strong) BookmarkTextFieldItem* nameItem; -@property(nonatomic, strong) BookmarkParentFolderItem* folderItem; -@property(nonatomic, strong) BookmarkTextFieldItem* URLItem; +@property(nonatomic, strong) LegacyBookmarkTextFieldItem* nameItem; +@property(nonatomic, strong) LegacyBookmarkParentFolderItem* folderItem; +@property(nonatomic, strong) LegacyBookmarkTextFieldItem* URLItem; // Reports the changes to the delegate, that has the responsibility to save the // bookmark. @@ -327,7 +327,8 @@ [model addSectionWithIdentifier:SectionIdentifierInfo]; - self.nameItem = [[BookmarkTextFieldItem alloc] initWithType:ItemTypeName]; + self.nameItem = + [[LegacyBookmarkTextFieldItem alloc] initWithType:ItemTypeName]; self.nameItem.accessibilityIdentifier = @"Title Field"; self.nameItem.placeholder = l10n_util::GetNSString(IDS_IOS_BOOKMARK_NAME_FIELD_HEADER); @@ -336,11 +337,11 @@ [model addItem:self.nameItem toSectionWithIdentifier:SectionIdentifierInfo]; self.folderItem = - [[BookmarkParentFolderItem alloc] initWithType:ItemTypeFolder]; + [[LegacyBookmarkParentFolderItem alloc] initWithType:ItemTypeFolder]; self.folderItem.title = bookmark_utils_ios::TitleForBookmarkNode(self.folder); [model addItem:self.folderItem toSectionWithIdentifier:SectionIdentifierInfo]; - self.URLItem = [[BookmarkTextFieldItem alloc] initWithType:ItemTypeURL]; + self.URLItem = [[LegacyBookmarkTextFieldItem alloc] initWithType:ItemTypeURL]; self.URLItem.accessibilityIdentifier = @"URL Field"; self.URLItem.placeholder = l10n_util::GetNSString(IDS_IOS_BOOKMARK_URL_FIELD_HEADER); @@ -410,9 +411,9 @@ [self dismiss]; } -#pragma mark - BookmarkTextFieldItemDelegate +#pragma mark - LegacyBookmarkTextFieldItemDelegate -- (void)textDidChangeForItem:(BookmarkTextFieldItem*)item { +- (void)textDidChangeForItem:(LegacyBookmarkTextFieldItem*)item { [self updateSaveButtonState]; } @@ -440,8 +441,8 @@ [super collectionView:collectionView cellForItemAtIndexPath:indexPath]; if ([self.collectionViewModel itemTypeForIndexPath:indexPath] == ItemTypeURL) { - BookmarkTextFieldCell* URLCell = - base::mac::ObjCCastStrict<BookmarkTextFieldCell>(cell); + LegacyBookmarkTextFieldCell* URLCell = + base::mac::ObjCCastStrict<LegacyBookmarkTextFieldCell>(cell); URLCell.textField.textValidator = self; } return cell;
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.h b/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.h index b3d808a..a7c0285 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.h +++ b/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.h
@@ -6,7 +6,7 @@ #import <UIKit/UIKit.h> -#import "ios/chrome/browser/ui/collection_view/collection_view_controller.h" +#import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h" @class BookmarkFolderEditorViewController; @@ -40,7 +40,7 @@ // the title and selecting the parent folder of the bookmark. // This controller monitors the state of the bookmark model, so changes to the // bookmark model can affect this controller's state. -@interface BookmarkFolderEditorViewController : CollectionViewController +@interface BookmarkFolderEditorViewController : ChromeTableViewController @property(nonatomic, weak) id<BookmarkFolderEditorViewControllerDelegate> delegate; @@ -62,8 +62,8 @@ folder:(const bookmarks::BookmarkNode*)folder browserState:(ios::ChromeBrowserState*)browserState; -- (instancetype)initWithLayout:(UICollectionViewLayout*)layout - style:(CollectionViewControllerStyle)style +- (instancetype)initWithTableViewStyle:(UICollectionViewLayout*)layout + appBarStyle:(ChromeTableViewControllerStyle)style NS_UNAVAILABLE; @end
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.mm index 2b8ada4..6923ce0 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.mm
@@ -14,7 +14,6 @@ #include "base/strings/sys_string_conversions.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_node.h" -#import "ios/chrome/browser/ui/bookmarks/bookmark_elevated_toolbar.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_folder_view_controller.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_model_bridge_observer.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" @@ -25,6 +24,8 @@ #import "ios/chrome/browser/ui/icons/chrome_icon.h" #import "ios/chrome/browser/ui/material_components/utils.h" #include "ios/chrome/browser/ui/rtl_geometry.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h" +#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" #import "ios/chrome/browser/ui/util/constraints_ui_util.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/third_party/material_components_ios/src/components/Buttons/src/MDCFlatButton.h" @@ -73,9 +74,6 @@ @property(nonatomic, weak) UIBarButtonItem* doneItem; @property(nonatomic, strong) BookmarkTextFieldItem* titleItem; @property(nonatomic, strong) BookmarkParentFolderItem* parentFolderItem; -// Bottom toolbar with DELETE button that only appears when the edited folder -// allows deletion. -@property(nonatomic, weak) BookmarksElevatedToolbar* toolbar; // |bookmarkModel| must not be NULL and must be loaded. - (instancetype)initWithBookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel @@ -87,12 +85,10 @@ // Configures collection view model. - (void)setupCollectionViewModel; -// Adds toolbar with DELETE button. +// Bottom toolbar with DELETE button that only appears when the edited folder +// allows deletion. - (void)addToolbar; -// Removes toolbar. -- (void)removeToolbar; - @end @implementation BookmarkFolderEditorViewController @@ -107,7 +103,6 @@ @synthesize doneItem = _doneItem; @synthesize titleItem = _titleItem; @synthesize parentFolderItem = _parentFolderItem; -@synthesize toolbar = _toolbar; #pragma mark - Class methods @@ -143,9 +138,9 @@ - (instancetype)initWithBookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel { DCHECK(bookmarkModel); DCHECK(bookmarkModel->loaded()); - UICollectionViewLayout* layout = [[MDCCollectionViewFlowLayout alloc] init]; self = - [super initWithLayout:layout style:CollectionViewControllerStyleAppBar]; + [super initWithTableViewStyle:UITableViewStylePlain + appBarStyle:ChromeTableViewControllerStyleWithAppBar]; if (self) { _bookmarkModel = bookmarkModel; @@ -165,7 +160,12 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.collectionView.backgroundColor = [UIColor whiteColor]; + self.tableView.backgroundColor = self.styler.tableViewBackgroundColor; + self.tableView.estimatedRowHeight = 150.0; + self.tableView.rowHeight = UITableViewAutomaticDimension; + self.tableView.sectionHeaderHeight = 0; + self.tableView.sectionFooterHeight = 0; + [self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone]; // Add Done button. UIBarButtonItem* doneItem = [[UIBarButtonItem alloc] @@ -201,7 +201,6 @@ backItem.accessibilityIdentifier = @"Back"; self.navigationItem.leftBarButtonItem = backItem; } - [self updateEditingState]; [self setupCollectionViewModel]; } @@ -366,39 +365,17 @@ return YES; } -#pragma mark - UICollectionViewDelegate +#pragma mark - UITableViewDelegate -- (void)collectionView:(UICollectionView*)collectionView - didSelectItemAtIndexPath:(NSIndexPath*)indexPath { - [super collectionView:collectionView didSelectItemAtIndexPath:indexPath]; - if ([self.collectionViewModel itemTypeForIndexPath:indexPath] == +- (void)tableView:(UITableView*)tableView + didSelectRowAtIndexPath:(NSIndexPath*)indexPath { + DCHECK_EQ(tableView, self.tableView); + if ([self.tableViewModel itemTypeForIndexPath:indexPath] == ItemTypeParentFolder) { [self changeParentFolder]; } } -#pragma mark - UICollectionViewFlowLayout - -- (CGSize)collectionView:(UICollectionView*)collectionView - layout:(UICollectionViewLayout*)collectionViewLayout - sizeForItemAtIndexPath:(NSIndexPath*)indexPath { - switch ([self.collectionViewModel itemTypeForIndexPath:indexPath]) { - case ItemTypeFolderTitle: { - const CGFloat kTitleCellHeight = 96; - return CGSizeMake(CGRectGetWidth(collectionView.bounds), - kTitleCellHeight); - } - case ItemTypeParentFolder: { - const CGFloat kParentFolderCellHeight = 50; - return CGSizeMake(CGRectGetWidth(collectionView.bounds), - kParentFolderCellHeight); - } - default: - NOTREACHED(); - return CGSizeZero; - } -} - #pragma mark - Private - (void)setParentFolder:(const BookmarkNode*)parentFolder { @@ -424,23 +401,24 @@ - (void)updateParentFolderState { NSIndexPath* folderSelectionIndexPath = - [self.collectionViewModel indexPathForItemType:ItemTypeParentFolder - sectionIdentifier:SectionIdentifierInfo]; + [self.tableViewModel indexPathForItemType:ItemTypeParentFolder + sectionIdentifier:SectionIdentifierInfo]; self.parentFolderItem.title = bookmark_utils_ios::TitleForBookmarkNode(self.parentFolder); - [self.collectionView reloadItemsAtIndexPaths:@[ folderSelectionIndexPath ]]; + [self.tableView reloadRowsAtIndexPaths:@[ folderSelectionIndexPath ] + withRowAnimation:UITableViewRowAnimationNone]; - if (self.editingExistingFolder && !self.toolbar) + if (self.editingExistingFolder && self.navigationController.isToolbarHidden) [self addToolbar]; - if (!self.editingExistingFolder && self.toolbar) - [self removeToolbar]; + if (!self.editingExistingFolder && !self.navigationController.isToolbarHidden) + self.navigationController.toolbarHidden = YES; } - (void)setupCollectionViewModel { [self loadModel]; - [self.collectionViewModel addSectionWithIdentifier:SectionIdentifierInfo]; + [self.tableViewModel addSectionWithIdentifier:SectionIdentifierInfo]; BookmarkTextFieldItem* titleItem = [[BookmarkTextFieldItem alloc] initWithType:ItemTypeFolderTitle]; @@ -451,8 +429,8 @@ titleItem.placeholder = l10n_util::GetNSString(IDS_IOS_BOOKMARK_NEW_EDITOR_NAME_LABEL); titleItem.accessibilityIdentifier = @"Title"; - [self.collectionViewModel addItem:titleItem - toSectionWithIdentifier:SectionIdentifierInfo]; + [self.tableViewModel addItem:titleItem + toSectionWithIdentifier:SectionIdentifierInfo]; titleItem.delegate = self; self.titleItem = titleItem; @@ -460,35 +438,27 @@ [[BookmarkParentFolderItem alloc] initWithType:ItemTypeParentFolder]; parentFolderItem.title = bookmark_utils_ios::TitleForBookmarkNode(self.parentFolder); - [self.collectionViewModel addItem:parentFolderItem - toSectionWithIdentifier:SectionIdentifierInfo]; + [self.tableViewModel addItem:parentFolderItem + toSectionWithIdentifier:SectionIdentifierInfo]; self.parentFolderItem = parentFolderItem; } - (void)addToolbar { - // Add bottom toolbar with Delete button. - BookmarksElevatedToolbar* buttonBar = [[BookmarksElevatedToolbar alloc] init]; - MDCButton* deleteButton = [[MDCFlatButton alloc] init]; - [deleteButton setTitle:l10n_util::GetNSString(IDS_IOS_BOOKMARK_GROUP_DELETE) - forState:UIControlStateNormal]; - [deleteButton addTarget:self - action:@selector(deleteFolder) - forControlEvents:UIControlEventTouchUpInside]; + self.navigationController.toolbarHidden = NO; + NSString* titleString = l10n_util::GetNSString(IDS_IOS_BOOKMARK_GROUP_DELETE); + UIBarButtonItem* deleteButton = + [[UIBarButtonItem alloc] initWithTitle:titleString + style:UIBarButtonItemStylePlain + target:self + action:@selector(deleteFolder)]; deleteButton.accessibilityIdentifier = @"Delete Folder"; + deleteButton.tintColor = [UIColor blackColor]; - [buttonBar setButton:deleteButton]; - [self.view addSubview:buttonBar]; - - // Constraint |buttonBar| to be in bottom. - buttonBar.translatesAutoresizingMaskIntoConstraints = NO; - ApplyVisualConstraints(@[ @"H:|[buttonBar]|", @"V:[buttonBar]|" ], - NSDictionaryOfVariableBindings(buttonBar)); - self.toolbar = buttonBar; -} - -- (void)removeToolbar { - [self.toolbar removeFromSuperview]; - self.toolbar = nil; + UIBarButtonItem* spaceButton = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace + target:nil + action:nil]; + [self setToolbarItems:@[ deleteButton, spaceButton ] animated:NO]; } - (void)updateSaveButtonState {
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm index 8df69ff..ec57837a 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -1658,8 +1658,7 @@ [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Folder Editor")] assertWithMatcher:grey_notNil()]; - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( - IDS_IOS_BOOKMARK_GROUP_DELETE)] + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Delete Folder")] performAction:grey_tap()]; // Wait for Undo toast to go away from screen. @@ -2073,8 +2072,7 @@ performAction:grey_tap()]; // Delete it. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( - IDS_IOS_BOOKMARK_GROUP_DELETE)] + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Delete Folder")] performAction:grey_tap()]; // Wait until it's gone.
diff --git a/ios/chrome/browser/ui/bookmarks/cells/BUILD.gn b/ios/chrome/browser/ui/bookmarks/cells/BUILD.gn index 9fc3129..2d82fcd 100644 --- a/ios/chrome/browser/ui/bookmarks/cells/BUILD.gn +++ b/ios/chrome/browser/ui/bookmarks/cells/BUILD.gn
@@ -12,6 +12,10 @@ "bookmark_table_signin_promo_cell.mm", "bookmark_text_field_item.h", "bookmark_text_field_item.mm", + "legacy_bookmark_parent_folder_item.h", + "legacy_bookmark_parent_folder_item.mm", + "legacy_bookmark_text_field_item.h", + "legacy_bookmark_text_field_item.mm", ] deps = [ @@ -23,6 +27,8 @@ "//ios/chrome/browser/ui/collection_view/cells", "//ios/chrome/browser/ui/colors", "//ios/chrome/browser/ui/icons", + "//ios/chrome/browser/ui/table_view:styler", + "//ios/chrome/browser/ui/table_view/cells", "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/ui", "//ios/third_party/material_components_ios", @@ -43,6 +49,7 @@ deps = [ ":cells", "//ios/chrome/browser/ui/collection_view/cells", + "//ios/chrome/browser/ui/table_view:styler", "//ios/third_party/material_components_ios", "//testing/gtest", "//third_party/ocmock",
diff --git a/ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item.h b/ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item.h index 089ce93..2911634 100644 --- a/ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item.h +++ b/ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item.h
@@ -1,4 +1,4 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,11 +7,10 @@ #import <UIKit/UIKit.h> -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" -#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h" // Item to display the name of the parent folder of a bookmark node. -@interface BookmarkParentFolderItem : CollectionViewItem +@interface BookmarkParentFolderItem : TableViewItem // The title of the bookmark folder it represents. @property(nonatomic, copy) NSString* title; @@ -19,7 +18,7 @@ @end // Cell class associated to BookmarkParentFolderItem. -@interface BookmarkParentFolderCell : MDCCollectionViewCell +@interface BookmarkParentFolderCell : UITableViewCell // Label that displays the item's title. @property(nonatomic, readonly, strong) UILabel* parentFolderNameLabel;
diff --git a/ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item.mm b/ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item.mm index 1e5b3e3..da67b89 100644 --- a/ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item.mm +++ b/ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item.mm
@@ -1,9 +1,10 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #import "ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item.h" +#include "base/mac/foundation_util.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" #import "ios/chrome/browser/ui/icons/chrome_icon.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" @@ -15,11 +16,6 @@ #error "This file requires ARC support." #endif -@interface BookmarkParentFolderCell () -@property(nonatomic, readwrite, strong) UILabel* parentFolderNameLabel; -@property(nonatomic, strong) UILabel* decorationLabel; -@end - @implementation BookmarkParentFolderItem @synthesize title = _title; @@ -33,22 +29,31 @@ return self; } -#pragma mark CollectionViewItem +#pragma mark TableViewItem -- (void)configureCell:(BookmarkParentFolderCell*)cell { - [super configureCell:cell]; +- (void)configureCell:(UITableViewCell*)tableCell + withStyler:(ChromeTableViewStyler*)styler { + [super configureCell:tableCell withStyler:styler]; + BookmarkParentFolderCell* cell = + base::mac::ObjCCastStrict<BookmarkParentFolderCell>(tableCell); cell.parentFolderNameLabel.text = self.title; } @end +@interface BookmarkParentFolderCell () +@property(nonatomic, readwrite, strong) UILabel* parentFolderNameLabel; +@property(nonatomic, strong) UILabel* decorationLabel; +@end + @implementation BookmarkParentFolderCell @synthesize parentFolderNameLabel = _parentFolderNameLabel; @synthesize decorationLabel = _decorationLabel; -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; +- (instancetype)initWithStyle:(UITableViewCellStyle)style + reuseIdentifier:(NSString*)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (!self) return nil; @@ -59,12 +64,15 @@ const CGFloat kVerticalPadding = 8; const CGFloat kParentFolderLabelTopPadding = 7; + UIView* containerView = [[UIView alloc] initWithFrame:CGRectZero]; + containerView.translatesAutoresizingMaskIntoConstraints = NO; + _decorationLabel = [[UILabel alloc] init]; _decorationLabel.translatesAutoresizingMaskIntoConstraints = NO; _decorationLabel.text = l10n_util::GetNSString(IDS_IOS_BOOKMARK_GROUP_BUTTON); _decorationLabel.font = [[MDCTypography fontLoader] regularFontOfSize:12]; _decorationLabel.textColor = bookmark_utils_ios::lightTextColor(); - [self.contentView addSubview:_decorationLabel]; + [containerView addSubview:_decorationLabel]; _parentFolderNameLabel = [[UILabel alloc] init]; _parentFolderNameLabel.translatesAutoresizingMaskIntoConstraints = NO; @@ -73,25 +81,29 @@ _parentFolderNameLabel.textColor = [UIColor colorWithWhite:33.0 / 255.0 alpha:1.0]; _parentFolderNameLabel.textAlignment = NSTextAlignmentNatural; - [self.contentView addSubview:_parentFolderNameLabel]; + [containerView addSubview:_parentFolderNameLabel]; UIImageView* navigationChevronImage = [[UIImageView alloc] init]; UIImage* image = TintImage([ChromeIcon chevronIcon], [UIColor grayColor]); navigationChevronImage.image = image; navigationChevronImage.translatesAutoresizingMaskIntoConstraints = NO; - [self.contentView addSubview:navigationChevronImage]; + [containerView addSubview:navigationChevronImage]; + + [self.contentView addSubview:containerView]; // Set up the constraints. [NSLayoutConstraint activateConstraints:@[ - [_decorationLabel.topAnchor constraintEqualToAnchor:self.topAnchor - constant:kVerticalPadding], - [_decorationLabel.leadingAnchor constraintEqualToAnchor:self.leadingAnchor - constant:kHorizontalPadding], + [_decorationLabel.topAnchor + constraintEqualToAnchor:containerView.topAnchor], + [_decorationLabel.leadingAnchor + constraintEqualToAnchor:containerView.leadingAnchor], [_parentFolderNameLabel.topAnchor constraintEqualToAnchor:_decorationLabel.bottomAnchor constant:kParentFolderLabelTopPadding], [_parentFolderNameLabel.leadingAnchor constraintEqualToAnchor:_decorationLabel.leadingAnchor], + [_parentFolderNameLabel.bottomAnchor + constraintEqualToAnchor:containerView.bottomAnchor], [navigationChevronImage.centerYAnchor constraintEqualToAnchor:_parentFolderNameLabel.centerYAnchor], [navigationChevronImage.leadingAnchor @@ -99,11 +111,20 @@ [navigationChevronImage.widthAnchor constraintEqualToConstant:navigationChevronImage.image.size.width], [navigationChevronImage.trailingAnchor - constraintEqualToAnchor:self.trailingAnchor + constraintEqualToAnchor:containerView.trailingAnchor], + [containerView.leadingAnchor + constraintEqualToAnchor:self.contentView.leadingAnchor + constant:kHorizontalPadding], + [containerView.trailingAnchor + constraintEqualToAnchor:self.contentView.trailingAnchor constant:-kHorizontalPadding], + [containerView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor + constant:kVerticalPadding], + [containerView.bottomAnchor + constraintEqualToAnchor:self.contentView.bottomAnchor + constant:-kVerticalPadding], ]]; - self.shouldHideSeparator = YES; return self; }
diff --git a/ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item_unittest.mm b/ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item_unittest.mm index cd6d122..55d823c 100644 --- a/ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item_unittest.mm +++ b/ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item_unittest.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/bookmarks/cells/bookmark_parent_folder_item.h" #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" +#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" #include "testing/platform_test.h" @@ -22,9 +23,10 @@ [[BookmarkParentFolderItem alloc] initWithType:0]; BookmarkParentFolderCell* cell = [[BookmarkParentFolderCell alloc] initWithFrame:CGRectZero]; + ChromeTableViewStyler* styler = [[ChromeTableViewStyler alloc] init]; item.title = @"Foo"; - [item configureCell:cell]; + [item configureCell:cell withStyler:styler]; EXPECT_NSEQ(@"Foo", cell.parentFolderNameLabel.text); }
diff --git a/ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item.h b/ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item.h index df3cffba..51fd641 100644 --- a/ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item.h +++ b/ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item.h
@@ -1,4 +1,4 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,8 +7,7 @@ #import <UIKit/UIKit.h> -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" -#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h" @class BookmarkTextFieldItem; @protocol TextFieldStyling; @@ -22,7 +21,7 @@ @end -@interface BookmarkTextFieldItem : CollectionViewItem +@interface BookmarkTextFieldItem : TableViewItem // The text field content. @property(nonatomic, copy) NSString* text; @@ -35,7 +34,7 @@ @end -@interface BookmarkTextFieldCell : MDCCollectionViewCell +@interface BookmarkTextFieldCell : UITableViewCell // Text field to display the title or the URL of the bookmark node. @property(nonatomic, readonly, strong) UITextField<TextFieldStyling>* textField;
diff --git a/ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item.mm b/ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item.mm index d41f952..e7364e49 100644 --- a/ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item.mm +++ b/ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item.mm
@@ -1,10 +1,11 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #import "ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item.h" #include "base/logging.h" +#include "base/mac/foundation_util.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" #import "ios/public/provider/chrome/browser/chrome_browser_provider.h" #import "ios/public/provider/chrome/browser/ui/text_field_styling.h" @@ -13,11 +14,6 @@ #error "This file requires ARC support." #endif -@interface BookmarkTextFieldCell () -@property(nonatomic, readwrite, strong) - UITextField<TextFieldStyling>* textField; -@end - @implementation BookmarkTextFieldItem @synthesize text = _text; @@ -32,10 +28,14 @@ return self; } -#pragma mark CollectionViewItem +#pragma mark TableViewItem -- (void)configureCell:(BookmarkTextFieldCell*)cell { - [super configureCell:cell]; +- (void)configureCell:(UITableViewCell*)tableCell + withStyler:(ChromeTableViewStyler*)styler { + [super configureCell:tableCell withStyler:styler]; + + BookmarkTextFieldCell* cell = + base::mac::ObjCCastStrict<BookmarkTextFieldCell>(tableCell); cell.textField.text = self.text; cell.textField.placeholder = self.placeholder; cell.textField.tag = self.type; @@ -58,14 +58,19 @@ @end +@interface BookmarkTextFieldCell () +@property(nonatomic, readwrite, strong) + UITextField<TextFieldStyling>* textField; +@end + @implementation BookmarkTextFieldCell @synthesize textField = _textField; -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; +- (instancetype)initWithStyle:(UITableViewCellStyle)style + reuseIdentifier:(NSString*)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { - _textField = ios::GetChromeBrowserProvider()->CreateStyledTextField(CGRectZero); _textField.translatesAutoresizingMaskIntoConstraints = NO; @@ -77,15 +82,18 @@ const CGFloat kHorizontalPadding = 15; const CGFloat kTopPadding = 8; [NSLayoutConstraint activateConstraints:@[ - [_textField.leadingAnchor constraintEqualToAnchor:self.leadingAnchor - constant:kHorizontalPadding], - [_textField.topAnchor constraintEqualToAnchor:self.topAnchor + [_textField.leadingAnchor + constraintEqualToAnchor:self.contentView.leadingAnchor + constant:kHorizontalPadding], + [_textField.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:kTopPadding], - [_textField.trailingAnchor constraintEqualToAnchor:self.trailingAnchor - constant:-kHorizontalPadding], + [_textField.trailingAnchor + constraintEqualToAnchor:self.contentView.trailingAnchor + constant:-kHorizontalPadding], + [_textField.bottomAnchor + constraintEqualToAnchor:self.contentView.bottomAnchor + constant:-kTopPadding], ]]; - - self.shouldHideSeparator = YES; } return self; }
diff --git a/ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item_unittest.mm b/ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item_unittest.mm index 239c1ed..eebf1ed1 100644 --- a/ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item_unittest.mm +++ b/ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item_unittest.mm
@@ -4,6 +4,7 @@ #import "ios/chrome/browser/ui/bookmarks/cells/bookmark_text_field_item.h" +#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" #include "testing/platform_test.h" @@ -23,9 +24,10 @@ [[BookmarkTextFieldCell alloc] initWithFrame:CGRectZero]; id mockDelegate = [OCMockObject mockForProtocol:@protocol(BookmarkTextFieldItemDelegate)]; + ChromeTableViewStyler* styler = [[ChromeTableViewStyler alloc] init]; item.delegate = mockDelegate; - [item configureCell:cell]; + [item configureCell:cell withStyler:styler]; EXPECT_EQ(mockDelegate, cell.textField.delegate); [[mockDelegate expect] textDidChangeForItem:item]; @@ -36,9 +38,10 @@ BookmarkTextFieldItem* item = [[BookmarkTextFieldItem alloc] initWithType:0]; BookmarkTextFieldCell* cell = [[BookmarkTextFieldCell alloc] initWithFrame:CGRectZero]; + ChromeTableViewStyler* styler = [[ChromeTableViewStyler alloc] init]; item.text = @"Foo"; - [item configureCell:cell]; + [item configureCell:cell withStyler:styler]; EXPECT_NSEQ(@"Foo", cell.textField.text); }
diff --git a/ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_parent_folder_item.h b/ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_parent_folder_item.h new file mode 100644 index 0000000..0d36c90 --- /dev/null +++ b/ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_parent_folder_item.h
@@ -0,0 +1,29 @@ +// 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 IOS_CHROME_BROWSER_UI_BOOKMARKS_CELLS_LEGACY_BOOKMARK_PARENT_FOLDER_ITEM_H_ +#define IOS_CHROME_BROWSER_UI_BOOKMARKS_CELLS_LEGACY_BOOKMARK_PARENT_FOLDER_ITEM_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" +#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" + +// Item to display the name of the parent folder of a bookmark node. +@interface LegacyBookmarkParentFolderItem : CollectionViewItem + +// The title of the bookmark folder it represents. +@property(nonatomic, copy) NSString* title; + +@end + +// Cell class associated to LegacyBookmarkParentFolderItem. +@interface LegacyBookmarkParentFolderCell : MDCCollectionViewCell + +// Label that displays the item's title. +@property(nonatomic, readonly, strong) UILabel* parentFolderNameLabel; + +@end + +#endif // IOS_CHROME_BROWSER_UI_BOOKMARKS_CELLS_LEGACY_BOOKMARK_PARENT_FOLDER_ITEM_H_
diff --git a/ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_parent_folder_item.mm b/ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_parent_folder_item.mm new file mode 100644 index 0000000..76e1f6c5 --- /dev/null +++ b/ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_parent_folder_item.mm
@@ -0,0 +1,124 @@ +// 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. + +#import "ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_parent_folder_item.h" + +#import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" +#import "ios/chrome/browser/ui/icons/chrome_icon.h" +#import "ios/chrome/browser/ui/uikit_ui_util.h" +#include "ios/chrome/grit/ios_strings.h" +#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" +#include "ui/base/l10n/l10n_util_mac.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface LegacyBookmarkParentFolderCell () +@property(nonatomic, readwrite, strong) UILabel* parentFolderNameLabel; +@property(nonatomic, strong) UILabel* decorationLabel; +@end + +@implementation LegacyBookmarkParentFolderItem + +@synthesize title = _title; + +- (instancetype)initWithType:(NSInteger)type { + self = [super initWithType:type]; + if (self) { + self.accessibilityIdentifier = @"Change Folder"; + self.cellClass = [LegacyBookmarkParentFolderCell class]; + } + return self; +} + +#pragma mark CollectionViewItem + +- (void)configureCell:(LegacyBookmarkParentFolderCell*)cell { + [super configureCell:cell]; + cell.parentFolderNameLabel.text = self.title; +} + +@end + +@implementation LegacyBookmarkParentFolderCell + +@synthesize parentFolderNameLabel = _parentFolderNameLabel; +@synthesize decorationLabel = _decorationLabel; + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (!self) + return nil; + + self.isAccessibilityElement = YES; + self.accessibilityTraits |= UIAccessibilityTraitButton; + + const CGFloat kHorizontalPadding = 15; + const CGFloat kVerticalPadding = 8; + const CGFloat kParentFolderLabelTopPadding = 7; + + _decorationLabel = [[UILabel alloc] init]; + _decorationLabel.translatesAutoresizingMaskIntoConstraints = NO; + _decorationLabel.text = l10n_util::GetNSString(IDS_IOS_BOOKMARK_GROUP_BUTTON); + _decorationLabel.font = [[MDCTypography fontLoader] regularFontOfSize:12]; + _decorationLabel.textColor = bookmark_utils_ios::lightTextColor(); + [self.contentView addSubview:_decorationLabel]; + + _parentFolderNameLabel = [[UILabel alloc] init]; + _parentFolderNameLabel.translatesAutoresizingMaskIntoConstraints = NO; + _parentFolderNameLabel.font = + [[MDCTypography fontLoader] regularFontOfSize:16]; + _parentFolderNameLabel.textColor = + [UIColor colorWithWhite:33.0 / 255.0 alpha:1.0]; + _parentFolderNameLabel.textAlignment = NSTextAlignmentNatural; + [self.contentView addSubview:_parentFolderNameLabel]; + + UIImageView* navigationChevronImage = [[UIImageView alloc] init]; + UIImage* image = TintImage([ChromeIcon chevronIcon], [UIColor grayColor]); + navigationChevronImage.image = image; + navigationChevronImage.translatesAutoresizingMaskIntoConstraints = NO; + [self.contentView addSubview:navigationChevronImage]; + + // Set up the constraints. + [NSLayoutConstraint activateConstraints:@[ + [_decorationLabel.topAnchor constraintEqualToAnchor:self.topAnchor + constant:kVerticalPadding], + [_decorationLabel.leadingAnchor constraintEqualToAnchor:self.leadingAnchor + constant:kHorizontalPadding], + [_parentFolderNameLabel.topAnchor + constraintEqualToAnchor:_decorationLabel.bottomAnchor + constant:kParentFolderLabelTopPadding], + [_parentFolderNameLabel.leadingAnchor + constraintEqualToAnchor:_decorationLabel.leadingAnchor], + [navigationChevronImage.centerYAnchor + constraintEqualToAnchor:_parentFolderNameLabel.centerYAnchor], + [navigationChevronImage.leadingAnchor + constraintEqualToAnchor:_parentFolderNameLabel.trailingAnchor], + [navigationChevronImage.widthAnchor + constraintEqualToConstant:navigationChevronImage.image.size.width], + [navigationChevronImage.trailingAnchor + constraintEqualToAnchor:self.trailingAnchor + constant:-kHorizontalPadding], + ]]; + + self.shouldHideSeparator = YES; + return self; +} + +- (void)prepareForReuse { + [super prepareForReuse]; + self.parentFolderNameLabel.text = nil; +} + +- (NSString*)accessibilityLabel { + return self.parentFolderNameLabel.text; +} + +- (NSString*)accessibilityHint { + return l10n_util::GetNSString( + IDS_IOS_BOOKMARK_EDIT_PARENT_FOLDER_BUTTON_HINT); +} + +@end
diff --git a/ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_text_field_item.h b/ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_text_field_item.h new file mode 100644 index 0000000..b2fc511 --- /dev/null +++ b/ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_text_field_item.h
@@ -0,0 +1,45 @@ +// 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 IOS_CHROME_BROWSER_UI_BOOKMARKS_CELLS_LEGACY_BOOKMARK_TEXT_FIELD_ITEM_H_ +#define IOS_CHROME_BROWSER_UI_BOOKMARKS_CELLS_LEGACY_BOOKMARK_TEXT_FIELD_ITEM_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" +#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" + +@class LegacyBookmarkTextFieldItem; +@protocol TextFieldStyling; + +// Delegates the cell's text field's events. +@protocol LegacyBookmarkTextFieldItemDelegate<UITextFieldDelegate> + +// Called when the |text| of the item was changed via the textfield. The item's +// |text| is up-to-date when this is called. +- (void)textDidChangeForItem:(LegacyBookmarkTextFieldItem*)item; + +@end + +@interface LegacyBookmarkTextFieldItem : CollectionViewItem + +// The text field content. +@property(nonatomic, copy) NSString* text; + +// The text field placeholder. +@property(nonatomic, copy) NSString* placeholder; + +// Receives the text field events. +@property(nonatomic, weak) id<LegacyBookmarkTextFieldItemDelegate> delegate; + +@end + +@interface LegacyBookmarkTextFieldCell : MDCCollectionViewCell + +// Text field to display the title or the URL of the bookmark node. +@property(nonatomic, readonly, strong) UITextField<TextFieldStyling>* textField; + +@end + +#endif // IOS_CHROME_BROWSER_UI_BOOKMARKS_CELLS_LEGACY_BOOKMARK_TEXT_FIELD_ITEM_H_
diff --git a/ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_text_field_item.mm b/ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_text_field_item.mm new file mode 100644 index 0000000..b6acb9b --- /dev/null +++ b/ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_text_field_item.mm
@@ -0,0 +1,103 @@ +// 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. + +#import "ios/chrome/browser/ui/bookmarks/cells/legacy_bookmark_text_field_item.h" + +#include "base/logging.h" +#import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" +#import "ios/public/provider/chrome/browser/chrome_browser_provider.h" +#import "ios/public/provider/chrome/browser/ui/text_field_styling.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface LegacyBookmarkTextFieldCell () +@property(nonatomic, readwrite, strong) + UITextField<TextFieldStyling>* textField; +@end + +@implementation LegacyBookmarkTextFieldItem + +@synthesize text = _text; +@synthesize placeholder = _placeholder; +@synthesize delegate = _delegate; + +- (instancetype)initWithType:(NSInteger)type { + self = [super initWithType:type]; + if (self) { + self.cellClass = [LegacyBookmarkTextFieldCell class]; + } + return self; +} + +#pragma mark CollectionViewItem + +- (void)configureCell:(LegacyBookmarkTextFieldCell*)cell { + [super configureCell:cell]; + cell.textField.text = self.text; + cell.textField.placeholder = self.placeholder; + cell.textField.tag = self.type; + [cell.textField addTarget:self + action:@selector(textFieldDidChange:) + forControlEvents:UIControlEventEditingChanged]; + cell.textField.delegate = self.delegate; + cell.textField.accessibilityLabel = self.text; + cell.textField.accessibilityIdentifier = + [NSString stringWithFormat:@"%@_textField", self.accessibilityIdentifier]; +} + +#pragma mark UIControlEventEditingChanged + +- (void)textFieldDidChange:(UITextField*)textField { + DCHECK_EQ(textField.tag, self.type); + self.text = textField.text; + [self.delegate textDidChangeForItem:self]; +} + +@end + +@implementation LegacyBookmarkTextFieldCell + +@synthesize textField = _textField; + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _textField = + ios::GetChromeBrowserProvider()->CreateStyledTextField(CGRectZero); + _textField.translatesAutoresizingMaskIntoConstraints = NO; + _textField.textColor = bookmark_utils_ios::darkTextColor(); + _textField.clearButtonMode = UITextFieldViewModeWhileEditing; + _textField.placeholderStyle = + TextFieldStylingPlaceholderFloatingPlaceholder; + [self.contentView addSubview:_textField]; + const CGFloat kHorizontalPadding = 15; + const CGFloat kTopPadding = 8; + [NSLayoutConstraint activateConstraints:@[ + [_textField.leadingAnchor constraintEqualToAnchor:self.leadingAnchor + constant:kHorizontalPadding], + [_textField.topAnchor constraintEqualToAnchor:self.topAnchor + constant:kTopPadding], + [_textField.trailingAnchor constraintEqualToAnchor:self.trailingAnchor + constant:-kHorizontalPadding], + ]]; + + self.shouldHideSeparator = YES; + } + return self; +} + +- (void)prepareForReuse { + [super prepareForReuse]; + [self.textField resignFirstResponder]; + [self.textField removeTarget:nil + action:NULL + forControlEvents:UIControlEventAllEvents]; + self.textField.delegate = nil; + self.textField.text = nil; + self.textField.textValidator = nil; +} + +@end
diff --git a/ios/third_party/material_components_ios/README.chromium b/ios/third_party/material_components_ios/README.chromium index d3d75a5b..2b03271 100644 --- a/ios/third_party/material_components_ios/README.chromium +++ b/ios/third_party/material_components_ios/README.chromium
@@ -1,7 +1,7 @@ Name: Material Components for iOS URL: https://github.com/material-components/material-components-ios Version: 0 -Revision: 5ee7e2e3a845c5ca7e3d8a5a0d2ab4faddb52da5 +Revision: dc1eae3b21358b4761a09e7c586bc69f3695eb6e License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/media/BUILD.gn b/media/BUILD.gn index 2127862..a1467fa 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -174,9 +174,8 @@ deps += [ "//media/remoting:media_remoting_tests" ] } - if (proprietary_codecs) { - configs += [ "//third_party/opus:opus_config" ] - } + # The test needs OPUS_FIXED_POINT conditional define. + configs += [ "//third_party/opus:opus_config" ] } test("media_perftests") {
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 0891a26..c7aa2bf1 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -269,10 +269,6 @@ const base::Feature kMseBufferByPts{"MseBufferByPts", base::FEATURE_DISABLED_BY_DEFAULT}; -// Support FLAC codec within ISOBMFF streams used with Media Source Extensions. -const base::Feature kMseFlacInIsobmff{"MseFlacInIsobmff", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Enable new cpu load estimator. Intended for evaluation in local // testing and origin-trial. // TODO(nisse): Delete once we have switched over to always using the
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 2c3d82c..c9077f9e 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -115,7 +115,6 @@ MEDIA_EXPORT extern const base::Feature kMemoryPressureBasedSourceBufferGC; MEDIA_EXPORT extern const base::Feature kMojoVideoDecoder; MEDIA_EXPORT extern const base::Feature kMseBufferByPts; -MEDIA_EXPORT extern const base::Feature kMseFlacInIsobmff; MEDIA_EXPORT extern const base::Feature kNewAudioRenderingMixingStrategy; MEDIA_EXPORT extern const base::Feature kNewEncodeCpuLoadEstimator; MEDIA_EXPORT extern const base::Feature kNewRemotePlaybackPipeline;
diff --git a/media/base/mime_util_unittest.cc b/media/base/mime_util_unittest.cc index b625de0..294cd39 100644 --- a/media/base/mime_util_unittest.cc +++ b/media/base/mime_util_unittest.cc
@@ -326,10 +326,8 @@ // Valid FLAC string with MP4. Neither decoding nor demuxing is proprietary. EXPECT_TRUE(ParseAudioCodecString("audio/mp4", "flac", &out_is_ambiguous, &out_codec)); - if (kUsePropCodecs) { - EXPECT_FALSE(out_is_ambiguous); - EXPECT_EQ(kCodecFLAC, out_codec); - } + EXPECT_FALSE(out_is_ambiguous); + EXPECT_EQ(kCodecFLAC, out_codec); // Ambiguous AAC string. // TODO(chcunningha): This can probably be allowed. I think we treat all
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 5f55d6a..3780302 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -385,8 +385,7 @@ void WebMediaPlayerImpl::RegisterContentsLayer(blink::WebLayer* web_layer) { DCHECK(bridge_); - bridge_->GetWebLayer()->CcLayer()->SetContentsOpaque(opaque_); - bridge_->GetWebLayer()->SetContentsOpaqueIsFixed(true); + bridge_->GetWebLayer()->SetOpaque(opaque_); client_->SetWebLayer(web_layer); } @@ -1606,8 +1605,7 @@ video_weblayer_.reset(new cc_blink::WebLayerImpl(cc::VideoLayer::Create( compositor_.get(), pipeline_metadata_.video_decoder_config.video_rotation()))); - video_weblayer_->layer()->SetContentsOpaque(opaque_); - video_weblayer_->SetContentsOpaqueIsFixed(true); + video_weblayer_->SetOpaque(opaque_); client_->SetWebLayer(video_weblayer_.get()); } else { vfc_task_runner_->PostTask( @@ -1867,13 +1865,11 @@ DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing); opaque_ = opaque; - // Modify content opaqueness of cc::Layer directly so that - // SetContentsOpaqueIsFixed is ignored. if (!surface_layer_for_video_enabled_) { if (video_weblayer_) - video_weblayer_->layer()->SetContentsOpaque(opaque_); + video_weblayer_->SetOpaque(opaque_); } else if (bridge_->GetWebLayer()) { - bridge_->GetWebLayer()->CcLayer()->SetContentsOpaque(opaque_); + bridge_->GetWebLayer()->SetOpaque(opaque_); } }
diff --git a/media/filters/audio_file_reader_unittest.cc b/media/filters/audio_file_reader_unittest.cc index 6b3ce992..6df10b2 100644 --- a/media/filters/audio_file_reader_unittest.cc +++ b/media/filters/audio_file_reader_unittest.cc
@@ -201,7 +201,6 @@ 12719); } -#if BUILDFLAG(USE_PROPRIETARY_CODECS) TEST_F(AudioFileReaderTest, MP3) { RunTest("sfx.mp3", "1.30,2.72,4.56,5.08,3.74,2.03,", @@ -225,6 +224,7 @@ 44928); } +#if BUILDFLAG(USE_PROPRIETARY_CODECS) TEST_F(AudioFileReaderTest, AAC) { RunTest("sfx.m4a", "1.81,1.66,2.32,3.27,4.46,3.36,", 1, 44100, base::TimeDelta::FromMicroseconds(371660), 16391, 13312);
diff --git a/media/filters/audio_video_metadata_extractor_unittest.cc b/media/filters/audio_video_metadata_extractor_unittest.cc index 022efcc..7e5793a 100644 --- a/media/filters/audio_video_metadata_extractor_unittest.cc +++ b/media/filters/audio_video_metadata_extractor_unittest.cc
@@ -185,6 +185,7 @@ EXPECT_EQ(0u, extractor->attached_images_bytes().size()); } +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) TEST(AudioVideoMetadataExtractorTest, AudioMP3) { std::unique_ptr<AudioVideoMetadataExtractor> extractor = @@ -259,6 +260,5 @@ EXPECT_EQ(0u, extractor->attached_images_bytes().size()); } -#endif } // namespace media
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc index e630715..50fc1bc8 100644 --- a/media/filters/chunk_demuxer.cc +++ b/media/filters/chunk_demuxer.cc
@@ -235,12 +235,6 @@ if (!SBSTREAM_IS_SET) { DCHECK_EQ(state_, UNINITIALIZED); - // FLAC in MSE here is only supported if in ISOBMFF, which has feature flag. - // Though the MP4StreamParser shouldn't produce FLAC decoder configs if the - // feature is disabled, double-check feature support here in debug builds. - DCHECK(config.codec() != kCodecFLAC || - base::FeatureList::IsEnabled(kMseFlacInIsobmff)); - // Enable partial append window support for most audio codecs (notably: not // opus). partial_append_window_trimming_enabled_ =
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index d4b55e6..253d889 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -1230,7 +1230,6 @@ base::RunLoop().Run(); } -#if BUILDFLAG(USE_PROPRIETARY_CODECS) // Ensure ID3v1 tag reading is disabled. id3_test.mp3 has an ID3v1 tag with the // field "title" set to "sample for id3 test". TEST_F(FFmpegDemuxerTest, NoID3TagData) { @@ -1238,9 +1237,7 @@ InitializeDemuxer(); EXPECT_FALSE(av_dict_get(format_context()->metadata, "title", NULL, 0)); } -#endif -#if BUILDFLAG(USE_PROPRIETARY_CODECS) // Ensure MP3 files with large image/video based ID3 tags demux okay. FFmpeg // will hand us a video stream to the data which will likely be in a format we // don't accept as video; e.g. PNG. @@ -1260,7 +1257,6 @@ EXPECT_FALSE(GetStream(DemuxerStream::VIDEO)); EXPECT_TRUE(GetStream(DemuxerStream::AUDIO)); } -#endif // Ensure a video with an unsupported audio track still results in the video // stream being demuxed. Because we disable the speex parser for ogg, the audio @@ -1303,6 +1299,7 @@ InitializeDemuxer(); ReadUntilEndOfStream(GetStream(DemuxerStream::AUDIO)); } +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) class Mp3SeekFFmpegDemuxerTest : public FFmpegDemuxerTest, @@ -1344,6 +1341,7 @@ "bear-audio-10s-VBR-has-TOC.mp3", "bear-audio-10s-VBR-no-TOC.mp3")); +#if BUILDFLAG(USE_PROPRIETARY_CODECS) static void ValidateAnnexB(DemuxerStream* stream, DemuxerStream::Status status, scoped_refptr<DecoderBuffer> buffer) { @@ -1710,7 +1708,6 @@ 44100, kSampleFormatS32); } -#if BUILDFLAG(USE_PROPRIETARY_CODECS) TEST_F(FFmpegDemuxerTest, Read_Flac_Mp4) { CreateDemuxer("bear-flac.mp4"); InitializeDemuxer(); @@ -1732,7 +1729,6 @@ VerifyFlacStream(GetStream(DemuxerStream::AUDIO), 32, CHANNEL_LAYOUT_STEREO, 192000, kSampleFormatS32); } -#endif // USE_PROPRIETARY_CODECS // Verify that FFmpeg demuxer falls back to choosing disabled streams for // seeking if there's no suitable enabled stream found.
diff --git a/media/filters/ffmpeg_glue_unittest.cc b/media/filters/ffmpeg_glue_unittest.cc index 2289d83..e51019c 100644 --- a/media/filters/ffmpeg_glue_unittest.cc +++ b/media/filters/ffmpeg_glue_unittest.cc
@@ -299,17 +299,17 @@ ExpectContainer(container_names::CONTAINER_WAV); } +TEST_F(FFmpegGlueContainerTest, MP3) { + InitializeAndOpen("sfx.mp3"); + ExpectContainer(container_names::CONTAINER_MP3); +} + #if BUILDFLAG(USE_PROPRIETARY_CODECS) TEST_F(FFmpegGlueContainerTest, MOV) { InitializeAndOpen("sfx.m4a"); ExpectContainer(container_names::CONTAINER_MOV); } -TEST_F(FFmpegGlueContainerTest, MP3) { - InitializeAndOpen("sfx.mp3"); - ExpectContainer(container_names::CONTAINER_MP3); -} - TEST_F(FFmpegGlueContainerTest, AAC) { InitializeAndOpen("sfx.adts"); ExpectContainer(container_names::CONTAINER_AAC);
diff --git a/media/filters/media_file_checker_unittest.cc b/media/filters/media_file_checker_unittest.cc index 27d47960..9ee40bf9 100644 --- a/media/filters/media_file_checker_unittest.cc +++ b/media/filters/media_file_checker_unittest.cc
@@ -38,10 +38,8 @@ RunMediaFileChecker("sfx.ogg", true); } -#if BUILDFLAG(USE_PROPRIETARY_CODECS) TEST(MediaFileCheckerTest, MP3) { RunMediaFileChecker("sfx.mp3", true); } -#endif } // namespace media
diff --git a/media/filters/stream_parser_factory.cc b/media/filters/stream_parser_factory.cc index 927c8b7..f9e9601 100644 --- a/media/filters/stream_parser_factory.cc +++ b/media/filters/stream_parser_factory.cc
@@ -217,15 +217,9 @@ return new MPEG1AudioStreamParser(); } -bool CheckIfMseFlacInIsobmffEnabled(const std::string& codec_id, - MediaLog* media_log) { - return base::FeatureList::IsEnabled(kMseFlacInIsobmff); -} - static const CodecInfo kMPEG4VP09CodecInfo = { "vp09.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_VP9}; -static const CodecInfo kMPEG4FLACCodecInfo = {"flac", CodecInfo::AUDIO, - &CheckIfMseFlacInIsobmffEnabled, +static const CodecInfo kMPEG4FLACCodecInfo = {"flac", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_FLAC}; static const CodecInfo* const kVideoMP4Codecs[] = {&kMPEG4FLACCodecInfo,
diff --git a/media/formats/BUILD.gn b/media/formats/BUILD.gn index c8d616e..1ed89cb 100644 --- a/media/formats/BUILD.gn +++ b/media/formats/BUILD.gn
@@ -162,6 +162,8 @@ visibility = [ "//media:test_support" ] sources = [ + "common/stream_parser_test_base.cc", + "common/stream_parser_test_base.h", "webm/cluster_builder.cc", "webm/cluster_builder.h", "webm/opus_packet_builder.cc", @@ -178,22 +180,14 @@ deps = [ "//base/test:test_support", "//media/base:test_support", + "//testing/gtest", ] - if (proprietary_codecs) { + if (proprietary_codecs && enable_mse_mpeg2ts_stream_parser) { sources += [ - "common/stream_parser_test_base.cc", - "common/stream_parser_test_base.h", + "mp2t/es_parser_test_base.cc", + "mp2t/es_parser_test_base.h", ] - - deps += [ "//testing/gtest" ] - - if (enable_mse_mpeg2ts_stream_parser) { - sources += [ - "mp2t/es_parser_test_base.cc", - "mp2t/es_parser_test_base.h", - ] - } } } @@ -202,6 +196,7 @@ sources = [ "ac3/ac3_util_unittest.cc", "common/offset_byte_queue_unittest.cc", + "mpeg/mpeg1_audio_stream_parser_unittest.cc", "webm/webm_cluster_parser_unittest.cc", "webm/webm_content_encodings_client_unittest.cc", "webm/webm_crypto_helpers_unittest.cc", @@ -234,7 +229,6 @@ "mp4/sample_to_group_iterator_unittest.cc", "mp4/track_run_iterator_unittest.cc", "mpeg/adts_stream_parser_unittest.cc", - "mpeg/mpeg1_audio_stream_parser_unittest.cc", ] deps += [ "//crypto" ]
diff --git a/media/formats/mp4/box_definitions.cc b/media/formats/mp4/box_definitions.cc index 7dd4198..6def180 100644 --- a/media/formats/mp4/box_definitions.cc +++ b/media/formats/mp4/box_definitions.cc
@@ -1040,10 +1040,6 @@ // Read the FLACSpecificBox, even if CENC is signalled. if (format == FOURCC_FLAC || (format == FOURCC_ENCA && sinf.format.format == FOURCC_FLAC)) { - RCHECK_MEDIA_LOGGED(base::FeatureList::IsEnabled(kMseFlacInIsobmff), - reader->media_log(), - "MSE support for FLAC in MP4 is not enabled."); - RCHECK_MEDIA_LOGGED(reader->ReadChild(&dfla), reader->media_log(), "Failure parsing FLACSpecificBox (dfLa)");
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc index 6a35ed9..681274b 100644 --- a/media/formats/mp4/mp4_stream_parser.cc +++ b/media/formats/mp4/mp4_stream_parser.cc
@@ -91,7 +91,6 @@ has_flac_(has_flac), num_empty_samples_skipped_(0), num_invalid_conversions_(0) { - DCHECK(!has_flac || base::FeatureList::IsEnabled(kMseFlacInIsobmff)); } MP4StreamParser::~MP4StreamParser() = default;
diff --git a/media/formats/mp4/mp4_stream_parser_unittest.cc b/media/formats/mp4/mp4_stream_parser_unittest.cc index bc8cf117..dac384d 100644 --- a/media/formats/mp4/mp4_stream_parser_unittest.cc +++ b/media/formats/mp4/mp4_stream_parser_unittest.cc
@@ -472,10 +472,6 @@ } TEST_F(MP4StreamParserTest, Flac) { - // The feature is disabled by default. Enable it. - base::test::ScopedFeatureList features; - features.InitAndEnableFeature(kMseFlacInIsobmff); - parser_.reset(new MP4StreamParser(std::set<int>(), false, true)); auto params = GetDefaultInitParametersExpectations(); @@ -487,10 +483,6 @@ } TEST_F(MP4StreamParserTest, Flac192kHz) { - // The feature is disabled by default. Enable it. - base::test::ScopedFeatureList features; - features.InitAndEnableFeature(kMseFlacInIsobmff); - parser_.reset(new MP4StreamParser(std::set<int>(), false, true)); auto params = GetDefaultInitParametersExpectations();
diff --git a/media/test/BUILD.gn b/media/test/BUILD.gn index ef031a4a..2e6bdabd 100644 --- a/media/test/BUILD.gn +++ b/media/test/BUILD.gn
@@ -161,6 +161,8 @@ "WEBM_VP8", "WEBM_VP9", "WEBM_OPUS_VP9", + "MP4_FLAC", + "MP3", # See below for additional variants depending on build configuration. ] @@ -168,7 +170,6 @@ if (proprietary_codecs) { pipeline_integration_fuzzer_variants += [ "ADTS", - "MP3", "MP4_AACLC", "MP4_AACSBR", @@ -176,7 +177,6 @@ # SourceBufferState::Init differentiate kinds of AVC, we use "AVC1" here to # retain corpus associated with this fuzzer target name. "MP4_AVC1", - "MP4_FLAC", "MP4_AACLC_AVC", ] if (enable_mse_mpeg2ts_stream_parser) {
diff --git a/media/test/pipeline_integration_fuzzertest.cc b/media/test/pipeline_integration_fuzzertest.cc index b954ef0..7148e4b 100644 --- a/media/test/pipeline_integration_fuzzertest.cc +++ b/media/test/pipeline_integration_fuzzertest.cc
@@ -31,13 +31,13 @@ WEBM_VP8, WEBM_VP9, WEBM_OPUS_VP9, + MP4_FLAC, + MP3, #if BUILDFLAG(USE_PROPRIETARY_CODECS) ADTS, - MP3, MP4_AACLC, MP4_AACSBR, MP4_AVC1, - MP4_FLAC, MP4_AACLC_AVC, #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) MP2T_AACLC, @@ -61,19 +61,19 @@ return "video/webm; codecs=\"vp9\""; case WEBM_OPUS_VP9: return "video/webm; codecs=\"opus,vp9\""; + case MP4_FLAC: + return "audio/mp4; codecs=\"flac\""; + case MP3: + return "audio/mpeg"; #if BUILDFLAG(USE_PROPRIETARY_CODECS) case ADTS: return "audio/aac"; - case MP3: - return "audio/mpeg"; case MP4_AACLC: return "audio/mp4; codecs=\"mp4a.40.2\""; case MP4_AACSBR: return "audio/mp4; codecs=\"mp4a.40.5\""; case MP4_AVC1: return "video/mp4; codecs=\"avc1.42E01E\""; - case MP4_FLAC: - return "audio/mp4; codecs=\"flac\""; case MP4_AACLC_AVC: return "video/mp4; codecs=\"mp4a.40.2,avc1.42E01E\""; #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) @@ -147,7 +147,6 @@ } ~ProgressivePipelineIntegrationFuzzerTest() override = default; - ; void RunTest(const uint8_t* data, size_t size) { if (PIPELINE_OK != Start(data, size, kUnreliableDuration)) @@ -172,7 +171,6 @@ } ~MediaSourcePipelineIntegrationFuzzerTest() override = default; - ; void RunTest(const uint8_t* data, size_t size, const std::string& mimetype) { if (size == 0) @@ -226,9 +224,6 @@ media::InitializeMediaLibrary(); - base::test::ScopedFeatureList features; - features.InitAndEnableFeature(media::kMseFlacInIsobmff); - FuzzerVariant variant = PIPELINE_FUZZER_VARIANT; if (variant == SRC) {
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc index 6d82002..f1a5128f 100644 --- a/media/test/pipeline_integration_test.cc +++ b/media/test/pipeline_integration_test.cc
@@ -1588,10 +1588,6 @@ #endif TEST_P(MSEPipelineIntegrationTest, FlacInMp4_Hashed) { - // The feature is disabled by default. Enable it. - base::test::ScopedFeatureList features; - features.InitAndEnableFeature(kMseFlacInIsobmff); - MockMediaSource source("sfx-flac_frag.mp4", kMP4AudioFlac, kAppendWholeFile); EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source, kHashed, nullptr)); @@ -2012,6 +2008,7 @@ EXPECT_EQ(CHUNK_DEMUXER_ERROR_APPEND_FAILED, WaitUntilEndedOrError()); source.Shutdown(); } +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) // Verify files which change configuration midstream fail gracefully. TEST_F(PipelineIntegrationTest, MidStreamConfigChangesFail) { @@ -2019,7 +2016,6 @@ Play(); ASSERT_EQ(WaitUntilEndedOrError(), PIPELINE_ERROR_DECODE); } -#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) { ASSERT_EQ(PIPELINE_OK, Start("bear-320x240-16x9-aspect.webm"));
diff --git a/media/test/pipeline_integration_test_base.cc b/media/test/pipeline_integration_test_base.cc index 68a688fe..66f0913 100644 --- a/media/test/pipeline_integration_test_base.cc +++ b/media/test/pipeline_integration_test_base.cc
@@ -358,7 +358,7 @@ pipeline_->Seek(seek_time, base::Bind(&PipelineIntegrationTestBase::OnSeeked, base::Unretained(this), seek_time)); - RunUntilQuit(&run_loop); + RunUntilQuitOrError(&run_loop); return (pipeline_status_ == PIPELINE_OK); } @@ -367,7 +367,7 @@ pipeline_->Suspend(base::Bind(&PipelineIntegrationTestBase::OnStatusCallback, base::Unretained(this), run_loop.QuitWhenIdleClosure())); - RunUntilQuit(&run_loop); + RunUntilQuitOrError(&run_loop); return (pipeline_status_ == PIPELINE_OK); } @@ -382,7 +382,7 @@ seek_time, base::Bind(&PipelineIntegrationTestBase::OnSeeked, base::Unretained(this), seek_time)); - RunUntilQuit(&run_loop); + RunUntilQuitOrError(&run_loop); return (pipeline_status_ == PIPELINE_OK); } @@ -655,7 +655,10 @@ return pipeline_status_; } -void PipelineIntegrationTestBase::RunUntilQuit(base::RunLoop* run_loop) { +void PipelineIntegrationTestBase::RunUntilQuitOrError(base::RunLoop* run_loop) { + // We always install an error handler to avoid test hangs. + on_error_closure_ = run_loop->QuitWhenIdleClosure(); + run_loop->Run(); on_ended_closure_ = base::OnceClosure(); on_error_closure_ = base::OnceClosure(); @@ -668,8 +671,7 @@ DCHECK(on_error_closure_.is_null()); on_ended_closure_ = run_loop->QuitWhenIdleClosure(); - on_error_closure_ = run_loop->QuitWhenIdleClosure(); - RunUntilQuit(run_loop); + RunUntilQuitOrError(run_loop); } base::TimeTicks DummyTickClock::NowTicks() const {
diff --git a/media/test/pipeline_integration_test_base.h b/media/test/pipeline_integration_test_base.h index aa27784..9fb3815 100644 --- a/media/test/pipeline_integration_test_base.h +++ b/media/test/pipeline_integration_test_base.h
@@ -253,11 +253,13 @@ private: // Runs |run_loop| until it is explicitly Quit() by some part of the calling - // test fixture. The |scoped_task_environment_| is RunUntilIdle() after the - // RunLoop finishes running, before returning to the caller. - void RunUntilQuit(base::RunLoop* run_loop); - // Configures |on_ended_closure_| and |on_error_closure_| to quit |run_loop| - // and then calls RunUntilQuit() on it. + // test fixture or when an error occurs (by setting |on_error_closure_|). The + // |scoped_task_environment_| is RunUntilIdle() after the RunLoop finishes + // running, before returning to the caller. + void RunUntilQuitOrError(base::RunLoop* run_loop); + + // Configures |on_ended_closure_| to quit |run_loop| and then calls + // RunUntilQuitOrError() on it. void RunUntilQuitOrEndedOrError(base::RunLoop* run_loop); base::OnceClosure on_ended_closure_;
diff --git a/net/quic/core/congestion_control/bbr_sender.cc b/net/quic/core/congestion_control/bbr_sender.cc index ecbdbd7..a3aa205 100644 --- a/net/quic/core/congestion_control/bbr_sender.cc +++ b/net/quic/core/congestion_control/bbr_sender.cc
@@ -93,8 +93,6 @@ max_ack_height_(kBandwidthWindowSize, 0, 0), aggregation_epoch_start_time_(QuicTime::Zero()), aggregation_epoch_bytes_(0), - bytes_acked_since_queue_drained_(0), - max_aggregation_bytes_multiplier_(0), min_rtt_(QuicTime::Delta::Zero()), min_rtt_timestamp_(QuicTime::Zero()), congestion_window_(initial_tcp_congestion_window * kDefaultTCPMSS), @@ -225,12 +223,6 @@ config.HasClientRequestedIndependentOption(kBBRR, perspective)) { rate_based_recovery_ = true; } - if (config.HasClientRequestedIndependentOption(kBBR1, perspective)) { - max_aggregation_bytes_multiplier_ = 1.5; - } - if (config.HasClientRequestedIndependentOption(kBBR2, perspective)) { - max_aggregation_bytes_multiplier_ = 2; - } if (config.HasClientRequestedIndependentOption(kBBRS, perspective)) { slower_startup_ = true; } @@ -308,14 +300,6 @@ sampler_->total_bytes_acked() - total_bytes_acked_before; UpdateAckAggregationBytes(event_time, bytes_acked); - if (max_aggregation_bytes_multiplier_ > 0) { - if (unacked_packets_->bytes_in_flight() <= - 1.25 * GetTargetCongestionWindow(pacing_gain_)) { - bytes_acked_since_queue_drained_ = 0; - } else { - bytes_acked_since_queue_drained_ += bytes_acked; - } - } } // Handle logic specific to PROBE_BW mode. @@ -488,6 +472,11 @@ void BbrSender::UpdateGainCyclePhase(QuicTime now, QuicByteCount prior_in_flight, bool has_losses) { + QuicByteCount bytes_in_flight = prior_in_flight; + if (GetQuicReloadableFlag(quic_bbr_fix_probe_bw)) { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_bbr_fix_probe_bw); + bytes_in_flight = unacked_packets_->bytes_in_flight(); + } // In most cases, the cycle is advanced after an RTT passes. bool should_advance_gain_cycling = now - last_cycle_start_ > GetMinRtt(); @@ -505,7 +494,7 @@ // queue which could have been incurred by probing prior to it. If the number // of bytes in flight falls down to the estimated BDP value earlier, conclude // that the queue has been successfully drained and exit this cycle early. - if (pacing_gain_ < 1.0 && prior_in_flight <= GetTargetCongestionWindow(1)) { + if (pacing_gain_ < 1.0 && bytes_in_flight <= GetTargetCongestionWindow(1)) { should_advance_gain_cycling = true; } @@ -516,7 +505,7 @@ // Low gain mode will be exited immediately when the target BDP is achieved. if (fully_drain_queue_ && pacing_gain_ < 1 && kPacingGain[cycle_current_offset_] == 1 && - prior_in_flight > GetTargetCongestionWindow(1)) { + bytes_in_flight > GetTargetCongestionWindow(1)) { return; } pacing_gain_ = kPacingGain[cycle_current_offset_]; @@ -705,36 +694,10 @@ if (rtt_variance_weight_ > 0.f && !BandwidthEstimate().IsZero()) { target_window += rtt_variance_weight_ * rtt_stats_->mean_deviation() * BandwidthEstimate(); - } else if (max_aggregation_bytes_multiplier_ > 0 && is_at_full_bandwidth_) { - // Subtracting only half the bytes_acked_since_queue_drained ensures sending - // doesn't completely stop for a long period of time if the queue hasn't - // been drained recently. - if (max_aggregation_bytes_multiplier_ * max_ack_height_.GetBest() > - bytes_acked_since_queue_drained_ / 2) { - target_window += - max_aggregation_bytes_multiplier_ * max_ack_height_.GetBest() - - bytes_acked_since_queue_drained_ / 2; - } } else if (is_at_full_bandwidth_) { target_window += max_ack_height_.GetBest(); } - if (GetQuicReloadableFlag(quic_bbr_add_tso_cwnd)) { - // QUIC doesn't have TSO, but it does have similarly quantized pacing, so - // allow extra CWND to make QUIC's BBR CWND identical to TCP's. - QuicByteCount tso_segs_goal = 0; - if (pacing_rate_ < QuicBandwidth::FromKBitsPerSecond(1200)) { - tso_segs_goal = kDefaultTCPMSS; - } else if (pacing_rate_ < QuicBandwidth::FromKBitsPerSecond(24000)) { - tso_segs_goal = 2 * kDefaultTCPMSS; - } else { - tso_segs_goal = - std::min(pacing_rate_ * QuicTime::Delta::FromMilliseconds(1), - /* 64k */ static_cast<QuicByteCount>(1 << 16)); - } - target_window += 3 * tso_segs_goal; - } - // Instead of immediately setting the target CWND as the new one, BBR grows // the CWND towards |target_window| by only increasing it |bytes_acked| at a // time.
diff --git a/net/quic/core/congestion_control/bbr_sender.h b/net/quic/core/congestion_control/bbr_sender.h index 46993fc2..cb3f0fbe 100644 --- a/net/quic/core/congestion_control/bbr_sender.h +++ b/net/quic/core/congestion_control/bbr_sender.h
@@ -248,14 +248,6 @@ QuicTime aggregation_epoch_start_time_; QuicByteCount aggregation_epoch_bytes_; - // The number of bytes acknowledged since the last time bytes in flight - // dropped below the target window. - QuicByteCount bytes_acked_since_queue_drained_; - - // The muliplier for calculating the max amount of extra CWND to add to - // compensate for ack aggregation. - float max_aggregation_bytes_multiplier_; - // Minimum RTT estimate. Automatically expires within 10 seconds (and // triggers PROBE_RTT mode) if no new value is sampled during that period. QuicTime::Delta min_rtt_;
diff --git a/net/quic/core/congestion_control/bbr_sender_test.cc b/net/quic/core/congestion_control/bbr_sender_test.cc index 6c12d58..6c3302b95 100644 --- a/net/quic/core/congestion_control/bbr_sender_test.cc +++ b/net/quic/core/congestion_control/bbr_sender_test.cc
@@ -92,9 +92,6 @@ /*connection_id=*/43), receiver_multiplexer_("Receiver multiplexer", {&receiver_, &competing_receiver_}) { - // These will be changed by the appropriate tests as necessary. - SetQuicReloadableFlag(quic_bbr_add_tso_cwnd, false); - rtt_stats_ = bbr_sender_.connection()->sent_packet_manager().GetRttStats(); sender_ = SetupBbrSender(&bbr_sender_); @@ -258,8 +255,6 @@ // Test a simple long data transfer in the default setup. TEST_F(BbrSenderTest, SimpleTransfer) { - // Adding TSO CWND causes packet loss before exiting startup. - SetQuicReloadableFlag(quic_bbr_add_tso_cwnd, false); // Disable Ack Decimation on the receiver, because it can increase srtt. QuicConnectionPeer::SetAckMode(receiver_.connection(), QuicConnection::AckMode::TCP_ACKING); @@ -309,7 +304,6 @@ // Test a simple long data transfer with 2 rtts of aggregation. TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes) { - SetQuicReloadableFlag(quic_bbr_add_tso_cwnd, false); CreateDefaultSetup(); // 2 RTTs of aggregation, with a max of 10kb. EnableAggregation(10 * 1024, 2 * kTestRtt); @@ -368,76 +362,7 @@ } // Test a simple long data transfer with 2 rtts of aggregation. -TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes4) { - SetQuicReloadableFlag(quic_bbr_add_tso_cwnd, false); - // Disable Ack Decimation on the receiver, because it can increase srtt. - QuicConnectionPeer::SetAckMode(receiver_.connection(), - QuicConnection::AckMode::TCP_ACKING); - CreateDefaultSetup(); - // Enable ack aggregation that forces the queue to be drained. - SetConnectionOption(kBBR1); - - // 2 RTTs of aggregation, with a max of 10kb. - EnableAggregation(10 * 1024, 2 * kTestRtt); - - // Transfer 12MB. - DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35)); - EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode); - // It's possible to read a bandwidth as much as 50% too high with aggregation. - EXPECT_LE(kTestLinkBandwidth * 0.99f, - sender_->ExportDebugState().max_bandwidth); - // TODO(ianswett): Tighten this bound once we understand why BBR is - // overestimating bandwidth with aggregation. b/36022633 - EXPECT_GE(kTestLinkBandwidth * 1.5f, - sender_->ExportDebugState().max_bandwidth); - // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures - // bandwidth higher than the link rate. - // The margin here is high, because the aggregation greatly increases - // smoothed rtt. - EXPECT_GE(kTestRtt * 3.5, rtt_stats_->smoothed_rtt()); - ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.12f); -} - -// Test a simple long data transfer with 2 rtts of aggregation. -TEST_F(BbrSenderTest, SimpleTransferAckDecimation4) { - // Decrease the CWND gain so extra CWND is required with stretch acks. - FLAGS_quic_bbr_cwnd_gain = 1.0; - sender_ = new BbrSender( - rtt_stats_, - QuicSentPacketManagerPeer::GetUnackedPacketMap( - QuicConnectionPeer::GetSentPacketManager(bbr_sender_.connection())), - kInitialCongestionWindowPackets, kDefaultMaxCongestionWindowPackets, - &random_); - QuicConnectionPeer::SetSendAlgorithm(bbr_sender_.connection(), sender_); - // Enable Ack Decimation on the receiver. - QuicConnectionPeer::SetAckMode(receiver_.connection(), - QuicConnection::AckMode::ACK_DECIMATION); - CreateDefaultSetup(); - // Enable ack aggregation that forces the queue to be drained. - SetConnectionOption(kBBR1); - - // Transfer 12MB. - DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35)); - EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode); - // It's possible to read a bandwidth as much as 50% too high with aggregation. - EXPECT_LE(kTestLinkBandwidth * 0.99f, - sender_->ExportDebugState().max_bandwidth); - // TODO(ianswett): Tighten this bound once we understand why BBR is - // overestimating bandwidth with aggregation. b/36022633 - EXPECT_GE(kTestLinkBandwidth * 1.5f, - sender_->ExportDebugState().max_bandwidth); - // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures - // bandwidth higher than the link rate. - EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited); - // The margin here is high, because the aggregation greatly increases - // smoothed rtt. - EXPECT_GE(kTestRtt * 2, rtt_stats_->smoothed_rtt()); - ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.1f); -} - -// Test a simple long data transfer with 2 rtts of aggregation. TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes20RTTWindow) { - SetQuicReloadableFlag(quic_bbr_add_tso_cwnd, false); // Disable Ack Decimation on the receiver, because it can increase srtt. QuicConnectionPeer::SetAckMode(receiver_.connection(), QuicConnection::AckMode::TCP_ACKING); @@ -466,7 +391,6 @@ // Test a simple long data transfer with 2 rtts of aggregation. TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes40RTTWindow) { - SetQuicReloadableFlag(quic_bbr_add_tso_cwnd, false); // Disable Ack Decimation on the receiver, because it can increase srtt. QuicConnectionPeer::SetAckMode(receiver_.connection(), QuicConnection::AckMode::TCP_ACKING); @@ -936,8 +860,6 @@ // Test exiting STARTUP earlier due to the 2RTT connection option. TEST_F(BbrSenderTest, SimpleTransfer2RTTStartup) { - // Adding TSO CWND causes packet loss before exiting startup. - SetQuicReloadableFlag(quic_bbr_add_tso_cwnd, false); CreateDefaultSetup(); SetConnectionOption(k2RTT); @@ -1022,8 +944,6 @@ // Test slower pacing after loss in STARTUP due to the BBRS connection option. TEST_F(BbrSenderTest, SimpleTransferSlowerStartup) { - // Adding TSO CWND causes packet loss before exiting startup. - SetQuicReloadableFlag(quic_bbr_add_tso_cwnd, false); CreateSmallBufferSetup(); SetConnectionOption(kBBRS); @@ -1058,8 +978,6 @@ // Ensures no change in congestion window in STARTUP after loss. TEST_F(BbrSenderTest, SimpleTransferNoConservationInStartup) { - // Adding TSO CWND causes packet loss before exiting startup. - SetQuicReloadableFlag(quic_bbr_add_tso_cwnd, false); CreateSmallBufferSetup(); SetConnectionOption(kBBS1);
diff --git a/net/quic/core/crypto/crypto_handshake_message.cc b/net/quic/core/crypto/crypto_handshake_message.cc index c2b052e6..06e93eb 100644 --- a/net/quic/core/crypto/crypto_handshake_message.cc +++ b/net/quic/core/crypto/crypto_handshake_message.cc
@@ -73,19 +73,18 @@ void CryptoHandshakeMessage::SetVersionVector( QuicTag tag, - QuicTransportVersionVector versions) { + ParsedQuicVersionVector versions) { QuicVersionLabelVector version_labels; - for (QuicTransportVersion version : versions) { + for (ParsedQuicVersion version : versions) { version_labels.push_back( - QuicEndian::HostToNet32(QuicVersionToQuicVersionLabel(version))); + QuicEndian::HostToNet32(CreateQuicVersionLabel(version))); } SetVector(tag, version_labels); } void CryptoHandshakeMessage::SetVersion(QuicTag tag, - QuicTransportVersion version) { - SetValue(tag, - QuicEndian::HostToNet32(QuicVersionToQuicVersionLabel(version))); + ParsedQuicVersion version) { + SetValue(tag, QuicEndian::HostToNet32(CreateQuicVersionLabel(version))); } void CryptoHandshakeMessage::SetStringPiece(QuicTag tag,
diff --git a/net/quic/core/crypto/crypto_handshake_message.h b/net/quic/core/crypto/crypto_handshake_message.h index 772c036..6b57c56 100644 --- a/net/quic/core/crypto/crypto_handshake_message.h +++ b/net/quic/core/crypto/crypto_handshake_message.h
@@ -62,11 +62,11 @@ // Sets an element with the given tag to the on-the-wire representation of // |version|. - void SetVersion(QuicTag tag, QuicTransportVersion version); + void SetVersion(QuicTag tag, ParsedQuicVersion version); // Sets an element with the given tag to the on-the-wire representation of // the elements in |versions|. - void SetVersionVector(QuicTag tag, QuicTransportVersionVector versions); + void SetVersionVector(QuicTag tag, ParsedQuicVersionVector versions); // Returns the message tag. QuicTag tag() const { return tag_; }
diff --git a/net/quic/core/crypto/crypto_protocol.h b/net/quic/core/crypto/crypto_protocol.h index 1b2d647..3fe1bfb6 100644 --- a/net/quic/core/crypto/crypto_protocol.h +++ b/net/quic/core/crypto/crypto_protocol.h
@@ -87,8 +87,8 @@ const QuicTag kBBS3 = TAG('B', 'B', 'S', '3'); // Slowstart packet // conservation in BBR STARTUP const QuicTag kBBRR = TAG('B', 'B', 'R', 'R'); // Rate-based recovery in BBR -const QuicTag kBBR1 = TAG('B', 'B', 'R', '1'); // Ack aggregation v1 -const QuicTag kBBR2 = TAG('B', 'B', 'R', '2'); // Ack aggregation v2 +const QuicTag kBBR1 = TAG('B', 'B', 'R', '1'); // DEPRECATED +const QuicTag kBBR2 = TAG('B', 'B', 'R', '2'); // DEPRECATED const QuicTag kBBR3 = TAG('B', 'B', 'R', '3'); // Fully drain the queue once // per cycle const QuicTag kBBR4 = TAG('B', 'B', 'R', '4'); // 20 RTT ack aggregation @@ -111,6 +111,7 @@ const QuicTag k1CON = TAG('1', 'C', 'O', 'N'); // Emulate a single connection const QuicTag kNTLP = TAG('N', 'T', 'L', 'P'); // No tail loss probe const QuicTag k1TLP = TAG('1', 'T', 'L', 'P'); // 1 tail loss probe +const QuicTag k1RTO = TAG('1', 'R', 'T', 'O'); // Send 1 packet upon RTO const QuicTag kNCON = TAG('N', 'C', 'O', 'N'); // N Connection Congestion Ctrl const QuicTag kNRTO = TAG('N', 'R', 'T', 'O'); // CWND reduction on loss const QuicTag kTIME = TAG('T', 'I', 'M', 'E'); // Time based loss detection @@ -136,6 +137,8 @@ // tolerating out of order. const QuicTag kAKDU = TAG('A', 'K', 'D', 'U'); // Unlimited number of packets // received before acking +const QuicTag kACKQ = TAG('A', 'C', 'K', 'Q'); // Send an immediate ack after + // 1 RTT of not sending acks. const QuicTag kSSLR = TAG('S', 'S', 'L', 'R'); // Slow Start Large Reduction. const QuicTag kNPRR = TAG('N', 'P', 'R', 'R'); // Pace at unity instead of PRR const QuicTag k5RTO = TAG('5', 'R', 'T', 'O'); // Close connection on 5 RTOs @@ -150,6 +153,7 @@ const QuicTag kSMHL = TAG('S', 'M', 'H', 'L'); // Support MAX_HEADER_LIST_SIZE // settings frame. const QuicTag kNSTP = TAG('N', 'S', 'T', 'P'); // No stop waiting frames. +const QuicTag kNRTT = TAG('N', 'R', 'T', 'T'); // Ignore initial RTT // Optional support of truncated Connection IDs. If sent by a peer, the value // is the minimum number of bytes allowed for the connection ID sent to the
diff --git a/net/quic/core/crypto/crypto_server_test.cc b/net/quic/core/crypto/crypto_server_test.cc index 8012d75..3566c8a 100644 --- a/net/quic/core/crypto/crypto_server_test.cc +++ b/net/quic/core/crypto/crypto_server_test.cc
@@ -61,7 +61,7 @@ struct TestParams { TestParams(bool enable_stateless_rejects, bool use_stateless_rejects, - QuicTransportVersionVector supported_versions) + ParsedQuicVersionVector supported_versions) : enable_stateless_rejects(enable_stateless_rejects), use_stateless_rejects(use_stateless_rejects), supported_versions(std::move(supported_versions)) {} @@ -71,7 +71,7 @@ << std::endl; os << " use_stateless_rejects: " << p.use_stateless_rejects << std::endl; os << " versions: " - << QuicTransportVersionVectorToString(p.supported_versions) << " }"; + << ParsedQuicVersionVectorToString(p.supported_versions) << " }"; return os; } @@ -83,7 +83,7 @@ // enable_stateless_rejects is false. bool use_stateless_rejects; // Versions supported by client and server. - QuicTransportVersionVector supported_versions; + ParsedQuicVersionVector supported_versions; }; // Constructs various test permutations. @@ -93,8 +93,7 @@ for (bool enable_stateless_rejects : kTrueFalse) { for (bool use_stateless_rejects : kTrueFalse) { // Start with all versions, remove highest on each iteration. - QuicTransportVersionVector supported_versions = - AllSupportedTransportVersions(); + ParsedQuicVersionVector supported_versions = AllSupportedVersions(); while (!supported_versions.empty()) { params.push_back(TestParams(enable_stateless_rejects, use_stateless_rejects, supported_versions)); @@ -110,6 +109,7 @@ CryptoServerTest() : rand_(QuicRandom::GetInstance()), client_address_(QuicIpAddress::Loopback4(), 1234), + client_version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), config_(QuicCryptoServerConfig::TESTING, rand_, crypto_test_utils::ProofSourceForTesting(), @@ -124,8 +124,7 @@ config_.set_enable_serving_sct(true); client_version_ = supported_versions_.front(); - client_version_string_ = QuicVersionLabelToString( - QuicVersionToQuicVersionLabel(client_version_)); + client_version_string_ = ParsedQuicVersionToString(client_version_); SetQuicReloadableFlag(enable_quic_stateless_reject_support, GetParam().enable_stateless_rejects); @@ -225,8 +224,7 @@ server_hello.GetVersionLabelList(kVER, &versions); ASSERT_EQ(supported_versions_.size(), versions.size()); for (size_t i = 0; i < versions.size(); ++i) { - EXPECT_EQ(QuicVersionToQuicVersionLabel(supported_versions_[i]), - versions[i]); + EXPECT_EQ(CreateQuicVersionLabel(supported_versions_[i]), versions[i]); } QuicStringPiece address; @@ -242,7 +240,7 @@ QuicSocketAddress server_address; config_.ValidateClientHello( message, client_address_.host(), server_address, - supported_versions_.front(), &clock_, signed_config_, + supported_versions_.front().transport_version, &clock_, signed_config_, QuicMakeUnique<ValidateCallback>(this, true, "", &called)); EXPECT_TRUE(called); } @@ -260,7 +258,7 @@ QuicSocketAddress server_address; config_.ValidateClientHello( message, client_address_.host(), server_address, - supported_versions_.front(), &clock_, signed_config_, + supported_versions_.front().transport_version, &clock_, signed_config_, QuicMakeUnique<ValidateCallback>(this, false, error_substr, called)); } @@ -398,8 +396,8 @@ MockRandom rand_for_id_generation_; MockClock clock_; QuicSocketAddress client_address_; - QuicTransportVersionVector supported_versions_; - QuicTransportVersion client_version_; + ParsedQuicVersionVector supported_versions_; + ParsedQuicVersion client_version_; QuicString client_version_string_; QuicCryptoServerConfig config_; QuicCryptoServerConfigPeer peer_; @@ -673,8 +671,8 @@ } // Set the client's preferred version to a supported version that // is not the "current" version (supported_versions_.front()). - QuicString bad_version = QuicVersionLabelToString( - QuicVersionToQuicVersionLabel(supported_versions_.back())); + QuicString bad_version = + ParsedQuicVersionToString(supported_versions_.back()); CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO( {{"PDMD", "X509"}, {"VER\0", bad_version}}, kClientHelloMinimumSize); @@ -848,11 +846,11 @@ new DummyProofVerifierCallback()); QuicString chlo_hash; CryptoUtils::HashHandshakeMessage(msg, &chlo_hash, Perspective::IS_SERVER); - EXPECT_EQ(QUIC_SUCCESS, - proof_verifier->VerifyProof( - "test.example.com", 443, (string(scfg_str)), client_version_, - chlo_hash, certs, "", (string(proof)), verify_context.get(), - &error_details, &details, std::move(callback))); + EXPECT_EQ(QUIC_SUCCESS, proof_verifier->VerifyProof( + "test.example.com", 443, (string(scfg_str)), + client_version_.transport_version, chlo_hash, + certs, "", (string(proof)), verify_context.get(), + &error_details, &details, std::move(callback))); } TEST_P(CryptoServerTest, RejectInvalidXlct) { @@ -1101,8 +1099,7 @@ public: void SetUp() override { client_version_ = supported_versions_.back(); - client_version_string_ = QuicVersionLabelToString( - QuicVersionToQuicVersionLabel(client_version_)); + client_version_string_ = ParsedQuicVersionToString(client_version_); CryptoServerTest::SetUp(); } };
diff --git a/net/quic/core/crypto/crypto_utils.cc b/net/quic/core/crypto/crypto_utils.cc index edb7287..f9bb63c 100644 --- a/net/quic/core/crypto/crypto_utils.cc +++ b/net/quic/core/crypto/crypto_utils.cc
@@ -281,7 +281,7 @@ QuicErrorCode CryptoUtils::ValidateServerHello( const CryptoHandshakeMessage& server_hello, - const QuicTransportVersionVector& negotiated_versions, + const ParsedQuicVersionVector& negotiated_versions, QuicString* error_details) { DCHECK(error_details != nullptr); @@ -296,12 +296,20 @@ *error_details = "server hello missing version list"; return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; } + + return ValidateServerHelloVersions(supported_version_labels, + negotiated_versions, error_details); +} + +QuicErrorCode CryptoUtils::ValidateServerHelloVersions( + const QuicVersionLabelVector& server_versions, + const ParsedQuicVersionVector& negotiated_versions, + QuicString* error_details) { if (!negotiated_versions.empty()) { - bool mismatch = - supported_version_labels.size() != negotiated_versions.size(); - for (size_t i = 0; i < supported_version_labels.size() && !mismatch; ++i) { - mismatch = QuicVersionLabelToQuicVersion(supported_version_labels[i]) != - negotiated_versions[i]; + bool mismatch = server_versions.size() != negotiated_versions.size(); + for (size_t i = 0; i < server_versions.size() && !mismatch; ++i) { + mismatch = + server_versions[i] != CreateQuicVersionLabel(negotiated_versions[i]); } // The server sent a list of supported versions, and the connection // reports that there was a version negotiation during the handshake. @@ -316,8 +324,8 @@ QuicErrorCode CryptoUtils::ValidateClientHello( const CryptoHandshakeMessage& client_hello, - QuicTransportVersion version, - const QuicTransportVersionVector& supported_versions, + ParsedQuicVersion version, + const ParsedQuicVersionVector& supported_versions, QuicString* error_details) { if (client_hello.tag() != kCHLO) { *error_details = "Bad tag"; @@ -334,14 +342,21 @@ *error_details = "client hello missing version list"; return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; } - QuicTransportVersion client_version = - QuicVersionLabelToQuicVersion(client_version_label); - if (client_version != version) { - // Just because client_version is a valid version enum doesn't mean that - // this server actually supports that version, so we check to see if - // it's actually in the supported versions list. + return ValidateClientHelloVersion(client_version_label, version, + supported_versions, error_details); +} + +QuicErrorCode CryptoUtils::ValidateClientHelloVersion( + QuicVersionLabel client_version, + ParsedQuicVersion connection_version, + const ParsedQuicVersionVector& supported_versions, + QuicString* error_details) { + if (client_version != CreateQuicVersionLabel(connection_version)) { + // Check to see if |client_version| is actually on the supported versions + // list. If not, the server doesn't support that version and it's not a + // downgrade attack. for (size_t i = 0; i < supported_versions.size(); ++i) { - if (client_version == supported_versions[i]) { + if (client_version == CreateQuicVersionLabel(supported_versions[i])) { *error_details = "Downgrade attack detected"; return QUIC_VERSION_NEGOTIATION_MISMATCH; }
diff --git a/net/quic/core/crypto/crypto_utils.h b/net/quic/core/crypto/crypto_utils.h index 8315bae..9a7f60e2 100644 --- a/net/quic/core/crypto/crypto_utils.h +++ b/net/quic/core/crypto/crypto_utils.h
@@ -166,7 +166,19 @@ // code and sets |error_details|. static QuicErrorCode ValidateServerHello( const CryptoHandshakeMessage& server_hello, - const QuicTransportVersionVector& negotiated_versions, + const ParsedQuicVersionVector& negotiated_versions, + QuicString* error_details); + + // Validates that the |server_versions| received do not indicate that the + // ServerHello is part of a downgrade attack. |negotiated_versions| must + // contain the list of versions received in the server's version negotiation + // packet (or be empty if no such packet was received). + // + // Returns QUIC_NO_ERROR if this is the case or returns the appropriate error + // code and sets |error_details|. + static QuicErrorCode ValidateServerHelloVersions( + const QuicVersionLabelVector& server_versions, + const ParsedQuicVersionVector& negotiated_versions, QuicString* error_details); // Validates that |client_hello| is actually a CHLO and that this is not part @@ -177,8 +189,21 @@ // code and sets |error_details|. static QuicErrorCode ValidateClientHello( const CryptoHandshakeMessage& client_hello, - QuicTransportVersion version, - const QuicTransportVersionVector& supported_versions, + ParsedQuicVersion version, + const ParsedQuicVersionVector& supported_versions, + QuicString* error_details); + + // Validates that the |client_version| received does not indicate that a + // downgrade attack has occurred. |connection_version| is the version of the + // QuicConnection, and |supported_versions| is all versions that that + // QuicConnection supports. + // + // Returns QUIC_NO_ERROR if this is the case or returns the appropriate error + // code and sets |error_details|. + static QuicErrorCode ValidateClientHelloVersion( + QuicVersionLabel client_version, + ParsedQuicVersion connection_version, + const ParsedQuicVersionVector& supported_versions, QuicString* error_details); // Returns the name of the HandshakeFailureReason as a char*
diff --git a/net/quic/core/crypto/quic_crypto_client_config.cc b/net/quic/core/crypto/quic_crypto_client_config.cc index 1ce64244..7bc2862 100644 --- a/net/quic/core/crypto/quic_crypto_client_config.cc +++ b/net/quic/core/crypto/quic_crypto_client_config.cc
@@ -426,7 +426,7 @@ void QuicCryptoClientConfig::FillInchoateClientHello( const QuicServerId& server_id, - const QuicTransportVersion preferred_version, + const ParsedQuicVersion preferred_version, const CachedState* cached, QuicRandom* rand, bool demand_x509_proof, @@ -503,7 +503,7 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello( const QuicServerId& server_id, QuicConnectionId connection_id, - const QuicTransportVersion preferred_version, + const ParsedQuicVersion preferred_version, const CachedState* cached, QuicWallTime now, QuicRandom* rand, @@ -671,7 +671,7 @@ std::unique_ptr<char[]> output(new char[encrypted_len]); size_t output_size = 0; if (!crypters.encrypter->EncryptPacket( - preferred_version, 0 /* packet number */, + preferred_version.transport_version, 0 /* packet number */, QuicStringPiece() /* associated data */, cetv_plaintext.AsStringPiece(), output.get(), &output_size, encrypted_len)) { @@ -842,8 +842,8 @@ QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( const CryptoHandshakeMessage& server_hello, QuicConnectionId connection_id, - QuicTransportVersion version, - const QuicTransportVersionVector& negotiated_versions, + ParsedQuicVersion version, + const ParsedQuicVersionVector& negotiated_versions, CachedState* cached, QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params, QuicString* error_details) {
diff --git a/net/quic/core/crypto/quic_crypto_client_config.h b/net/quic/core/crypto/quic_crypto_client_config.h index b38584a..2ef884f 100644 --- a/net/quic/core/crypto/quic_crypto_client_config.h +++ b/net/quic/core/crypto/quic_crypto_client_config.h
@@ -228,7 +228,7 @@ // certificate related fields. void FillInchoateClientHello( const QuicServerId& server_id, - const QuicTransportVersion preferred_version, + const ParsedQuicVersion preferred_version, const CachedState* cached, QuicRandom* rand, bool demand_x509_proof, @@ -252,7 +252,7 @@ QuicErrorCode FillClientHello( const QuicServerId& server_id, QuicConnectionId connection_id, - const QuicTransportVersion preferred_version, + const ParsedQuicVersion preferred_version, const CachedState* cached, QuicWallTime now, QuicRandom* rand, @@ -288,8 +288,8 @@ QuicErrorCode ProcessServerHello( const CryptoHandshakeMessage& server_hello, QuicConnectionId connection_id, - QuicTransportVersion version, - const QuicTransportVersionVector& negotiated_versions, + ParsedQuicVersion version, + const ParsedQuicVersionVector& negotiated_versions, CachedState* cached, QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params, QuicString* error_details);
diff --git a/net/quic/core/crypto/quic_crypto_client_config_test.cc b/net/quic/core/crypto/quic_crypto_client_config_test.cc index 4bdb2ea..1f2433de6 100644 --- a/net/quic/core/crypto/quic_crypto_client_config_test.cc +++ b/net/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -182,13 +182,12 @@ CryptoHandshakeMessage msg; QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); MockRandom rand; - config.FillInchoateClientHello(server_id, QuicTransportVersionMax(), &state, - &rand, + config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand, /* demand_x509_proof= */ true, params, &msg); QuicVersionLabel cver; EXPECT_EQ(QUIC_NO_ERROR, msg.GetVersionLabel(kVER, &cver)); - EXPECT_EQ(QuicVersionToQuicVersionLabel(QuicTransportVersionMax()), cver); + EXPECT_EQ(CreateQuicVersionLabel(QuicVersionMax()), cver); QuicStringPiece proof_nonce; EXPECT_TRUE(msg.GetStringPiece(kNONP, &proof_nonce)); EXPECT_EQ(QuicString(32, 'r'), proof_nonce); @@ -218,8 +217,7 @@ CryptoHandshakeMessage msg; QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); MockRandom rand; - config.FillInchoateClientHello(server_id, QuicTransportVersionMax(), &state, - &rand, + config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand, /* demand_x509_proof= */ true, params, &msg); QuicTag pdmd; @@ -250,8 +248,7 @@ CryptoHandshakeMessage msg; QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); MockRandom rand; - config.FillInchoateClientHello(server_id, QuicTransportVersionMax(), &state, - &rand, + config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand, /* demand_x509_proof= */ true, params, &msg); QuicStringPiece scid; @@ -279,8 +276,7 @@ CryptoHandshakeMessage msg; QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); MockRandom rand; - config.FillInchoateClientHello(server_id, QuicTransportVersionMax(), &state, - &rand, + config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand, /* demand_x509_proof= */ true, params, &msg); QuicStringPiece scid; @@ -299,26 +295,25 @@ MockRandom rand; CryptoHandshakeMessage chlo; QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); - config.FillClientHello(server_id, kConnectionId, QuicTransportVersionMax(), - &state, QuicWallTime::Zero(), &rand, + config.FillClientHello(server_id, kConnectionId, QuicVersionMax(), &state, + QuicWallTime::Zero(), &rand, nullptr, // channel_id_key params, &chlo, &error_details); // Verify that the version label has been set correctly in the CHLO. QuicVersionLabel cver; EXPECT_EQ(QUIC_NO_ERROR, chlo.GetVersionLabel(kVER, &cver)); - EXPECT_EQ(QuicVersionToQuicVersionLabel(QuicTransportVersionMax()), cver); + EXPECT_EQ(CreateQuicVersionLabel(QuicVersionMax()), cver); } TEST_F(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) { - QuicTransportVersionVector supported_versions = - AllSupportedTransportVersions(); + ParsedQuicVersionVector supported_versions = AllSupportedVersions(); if (supported_versions.size() == 1) { // No downgrade attack is possible if the client only supports one version. return; } - QuicTransportVersionVector supported_version_vector; + ParsedQuicVersionVector supported_version_vector; for (size_t i = supported_versions.size(); i > 0; --i) { supported_version_vector.push_back(supported_versions[i - 1]); } @@ -589,8 +584,8 @@ CryptoHandshakeMessage msg; msg.set_tag(kSHLO); // Choose the latest version. - QuicTransportVersionVector supported_versions; - QuicTransportVersion version = AllSupportedTransportVersions().front(); + ParsedQuicVersionVector supported_versions; + ParsedQuicVersion version = AllSupportedVersions().front(); supported_versions.push_back(version); msg.SetVersionVector(kVER, supported_versions);
diff --git a/net/quic/core/crypto/quic_crypto_server_config.cc b/net/quic/core/crypto/quic_crypto_server_config.cc index a376ea9..31462de 100644 --- a/net/quic/core/crypto/quic_crypto_server_config.cc +++ b/net/quic/core/crypto/quic_crypto_server_config.cc
@@ -534,8 +534,8 @@ bool reject_only, QuicConnectionId connection_id, const QuicSocketAddress& client_address, - QuicTransportVersion version, - const QuicTransportVersionVector& supported_versions, + ParsedQuicVersion version, + const ParsedQuicVersionVector& supported_versions, bool use_stateless_rejects, QuicConnectionId server_designated_connection_id, const QuicClock* clock, @@ -594,8 +594,8 @@ const bool reject_only_; const QuicConnectionId connection_id_; const QuicSocketAddress client_address_; - const QuicTransportVersion version_; - const QuicTransportVersionVector supported_versions_; + const ParsedQuicVersion version_; + const ParsedQuicVersionVector supported_versions_; const bool use_stateless_rejects_; const QuicConnectionId server_designated_connection_id_; const QuicClock* const clock_; @@ -619,8 +619,8 @@ QuicConnectionId connection_id, const QuicSocketAddress& server_address, const QuicSocketAddress& client_address, - QuicTransportVersion version, - const QuicTransportVersionVector& supported_versions, + ParsedQuicVersion version, + const ParsedQuicVersionVector& supported_versions, bool use_stateless_rejects, QuicConnectionId server_designated_connection_id, const QuicClock* clock, @@ -708,9 +708,9 @@ compressed_certs_cache, params, signed_config, total_framing_overhead, chlo_packet_size, requested_config, primary_config, std::move(done_cb))); - proof_source_->GetProof(server_address, string(info.sni), - primary_config->serialized, version, chlo_hash, - std::move(cb)); + proof_source_->GetProof( + server_address, string(info.sni), primary_config->serialized, + version.transport_version, chlo_hash, std::move(cb)); helper.DetachCallback(); return; } @@ -732,8 +732,8 @@ bool reject_only, QuicConnectionId connection_id, const QuicSocketAddress& client_address, - QuicTransportVersion version, - const QuicTransportVersionVector& supported_versions, + ParsedQuicVersion version, + const ParsedQuicVersionVector& supported_versions, bool use_stateless_rejects, QuicConnectionId server_designated_connection_id, const QuicClock* clock, @@ -769,8 +769,9 @@ std::unique_ptr<CryptoHandshakeMessage> out(new CryptoHandshakeMessage); if (!info.reject_reasons.empty() || !requested_config.get()) { - BuildRejection(version, clock->WallNow(), *primary_config, client_hello, - info, validate_chlo_result.cached_network_params, + BuildRejection(version.transport_version, clock->WallNow(), *primary_config, + client_hello, info, + validate_chlo_result.cached_network_params, use_stateless_rejects, server_designated_connection_id, rand, compressed_certs_cache, params, *signed_config, total_framing_overhead, chlo_packet_size, out.get());
diff --git a/net/quic/core/crypto/quic_crypto_server_config.h b/net/quic/core/crypto/quic_crypto_server_config.h index 312f1377..9400a6d 100644 --- a/net/quic/core/crypto/quic_crypto_server_config.h +++ b/net/quic/core/crypto/quic_crypto_server_config.h
@@ -317,8 +317,8 @@ QuicConnectionId connection_id, const QuicSocketAddress& server_address, const QuicSocketAddress& client_address, - QuicTransportVersion version, - const QuicTransportVersionVector& supported_versions, + ParsedQuicVersion version, + const ParsedQuicVersionVector& supported_versions, bool use_stateless_rejects, QuicConnectionId server_designated_connection_id, const QuicClock* clock, @@ -534,8 +534,8 @@ bool reject_only, QuicConnectionId connection_id, const QuicSocketAddress& client_address, - QuicTransportVersion version, - const QuicTransportVersionVector& supported_versions, + ParsedQuicVersion version, + const ParsedQuicVersionVector& supported_versions, bool use_stateless_rejects, QuicConnectionId server_designated_connection_id, const QuicClock* clock,
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc index e6b032f..93d892f5 100644 --- a/net/quic/core/quic_connection.cc +++ b/net/quic/core/quic_connection.cc
@@ -316,10 +316,6 @@ received_stateless_reset_token_(0), last_control_frame_id_(kInvalidControlFrameId), is_path_degrading_(false), - negotiate_version_early_( - GetQuicReloadableFlag(quic_server_early_version_negotiation)), - always_discard_packets_after_close_( - GetQuicReloadableFlag(quic_always_discard_packets_after_close)), handle_write_results_for_connectivity_probe_(GetQuicReloadableFlag( quic_handle_write_results_for_connectivity_probe)), use_path_degrading_alarm_( @@ -693,10 +689,8 @@ return false; } - if (negotiate_version_early_ && - version_negotiation_state_ != NEGOTIATED_VERSION && + if (version_negotiation_state_ != NEGOTIATED_VERSION && perspective_ == Perspective::IS_SERVER) { - QUIC_FLAG_COUNT(quic_reloadable_flag_quic_server_early_version_negotiation); if (!header.version_flag) { // Packets should have the version flag till version negotiation is // done. @@ -1805,25 +1799,6 @@ if (debug_visitor_ != nullptr) { debug_visitor_->OnSuccessfulVersionNegotiation(version()); } - } else if (!negotiate_version_early_) { - if (!header.version_flag) { - // Packets should have the version flag till version negotiation is - // done. - QuicString error_details = - QuicStrCat(ENDPOINT, "Packet ", header.packet_number, - " without version flag before version negotiated."); - QUIC_DLOG(WARNING) << error_details; - CloseConnection(QUIC_INVALID_VERSION, error_details, - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - return false; - } else { - DCHECK_EQ(header.version, version()); - version_negotiation_state_ = NEGOTIATED_VERSION; - visitor_->OnSuccessfulVersionNegotiation(version()); - if (debug_visitor_ != nullptr) { - debug_visitor_->OnSuccessfulVersionNegotiation(version()); - } - } } } @@ -1990,9 +1965,7 @@ } bool QuicConnection::WritePacket(SerializedPacket* packet) { - if (always_discard_packets_after_close_ && ShouldDiscardPacket(*packet)) { - QUIC_FLAG_COUNT_N( - quic_reloadable_flag_quic_always_discard_packets_after_close, 1, 2); + if (ShouldDiscardPacket(*packet)) { ++stats_.packets_discarded; return true; } @@ -2006,10 +1979,6 @@ RecordInternalErrorLocation(QUIC_CONNECTION_WRITE_PACKET); return true; } - if (!always_discard_packets_after_close_ && ShouldDiscardPacket(*packet)) { - ++stats_.packets_discarded; - return true; - } // Termination packets are encrypted and saved, so don't exit early. const bool is_termination_packet = IsTerminationPacket(*packet); if (writer_->IsWriteBlocked() && !is_termination_packet) { @@ -2863,9 +2832,7 @@ QuicPacketWriter* probing_writer, const QuicSocketAddress& peer_address) { DCHECK(peer_address.IsInitialized()); - if (always_discard_packets_after_close_ && !connected_) { - QUIC_FLAG_COUNT_N( - quic_reloadable_flag_quic_always_discard_packets_after_close, 2, 2); + if (!connected_) { QUIC_BUG << "Not sending connectivity probing packet as connection is " << "disconnected."; return false;
diff --git a/net/quic/core/quic_connection.h b/net/quic/core/quic_connection.h index b670be5..e01aa5d3 100644 --- a/net/quic/core/quic_connection.h +++ b/net/quic/core/quic_connection.h
@@ -1309,13 +1309,6 @@ // True if the peer is unreachable on the current path. bool is_path_degrading_; - // Latched value of - // quic_reloadable_flag_quic_server_early_version_negotiation. - const bool negotiate_version_early_; - - // Latched value of - // quic_reloadable_flag_quic_always_discard_packets_after_close. - const bool always_discard_packets_after_close_; // Latched valure of // quic_reloadable_flag_quic_handle_write_results_for_connectivity_probe. const bool handle_write_results_for_connectivity_probe_;
diff --git a/net/quic/core/quic_connection_test.cc b/net/quic/core/quic_connection_test.cc index 568a3bb..a77c925e 100644 --- a/net/quic/core/quic_connection_test.cc +++ b/net/quic/core/quic_connection_test.cc
@@ -1573,14 +1573,9 @@ EXPECT_FALSE(connection_.connected()); EXPECT_EQ(1u, connection_.NumQueuedPackets()); - if (GetQuicReloadableFlag(quic_always_discard_packets_after_close)) { - EXPECT_EQ(0u, connection_.GetStats().packets_discarded); - connection_.OnCanWrite(); - EXPECT_EQ(1u, connection_.GetStats().packets_discarded); - } else { - EXPECT_QUIC_BUG(connection_.OnCanWrite(), - "Attempt to write packet:1 after:2"); - } + EXPECT_EQ(0u, connection_.GetStats().packets_discarded); + connection_.OnCanWrite(); + EXPECT_EQ(1u, connection_.GetStats().packets_discarded); } TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) { @@ -5414,20 +5409,12 @@ EXPECT_FALSE(connection_.connected()); EXPECT_FALSE(connection_.CanWriteStreamData()); - int num_packets_sent = - GetQuicReloadableFlag(quic_always_discard_packets_after_close) ? 0 : 1; - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)) - .Times(num_packets_sent); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0); - if (GetQuicReloadableFlag(quic_always_discard_packets_after_close)) { - EXPECT_QUIC_BUG(connection_.SendConnectivityProbingPacket( - writer_.get(), connection_.peer_address()), - "Not sending connectivity probing packet as connection is " - "disconnected."); - } else { - connection_.SendConnectivityProbingPacket(writer_.get(), - connection_.peer_address()); - } + EXPECT_QUIC_BUG(connection_.SendConnectivityProbingPacket( + writer_.get(), connection_.peer_address()), + "Not sending connectivity probing packet as connection is " + "disconnected."); } TEST_P(QuicConnectionTest, WriteBlockedAfterClientSendsConnectivityProbe) {
diff --git a/net/quic/core/quic_crypto_client_handshaker.cc b/net/quic/core/quic_crypto_client_handshaker.cc index 32a17d7..5737a7c61 100644 --- a/net/quic/core/quic_crypto_client_handshaker.cc +++ b/net/quic/core/quic_crypto_client_handshaker.cc
@@ -318,8 +318,7 @@ if (!cached->IsComplete(session()->connection()->clock()->WallNow())) { crypto_config_->FillInchoateClientHello( - server_id_, - session()->connection()->supported_versions().front().transport_version, + server_id_, session()->connection()->supported_versions().front(), cached, session()->connection()->random_generator(), /* demand_x509_proof= */ true, crypto_negotiated_params_, &out); // Pad the inchoate client hello to fill up a packet. @@ -363,8 +362,8 @@ QuicString error_details; QuicErrorCode error = crypto_config_->FillClientHello( server_id_, session()->connection()->connection_id(), - session()->connection()->supported_versions().front().transport_version, - cached, session()->connection()->clock()->WallNow(), + session()->connection()->supported_versions().front(), cached, + session()->connection()->clock()->WallNow(), session()->connection()->random_generator(), channel_id_key_.get(), crypto_negotiated_params_, &out, &error_details); if (error != QUIC_NO_ERROR) { @@ -621,10 +620,9 @@ QuicString error_details; QuicErrorCode error = crypto_config_->ProcessServerHello( *in, session()->connection()->connection_id(), - session()->connection()->transport_version(), - ParsedVersionsToTransportVersions( - session()->connection()->server_supported_versions()), - cached, crypto_negotiated_params_, &error_details); + session()->connection()->version(), + session()->connection()->server_supported_versions(), cached, + crypto_negotiated_params_, &error_details); if (error != QUIC_NO_ERROR) { stream_->CloseConnectionWithDetails(
diff --git a/net/quic/core/quic_crypto_client_stream_test.cc b/net/quic/core/quic_crypto_client_stream_test.cc index 7ef81c5..0ec9ba3 100644 --- a/net/quic/core/quic_crypto_client_stream_test.cc +++ b/net/quic/core/quic_crypto_client_stream_test.cc
@@ -409,7 +409,7 @@ void AdvanceHandshakeWithFakeServer() { client_session_->GetMutableCryptoStream()->CryptoConnect(); - EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _)) + EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _)) .Times(testing::AnyNumber()); EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_)) .Times(testing::AnyNumber());
diff --git a/net/quic/core/quic_crypto_server_handshaker.cc b/net/quic/core/quic_crypto_server_handshaker.cc index febd64b..e1827f7c 100644 --- a/net/quic/core/quic_crypto_server_handshaker.cc +++ b/net/quic/core/quic_crypto_server_handshaker.cc
@@ -398,7 +398,8 @@ const CryptoHandshakeMessage& message = result->client_hello; QuicString error_details; if (!helper_->CanAcceptClientHello( - message, session()->connection()->self_address(), &error_details)) { + message, GetClientAddress(), session()->connection()->peer_address(), + session()->connection()->self_address(), &error_details)) { done_cb->Run(QUIC_HANDSHAKE_FAILED, error_details, nullptr, nullptr, nullptr); return; @@ -428,11 +429,11 @@ GenerateConnectionIdForReject(use_stateless_rejects_in_crypto_config); crypto_config_->ProcessClientHello( result, /*reject_only=*/false, connection->connection_id(), - connection->self_address(), GetClientAddress(), transport_version(), - ParsedVersionsToTransportVersions(connection->supported_versions()), - use_stateless_rejects_in_crypto_config, server_designated_connection_id, - connection->clock(), connection->random_generator(), - compressed_certs_cache_, crypto_negotiated_params_, signed_config_, + connection->self_address(), GetClientAddress(), connection->version(), + connection->supported_versions(), use_stateless_rejects_in_crypto_config, + server_designated_connection_id, connection->clock(), + connection->random_generator(), compressed_certs_cache_, + crypto_negotiated_params_, signed_config_, QuicCryptoStream::CryptoMessageFramingOverhead(transport_version()), chlo_packet_size_, std::move(done_cb)); }
diff --git a/net/quic/core/quic_crypto_server_stream.h b/net/quic/core/quic_crypto_server_stream.h index 98d7d34..6b9ec15 100644 --- a/net/quic/core/quic_crypto_server_stream.h +++ b/net/quic/core/quic_crypto_server_stream.h
@@ -147,6 +147,8 @@ // acceptable according to the visitor's policy. Otherwise, returns false // and populates |error_details|. virtual bool CanAcceptClientHello(const CryptoHandshakeMessage& message, + const QuicSocketAddress& client_address, + const QuicSocketAddress& peer_address, const QuicSocketAddress& self_address, QuicString* error_details) const = 0; };
diff --git a/net/quic/core/quic_crypto_server_stream_test.cc b/net/quic/core/quic_crypto_server_stream_test.cc index c1a1f45..22e9d66 100644 --- a/net/quic/core/quic_crypto_server_stream_test.cc +++ b/net/quic/core/quic_crypto_server_stream_test.cc
@@ -103,7 +103,7 @@ &server_connection_, &server_session); CHECK(server_session); server_session_.reset(server_session); - EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _)) + EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _)) .Times(testing::AnyNumber()); EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_)) .Times(testing::AnyNumber()); @@ -390,7 +390,7 @@ Initialize(); InitializeFakeClient(/* supports_stateless_rejects= */ false); - EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _)) + EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _)) .WillOnce(testing::Return(false)); EXPECT_CALL(*server_connection_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _)); @@ -534,7 +534,7 @@ Initialize(); InitializeFakeClient(/* supports_stateless_rejects= */ false); - EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _)) + EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _)) .WillOnce(testing::Return(true)); EXPECT_CALL(*server_connection_, CloseConnection(QUIC_HANDSHAKE_FAILED, "Failed to get proof", _)); @@ -570,7 +570,7 @@ TEST_P(QuicCryptoServerStreamTestWithFakeProofSource, MultipleChlo) { Initialize(); GetFakeProofSource()->Activate(); - EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _)) + EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _)) .WillOnce(testing::Return(true)); // Create a minimal CHLO
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h index 3da4a0c0..8098745 100644 --- a/net/quic/core/quic_flags_list.h +++ b/net/quic/core/quic_flags_list.h
@@ -60,9 +60,6 @@ // Congestion window gain for QUIC BBR during PROBE_BW phase. QUIC_FLAG(double, FLAGS_quic_bbr_cwnd_gain, 2.0f) -// Add the equivalent number of bytes as 3 TCP TSO segments to QUIC's BBR CWND. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd, false) - // Simplify QUIC\'s adaptive time loss detection to measure the necessary // reordering window for every spurious retransmit. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_adaptive_time_loss, false) @@ -141,10 +138,6 @@ FLAGS_quic_reloadable_flag_quic_fast_path_on_stream_data_acked, true) -// If true, QUIC streams are registered in the QuicStream constructor instead -// of in the QuicSpdyStream constructor. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_register_streams_early2, true) - // If this flag and // FLAGS_quic_reloadable_flag_quic_fix_write_out_of_order_queued_packet_crash // are both ture, QUIC will clear queued packets before sending connectivity @@ -154,19 +147,6 @@ FLAGS_quic_reloadable_flag_quic_clear_queued_packets_before_sending_connectivity_probing, false) -// When true, this flag has QuicConnection call -// QuicConnectionVisitorInterface::OnSuccessfulVersionNegotiation earlier when -// processing the packet header. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_server_early_version_negotiation, - true) - -// If true, QUIC will always discard outgoing packets after connection close. -// Currently out-of-order outgoing packets are not discarded -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_always_discard_packets_after_close, - true) - // If true, when a stream is reset by peer with error, it should not be added to // zombie streams. QUIC_FLAG(bool, @@ -189,11 +169,6 @@ // replace it with a static streams map. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_register_static_streams, true) -// Base the QUIC crypto retransmission timer on the last sent crypto packet. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_better_crypto_retransmission, - true) - // If true, enable server proxy support in QUIC. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_server_proxy2, false) @@ -250,3 +225,24 @@ bool, FLAGS_quic_reloadable_flag_quic_early_retransmit_detects_in_flight_packet_lost, false) + +// Enables the 1RTO connection option which only sends one packet on QUIC +// retransmission timeout, instead of 2. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_one_rto, false) + +// Modify QuicVersionManager so that the QuicTransportVersionVector returned by +// GetSupportedTransportVersions contains a unique list of entries. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_version_manager_dedupe_transport_versions, + false) + +// When true, the NRTT QUIC connection option causes receivers to ignore +// incoming initial RTT values. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_no_irtt, false) + +// Fixed QUIC's PROBE_BW logic to exit low gain mode based on bytes_in_flight, +// not prior_in_flight. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_fix_probe_bw, false) + +// If true, changes when the dispatcher changes internal state. +QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_enable_l1_munge, false)
diff --git a/net/quic/core/quic_sent_packet_manager.cc b/net/quic/core/quic_sent_packet_manager.cc index 5539f37e..9fb7a2263 100644 --- a/net/quic/core/quic_sent_packet_manager.cc +++ b/net/quic/core/quic_sent_packet_manager.cc
@@ -75,6 +75,7 @@ consecutive_crypto_retransmission_count_(0), pending_timer_transmission_count_(0), max_tail_loss_probes_(kDefaultMaxTailLossProbes), + max_rto_packets_(kMaxRetransmissionsOnTimeout), enable_half_rtt_tail_loss_probe_(false), using_pacing_(false), use_new_rto_(false), @@ -94,10 +95,7 @@ rtt_updated_(false), acked_packets_iter_(last_ack_frame_.packets.rbegin()), use_path_degrading_alarm_( - GetQuicReloadableFlag(quic_path_degrading_alarm2)), - use_better_crypto_retransmission_( - GetQuicReloadableFlag(quic_better_crypto_retransmission)) { - QUIC_FLAG_COUNT(quic_reloadable_flag_quic_better_crypto_retransmission); + GetQuicReloadableFlag(quic_path_degrading_alarm2)) { SetSendAlgorithm(congestion_control_type); } @@ -106,8 +104,13 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) { if (config.HasReceivedInitialRoundTripTimeUs() && config.ReceivedInitialRoundTripTimeUs() > 0) { - SetInitialRtt(QuicTime::Delta::FromMicroseconds( - config.ReceivedInitialRoundTripTimeUs())); + if (GetQuicReloadableFlag(quic_no_irtt) && + config.HasClientSentConnectionOption(kNRTT, perspective_)) { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_no_irtt); + } else { + SetInitialRtt(QuicTime::Delta::FromMicroseconds( + config.ReceivedInitialRoundTripTimeUs())); + } } else if (config.HasInitialRoundTripTimeUsToSend() && config.GetInitialRoundTripTimeUsToSend() > 0) { SetInitialRtt(QuicTime::Delta::FromMicroseconds( @@ -195,6 +198,11 @@ QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_one_tlp, 1, 2); max_tail_loss_probes_ = 1; } + if (GetQuicReloadableFlag(quic_one_rto) && + config.HasClientSentConnectionOption(k1RTO, perspective_)) { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_one_rto); + max_rto_packets_ = 1; + } if (config.HasClientSentConnectionOption(kTLPR, perspective_)) { enable_half_rtt_tail_loss_probe_ = true; } @@ -768,7 +776,7 @@ it != unacked_packets_.end(); ++it, ++packet_number) { if ((!session_decides_what_to_write() || it->state == OUTSTANDING) && unacked_packets_.HasRetransmittableFrames(*it) && - pending_timer_transmission_count_ < kMaxRetransmissionsOnTimeout) { + pending_timer_transmission_count_ < max_rto_packets_) { if (session_decides_what_to_write()) { retransmissions.push_back(packet_number); } else { @@ -913,11 +921,8 @@ } switch (GetRetransmissionMode()) { case HANDSHAKE_MODE: - if (use_better_crypto_retransmission_) { - return unacked_packets_.GetLastCryptoPacketSentTime() + - GetCryptoRetransmissionDelay(); - } - return clock_->ApproximateNow() + GetCryptoRetransmissionDelay(); + return unacked_packets_.GetLastCryptoPacketSentTime() + + GetCryptoRetransmissionDelay(); case LOSS_MODE: return loss_algorithm_->GetLossTimeout(); case TLP_MODE: {
diff --git a/net/quic/core/quic_sent_packet_manager.h b/net/quic/core/quic_sent_packet_manager.h index 6c44610..d1b8b2ac 100644 --- a/net/quic/core/quic_sent_packet_manager.h +++ b/net/quic/core/quic_sent_packet_manager.h
@@ -449,6 +449,8 @@ size_t pending_timer_transmission_count_; // Maximum number of tail loss probes to send before firing an RTO. size_t max_tail_loss_probes_; + // Maximum number of packets to send upon RTO. + QuicPacketCount max_rto_packets_; // If true, send the TLP at 0.5 RTT. bool enable_half_rtt_tail_loss_probe_; bool using_pacing_; @@ -517,10 +519,6 @@ // quic_reloadable_flag_quic_path_degrading_alarm const bool use_path_degrading_alarm_; - // Latched value of - // quic_reloadable_flag_quic_better_crypto_retransmission - const bool use_better_crypto_retransmission_; - DISALLOW_COPY_AND_ASSIGN(QuicSentPacketManager); };
diff --git a/net/quic/core/quic_sent_packet_manager_test.cc b/net/quic/core/quic_sent_packet_manager_test.cc index 04330445..a19e434 100644 --- a/net/quic/core/quic_sent_packet_manager_test.cc +++ b/net/quic/core/quic_sent_packet_manager_test.cc
@@ -1445,10 +1445,11 @@ EXPECT_EQ(102 * kDefaultLength, QuicSentPacketManagerPeer::GetBytesInFlight(&manager_)); } else { - EXPECT_TRUE(manager_.HasPendingRetransmissions()); + ASSERT_TRUE(manager_.HasPendingRetransmissions()); EXPECT_EQ(100 * kDefaultLength, QuicSentPacketManagerPeer::GetBytesInFlight(&manager_)); RetransmitNextPacket(101); + ASSERT_TRUE(manager_.HasPendingRetransmissions()); RetransmitNextPacket(102); EXPECT_FALSE(manager_.HasPendingRetransmissions()); } @@ -1490,6 +1491,53 @@ } } +TEST_P(QuicSentPacketManagerTest, RetransmissionTimeoutOnePacket) { + SetQuicReloadableFlag(quic_one_rto, true); + // Set the 1RTO connection option. + QuicConfig client_config; + QuicTagVector options; + options.push_back(k1RTO); + QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); + client_config.SetConnectionOptionsToSend(options); + EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + EXPECT_CALL(*send_algorithm_, PacingRate(_)) + .WillRepeatedly(Return(QuicBandwidth::Zero())); + EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) + .WillRepeatedly(Return(10 * kDefaultTCPMSS)); + manager_.SetFromConfig(client_config); + EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true)); + + StrictMock<MockDebugDelegate> debug_delegate; + manager_.SetDebugDelegate(&debug_delegate); + + // Send 100 packets. + const size_t kNumSentPackets = 100; + for (size_t i = 1; i <= kNumSentPackets; ++i) { + SendDataPacket(i); + } + + EXPECT_FALSE(manager_.MaybeRetransmitTailLossProbe()); + if (manager_.session_decides_what_to_write()) { + EXPECT_CALL(notifier_, RetransmitFrames(_, _)) + .Times(1) + .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { + RetransmitDataPacket(101, type); + }))); + } + manager_.OnRetransmissionTimeout(); + if (manager_.session_decides_what_to_write()) { + EXPECT_EQ(101 * kDefaultLength, + QuicSentPacketManagerPeer::GetBytesInFlight(&manager_)); + } else { + ASSERT_TRUE(manager_.HasPendingRetransmissions()); + EXPECT_EQ(100 * kDefaultLength, + QuicSentPacketManagerPeer::GetBytesInFlight(&manager_)); + RetransmitNextPacket(101); + EXPECT_FALSE(manager_.HasPendingRetransmissions()); + } +} + TEST_P(QuicSentPacketManagerTest, NewRetransmissionTimeout) { QuicConfig client_config; QuicTagVector options; @@ -1748,11 +1796,7 @@ } // The retransmission time should now be twice as far in the future. - if (GetQuicReloadableFlag(quic_better_crypto_retransmission)) { - expected_time = crypto_packet_send_time + srtt * 2 * 1.5; - } else { - expected_time = clock_.Now() + srtt * 2 * 1.5; - } + expected_time = crypto_packet_send_time + srtt * 2 * 1.5; EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); } @@ -1800,11 +1844,7 @@ } // The retransmission time should now be twice as far in the future. - if (GetQuicReloadableFlag(quic_better_crypto_retransmission)) { - expected_time = crypto_packet_send_time + srtt * 2 * 2; - } else { - expected_time = clock_.Now() + srtt * 2 * 2; - } + expected_time = crypto_packet_send_time + srtt * 2 * 2; EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); }
diff --git a/net/quic/core/quic_server_session_base_test.cc b/net/quic/core/quic_server_session_base_test.cc index 3b3e309..2bd1a42 100644 --- a/net/quic/core/quic_server_session_base_test.cc +++ b/net/quic/core/quic_server_session_base_test.cc
@@ -405,8 +405,7 @@ const QuicString serving_region = "not a real region"; session_->set_serving_region(serving_region); - if (GetQuicReloadableFlag(quic_register_streams_early2) && - GetQuicReloadableFlag(quic_register_static_streams)) { + if (GetQuicReloadableFlag(quic_register_static_streams)) { session_->UnregisterStreamPriority(kHeadersStreamId, /*is_static=*/true); } QuicServerSessionBasePeer::SetCryptoStream(session_.get(), nullptr); @@ -414,8 +413,7 @@ new MockQuicCryptoServerStream(&crypto_config_, &compressed_certs_cache_, session_.get(), &stream_helper_); QuicServerSessionBasePeer::SetCryptoStream(session_.get(), crypto_stream); - if (GetQuicReloadableFlag(quic_register_streams_early2) && - GetQuicReloadableFlag(quic_register_static_streams)) { + if (GetQuicReloadableFlag(quic_register_static_streams)) { session_->RegisterStreamPriority(kHeadersStreamId, /*is_static=*/true, QuicStream::kDefaultPriority); } @@ -497,6 +495,12 @@ } TEST_P(QuicServerSessionBaseTest, BandwidthResumptionExperiment) { + if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) { + // This test relies on resumption, which is not currently supported by the + // TLS handshake. + // TODO(nharper): Add support for resumption to the TLS handshake. + return; + } // Test that if a client provides a CachedNetworkParameters with the same // serving region as the current server, and which was made within an hour of // now, that this data is passed down to the send algorithm. @@ -592,6 +596,12 @@ // ProofSource::GetProof. Delay the completion of the operation until after the // stream has been destroyed, and verify that there are no memory bugs. TEST_P(StreamMemberLifetimeTest, Basic) { + if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) { + // This test depends on the QUIC crypto protocol, so it is disabled for the + // TLS handshake. + // TODO(nharper): Fix this test so it doesn't rely on QUIC crypto. + return; + } SetQuicReloadableFlag(enable_quic_stateless_reject_support, true); SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, true); @@ -609,7 +619,7 @@ PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, &packet_version_list)); - EXPECT_CALL(stream_helper_, CanAcceptClientHello(_, _, _)) + EXPECT_CALL(stream_helper_, CanAcceptClientHello(_, _, _, _, _)) .WillOnce(testing::Return(true)); EXPECT_CALL(stream_helper_, GenerateConnectionIdForReject(_)) .WillOnce(testing::Return(12345));
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc index 694f415..a38e1185 100644 --- a/net/quic/core/quic_session.cc +++ b/net/quic/core/quic_session.cc
@@ -37,11 +37,8 @@ const QuicConfig& config) : connection_(connection), visitor_(owner), - register_streams_early_( - GetQuicReloadableFlag(quic_register_streams_early2)), write_blocked_streams_( - GetQuicReloadableFlag(quic_register_static_streams) && - register_streams_early_), + GetQuicReloadableFlag(quic_register_static_streams)), config_(config), max_open_outgoing_streams_(kDefaultMaxStreamsPerConnection), max_open_incoming_streams_(config_.GetMaxIncomingDynamicStreamsToSend()), @@ -63,11 +60,7 @@ currently_writing_stream_id_(0), goaway_sent_(false), goaway_received_(false), - control_frame_manager_(this) { - if (register_streams_early()) { - QUIC_FLAG_COUNT(quic_reloadable_flag_quic_register_streams_early2); - } -} + control_frame_manager_(this) {} void QuicSession::Initialize() { connection_->set_visitor(this); @@ -749,13 +742,9 @@ void QuicSession::RegisterStreamPriority(QuicStreamId id, bool is_static, SpdyPriority priority) { - // Static streams should not be registered unless register_streams_early - // is true. - DCHECK(register_streams_early() || !is_static); // Static streams do not need to be registered with the write blocked list, // since it has special handling for them. - if (!write_blocked_streams()->register_static_streams() && - register_streams_early() && is_static) { + if (!write_blocked_streams()->register_static_streams() && is_static) { return; } @@ -763,13 +752,9 @@ } void QuicSession::UnregisterStreamPriority(QuicStreamId id, bool is_static) { - // Static streams should not be registered unless register_streams_early - // is true. - DCHECK(register_streams_early() || !is_static); // Static streams do not need to be registered with the write blocked list, // since it has special handling for them. - if (!write_blocked_streams()->register_static_streams() && - register_streams_early() && is_static) { + if (!write_blocked_streams()->register_static_streams() && is_static) { return; } write_blocked_streams()->UnregisterStream(id, is_static);
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h index c853834d..35d9194 100644 --- a/net/quic/core/quic_session.h +++ b/net/quic/core/quic_session.h
@@ -308,8 +308,6 @@ // Set transmission type of next sending packets. void SetTransmissionType(TransmissionType type); - bool register_streams_early() const { return register_streams_early_; } - bool session_decides_what_to_write() const; protected: @@ -478,9 +476,6 @@ // May be null. Visitor* visitor_; - // Latched value of quic_reloadable_flag_quic_register_streams_early2. - const bool register_streams_early_; - // A list of streams which need to write more data. Stream register // themselves in their constructor, and unregisterm themselves in their // destructors, so the write blocked list must outlive all streams.
diff --git a/net/quic/core/quic_session_test.cc b/net/quic/core/quic_session_test.cc index 719b10e6..19ed1f31 100644 --- a/net/quic/core/quic_session_test.cc +++ b/net/quic/core/quic_session_test.cc
@@ -108,17 +108,7 @@ class TestStream : public QuicStream { public: TestStream(QuicStreamId id, QuicSession* session) - : QuicStream(id, session, /*is_static=*/false) { - if (!session->register_streams_early()) { - session->RegisterStreamPriority(id, false, QuicStream::kDefaultPriority); - } - } - - ~TestStream() override { - if (!session()->register_streams_early()) { - session()->UnregisterStreamPriority(id(), false); - } - } + : QuicStream(id, session, /*is_static=*/false) {} using QuicStream::CloseWriteSide;
diff --git a/net/quic/core/quic_spdy_stream.cc b/net/quic/core/quic_spdy_stream.cc index 4fa1d8b0..aba21f7a 100644 --- a/net/quic/core/quic_spdy_stream.cc +++ b/net/quic/core/quic_spdy_stream.cc
@@ -36,17 +36,9 @@ // Don't receive any callbacks from the sequencer until headers // are complete. sequencer()->SetBlockedUntilFlush(); - if (!session()->register_streams_early()) { - spdy_session_->RegisterStreamPriority(id, /*is_static=*/false, priority()); - } } -QuicSpdyStream::~QuicSpdyStream() { - if (spdy_session_ != nullptr && !session()->register_streams_early()) { - spdy_session_->UnregisterStreamPriority(id(), - /*is_static=*/false); - } -} +QuicSpdyStream::~QuicSpdyStream() {} size_t QuicSpdyStream::WriteHeaders( SpdyHeaderBlock header_block,
diff --git a/net/quic/core/quic_stream.cc b/net/quic/core/quic_stream.cc index 72e1567..0cefab11 100644 --- a/net/quic/core/quic_stream.cc +++ b/net/quic/core/quic_stream.cc
@@ -81,9 +81,7 @@ buffered_data_threshold_(GetQuicFlag(FLAGS_quic_buffered_data_threshold)), is_static_(is_static) { SetFromConfig(); - if (session_->register_streams_early()) { - session_->RegisterStreamPriority(id, is_static_, priority_); - } + session_->RegisterStreamPriority(id, is_static_, priority_); } QuicStream::~QuicStream() { @@ -94,7 +92,7 @@ << send_buffer_.stream_bytes_outstanding() << ", fin_outstanding: " << fin_outstanding_; } - if (session_ != nullptr && session_->register_streams_early()) { + if (session_ != nullptr) { session_->UnregisterStreamPriority(id(), is_static_); } }
diff --git a/net/quic/core/quic_stream_test.cc b/net/quic/core/quic_stream_test.cc index 7b7d1a5..58098dd 100644 --- a/net/quic/core/quic_stream_test.cc +++ b/net/quic/core/quic_stream_test.cc
@@ -123,11 +123,6 @@ .Times(AnyNumber()); write_blocked_list_ = QuicSessionPeer::GetWriteBlockedStreams(session_.get()); - if (!session_->register_streams_early()) { - write_blocked_list_->RegisterStream(kTestStreamId, - /*is_static_stream=*/false, - kV3HighestPriority); - } } bool fin_sent() { return QuicStreamPeer::FinSent(stream_); }
diff --git a/net/quic/core/quic_version_manager.cc b/net/quic/core/quic_version_manager.cc index e38aad5..b69b15b 100644 --- a/net/quic/core/quic_version_manager.cc +++ b/net/quic/core/quic_version_manager.cc
@@ -5,8 +5,11 @@ #include "net/quic/core/quic_version_manager.h" #include "net/quic/core/quic_versions.h" +#include "net/quic/platform/api/quic_flag_utils.h" #include "net/quic/platform/api/quic_flags.h" +#include <algorithm> + namespace net { QuicVersionManager::QuicVersionManager( @@ -56,8 +59,17 @@ FilterSupportedVersions(allowed_supported_versions_); filtered_transport_versions_.clear(); for (ParsedQuicVersion version : filtered_supported_versions_) { - filtered_transport_versions_.push_back(version.transport_version); + auto transport_version = version.transport_version; + if (!GetQuicReloadableFlag( + quic_version_manager_dedupe_transport_versions) || + std::find(filtered_transport_versions_.begin(), + filtered_transport_versions_.end(), + transport_version) == filtered_transport_versions_.end()) { + filtered_transport_versions_.push_back(transport_version); + } } + QUIC_FLAG_COUNT( + quic_reloadable_flag_quic_version_manager_dedupe_transport_versions); } } // namespace net
diff --git a/net/quic/quartc/quartc_factory.cc b/net/quic/quartc/quartc_factory.cc index 41063ec9a..c33d108f 100644 --- a/net/quic/quartc/quartc_factory.cc +++ b/net/quic/quartc/quartc_factory.cc
@@ -106,7 +106,6 @@ std::unique_ptr<QuartcSessionInterface> QuartcFactory::CreateQuartcSession( const QuartcSessionConfig& quartc_session_config) { DCHECK(quartc_session_config.packet_transport); - SetQuicReloadableFlag(quic_better_crypto_retransmission, true); SetQuicReloadableFlag(quic_is_write_blocked, true); Perspective perspective = quartc_session_config.is_server
diff --git a/net/quic/quartc/quartc_session.cc b/net/quic/quartc/quartc_session.cc index 7d12b46f..a2c0da4 100644 --- a/net/quic/quartc/quartc_session.cc +++ b/net/quic/quartc/quartc_session.cc
@@ -107,6 +107,8 @@ bool QuartcCryptoServerStreamHelper::CanAcceptClientHello( const CryptoHandshakeMessage& message, + const QuicSocketAddress& client_address, + const QuicSocketAddress& peer_address, const QuicSocketAddress& self_address, string* error_details) const { return true; @@ -237,9 +239,6 @@ // QuicStream::OnClose), the stream is already closed so return. return; } - if (!register_streams_early()) { - write_blocked_streams()->UnregisterStream(stream_id, /*is_static=*/false); - } QuicSession::CloseStream(stream_id); } @@ -423,12 +422,7 @@ // Register the stream to the QuicWriteBlockedList. |priority| is clamped // between 0 and 7, with 0 being the highest priority and 7 the lowest // priority. - if (!register_streams_early()) { - write_blocked_streams()->RegisterStream( - stream->id(), /* is_static_stream= */ false, priority); - } else { - write_blocked_streams()->UpdateStreamPriority(stream->id(), priority); - } + write_blocked_streams()->UpdateStreamPriority(stream->id(), priority); if (IsIncomingStream(id)) { DCHECK(session_delegate_);
diff --git a/net/quic/quartc/quartc_session.h b/net/quic/quartc/quartc_session.h index fdfa7b75..16d8b57 100644 --- a/net/quic/quartc/quartc_session.h +++ b/net/quic/quartc/quartc_session.h
@@ -24,6 +24,8 @@ QuicConnectionId connection_id) const override; bool CanAcceptClientHello(const CryptoHandshakeMessage& message, + const QuicSocketAddress& client_address, + const QuicSocketAddress& peer_address, const QuicSocketAddress& self_address, std::string* error_details) const override; };
diff --git a/net/quic/quartc/quartc_stream_test.cc b/net/quic/quartc/quartc_stream_test.cc index d5e7d93..37806e08 100644 --- a/net/quic/quartc/quartc_stream_test.cc +++ b/net/quic/quartc/quartc_stream_test.cc
@@ -180,10 +180,6 @@ QuicMakeUnique<MockQuartcStreamDelegate>(kStreamId, &read_buffer_); stream_ = new QuartcStream(kStreamId, session_.get()); stream_->SetDelegate(mock_stream_delegate_.get()); - if (!session_->register_streams_early()) { - session_->RegisterReliableStream(stream_->stream_id(), - QuicStream::kDefaultPriority); - } session_->ActivateReliableStream(std::unique_ptr<QuartcStream>(stream_)); }
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc index e451532f..34d0931 100644 --- a/net/quic/test_tools/crypto_test_utils.cc +++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -311,8 +311,7 @@ result_ = result; crypto_config_->ProcessClientHello( result_, /*reject_only=*/false, /*connection_id=*/1, server_addr_, - client_addr_, AllSupportedTransportVersions().front(), - AllSupportedTransportVersions(), + client_addr_, AllSupportedVersions().front(), AllSupportedVersions(), /*use_stateless_rejects=*/true, /*server_designated_connection_id=*/0, clock_, QuicRandom::GetInstance(), compressed_certs_cache_, params_, signed_config_, /*total_framing_overhead=*/50, kDefaultMaxPacketSize, @@ -406,7 +405,8 @@ server_session.OnSuccessfulVersionNegotiation( client_conn->supported_versions().front()); EXPECT_CALL(*server_session.helper(), - CanAcceptClientHello(testing::_, testing::_, testing::_)) + CanAcceptClientHello(testing::_, testing::_, testing::_, + testing::_, testing::_)) .Times(testing::AnyNumber()); EXPECT_CALL(*server_session.helper(), GenerateConnectionIdForReject(testing::_))
diff --git a/net/quic/test_tools/crypto_test_utils_test.cc b/net/quic/test_tools/crypto_test_utils_test.cc index 315b7b66..8ddaf432 100644 --- a/net/quic/test_tools/crypto_test_utils_test.cc +++ b/net/quic/test_tools/crypto_test_utils_test.cc
@@ -61,8 +61,7 @@ result_ = result; crypto_config_->ProcessClientHello( result_, /*reject_only=*/false, /*connection_id=*/1, server_addr_, - client_addr_, AllSupportedTransportVersions().front(), - AllSupportedTransportVersions(), + client_addr_, AllSupportedVersions().front(), AllSupportedVersions(), /*use_stateless_rejects=*/true, /*server_designated_connection_id=*/0, clock_, QuicRandom::GetInstance(), compressed_certs_cache_, params_, signed_config_, /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc index 4a7a0dd..07fa8e58 100644 --- a/net/quic/test_tools/quic_test_utils.cc +++ b/net/quic/test_tools/quic_test_utils.cc
@@ -505,7 +505,7 @@ ON_CALL(helper_, GenerateConnectionIdForReject(_)) .WillByDefault( testing::Return(connection->random_generator()->RandUint64())); - ON_CALL(helper_, CanAcceptClientHello(_, _, _)) + ON_CALL(helper_, CanAcceptClientHello(_, _, _, _, _)) .WillByDefault(testing::Return(true)); }
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index a6f7ab9..1095fb1 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc
@@ -610,12 +610,7 @@ bool support_server_push_; }; -class EndToEndTestWithTls : public EndToEndTest { - protected: - EndToEndTestWithTls() : EndToEndTest() { - SetQuicReloadableFlag(quic_server_early_version_negotiation, true); - } -}; +class EndToEndTestWithTls : public EndToEndTest {}; // Run all end to end tests with all supported versions. INSTANTIATE_TEST_CASE_P(EndToEndTests, @@ -1391,6 +1386,36 @@ server_thread_->Resume(); } +TEST_P(EndToEndTest, ClientSuggestsIgnoredRTT) { + SetQuicReloadableFlag(quic_no_irtt, true); + // Client suggests initial RTT, but also specifies NRTT, so it's not used. + const QuicTime::Delta kInitialRTT = QuicTime::Delta::FromMicroseconds(20000); + client_config_.SetInitialRoundTripTimeUsToSend(kInitialRTT.ToMicroseconds()); + QuicTagVector options; + options.push_back(kNRTT); + client_config_.SetConnectionOptionsToSend(options); + + ASSERT_TRUE(Initialize()); + EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); + server_thread_->WaitForCryptoHandshakeConfirmed(); + + // Pause the server so we can access the server's internals without races. + server_thread_->Pause(); + QuicDispatcher* dispatcher = + QuicServerPeer::GetDispatcher(server_thread_->server()); + ASSERT_EQ(1u, dispatcher->session_map().size()); + const QuicSentPacketManager& client_sent_packet_manager = + client_->client()->client_session()->connection()->sent_packet_manager(); + const QuicSentPacketManager* server_sent_packet_manager = + GetSentPacketManagerFromFirstServerSession(); + + EXPECT_EQ(kInitialRTT, + client_sent_packet_manager.GetRttStats()->initial_rtt()); + EXPECT_EQ(kInitialRTT, + server_sent_packet_manager->GetRttStats()->initial_rtt()); + server_thread_->Resume(); +} + TEST_P(EndToEndTest, MaxInitialRTT) { // Client tries to suggest twice the server's max initial rtt and the server // uses the max.
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc index 5e167368..ce846427f 100644 --- a/net/tools/quic/quic_dispatcher.cc +++ b/net/tools/quic/quic_dispatcher.cc
@@ -203,9 +203,13 @@ class ChloValidator : public ChloAlpnExtractor { public: ChloValidator(QuicCryptoServerStream::Helper* helper, - QuicSocketAddress self_address, + const QuicSocketAddress& client_address, + const QuicSocketAddress& peer_address, + const QuicSocketAddress& self_address, StatelessRejector* rejector) : helper_(helper), + client_address_(client_address), + peer_address_(peer_address), self_address_(self_address), rejector_(rejector), can_accept_(false), @@ -217,7 +221,8 @@ const CryptoHandshakeMessage& chlo) override { // Extract the ALPN ChloAlpnExtractor::OnChlo(version, connection_id, chlo); - if (helper_->CanAcceptClientHello(chlo, self_address_, &error_details_)) { + if (helper_->CanAcceptClientHello(chlo, client_address_, peer_address_, + self_address_, &error_details_)) { can_accept_ = true; rejector_->OnChlo(version, connection_id, helper_->GenerateConnectionIdForReject(connection_id), @@ -231,6 +236,10 @@ private: QuicCryptoServerStream::Helper* helper_; // Unowned. + // client_address_ and peer_address_ could be different values for proxy + // connections. + QuicSocketAddress client_address_; + QuicSocketAddress peer_address_; QuicSocketAddress self_address_; StatelessRejector* rejector_; // Unowned. bool can_accept_; @@ -971,11 +980,12 @@ } std::unique_ptr<StatelessRejector> rejector(new StatelessRejector( - version.transport_version, GetSupportedTransportVersions(), - crypto_config_, &compressed_certs_cache_, helper()->GetClock(), - helper()->GetRandomGenerator(), current_packet_->length(), - current_client_address_, current_self_address_)); - ChloValidator validator(session_helper_.get(), current_self_address_, + version, GetSupportedVersions(), crypto_config_, &compressed_certs_cache_, + helper()->GetClock(), helper()->GetRandomGenerator(), + current_packet_->length(), current_client_address_, + current_self_address_)); + ChloValidator validator(session_helper_.get(), current_client_address_, + current_peer_address_, current_self_address_, rejector.get()); if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), config_.create_session_tag_indicators(), @@ -1024,6 +1034,18 @@ const QuicSocketAddress& current_self_address, std::unique_ptr<QuicReceivedPacket> current_packet, ParsedQuicVersion first_version) { + const bool enable_l1_munge = GetQuicRestartFlag(quic_enable_l1_munge); + if (enable_l1_munge) { + // Reset current_* to correspond to the packet which initiated the stateless + // reject logic. + current_client_address_ = current_client_address; + current_peer_address_ = current_peer_address; + current_self_address_ = current_self_address; + current_packet_ = current_packet.get(); + current_connection_id_ = rejector->connection_id(); + framer_.set_version(first_version); + } + // Stop buffering packets on this connection const auto num_erased = temporarily_buffered_connections_.erase(rejector->connection_id()); @@ -1040,14 +1062,16 @@ return; } - // Reset current_* to correspond to the packet which initiated the stateless - // reject logic. - current_client_address_ = current_client_address; - current_peer_address_ = current_peer_address; - current_self_address_ = current_self_address; - current_packet_ = current_packet.get(); - current_connection_id_ = rejector->connection_id(); - framer_.set_version(first_version); + if (!enable_l1_munge) { + // Reset current_* to correspond to the packet which initiated the stateless + // reject logic. + current_client_address_ = current_client_address; + current_peer_address_ = current_peer_address; + current_self_address_ = current_self_address; + current_packet_ = current_packet.get(); + current_connection_id_ = rejector->connection_id(); + framer_.set_version(first_version); + } ProcessStatelessRejectorState(std::move(rejector), first_version.transport_version);
diff --git a/net/tools/quic/quic_simple_crypto_server_stream_helper.cc b/net/tools/quic/quic_simple_crypto_server_stream_helper.cc index 56afbf82..d75a675 100644 --- a/net/tools/quic/quic_simple_crypto_server_stream_helper.cc +++ b/net/tools/quic/quic_simple_crypto_server_stream_helper.cc
@@ -21,6 +21,8 @@ bool QuicSimpleCryptoServerStreamHelper::CanAcceptClientHello( const CryptoHandshakeMessage& message, + const QuicSocketAddress& client_address, + const QuicSocketAddress& peer_address, const QuicSocketAddress& self_address, std::string* error_details) const { return true;
diff --git a/net/tools/quic/quic_simple_crypto_server_stream_helper.h b/net/tools/quic/quic_simple_crypto_server_stream_helper.h index 31c257df..585a232 100644 --- a/net/tools/quic/quic_simple_crypto_server_stream_helper.h +++ b/net/tools/quic/quic_simple_crypto_server_stream_helper.h
@@ -23,6 +23,8 @@ QuicConnectionId /*connection_id*/) const override; bool CanAcceptClientHello(const CryptoHandshakeMessage& message, + const QuicSocketAddress& client_address, + const QuicSocketAddress& peer_address, const QuicSocketAddress& self_address, std::string* error_details) const override;
diff --git a/net/tools/quic/quic_simple_server_session_helper.cc b/net/tools/quic/quic_simple_server_session_helper.cc index 819553a..21a7977 100644 --- a/net/tools/quic/quic_simple_server_session_helper.cc +++ b/net/tools/quic/quic_simple_server_session_helper.cc
@@ -18,6 +18,8 @@ bool QuicSimpleServerSessionHelper::CanAcceptClientHello( const CryptoHandshakeMessage& message, + const QuicSocketAddress& client_address, + const QuicSocketAddress& peer_address, const QuicSocketAddress& self_address, std::string* error_details) const { return true;
diff --git a/net/tools/quic/quic_simple_server_session_helper.h b/net/tools/quic/quic_simple_server_session_helper.h index 00a3bf9c..f2b3f3b 100644 --- a/net/tools/quic/quic_simple_server_session_helper.h +++ b/net/tools/quic/quic_simple_server_session_helper.h
@@ -22,6 +22,8 @@ QuicConnectionId /*connection_id*/) const override; bool CanAcceptClientHello(const CryptoHandshakeMessage& message, + const QuicSocketAddress& client_address, + const QuicSocketAddress& peer_address, const QuicSocketAddress& self_address, std::string* error_details) const override;
diff --git a/net/tools/quic/quic_simple_server_session_test.cc b/net/tools/quic/quic_simple_server_session_test.cc index 124ff389..7973f56 100644 --- a/net/tools/quic/quic_simple_server_session_test.cc +++ b/net/tools/quic/quic_simple_server_session_test.cc
@@ -384,8 +384,7 @@ EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams()); - if (GetQuicReloadableFlag(quic_register_streams_early2) && - GetQuicReloadableFlag(quic_register_static_streams)) { + if (GetQuicReloadableFlag(quic_register_static_streams)) { session_->UnregisterStreamPriority(kHeadersStreamId, /*is_static=*/true); } // Assume encryption already established. @@ -395,8 +394,7 @@ session_.get(), &stream_helper_); crypto_stream->set_encryption_established(true); QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream); - if (GetQuicReloadableFlag(quic_register_streams_early2) && - GetQuicReloadableFlag(quic_register_static_streams)) { + if (GetQuicReloadableFlag(quic_register_static_streams)) { session_->RegisterStreamPriority(kHeadersStreamId, /*is_static=*/true, QuicStream::kDefaultPriority); } @@ -482,8 +480,7 @@ visitor_ = QuicConnectionPeer::GetVisitor(connection_); - if (GetQuicReloadableFlag(quic_register_streams_early2) && - GetQuicReloadableFlag(quic_register_static_streams)) { + if (GetQuicReloadableFlag(quic_register_static_streams)) { session_->UnregisterStreamPriority(kHeadersStreamId, /*is_static=*/true); } QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), nullptr); @@ -494,8 +491,7 @@ crypto_stream->set_encryption_established(true); QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream); - if (GetQuicReloadableFlag(quic_register_streams_early2) && - GetQuicReloadableFlag(quic_register_static_streams)) { + if (GetQuicReloadableFlag(quic_register_static_streams)) { session_->RegisterStreamPriority(kHeadersStreamId, /*is_static=*/true, QuicStream::kDefaultPriority); }
diff --git a/net/tools/quic/quic_spdy_client_session_test.cc b/net/tools/quic/quic_spdy_client_session_test.cc index eb16b3f..32fe5d8 100644 --- a/net/tools/quic/quic_spdy_client_session_test.cc +++ b/net/tools/quic/quic_spdy_client_session_test.cc
@@ -140,6 +140,13 @@ } TEST_P(QuicSpdyClientSessionTest, NoEncryptionAfterInitialEncryption) { + if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) { + // This test relies on resumption and is QUIC crypto specific, so it is + // disabled for TLS. + // TODO(nharper): Add support for resumption to the TLS handshake, and fix + // this test to not rely on QUIC crypto. + return; + } // Complete a handshake in order to prime the crypto config for 0-RTT. CompleteCryptoHandshake(); @@ -178,6 +185,12 @@ } TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithNoFinOrRst) { + if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) { + // This test relies on the MIDS transport parameter, which is not yet + // supported in TLS 1.3. + // TODO(nharper): Add support for Transport Parameters in the TLS handshake. + return; + } EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AnyNumber()); EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(AnyNumber()); @@ -198,6 +211,12 @@ } TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithRst) { + if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) { + // This test relies on the MIDS transport parameter, which is not yet + // supported in TLS 1.3. + // TODO(nharper): Add support for Transport Parameters in the TLS handshake. + return; + } EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AnyNumber()); EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(AnyNumber()); @@ -219,6 +238,12 @@ } TEST_P(QuicSpdyClientSessionTest, ResetAndTrailers) { + if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) { + // This test relies on the MIDS transport parameter, which is not yet + // supported in TLS 1.3. + // TODO(nharper): Add support for Transport Parameters in the TLS handshake. + return; + } // Tests the situation in which the client sends a RST at the same time that // the server sends trailing headers (trailers). Receipt of the trailers by // the client should result in all outstanding stream state being tidied up
diff --git a/net/tools/quic/stateless_rejector.cc b/net/tools/quic/stateless_rejector.cc index 8ae3e851..3497c41 100644 --- a/net/tools/quic/stateless_rejector.cc +++ b/net/tools/quic/stateless_rejector.cc
@@ -35,8 +35,8 @@ }; StatelessRejector::StatelessRejector( - QuicTransportVersion version, - const QuicTransportVersionVector& versions, + ParsedQuicVersion version, + const ParsedQuicVersionVector& versions, const QuicCryptoServerConfig* crypto_config, QuicCompressedCertsCache* compressed_certs_cache, const QuicClock* clock, @@ -89,7 +89,7 @@ StatelessRejector* rejector_ptr = rejector.get(); rejector_ptr->crypto_config_->ValidateClientHello( rejector_ptr->chlo_, rejector_ptr->client_address_.host(), - rejector_ptr->server_address_, rejector_ptr->version_, + rejector_ptr->server_address_, rejector_ptr->version_.transport_version, rejector_ptr->clock_, rejector_ptr->signed_config_, std::unique_ptr<ValidateCallback>( new ValidateCallback(std::move(rejector), std::move(done_cb)))); @@ -133,7 +133,8 @@ version_, versions_, /*use_stateless_rejects=*/true, server_designated_connection_id_, clock_, random_, compressed_certs_cache_, params_, signed_config_, - QuicCryptoStream::CryptoMessageFramingOverhead(version_), + QuicCryptoStream::CryptoMessageFramingOverhead( + version_.transport_version), chlo_packet_size_, std::move(cb)); }
diff --git a/net/tools/quic/stateless_rejector.h b/net/tools/quic/stateless_rejector.h index ac04e402..d678cf8 100644 --- a/net/tools/quic/stateless_rejector.h +++ b/net/tools/quic/stateless_rejector.h
@@ -24,8 +24,8 @@ REJECTED, // The CHLO was rejected. }; - StatelessRejector(QuicTransportVersion version, - const QuicTransportVersionVector& versions, + StatelessRejector(ParsedQuicVersion version, + const ParsedQuicVersionVector& versions, const QuicCryptoServerConfig* crypto_config, QuicCompressedCertsCache* compressed_certs_cache, const QuicClock* clock, @@ -94,8 +94,8 @@ State state_; QuicErrorCode error_; QuicString error_details_; - QuicTransportVersion version_; - QuicTransportVersionVector versions_; + ParsedQuicVersion version_; + ParsedQuicVersionVector versions_; QuicConnectionId connection_id_; QuicConnectionId server_designated_connection_id_; QuicByteCount chlo_packet_size_;
diff --git a/net/tools/quic/stateless_rejector_test.cc b/net/tools/quic/stateless_rejector_test.cc index 62e741b..4eb3bae 100644 --- a/net/tools/quic/stateless_rejector_test.cc +++ b/net/tools/quic/stateless_rejector_test.cc
@@ -52,12 +52,13 @@ // Test various combinations of QUIC version and flag state. struct TestParams { - QuicTransportVersion version; + ParsedQuicVersion version = + ParsedQuicVersion{PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED}; FlagsMode flags; }; QuicString TestParamToString(const testing::TestParamInfo<TestParams>& params) { - return QuicStrCat("v", params.param.version, "_", + return QuicStrCat("v", ParsedQuicVersionToString(params.param.version), "_", FlagsModeToString(params.param.flags)); } @@ -65,7 +66,7 @@ std::vector<TestParams> params; for (FlagsMode flags : {ENABLED, STATELESS_DISABLED, CHEAP_DISABLED, BOTH_DISABLED}) { - for (QuicTransportVersion version : AllSupportedTransportVersions()) { + for (ParsedQuicVersion version : AllSupportedVersions()) { TestParams param; param.version = version; param.flags = flags; @@ -88,7 +89,7 @@ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), rejector_(QuicMakeUnique<StatelessRejector>( GetParam().version, - AllSupportedTransportVersions(), + AllSupportedVersions(), &config_, &compressed_certs_cache_, &clock_, @@ -112,8 +113,7 @@ "#" + QuicTextUtils::HexEncode(config_peer_.GetPrimaryConfig()->id); // Encode the QUIC version. - ver_hex_ = QuicVersionLabelToString( - QuicVersionToQuicVersionLabel(GetParam().version)); + ver_hex_ = ParsedQuicVersionToString(GetParam().version); // Generate a public value. char public_value[32]; @@ -180,7 +180,7 @@ {{"PDMD", "X509"}, {"COPT", "SREJ"}}); // clang-format on - rejector_->OnChlo(GetParam().version, kConnectionId, + rejector_->OnChlo(GetParam().version.transport_version, kConnectionId, kServerDesignateConnectionId, client_hello); if (GetParam().flags != ENABLED) { @@ -209,7 +209,7 @@ kClientHelloMinimumSize); // clang-format on - rejector_->OnChlo(GetParam().version, kConnectionId, + rejector_->OnChlo(GetParam().version.transport_version, kConnectionId, kServerDesignateConnectionId, client_hello); EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state()); } @@ -229,7 +229,7 @@ kClientHelloMinimumSize); // clang-format on - rejector_->OnChlo(GetParam().version, kConnectionId, + rejector_->OnChlo(GetParam().version.transport_version, kConnectionId, kServerDesignateConnectionId, client_hello); if (GetParam().flags != ENABLED) { EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state()); @@ -271,7 +271,7 @@ kClientHelloMinimumSize); // clang-format on - rejector_->OnChlo(GetParam().version, kConnectionId, + rejector_->OnChlo(GetParam().version.transport_version, kConnectionId, kServerDesignateConnectionId, client_hello); if (GetParam().flags != ENABLED) { EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state());
diff --git a/net/tools/quic/test_tools/mock_quic_session_visitor.h b/net/tools/quic/test_tools/mock_quic_session_visitor.h index 793be8d4..80cf2ba 100644 --- a/net/tools/quic/test_tools/mock_quic_session_visitor.h +++ b/net/tools/quic/test_tools/mock_quic_session_visitor.h
@@ -37,8 +37,10 @@ ~MockQuicCryptoServerStreamHelper() override; MOCK_CONST_METHOD1(GenerateConnectionIdForReject, QuicConnectionId(QuicConnectionId connection_id)); - MOCK_CONST_METHOD3(CanAcceptClientHello, + MOCK_CONST_METHOD5(CanAcceptClientHello, bool(const CryptoHandshakeMessage& message, + const QuicSocketAddress& client_address, + const QuicSocketAddress& peer_address, const QuicSocketAddress& self_address, std::string* error_details));
diff --git a/printing/common/pdf_metafile_utils.cc b/printing/common/pdf_metafile_utils.cc index c3c073e8..fe3fd49 100644 --- a/printing/common/pdf_metafile_utils.cc +++ b/printing/common/pdf_metafile_utils.cc
@@ -51,6 +51,7 @@ metadata.fCreator = creator.empty() ? SkString("Chromium") : SkString(creator.c_str(), creator.size()); + metadata.fRasterDPI = 300.0f; return SkDocument::MakePDF(stream, metadata); }
diff --git a/services/audio/BUILD.gn b/services/audio/BUILD.gn index 83045cbd..b7651d3 100644 --- a/services/audio/BUILD.gn +++ b/services/audio/BUILD.gn
@@ -32,6 +32,8 @@ sources = [ "debug_recording.cc", "debug_recording.h", + "delay_buffer.cc", + "delay_buffer.h", "group_coordinator.cc", "group_coordinator.h", "group_member.h", @@ -74,6 +76,7 @@ sources = [ "debug_recording_unittest.cc", + "delay_buffer_unittest.cc", "group_coordinator_unittest.cc", "input_stream_unittest.cc", "local_muter_unittest.cc", @@ -83,6 +86,8 @@ "sync_reader_unittest.cc", "test/audio_system_to_service_adapter_test.cc", "test/debug_recording_session_unittest.cc", + "test/fake_consumer.cc", + "test/fake_consumer.h", "test/fake_group_member.cc", "test/fake_group_member.h", "test/in_process_service_test.cc",
diff --git a/services/audio/delay_buffer.cc b/services/audio/delay_buffer.cc new file mode 100644 index 0000000..17d2a04b --- /dev/null +++ b/services/audio/delay_buffer.cc
@@ -0,0 +1,126 @@ +// 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 "services/audio/delay_buffer.h" + +#include <algorithm> +#include <utility> + +#include "base/numerics/safe_conversions.h" +#include "media/base/audio_bus.h" +#include "media/base/vector_math.h" + +namespace audio { + +DelayBuffer::DelayBuffer(int history_size) : history_size_(history_size) {} + +DelayBuffer::~DelayBuffer() = default; + +void DelayBuffer::Write(FrameTicks position, + const media::AudioBus& input_bus, + double volume) { + DCHECK(chunks_.empty() || chunks_.back().GetEndPosition() <= position); + + // Prune-out the oldest InputChunks, but ensure that this DelayBuffer is + // maintaining at least |history_size_| frames in total when this method + // returns (i.e., after the current chunk is inserted). + const FrameTicks prune_position = + position + input_bus.frames() - history_size_; + while (!chunks_.empty() && + chunks_.front().GetEndPosition() <= prune_position) { + chunks_.pop_front(); + } + + // Make a copy of the AudioBus for later consumption. Apply the volume setting + // by scaling the audio signal during the copy. + auto copy = media::AudioBus::Create(input_bus.channels(), input_bus.frames()); + for (int ch = 0; ch < input_bus.channels(); ++ch) { + media::vector_math::FMUL(input_bus.channel(ch), volume, input_bus.frames(), + copy->channel(ch)); + } + + chunks_.emplace_back(position, std::move(copy)); +} + +void DelayBuffer::Read(FrameTicks from, + int frames_to_read, + media::AudioBus* output_bus) { + DCHECK_LE(frames_to_read, output_bus->frames()); + + // Remove all of the oldest chunks until the one in front contains the |from| + // position (or is the first chunk after it). + while (!chunks_.empty() && chunks_.front().GetEndPosition() <= from) { + chunks_.pop_front(); + } + + // Loop, transferring data from each InputChunk to the output AudioBus until + // the requested number of frames have been read. + for (int frames_remaining = frames_to_read; frames_remaining > 0;) { + const int dest_offset = frames_to_read - frames_remaining; + + // If attempting to read past the end of the recorded signal, zero-pad the + // rest of the output and return. + if (chunks_.empty()) { + output_bus->ZeroFramesPartial(dest_offset, frames_remaining); + return; + } + const InputChunk& chunk = chunks_.front(); + + // This is the offset to the frame within the chunk's AudioBus that + // corresponds to the offset in the output AudioBus. If this calculated + // value is out-of-range, there is a gap (i.e., a missing piece of audio + // signal) in the recording. + const int source_offset = + base::saturated_cast<int>(from + dest_offset - chunk.position); + + if (source_offset < 0) { + // There is a gap in the recording. Fill zeroes in the corresponding part + // of the output. + const int frames_to_zero_fill = (source_offset + frames_remaining <= 0) + ? frames_remaining + : -source_offset; + output_bus->ZeroFramesPartial(dest_offset, frames_to_zero_fill); + frames_remaining -= frames_to_zero_fill; + continue; + } + DCHECK_LE(source_offset, chunk.bus->frames()); + + // Copy some or all of the frames in the current chunk to the output; the + // lesser of: a) the frames available in the chunk, or b) the frames + // remaining to output. + const int frames_to_copy_from_chunk = chunk.bus->frames() - source_offset; + if (frames_to_copy_from_chunk <= frames_remaining) { + chunk.bus->CopyPartialFramesTo(source_offset, frames_to_copy_from_chunk, + dest_offset, output_bus); + frames_remaining -= frames_to_copy_from_chunk; + chunks_.pop_front(); // All frames from this chunk have been consumed. + } else { + chunk.bus->CopyPartialFramesTo(source_offset, frames_remaining, + dest_offset, output_bus); + return; // The |output_bus| has been fully populated. + } + } +} + +DelayBuffer::FrameTicks DelayBuffer::GetBeginPosition() const { + return chunks_.empty() ? 0 : chunks_.front().position; +} + +DelayBuffer::FrameTicks DelayBuffer::GetEndPosition() const { + return chunks_.empty() ? 0 : chunks_.back().GetEndPosition(); +} + +DelayBuffer::InputChunk::InputChunk(FrameTicks p, + std::unique_ptr<media::AudioBus> b) + : position(p), bus(std::move(b)) {} +DelayBuffer::InputChunk::InputChunk(DelayBuffer::InputChunk&&) = default; +DelayBuffer::InputChunk& DelayBuffer::InputChunk::operator=( + DelayBuffer::InputChunk&&) = default; +DelayBuffer::InputChunk::~InputChunk() = default; + +DelayBuffer::FrameTicks DelayBuffer::InputChunk::GetEndPosition() const { + return position + bus->frames(); +} + +} // namespace audio
diff --git a/services/audio/delay_buffer.h b/services/audio/delay_buffer.h new file mode 100644 index 0000000..2d1482c --- /dev/null +++ b/services/audio/delay_buffer.h
@@ -0,0 +1,109 @@ +// 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 SERVICES_AUDIO_DELAY_BUFFER_H_ +#define SERVICES_AUDIO_DELAY_BUFFER_H_ + +#include <memory> + +#include "base/containers/circular_deque.h" +#include "base/macros.h" + +namespace media { +class AudioBus; +} // namespace media + +namespace audio { + +// Records and maintains a recent history of an audio signal, then allows +// read-back starting from part of the recording. While this looks a lot like a +// FIFO, it is not because Read() will typically not be reading from one end of +// a queue. +// +// The audio format is the same throughout all operations, as this DelayBuffer +// does not resample or remix the audio. Also, for absolute precision, it uses +// frame counts to track the timing of the audio recorded and read. +// +// The typical use case is the loopback audio system: In this scenario, the +// service has an audio output stream running for local playback, and the +// stream's audio is timed to play back in the near future (usually, 1 ms to 20 +// ms, depending on the platform). When loopback is active, that audio will be +// copied into this DelayBuffer via calls to Write(). Then, the loopback audio +// stream implementation will Read() the audio at a time in the recent past +// (approximately 20 ms before "now," but this will vary slightly). Because of +// clock drift concerns, the loopback implementation will slightly compress/ +// stretch the audio signal it pulls out of this buffer, to maintain +// synchronization, and this will cause it to vary the number of frames read for +// each successive Read() call. +class DelayBuffer { + public: + // Use sample counts as a measure of audio signal position. + using FrameTicks = int64_t; + + // Construct a DelayBuffer that keeps at least |history_size| un-read frames + // recorded. + explicit DelayBuffer(int history_size); + + ~DelayBuffer(); + + // Inserts a copy of the given audio into the buffer. |position| must be + // monotonically increasing, and the audio must not overlap any + // previously-written audio. The length of the |input_bus| may vary, but the + // channel layout may not. The given |volume| will be used to scale the audio + // during the copy to the internal buffer. + void Write(FrameTicks position, + const media::AudioBus& input_bus, + double volume); + + // Reads audio from the buffer, starting at the given |from| position, which + // must not overlap any previously-read audio. |frames_to_read| is the number + // of frames to read, which may be any amount less than or equal to the size + // of the |output_bus|. No part of the |output_bus| beyond the first + // |frames_to_read| will be modified. If there are gaps (i.e., missing pieces) + // of the recording, zeros will be filled in the output. + void Read(FrameTicks from, int frames_to_read, media::AudioBus* output_bus); + + // Returns the current buffered range of the recording, ala the usual C++ + // [begin,end) semantics. + FrameTicks GetBeginPosition() const; + FrameTicks GetEndPosition() const; + + private: + struct InputChunk { + // The position of the first frame in this chunk. + FrameTicks position; + + // The storage for the audio frames. + std::unique_ptr<media::AudioBus> bus; + + // Constructor for an InputChunk with data. + InputChunk(FrameTicks p, std::unique_ptr<media::AudioBus> b); + + // Move constructor/assignment. + InputChunk(InputChunk&& other); + InputChunk& operator=(InputChunk&& other); + + ~InputChunk(); + + // Returns the position just after the last frame's position. + FrameTicks GetEndPosition() const; + + private: + DISALLOW_COPY_AND_ASSIGN(InputChunk); + }; + + // The minimum number of un-read frames that must be kept. + const int history_size_; + + // A queue storing each chunk of recorded audio. The elements in the queue are + // always in-order, chronologically increasing by InputChunk::position, and do + // not overlap. + base::circular_deque<InputChunk> chunks_; + + DISALLOW_COPY_AND_ASSIGN(DelayBuffer); +}; + +} // namespace audio + +#endif // SERVICES_AUDIO_DELAY_BUFFER_H_
diff --git a/services/audio/delay_buffer_unittest.cc b/services/audio/delay_buffer_unittest.cc new file mode 100644 index 0000000..5fcaad7 --- /dev/null +++ b/services/audio/delay_buffer_unittest.cc
@@ -0,0 +1,167 @@ +// 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 "services/audio/delay_buffer.h" + +#include <algorithm> + +#include "media/base/audio_bus.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace audio { +namespace { + +constexpr int kChannels = 1; +constexpr int kMaxFrames = 32; + +#define EXPECT_BUS_VALUES_EQ(bus, begin, end, value) \ + { \ + const auto IsValue = [](float x) { return x == (value); }; \ + EXPECT_TRUE(std::all_of((bus)->channel(0) + (begin), \ + (bus)->channel(0) + (end) - (begin), IsValue)); \ + } + +TEST(DelayBufferTest, RecordsAMaximumNumberOfFrames) { + DelayBuffer buffer(kMaxFrames); + ASSERT_EQ(buffer.GetBeginPosition(), buffer.GetEndPosition()); + + constexpr int frames_per_bus = kMaxFrames / 4; + const auto bus = media::AudioBus::Create(kChannels, frames_per_bus); + std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 1.0); + + // Fill the buffer. + DelayBuffer::FrameTicks position = 0; + for (int i = 0; i < 4; ++i) { + buffer.Write(position, *bus, 1.0); + position += frames_per_bus; + EXPECT_EQ(0, buffer.GetBeginPosition()); + EXPECT_EQ(position, buffer.GetEndPosition()); + } + + // Writing just one more bus should cause the leading frames to be dropped. + buffer.Write(position, *bus, 1.0); + position += frames_per_bus; + EXPECT_EQ(position - kMaxFrames, buffer.GetBeginPosition()); + EXPECT_EQ(position, buffer.GetEndPosition()); + + // Now, simulate a gap in the recording by recording the next bus late. + position += frames_per_bus * 2; + buffer.Write(position, *bus, 1.0); + position += frames_per_bus; + EXPECT_EQ(position - kMaxFrames, buffer.GetBeginPosition()); + EXPECT_EQ(position, buffer.GetEndPosition()); +} + +TEST(DelayBufferTest, ReadsSilenceIfNothingWasRecorded) { + DelayBuffer buffer(kMaxFrames); + ASSERT_EQ(buffer.GetBeginPosition(), buffer.GetEndPosition()); + + DelayBuffer::FrameTicks position = 0; + constexpr int frames_per_bus = kMaxFrames / 4; + const auto bus = media::AudioBus::Create(kChannels, frames_per_bus); + + for (int i = 0; i < 10; ++i) { + // Set data in the bus to confirm it is all going to be overwritten. + std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 1.0); + + buffer.Read(position, frames_per_bus, bus.get()); + EXPECT_EQ(buffer.GetBeginPosition(), buffer.GetEndPosition()); + EXPECT_BUS_VALUES_EQ(bus, 0, frames_per_bus, 0.0); + + position += frames_per_bus; + } +} + +TEST(DelayBufferTest, ReadsSilenceIfOutsideRecordedRange) { + DelayBuffer buffer(kMaxFrames); + ASSERT_EQ(buffer.GetBeginPosition(), buffer.GetEndPosition()); + + constexpr int frames_per_bus = kMaxFrames / 4; + const auto bus = media::AudioBus::Create(kChannels, frames_per_bus); + std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 1.0); + + // Fill the buffer. + DelayBuffer::FrameTicks position = 0; + for (int i = 0; i < 4; ++i) { + buffer.Write(position, *bus, 1.0); + position += frames_per_bus; + } + EXPECT_EQ(0, buffer.GetBeginPosition()); + EXPECT_EQ(position, buffer.GetEndPosition()); + + // Read before the begin position and expect to get silence. + std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5); + buffer.Read(-kMaxFrames, frames_per_bus, bus.get()); + EXPECT_BUS_VALUES_EQ(bus, 0, frames_per_bus, 0.0); + + // Read at a position one before the begin position. Expect the first sample + // to be 0.0, and the rest 1.0. + std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5); + buffer.Read(buffer.GetBeginPosition() - 1, frames_per_bus, bus.get()); + EXPECT_EQ(0.0, bus->channel(0)[0]); + EXPECT_BUS_VALUES_EQ(bus, 1, frames_per_bus - 1, 1.0); + + // Read at a position where the last sample should be 0.0 and the rest 1.0. + std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5); + buffer.Read(buffer.GetEndPosition() - frames_per_bus + 1, frames_per_bus, + bus.get()); + EXPECT_BUS_VALUES_EQ(bus, 0, frames_per_bus - 1, 1.0); + EXPECT_EQ(0.0, bus->channel(0)[frames_per_bus - 1]); + + // Read after the end position and expect to get silence. + std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5); + buffer.Read(kMaxFrames, frames_per_bus, bus.get()); + EXPECT_BUS_VALUES_EQ(bus, 0, frames_per_bus, 0.0); +} + +TEST(DelayBufferTest, ReadsGapsInRecording) { + DelayBuffer buffer(kMaxFrames); + ASSERT_EQ(buffer.GetBeginPosition(), buffer.GetEndPosition()); + + constexpr int frames_per_bus = kMaxFrames / 4; + const auto bus = media::AudioBus::Create(kChannels, frames_per_bus); + std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 1.0); + + // Fill the buffer, but with a gap in the third quarter of it. + DelayBuffer::FrameTicks record_position = 0; + for (int i = 0; i < 4; ++i) { + if (i != 2) { + buffer.Write(record_position, *bus, 1.0); + } + record_position += frames_per_bus; + } + EXPECT_EQ(0, buffer.GetBeginPosition()); + EXPECT_EQ(record_position, buffer.GetEndPosition()); + + // Read through the whole range, but offset by one frame early. Confirm the + // silence gap appears in the right place. + DelayBuffer::FrameTicks read_position = -1; + std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5); + buffer.Read(read_position, frames_per_bus, bus.get()); + read_position += frames_per_bus; + EXPECT_EQ(0.0, bus->channel(0)[0]); + EXPECT_BUS_VALUES_EQ(bus, 1, frames_per_bus - 1, 1.0); + + std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5); + buffer.Read(read_position, frames_per_bus, bus.get()); + read_position += frames_per_bus; + EXPECT_BUS_VALUES_EQ(bus, 0, frames_per_bus, 1.0); + + std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5); + buffer.Read(read_position, frames_per_bus, bus.get()); + read_position += frames_per_bus; + EXPECT_EQ(1.0, bus->channel(0)[0]); + // The gap begins. + EXPECT_BUS_VALUES_EQ(bus, 1, frames_per_bus - 1, 0.0); + + std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5); + buffer.Read(read_position, frames_per_bus, bus.get()); + read_position += frames_per_bus; + EXPECT_EQ(0.0, bus->channel(0)[0]); + // The gap ends. + EXPECT_BUS_VALUES_EQ(bus, 1, frames_per_bus - 1, 1.0); +} + +} // namespace +} // namespace audio
diff --git a/services/audio/test/fake_consumer.cc b/services/audio/test/fake_consumer.cc new file mode 100644 index 0000000..4d3241b --- /dev/null +++ b/services/audio/test/fake_consumer.cc
@@ -0,0 +1,114 @@ +// 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 "services/audio/test/fake_consumer.h" + +#include <algorithm> +#include <cmath> + +#include "base/logging.h" +#include "base/numerics/math_constants.h" +#include "media/base/audio_bus.h" + +namespace audio { + +FakeConsumer::FakeConsumer(int channels, int sample_rate) + : sample_rate_(sample_rate) { + recorded_channel_data_.resize(channels); +} + +FakeConsumer::~FakeConsumer() = default; + +int FakeConsumer::GetRecordedFrameCount() const { + return static_cast<int>(recorded_channel_data_[0].size()); +} + +void FakeConsumer::Clear() { + for (auto& data : recorded_channel_data_) { + data.clear(); + } +} + +void FakeConsumer::Consume(const media::AudioBus& bus) { + CHECK_EQ(static_cast<int>(recorded_channel_data_.size()), bus.channels()); + for (int ch = 0; ch < static_cast<int>(recorded_channel_data_.size()); ++ch) { + const float* const src = bus.channel(ch); + std::vector<float>& samples = recorded_channel_data_[ch]; + samples.insert(samples.end(), src, src + bus.frames()); + } +} + +bool FakeConsumer::IsSilent(int channel) const { + return IsSilentInRange(channel, 0, GetRecordedFrameCount()); +} + +bool FakeConsumer::IsSilentInRange(int channel, + int begin_frame, + int end_frame) const { + CHECK_LT(channel, static_cast<int>(recorded_channel_data_.size())); + const std::vector<float>& samples = recorded_channel_data_[channel]; + + CHECK_GE(begin_frame, 0); + CHECK_LE(begin_frame, end_frame); + CHECK_LE(end_frame, static_cast<int>(samples.size())); + + if (begin_frame == end_frame) { + return true; + } + const float value = samples[begin_frame]; + return std::all_of(samples.data() + begin_frame + 1, + samples.data() + end_frame, + [&value](float f) { return f == value; }); +} + +int FakeConsumer::FindEndOfSilence(int channel, int begin_frame) const { + CHECK_LT(channel, static_cast<int>(recorded_channel_data_.size())); + CHECK_GE(begin_frame, 0); + const std::vector<float>& samples = recorded_channel_data_[channel]; + + if (static_cast<int>(samples.size()) <= begin_frame) { + return begin_frame; + } + const float value = samples[begin_frame]; + const float* at = std::find_if(samples.data() + begin_frame + 1, + samples.data() + GetRecordedFrameCount(), + [&value](float f) { return f != value; }); + return at - samples.data(); +} + +double FakeConsumer::ComputeAmplitudeAt(int channel, + double frequency, + int end_frame) const { + CHECK_LT(channel, static_cast<int>(recorded_channel_data_.size())); + CHECK_GT(frequency, 0.0); + const std::vector<float>& samples = recorded_channel_data_[channel]; + CHECK_LE(end_frame, static_cast<int>(samples.size())); + + // Attempt to analyze the last three cycles of waveform, or less if the + // recording is shorter than that. Three is chosen here because this will + // allow the algorithm below to reliably compute an amplitude value that is + // very close to that which was used to generate the pure source signal, even + // if the implementation under test has slightly stretched/compressed the + // signal (e.g., +/- 1 Hz). + const int analysis_length = + std::min(end_frame, static_cast<int>(3 * sample_rate_ / frequency)); + if (analysis_length == 0) { + return 0.0; + } + + // Compute the amplitude for just the |frequency| of interest, as opposed to + // doing a full Discrete Fourier Transform. + const double step = 2.0 * base::kPiDouble * frequency / sample_rate_; + double real_part = 0.0; + double img_part = 0.0; + for (int i = end_frame - analysis_length; i < end_frame; ++i) { + real_part += samples[i] * std::cos(i * step); + img_part -= samples[i] * std::sin(i * step); + } + const double normalization_factor = 2.0 / analysis_length; + return std::sqrt(real_part * real_part + img_part * img_part) * + normalization_factor; +} + +} // namespace audio
diff --git a/services/audio/test/fake_consumer.h b/services/audio/test/fake_consumer.h new file mode 100644 index 0000000..28b3b33 --- /dev/null +++ b/services/audio/test/fake_consumer.h
@@ -0,0 +1,59 @@ +// 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 SERVICES_AUDIO_TEST_FAKE_CONSUMER_H_ +#define SERVICES_AUDIO_TEST_FAKE_CONSUMER_H_ + +#include <vector> + +#include "base/macros.h" + +namespace media { +class AudioBus; +} + +namespace audio { + +// Consumes and records the audio signal. Then, test procedures may use the +// utility methods to analyze the recording. +class FakeConsumer { + public: + FakeConsumer(int channels, int sample_rate); + + ~FakeConsumer(); + + // Returns the total number of frames recorded (the end position of the + // recording). + int GetRecordedFrameCount() const; + + // Throws away all samples recorded so far. + void Clear(); + + // Appends the audio signal in |bus| to the recording. + void Consume(const media::AudioBus& bus); + + // Returns true if all (or a part) of the recording in |channel| is flat + // (i.e., not oscillating, and effectively silent). + bool IsSilent(int channel) const; + bool IsSilentInRange(int channel, int begin_frame, int end_frame) const; + + // Returns the position at which silence in the recording ends, at or after + // |begin_frame|. If the entire recording after the given position is silent, + // this will return GetRecordedFrameCount(). + int FindEndOfSilence(int channel, int begin_frame) const; + + // Returns the amplitude of the given |frequency| in the given |channel| just + // before the given |end_frame| position. + double ComputeAmplitudeAt(int channel, double frequency, int end_frame) const; + + private: + const int sample_rate_; + std::vector<std::vector<float>> recorded_channel_data_; + + DISALLOW_COPY_AND_ASSIGN(FakeConsumer); +}; + +} // namespace audio + +#endif // SERVICES_AUDIO_TEST_FAKE_CONSUMER_H_
diff --git a/services/network/cross_origin_read_blocking_unittest.cc b/services/network/cross_origin_read_blocking_unittest.cc index 7722ca2..68a1e39 100644 --- a/services/network/cross_origin_read_blocking_unittest.cc +++ b/services/network/cross_origin_read_blocking_unittest.cc
@@ -140,7 +140,6 @@ StringPiece json_data2("{ \"key \\\" \" \t\t\r\n:"); StringPiece non_json_data0("\t\t\r\n { name : \"chrome\", "); StringPiece non_json_data1("\t\t\r\n foo({ \"name\" : \"chrome\", "); - StringPiece empty_data(""); EXPECT_EQ(SniffingResult::kYes, CrossOriginReadBlocking::SniffForJSON(json_data));
diff --git a/services/service_manager/runner/init.cc b/services/service_manager/runner/init.cc index 0162ea6d..f598822 100644 --- a/services/service_manager/runner/init.cc +++ b/services/service_manager/runner/init.cc
@@ -67,6 +67,7 @@ } } +NO_SANITIZE("cfi-icall") void CallLibraryEarlyInitialization(base::NativeLibrary app_library) { // Do whatever warming that the service wants.
diff --git a/services/tracing/perfetto/json_trace_exporter.cc b/services/tracing/perfetto/json_trace_exporter.cc index 202982f..69e56ce 100644 --- a/services/tracing/perfetto/json_trace_exporter.cc +++ b/services/tracing/perfetto/json_trace_exporter.cc
@@ -16,6 +16,8 @@ #include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h" #include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_packet.pb.h" +using TraceEvent = base::trace_event::TraceEvent; + namespace { void OutputJSONFromTraceEventProto( @@ -111,9 +113,58 @@ base::StringAppendF(out, ",\"s\":\"%c\"", scope); } - *out += ",\"args\":\"__stripped__\""; + *out += ",\"args\":{"; + for (int i = 0; i < event.args_size(); ++i) { + auto& arg = event.args(i); - *out += "}"; + if (i > 0) { + *out += ","; + } + + *out += "\""; + *out += arg.name(); + *out += "\":"; + + TraceEvent::TraceValue value; + if (arg.has_bool_value()) { + value.as_bool = arg.bool_value(); + TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_BOOL, value, out); + continue; + } + + if (arg.has_uint_value()) { + value.as_uint = arg.uint_value(); + TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_UINT, value, out); + continue; + } + + if (arg.has_int_value()) { + value.as_int = arg.int_value(); + TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_INT, value, out); + continue; + } + + if (arg.has_double_value()) { + value.as_double = arg.double_value(); + TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_DOUBLE, value, out); + continue; + } + + if (arg.has_pointer_value()) { + value.as_pointer = reinterpret_cast<void*>(arg.pointer_value()); + TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_POINTER, value, out); + continue; + } + + if (arg.has_string_value()) { + std::string str = arg.string_value(); + value.as_string = &str[0]; + TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_STRING, value, out); + continue; + } + } + + *out += "}}"; } } // namespace
diff --git a/services/tracing/perfetto/json_trace_exporter_unittest.cc b/services/tracing/perfetto/json_trace_exporter_unittest.cc index 0bb40352..bd5e14a4 100644 --- a/services/tracing/perfetto/json_trace_exporter_unittest.cc +++ b/services/tracing/perfetto/json_trace_exporter_unittest.cc
@@ -8,8 +8,10 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/json/json_reader.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/trace_event_analyzer.h" #include "base/trace_event/trace_event.h" #include "testing/gtest/include/gtest/gtest.h" @@ -140,24 +142,29 @@ } void OnTraceEventJSON(const std::string& json, bool has_more) { - last_received_json_ = json; + // The TraceAnalyzer expects the raw trace output, without the + // wrapping root-node. + static const size_t kTracingPreambleLength = strlen("\"{traceEvents\":"); + static const size_t kTracingEpilogueLength = strlen("}"); + std::string raw_events = json.substr( + kTracingPreambleLength, + json.length() - kTracingPreambleLength - kTracingEpilogueLength); + + trace_analyzer_.reset(trace_analyzer::TraceAnalyzer::Create(raw_events)); + EXPECT_TRUE(trace_analyzer_); } - void EmitTestPacket() { - perfetto::protos::TracePacket trace_packet_proto; - - auto* event_bundle = trace_packet_proto.mutable_chrome_events(); - auto* new_trace_event = event_bundle->add_trace_events(); - - new_trace_event->set_name("name"); + void SetTestPacketBasicData( + perfetto::protos::ChromeTraceEvent* new_trace_event) { + new_trace_event->set_name("foo_name"); new_trace_event->set_timestamp(42); new_trace_event->set_flags(TRACE_EVENT_FLAG_HAS_GLOBAL_ID | TRACE_EVENT_FLAG_FLOW_OUT); new_trace_event->set_process_id(2); new_trace_event->set_thread_id(3); - new_trace_event->set_category_group_name("cat"); - new_trace_event->set_phase(TRACE_EVENT_PHASE_INSTANT); + new_trace_event->set_category_group_name("cat_name"); + new_trace_event->set_phase(TRACE_EVENT_PHASE_COMPLETE); new_trace_event->set_duration(4); new_trace_event->set_thread_duration(5); new_trace_event->set_thread_timestamp(6); @@ -167,7 +174,9 @@ std::string scope; scope += TRACE_EVENT_SCOPE_NAME_GLOBAL; new_trace_event->set_scope(scope); + } + void FinalizePacket(const perfetto::protos::TracePacket& trace_packet_proto) { perfetto::TracePacket trace_packet; std::string ser_buf = trace_packet_proto.SerializeAsString(); trace_packet.AddSlice(&ser_buf[0], ser_buf.size()); @@ -178,39 +187,248 @@ json_trace_exporter_->OnTraceData(std::move(packets), false); } - void ValidateTestPacket() { - EXPECT_EQ( - "{\"traceEvents\":[{\"pid\":2,\"tid\":3,\"ts\":42,\"ph\":\"I\",\"cat\":" - "\"cat\",\"name\":\"name\",\"dur\":4,\"tdur\":5,\"tts\":6,\"scope\":" - "\"g\",\"id2\":{\"global\":\"0x7\"},\"bind_id\":\"0x8\",\"flow_out\":" - "true,\"s\":\"g\",\"args\":\"__stripped__\"}]}", - last_received_json_); + const trace_analyzer::TraceEvent* ValidateAndGetBasicTestPacket() { + const trace_analyzer::TraceEvent* trace_event = + trace_analyzer_->FindFirstOf( + trace_analyzer::Query(trace_analyzer::Query::EVENT_NAME) == + trace_analyzer::Query::String("foo_name")); + EXPECT_TRUE(trace_event); + + EXPECT_EQ(2, trace_event->thread.process_id); + EXPECT_EQ(3, trace_event->thread.thread_id); + EXPECT_EQ(42, trace_event->timestamp); + EXPECT_EQ('X', trace_event->phase); + EXPECT_EQ("foo_name", trace_event->name); + EXPECT_EQ("cat_name", trace_event->category); + EXPECT_EQ(4, trace_event->duration); + EXPECT_EQ(5, trace_event->thread_duration); + EXPECT_EQ(6, trace_event->thread_timestamp); + EXPECT_EQ("g", trace_event->scope); + EXPECT_EQ("0x7", trace_event->global_id2); + EXPECT_EQ("0x8", trace_event->bind_id); + EXPECT_TRUE(trace_event->flow_out); + + return trace_event; } - std::unique_ptr<MockService> service_; + const trace_analyzer::TraceAnalyzer* trace_analyzer() const { + return trace_analyzer_.get(); + } + MockService* service() { return service_.get(); } private: + std::unique_ptr<MockService> service_; std::unique_ptr<JSONTraceExporter> json_trace_exporter_; std::unique_ptr<base::MessageLoop> message_loop_; - std::string last_received_json_; + std::unique_ptr<trace_analyzer::TraceAnalyzer> trace_analyzer_; }; TEST_F(JSONTraceExporterTest, EnableTracingWithGivenConfig) { const char kDummyTraceConfig[] = "trace_all_the_things"; CreateJSONTraceExporter(kDummyTraceConfig); - service_->WaitForTracingEnabled(); - EXPECT_EQ(kDummyTraceConfig, service_->tracing_enabled_with_config()); + service()->WaitForTracingEnabled(); + EXPECT_EQ(kDummyTraceConfig, service()->tracing_enabled_with_config()); } -TEST_F(JSONTraceExporterTest, TestEvent) { +TEST_F(JSONTraceExporterTest, TestBasicEvent) { CreateJSONTraceExporter("foo"); - service_->WaitForTracingEnabled(); - + service()->WaitForTracingEnabled(); StopAndFlush(); - EmitTestPacket(); - service_->WaitForTracingDisabled(); - ValidateTestPacket(); + perfetto::protos::TracePacket trace_packet_proto; + auto* new_trace_event = + trace_packet_proto.mutable_chrome_events()->add_trace_events(); + SetTestPacketBasicData(new_trace_event); + FinalizePacket(trace_packet_proto); + + service()->WaitForTracingDisabled(); + ValidateAndGetBasicTestPacket(); +} + +TEST_F(JSONTraceExporterTest, TestEventWithBoolArgs) { + CreateJSONTraceExporter("foo"); + service()->WaitForTracingEnabled(); + StopAndFlush(); + + perfetto::protos::TracePacket trace_packet_proto; + auto* new_trace_event = + trace_packet_proto.mutable_chrome_events()->add_trace_events(); + SetTestPacketBasicData(new_trace_event); + + { + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name("foo1"); + new_arg->set_bool_value(true); + } + + { + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name("foo2"); + new_arg->set_bool_value(false); + } + + FinalizePacket(trace_packet_proto); + + service()->WaitForTracingDisabled(); + auto* trace_event = ValidateAndGetBasicTestPacket(); + + EXPECT_TRUE(trace_event->GetKnownArgAsBool("foo1")); + EXPECT_FALSE(trace_event->GetKnownArgAsBool("foo2")); +} + +TEST_F(JSONTraceExporterTest, TestEventWithUintArgs) { + CreateJSONTraceExporter("foo"); + service()->WaitForTracingEnabled(); + StopAndFlush(); + + perfetto::protos::TracePacket trace_packet_proto; + auto* new_trace_event = + trace_packet_proto.mutable_chrome_events()->add_trace_events(); + SetTestPacketBasicData(new_trace_event); + + { + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name("foo1"); + new_arg->set_uint_value(1); + } + + { + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name("foo2"); + new_arg->set_uint_value(2); + } + + FinalizePacket(trace_packet_proto); + + service()->WaitForTracingDisabled(); + auto* trace_event = ValidateAndGetBasicTestPacket(); + + EXPECT_EQ(1, trace_event->GetKnownArgAsDouble("foo1")); + EXPECT_EQ(2, trace_event->GetKnownArgAsDouble("foo2")); +} + +TEST_F(JSONTraceExporterTest, TestEventWithIntArgs) { + CreateJSONTraceExporter("foo"); + service()->WaitForTracingEnabled(); + StopAndFlush(); + + perfetto::protos::TracePacket trace_packet_proto; + auto* new_trace_event = + trace_packet_proto.mutable_chrome_events()->add_trace_events(); + SetTestPacketBasicData(new_trace_event); + + { + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name("foo1"); + new_arg->set_int_value(1); + } + + { + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name("foo2"); + new_arg->set_int_value(2); + } + + FinalizePacket(trace_packet_proto); + + service()->WaitForTracingDisabled(); + auto* trace_event = ValidateAndGetBasicTestPacket(); + + EXPECT_EQ(1, trace_event->GetKnownArgAsDouble("foo1")); + EXPECT_EQ(2, trace_event->GetKnownArgAsDouble("foo2")); +} + +TEST_F(JSONTraceExporterTest, TestEventWithDoubleArgs) { + CreateJSONTraceExporter("foo"); + service()->WaitForTracingEnabled(); + StopAndFlush(); + + perfetto::protos::TracePacket trace_packet_proto; + auto* new_trace_event = + trace_packet_proto.mutable_chrome_events()->add_trace_events(); + SetTestPacketBasicData(new_trace_event); + + { + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name("foo1"); + new_arg->set_double_value(1.0); + } + + { + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name("foo2"); + new_arg->set_double_value(2.0); + } + + FinalizePacket(trace_packet_proto); + + service()->WaitForTracingDisabled(); + auto* trace_event = ValidateAndGetBasicTestPacket(); + + EXPECT_EQ(1.0, trace_event->GetKnownArgAsDouble("foo1")); + EXPECT_EQ(2.0, trace_event->GetKnownArgAsDouble("foo2")); +} + +TEST_F(JSONTraceExporterTest, TestEventWithStringArgs) { + CreateJSONTraceExporter("foo"); + service()->WaitForTracingEnabled(); + StopAndFlush(); + + perfetto::protos::TracePacket trace_packet_proto; + auto* new_trace_event = + trace_packet_proto.mutable_chrome_events()->add_trace_events(); + SetTestPacketBasicData(new_trace_event); + + { + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name("foo1"); + new_arg->set_string_value("bar1"); + } + + { + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name("foo2"); + new_arg->set_string_value("bar2"); + } + + FinalizePacket(trace_packet_proto); + + service()->WaitForTracingDisabled(); + auto* trace_event = ValidateAndGetBasicTestPacket(); + + EXPECT_EQ("bar1", trace_event->GetKnownArgAsString("foo1")); + EXPECT_EQ("bar2", trace_event->GetKnownArgAsString("foo2")); +} + +TEST_F(JSONTraceExporterTest, TestEventWithPointerArgs) { + CreateJSONTraceExporter("foo"); + service()->WaitForTracingEnabled(); + StopAndFlush(); + + perfetto::protos::TracePacket trace_packet_proto; + auto* new_trace_event = + trace_packet_proto.mutable_chrome_events()->add_trace_events(); + SetTestPacketBasicData(new_trace_event); + + { + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name("foo1"); + new_arg->set_pointer_value(0x1); + } + + { + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name("foo2"); + new_arg->set_pointer_value(0x2); + } + + FinalizePacket(trace_packet_proto); + + service()->WaitForTracingDisabled(); + auto* trace_event = ValidateAndGetBasicTestPacket(); + + EXPECT_EQ("0x1", trace_event->GetKnownArgAsString("foo1")); + EXPECT_EQ("0x2", trace_event->GetKnownArgAsString("foo2")); } } // namespace tracing
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc index a1f2ce6..9470d9b 100644 --- a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc +++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
@@ -76,6 +76,48 @@ char phase = trace_event.phase(); new_trace_event->set_phase(phase); + + for (int i = 0; + i < base::trace_event::kTraceMaxNumArgs && trace_event.arg_name(i); + ++i) { + // TODO(oysteine): Support ConvertableToTraceFormat serialized into a JSON + // string. + auto type = trace_event.arg_type(i); + if (type == TRACE_VALUE_TYPE_CONVERTABLE) { + continue; + } + + auto* new_arg = new_trace_event->add_args(); + new_arg->set_name(trace_event.arg_name(i)); + + auto& value = trace_event.arg_value(i); + switch (type) { + case TRACE_VALUE_TYPE_BOOL: + new_arg->set_bool_value(value.as_bool); + break; + case TRACE_VALUE_TYPE_UINT: + new_arg->set_uint_value(value.as_uint); + break; + case TRACE_VALUE_TYPE_INT: + new_arg->set_int_value(value.as_int); + break; + case TRACE_VALUE_TYPE_DOUBLE: + new_arg->set_double_value(value.as_double); + break; + case TRACE_VALUE_TYPE_POINTER: + new_arg->set_pointer_value(static_cast<uint64_t>( + reinterpret_cast<uintptr_t>(value.as_pointer))); + break; + case TRACE_VALUE_TYPE_STRING: + case TRACE_VALUE_TYPE_COPY_STRING: + new_arg->set_string_value(value.as_string ? value.as_string : "NULL"); + break; + default: + NOTREACHED() << "Don't know how to print this value"; + break; + } + } + if (phase == TRACE_EVENT_PHASE_COMPLETE) { int64_t duration = trace_event.duration().InMicroseconds(); if (duration != -1) { @@ -121,6 +163,20 @@ std::unique_ptr<perfetto::TraceWriter> trace_writer_; }; +namespace { + +base::ThreadLocalStorage::Slot* ThreadLocalEventSinkSlot() { + static base::NoDestructor<base::ThreadLocalStorage::Slot> + thread_local_event_sink_tls([](void* event_sink) { + delete static_cast<TraceEventDataSource::ThreadLocalEventSink*>( + event_sink); + }); + + return thread_local_event_sink_tls.get(); +} + +} // namespace + // static TraceEventDataSource* TraceEventDataSource::GetInstance() { static base::NoDestructor<TraceEventDataSource> instance; @@ -186,17 +242,12 @@ // static void TraceEventDataSource::OnAddTraceEvent(const TraceEvent& trace_event) { - static base::NoDestructor<base::ThreadLocalStorage::Slot> - thread_local_event_sink_tls([](void* event_sink) { - delete static_cast<ThreadLocalEventSink*>(event_sink); - }); - - auto* thread_local_event_sink = static_cast<ThreadLocalEventSink*>( - thread_local_event_sink_tls.get()->Get()); + auto* thread_local_event_sink = + static_cast<ThreadLocalEventSink*>(ThreadLocalEventSinkSlot()->Get()); if (!thread_local_event_sink) { thread_local_event_sink = GetInstance()->CreateThreadLocalEventSink(); - thread_local_event_sink_tls.get()->Set(thread_local_event_sink); + ThreadLocalEventSinkSlot()->Set(thread_local_event_sink); } if (thread_local_event_sink) { @@ -204,4 +255,14 @@ } } +// static +void TraceEventDataSource::ResetCurrentThreadForTesting() { + ThreadLocalEventSink* thread_local_event_sink = + static_cast<ThreadLocalEventSink*>(ThreadLocalEventSinkSlot()->Get()); + if (thread_local_event_sink) { + delete thread_local_event_sink; + ThreadLocalEventSinkSlot()->Set(nullptr); + } +} + } // namespace tracing
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.h b/services/tracing/public/cpp/perfetto/trace_event_data_source.h index 9871eeb3..4e0741a 100644 --- a/services/tracing/public/cpp/perfetto/trace_event_data_source.h +++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.h
@@ -27,6 +27,9 @@ static TraceEventDataSource* GetInstance(); + // Deletes the TraceWriter for the current thread, if any. + static void ResetCurrentThreadForTesting(); + // The ProducerClient is responsible for calling RequestStop // which will clear the stored pointer to it, before it // gets destroyed. ProducerClient::CreateTraceWriter can be
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc index bb1c99e..02de2dc 100644 --- a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc +++ b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
@@ -37,11 +37,14 @@ std::unique_ptr<perfetto::protos::TracePacket> GetPreviousPacket() { uint32_t message_size = trace_packet_.Finalize(); + // GetNewBuffer() in ScatteredStreamWriterNullDelegate doesn't + // actually return a new buffer, but rather lets us access the buffer + // buffer already used by protozero to write the TracePacket into. protozero::ContiguousMemoryRange buffer = delegate_.GetNewBuffer(); EXPECT_GE(buffer.size(), message_size); auto proto = std::make_unique<perfetto::protos::TracePacket>(); - proto->ParseFromArray(buffer.begin, buffer.size()); + EXPECT_TRUE(proto->ParseFromArray(buffer.begin, message_size)); return proto; } @@ -101,13 +104,19 @@ wait_for_tracelog_flush.Run(); + // As MockTraceWriter keeps a pointer to our MockProducerClient, + // we need to make sure to clean it up from TLS. This means + // these tests can't use a multithreaded task environment that + // might add trace events from other threads, as those might + // use old TraceWriters writing into invalid memory. + TraceEventDataSource::GetInstance()->ResetCurrentThreadForTesting(); producer_client_.reset(); message_loop_.reset(); } void CreateTraceEventDataSource() { auto data_source_config = mojom::DataSourceConfig::New(); - TraceEventDataSource::GetInstance()->StartTracing(producer_client_.get(), + TraceEventDataSource::GetInstance()->StartTracing(producer_client(), *data_source_config); } @@ -166,6 +175,107 @@ EXPECT_EQ(TRACE_EVENT_PHASE_INSTANT, trace_event.phase()); } +TEST_F(TraceEventDataSourceTest, EventWithStringArgs) { + CreateTraceEventDataSource(); + + TRACE_EVENT_INSTANT2("foo", "bar", TRACE_EVENT_SCOPE_THREAD, "arg1_name", + "arg1_val", "arg2_name", "arg2_val"); + + auto trace_events = producer_client()->GetChromeTraceEvents(); + EXPECT_EQ(trace_events.size(), 1); + + auto trace_args = trace_events[0].args(); + EXPECT_EQ(trace_args.size(), 2); + + EXPECT_EQ("arg1_name", trace_args[0].name()); + EXPECT_EQ("arg1_val", trace_args[0].string_value()); + EXPECT_EQ("arg2_name", trace_args[1].name()); + EXPECT_EQ("arg2_val", trace_args[1].string_value()); +} + +TEST_F(TraceEventDataSourceTest, EventWithUIntArgs) { + CreateTraceEventDataSource(); + + TRACE_EVENT_INSTANT2("foo", "bar", TRACE_EVENT_SCOPE_THREAD, "foo", 42u, + "bar", 4242u); + + auto trace_events = producer_client()->GetChromeTraceEvents(); + EXPECT_EQ(trace_events.size(), 1); + + auto trace_args = trace_events[0].args(); + EXPECT_EQ(trace_args.size(), 2); + + EXPECT_EQ(42u, trace_args[0].uint_value()); + EXPECT_EQ(4242u, trace_args[1].uint_value()); +} + +TEST_F(TraceEventDataSourceTest, EventWithIntArgs) { + CreateTraceEventDataSource(); + + TRACE_EVENT_INSTANT2("foo", "bar", TRACE_EVENT_SCOPE_THREAD, "foo", 42, "bar", + 4242); + + auto trace_events = producer_client()->GetChromeTraceEvents(); + EXPECT_EQ(trace_events.size(), 1); + + auto trace_args = trace_events[0].args(); + EXPECT_EQ(trace_args.size(), 2); + + EXPECT_EQ(42, trace_args[0].int_value()); + EXPECT_EQ(4242, trace_args[1].int_value()); +} + +TEST_F(TraceEventDataSourceTest, EventWithBoolArgs) { + CreateTraceEventDataSource(); + + TRACE_EVENT_INSTANT2("foo", "bar", TRACE_EVENT_SCOPE_THREAD, "foo", true, + "bar", false); + + auto trace_events = producer_client()->GetChromeTraceEvents(); + EXPECT_EQ(trace_events.size(), 1); + + auto trace_args = trace_events[0].args(); + EXPECT_EQ(trace_args.size(), 2); + + EXPECT_TRUE(trace_args[0].has_bool_value()); + EXPECT_EQ(true, trace_args[0].bool_value()); + EXPECT_TRUE(trace_args[1].has_bool_value()); + EXPECT_EQ(false, trace_args[1].bool_value()); +} + +TEST_F(TraceEventDataSourceTest, EventWithDoubleArgs) { + CreateTraceEventDataSource(); + + TRACE_EVENT_INSTANT2("foo", "bar", TRACE_EVENT_SCOPE_THREAD, "foo", 42.42, + "bar", 4242.42); + + auto trace_events = producer_client()->GetChromeTraceEvents(); + EXPECT_EQ(trace_events.size(), 1); + + auto trace_args = trace_events[0].args(); + EXPECT_EQ(trace_args.size(), 2); + + EXPECT_EQ(42.42, trace_args[0].double_value()); + EXPECT_EQ(4242.42, trace_args[1].double_value()); +} + +TEST_F(TraceEventDataSourceTest, EventWithPointerArgs) { + CreateTraceEventDataSource(); + + TRACE_EVENT_INSTANT2("foo", "bar", TRACE_EVENT_SCOPE_THREAD, "foo", + reinterpret_cast<void*>(0xBEEF), "bar", + reinterpret_cast<void*>(0xF00D)); + + auto trace_events = producer_client()->GetChromeTraceEvents(); + EXPECT_EQ(trace_events.size(), 1); + + auto trace_args = trace_events[0].args(); + EXPECT_EQ(trace_args.size(), 2); + + EXPECT_EQ(static_cast<uintptr_t>(0xBEEF), trace_args[0].pointer_value()); + EXPECT_EQ(static_cast<uintptr_t>(0xF00D), trace_args[1].pointer_value()); +} + } // namespace } // namespace tracing
diff --git a/testing/buildbot/filters/fuchsia.net_unittests.filter b/testing/buildbot/filters/fuchsia.net_unittests.filter index 433c7bd..47c72ba 100644 --- a/testing/buildbot/filters/fuchsia.net_unittests.filter +++ b/testing/buildbot/filters/fuchsia.net_unittests.filter
@@ -1,9 +1,5 @@ # TODO(fuchsia): Fix these tests and remove the filter. https://crbug.com/731302 . -# Timeout on the bots exceeding 45s on the bots (apperently due to slow IO). --DiskCacheTest.BlockFiles_Grow --DiskCacheBackendTest.SimpleCacheDeleteQuickly - # Exceeds FD limit, ZX-1127. -PacFileFetcherImplTest.Priority
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 76dadf2..2fdaeb4 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -33,16 +33,16 @@ crbug.com/636993 external/wpt/fullscreen/api/element-ready-check-not-allowed-cross-origin-manual.sub.html [ Crash ] crbug.com/636993 fast/block/child-not-removed-from-parent-lineboxes-crash.html [ Crash ] crbug.com/636993 fast/block/float/add-float-back-to-anonymous-block-previous.html [ Crash ] +crbug.com/636993 fast/css-generated-content/dynamic-apply-after-for-inline.html [ Crash ] crbug.com/636993 fast/css/css-property-setter-getter.html [ Crash ] crbug.com/636993 fast/css/first-letter-removed-added.html [ Crash ] -crbug.com/636993 fast/css/relative-position-replaced-in-table-display-crash.html [ Crash ] crbug.com/591099 fast/css/getComputedStyle/getComputedStyle-resolved-values.html [ Timeout Crash ] -crbug.com/636993 fast/css-generated-content/dynamic-apply-after-for-inline.html [ Crash ] +crbug.com/636993 fast/css/relative-position-replaced-in-table-display-crash.html [ Crash ] +crbug.com/636993 fast/dynamic/unicode-bidi.html [ Failure ] crbug.com/594672 fast/events/updateLayoutForHitTest.html [ Pass Failure Crash ] crbug.com/636993 fast/inline/inline-empty-block-continuation-remove.html [ Crash ] crbug.com/636993 fast/overflow/scroll-div-hide-show.html [ Crash ] crbug.com/594672 virtual/mouseevent_fractional/fast/events/updateLayoutForHitTest.html [ Pass Failure Crash ] -crbug.com/636993 fast/dynamic/unicode-bidi.html [ Failure ] # New passes crbug.com/626703 external/wpt/css/css-ui/text-overflow-021.html [ Failure ] @@ -77,7 +77,7 @@ crbug.com/714962 accessibility/background-color.html [ Failure ] crbug.com/714962 accessibility/bounds-calc.html [ Failure ] crbug.com/591099 accessibility/canvas-fallback-content-2.html [ Timeout ] -crbug.com/591099 accessibility/computed-name.html [ Timeout ] +crbug.com/591099 accessibility/computed-name.html [ Pass Timeout ] crbug.com/591099 accessibility/computed-role.html [ Pass Timeout ] crbug.com/714962 accessibility/css-first-letter-children.html [ Failure ] crbug.com/591099 accessibility/css-generated-content.html [ Failure ] @@ -118,11 +118,11 @@ crbug.com/591099 animations/animation-ready-reject-script-forbidden.html [ Timeout ] crbug.com/591099 animations/cross-fade-list-style-image.html [ Failure ] crbug.com/591099 animations/interpolation/backdrop-filter-interpolation.html [ Timeout ] -crbug.com/591099 animations/interpolation/line-height-interpolation.html [ Pass Timeout ] +crbug.com/591099 animations/interpolation/line-height-interpolation.html [ Timeout ] crbug.com/591099 animations/interpolation/svg-stroke-dasharray-interpolation.html [ Timeout ] crbug.com/591099 animations/interpolation/webkit-clip-path-interpolation.html [ Pass Timeout ] crbug.com/591099 animations/rotate-transform-equivalent.html [ Failure ] -crbug.com/591099 animations/timing/timing-model.html [ Timeout ] +crbug.com/591099 animations/timing/timing-model.html [ Pass Timeout ] crbug.com/714962 compositing/background-color/view-blending-base-background.html [ Failure ] crbug.com/591099 compositing/draws-content/canvas-background-layer.html [ Failure ] crbug.com/591099 compositing/draws-content/webgl-background-layer.html [ Failure ] @@ -230,22 +230,22 @@ crbug.com/591099 editing/selection/shift-click.html [ Failure ] crbug.com/591099 editing/selection/skip-over-contenteditable.html [ Failure ] crbug.com/591099 editing/selection/transformed-selection-rects.html [ Failure ] -crbug.com/591099 editing/text-iterator/findString.html [ Timeout ] +crbug.com/591099 editing/text-iterator/findString.html [ Pass Timeout ] crbug.com/591099 external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_11.html [ Pass ] crbug.com/591099 external/wpt/WebCryptoAPI/derive_bits_keys/hkdf.https.worker.html [ Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/derive_bits_keys/test_hkdf.https.html [ Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures.worker.html [ Timeout ] -crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_AES-CBC.https.worker.html [ Timeout ] +crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_AES-CBC.https.worker.html [ Pass Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_AES-CBC.worker.html [ Timeout ] -crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_AES-CTR.https.worker.html [ Timeout ] +crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_AES-CTR.https.worker.html [ Pass Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_AES-CTR.worker.html [ Timeout ] -crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_AES-GCM.https.worker.html [ Timeout ] +crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_AES-GCM.https.worker.html [ Pass Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_AES-GCM.worker.html [ Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_AES-KW.worker.html [ Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_ECDH.worker.html [ Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_ECDSA.worker.html [ Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_HMAC.worker.html [ Timeout ] -crbug.com/714962 external/wpt/WebCryptoAPI/generateKey/failures_RSA-OAEP.https.worker.html [ Timeout ] +crbug.com/714962 external/wpt/WebCryptoAPI/generateKey/failures_RSA-OAEP.https.worker.html [ Pass Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_RSA-OAEP.worker.html [ Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_RSA-PSS.worker.html [ Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.html [ Timeout ] @@ -256,14 +256,10 @@ crbug.com/714962 external/wpt/WebCryptoAPI/import_export/test_rsa_importKey.https.html [ Pass Timeout ] crbug.com/591099 external/wpt/acid/acid3/numbered-tests.html [ Crash ] crbug.com/591099 external/wpt/acid/acid3/test.html [ Crash ] -crbug.com/591099 external/wpt/content-security-policy/inside-worker/dedicated-inheritance.html [ Failure Pass ] -crbug.com/591099 external/wpt/content-security-policy/reporting/report-original-url.sub.html [ Pass Timeout ] -crbug.com/591099 external/wpt/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-image-from-script.sub.html [ Pass Timeout ] crbug.com/591099 external/wpt/credential-management/federatedcredential-framed-get.sub.https.html [ Pass ] crbug.com/591099 external/wpt/credential-management/passwordcredential-framed-get.sub.https.html [ Pass ] -crbug.com/591099 external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-001r.xht [ Failure Pass ] crbug.com/635619 external/wpt/css/CSS2/floats/floats-in-table-caption-001.html [ Failure ] -crbug.com/714962 external/wpt/css/CSS2/linebox/vertical-align-baseline-005a.xht [ Failure Pass ] +crbug.com/714962 external/wpt/css/CSS2/linebox/vertical-align-baseline-005a.xht [ Failure ] crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-insert-001e.xht [ Pass ] crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-insert-001h.xht [ Pass ] crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-insert-002e.xht [ Pass ] @@ -275,23 +271,15 @@ crbug.com/714962 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ] crbug.com/714962 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-image-5.html [ Failure ] crbug.com/591099 external/wpt/css/css-backgrounds/box-shadow-syntax-001.xht [ Failure ] -crbug.com/591099 external/wpt/css/css-color/t425-hsla-onscreen-multiple-boxes-c.xht [ Pass ] -crbug.com/591099 external/wpt/css/css-contain/quote-scoping-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-display/display-contents-details.html [ Crash ] crbug.com/591099 external/wpt/css/css-display/display-contents-dynamic-list-001-inline.html [ Failure ] crbug.com/591099 external/wpt/css/css-display/display-contents-dynamic-list-001-none.html [ Failure ] crbug.com/591099 external/wpt/css/css-display/display-contents-dynamic-table-001-inline.html [ Failure ] crbug.com/591099 external/wpt/css/css-display/display-contents-list-001.html [ Failure ] -crbug.com/591099 external/wpt/css/css-fill-stroke/paint-order-001.tentative.html [ Pass ] -crbug.com/591099 external/wpt/css/css-flexbox/anonymous-flex-item-005.html [ Pass ] -crbug.com/591099 external/wpt/css/css-flexbox/flex-minimum-width-flex-items-008.xht [ Pass ] crbug.com/591099 external/wpt/css/css-flexbox/percentage-heights-001.html [ Failure ] crbug.com/591099 external/wpt/css/css-flexbox/percentage-heights-003.html [ Pass ] crbug.com/714962 external/wpt/css/css-fonts/font-features-across-space-1.html [ Pass ] crbug.com/714962 external/wpt/css/css-fonts/font-features-across-space-3.html [ Pass ] -crbug.com/591099 external/wpt/css/css-fonts/font-variant-05.xht [ Pass ] -crbug.com/591099 external/wpt/css/css-fonts/font-variant-06.xht [ Pass ] -crbug.com/591099 external/wpt/css/css-fonts/font-variant-alternates-16.html [ Pass ] crbug.com/591099 external/wpt/css/css-fonts/font-variant-ligatures-11.html [ Pass ] crbug.com/591099 external/wpt/css/css-fonts/matching/fixed-stretch-style-over-weight.html [ Pass ] crbug.com/591099 external/wpt/css/css-fonts/matching/stretch-distance-over-weight-distance.html [ Pass ] @@ -306,17 +294,7 @@ crbug.com/591099 external/wpt/css/css-grid/alignment/self-baseline/grid-self-baseline-changes-grid-area-size-010.html [ Failure ] crbug.com/591099 external/wpt/css/css-grid/alignment/self-baseline/grid-self-baseline-changes-grid-area-size-011.html [ Failure ] crbug.com/591099 external/wpt/css/css-grid/alignment/self-baseline/grid-self-baseline-changes-grid-area-size-012.html [ Failure ] -crbug.com/591099 external/wpt/css/css-layout-api/constraints-fixed-inline-size-absolute-left-right.https.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-layout-api/style-map.https.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-multicol/multicol-count-computed-003.xht [ Pass ] -crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-004.xht [ Pass ] -crbug.com/591099 external/wpt/css/css-overflow/logical-overflow-001.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-paint-api/geometry-border-image-001.https.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-paint-api/paint-function-arguments.https.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-paint-api/parse-input-arguments-003.https.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-position/position-relative-table-tr-top-absolute-child.html [ Pass ] crbug.com/591099 external/wpt/css/css-position/position-sticky-writing-modes.html [ Failure ] -crbug.com/591099 external/wpt/css/css-pseudo/first-letter-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-rhythm/ [ Skip ] crbug.com/591099 external/wpt/css/css-scroll-anchoring/clipped-scrollers-skipped.html [ Failure ] crbug.com/591099 external/wpt/css/css-scroll-anchoring/opt-out.html [ Failure ] @@ -326,13 +304,13 @@ crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-box/shape-outside-box-002.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-box/shape-outside-box-003.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-box/shape-outside-box-004.html [ Failure ] -crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-box/shape-outside-box-006.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-box/shape-outside-box-006.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-box/shape-outside-box-007.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-box/shape-outside-box-008.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-001.html [ Failure ] -crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-002.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-002.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-003.html [ Failure ] -crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-004.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-004.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-001.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-002.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-003.html [ Failure ] @@ -379,7 +357,7 @@ crbug.com/591099 external/wpt/css/css-shapes/shape-outside/supported-shapes/circle/shape-outside-circle-030.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/supported-shapes/circle/shape-outside-circle-031.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/supported-shapes/ellipse/shape-outside-ellipse-013.html [ Failure ] -crbug.com/591099 external/wpt/css/css-shapes/shape-outside/supported-shapes/ellipse/shape-outside-ellipse-014.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-shapes/shape-outside/supported-shapes/ellipse/shape-outside-ellipse-014.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/supported-shapes/ellipse/shape-outside-ellipse-015.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/supported-shapes/ellipse/shape-outside-ellipse-016.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/supported-shapes/ellipse/shape-outside-ellipse-017.html [ Failure ] @@ -419,10 +397,10 @@ crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-001.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-002.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-003.html [ Failure ] -crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-004.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-004.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-005.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-006.html [ Failure ] -crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-007.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-007.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-008.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-010.html [ Failure ] crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-011.html [ Failure ] @@ -437,14 +415,12 @@ crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-non-replaced-001.html [ Failure ] crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-non-replaced-003.html [ Failure ] crbug.com/591099 external/wpt/css/css-tables/height-distribution/percentage-sizing-of-table-cell-children.html [ Failure ] -crbug.com/591099 external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row.html [ Failure Pass ] crbug.com/591099 external/wpt/css/css-tables/table-model-fixup-2.html [ Failure ] crbug.com/591099 external/wpt/css/css-tables/width-distribution/td-with-subpixel-padding-vertical-rl.html [ Failure ] -crbug.com/591099 external/wpt/css/css-text-decor/text-decoration-serialization.tentative.html [ Failure Pass ] crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-color-001.xht [ Failure ] crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-position-above-left-001.xht [ Failure ] crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-position-above-left-002.xht [ Failure ] -crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-position-above-right-001.xht [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-position-above-right-001.xht [ Failure ] crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-position-above-right-002.xht [ Failure ] crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-position-below-left-001.xht [ Failure ] crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-position-below-left-002.xht [ Failure ] @@ -460,7 +436,7 @@ crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-style-filled-001.xht [ Failure ] crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-style-open-001.xht [ Failure ] crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-style-shape-001.xht [ Failure ] -crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-style-string-001.xht [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-style-string-001.xht [ Failure ] crbug.com/591099 external/wpt/css/css-text/i18n/css3-text-line-break-jazh-136.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/i18n/css3-text-line-break-jazh-142.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/i18n/css3-text-line-break-opclns-255.html [ Pass ] @@ -484,22 +460,10 @@ crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Pass ] crbug.com/714962 external/wpt/css/css-transforms/transform-abspos-006.html [ Failure ] crbug.com/714962 external/wpt/css/css-transforms/transform-abspos-007.html [ Failure ] -crbug.com/591099 external/wpt/css/css-transforms/transform-generated-002.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-transforms/transform-origin-name-002.html [ Failure Pass ] crbug.com/591099 external/wpt/css/css-transforms/transform-transformed-tr-percent-height-child.html [ Failure ] crbug.com/591099 external/wpt/css/css-transforms/transform3d-perspective-008.html [ Pass ] -crbug.com/591099 external/wpt/css/css-transforms/transform3d-rotatex-transformorigin-001.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-transforms/transform3d-scale-001.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-transitions/before-load-001.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-transitions/transition-timing-function-001.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-typed-om/the-stylepropertymap/properties/line-break.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-typed-om/the-stylepropertymap/properties/text-decoration-line.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-typed-om/the-stylepropertymap/properties/text-transform.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-ui/box-sizing-018.html [ Pass ] crbug.com/591099 external/wpt/css/css-ui/text-overflow-010.html [ Pass ] crbug.com/591099 external/wpt/css/css-ui/text-overflow-015.html [ Failure ] -crbug.com/591099 external/wpt/css/css-ui/text-overflow-023.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/css-variables/variable-definition.html [ Failure Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vlr-003.xht [ Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vlr-005.xht [ Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vlr-011.xht [ Pass ] @@ -580,9 +544,8 @@ crbug.com/591099 external/wpt/css/css-writing-modes/available-size-001.html [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/available-size-002.html [ Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/available-size-010.html [ Pass ] -crbug.com/591099 external/wpt/css/css-writing-modes/available-size-011.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/available-size-011.html [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/available-size-012.html [ Failure ] -crbug.com/591099 external/wpt/css/css-writing-modes/available-size-015.html [ Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/available-size-017.html [ Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/available-size-018.html [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/baseline-inline-non-replaced-004.xht [ Failure ] @@ -594,7 +557,7 @@ crbug.com/591099 external/wpt/css/css-writing-modes/float-contiguous-vrl-002.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/float-contiguous-vrl-004.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/float-contiguous-vrl-006.xht [ Failure ] -crbug.com/591099 external/wpt/css/css-writing-modes/float-contiguous-vrl-008.xht [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/float-contiguous-vrl-008.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/float-vlr-013.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/float-vrl-002.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/float-vrl-004.xht [ Failure ] @@ -634,18 +597,18 @@ crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-020.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-021.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-023.xht [ Failure ] -crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-024.xht [ Failure Pass ] +crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-024.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-prct-htb-in-vrl-003.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-prct-htb-in-vrl-004.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-prct-htb-in-vrl-007.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-prct-htb-in-vrl-008.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/sizing-orthog-vrl-in-htb-013.xht [ Failure ] -crbug.com/591099 external/wpt/css/css-writing-modes/text-baseline-vlr-007.xht [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/text-baseline-vlr-007.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/text-baseline-vrl-006.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/text-combine-upright-decorations-001.html [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/text-combine-upright-layout-rules-001.html [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-016.xht [ Failure ] -crbug.com/591099 external/wpt/css/css-writing-modes/vertical-alignment-005.xht [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/vertical-alignment-005.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/vertical-alignment-007.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/vertical-alignment-vlr-023.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/vertical-alignment-vlr-025.xht [ Failure ] @@ -656,19 +619,14 @@ crbug.com/591099 external/wpt/css/css-writing-modes/wm-propagation-body-006.xht [ Failure ] crbug.com/591099 external/wpt/css/cssom-view/elementFromPoint-002.html [ Failure ] crbug.com/591099 external/wpt/css/cssom-view/elementFromPoint-003.html [ Failure ] -crbug.com/591099 external/wpt/css/cssom/getComputedStyle-detached-subtree.html [ Failure Pass ] crbug.com/591099 external/wpt/css/cssom/interfaces.html [ Pass Timeout ] crbug.com/591099 external/wpt/css/geometry/interfaces.worker.html [ Pass ] crbug.com/591099 external/wpt/css/selectors/focus-within-004.html [ Pass ] -crbug.com/591099 external/wpt/css/selectors/selection-image-001.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/descriptor-pad-invalid.html [ Pass ] -crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/name-case-sensitivity.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-001a.xhtml [ Failure ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-vert-001b.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-definite-sizes-002.html [ Failure ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-definite-sizes-004.html [ Failure ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003v.html [ Pass ] -crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006v.html [ Pass ] crbug.com/714962 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-items-as-stacking-contexts-002.html [ Failure ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-011.html [ Failure ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-012.html [ Failure ] @@ -677,10 +635,7 @@ crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/remove-from-split-inline-6.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/split-inner-inline-2.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-break-inside-001.html [ Failure ] -crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-004.html [ Pass ] -crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-006a.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-007.html [ Failure ] -crbug.com/591099 external/wpt/dom/events/Event-returnValue.html [ Failure Pass ] crbug.com/591099 external/wpt/dom/nodes/Element-classlist.html [ Timeout ] crbug.com/591099 external/wpt/dom/nodes/Element-matches.html [ Timeout ] crbug.com/591099 external/wpt/dom/nodes/Element-webkitMatchesSelector.html [ Timeout ] @@ -696,7 +651,6 @@ crbug.com/591099 external/wpt/dom/ranges/Range-mutations-dataChange.html [ Timeout ] crbug.com/591099 external/wpt/dom/ranges/Range-set.html [ Timeout ] crbug.com/591099 external/wpt/dom/ranges/Range-surroundContents.html [ Timeout ] -crbug.com/591099 external/wpt/domxpath/002.html [ Failure Pass ] crbug.com/591099 external/wpt/domxpath/xml_xpath_runner.html [ Pass Timeout ] crbug.com/591099 external/wpt/editing/run/backcolor.html [ Pass Timeout ] crbug.com/591099 external/wpt/editing/run/bold.html [ Timeout ] @@ -706,8 +660,8 @@ crbug.com/591099 external/wpt/editing/run/formatblock.html [ Timeout ] crbug.com/591099 external/wpt/editing/run/forwarddelete.html [ Timeout ] crbug.com/591099 external/wpt/editing/run/hilitecolor.html [ Timeout ] -crbug.com/591099 external/wpt/editing/run/indent.html [ Failure Timeout ] -crbug.com/591099 external/wpt/editing/run/inserthorizontalrule.html [ Timeout ] +crbug.com/591099 external/wpt/editing/run/indent.html [ Timeout ] +crbug.com/591099 external/wpt/editing/run/inserthorizontalrule.html [ Pass Timeout ] crbug.com/591099 external/wpt/editing/run/inserthtml.html [ Timeout ] crbug.com/591099 external/wpt/editing/run/insertlinebreak.html [ Timeout ] crbug.com/591099 external/wpt/editing/run/insertorderedlist.html [ Timeout ] @@ -725,7 +679,7 @@ crbug.com/591099 external/wpt/editing/run/strikethrough.html [ Timeout ] crbug.com/591099 external/wpt/editing/run/subscript.html [ Timeout ] crbug.com/591099 external/wpt/editing/run/superscript.html [ Pass Timeout ] -crbug.com/591099 external/wpt/editing/run/underline.html [ Failure Timeout ] +crbug.com/591099 external/wpt/editing/run/underline.html [ Timeout ] crbug.com/591099 external/wpt/encoding/api-invalid-label.html [ Timeout ] crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/euc-jp/eucjp-decode-cseucpkdfmtjapanese.html [ Timeout ] crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/euc-jp/eucjp-decode-x-euc-jp.html [ Timeout ] @@ -819,16 +773,10 @@ crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-href-errors-misc.html [ Timeout ] crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-href.html [ Timeout ] crbug.com/591099 external/wpt/encoding/textdecoder-fatal-single-byte.html [ Timeout ] -crbug.com/591099 external/wpt/fetch/api/idl.any.html [ Failure Pass ] -crbug.com/591099 external/wpt/fetch/http-cache/heuristic.html [ Failure Pass ] crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure Pass ] crbug.com/591099 external/wpt/html-media-capture/capture_audio_cancel-manual.html [ Failure ] crbug.com/591099 external/wpt/html-media-capture/capture_image_cancel-manual.html [ Failure ] crbug.com/591099 external/wpt/html-media-capture/capture_video_cancel-manual.html [ Failure ] -crbug.com/591099 external/wpt/html/browsers/history/the-location-interface/location-stringifier.html [ Failure Pass ] -crbug.com/591099 external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter.html [ Failure Pass ] -crbug.com/591099 external/wpt/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-03.html [ Failure Pass ] -crbug.com/591099 external/wpt/html/browsers/windows/browsing-context.html [ Failure Pass ] crbug.com/591099 external/wpt/html/browsers/windows/noreferrer-window-name.html [ Timeout ] crbug.com/591099 external/wpt/html/dom/documents/dom-tree-accessors/Document.currentScript.html [ Pass ] crbug.com/591099 external/wpt/html/dom/elements/the-innertext-idl-attribute/getter.html [ Failure ] @@ -841,45 +789,25 @@ crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/windows-1252.html [ Timeout ] crbug.com/591099 external/wpt/html/rendering/non-replaced-elements/flow-content-0/dialog.html [ Failure ] crbug.com/591099 external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/legend-block-formatting-context.html [ Failure ] -crbug.com/591099 external/wpt/html/rendering/non-replaced-elements/the-page/body-margin-2k.html [ Pass ] crbug.com/591099 external/wpt/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-auto.html [ Failure ] crbug.com/591099 external/wpt/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-percentage.html [ Failure ] crbug.com/591099 external/wpt/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.html [ Timeout ] -crbug.com/591099 external/wpt/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html [ Failure Pass ] -crbug.com/591099 external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-control.html [ Failure Pass ] crbug.com/591099 external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-non-snap-to-lines.html [ Failure ] -crbug.com/591099 external/wpt/html/semantics/embedded-content/the-img-element/current-pixel-density/basic.html [ Failure Pass ] -crbug.com/591099 external/wpt/html/semantics/embedded-content/the-object-element/object-in-object-fallback-2.html [ Failure Pass ] -crbug.com/591099 external/wpt/html/semantics/forms/autofocus/first-when-later-but-before.html [ Failure Pass ] -crbug.com/591099 external/wpt/html/semantics/forms/the-input-element/image-click-form-data.html [ Failure Pass ] -crbug.com/591099 external/wpt/html/semantics/forms/the-label-element/label-attributes.html [ Failure Pass ] -crbug.com/591099 external/wpt/html/semantics/forms/the-textarea-element/value-defaultValue-textContent.html [ Failure Pass ] crbug.com/591099 external/wpt/html/semantics/grouping-content/the-li-element/grouping-li-reftest-list-owner-menu.html [ Failure ] crbug.com/591099 external/wpt/html/semantics/grouping-content/the-li-element/grouping-li-reftest-list-owner-skip-no-boxes.html [ Failure ] crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html [ Failure ] crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-dialog-element/centering.html [ Crash ] -crbug.com/591099 external/wpt/html/semantics/scripting-1/the-script-element/execution-timing/084.html [ Failure Pass ] -crbug.com/591099 external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-descendant-frameset.html [ Failure Pass ] -crbug.com/591099 external/wpt/html/syntax/parsing/html5lib_innerHTML_foreign-fragment.html [ Failure Pass ] -crbug.com/591099 external/wpt/html/syntax/parsing/html5lib_tests11.html?run_type=write_single [ Failure Pass ] crbug.com/591099 external/wpt/html/syntax/parsing/named-character-references.html [ Timeout ] crbug.com/591099 external/wpt/html/the-xhtml-syntax/parsing-xhtml-documents/xhtml-mathml-dtd-entity-1.htm [ Pass Timeout ] crbug.com/591099 external/wpt/html/the-xhtml-syntax/parsing-xhtml-documents/xhtml-mathml-dtd-entity-4.htm [ Pass Timeout ] crbug.com/591099 external/wpt/html/the-xhtml-syntax/parsing-xhtml-documents/xhtml-mathml-dtd-entity-7.htm [ Pass Timeout ] -crbug.com/591099 external/wpt/html/webappapis/scripting/processing-model-2/compile-error-same-origin-with-hash.html [ Failure Pass ] crbug.com/591099 external/wpt/http/basic-auth-cache-test.html [ Timeout ] -crbug.com/591099 external/wpt/infrastructure/reftest/reftest_timeout.html [ Pass ] -crbug.com/591099 external/wpt/infrastructure/testdriver/send_keys.html [ Failure Pass ] crbug.com/591099 external/wpt/longtask-timing/longtask-in-sibling-iframe.html [ Pass Timeout ] crbug.com/591099 external/wpt/media-source/mediasource-getvideoplaybackquality.html [ Timeout ] -crbug.com/591099 external/wpt/mediacapture-streams/MediaDevices-IDL-all.html [ Failure Pass ] crbug.com/591099 external/wpt/mimesniff/mime-types/parsing.any.html [ Timeout ] crbug.com/591099 external/wpt/mimesniff/mime-types/parsing.any.worker.html [ Timeout ] -crbug.com/591099 external/wpt/mixed-content/video-tag/no-opt-in/same-host-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html [ Failure Pass ] crbug.com/591099 external/wpt/offscreen-canvas/fill-and-stroke-styles/2d.pattern.basic.nocontext.worker.html [ Crash ] crbug.com/591099 external/wpt/offscreen-canvas/the-offscreen-canvas/offscreencanvas.getcontext.worker.html [ Pass ] -crbug.com/591099 external/wpt/offscreen-canvas/the-offscreen-canvas/offscreencanvas.resize.html [ Failure Pass ] -crbug.com/591099 external/wpt/offscreen-canvas/the-offscreen-canvas/size.attributes.parse.trailingjunk.html [ Failure Pass ] crbug.com/591099 external/wpt/payment-request/payment-allowed-by-feature-policy.https.sub.html [ Pass ] crbug.com/591099 external/wpt/payment-request/payment-disabled-by-feature-policy.https.sub.html [ Pass ] crbug.com/591099 external/wpt/pointerevents/pointerevent_attributes_hoverable_pointers-manual.html [ Timeout ] @@ -895,8 +823,6 @@ crbug.com/591099 external/wpt/requestidlecallback/callback-invoked.html [ Pass ] crbug.com/591099 external/wpt/requestidlecallback/cancel-invoked.html [ Pass ] crbug.com/591099 external/wpt/requestidlecallback/idlharness.html [ Pass ] -crbug.com/591099 external/wpt/screen-orientation/orientation-reading.html [ Failure Pass ] -crbug.com/591099 external/wpt/secure-contexts/basic-dedicated-worker.html [ Failure Pass ] crbug.com/591099 external/wpt/selection/addRange-00.html [ Timeout ] crbug.com/591099 external/wpt/selection/addRange-04.html [ Timeout ] crbug.com/591099 external/wpt/selection/addRange-12.html [ Pass Timeout ] @@ -914,69 +840,39 @@ crbug.com/591099 external/wpt/selection/selectAllChildren.html [ Timeout ] crbug.com/591099 external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/update.https.html [ Failure Pass ] crbug.com/591099 external/wpt/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html [ Failure ] -crbug.com/591099 external/wpt/speech-api/SpeechSynthesis-speak-ownership.html [ Failure Pass ] -crbug.com/591099 external/wpt/streams/readable-byte-streams/properties.dedicatedworker.html [ Failure Pass ] -crbug.com/591099 external/wpt/streams/readable-byte-streams/properties.html [ Failure Pass ] -crbug.com/591099 external/wpt/streams/transform-streams/properties.dedicatedworker.html [ Failure Pass ] crbug.com/591099 external/wpt/svg/interfaces.html [ Timeout ] crbug.com/591099 external/wpt/svg/linking/reftests/href-filter-element.html [ Failure ] -crbug.com/591099 external/wpt/url/a-element-xhtml.xhtml [ Failure Pass ] -crbug.com/591099 external/wpt/url/interfaces.any.html [ Failure Pass ] crbug.com/591099 external/wpt/url/url-setters.html [ Pass Timeout ] crbug.com/591099 external/wpt/wasm/wasm_local_iframe_test.html [ Failure ] -crbug.com/591099 external/wpt/web-animations/animation-model/animation-types/addition-per-property.html [ Failure Pass ] crbug.com/591099 external/wpt/web-animations/animation-model/animation-types/interpolation-per-property.html [ Timeout ] -crbug.com/591099 external/wpt/web-animations/timing-model/animations/setting-the-timeline-of-an-animation.html [ Failure Pass ] crbug.com/591099 external/wpt/webaudio/idlharness.https.html [ Timeout ] crbug.com/591099 external/wpt/webmessaging/broadcastchannel/sandbox.html [ Failure ] -crbug.com/591099 external/wpt/webrtc/RTCConfiguration-iceCandidatePoolSize.html [ Failure Pass ] -crbug.com/591099 external/wpt/webrtc/RTCPeerConnectionIceEvent-constructor.html [ Failure Pass ] -crbug.com/591099 external/wpt/webrtc/RTCRtpParameters-encodings.html [ Failure Pass ] crbug.com/591099 external/wpt/webrtc/interfaces.html [ Pass Timeout ] -crbug.com/591099 external/wpt/websockets/unload-a-document/004.html [ Failure Pass ] +crbug.com/591099 external/wpt/websockets/constructor/014.html?wss [ Pass Timeout ] +crbug.com/591099 external/wpt/websockets/keeping-connection-open/001.html?wss [ Pass Timeout ] crbug.com/591099 external/wpt/webstorage/storage_setitem.html [ Pass Timeout ] crbug.com/591099 external/wpt/webvr/idlharness.https.html [ Pass ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html [ Failure ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up.html [ Failure ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/align_end.html [ Pass ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50.html [ Pass ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby.html [ Failure ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused.html [ Pass ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely.html [ Failure ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp.html [ Failure ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url.html [ Pass ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties.html [ Failure ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand.html [ Failure ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element.html [ Pass ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties.html [ Failure Pass ] +crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties.html [ Failure ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand.html [ Failure ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace.html [ Pass ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow.html [ Pass ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped.html [ Pass ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector.html [ Pass ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties.html [ Failure ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand.html [ Failure ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped.html [ Pass ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla.html [ Pass ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties.html [ Failure ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand.html [ Failure ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element.html [ Pass ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties.html [ Failure ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand.html [ Failure ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp.html [ Pass ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color.html [ Pass ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties.html [ Failure ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand.html [ Failure ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand.html [ Pass ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector.html [ Pass ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties.html [ Failure ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand.html [ Failure ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace.html [ Pass ] -crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/size_50.html [ Pass ] crbug.com/591099 external/wpt/workers/Worker_terminate_event_queue.htm [ Timeout ] -crbug.com/591099 external/wpt/workers/interfaces.worker.html [ Failure Pass ] crbug.com/591099 external/wpt/xhr/send-authentication-prompt-2-manual.htm [ Failure ] -crbug.com/591099 external/wpt/xhr/send-response-event-order.htm [ Failure Pass ] crbug.com/591099 fast/backgrounds/background-clip-text.html [ Failure ] crbug.com/591099 fast/backgrounds/background-leakage-transforms.html [ Failure ] crbug.com/591099 fast/backgrounds/border-radius-split-background-image.html [ Failure ] @@ -1042,7 +938,7 @@ crbug.com/591099 fast/css-grid-layout/flex-and-minmax-content-resolution-columns.html [ Failure ] crbug.com/591099 fast/css-grid-layout/grid-align-baseline-vertical.html [ Failure ] crbug.com/591099 fast/css-grid-layout/grid-baseline-margins.html [ Pass ] -crbug.com/591099 fast/css-grid-layout/grid-columns-rows-get-set-multiple.html [ Timeout ] +crbug.com/591099 fast/css-grid-layout/grid-columns-rows-get-set-multiple.html [ Pass Timeout ] crbug.com/591099 fast/css-grid-layout/grid-columns-rows-get-set.html [ Timeout ] crbug.com/591099 fast/css-grid-layout/grid-item-column-row-get-set.html [ Pass Timeout ] crbug.com/591099 fast/css-grid-layout/grid-item-overflow.html [ Failure ] @@ -1113,7 +1009,7 @@ crbug.com/591099 fast/css/getComputedStyle/getComputedStyle-margin-percentage.html [ Failure ] crbug.com/714962 fast/css/hover-pseudo-element-quirks.html [ Failure ] crbug.com/591099 fast/css/import_with_baseurl.html [ Failure Pass ] -crbug.com/591099 fast/css/large-numbers.html [ Timeout ] +crbug.com/591099 fast/css/large-numbers.html [ Pass Timeout ] crbug.com/591099 fast/css/margin-top-bottom-dynamic.html [ Failure ] crbug.com/591099 fast/css/negative-text-indent-in-inline-block.html [ Failure ] crbug.com/591099 fast/css/outline-narrowLine.html [ Failure ] @@ -1152,7 +1048,7 @@ crbug.com/591099 fast/dom/HTMLAreaElement/area-download.html [ Failure ] crbug.com/591099 fast/dom/MutationObserver/observe-attributes.html [ Pass Timeout ] crbug.com/714962 fast/dom/Range/getBoundingClientRect-linebreak-character.html [ Failure ] -crbug.com/591099 fast/dom/Window/property-access-on-cached-window-after-frame-navigated.html [ Timeout ] +crbug.com/591099 fast/dom/Window/property-access-on-cached-window-after-frame-navigated.html [ Pass Timeout ] crbug.com/591099 fast/dom/Window/window-lookup-precedence.html [ Timeout ] crbug.com/591099 fast/dom/Window/window-postmessage-clone-deep-array.html [ Failure ] crbug.com/591099 fast/dom/domstring-attribute-reflection.html [ Timeout ] @@ -1181,16 +1077,16 @@ crbug.com/591099 fast/events/keyboardevent-getModifierState.html [ Timeout ] crbug.com/714962 fast/events/middleClickAutoscroll-latching.html [ Pass Timeout ] crbug.com/714962 fast/events/mouse-down-on-pseudo-element-remove-crash.html [ Failure Pass ] -crbug.com/591099 fast/events/mouse-event-buttons-attribute.html [ Timeout ] +crbug.com/591099 fast/events/mouse-event-buttons-attribute.html [ Pass Timeout ] crbug.com/591099 fast/events/mouse-relative-position.html [ Failure ] crbug.com/591099 fast/events/mouseevent-getModifierState.html [ Timeout ] crbug.com/591099 fast/events/onclick-list-marker.html [ Failure ] crbug.com/591099 fast/events/pointerevents/mouse-pointer-capture-transition-events.html [ Timeout ] -crbug.com/591099 fast/events/pointerevents/mouse-pointer-capture.html [ Timeout ] +crbug.com/591099 fast/events/pointerevents/mouse-pointer-capture.html [ Pass Timeout ] crbug.com/591099 fast/events/pointerevents/mouse-pointer-event-properties.html [ Timeout ] -crbug.com/591099 fast/events/pointerevents/mouse-pointer-preventdefault.html [ Timeout ] +crbug.com/591099 fast/events/pointerevents/mouse-pointer-preventdefault.html [ Failure Pass Timeout ] crbug.com/591099 fast/events/pointerevents/multi-pointer-preventdefault.html [ Pass Timeout ] -crbug.com/591099 fast/events/pointerevents/touch-capture-in-iframe.html [ Timeout ] +crbug.com/591099 fast/events/pointerevents/touch-capture-in-iframe.html [ Pass Timeout ] crbug.com/591099 fast/events/pointerevents/touch-capture.html [ Timeout ] crbug.com/591099 fast/events/select-element.html [ Timeout ] crbug.com/591099 fast/events/sequential-focus-navigation-starting-point.html [ Failure ] @@ -1199,9 +1095,9 @@ crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ] crbug.com/591099 fast/forms/calendar-picker/calendar-picker-key-operations.html [ Pass Timeout ] crbug.com/714962 fast/forms/calendar-picker/calendar-picker-mouse-operations.html [ Failure ] -crbug.com/591099 fast/forms/calendar-picker/month-picker-key-operations.html [ Timeout ] +crbug.com/591099 fast/forms/calendar-picker/month-picker-key-operations.html [ Pass Timeout ] crbug.com/714962 fast/forms/calendar-picker/month-picker-mouse-operations.html [ Failure ] -crbug.com/591099 fast/forms/calendar-picker/week-picker-key-operations.html [ Timeout ] +crbug.com/591099 fast/forms/calendar-picker/week-picker-key-operations.html [ Pass Timeout ] crbug.com/714962 fast/forms/calendar-picker/week-picker-mouse-operations.html [ Failure ] crbug.com/591099 fast/forms/control-clip-overflow.html [ Failure ] crbug.com/591099 fast/forms/fieldset/fieldset-with-float.html [ Failure ] @@ -1521,7 +1417,7 @@ crbug.com/591099 fast/text/emphasis-complex.html [ Failure ] crbug.com/591099 fast/text/emphasis-ellipsis-complextext.html [ Failure ] crbug.com/591099 fast/text/emphasis-overlap.html [ Failure ] -crbug.com/591099 fast/text/find-kana.html [ Timeout ] +crbug.com/591099 fast/text/find-kana.html [ Pass Timeout ] crbug.com/591099 fast/text/hide-atomic-inlines-after-ellipsis.html [ Failure ] crbug.com/591099 fast/text/international/bidi-linebreak-002.html [ Failure ] crbug.com/591099 fast/text/international/bidi-linebreak-003.html [ Failure ] @@ -1638,7 +1534,7 @@ crbug.com/591099 http/tests/devtools/editor/text-editor-word-jumps.js [ Pass ] crbug.com/714962 http/tests/devtools/elements/edit/edit-dom-actions-4.js [ Crash ] crbug.com/591099 http/tests/devtools/elements/elements-inspect-iframe-from-different-domain.js [ Timeout ] -crbug.com/591099 http/tests/devtools/elements/elements-panel-rewrite-href.js [ Failure ] +crbug.com/591099 http/tests/devtools/elements/elements-panel-rewrite-href.js [ Failure Pass ] crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside-scroll.js [ Failure ] crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside.js [ Failure ] crbug.com/714962 http/tests/devtools/elements/inspect-pseudo-element.js [ Timeout ] @@ -1658,7 +1554,7 @@ crbug.com/591099 http/tests/images/restyle-decode-error.html [ Failure ] crbug.com/783102 http/tests/incremental/frame-focus-before-load.html [ Timeout ] crbug.com/591099 http/tests/incremental/slow-utf8-text.pl [ Pass Timeout ] -crbug.com/591099 http/tests/inspector-protocol/side-effects/evaluate-embedder-side-effect-free-attributes.js [ Timeout ] +crbug.com/591099 http/tests/inspector-protocol/side-effects/evaluate-embedder-side-effect-free-attributes.js [ Pass Timeout ] crbug.com/591099 http/tests/loading/nested_bad_objects.php [ Failure ] crbug.com/591099 http/tests/loading/preload-picture-nested.html [ Failure ] crbug.com/591099 http/tests/loading/preload-picture-sizes-2x.html [ Failure ] @@ -1693,11 +1589,11 @@ crbug.com/591099 inspector-protocol/accessibility/accessibility-ignoredNodes.js [ Failure Timeout ] crbug.com/714962 inspector-protocol/accessibility/accessibility-ignoredNodesModal.js [ Failure ] crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-img-figure.js [ Pass Timeout ] -crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-input-buttons.js [ Timeout ] +crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-input-buttons.js [ Pass Timeout ] crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-input.js [ Timeout Failure ] crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-labelledby.js [ Timeout Failure ] -crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-visiblity.js [ Timeout ] -crbug.com/591099 inspector-protocol/css/css-add-rule.js [ Timeout ] +crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-visiblity.js [ Pass Timeout ] +crbug.com/591099 inspector-protocol/css/css-add-rule.js [ Pass Timeout ] crbug.com/714962 inspector-protocol/css/css-get-platform-fonts.js [ Failure ] crbug.com/591099 inspector-protocol/css/css-set-style-text.js [ Pass Timeout ] crbug.com/714962 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-viewport.js [ Failure ] @@ -1708,6 +1604,7 @@ crbug.com/714962 intersection-observer/text-target.html [ Failure ] crbug.com/591099 media/audio-controls-rendering.html [ Failure ] crbug.com/591099 media/autoplay/document-user-activation.html [ Failure ] +crbug.com/591099 media/controls/modern/tap-to-hide-controls.html [ Failure ] crbug.com/591099 media/media-document-audio-repaint.html [ Failure ] crbug.com/591099 media/video-aspect-ratio.html [ Failure ] crbug.com/591099 media/video-colorspace-yuv420.html [ Failure ] @@ -1898,6 +1795,7 @@ crbug.com/591099 paint/invalidation/table/composited-table-background-initial-empty.html [ Failure ] crbug.com/591099 paint/invalidation/table/composited-table-row.html [ Failure ] crbug.com/591099 paint/invalidation/table/repaint-table-row-in-composited-document.html [ Failure ] +crbug.com/591099 paint/invalidation/table/replace-col.html [ Failure ] crbug.com/591099 paint/invalidation/table/resize-table-repaint-percent-size-cell.html [ Failure ] crbug.com/591099 paint/invalidation/table/resize-table-repaint-vertical-align-cell.html [ Failure ] crbug.com/591099 paint/invalidation/table/resize-table-row-repaint.html [ Failure ] @@ -1967,13 +1865,13 @@ crbug.com/591099 printing/webgl-repeated-printing.html [ Failure ] crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ] crbug.com/591099 scrollbars/scrollbar-miss-mousemove-disabled.html [ Failure ] -crbug.com/591099 shadow-dom/focus-navigation-with-delegatesFocus.html [ Timeout ] +crbug.com/591099 shadow-dom/focus-navigation-with-delegatesFocus.html [ Pass Timeout ] crbug.com/591099 shapedetection/detection-HTMLVideoElement.html [ Pass ] crbug.com/591099 storage/indexeddb/cursor-advance.html [ Pass Timeout ] crbug.com/591099 storage/indexeddb/cursor-continue-validity.html [ Timeout ] crbug.com/591099 storage/indexeddb/cursor-key-order.html [ Timeout ] crbug.com/591099 storage/indexeddb/cursor-update.html [ Pass Timeout ] -crbug.com/591099 storage/indexeddb/deleted-objects.html [ Timeout ] +crbug.com/591099 storage/indexeddb/deleted-objects.html [ Pass Timeout ] crbug.com/591099 storage/indexeddb/exceptions.html [ Timeout ] crbug.com/591099 storage/indexeddb/index-cursor.html [ Timeout ] crbug.com/591099 storage/indexeddb/keypath-basics.html [ Pass Timeout ] @@ -1982,7 +1880,7 @@ crbug.com/591099 storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Timeout ] crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Timeout ] crbug.com/591099 storage/indexeddb/objectstore-keycursor.html [ Timeout ] -crbug.com/591099 storage/indexeddb/structured-clone.html [ Timeout ] +crbug.com/591099 storage/indexeddb/structured-clone.html [ Pass Timeout ] crbug.com/714962 svg/as-background-image/svg-as-background-body.html [ Failure ] crbug.com/591099 svg/as-border-image/svg-as-border-image-2.html [ Failure ] crbug.com/591099 svg/as-border-image/svg-as-border-image.html [ Failure ] @@ -2074,30 +1972,29 @@ crbug.com/591099 virtual/gpu/fast/canvas/canvas-imageSmoothingQuality.html [ Pass ] crbug.com/591099 virtual/incremental-shadow-dom/external/wpt/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html [ Failure ] crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/scrollbar.html [ Crash ] -crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/selections-in-shadow.html [ Timeout ] +crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/selections-in-shadow.html [ Pass Timeout ] crbug.com/591099 virtual/incremental-shadow-dom/html/details_summary/details-writing-mode-align-center.html [ Failure ] crbug.com/591099 virtual/incremental-shadow-dom/html/details_summary/details-writing-mode-align-left.html [ Failure ] crbug.com/591099 virtual/incremental-shadow-dom/html/details_summary/details-writing-mode-align-right.html [ Failure ] crbug.com/591099 virtual/incremental-shadow-dom/html/details_summary/details-writing-mode.html [ Failure ] -crbug.com/714962 virtual/incremental-shadow-dom/shadow-dom/focus-navigation-with-delegatesFocus.html [ Timeout ] +crbug.com/714962 virtual/incremental-shadow-dom/shadow-dom/focus-navigation-with-delegatesFocus.html [ Pass Timeout ] crbug.com/591099 virtual/layout_ng/ [ Skip ] crbug.com/824918 virtual/layout_ng_experimental/ [ Skip ] crbug.com/836297 virtual/layout_ng_experimental/printing/webgl-oversized-printing.html [ Pass Timeout ] -crbug.com/591099 media/controls/modern/tap-to-hide-controls.html [ Failure ] crbug.com/714962 virtual/mouseevent_fractional/fast/events/drag-in-frames.html [ Failure ] crbug.com/714962 virtual/mouseevent_fractional/fast/events/event-on-culled_inline.html [ Failure ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/hr-timestamp/input-events.html [ Failure Pass ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/keyboardevent-getModifierState.html [ Timeout ] crbug.com/714962 virtual/mouseevent_fractional/fast/events/mouse-down-on-pseudo-element-remove-crash.html [ Failure ] -crbug.com/591099 virtual/mouseevent_fractional/fast/events/mouse-event-buttons-attribute.html [ Timeout ] +crbug.com/591099 virtual/mouseevent_fractional/fast/events/mouse-event-buttons-attribute.html [ Pass Timeout ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/mouse-relative-position.html [ Failure ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/mouseevent-getModifierState.html [ Timeout ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/onclick-list-marker.html [ Failure ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-capture-transition-events.html [ Timeout ] -crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-capture.html [ Timeout ] -crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-preventdefault.html [ Timeout ] +crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-capture.html [ Pass Timeout ] +crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-preventdefault.html [ Pass Timeout ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/multi-pointer-preventdefault.html [ Pass Timeout ] -crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/touch-capture-in-iframe.html [ Timeout ] +crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/touch-capture-in-iframe.html [ Pass Timeout ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/touch-capture.html [ Timeout ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/select-element.html [ Timeout ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/sequential-focus-navigation-starting-point.html [ Failure ] @@ -2105,6 +2002,8 @@ crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ] crbug.com/591099 virtual/new-remote-playback-pipeline/ [ Skip ] +crbug.com/591099 virtual/off-main-thread-websocket/external/wpt/websockets/constructor/014.html?wss [ Pass Timeout ] +crbug.com/591099 virtual/off-main-thread-websocket/external/wpt/websockets/keeping-connection-open/001.html?wss [ Pass Timeout ] crbug.com/591099 virtual/off-main-thread-websocket/http/tests/websocket/invalid-subprotocol-characters.html [ Timeout ] crbug.com/591099 virtual/outofblink-cors/ [ Skip ] crbug.com/591099 virtual/paint-timing/external/wpt/paint-timing/sibling-painting-first-image.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService index 95f2bc7..6486146 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -41,9 +41,7 @@ # Cross-Origin Read Blocking is not implemented. crbug.com/792546 http/tests/inspector-protocol/network/block_cross_site_document_load.js [ Failure ] -crbug.com/792546 external/wpt/fetch/corb/img-mime-types-coverage.tentative.sub.html [ Failure ] -crbug.com/792546 external/wpt/fetch/corb/img-png-mislabeled-as-html-nosniff.tentative.sub.html [ Failure ] -crbug.com/792546 external/wpt/fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html [ Failure ] +crbug.com/792546 external/wpt/fetch/corb/img-mime-types-coverage.tentative.sub.html [ Failure ] +crbug.com/792546 external/wpt/fetch/corb/img-png-mislabeled-as-html-nosniff.tentative.sub.html [ Failure ] +crbug.com/792546 external/wpt/fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html [ Failure ] crbug.com/792546 external/wpt/fetch/corb/script-html-correctly-labeled.tentative.sub.html [ Failure ] - -crbug.com/812464 inspector-protocol/network/interception-file-url.js [ Pass Crash ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 index f6b13e2..17e59858 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -92,12 +92,15 @@ Bug(none) virtual/spv2/ [ Skip ] Bug(none) virtual/stable/ [ Skip ] Bug(none) virtual/targetedstylerecalc/ [ Skip ] +Bug(none) virtual/video-surface-layer/ [ Skip ] Bug(none) virtual/reporting-api/ [ Skip ] Bug(none) virtual/wheelscrolllatching/ [ Skip ] Bug(none) virtual/windows-directwrite/ [ Skip ] Bug(none) virtual/without-smil/ [ Skip ] Bug(none) virtual/blink-gen-property-trees/ [ Skip ] +crbug.com/778875 virtual/threaded/fast/animationworklet/ [ Skip ] + # Fail on SPv1, but succeed on SPv2 crbug.com/472330 fast/borders/border-image-outset-split-inline-vertical-lr.html [ Pass ] crbug.com/817175 compositing/overflow/clip-escaping-reverse-order-should-not-crash.html [ Pass ] @@ -383,8 +386,10 @@ Bug(none) compositing/squashing/squashing-sparsity-heuristic.html [ Failure ] Bug(none) compositing/tiled-layers-hidpi.html [ Failure ] Bug(none) compositing/update-paint-phases.html [ Failure ] +Bug(none) compositing/video/video-controls-layer-creation-squashing.html [ Crash Failure ] +Bug(none) compositing/video/video-controls-layer-creation.html [ Crash Failure ] Bug(none) compositing/video/video-poster.html [ Crash Failure ] -Bug(none) compositing/video/video-reflection.html [ Crash Failure ] +Bug(none) compositing/video/video-reflection.html [ Crash Failure ] Bug(none) compositing/visibility/layer-visible-content.html [ Failure ] Bug(none) compositing/visibility/overlays.html [ Failure Crash ] Bug(none) compositing/visibility/visibility-image-layers-dynamic.html [ Crash Failure ] @@ -1012,9 +1017,6 @@ crbug.com/702353 virtual/threaded/transitions/transition-end-event-destroy-iframe.html [ Timeout ] crbug.com/702365 virtual/threaded/animations/composited-filter-webkit-filter.html [ Failure ] crbug.com/702370 virtual/threaded/animations/compositor-independent-transform-cancel.html [ Failure ] -crbug.com/778875 virtual/threaded/fast/animationworklet/animation-worklet-visual-update.html [ Failure Crash ] -crbug.com/778875 virtual/threaded/fast/animationworklet/animation-worklet-animator-animate.html [ Failure ] -crbug.com/778875 virtual/threaded/fast/animationworklet/animation-worklet-scroll-timeline.html [ Failure ] # Eight of the frames in the test below paint no content. In SPv2 we will never # composite animations that paint nothing. For now we mark this test as failing, @@ -1406,4 +1408,4 @@ Bug(none) compositing/squashing/frame-clip-squashed-scrolled.html [ Failure ] Bug(none) fast/block/positioning/vertical-rl/002.html [ Failure ] -Bug(none) virtual/threaded/fast/animationworklet/animation-worklet-start-delay.html [ Failure ] +Bug(none) rootscroller/gesture-scroll-document-not-root-scroller.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 500f3ac..17e8fe3f 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -153,6 +153,10 @@ # Not relevant, because SPv175 is launching imminently. crbug.com/804670 virtual/disable-spv175/paint/filters/drop-shadow-clipped.html [ Skip ] + +crbug.com/795549 external/wpt/css/css-filter/filtered-block-is-container.html [ Failure ] +crbug.com/795549 external/wpt/css/css-filter/filtered-inline-is-container.html [ Failure ] + # ====== Paint team owned tests to here ====== # ====== Layout team owned tests from here ======
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 37ef0e3..659df7f 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -35999,6 +35999,42 @@ {} ] ], + "css/css-filter/filtered-block-is-container.html": [ + [ + "/css/css-filter/filtered-block-is-container.html", + [ + [ + "/css/css-filter/filtered-block-is-container-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-filter/filtered-html-is-not-container.html": [ + [ + "/css/css-filter/filtered-html-is-not-container.html", + [ + [ + "/css/css-filter/filtered-html-is-not-container-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-filter/filtered-inline-is-container.html": [ + [ + "/css/css-filter/filtered-inline-is-container.html", + [ + [ + "/css/css-filter/filtered-inline-is-container-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-flexbox/Flexible-order.html": [ [ "/css/css-flexbox/Flexible-order.html", @@ -99265,6 +99301,11 @@ {} ] ], + "WebCryptoAPI/derive_bits_keys/pbkdf2.https.worker-expected.txt": [ + [ + {} + ] + ], "WebCryptoAPI/derive_bits_keys/pbkdf2.js": [ [ {} @@ -109495,6 +109536,21 @@ {} ] ], + "css/css-filter/filtered-block-is-container-ref.html": [ + [ + {} + ] + ], + "css/css-filter/filtered-html-is-not-container-ref.html": [ + [ + {} + ] + ], + "css/css-filter/filtered-inline-is-container-ref.html": [ + [ + {} + ] + ], "css/css-flexbox/OWNERS": [ [ {} @@ -132690,6 +132746,11 @@ {} ] ], + "css/cssom/historical-expected.txt": [ + [ + {} + ] + ], "css/cssom/interfaces-expected.txt": [ [ {} @@ -168825,6 +168886,11 @@ {} ] ], + "x-frame-options/README.md": [ + [ + {} + ] + ], "x-frame-options/support/helper.js": [ [ {} @@ -190618,6 +190684,12 @@ {} ] ], + "css/cssom-view/elementScroll-002.html": [ + [ + "/css/cssom-view/elementScroll-002.html", + {} + ] + ], "css/cssom-view/elementScroll.html": [ [ "/css/cssom-view/elementScroll.html", @@ -210276,6 +210348,16 @@ {} ] ], + "html/webappapis/timers/missing-timeout-setinterval.any.js": [ + [ + "/html/webappapis/timers/missing-timeout-setinterval.any.html", + {} + ], + [ + "/html/webappapis/timers/missing-timeout-setinterval.any.worker.html", + {} + ] + ], "html/webappapis/timers/negative-setinterval.html": [ [ "/html/webappapis/timers/negative-setinterval.html", @@ -211258,6 +211340,12 @@ {} ] ], + "mediacapture-streams/MediaStreamTrack-applyConstraints.https.html": [ + [ + "/mediacapture-streams/MediaStreamTrack-applyConstraints.https.html", + {} + ] + ], "mediacapture-streams/MediaStreamTrack-getCapabilities.https.html": [ [ "/mediacapture-streams/MediaStreamTrack-getCapabilities.https.html", @@ -255902,11 +255990,11 @@ "testharness" ], "IndexedDB/keypath-special-identifiers.htm": [ - "588026e7e95192b98b594e77fafe67495d5cd481", + "0392d5dc6be8c17d435f2e0382e378521551c4fb", "testharness" ], "IndexedDB/keypath.htm": [ - "a21b6eecc56a924bdf017d9053be2f0eecd25eeb", + "169a6f8e0f70ecf9089e2a6aa9232f632fe24e9a", "testharness" ], "IndexedDB/keypath_invalid.htm": [ @@ -256109,6 +256197,10 @@ "766a7184da406918e9dc6718125975a59d3d5d36", "support" ], + "WebCryptoAPI/derive_bits_keys/pbkdf2.https.worker-expected.txt": [ + "bbc9e6ea6464cb50fdd14aee00e460e831f1c507", + "support" + ], "WebCryptoAPI/derive_bits_keys/pbkdf2.https.worker.js": [ "1149c335951baa52b7d1ad3192292fb46176d491", "testharness" @@ -282117,6 +282209,30 @@ "35eb3b4cfe4505a5c9761dcecc047a8cd09f8fb9", "support" ], + "css/css-filter/filtered-block-is-container-ref.html": [ + "937aebf17944a83bfb41b3d9a6035f00e975c05d", + "support" + ], + "css/css-filter/filtered-block-is-container.html": [ + "e910cc30bcb2aecc0fcc60ca3cbf381c39dab837", + "reftest" + ], + "css/css-filter/filtered-html-is-not-container-ref.html": [ + "2e7b8249aa26a996e173f8f0d5e42b0b45457719", + "support" + ], + "css/css-filter/filtered-html-is-not-container.html": [ + "5fb31e59005e70dd8bb10525698c4b343c22b2dc", + "reftest" + ], + "css/css-filter/filtered-inline-is-container-ref.html": [ + "7c985ca7fb9e26a2b6139ff863817aaf236d6af2", + "support" + ], + "css/css-filter/filtered-inline-is-container.html": [ + "0c1b258810f515e72269ab07d8efb34791a9b0c4", + "reftest" + ], "css/css-flexbox/Flexible-order.html": [ "ff6b01d6069b9106c60e3f86ac29bffb7c94f916", "reftest" @@ -323373,6 +323489,10 @@ "f033a1ec4b1f0636897c4ee16b67c1c13f0eac4e", "testharness" ], + "css/cssom-view/elementScroll-002.html": [ + "98dec0c15711c0f7baf4a0ea404e1fda872e3d5b", + "testharness" + ], "css/cssom-view/elementScroll.html": [ "2119d689cc369bd6632ee1a9525bcbf7d1d4ba65", "testharness" @@ -323933,8 +324053,12 @@ "d3ef09fb6092078562f8923879b9ece97938df47", "testharness" ], + "css/cssom/historical-expected.txt": [ + "ae1b10ae00e5fec559c56734b2d42d2c1766d9c7", + "support" + ], "css/cssom/historical.html": [ - "02b135e62439d775d7e8de7ca94c831a8d00e077", + "89c506ea58f2ad38eb9ecc1e5f422b81a45b07fa", "testharness" ], "css/cssom/inline-style-001.html": [ @@ -330226,11 +330350,11 @@ "testharness" ], "dom/events/relatedTarget.window-expected.txt": [ - "4e0722bf72ed7df73fe9fe833df9186b09d11596", + "2d8e58a9fe23b6068ecd4c5ceae4dac6dd512d12", "support" ], "dom/events/relatedTarget.window.js": [ - "0426d2ecae3f3562be175e4364353d979365ed1c", + "3dd9ddfa4d8d584f6ddf6db52e4e9020491088d8", "testharness" ], "dom/historical-expected.txt": [ @@ -335826,7 +335950,7 @@ "reftest" ], "fetch/corb/img-mime-types-coverage.tentative.sub.html": [ - "58422f923455c1f62e0c4e743b1c900061657146", + "02da8b9ee9430d552c4cb71fb759e05e939ec05e", "testharness" ], "fetch/corb/img-png-mislabeled-as-html-nosniff.tentative.sub-expected.html": [ @@ -335938,11 +336062,11 @@ "support" ], "fetch/corb/script-html-correctly-labeled.tentative.sub.html": [ - "71cb97517821177aa1c1d116f830cd2315963d18", + "971fcca2f52153a39bf3643b52fb69b6255acf32", "testharness" ], "fetch/corb/script-html-js-polyglot.sub.html": [ - "19d0530fcb573b6bcbffebc5dbe2ce3537faa8a3", + "4b28bd95bd19ea95df3e78bbfc477fb7dea60e29", "testharness" ], "fetch/corb/script-html-via-cross-origin-blob-url.sub.html": [ @@ -342714,15 +342838,15 @@ "manual" ], "html/editing/dnd/file/001.html": [ - "28e4e1d0e06a8c300c116aeb2d07e4808bdf56fe", + "9a004cc780577f28242feeedce7a15deb7849c8c", "support" ], "html/editing/dnd/file/002.html": [ - "62f40d477019e663e377f314947c28ea6b556864", + "fdb4d92324f81cd4412fa8334aeb75fa79044804", "support" ], "html/editing/dnd/file/003.html": [ - "df5bb0614ea6c7135caead8c5a1258bf981aeb13", + "578bc2823d303d41577abc9c0a855af338baf8be", "support" ], "html/editing/dnd/file/004.html": [ @@ -342738,11 +342862,11 @@ "support" ], "html/editing/dnd/file/007.html": [ - "21851c97db234d854576e3ea6e1029ffed38a761", + "bb927ac9126c217f7cb0bcf07e58f6e8f756fc06", "support" ], "html/editing/dnd/file/008.html": [ - "081def5342c9b8bb426812bef312e6cdee3dd66e", + "b632d267d0c66c631670957566e763d8511efbe4", "support" ], "html/editing/dnd/file/009.html": [ @@ -342754,7 +342878,7 @@ "support" ], "html/editing/dnd/file/011.html": [ - "6c5de23f6a63e817d60d1357020ee90f71193372", + "4e78bcbbdd8b8f220e1b431f964c299636d2a064", "support" ], "html/editing/dnd/file/fail.txt": [ @@ -356601,6 +356725,10 @@ "49fd55dbbf64c6973a0e76284c0e3d8b7bf0ef3c", "testharness" ], + "html/webappapis/timers/missing-timeout-setinterval.any.js": [ + "40ad74d6ed3719dcad2097246d74d49c87b989aa", + "testharness" + ], "html/webappapis/timers/negative-setinterval.html": [ "405046cab9cd15a88d57eace1f293ebdd7b1b3e2", "testharness" @@ -358450,7 +358578,7 @@ "testharness" ], "mediacapture-streams/MediaDevices-getUserMedia.https.html": [ - "a515deeec87c394b4a826b538df6dd0baa05cae6", + "dbd2cbacb24f088167e1c34207bea12c19f5d0e1", "testharness" ], "mediacapture-streams/MediaStream-MediaElement-preload-none-manual.https.html": [ @@ -358525,6 +358653,10 @@ "e3358344a76f874b68bdba743f113caa3b61ec88", "testharness" ], + "mediacapture-streams/MediaStreamTrack-applyConstraints.https.html": [ + "cda78cab93e93f9e436d46db8b7a6a0d12471e87", + "testharness" + ], "mediacapture-streams/MediaStreamTrack-end-manual.https.html": [ "6511203b417168722d1e05d90e58364ebce145ea", "manual" @@ -391921,6 +392053,10 @@ "fad08f267635717c6a2930de14df27107039b3a8", "support" ], + "x-frame-options/README.md": [ + "cb5f2cb5d74263ce584e1ad76045a04afae4ba0a", + "support" + ], "x-frame-options/deny.sub.html": [ "eb6b6474a393714f62a85bf435e7f342ceff2e0e", "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/keypath-special-identifiers.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/keypath-special-identifiers.htm index 331169b5..cb64d0b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/keypath-special-identifiers.htm +++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/keypath-special-identifiers.htm
@@ -38,11 +38,6 @@ property: 'lastModified', instance: new File([''], '', {lastModified: 123}), }, - { - type: 'File', - property: 'lastModifiedDate', - instance: new File([''], '', {lastModified: 123}), - }, ].forEach(function(testcase) { indexeddb_test( (t, db) => {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/keypath.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/keypath.htm index b59d614..4985712 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/keypath.htm +++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/keypath.htm
@@ -125,7 +125,7 @@ "[Blob.length, Blob.type]"); } - // File.name and File.lastModifiedDate is not testable automatically + // File.name and File.lastModified is not testable automatically keypath(['name', 'type'], [ { name: "orange", type: "fruit" }, { name: "orange", type: ["telecom", "french"] } ],
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-block-is-container-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-block-is-container-ref.html new file mode 100644 index 0000000..fc9467f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-block-is-container-ref.html
@@ -0,0 +1,60 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Filter: Filtered block establishes a containing block reference.</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> + +<style> +#scroller { + width: 500px; + height: 500px; + overflow: scroll +} +.spacer { + width: 1000px; + height: 500px; + background-color: lightgreen; +} +#transform { + /* no-op transform */ + transform: translateX(0px); + width: 100px; + height: 50px; + background-color: lightblue; +} +#fixed, #absolute { + width: 100px; + height: 100px; +} +#fixed { + position: fixed; + top: 100px; + left: 150px; + background-color: green; +} +#absolute { + position: absolute; + top: 200px; + left: 300px; + background-color: blue; +} +</style> + +<div id="scroller"> + <div class="spacer"> + </div> + <div id="transform"> + <div id="fixed"></div> + <div id="absolute"></div> + </div> + <div class="spacer"> + </div> +</div> + +<script> +window.onload = function() { + document.getElementById("scroller").scrollTo(50, 250); +} +</script> + + +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-block-is-container.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-block-is-container.html new file mode 100644 index 0000000..6f99f36 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-block-is-container.html
@@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Filter: Filtered block establishes a containing block.</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty"> +<link rel="match" href="filtered-block-is-container-ref.html"> + +<style> +#scroller { + width: 500px; + height: 500px; + overflow: scroll +} +.spacer { + width: 1000px; + height: 500px; + background-color: lightgreen; +} +#filter { + /* no-op filter */ + filter: blur(0px); + width: 100px; + height: 50px; + background-color: lightblue; +} +#fixed, #absolute { + width: 100px; + height: 100px; +} +#fixed { + position: fixed; + top: 100px; + left: 150px; + background-color: green; +} +#absolute { + position: absolute; + top: 200px; + left: 300px; + background-color: blue; +} +</style> + +<div id="scroller"> + <div class="spacer"> + </div> + <div id="filter"> + <div id="fixed"></div> + <div id="absolute"></div> + </div> + <div class="spacer"> + </div> +</div> + +<script> +window.onload = function() { + document.getElementById("scroller").scrollTo(50, 250); +} +</script> + +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-html-is-not-container-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-html-is-not-container-ref.html new file mode 100644 index 0000000..c1f179a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-html-is-not-container-ref.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Filter: Filtered html element does not establish a containing block.</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> + +<style> +#spacer { + width: 2000px; + height: 2000px; + background-color: lightgreen; +} +#fixed, #absolute { + width: 100px; + height: 100px; +} +#fixed { + position: fixed; + top: 100px; + left: 150px; + background-color: green; +} +#absolute { + position: absolute; + top: 200px; + left: 300px; + background-color: blue; +} +</style> + +<div id="fixed"></div> +<div id="absolute"></div> +<div id="spacer"></div> + +<script> +window.onload = function() { window.scrollTo(50, 100); }; +</script> + +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-html-is-not-container.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-html-is-not-container.html new file mode 100644 index 0000000..8adc302 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-html-is-not-container.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Filter: Filtered html element does not establish a containing block.</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty"> +<link rel="match" href="filtered-html-is-not-container-ref.html"> + +<style> +html { + filter: blur(0px); +} +#spacer { + width: 2000px; + height: 2000px; + background-color: lightgreen; +} +#fixed, #absolute { + width: 100px; + height: 100px; +} +#fixed { + position: fixed; + top: 100px; + left: 150px; + background-color: green; +} +#absolute { + position: absolute; + top: 200px; + left: 300px; + background-color: blue; +} +</style> + +<div id="fixed"></div> +<div id="absolute"></div> +<div id="spacer"></div> + +<script> +window.onload = function() { window.scrollTo(50, 100); }; +</script> + +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-inline-is-container-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-inline-is-container-ref.html new file mode 100644 index 0000000..aa6c12e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-inline-is-container-ref.html
@@ -0,0 +1,57 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Filter: Filtered inline establishes a containing block.</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> + +<style> +#scroller { + width: 500px; + height: 500px; + overflow: scroll +} +.spacer { + width: 1000px; + height: 500px; + background-color: lightgreen; +} +#transform { + /* no-op filter */ + transform: translateX(0px); +} +#fixed, #absolute { + width: 100px; + height: 100px; +} +#fixed { + position: fixed; + top: 100px; + left: 150px; + background-color: green; +} +#absolute { + position: absolute; + top: 200px; + left: 300px; + background-color: blue; +} +</style> + +<div id="scroller"> + <div class="spacer"> + </div> + <div id="transform"> + a + <div id="fixed"></div> + <div id="absolute"></div> + </div> + <div class="spacer"> + </div> +</div> + +<script> +window.onload = function() { + document.getElementById("scroller").scrollTo(50, 250); +} +</script> + +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-inline-is-container.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-inline-is-container.html new file mode 100644 index 0000000..56f1d91f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-filter/filtered-inline-is-container.html
@@ -0,0 +1,60 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Filter: Filtered inline establishes a containing block reference.</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty"> +<link rel="match" href="filtered-inline-is-container-ref.html"> + +<style> +#scroller { + width: 500px; + height: 500px; + overflow: scroll +} +.spacer { + width: 1000px; + height: 500px; + background-color: lightgreen; +} +#filter { + /* no-op filter */ + filter: blur(0px); + display: inline; +} +#fixed, #absolute { + width: 100px; + height: 100px; +} +#fixed { + position: fixed; + top: 100px; + left: 150px; + background-color: green; +} +#absolute { + position: absolute; + top: 200px; + left: 300px; + background-color: blue; +} +</style> + +<div id="scroller"> + <div class="spacer"> + </div> + <div id="filter"> + a + <div id="fixed"></div> + <div id="absolute"></div> + </div> + <div class="spacer"> + </div> +</div> + +<script> +window.onload = function() { + document.getElementById("scroller").scrollTo(50, 250); +} +</script> + +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom-view/elementScroll-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/cssom-view/elementScroll-002.html new file mode 100644 index 0000000..a1a28aab --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom-view/elementScroll-002.html
@@ -0,0 +1,57 @@ +<!doctype html> +<meta charset="utf-8"> +<title>cssom-view - elementScroll - 002</title> +<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-scrolltop"> +<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-scrollleft"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="scroller1" style="height: 100px; width: 100px; overflow: scroll; background: red;"> + <div style="background: green; margin-top: 100px; margin-left: 100px; width: 100px; height: 100px;"></div> +</div> +<div id="scroller2" style="height: 100px; width: 100px; overflow: hidden; background: red;"> + <div style="background: green; margin-top: 100px; padding-left: 100px; width: 100px; height: 100px;"></div> +</div> +<div id="scroller3" style="height: 100px; width: 100px; overflow: scroll; background: red;"> + <div style="background: green; padding-top: 100px; margin-left: 100px; width: 100px; height: 100px;"></div> +</div> +<div id="scroller4" style="height: 100px; width: 100px; overflow: hidden; background: red;"> + <div style="background: green; padding-top: 100px; padding-left: 100px; width: 100px; height: 100px;"></div> +</div> +<script> + test(function () { + var scroller1 = document.getElementById("scroller1"); + + scroller1.scrollTop = 100; + scroller1.scrollLeft = 100; + assert_equals(scroller1.scrollTop, 100, "changed scrollTop should be 100"); + assert_equals(scroller1.scrollLeft, 100, "changed scrollLeft should be 100"); + + }, "simple scroll with style: 'margin' and 'overflow: scroll'"); + test(function () { + var scroller2 = document.getElementById("scroller2"); + + scroller2.scrollTop = 100; + scroller2.scrollLeft = 100; + assert_equals(scroller2.scrollTop, 100, "changed scrollTop should be 100"); + assert_equals(scroller2.scrollLeft, 100, "changed scrollLeft should be 100"); + + }, "simple scroll with style: 'margin' and 'overflow: hidden'"); + test(function () { + var scroller3 = document.getElementById("scroller3"); + + scroller3.scrollTop = 100; + scroller3.scrollLeft = 100; + assert_equals(scroller3.scrollTop, 100, "changed scrollTop should be 100"); + assert_equals(scroller3.scrollLeft, 100, "changed scrollLeft should be 100"); + + }, "simple scroll with style: 'padding' and 'overflow: scroll'"); + test(function () { + var scroller4 = document.getElementById("scroller4"); + + scroller4.scrollTop = 100; + scroller4.scrollLeft = 100; + assert_equals(scroller4.scrollTop, 100, "changed scrollTop should be 100"); + assert_equals(scroller4.scrollLeft, 100, "changed scrollLeft should be 100"); + + }, "simple scroll with style: 'padding' and 'overflow: hidden'"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/historical-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/historical-expected.txt new file mode 100644 index 0000000..f2193a15 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/historical-expected.txt
@@ -0,0 +1,14 @@ +This is a testharness.js-based test. +PASS Historical Document member: selectedStyleSheetSet +PASS Historical Document member: lastStyleSheetSet +PASS Historical Document member: preferredStyleSheetSet +PASS Historical Document member: styleSheetSets +PASS Historical Document member: enableStyleSheetsForSet +FAIL Historical Document member: selectedStylesheetSet assert_false: expected false got true +FAIL Historical Document member: preferredStylesheetSet assert_false: expected false got true +PASS Historical Element member: cascadedStyle +PASS Historical Element member: defaultStyle +PASS Historical Element member: rawComputedStyle +PASS Historical Element member: usedStyle +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/historical.html b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/historical.html index d956f14..ddd264c8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/historical.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/historical.html
@@ -11,6 +11,8 @@ "preferredStyleSheetSet", "styleSheetSets", "enableStyleSheetsForSet", + "selectedStylesheetSet", + "preferredStylesheetSet", ].forEach(function(name) { test(function() { assert_false(name in document);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/relatedTarget.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/events/relatedTarget.window-expected.txt index bab0020..b22cc5b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/events/relatedTarget.window-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/events/relatedTarget.window-expected.txt
@@ -2,8 +2,7 @@ PASS Reset if target pointed to a shadow tree FAIL Reset if relatedTarget pointed to a shadow tree assert_equals: expected null but got object "[object XMLHttpRequest]" PASS Reset if target pointed to a shadow tree pre-dispatch -FAIL Reset if relatedTarget pointed to a shadow tree pre-dispatch assert_equals: expected Element node <body><div id="log"></div> -<script src="/dom/events/relat... but got DocumentFragment node with 2 children +PASS Reset if relatedTarget pointed to a shadow tree pre-dispatch FAIL Reset targets on early return assert_false: expected false got true FAIL Reset targets before activation behavior assert_equals: expected null but got Element node <input type="checkbox"></input> Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/relatedTarget.window.js b/third_party/WebKit/LayoutTests/external/wpt/dom/events/relatedTarget.window.js index d3632bb9..4f68550a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/events/relatedTarget.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/events/relatedTarget.window.js
@@ -41,13 +41,15 @@ async_test(t => { const shadowChild = shadow.appendChild(document.createElement("div")); - shadowChild.addEventListener("demo", t.step_func(() => document.body.appendChild(shadowChild))); + const shadowChild2 = shadow.appendChild(document.createElement("div")); + shadowChild2.addEventListener("demo", t.step_func(() => document.body.appendChild(shadowChild))); const event = new FocusEvent("demo", { relatedTarget: shadowChild }); - document.body.dispatchEvent(event); + shadowChild2.dispatchEvent(event); assert_equals(shadowChild.parentNode, document.body); assert_equals(event.target, null); assert_equals(event.relatedTarget, null); shadowChild.remove(); + shadowChild2.remove(); t.done(); }, "Reset if relatedTarget pointed to a shadow tree pre-dispatch");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/img-mime-types-coverage.tentative.sub.html b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/img-mime-types-coverage.tentative.sub.html index 7ccc41b4..65c5b84 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/img-mime-types-coverage.tentative.sub.html +++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/img-mime-types-coverage.tentative.sub.html
@@ -19,6 +19,7 @@ // MIME-types not protected by CORB "image/gif", "image/png", "image/png;blah", "image/svg+xml", "application/javascript", "application/jsonp", + "image/gif;HI=THERE", // MIME types that may seem to be JSON or XML, but really aren't - i.e. // these MIME types are not covered by: @@ -39,7 +40,8 @@ "text/json", "application/json", "text/xml", "application/xml", "application/blah+json", "text/blah+json", "application/blah+xml", "text/blah+xml", - "TEXT/HTML", "TEXT/JSON", "TEXT/BLAH+JSON", "APPLICATION/BLAH+XML"] + "TEXT/HTML", "TEXT/JSON", "TEXT/BLAH+JSON", "APPLICATION/BLAH+XML", + "text/json;does=it;matter", "text/HTML;NO=it;does=NOT"] const get_url = (mime) => { // www1 is cross-origin, so the HTTP response is CORB-eligible -->
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/script-html-correctly-labeled.tentative.sub.html b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/script-html-correctly-labeled.tentative.sub.html index 76a8fad..8f4d767 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/script-html-correctly-labeled.tentative.sub.html +++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/script-html-correctly-labeled.tentative.sub.html
@@ -26,5 +26,5 @@ // www1 is cross-origin, so the HTTP response is CORB-eligible. script.src = 'http://{{domains[www1]}}:{{ports[http][0]}}/fetch/corb/resources/html-correctly-labeled.html'; document.body.appendChild(script) -}); +}, "CORB-blocked script has no syntax errors"); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/script-html-js-polyglot.sub.html b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/script-html-js-polyglot.sub.html index 8395901..950a907 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/script-html-js-polyglot.sub.html +++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/script-html-js-polyglot.sub.html
@@ -25,5 +25,5 @@ // www1 is cross-origin, so the HTTP response is CORB-eligible. script.src = "http://{{domains[www1]}}:{{ports[http][0]}}/fetch/corb/resources/html-js-polyglot.js" document.body.appendChild(script) -}); +}, "CORB cannot block polyglot HTML/JS"); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/001.html b/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/001.html index 07ef4dbbb..b911920 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/001.html
@@ -55,8 +55,8 @@ fails[fails.length] = 'dataTransfer.files[0].size '+e.dataTransfer.files[0].size+' instead of '+filesize; } /* - if( !e.dataTransfer.files[0].lastModifiedDate ) { - fails[fails.length] = 'no dataTransfer.files[0].lastModifiedDate'; + if( !e.dataTransfer.files[0].lastModified ) { + fails[fails.length] = 'no dataTransfer.files[0].lastModified'; } */ if( e.dataTransfer.files[0].name != filename ) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/002.html b/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/002.html index b029afb..c8d633d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/002.html
@@ -66,8 +66,8 @@ fails[fails.length] = 'dataTransfer.files['+i0+'].size '+e.dataTransfer.files[i0].size+' instead of '+filesize1; } /* - if( !e.dataTransfer.files[i0].lastModifiedDate ) { - fails[fails.length] = 'no dataTransfer.files['+i0+'].lastModifiedDate'; + if( !e.dataTransfer.files[i0].lastModified ) { + fails[fails.length] = 'no dataTransfer.files['+i0+'].lastModified'; } */ if( e.dataTransfer.files[i0].name != filename1 ) { @@ -80,8 +80,8 @@ fails[fails.length] = 'dataTransfer.files['+i1+'].size '+e.dataTransfer.files[i1].size+' instead of '+filesize2; } /* - if( !e.dataTransfer.files[i1].lastModifiedDate ) { - fails[fails.length] = 'no dataTransfer.files['+i1+'].lastModifiedDate'; + if( !e.dataTransfer.files[i1].lastModified ) { + fails[fails.length] = 'no dataTransfer.files['+i1+'].lastModified'; } */ if( e.dataTransfer.files[i1].name != filename2 ) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/003.html b/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/003.html index 0c532ea5c..51e5a5a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/003.html
@@ -42,8 +42,8 @@ fails[fails.length] = 'dataTransfer.files[0].size '+e.dataTransfer.files[0].size+' instead of '+filesize; } /* - if( !e.dataTransfer.files[0].lastModifiedDate ) { - fails[fails.length] = 'no dataTransfer.files[0].lastModifiedDate'; + if( !e.dataTransfer.files[0].lastModified ) { + fails[fails.length] = 'no dataTransfer.files[0].lastModified'; } */ if( e.dataTransfer.files[0].name != filename ) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/007.html b/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/007.html index f3e51179..099716f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/007.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/007.html
@@ -57,8 +57,8 @@ fails[fails.length] = 'dataTransfer.files[0].size '+e.dataTransfer.files[0].size+' instead of '+filesize1+' or '+filesize2; } /* - if( !e.dataTransfer.files[0].lastModifiedDate ) { - fails[fails.length] = 'no dataTransfer.files[0].lastModifiedDate'; + if( !e.dataTransfer.files[0].lastModified ) { + fails[fails.length] = 'no dataTransfer.files[0].lastModified'; } */ if( !window.FileReader ) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/008.html b/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/008.html index 3ba28276..49751582 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/008.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/008.html
@@ -60,8 +60,8 @@ } */ /* - if( !e.dataTransfer.files[0].lastModifiedDate ) { - fails[fails.length] = 'no dataTransfer.files[0].lastModifiedDate'; + if( !e.dataTransfer.files[0].lastModified ) { + fails[fails.length] = 'no dataTransfer.files[0].lastModified'; } */ if( !window.FileReader ) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/011.html b/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/011.html index 2c12d64ec..a265e7b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/011.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/editing/dnd/file/011.html
@@ -45,8 +45,8 @@ fails[fails.length] = 'dataTransfer.files[0].size '+e.dataTransfer.files[0].size+' instead of '+filesize; } /* - if( !e.dataTransfer.files[0].lastModifiedDate ) { - fails[fails.length] = 'no dataTransfer.files[0].lastModifiedDate'; + if( !e.dataTransfer.files[0].lastModified ) { + fails[fails.length] = 'no dataTransfer.files[0].lastModified'; } */ if( e.dataTransfer.files[0].name != filename ) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/timers/missing-timeout-setinterval.any.js b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/timers/missing-timeout-setinterval.any.js new file mode 100644 index 0000000..33a1cc0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/timers/missing-timeout-setinterval.any.js
@@ -0,0 +1,34 @@ +function timeout_trampoline(t, timeout, message) { + t.step_timeout(function() { + // Yield in case we managed to be called before the second interval callback. + t.step_timeout(function() { + assert_unreached(message); + }, timeout); + }, timeout); +} + +async_test(function(t) { + let ctr = 0; + let h = setInterval(t.step_func(function() { + if (++ctr == 2) { + clearInterval(h); + t.done(); + return; + } + }) /* no interval */); + + timeout_trampoline(t, 100, "Expected setInterval callback to be called two times"); +}, "Calling setInterval with no interval should be the same as if called with 0 interval"); + +async_test(function(t) { + let ctr = 0; + let h = setInterval(t.step_func(function() { + if (++ctr == 2) { + clearInterval(h); + t.done(); + return; + } + }), undefined); + + timeout_trampoline(t, 100, "Expected setInterval callback to be called two times"); +}, "Calling setInterval with undefined interval should be the same as if called with 0 interval");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/x-frame-options/README.md b/third_party/WebKit/LayoutTests/external/wpt/x-frame-options/README.md new file mode 100644 index 0000000..7b35f0f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/x-frame-options/README.md
@@ -0,0 +1,2 @@ +This directory contains tests for +[HTTP Header Field X-Frame-Options](https://tools.ietf.org/html/rfc7034).
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/table/replace-col-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/table/replace-col-expected.txt new file mode 100644 index 0000000..a1b9688 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/table/replace-col-expected.txt
@@ -0,0 +1,50 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutTableSection THEAD", + "rect": [8, 82, 56, 26], + "reason": "style change" + }, + { + "object": "LayoutTableSection TFOOT", + "rect": [8, 132, 56, 24], + "reason": "style change" + }, + { + "object": "LayoutTableSection TBODY", + "rect": [8, 108, 56, 24], + "reason": "style change" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutTable TABLE", + "reason": "full" + }, + { + "object": "LayoutTableSection THEAD", + "reason": "style change" + }, + { + "object": "LayoutTableSection TBODY", + "reason": "style change" + }, + { + "object": "LayoutTableSection TFOOT", + "reason": "style change" + }, + { + "object": "LayoutTableCol COL", + "reason": "appeared" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/viewport-testing/console-runtime-result-below-prompt-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/viewport-testing/console-runtime-result-below-prompt-expected.txt index 7365feb..5735d66 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/viewport-testing/console-runtime-result-below-prompt-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/viewport-testing/console-runtime-result-below-prompt-expected.txt
@@ -44,3 +44,17 @@ Setting max length for evaluation to 0 Expression: "1 + 2" yielded preview: "" +Running: testClickingPreviewFocusesEditor +Prompt text set to `1 + 2` +Selection before: {"startLine":0,"startColumn":0,"endLine":0,"endColumn":0} +Clicking preview element +Selection after: {"startLine":0,"startColumn":5,"endLine":0,"endColumn":5} +Editor has focus: true + +Running: testClickWithSelectionDoesNotFocusEditor +Prompt text set to `1 + 2` +Selection before: 3 +Clicking preview element +Selection after: 3 +Editor has focus: false +
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/viewport-testing/console-runtime-result-below-prompt.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/viewport-testing/console-runtime-result-below-prompt.js index 2fdd3c9..f648ddbc 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/viewport-testing/console-runtime-result-below-prompt.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/viewport-testing/console-runtime-result-below-prompt.js
@@ -6,11 +6,11 @@ TestRunner.addResult(`Tests that console fills the empty element below the prompt editor.\n`); await TestRunner.loadModule('console_test_runner'); await TestRunner.showPanel('console'); - await ConsoleTestRunner.waitUntilConsoleEditorLoaded(); await ConsoleTestRunner.waitForPendingViewportUpdates(); const consoleView = Console.ConsoleView.instance(); const prompt = consoleView._prompt; + const editor = await ConsoleTestRunner.waitUntilConsoleEditorLoaded(); TestRunner.runTestSuite([ async function testUnsafeExpressions(next) { @@ -39,6 +39,44 @@ next(); }, + + async function testClickingPreviewFocusesEditor(next) { + const expression = `1 + 2`; + TestRunner.addResult(`Prompt text set to \`${expression}\``); + prompt.setText(expression); + await prompt._previewRequestForTest; + + editor.setSelection(TextUtils.TextRange.createFromLocation(0, 0)); + TestRunner.addResult('Selection before: ' + editor.selection().toString()); + + TestRunner.addResult(`Clicking preview element`); + prompt._eagerPreviewElement.click(); + + TestRunner.addResult('Selection after: ' + editor.selection().toString()); + TestRunner.addResult(`Editor has focus: ${editor.element.hasFocus()}`); + + next(); + }, + + async function testClickWithSelectionDoesNotFocusEditor(next) { + const expression = `1 + 2`; + TestRunner.addResult(`Prompt text set to \`${expression}\``); + prompt.setText(expression); + await prompt._previewRequestForTest; + document.activeElement.blur(); + + var firstTextNode = prompt.belowEditorElement().traverseNextTextNode(); + window.getSelection().setBaseAndExtent(firstTextNode, 0, firstTextNode, 1); + TestRunner.addResult('Selection before: ' + window.getSelection().toString()); + + TestRunner.addResult(`Clicking preview element`); + prompt._eagerPreviewElement.click(); + + TestRunner.addResult('Selection after: ' + window.getSelection().toString()); + TestRunner.addResult(`Editor has focus: ${editor.element.hasFocus()}`); + + next(); + }, ]); async function checkExpression(expression) {
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/viewport-testing/console-stick-to-bottom-with-large-prompt.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/viewport-testing/console-stick-to-bottom-with-large-prompt.js index c3a4d082..d8c067d 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/viewport-testing/console-stick-to-bottom-with-large-prompt.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/viewport-testing/console-stick-to-bottom-with-large-prompt.js
@@ -21,7 +21,7 @@ const consoleView = Console.ConsoleView.instance(); const viewport = consoleView._viewport; - const heightBelowPromptEditor = consoleView._prompt.heightBelowEditor(); + const heightBelowPromptEditor = consoleView._prompt.belowEditorElement().offsetHeight; const messagesCount = 150; TestRunner.runTestSuite([
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table/replace-col-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/table/replace-col-expected.html new file mode 100644 index 0000000..7fb4fad --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/invalidation/table/replace-col-expected.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<style>td { width: 50px; height: 20px; background: green }</style> +<p style="height: 50px"> +Tests repaint of table sections when a col is replaced. +Passes if there are 3 green rectangles without red. +</p> +<table> + <thead><tr><td></td></tr></thead> + <tbody><tr><td></td></tr></tbody> + <tfoot><tr><td></td></tr></tfoot> +</table>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table/replace-col-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/table/replace-col-expected.txt new file mode 100644 index 0000000..97db693 --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/invalidation/table/replace-col-expected.txt
@@ -0,0 +1,61 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutTableSection THEAD", + "rect": [8, 82, 56, 26], + "reason": "style change" + }, + { + "object": "LayoutTableSection TFOOT", + "rect": [8, 132, 56, 24], + "reason": "style change" + }, + { + "object": "LayoutTableSection TBODY", + "rect": [8, 108, 56, 24], + "reason": "style change" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutTable TABLE", + "reason": "full" + }, + { + "object": "LayoutTableSection THEAD", + "reason": "style change" + }, + { + "object": "LayoutTableSection TBODY", + "reason": "style change" + }, + { + "object": "LayoutTableSection TFOOT", + "reason": "style change" + }, + { + "object": "LayoutTableCol COL", + "reason": "appeared" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table/replace-col.html b/third_party/WebKit/LayoutTests/paint/invalidation/table/replace-col.html new file mode 100644 index 0000000..a0ca9b7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/invalidation/table/replace-col.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<style>td { width: 50px; height: 20px }</style> +<script src="../resources/text-based-repaint.js"></script> +<script> +function repaintTest() { + col.remove(); + var new_col = document.createElement('col'); + new_col.style.background = 'green'; + colgroup.insertBefore(new_col, colgroup.firstChild); +} +onload = runRepaintAndPixelTest; +</script> +<p style="height: 50px"> +Tests repaint of table sections when a col is replaced. +Passes if there are 3 green rectangles without red. +</p> +<table> + <colgroup id="colgroup"> + <col id="col" style="background: red"> + </colgroup> + <thead><tr><td></td></tr></thead> + <tbody><tr><td></td></tr></tbody> + <tfoot><tr><td></td></tr></tfoot> +</table>
diff --git a/third_party/WebKit/LayoutTests/virtual/disable-spv175/paint/invalidation/table/replace-col-expected.txt b/third_party/WebKit/LayoutTests/virtual/disable-spv175/paint/invalidation/table/replace-col-expected.txt new file mode 100644 index 0000000..15a6ca7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/disable-spv175/paint/invalidation/table/replace-col-expected.txt
@@ -0,0 +1,65 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutTable TABLE", + "rect": [8, 82, 56, 74], + "reason": "full" + }, + { + "object": "LayoutTableCol COL", + "rect": [8, 82, 56, 74], + "reason": "appeared" + }, + { + "object": "LayoutTableCol COL id='col'", + "rect": [8, 82, 56, 74], + "reason": "disappeared" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutTableCol COL id='col'", + "reason": "disappeared" + }, + { + "object": "LayoutTable TABLE", + "reason": "full" + }, + { + "object": "LayoutTableSection THEAD", + "reason": "style change" + }, + { + "object": "LayoutTableSection TBODY", + "reason": "style change" + }, + { + "object": "LayoutTableSection TFOOT", + "reason": "style change" + }, + { + "object": "LayoutTableCol COL", + "reason": "appeared" + } + ] +} +
diff --git a/third_party/blink/public/platform/web_layer.h b/third_party/blink/public/platform/web_layer.h index a4ba289b3..df50dd3 100644 --- a/third_party/blink/public/platform/web_layer.h +++ b/third_party/blink/public/platform/web_layer.h
@@ -89,13 +89,6 @@ virtual void SetOpacity(float) = 0; virtual float Opacity() const = 0; - // If set to true, content opaqueness cannot be changed using - // WebLayer::SetOpaque. However, it can still be modified using - // SetContentsOpaque on the cc::Layer. This is a roundabout way of allowing - // creators of WebLayers to specify opaqueness without - // CompositedLayerMapping/PaintArtifactCompositor clobbering it later. This - // will be addressed once WebLayer is removed. - virtual void SetContentsOpaqueIsFixed(bool) = 0; virtual void SetBlendMode(SkBlendMode) = 0; virtual SkBlendMode BlendMode() const = 0;
diff --git a/third_party/blink/public/web/web_plugin_container.h b/third_party/blink/public/web/web_plugin_container.h index c3693f44..3e324f0 100644 --- a/third_party/blink/public/web/web_plugin_container.h +++ b/third_party/blink/public/web/web_plugin_container.h
@@ -138,7 +138,7 @@ // Sets the layer representing the plugin for compositing. The // WebPluginContainer does *not* take ownership. - virtual void SetWebLayer(WebLayer*) = 0; + virtual void SetWebLayer(WebLayer*, bool prevent_contents_opaque_changes) = 0; virtual void RequestFullscreen() = 0; virtual bool IsFullscreenElement() const = 0;
diff --git a/third_party/blink/public/web/web_remote_frame.h b/third_party/blink/public/web/web_remote_frame.h index 85b44de..0d3e5e0 100644 --- a/third_party/blink/public/web/web_remote_frame.h +++ b/third_party/blink/public/web/web_remote_frame.h
@@ -61,7 +61,7 @@ WebFrame* opener) = 0; // Layer for the in-process compositor. - virtual void SetWebLayer(WebLayer*) = 0; + virtual void SetWebLayer(WebLayer*, bool prevent_contents_opaque_changes) = 0; // Set security origin replicated from another process. virtual void SetReplicatedOrigin(
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index d8f1b72..b873fc98 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -1280,17 +1280,39 @@ } IntRect Element::VisibleBoundsInVisualViewport() const { - if (!GetLayoutObject() || !GetDocument().GetPage()) + if (!GetLayoutObject() || !GetDocument().GetPage() || + !GetDocument().GetFrame()) return IntRect(); - // TODO(tkent): Can we check invisibility by scrollable non-frame elements? - IntSize viewport_size = GetDocument().GetPage()->GetVisualViewport().Size(); - IntRect rect(0, 0, viewport_size.Width(), viewport_size.Height()); // We don't use absoluteBoundingBoxRect() because it can return an IntRect // larger the actual size by 1px. crbug.com/470503 - rect.Intersect(GetDocument().View()->ContentsToViewport( - RoundedIntRect(GetLayoutObject()->AbsoluteBoundingBoxFloatRect()))); - return rect; + LayoutRect rect( + RoundedIntRect(GetLayoutObject()->AbsoluteBoundingBoxFloatRect())); + LayoutRect frame_clip_rect = + GetDocument().View()->GetLayoutBox()->ClippingRect(LayoutPoint()); + rect.Intersect(frame_clip_rect); + + // MapToVisualRectInAncestorSpace, called with a null ancestor argument, + // returns the viewport-visible rect in the local frame root's coordinates, + // accounting for clips and transformed in embedding containers. This + // includes clips that might be applied by out-of-process frame ancestors. + GetDocument().View()->GetLayoutView()->MapToVisualRectInAncestorSpace( + nullptr, rect, kUseTransforms | kTraverseDocumentBoundaries, + kDefaultVisualRectFlags); + + IntRect visible_rect = PixelSnappedIntRect(rect); + // If the rect is in the coordinates of the main frame, then it should + // also be clipped to the viewport to account for page scale. For OOPIFs, + // local frame root -> viewport coordinate conversion is done in the + // browser process. + if (GetDocument().GetFrame()->LocalFrameRoot().IsMainFrame()) { + IntSize viewport_size = GetDocument().GetPage()->GetVisualViewport().Size(); + visible_rect = + GetDocument().GetPage()->GetVisualViewport().RootFrameToViewport( + visible_rect); + visible_rect.Intersect(IntRect(IntPoint(), viewport_size)); + } + return visible_rect; } void Element::ClientQuads(Vector<FloatQuad>& quads) {
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h index 2d863ee..67433507 100644 --- a/third_party/blink/renderer/core/dom/element.h +++ b/third_party/blink/renderer/core/dom/element.h
@@ -281,9 +281,12 @@ virtual void scrollTo(const ScrollToOptions&); IntRect BoundsInViewport() const; - // Returns an intersection rectangle of the bounds rectangle and the - // viewport rectangle, in the visual viewport coordinate. This function is - // used to show popups beside this element. + // For elements that are not contained in any OOPIFs, this returns an + // intersection rectangle of the bounds rectangle and the viewport + // rectangle, in the visual viewport coordinate. For elements within OOPIFs, + // the returned rect is the intersection with the viewport but in the + // coordinate space of the local frame root. + // This function is used to show popups beside this element. IntRect VisibleBoundsInVisualViewport() const; DOMRectList* getClientRects();
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc index 2600295..09abcec 100644 --- a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc +++ b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
@@ -325,8 +325,10 @@ return frame->PageZoomFactor(); } -void WebPluginContainerImpl::SetWebLayer(WebLayer* layer) { - if (web_layer_ == layer) +void WebPluginContainerImpl::SetWebLayer(WebLayer* layer, + bool prevent_contents_opaque_changes) { + if (web_layer_ == layer && + prevent_contents_opaque_changes == prevent_contents_opaque_changes_) return; if (web_layer_) @@ -335,6 +337,7 @@ GraphicsLayer::RegisterContentsLayer(layer); web_layer_ = layer; + prevent_contents_opaque_changes_ = prevent_contents_opaque_changes; if (element_) element_->SetNeedsCompositingUpdate(); @@ -693,6 +696,11 @@ return web_layer_; } +bool WebPluginContainerImpl::PreventContentsOpaqueChangesToPlatformLayer() + const { + return prevent_contents_opaque_changes_; +} + v8::Local<v8::Object> WebPluginContainerImpl::ScriptableObject( v8::Isolate* isolate) { // With Oilpan, on plugin element detach dispose() will be called to safely @@ -737,6 +745,7 @@ web_plugin_(web_plugin), web_layer_(nullptr), touch_event_request_type_(kTouchEventRequestTypeNone), + prevent_contents_opaque_changes_(false), wants_wheel_events_(false), self_visible_(false), parent_visible_(false),
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_impl.h b/third_party/blink/renderer/core/exported/web_plugin_container_impl.h index c33ab33e..5290f85 100644 --- a/third_party/blink/renderer/core/exported/web_plugin_container_impl.h +++ b/third_party/blink/renderer/core/exported/web_plugin_container_impl.h
@@ -102,6 +102,7 @@ void Hide() override; WebLayer* PlatformLayer() const; + bool PreventContentsOpaqueChangesToPlatformLayer() const; v8::Local<v8::Object> ScriptableObject(v8::Isolate*); bool SupportsKeyboardFocus() const; bool SupportsInputMethod() const; @@ -147,7 +148,7 @@ float PageScaleFactor() override; float PageZoomFactor() override; - void SetWebLayer(WebLayer*) override; + void SetWebLayer(WebLayer*, bool prevent_contents_opaque_changes) override; void RequestFullscreen() override; bool IsFullscreenElement() const override; @@ -234,6 +235,7 @@ WebLayer* web_layer_; IntRect frame_rect_; TouchEventRequestType touch_event_request_type_; + bool prevent_contents_opaque_changes_; bool wants_wheel_events_; bool self_visible_; bool parent_visible_;
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_test.cc b/third_party/blink/renderer/core/exported/web_plugin_container_test.cc index e43a87ef..1210242 100644 --- a/third_party/blink/renderer/core/exported/web_plugin_container_test.cc +++ b/third_party/blink/renderer/core/exported/web_plugin_container_test.cc
@@ -1334,12 +1334,12 @@ bool Initialize(WebPluginContainer* container) override { if (!FakeWebPlugin::Initialize(container)) return false; - container->SetWebLayer(layer_.get()); + container->SetWebLayer(layer_.get(), false); return true; } void Destroy() override { - Container()->SetWebLayer(nullptr); + Container()->SetWebLayer(nullptr, false); FakeWebPlugin::Destroy(); }
diff --git a/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc b/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc index db660a3..dcf6140 100644 --- a/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc +++ b/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
@@ -183,11 +183,12 @@ return child; } -void WebRemoteFrameImpl::SetWebLayer(WebLayer* layer) { +void WebRemoteFrameImpl::SetWebLayer(WebLayer* layer, + bool prevent_contents_opaque_changes) { if (!GetFrame()) return; - GetFrame()->SetWebLayer(layer); + GetFrame()->SetWebLayer(layer, prevent_contents_opaque_changes); } void WebRemoteFrameImpl::SetCoreFrame(RemoteFrame* frame) {
diff --git a/third_party/blink/renderer/core/exported/web_remote_frame_impl.h b/third_party/blink/renderer/core/exported/web_remote_frame_impl.h index dcdccee..a7fd042 100644 --- a/third_party/blink/renderer/core/exported/web_remote_frame_impl.h +++ b/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
@@ -56,7 +56,7 @@ const ParsedFeaturePolicy&, WebRemoteFrameClient*, WebFrame* opener) override; - void SetWebLayer(WebLayer*) override; + void SetWebLayer(WebLayer*, bool prevent_contents_opaque_changes) override; void SetReplicatedOrigin( const WebSecurityOrigin&, bool is_potentially_trustworthy_unique_origin) override;
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc index a65038b..867d7a1 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.cc +++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -108,7 +108,7 @@ // of all these objects. Break the cycle by notifying of detachment. ToRemoteDOMWindow(dom_window_)->FrameDetached(); if (web_layer_) - SetWebLayer(nullptr); + SetWebLayer(nullptr, false); Frame::Detach(type); } @@ -172,10 +172,12 @@ return static_cast<RemoteFrameClient*>(Frame::Client()); } -void RemoteFrame::SetWebLayer(WebLayer* web_layer) { +void RemoteFrame::SetWebLayer(WebLayer* web_layer, + bool prevent_contents_opaque_changes) { if (web_layer_) GraphicsLayer::UnregisterContentsLayer(web_layer_); web_layer_ = web_layer; + prevent_contents_opaque_changes_ = prevent_contents_opaque_changes; if (web_layer_) GraphicsLayer::RegisterContentsLayer(web_layer_);
diff --git a/third_party/blink/renderer/core/frame/remote_frame.h b/third_party/blink/renderer/core/frame/remote_frame.h index 5edd418b..0aa8d936 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.h +++ b/third_party/blink/renderer/core/frame/remote_frame.h
@@ -41,8 +41,11 @@ void DidResume() override; void SetIsInert(bool) override; - void SetWebLayer(WebLayer*); + void SetWebLayer(WebLayer*, bool prevent_contents_opaque_changes); WebLayer* GetWebLayer() const { return web_layer_; } + bool WebLayerHasFixedContentsOpaque() const { + return prevent_contents_opaque_changes_; + } void AdvanceFocus(WebFocusType, LocalFrame* source); @@ -66,6 +69,7 @@ Member<RemoteFrameView> view_; Member<RemoteSecurityContext> security_context_; WebLayer* web_layer_ = nullptr; + bool prevent_contents_opaque_changes_ = false; }; inline RemoteFrameView* RemoteFrame::View() const {
diff --git a/third_party/blink/renderer/core/frame/visual_viewport.cc b/third_party/blink/renderer/core/frame/visual_viewport.cc index d7502963..a8e290b 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport.cc +++ b/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -471,7 +471,8 @@ // by default so scrollbars don't show up in layout tests. web_scrollbar_layer->Layer()->SetOpacity(0); scrollbar_graphics_layer->SetContentsToPlatformLayer( - web_scrollbar_layer->Layer()); + web_scrollbar_layer->Layer(), + /*prevent_contents_opaque_changes=*/false); scrollbar_graphics_layer->SetDrawsContent(false); web_scrollbar_layer->SetScrollLayer( inner_viewport_scroll_layer_->PlatformLayer());
diff --git a/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/third_party/blink/renderer/core/frame/visual_viewport_test.cc index 5f35204..061c513b 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport_test.cc +++ b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -1598,6 +1598,10 @@ } TEST_P(VisualViewportTest, ElementVisibleBoundsInVisualViewport) { + // VisibleBoundsInVisualViewport() assumes root layer scrolling is enabled. + if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled()) + return; + InitializeWithAndroidSettings(); WebView()->Resize(IntSize(640, 1080)); RegisterMockedHttpURLLoad("viewport-select.html");
diff --git a/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/third_party/blink/renderer/core/inspector/browser_protocol.pdl index fac87e2..1e46e1b 100644 --- a/third_party/blink/renderer/core/inspector/browser_protocol.pdl +++ b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -5537,7 +5537,7 @@ optional integer width # Frame height in DIP (headless chrome only). optional integer height - # The browser context to create the page in. + # The browser context to create the page in (headless chrome only). optional BrowserContextID browserContextId # Whether BeginFrames for this target will be controlled via DevTools (headless chrome only, # not supported on MacOS yet, false by default). @@ -5554,11 +5554,12 @@ # Deprecated. deprecated optional TargetID targetId - # Deletes a BrowserContext. All the belonging pages will be closed without calling their - # beforeunload hooks. + # Deletes a BrowserContext, will fail of any open page uses it. experimental command disposeBrowserContext parameters BrowserContextID browserContextId + returns + boolean success # Returns information about a target. experimental command getTargetInfo
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index e5bdbc84..a711c24 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -2328,7 +2328,7 @@ needs_paint_property_update_(true), subtree_needs_paint_property_update_(true), descendant_needs_paint_property_update_(true), - background_changed_since_last_paint_invalidation_(false), + background_changed_since_last_paint_invalidation_(true), outline_may_be_affected_by_descendants_(false), previous_outline_may_be_affected_by_descendants_(false), is_truncated_(false),
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc index 6c65aee99..41b5da1 100644 --- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc +++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
@@ -367,7 +367,7 @@ static void DetachScrollbarLayer(GraphicsLayer* scrollbar_graphics_layer) { DCHECK(scrollbar_graphics_layer); - scrollbar_graphics_layer->SetContentsToPlatformLayer(nullptr); + scrollbar_graphics_layer->SetContentsToPlatformLayer(nullptr, false); scrollbar_graphics_layer->SetDrawsContent(true); } @@ -383,7 +383,7 @@ } scrollbar_layer->SetScrollLayer(scroll_layer); scrollbar_graphics_layer->SetContentsToPlatformLayer( - scrollbar_layer->Layer()); + scrollbar_layer->Layer(), /*prevent_contents_opaque_changes=*/false); scrollbar_graphics_layer->SetDrawsContent(false); }
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc index ef65db7..f21c20a 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -159,12 +159,10 @@ return ContentsRect(layout_object).Contains(BackgroundRect(layout_object)); } -static WebLayer* PlatformLayerForPlugin(LayoutObject& layout_object) { +static WebPluginContainerImpl* GetPluginContainer(LayoutObject& layout_object) { if (!layout_object.IsEmbeddedObject()) return nullptr; - WebPluginContainerImpl* plugin = - ToLayoutEmbeddedObject(layout_object).Plugin(); - return plugin ? plugin->PlatformLayer() : nullptr; + return ToLayoutEmbeddedObject(layout_object).Plugin(); } static inline bool IsAcceleratedContents(LayoutObject& layout_object) { @@ -831,30 +829,39 @@ } } - if (WebLayer* layer = PlatformLayerForPlugin(layout_object)) { - graphics_layer_->SetContentsToPlatformLayer(layer); + if (WebPluginContainerImpl* plugin = GetPluginContainer(layout_object)) { + graphics_layer_->SetContentsToPlatformLayer( + plugin->PlatformLayer(), + plugin->PreventContentsOpaqueChangesToPlatformLayer()); } else if (layout_object.GetNode() && layout_object.GetNode()->IsFrameOwnerElement() && ToHTMLFrameOwnerElement(layout_object.GetNode())->ContentFrame()) { Frame* frame = ToHTMLFrameOwnerElement(layout_object.GetNode())->ContentFrame(); if (frame->IsRemoteFrame()) { - WebLayer* layer = ToRemoteFrame(frame)->GetWebLayer(); - graphics_layer_->SetContentsToPlatformLayer(layer); + RemoteFrame* remote = ToRemoteFrame(frame); + WebLayer* layer = remote->GetWebLayer(); + graphics_layer_->SetContentsToPlatformLayer( + layer, remote->WebLayerHasFixedContentsOpaque()); } } else if (layout_object.IsVideo()) { HTMLMediaElement* media_element = ToHTMLMediaElement(layout_object.GetNode()); - graphics_layer_->SetContentsToPlatformLayer(media_element->PlatformLayer()); + graphics_layer_->SetContentsToPlatformLayer( + media_element->PlatformLayer(), + /*prevent_contents_opaque_changes=*/true); } else if (IsSurfaceLayerCanvas(layout_object)) { HTMLCanvasElement* canvas = ToHTMLCanvasElement(layout_object.GetNode()); graphics_layer_->SetContentsToPlatformLayer( - canvas->SurfaceLayerBridge()->GetWebLayer()); + canvas->SurfaceLayerBridge()->GetWebLayer(), + /*prevent_contents_opaque_changes=*/false); layer_config_changed = true; } else if (IsTextureLayerCanvas(layout_object)) { HTMLCanvasElement* canvas = ToHTMLCanvasElement(layout_object.GetNode()); - if (CanvasRenderingContext* context = canvas->RenderingContext()) - graphics_layer_->SetContentsToPlatformLayer(context->PlatformLayer()); + if (CanvasRenderingContext* context = canvas->RenderingContext()) { + graphics_layer_->SetContentsToPlatformLayer( + context->PlatformLayer(), /*prevent_contents_opaque_changes=*/false); + } layer_config_changed = true; } if (layout_object.IsLayoutEmbeddedContent()) {
diff --git a/third_party/blink/renderer/devtools/front_end/Tests.js b/third_party/blink/renderer/devtools/front_end/Tests.js index 572ba99..add96169 100644 --- a/third_party/blink/renderer/devtools/front_end/Tests.js +++ b/third_party/blink/renderer/devtools/front_end/Tests.js
@@ -1125,12 +1125,13 @@ this.assertEquals(await evalCode(target2, 'localStorage.getItem("page1")'), null); this.assertEquals(await evalCode(target2, 'localStorage.getItem("page2")'), 'page2'); - const removedTargets = []; - SDK.targetManager.observeTargets({targetAdded: () => {}, targetRemoved: target => removedTargets.push(target)}); - await Promise.all([disposeBrowserContext(browserContextIds[0]), disposeBrowserContext(browserContextIds[1])]); - this.assertEquals(removedTargets.length, 2); - this.assertEquals(removedTargets.indexOf(target1) !== -1, true); - this.assertEquals(removedTargets.indexOf(target2) !== -1, true); + this.assertEquals(await disposeBrowserContext(browserContextIds[0]), false); + this.assertEquals(await disposeBrowserContext(browserContextIds[1]), false); + + await closeTarget(target1); + await closeTarget(target2); + this.assertEquals(await disposeBrowserContext(browserContextIds[0]), true); + this.assertEquals(await disposeBrowserContext(browserContextIds[1]), true); this.releaseControl(); @@ -1153,9 +1154,15 @@ return target; } + async function closeTarget(target) { + const targetAgent = SDK.targetManager.mainTarget().targetAgent(); + await targetAgent.invoke_closeTarget({targetId: target.id()}); + } + async function disposeBrowserContext(browserContextId) { const targetAgent = SDK.targetManager.mainTarget().targetAgent(); - await targetAgent.invoke_disposeBrowserContext({browserContextId}); + const {success} = await targetAgent.invoke_disposeBrowserContext({browserContextId}); + return success; } async function evalCode(target, code) {
diff --git a/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js b/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js index edb272f..4a50380 100644 --- a/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js +++ b/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
@@ -46,17 +46,18 @@ delete this._initialText; if (this.hasFocus()) this.focus(); - this.element.tabIndex = -1; + this.element.removeAttribute('tabindex'); + this._editor.widget().element.tabIndex = -1; this._editorSetForTest(); } } /** - * @return {number} + * @return {!Element} */ - heightBelowEditor() { - return this._eagerPreviewElement.offsetHeight; + belowEditorElement() { + return this._eagerPreviewElement; } _onTextChanged() {
diff --git a/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js b/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js index bd259ed..d801337 100644 --- a/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js +++ b/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js
@@ -833,9 +833,11 @@ * @param {!Event} event */ _messagesClicked(event) { + const target = /** @type {?Node} */ (event.target); // Do not focus prompt if messages have selection. if (!this._messagesElement.hasSelection()) { - const clickedOutsideMessageList = event.target === this._messagesElement; + const clickedOutsideMessageList = + target === this._messagesElement || this._prompt.belowEditorElement().isSelfOrAncestor(target); if (clickedOutsideMessageList) this._prompt.moveCaretToEndOfPrompt(); this.focus(); @@ -1168,7 +1170,7 @@ if (!this._isBelowPromptEnabled) return this._messagesElement.isScrolledToBottom(); const distanceToPromptEditorBottom = this._messagesElement.scrollHeight - this._messagesElement.scrollTop - - this._messagesElement.clientHeight - this._prompt.heightBelowEditor(); + this._messagesElement.clientHeight - this._prompt.belowEditorElement().offsetHeight; return distanceToPromptEditorBottom <= 2; } };
diff --git a/third_party/blink/renderer/devtools/front_end/externs.js b/third_party/blink/renderer/devtools/front_end/externs.js index df8a357..b363c2c 100644 --- a/third_party/blink/renderer/devtools/front_end/externs.js +++ b/third_party/blink/renderer/devtools/front_end/externs.js
@@ -526,7 +526,7 @@ setHistory: function(histData) {}, setLine: function(line, text) {}, setOption: function(option, value) {}, - setSelection: function(anchor, head) {}, + setSelection: function(anchor, head, options) {}, /** * @param {number=} primaryIndex * @param {?Object=} config
diff --git a/third_party/blink/renderer/devtools/front_end/main/Main.js b/third_party/blink/renderer/devtools/front_end/main/Main.js index c25eb1d..693f3829 100644 --- a/third_party/blink/renderer/devtools/front_end/main/Main.js +++ b/third_party/blink/renderer/devtools/front_end/main/Main.js
@@ -108,7 +108,7 @@ Runtime.experiments.register('applyCustomStylesheet', 'Allow custom UI themes'); Runtime.experiments.register('blackboxJSFramesOnTimeline', 'Blackbox JavaScript frames on Timeline', true); Runtime.experiments.register('colorContrastRatio', 'Color contrast ratio line in color picker', true); - Runtime.experiments.register('consoleBelowPrompt', 'Console below-prompt UI', true); + Runtime.experiments.register('consoleBelowPrompt', 'Eager evaluation'); Runtime.experiments.register('emptySourceMapAutoStepping', 'Empty sourcemap auto-stepping'); Runtime.experiments.register('inputEventsOnTimelineOverview', 'Input events on Timeline overview', true); Runtime.experiments.register('nativeHeapProfiler', 'Native memory sampling heap profiler', true);
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js b/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js index ca4d3be1..e37467a5 100644 --- a/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js +++ b/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
@@ -801,11 +801,11 @@ const name = this.property.name; const parentPath = this.parent.nameElement ? this.parent.nameElement.title : ''; if (useDotNotation.test(name)) - this.nameElement.title = parentPath + '.' + name; + this.nameElement.title = parentPath ? `${parentPath}.${name}` : name; else if (isInteger.test(name)) this.nameElement.title = parentPath + '[' + name + ']'; else - this.nameElement.title = parentPath + '["' + name + '"]'; + this.nameElement.title = parentPath + '["' + JSON.stringify(name) + '"]'; } /** @@ -813,6 +813,7 @@ */ _contextMenuFired(event) { const contextMenu = new UI.ContextMenu(event); + contextMenu.appendApplicableItems(this); if (this.property.symbol) contextMenu.appendApplicableItems(this.property.symbol); if (this.property.value) @@ -962,6 +963,13 @@ this.setExpandable(false); } } + + /** + * @return {string} + */ + path() { + return this.nameElement.title; + } };
diff --git a/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js b/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js index 44d1806..740e181 100644 --- a/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js +++ b/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js
@@ -110,12 +110,32 @@ this._prettyToggle.setToggled(value); this._prettyToggle.setEnabled(false); + const wasLoaded = this.loaded; const selection = this.selection(); + let newSelection; if (this._pretty && this._rawContent) { this.setContent(await this._requestFormattedContent()); const start = this._rawToPrettyLocation(selection.startLine, selection.startColumn); const end = this._rawToPrettyLocation(selection.endLine, selection.endColumn); - this.setSelection(new TextUtils.TextRange(start[0], start[1], end[0], end[1])); + newSelection = new TextUtils.TextRange(start[0], start[1], end[0], end[1]); + } else { + this.setContent(this._rawContent); + const start = this._prettyToRawLocation(selection.startLine, selection.startColumn); + const end = this._prettyToRawLocation(selection.endLine, selection.endColumn); + newSelection = new TextUtils.TextRange(start[0], start[1], end[0], end[1]); + } + if (wasLoaded) { + this.textEditor.revealPosition(newSelection.endLine, newSelection.endColumn, this._editable); + this.textEditor.setSelection(newSelection); + } + this._prettyToggle.setEnabled(true); + this._updatePrettyPrintState(); + } + + _updatePrettyPrintState() { + this._prettyToggle.setToggled(this._pretty); + this._textEditor.element.classList.toggle('pretty-printed', this._pretty); + if (this._pretty) { this._textEditor.setLineNumberFormatter(lineNumber => { const line = this._prettyToRawLocation(lineNumber - 1, 0)[0] + 1; if (lineNumber === 1) @@ -128,12 +148,7 @@ this._textEditor.setLineNumberFormatter(lineNumber => { return String(lineNumber); }); - this.setContent(this._rawContent); - const start = this._prettyToRawLocation(selection.startLine, selection.startColumn); - const end = this._prettyToRawLocation(selection.endLine, selection.endColumn); - this.setSelection(new TextUtils.TextRange(start[0], start[1], end[0], end[1])); } - this._prettyToggle.setEnabled(true); } /** @@ -294,7 +309,7 @@ _innerSetSelectionIfNeeded() { if (this._selectionToSet && this.loaded && this.isShowing()) { - this._textEditor.setSelection(this._selectionToSet); + this._textEditor.setSelection(this._selectionToSet, true); this._selectionToSet = null; } }
diff --git a/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js b/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js index 320aef7c..c5462594 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js +++ b/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js
@@ -180,6 +180,23 @@ } /** + * @param {string} expression + */ + _focusAndAddExpressionToWatch(expression) { + UI.viewManager.showView('sources.watch'); + this.doUpdate(); + this._addExpressionToWatch(expression); + } + + /** + * @param {string} expression + */ + _addExpressionToWatch(expression) { + this._createWatchExpression(expression); + this._saveExpressions(); + } + + /** * @override * @param {!UI.Context} context * @param {string} actionId @@ -190,20 +207,29 @@ if (!frame) return false; const text = frame.textEditor.text(frame.textEditor.selection()); - UI.viewManager.showView('sources.watch'); - this.doUpdate(); - this._createWatchExpression(text); - this._saveExpressions(); + this._focusAndAddExpressionToWatch(text); return true; } /** + * @param {!ObjectUI.ObjectPropertyTreeElement} target + */ + _addPropertyPathToWatch(target) { + this._addExpressionToWatch(target.path()); + } + + /** * @override * @param {!Event} event * @param {!UI.ContextMenu} contextMenu * @param {!Object} target */ appendApplicableItems(event, contextMenu, target) { + if (target instanceof ObjectUI.ObjectPropertyTreeElement) { + contextMenu.debugSection().appendItem( + ls`Add property path to watch`, this._addPropertyPathToWatch.bind(this, target)); + } + const frame = UI.context.flavor(Sources.UISourceCodeFrame); if (!frame || frame.textEditor.selection().isEmpty()) return;
diff --git a/third_party/blink/renderer/devtools/front_end/sources/module.json b/third_party/blink/renderer/devtools/front_end/sources/module.json index aed8aea..bbb61d2 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/module.json +++ b/third_party/blink/renderer/devtools/front_end/sources/module.json
@@ -197,6 +197,15 @@ }, { "type": "@UI.ContextMenu.Provider", + "actionId": "sources.add-to-watch", + "className": "Sources.WatchExpressionsSidebarPane", + "title": "Add to watch", + "contextTypes": [ + "ObjectUI.ObjectPropertyTreeElement" + ] + }, + { + "type": "@UI.ContextMenu.Provider", "contextTypes": [ "TextEditor.CodeMirrorTextEditor" ],
diff --git a/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js b/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js index 2b74611..f5605569 100644 --- a/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js +++ b/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js
@@ -1163,15 +1163,16 @@ /** * @override * @param {!TextUtils.TextRange} textRange + * @param {boolean=} dontScroll */ - setSelection(textRange) { + setSelection(textRange, dontScroll) { this._lastSelection = textRange; if (!this._editorSizeInSync) { this._selectionSetScheduled = true; return; } const pos = TextEditor.CodeMirrorUtils.toPos(textRange); - this._codeMirror.setSelection(pos.start, pos.end); + this._codeMirror.setSelection(pos.start, pos.end, {scroll: !dontScroll}); } /**
diff --git a/third_party/blink/renderer/devtools/front_end/text_editor/cmdevtools.css b/third_party/blink/renderer/devtools/front_end/text_editor/cmdevtools.css index 5ff40d8..e451a8f 100644 --- a/third_party/blink/renderer/devtools/front_end/text_editor/cmdevtools.css +++ b/third_party/blink/renderer/devtools/front_end/text_editor/cmdevtools.css
@@ -546,3 +546,7 @@ .CodeMirror-composing { border-bottom: 2px solid; } + +.pretty-printed .CodeMirror-linenumber { + color: var(--accent-color-b); +}
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc index 799a5303..41deb4a 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -89,6 +89,7 @@ blend_mode_(BlendMode::kNormal), has_transform_origin_(false), contents_opaque_(false), + prevent_contents_opaque_changes_(false), should_flatten_transform_(true), backface_visibility_(true), draws_content_(false), @@ -493,7 +494,8 @@ layer->SetLayerClient(nullptr); } -void GraphicsLayer::SetContentsTo(WebLayer* layer) { +void GraphicsLayer::SetContentsTo(WebLayer* layer, + bool prevent_contents_opaque_changes) { bool children_changed = false; if (layer) { DCHECK(g_registered_layer_set); @@ -503,6 +505,7 @@ children_changed = true; } UpdateContentsRect(); + prevent_contents_opaque_changes_ = prevent_contents_opaque_changes; } else { if (contents_layer_) { children_changed = true; @@ -1101,7 +1104,7 @@ contents_opaque_ = opaque; layer_->Layer()->SetOpaque(contents_opaque_); ClearContentsLayerIfUnregistered(); - if (contents_layer_) + if (contents_layer_ && !prevent_contents_opaque_changes_) contents_layer_->SetOpaque(opaque); } @@ -1260,7 +1263,7 @@ image_layer_.reset(); } - SetContentsTo(image_layer_ ? image_layer_->Layer() : nullptr); + SetContentsTo(image_layer_ ? image_layer_->Layer() : nullptr, true); } WebLayer* GraphicsLayer::PlatformLayer() const {
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h index d179891..59cff46 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.h +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -171,7 +171,7 @@ Color BackgroundColor() const { return background_color_; } void SetBackgroundColor(const Color&); - // opaque means that we know the layer contents have no alpha + // Opaque means that we know the layer contents have no alpha. bool ContentsOpaque() const { return contents_opaque_; } void SetContentsOpaque(bool); @@ -216,7 +216,14 @@ Image*, Image::ImageDecodingMode decode_mode, RespectImageOrientationEnum = kDoNotRespectImageOrientation); - void SetContentsToPlatformLayer(WebLayer* layer) { SetContentsTo(layer); } + // If |prevent_contents_opaque_changes| is set to true, then calls to + // SetContentsOpaque() will not be passed on to the |layer|. Use when + // the client wants to have control of the opaqueness of the contents + // |layer| independently of what outcome painting produces. + void SetContentsToPlatformLayer(WebLayer* layer, + bool prevent_contents_opaque_changes) { + SetContentsTo(layer, prevent_contents_opaque_changes); + } bool HasContentsLayer() const { return contents_layer_; } // For hosting this GraphicsLayer in a native layer hierarchy. @@ -343,7 +350,7 @@ void UpdateLayerIsDrawable(); void UpdateContentsRect(); - void SetContentsTo(WebLayer*); + void SetContentsTo(WebLayer*, bool prevent_contents_opaque_changes); void SetupContentsLayer(WebLayer*); void ClearContentsLayerIfUnregistered(); WebLayer* ContentsLayerIfRegistered(); @@ -385,6 +392,7 @@ bool has_transform_origin_ : 1; bool contents_opaque_ : 1; + bool prevent_contents_opaque_changes_ : 1; bool should_flatten_transform_ : 1; bool backface_visibility_ : 1; bool draws_content_ : 1; @@ -414,10 +422,10 @@ std::unique_ptr<WebContentLayer> layer_; std::unique_ptr<WebImageLayer> image_layer_; WebLayer* contents_layer_; - // We don't have ownership of m_contentsLayer, but we do want to know if a - // given layer is the same as our current layer in setContentsTo(). Since - // |m_contentsLayer| may be deleted at this point, we stash an ID away when we - // know |m_contentsLayer| is alive and use that for comparisons from that + // We don't have ownership of contents_layer_, but we do want to know if a + // given layer is the same as our current layer in SetContentsTo(). Since + // |contents_layer_| may be deleted at this point, we stash an ID away when we + // know |contents_layer_| is alive and use that for comparisons from that // point on. int contents_layer_id_;
diff --git a/tools/cfi/blacklist.txt b/tools/cfi/blacklist.txt index 03de7354..d7b086b 100644 --- a/tools/cfi/blacklist.txt +++ b/tools/cfi/blacklist.txt
@@ -184,6 +184,10 @@ # Call to libcurl.so from the symupload utility src:*third_party/breakpad/breakpad/src/common/linux/http_upload.cc +# The Kerberos code includes calls to dynamically resolved functions; however, +# the unit tests do not exercise those code paths. Be careful removing. +src:*net/http/http_auth_gssapi_posix.cc + ######### Function pointers cast to incorrect type signatures # libicu is currently compiled such that in libicu the 'UChar' type is a
diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py index 314df30..58d016c 100755 --- a/tools/code_coverage/coverage.py +++ b/tools/code_coverage/coverage.py
@@ -110,7 +110,10 @@ # Name of the final profdata file, and this file needs to be passed to # "llvm-cov" command in order to call "llvm-cov show" to inspect the # line-by-line coverage of specific files. -PROFDATA_FILE_NAME = 'coverage.profdata' +PROFDATA_FILE_NAME = os.extsep.join(['coverage', 'profdata']) + +# Name of the file with summary information generated by llvm-cov export. +SUMMARY_FILE_NAME = os.extsep.join(['summary', 'json']) # Build arg required for generating code coverage data. CLANG_COVERAGE_BUILD_ARG = 'use_clang_coverage' @@ -119,9 +122,12 @@ DIRECTORY_COVERAGE_HTML_REPORT_NAME = os.extsep.join(['report', 'html']) # Name of the html index files for different views. -DIRECTORY_VIEW_INDEX_FILE = os.extsep.join(['directory_view_index', 'html']) COMPONENT_VIEW_INDEX_FILE = os.extsep.join(['component_view_index', 'html']) +DIRECTORY_VIEW_INDEX_FILE = os.extsep.join(['directory_view_index', 'html']) FILE_VIEW_INDEX_FILE = os.extsep.join(['file_view_index', 'html']) +INDEX_HTML_FILE = os.extsep.join(['index', 'html']) + +LOGS_DIR_NAME = 'logs' # Used to extract a mapping between directories and components. COMPONENT_MAPPING_URL = 'https://storage.googleapis.com/chromium-owners/component_map.json' @@ -187,10 +193,10 @@ header. For example: 'Path', 'Component'. """ css_file_name = os.extsep.join(['style', 'css']) - css_absolute_path = os.path.abspath(os.path.join(OUTPUT_DIR, css_file_name)) + css_absolute_path = os.path.join(OUTPUT_DIR, css_file_name) assert os.path.exists(css_absolute_path), ( 'css file doesn\'t exit. Please make sure "llvm-cov show -format=html" ' - 'is called first, and the css file is generated at: "%s"' % + 'is called first, and the css file is generated at: "%s".' % css_absolute_path) self._css_absolute_path = css_absolute_path @@ -275,7 +281,7 @@ if percentage == 100: return 'green' - assert False, 'Invalid coverage percentage: "%d"' % percentage + assert False, 'Invalid coverage percentage: "%d".' % percentage def WriteHtmlCoverageReport(self): """Writes html coverage report. @@ -294,9 +300,10 @@ self._table_entries = sorted(self._table_entries, cmp=EntryCmp) css_path = os.path.join(OUTPUT_DIR, os.extsep.join(['style', 'css'])) - directory_view_path = os.path.join(OUTPUT_DIR, DIRECTORY_VIEW_INDEX_FILE) - component_view_path = os.path.join(OUTPUT_DIR, COMPONENT_VIEW_INDEX_FILE) - file_view_path = os.path.join(OUTPUT_DIR, FILE_VIEW_INDEX_FILE) + + directory_view_path = _GetDirectoryViewPath() + component_view_path = _GetComponentViewPath() + file_view_path = _GetFileViewPath() html_header = self._header_template.render( css_path=_GetRelativePathToDirectoryOfFile(css_path, self._output_path), @@ -339,7 +346,7 @@ cmd.extend(['otool', '-L']) shared_library_re = re.compile(r'\s+(@rpath/.*\.dylib)\s.*') else: - assert False, ('Cannot detect shared libraries used by the given targets.') + assert False, 'Cannot detect shared libraries used by the given targets.' assert shared_library_re is not None @@ -458,7 +465,7 @@ try: clang_update.DownloadAndUnpack(coverage_tools_url, clang_update.LLVM_BUILD_DIR) - logging.info('Coverage tools %s unpacked', package_version) + logging.info('Coverage tools %s unpacked.', package_version) with open(coverage_revision_stamp_file, 'w') as file_handle: file_handle.write('%s,%s' % (package_version, host_platform)) file_handle.write('\n') @@ -485,7 +492,7 @@ # NOTE: For object files, the first one is specified as a positional argument, # and the rest are specified as keyword argument. logging.debug('Generating per file line by line coverage reports using ' - '"llvm-cov show" command') + '"llvm-cov show" command.') subprocess_cmd = [ LLVM_COV_PATH, 'show', '-format=html', '-output-dir={}'.format(OUTPUT_DIR), @@ -504,17 +511,15 @@ # the platform name instead, as it simplifies the report dir structure when # the same report is generated for different platforms. default_report_subdir_path = os.path.join(OUTPUT_DIR, 'coverage') - platform_report_subdir_path = os.path.join(OUTPUT_DIR, _GetHostPlatform()) - if os.path.exists(platform_report_subdir_path): - shutil.rmtree(platform_report_subdir_path) - os.rename(default_report_subdir_path, platform_report_subdir_path) + platform_report_subdir_path = _GetCoverageReportRootDirPath() + _MergeTwoDirectories(default_report_subdir_path, platform_report_subdir_path) - logging.debug('Finished running "llvm-cov show" command') + logging.debug('Finished running "llvm-cov show" command.') def _GenerateFileViewHtmlIndexFile(per_file_coverage_summary): """Generates html index file for file view.""" - file_view_index_file_path = os.path.join(OUTPUT_DIR, FILE_VIEW_INDEX_FILE) + file_view_index_file_path = _GetFileViewPath() logging.debug('Generating file view html index file as: "%s".', file_view_index_file_path) html_generator = _CoverageReportHtmlGenerator(file_view_index_file_path, @@ -536,12 +541,13 @@ def _CalculatePerDirectoryCoverageSummary(per_file_coverage_summary): """Calculates per directory coverage summary.""" - logging.debug('Calculating per-directory coverage summary') + logging.debug('Calculating per-directory coverage summary.') per_directory_coverage_summary = defaultdict(lambda: _CoverageSummary()) for file_path in per_file_coverage_summary: summary = per_file_coverage_summary[file_path] parent_dir = os.path.dirname(file_path) + while True: per_directory_coverage_summary[parent_dir].AddSummary(summary) @@ -549,19 +555,19 @@ break parent_dir = os.path.dirname(parent_dir) - logging.debug('Finished calculating per-directory coverage summary') + logging.debug('Finished calculating per-directory coverage summary.') return per_directory_coverage_summary def _GeneratePerDirectoryCoverageInHtml(per_directory_coverage_summary, per_file_coverage_summary): """Generates per directory coverage breakdown in html.""" - logging.debug('Writing per-directory coverage html reports') + logging.debug('Writing per-directory coverage html reports.') for dir_path in per_directory_coverage_summary: _GenerateCoverageInHtmlForDirectory( dir_path, per_directory_coverage_summary, per_file_coverage_summary) - logging.debug('Finished writing per-directory coverage html reports') + logging.debug('Finished writing per-directory coverage html reports.') def _GenerateCoverageInHtmlForDirectory( @@ -600,8 +606,7 @@ file simply redirects to it, and the reason of this extra layer is for structural consistency with other views. """ - directory_view_index_file_path = os.path.join(OUTPUT_DIR, - DIRECTORY_VIEW_INDEX_FILE) + directory_view_index_file_path = _GetDirectoryViewPath() logging.debug('Generating directory view html index file as: "%s".', directory_view_index_file_path) src_root_html_report_path = _GetCoverageHtmlReportPathForDirectory( @@ -614,7 +619,7 @@ def _CalculatePerComponentCoverageSummary(component_to_directories, per_directory_coverage_summary): """Calculates per component coverage summary.""" - logging.debug('Calculating per-component coverage summary') + logging.debug('Calculating per-component coverage summary.') per_component_coverage_summary = defaultdict(lambda: _CoverageSummary()) for component in component_to_directories: @@ -624,7 +629,7 @@ per_component_coverage_summary[component].AddSummary( per_directory_coverage_summary[absolute_directory_path]) - logging.debug('Finished calculating per-component coverage summary') + logging.debug('Finished calculating per-component coverage summary.') return per_component_coverage_summary @@ -686,8 +691,7 @@ def _GenerateComponentViewHtmlIndexFile(per_component_coverage_summary): """Generates the html index file for component view.""" - component_view_index_file_path = os.path.join(OUTPUT_DIR, - COMPONENT_VIEW_INDEX_FILE) + component_view_index_file_path = _GetComponentViewPath() logging.debug('Generating component view html index file as: "%s".', component_view_index_file_path) html_generator = _CoverageReportHtmlGenerator(component_view_index_file_path, @@ -707,12 +711,20 @@ logging.debug('Finished generating component view html index file.') +def _MergeTwoDirectories(src_path, dst_path): + """Merge src_path directory into dst_path directory.""" + for filename in os.listdir(src_path): + dst_path = os.path.join(dst_path, filename) + if os.path.exists(dst_path): + shutil.rmtree(dst_path) + os.rename(os.path.join(src_path, filename), dst_path) + shutil.rmtree(src_path) + + def _OverwriteHtmlReportsIndexFile(): """Overwrites the root index file to redirect to the default view.""" - html_index_file_path = os.path.join(OUTPUT_DIR, - os.extsep.join(['index', 'html'])) - directory_view_index_file_path = os.path.join(OUTPUT_DIR, - DIRECTORY_VIEW_INDEX_FILE) + html_index_file_path = _GetHtmlIndexPath() + directory_view_index_file_path = _GetDirectoryViewPath() _WriteRedirectHtmlFile(html_index_file_path, directory_view_index_file_path) @@ -732,9 +744,17 @@ f.write(content) +def _CleanUpOutputDir(): + """Perform a cleanup of the output dir.""" + # Remove the default index.html file produced by llvm-cov. + index_path = os.path.join(OUTPUT_DIR, INDEX_HTML_FILE) + if os.path.exists(index_path): + os.remove(index_path) + + def _GetCoverageHtmlReportPathForFile(file_path): """Given a file path, returns the corresponding html report path.""" - assert os.path.isfile(file_path), '"%s" is not a file' % file_path + assert os.path.isfile(file_path), '"%s" is not a file.' % file_path html_report_path = os.extsep.join([os.path.abspath(file_path), 'html']) # '+' is used instead of os.path.join because both of them are absolute paths @@ -745,7 +765,7 @@ def _GetCoverageHtmlReportPathForDirectory(dir_path): """Given a directory path, returns the corresponding html report path.""" - assert os.path.isdir(dir_path), '"%s" is not a directory' % dir_path + assert os.path.isdir(dir_path), '"%s" is not a directory.' % dir_path html_report_path = os.path.join( os.path.abspath(dir_path), DIRECTORY_COVERAGE_HTML_REPORT_NAME) @@ -765,7 +785,44 @@ def _GetCoverageReportRootDirPath(): """The root directory that contains all generated coverage html reports.""" - return os.path.join(os.path.abspath(OUTPUT_DIR), _GetHostPlatform()) + return os.path.join(OUTPUT_DIR, _GetHostPlatform()) + + +def _GetComponentViewPath(): + """Path to the HTML file for the component view.""" + return os.path.join(_GetCoverageReportRootDirPath(), + COMPONENT_VIEW_INDEX_FILE) + + +def _GetDirectoryViewPath(): + """Path to the HTML file for the directory view.""" + return os.path.join(_GetCoverageReportRootDirPath(), + DIRECTORY_VIEW_INDEX_FILE) + + +def _GetFileViewPath(): + """Path to the HTML file for the file view.""" + return os.path.join(_GetCoverageReportRootDirPath(), FILE_VIEW_INDEX_FILE) + + +def _GetLogsDirectoryPath(): + """Path to the logs directory.""" + return os.path.join(_GetCoverageReportRootDirPath(), LOGS_DIR_NAME) + + +def _GetHtmlIndexPath(): + """Path to the main HTML index file.""" + return os.path.join(_GetCoverageReportRootDirPath(), INDEX_HTML_FILE) + + +def _GetProfdataFilePath(): + """Path to the resulting .profdata file.""" + return os.path.join(_GetCoverageReportRootDirPath(), PROFDATA_FILE_NAME) + + +def _GetSummaryFilePath(): + """The JSON file that contains coverage summary written by llvm-cov export.""" + return os.path.join(_GetCoverageReportRootDirPath(), SUMMARY_FILE_NAME) def _CreateCoverageProfileDataForTargets(targets, commands, jobs_count=None): @@ -813,7 +870,7 @@ build_args = _GetBuildArgs() return 'use_goma' in build_args and build_args['use_goma'] == 'true' - logging.info('Building %s', str(targets)) + logging.info('Building %s.', str(targets)) if jobs_count is None and _IsGomaConfigured(): jobs_count = DEFAULT_GOMA_JOBS @@ -823,7 +880,7 @@ subprocess_cmd.extend(targets) subprocess.check_call(subprocess_cmd) - logging.debug('Finished building %s', str(targets)) + logging.debug('Finished building %s.', str(targets)) def _GetTargetProfDataPathsByExecutingCommands(targets, commands): @@ -836,23 +893,27 @@ Returns: A list of relative paths to the generated profraw data files. """ - logging.debug('Executing the test commands') + logging.debug('Executing the test commands.') # Remove existing profraw data files. - for file_or_dir in os.listdir(OUTPUT_DIR): + for file_or_dir in os.listdir(_GetCoverageReportRootDirPath()): if file_or_dir.endswith(PROFRAW_FILE_EXTENSION): - os.remove(os.path.join(OUTPUT_DIR, file_or_dir)) + os.remove(os.path.join(_GetCoverageReportRootDirPath(), file_or_dir)) + + # Ensure that logs directory exists. + if not os.path.exists(_GetLogsDirectoryPath()): + os.makedirs(_GetLogsDirectoryPath()) profdata_file_paths = [] # Run all test targets to generate profraw data files. for target, command in zip(targets, commands): - output_file_name = os.extsep.join([target + '_output', 'txt']) - output_file_path = os.path.join(OUTPUT_DIR, output_file_name) + output_file_name = os.extsep.join([target + '_output', 'log']) + output_file_path = os.path.join(_GetLogsDirectoryPath(), output_file_name) profdata_file_path = None for _ in xrange(MERGE_RETRIES): - logging.info('Running command: "%s", the output is redirected to "%s"', + logging.info('Running command: "%s", the output is redirected to "%s".', command, output_file_path) if _IsIOSCommand(command): @@ -871,12 +932,13 @@ if _IsIOS(): profraw_file_paths = _GetProfrawDataFileByParsingOutput(output) else: - for file_or_dir in os.listdir(OUTPUT_DIR): + for file_or_dir in os.listdir(_GetCoverageReportRootDirPath()): if file_or_dir.endswith(PROFRAW_FILE_EXTENSION): - profraw_file_paths.append(os.path.join(OUTPUT_DIR, file_or_dir)) + profraw_file_paths.append( + os.path.join(_GetCoverageReportRootDirPath(), file_or_dir)) assert profraw_file_paths, ( - 'Running target %s failed to generate any profraw data file, ' + 'Running target "%s" failed to generate any profraw data file, ' 'please make sure the binary exists and is properly ' 'instrumented.' % target) @@ -892,14 +954,14 @@ os.remove(profraw_file_path) assert profdata_file_path, ( - 'Failed to merge target %s profraw files after %d retries. ' + 'Failed to merge target "%s" profraw files after %d retries. ' 'Please file a bug with command you used, commit position and args.gn ' 'config here: ' 'https://bugs.chromium.org/p/chromium/issues/entry?' - 'components=Tools%%3ECodeCoverage'% (target, MERGE_RETRIES)) + 'components=Tools%%3ECodeCoverage' % (target, MERGE_RETRIES)) profdata_file_paths.append(profdata_file_path) - logging.debug('Finished executing the test commands') + logging.debug('Finished executing the test commands.') return profdata_file_paths @@ -929,16 +991,18 @@ profile_pattern_string = '%1m' if _IsFuzzerTarget(target) else '%4m' expected_profraw_file_name = os.extsep.join( [target, profile_pattern_string, PROFRAW_FILE_EXTENSION]) - expected_profraw_file_path = os.path.join(OUTPUT_DIR, + expected_profraw_file_path = os.path.join(_GetCoverageReportRootDirPath(), expected_profraw_file_name) try: + # Some fuzz targets or tests may write into stderr, redirect it as well. output = subprocess.check_output( shlex.split(command), + stderr=subprocess.STDOUT, env={'LLVM_PROFILE_FILE': expected_profraw_file_path}) except subprocess.CalledProcessError as e: output = e.output - logging.warning('Command: "%s" exited with non-zero return code', command) + logging.warning('Command: "%s" exited with non-zero return code.', command) return output @@ -1016,10 +1080,9 @@ Raises: CalledProcessError: An error occurred merging profdata files. """ - logging.info('Creating the coverage profile data file') - logging.debug( - 'Merging target profdata files to create coverage profdata file') - profdata_file_path = os.path.join(OUTPUT_DIR, PROFDATA_FILE_NAME) + logging.info('Creating the coverage profile data file.') + logging.debug('Merging target profraw files to create target profdata file.') + profdata_file_path = _GetProfdataFilePath() try: subprocess_cmd = [ LLVM_PROFDATA_PATH, 'merge', '-o', profdata_file_path, '-sparse=true' @@ -1031,8 +1094,8 @@ 'Try again.') raise error - logging.debug('Finished merging target profdata files') - logging.info('Code coverage profile data is created as: %s', + logging.debug('Finished merging target profdata files.') + logging.info('Code coverage profile data is created as: "%s".', profdata_file_path) return profdata_file_path @@ -1051,8 +1114,8 @@ Raises: CalledProcessError: An error occurred merging profdata files. """ - logging.info('Creating target profile data file') - logging.debug('Merging target profraw files to create target profdata file') + logging.info('Creating target profile data file.') + logging.debug('Merging target profraw files to create target profdata file.') profdata_file_path = os.path.join(OUTPUT_DIR, '%s.profdata' % target) try: @@ -1065,8 +1128,8 @@ print('Failed to merge target profraw files to create target profdata.') raise error - logging.debug('Finished merging target profraw files') - logging.info('Target %s profile data is created as: %s', target, + logging.debug('Finished merging target profraw files.') + logging.info('Target "%s" profile data is created as: "%s".', target, profdata_file_path) return profdata_file_path @@ -1079,7 +1142,7 @@ # NOTE: For object files, the first one is specified as a positional argument, # and the rest are specified as keyword argument. logging.debug('Generating per-file code coverage summary using "llvm-cov ' - 'export -summary-only" command') + 'export -summary-only" command.') subprocess_cmd = [ LLVM_COV_PATH, 'export', '-summary-only', '-instr-profile=' + profdata_file_path, binary_paths[0] @@ -1091,15 +1154,24 @@ if ignore_filename_regex: subprocess_cmd.append('-ignore-filename-regex=%s' % ignore_filename_regex) - json_output = json.loads(subprocess.check_output(subprocess_cmd)) + export_output = subprocess.check_output(subprocess_cmd) + + # Write output on the disk to be used by code coverage bot. + with open(_GetSummaryFilePath(), 'w') as f: + f.write(export_output) + + json_output = json.loads(export_output) assert len(json_output['data']) == 1 files_coverage_data = json_output['data'][0]['files'] per_file_coverage_summary = {} for file_coverage_data in files_coverage_data: file_path = file_coverage_data['filename'] - summary = file_coverage_data['summary'] + assert file_path.startswith(SRC_ROOT_PATH + os.sep), ( + 'File path "%s" in coverage summary is outside source checkout.' % + file_path) + summary = file_coverage_data['summary'] if summary['lines']['count'] == 0: continue @@ -1111,7 +1183,7 @@ lines_total=summary['lines']['count'], lines_covered=summary['lines']['covered']) - logging.debug('Finished generating per-file code coverage summary') + logging.debug('Finished generating per-file code coverage summary.') return per_file_coverage_summary @@ -1151,7 +1223,7 @@ command_parts = shlex.split(command) if os.path.basename(command_parts[0]) == 'python': assert os.path.basename(command_parts[1]) == xvfb_script_name, ( - 'This tool doesn\'t understand the command: "%s"' % command) + 'This tool doesn\'t understand the command: "%s".' % command) return command_parts[2] if os.path.basename(command_parts[0]) == xvfb_script_name: @@ -1178,7 +1250,7 @@ for command in commands: binary_path = _GetBinaryPath(command) binary_absolute_path = os.path.abspath(os.path.normpath(binary_path)) - assert binary_absolute_path.startswith(os.path.abspath(BUILD_DIR)), ( + assert binary_absolute_path.startswith(BUILD_DIR), ( 'Target executable "%s" in command: "%s" is outside of ' 'the given build directory: "%s".' % (binary_path, command, BUILD_DIR)) @@ -1283,7 +1355,7 @@ binary_paths.append(binary_path) else: logging.warning( - 'Target binary %s not found in build directory, skipping.', + 'Target binary "%s" not found in build directory, skipping.', os.path.basename(binary_path)) return binary_paths @@ -1391,9 +1463,9 @@ _ConfigureLogging(args) global BUILD_DIR - BUILD_DIR = args.build_dir + BUILD_DIR = os.path.abspath(args.build_dir) global OUTPUT_DIR - OUTPUT_DIR = args.output_dir + OUTPUT_DIR = os.path.abspath(args.output_dir) assert args.command or args.profdata_file, ( 'Need to either provide commands to run using -c/--command option OR ' @@ -1403,8 +1475,8 @@ 'Number of targets must be equal to the number of test commands.') assert os.path.exists(BUILD_DIR), ( - 'Build directory: {} doesn\'t exist. ' - 'Please run "gn gen" to generate.').format(BUILD_DIR) + 'Build directory: "%s" doesn\'t exist. ' + 'Please run "gn gen" to generate.' % BUILD_DIR) _ValidateCurrentPlatformIsSupported() _ValidateBuildingWithClangCoverage() @@ -1413,8 +1485,8 @@ if args.filters: absolute_filter_paths = _VerifyPathsAndReturnAbsolutes(args.filters) - if not os.path.exists(OUTPUT_DIR): - os.makedirs(OUTPUT_DIR) + if not os.path.exists(_GetCoverageReportRootDirPath()): + os.makedirs(_GetCoverageReportRootDirPath()) # Get profdate file and list of binary paths. if args.command: @@ -1430,7 +1502,7 @@ binary_paths = _GetBinaryPathsFromTargets(args.targets, args.build_dir) logging.info('Generating code coverage report in html (this can take a while ' - 'depending on size of target!)') + 'depending on size of target!).') binary_paths.extend(_GetSharedLibraries(binary_paths)) per_file_coverage_summary = _GeneratePerFileCoverageSummary( binary_paths, profdata_file_path, absolute_filter_paths, @@ -1457,10 +1529,10 @@ # The default index file is generated only for the list of source files, needs # to overwrite it to display per directory coverage view by default. _OverwriteHtmlReportsIndexFile() + _CleanUpOutputDir() - html_index_file_path = 'file://' + os.path.abspath( - os.path.join(OUTPUT_DIR, 'index.html')) - logging.info('Index file for html report is generated as: %s', + html_index_file_path = 'file://' + os.path.abspath(_GetHtmlIndexPath()) + logging.info('Index file for html report is generated as: "%s".', html_index_file_path)
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 3bb4fa96..d2cf623 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -6918,7 +6918,7 @@ <enum name="ContentSuggestionsCategory"> <int value="0" label="Experimental"/> - <int value="1" label="Recent Tabs"/> + <int value="1" label="Recent Tabs (obsolete)"/> <int value="2" label="Downloads"/> <int value="3" label="Bookmarks"/> <int value="4" label="Physical Web Pages (obsolete)"/> @@ -48031,8 +48031,9 @@ <enum name="WindowsNotificationActivationStatus"> <int value="0" label="SUCCESS"/> - <int value="1" label="GET_PROFILE_ID_INVALID_LAUNCH_ID"/> - <int value="2" label="ACTIVATION_INVALID_LAUNCH_ID"/> + <int value="1" label="GET_PROFILE_ID_INVALID_LAUNCH_ID (deprecated)"/> + <int value="2" label="ACTIVATION_INVALID_LAUNCH_ID (deprecated)"/> + <int value="3" label="INVALID_LAUNCH_ID"/> </enum> <enum name="WindowsNotificationCloseStatus">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 3341fc2..8fd68f7 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -57329,6 +57329,7 @@ enum="WindowsNotificationActivationStatus"> <owner>finnur@chromium.org</owner> <owner>peter@chromium.org</owner> + <owner>chengx@chromium.org</owner> <summary> The status of Activation requests in NotificationPlatformBridgeWin (Windows only). Logged whenever an activation from a notification occurs.
diff --git a/ui/gl/gl_switches_util.cc b/ui/gl/gl_switches_util.cc index df9e4f9a..cdf0932 100644 --- a/ui/gl/gl_switches_util.cc +++ b/ui/gl/gl_switches_util.cc
@@ -13,7 +13,7 @@ bool IsPresentationCallbackEnabled() { // TODO(peng): always enable once 776877 is fixed. -#if defined(OS_CHROMEOS) || defined(OS_ANDROID) +#if defined(OS_CHROMEOS) || defined(OS_ANDROID) || defined(OS_LINUX) return true; #else return base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/ui/views/controls/webview/webview_unittest.cc b/ui/views/controls/webview/webview_unittest.cc index 3e82c4f5..f1d0ce7 100644 --- a/ui/views/controls/webview/webview_unittest.cc +++ b/ui/views/controls/webview/webview_unittest.cc
@@ -130,8 +130,8 @@ std::unique_ptr<content::WebContents> CreateWebContentsForWebView( content::BrowserContext* browser_context) { - return base::WrapUnique(content::WebContentsTester::CreateTestWebContents( - browser_context, nullptr)); + return content::WebContentsTester::CreateTestWebContents(browser_context, + nullptr); } void SetUp() override {
diff --git a/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.js b/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.js index 349c3e7..772bc6d 100644 --- a/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.js +++ b/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.js
@@ -55,8 +55,15 @@ this.setAttribute('aria-checked', this.checked ? 'true' : 'false'); }, - /** @private */ - disabledChanged_: function() { + /** + * @param {boolean} current + * @param {boolean} previous + * @private + */ + disabledChanged_: function(current, previous) { + if (previous === undefined && !this.disabled) + return; + this.setAttribute('tabindex', this.disabled ? -1 : 0); this.setAttribute('aria-disabled', this.disabled ? 'true' : 'false'); },
diff --git a/ui/webui/resources/cr_elements/cr_toggle/cr_toggle.html b/ui/webui/resources/cr_elements/cr_toggle/cr_toggle.html index 0ea8fbf..4b3f0bd 100644 --- a/ui/webui/resources/cr_elements/cr_toggle/cr_toggle.html +++ b/ui/webui/resources/cr_elements/cr_toggle/cr_toggle.html
@@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-behaviors/paper-ripple-behavior.html"> +<link rel="import" href="../shared_vars_css.html"> <dom-module id="cr-toggle"> <template> @@ -13,6 +14,7 @@ :host([disabled]) { cursor: initial; + opacity: 0.38; pointer-events: none; } @@ -29,11 +31,11 @@ } #bar { - background-color: var(--cr-toggle-unchecked-bar-color, black); + background-color: + var(--cr-toggle-unchecked-bar-color, var(--google-grey-400)); border-radius: 8px; height: 12px; left: 3px; - opacity: 0.4; position: absolute; top: 2px; transition: background-color linear 80ms; @@ -43,17 +45,12 @@ :host([checked]) #bar { background-color: var( - --cr-toggle-checked-bar-color, var(--google-blue-500)); - } - - :host([disabled]) #bar { - background-color: black; - opacity: 0.12; + --cr-toggle-checked-bar-color, var(--google-blue-600)); + opacity: 0.5; } #knob { - background-color: var( - --cr-toggle-unchecked-button-color, var(--paper-grey-50)); + background-color: var(--cr-toggle-unchecked-button-color, white); border-radius: 50%; box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.4); display: block; @@ -66,7 +63,7 @@ :host([checked]) #knob { background-color: var( - --cr-toggle-checked-button-color, var(--google-blue-500)); + --cr-toggle-checked-button-color, var(--google-blue-600)); transform: translate3d(18px, 0, 0); } @@ -74,11 +71,6 @@ transform: translate3d(-18px, 0, 0); } - :host([disabled]) #knob { - background-color: #bdbdbd; - opacity: 1; - } - paper-ripple { --paper-ripple-opacity: 0.125; color: var(--cr-toggle-unchecked-ink-color, var(--primary-text-color));
diff --git a/ui/webui/resources/cr_elements/shared_vars_css.html b/ui/webui/resources/cr_elements/shared_vars_css.html index b201c750..30d9d45 100644 --- a/ui/webui/resources/cr_elements/shared_vars_css.html +++ b/ui/webui/resources/cr_elements/shared_vars_css.html
@@ -120,6 +120,7 @@ /** MD Refresh Styles */ --google-blue-600: #1A73E8; + --google-grey-400: #BDC1C6; --cr-controls-background-grey: #2A3146; } </style>