diff --git a/AUTHORS b/AUTHORS index 171836c..c556566 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -992,6 +992,7 @@ Thiago Marcos P. Santos <thiago.santos@intel.com> Thomas Butter <tbutter@gmail.com> Thomas Conti <tomc@amazon.com> +Thomas Nguyen <haitung.nguyen@avast.com> Thomas White <im.toms.inbox@gmail.com> Tiago Vignatti <tiago.vignatti@intel.com> Tibor Dusnoki <tibor.dusnoki.91@gmail.com>
diff --git a/DEPS b/DEPS index 7b58126..6378e4f 100644 --- a/DEPS +++ b/DEPS
@@ -195,11 +195,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': '747a820a7d69c1e969cf4a1108958b2818ded3f6', + 'skia_revision': 'd7c4f9d06425d8ed5134475e94fb34f265fa1fbc', # 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': 'c07c0c9311b44b0d618819b7b916d154326ee177', + 'v8_revision': '759f70344a9a68576605324f760c5942981ea9fd', # 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. @@ -207,7 +207,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '19a1943b27a0b9fc821dcaeb5726acbcf4342494', + 'angle_revision': 'be774187b1cefe94f4717cbd747ebdea0b349478', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -266,7 +266,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'f70087925046672bfdd8277b17fabb31ef0795b3', + 'devtools_frontend_revision': '3186e69eb7995747d51b2c7126b8fef05c5032d1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -322,7 +322,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': '74ee66401627cc3ac60a153dfc57ecfb9650b347', + 'quiche_revision': '2146ce8055a5e96371eb31a169c46f322afac527', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -875,7 +875,7 @@ # Build tools for Chrome OS. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'bf47d2ef673b889870f4169e10a20f9c04d9db45', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'de0ed93bda6323335cf84bc3d33e3aa848786a65', 'condition': 'checkout_chromeos', }, @@ -1248,7 +1248,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'f6c424bb59238a75fbb10d4d802b5ad31107a3a3', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '22b8657a5558de83e88093a85d302f0d0773bb9f', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1465,7 +1465,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'ee8c246be71e4dd8d4ca34011d3b3e40faf576a2', + Var('webrtc_git') + '/src.git' + '@' + '81bbd7199a2e97680a4488c2da4f8248137e12e0', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1537,7 +1537,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f8ef67b87b415744c3325cb484a38dce93e5bacb', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@08057456d373475cd7e551639c334f360b1d4f92', 'condition': 'checkout_src_internal', }, @@ -4097,8 +4097,12 @@ '+third_party/icu/source/i18n/unicode', '+url', - # Chromium cannot directly depend on Abseil. + # Abseil features must be allowlisted explicitly for now. See + # //styleguide/c++/c++11.html. Allowed features' headers will be listed + # explicitly here. '-absl', + '-third_party/abseil-cpp', + '+third_party/abseil-cpp/absl/types/variant.h', ]
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java index 7c88ee5..365b2b7 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
@@ -37,6 +37,7 @@ import org.chromium.android_webview.test.TestAwContentsClient.OnDownloadStartHelper; import org.chromium.android_webview.test.util.CommonResources; import org.chromium.base.BuildInfo; +import org.chromium.base.Log; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; @@ -55,6 +56,7 @@ import java.util.Map; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; /** @@ -62,6 +64,8 @@ */ @RunWith(AwJUnit4ClassRunner.class) public class AwContentsTest { + private static final String TAG = "AwContentsTest"; + @Rule public AwActivityTestRule mActivityTestRule = new AwActivityTestRule(); @@ -837,7 +841,12 @@ callbackHelper.notifyCalled(); }); }); - callbackHelper.waitForFirst(); + try { + callbackHelper.waitForFirst(); + } catch (TimeoutException e) { + Log.w(TAG, "Timeout", e); + continue; + } int[] quadrantColors = (int[]) resultHolder[0]; lastQuadrantColors = quadrantColors; if (quadrantColors != null && Color.rgb(255, 0, 0) == quadrantColors[0]
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index c2fabf06..67fa7f7 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1944,6 +1944,7 @@ "system/message_center/ash_message_popup_collection_unittest.cc", "system/message_center/inactive_user_notification_blocker_unittest.cc", "system/message_center/message_center_ui_controller_unittest.cc", + "system/message_center/notification_swipe_control_view_unittest.cc", "system/message_center/notifier_settings_view_unittest.cc", "system/message_center/session_state_notification_blocker_unittest.cc", "system/message_center/unified_message_center_bubble_unittest.cc",
diff --git a/ash/app_list/views/assistant/assistant_page_view.cc b/ash/app_list/views/assistant/assistant_page_view.cc index d8becd6..fe3a302 100644 --- a/ash/app_list/views/assistant/assistant_page_view.cc +++ b/ash/app_list/views/assistant/assistant_page_view.cc
@@ -22,9 +22,11 @@ #include "ash/public/cpp/assistant/controller/assistant_ui_controller.h" #include "ash/public/cpp/view_shadow.h" #include "ash/strings/grit/ash_strings.h" +#include "base/metrics/histogram_functions.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/l10n/l10n_util.h" #include "ui/chromeos/search_box/search_box_constants.h" +#include "ui/compositor/animation_throughput_reporter.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor_extra/shadow.h" #include "ui/views/background.h" @@ -282,6 +284,14 @@ // of a bounds animation. { auto settings = contents_view()->CreateTransitionAnimationSettings(layer()); + + ui::AnimationThroughputReporter reporter( + settings->GetAnimator(), + metrics_util::ForSmoothness(base::BindRepeating([](int value) { + base::UmaHistogramPercentage( + assistant::ui::kAssistantResizePageViewHistogram, value); + }))); + layer()->SetClipRect(gfx::Rect(to_rect.size())); // Also animate corner radius for the view.
diff --git a/ash/assistant/ui/BUILD.gn b/ash/assistant/ui/BUILD.gn index ee005b3..07cd341 100644 --- a/ash/assistant/ui/BUILD.gn +++ b/ash/assistant/ui/BUILD.gn
@@ -70,6 +70,8 @@ "main_stage/assistant_text_element_view.h", "main_stage/assistant_ui_element_view.cc", "main_stage/assistant_ui_element_view.h", + "main_stage/assistant_ui_element_view_animator.cc", + "main_stage/assistant_ui_element_view_animator.h", "main_stage/assistant_ui_element_view_factory.cc", "main_stage/assistant_ui_element_view_factory.h", "main_stage/assistant_zero_state_view.cc",
diff --git a/ash/assistant/ui/assistant_ui_constants.h b/ash/assistant/ui/assistant_ui_constants.h index 8667802..40335e6f 100644 --- a/ash/assistant/ui/assistant_ui_constants.h +++ b/ash/assistant/ui/assistant_ui_constants.h
@@ -43,6 +43,16 @@ constexpr int kWarmerWelcomesMaxTimesTriggered = 3; +// Histogram names for measuring animation performance. +constexpr char kAssistantCardElementHistogram[] = + "Ash.Assistant.AnimationSmoothness.CardElement"; +constexpr char kAssistantTextElementHistogram[] = + "Ash.Assistant.AnimationSmoothness.TextElement"; +constexpr char kAssistantResizePageViewHistogram[] = + "Ash.Assistant.AnimationSmoothness.ResizeAssistantPageView"; +constexpr char kAssistantSuggestionChipHistogram[] = + "Ash.Assistant.AnimationSmoothness.SuggestionChip"; + } // namespace ui } // namespace assistant
diff --git a/ash/assistant/ui/main_stage/assistant_card_element_view.cc b/ash/assistant/ui/main_stage/assistant_card_element_view.cc index 492927f..f94c76a5 100644 --- a/ash/assistant/ui/main_stage/assistant_card_element_view.cc +++ b/ash/assistant/ui/main_stage/assistant_card_element_view.cc
@@ -9,6 +9,7 @@ #include "ash/assistant/model/ui/assistant_card_element.h" #include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/assistant/ui/assistant_view_delegate.h" +#include "ash/assistant/ui/main_stage/assistant_ui_element_view_animator.h" #include "ash/assistant/util/deep_link_util.h" #include "ash/public/cpp/assistant/controller/assistant_controller.h" #include "ui/aura/window.h" @@ -214,4 +215,9 @@ GetViewAccessibility().OverrideName(card_element_->fallback()); } +std::unique_ptr<ElementAnimator> AssistantCardElementView::CreateAnimator() { + return std::make_unique<AssistantUiElementViewAnimator>( + this, assistant::ui::kAssistantCardElementHistogram); +} + } // namespace ash
diff --git a/ash/assistant/ui/main_stage/assistant_card_element_view.h b/ash/assistant/ui/main_stage/assistant_card_element_view.h index 4d2d61a..df26e6b 100644 --- a/ash/assistant/ui/main_stage/assistant_card_element_view.h +++ b/ash/assistant/ui/main_stage/assistant_card_element_view.h
@@ -35,6 +35,7 @@ void ChildPreferredSizeChanged(views::View* child) override; void OnGestureEvent(ui::GestureEvent* event) override; void ScrollRectToVisible(const gfx::Rect& rect) override; + std::unique_ptr<ElementAnimator> CreateAnimator() override; // AssistantWebView::Observer: void DidSuppressNavigation(const GURL& url,
diff --git a/ash/assistant/ui/main_stage/assistant_text_element_view.cc b/ash/assistant/ui/main_stage/assistant_text_element_view.cc index 0e1173e..4913803 100644 --- a/ash/assistant/ui/main_stage/assistant_text_element_view.cc +++ b/ash/assistant/ui/main_stage/assistant_text_element_view.cc
@@ -8,6 +8,7 @@ #include "ash/assistant/model/ui/assistant_text_element.h" #include "ash/assistant/ui/assistant_ui_constants.h" +#include "ash/assistant/ui/main_stage/assistant_ui_element_view_animator.h" #include "base/strings/utf_string_conversions.h" #include "ui/views/background.h" #include "ui/views/controls/label.h" @@ -65,4 +66,9 @@ label_->SetMultiLine(true); } +std::unique_ptr<ElementAnimator> AssistantTextElementView::CreateAnimator() { + return std::make_unique<AssistantUiElementViewAnimator>( + this, assistant::ui::kAssistantTextElementHistogram); +} + } // namespace ash
diff --git a/ash/assistant/ui/main_stage/assistant_text_element_view.h b/ash/assistant/ui/main_stage/assistant_text_element_view.h index 05c1a24e..ad5e005 100644 --- a/ash/assistant/ui/main_stage/assistant_text_element_view.h +++ b/ash/assistant/ui/main_stage/assistant_text_element_view.h
@@ -18,6 +18,7 @@ namespace ash { class AssistantTextElement; +class ElementAnimator; // AssistantTextElementView is the visual representation of an // AssistantTextElement. It is a child view of UiElementContainerView. @@ -35,6 +36,7 @@ ui::Layer* GetLayerForAnimating() override; std::string ToStringForTesting() const override; void ChildPreferredSizeChanged(views::View* child) override; + std::unique_ptr<ElementAnimator> CreateAnimator() override; private: void InitLayout(const std::string& text);
diff --git a/ash/assistant/ui/main_stage/assistant_ui_element_view.cc b/ash/assistant/ui/main_stage/assistant_ui_element_view.cc index b8d4c60..28ac5ff 100644 --- a/ash/assistant/ui/main_stage/assistant_ui_element_view.cc +++ b/ash/assistant/ui/main_stage/assistant_ui_element_view.cc
@@ -4,65 +4,8 @@ #include "ash/assistant/ui/main_stage/assistant_ui_element_view.h" -#include "ash/assistant/ui/main_stage/element_animator.h" -#include "ash/assistant/util/animation_util.h" -#include "ui/compositor/callback_layer_animation_observer.h" -#include "ui/compositor/layer_animation_element.h" -#include "ui/compositor/layer_animator.h" - namespace ash { -namespace { - -using assistant::util::CreateLayerAnimationSequence; -using assistant::util::CreateOpacityElement; -using assistant::util::StartLayerAnimationSequence; - -// Animation. -constexpr base::TimeDelta kAnimateInDuration = - base::TimeDelta::FromMilliseconds(250); -constexpr base::TimeDelta kAnimateOutDuration = - base::TimeDelta::FromMilliseconds(200); - -// AssistantUiElementViewAnimator ---------------------------------------------- - -class AssistantUiElementViewAnimator : public ElementAnimator { - public: - explicit AssistantUiElementViewAnimator(AssistantUiElementView* view) - : ElementAnimator(view), view_(view) {} - explicit AssistantUiElementViewAnimator( - AssistantUiElementViewAnimator& copy) = delete; - AssistantUiElementViewAnimator& operator=( - AssistantUiElementViewAnimator& assign) = delete; - ~AssistantUiElementViewAnimator() override = default; - - // ElementAnimator: - void AnimateIn(ui::CallbackLayerAnimationObserver* observer) override { - StartLayerAnimationSequence( - layer()->GetAnimator(), - CreateLayerAnimationSequence(CreateOpacityElement( - 1.f, kAnimateInDuration, gfx::Tween::Type::FAST_OUT_SLOW_IN)), - observer); - } - - void AnimateOut(ui::CallbackLayerAnimationObserver* observer) override { - StartLayerAnimationSequence( - layer()->GetAnimator(), - CreateLayerAnimationSequence(CreateOpacityElement( - kMinimumAnimateOutOpacity, kAnimateOutDuration)), - observer); - } - - ui::Layer* layer() const override { return view_->GetLayerForAnimating(); } - - private: - AssistantUiElementView* const view_; -}; - -} // namespace - -// AssistantUiElementView ------------------------------------------------------ - AssistantUiElementView::AssistantUiElementView() = default; AssistantUiElementView::~AssistantUiElementView() = default; @@ -71,8 +14,4 @@ return "AssistantUiElementView"; } -std::unique_ptr<ElementAnimator> AssistantUiElementView::CreateAnimator() { - return std::make_unique<AssistantUiElementViewAnimator>(this); -} - } // namespace ash
diff --git a/ash/assistant/ui/main_stage/assistant_ui_element_view.h b/ash/assistant/ui/main_stage/assistant_ui_element_view.h index ca36f22..18e8aa5 100644 --- a/ash/assistant/ui/main_stage/assistant_ui_element_view.h +++ b/ash/assistant/ui/main_stage/assistant_ui_element_view.h
@@ -35,7 +35,7 @@ // Returns a newly created animator which is used by UiElementContainerView // to animate this view on/off stage in sync with Assistant response events. - virtual std::unique_ptr<ElementAnimator> CreateAnimator(); + virtual std::unique_ptr<ElementAnimator> CreateAnimator() = 0; protected: AssistantUiElementView();
diff --git a/ash/assistant/ui/main_stage/assistant_ui_element_view_animator.cc b/ash/assistant/ui/main_stage/assistant_ui_element_view_animator.cc new file mode 100644 index 0000000..152f514 --- /dev/null +++ b/ash/assistant/ui/main_stage/assistant_ui_element_view_animator.cc
@@ -0,0 +1,66 @@ +// Copyright 2020 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/assistant/ui/main_stage/assistant_ui_element_view_animator.h" + +#include "ash/assistant/ui/main_stage/assistant_ui_element_view.h" +#include "ash/assistant/ui/main_stage/element_animator.h" +#include "ash/assistant/util/animation_util.h" +#include "base/metrics/histogram_functions.h" +#include "ui/compositor/callback_layer_animation_observer.h" +#include "ui/gfx/animation/tween.h" + +namespace ash { + +namespace { + +using assistant::util::CreateLayerAnimationSequence; +using assistant::util::CreateOpacityElement; +using assistant::util::StartLayerAnimationSequence; + +// Animation. +constexpr base::TimeDelta kAnimateInDuration = + base::TimeDelta::FromMilliseconds(250); +constexpr base::TimeDelta kAnimateOutDuration = + base::TimeDelta::FromMilliseconds(200); + +} // namespace + +AssistantUiElementViewAnimator::AssistantUiElementViewAnimator( + AssistantUiElementView* view, + const char* animation_smoothness_histogram) + : ElementAnimator(view), + view_(view), + animation_smoothness_histogram_(animation_smoothness_histogram) {} + +AssistantUiElementViewAnimator::AnimationSmoothnessCallback +AssistantUiElementViewAnimator::GetAnimationSmoothnessCallback() const { + return base::BindRepeating<void(const std::string&, int value)>( + base::UmaHistogramPercentage, animation_smoothness_histogram_); +} + +// ElementAnimator: +void AssistantUiElementViewAnimator::AnimateIn( + ui::CallbackLayerAnimationObserver* observer) { + StartLayerAnimationSequence( + layer()->GetAnimator(), + CreateLayerAnimationSequence(CreateOpacityElement( + 1.f, kAnimateInDuration, gfx::Tween::Type::FAST_OUT_SLOW_IN)), + observer, GetAnimationSmoothnessCallback()); +} + +void AssistantUiElementViewAnimator::AnimateOut( + ui::CallbackLayerAnimationObserver* observer) { + StartLayerAnimationSequence( + layer()->GetAnimator(), + CreateLayerAnimationSequence( + CreateOpacityElement(kMinimumAnimateOutOpacity, kAnimateOutDuration)), + observer, GetAnimationSmoothnessCallback()); +} + +ui::Layer* AssistantUiElementViewAnimator::layer() const { + return view_->GetLayerForAnimating(); +} + +} // namespace ash
diff --git a/ash/assistant/ui/main_stage/assistant_ui_element_view_animator.h b/ash/assistant/ui/main_stage/assistant_ui_element_view_animator.h new file mode 100644 index 0000000..ff0c122 --- /dev/null +++ b/ash/assistant/ui/main_stage/assistant_ui_element_view_animator.h
@@ -0,0 +1,49 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_UI_ELEMENT_VIEW_ANIMATOR_H_ +#define ASH_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_UI_ELEMENT_VIEW_ANIMATOR_H_ + +#include "ash/assistant/ui/main_stage/element_animator.h" +#include "ash/assistant/util/animation_util.h" +#include "base/callback.h" + +namespace ui { +class CallbackLayerAnimationObserver; +class Layer; +} // namespace ui + +namespace ash { + +class AssistantUiElementView; + +class AssistantUiElementViewAnimator : public ElementAnimator { + public: + using AnimationSmoothnessCallback = + assistant::util::AnimationSmoothnessCallback; + + AssistantUiElementViewAnimator(AssistantUiElementView* view, + const char* animation_smoothness_histogram); + + explicit AssistantUiElementViewAnimator( + AssistantUiElementViewAnimator& copy) = delete; + AssistantUiElementViewAnimator& operator=( + AssistantUiElementViewAnimator& assign) = delete; + ~AssistantUiElementViewAnimator() override = default; + + // ElementAnimator: + void AnimateIn(ui::CallbackLayerAnimationObserver* observer) override; + void AnimateOut(ui::CallbackLayerAnimationObserver* observer) override; + ui::Layer* layer() const override; + + AnimationSmoothnessCallback GetAnimationSmoothnessCallback() const; + + private: + AssistantUiElementView* const view_; + std::string const animation_smoothness_histogram_; +}; + +} // namespace ash + +#endif // ASH_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_UI_ELEMENT_VIEW_ANIMATOR_H_
diff --git a/ash/assistant/ui/main_stage/element_animator.h b/ash/assistant/ui/main_stage/element_animator.h index a88e40a..d74da75e 100644 --- a/ash/assistant/ui/main_stage/element_animator.h +++ b/ash/assistant/ui/main_stage/element_animator.h
@@ -34,7 +34,7 @@ // value, it should be safe to circumnavigate this DCHECK. constexpr static float kMinimumAnimateOutOpacity = 0.0001f; - ElementAnimator(views::View* animated_view); + explicit ElementAnimator(views::View* animated_view); virtual ~ElementAnimator() = default; // Fade out the current element, meaning it will still be visible but
diff --git a/ash/assistant/ui/main_stage/suggestion_container_view.cc b/ash/assistant/ui/main_stage/suggestion_container_view.cc index a16de97..2a23b68 100644 --- a/ash/assistant/ui/main_stage/suggestion_container_view.cc +++ b/ash/assistant/ui/main_stage/suggestion_container_view.cc
@@ -22,6 +22,7 @@ #include "ash/public/cpp/assistant/controller/assistant_suggestions_controller.h" #include "ash/public/cpp/assistant/controller/assistant_ui_controller.h" #include "base/bind.h" +#include "base/metrics/histogram_functions.h" #include "ui/compositor/callback_layer_animation_observer.h" #include "ui/compositor/layer_animation_element.h" #include "ui/views/layout/box_layout.h" @@ -55,13 +56,19 @@ ~SuggestionChipAnimator() override = default; void AnimateIn(ui::CallbackLayerAnimationObserver* observer) override { - StartLayerAnimationSequence(layer()->GetAnimator(), - CreateAnimateInAnimation(), observer); + StartLayerAnimationSequence( + layer()->GetAnimator(), CreateAnimateInAnimation(), observer, + base::BindRepeating<void(const std::string&, int)>( + base::UmaHistogramPercentage, + assistant::ui::kAssistantSuggestionChipHistogram)); } void AnimateOut(ui::CallbackLayerAnimationObserver* observer) override { - StartLayerAnimationSequence(layer()->GetAnimator(), - CreateAnimateOutAnimation(), observer); + StartLayerAnimationSequence( + layer()->GetAnimator(), CreateAnimateOutAnimation(), observer, + base::BindRepeating<void(const std::string&, int)>( + base::UmaHistogramPercentage, + assistant::ui::kAssistantSuggestionChipHistogram)); } void FadeOut(ui::CallbackLayerAnimationObserver* observer) override { @@ -74,9 +81,8 @@ bool IsSelectedChip() const { return view() == parent_->selected_chip(); } ui::LayerAnimationSequence* CreateAnimateInAnimation() const { - return CreateLayerAnimationSequence( - CreateOpacityElement(1.f, kChipFadeInDuration, - gfx::Tween::Type::FAST_OUT_SLOW_IN)); + return CreateLayerAnimationSequence(CreateOpacityElement( + 1.f, kChipFadeInDuration, gfx::Tween::Type::FAST_OUT_SLOW_IN)); } ui::LayerAnimationSequence* CreateAnimateOutAnimation() const {
diff --git a/ash/assistant/util/BUILD.gn b/ash/assistant/util/BUILD.gn index aa4c1331..31a4675 100644 --- a/ash/assistant/util/BUILD.gn +++ b/ash/assistant/util/BUILD.gn
@@ -26,6 +26,7 @@ deps = [ "//ash/assistant/model", + "//ash/public/cpp", "//ash/public/cpp/vector_icons", "//base", "//base:i18n",
diff --git a/ash/assistant/util/DEPS b/ash/assistant/util/DEPS index 19d3edc5..8bae261 100644 --- a/ash/assistant/util/DEPS +++ b/ash/assistant/util/DEPS
@@ -2,7 +2,7 @@ "-ash", "+ash/assistant/model", "+ash/assistant/util", - "+ash/public/cpp/vector_icons", + "+ash/public/cpp", "+net", "+ui/base", "+ui/gfx",
diff --git a/ash/assistant/util/animation_util.cc b/ash/assistant/util/animation_util.cc index 5d4e01612..46fb357 100644 --- a/ash/assistant/util/animation_util.cc +++ b/ash/assistant/util/animation_util.cc
@@ -4,7 +4,9 @@ #include "ash/assistant/util/animation_util.h" +#include "ash/public/cpp/metrics_util.h" #include "base/time/time.h" +#include "ui/compositor/animation_throughput_reporter.h" #include "ui/compositor/callback_layer_animation_observer.h" #include "ui/compositor/layer_animation_element.h" #include "ui/compositor/layer_animation_observer.h" @@ -112,19 +114,28 @@ void StartLayerAnimationSequence( ::ui::LayerAnimator* layer_animator, ::ui::LayerAnimationSequence* layer_animation_sequence, - ::ui::LayerAnimationObserver* observer) { + ::ui::LayerAnimationObserver* observer, + base::Optional<AnimationSmoothnessCallback> smoothness_callback) { if (observer) layer_animation_sequence->AddObserver(observer); + + base::Optional<ui::AnimationThroughputReporter> reporter; + if (smoothness_callback) { + reporter.emplace(layer_animator, ash::metrics_util::ForSmoothness( + smoothness_callback.value())); + } layer_animator->StartAnimation(layer_animation_sequence); } void StartLayerAnimationSequence( views::View* view, ::ui::LayerAnimationSequence* layer_animation_sequence, - ::ui::LayerAnimationObserver* observer) { + ::ui::LayerAnimationObserver* observer, + base::Optional<AnimationSmoothnessCallback> smoothness_callback) { DCHECK(view->layer()); StartLayerAnimationSequence(view->layer()->GetAnimator(), - layer_animation_sequence, observer); + layer_animation_sequence, observer, + smoothness_callback); } void StartLayerAnimationSequencesTogether(
diff --git a/ash/assistant/util/animation_util.h b/ash/assistant/util/animation_util.h index 25483f6..cea08bc 100644 --- a/ash/assistant/util/animation_util.h +++ b/ash/assistant/util/animation_util.h
@@ -8,7 +8,9 @@ #include <memory> #include <vector> +#include "base/callback.h" #include "base/component_export.h" +#include "base/optional.h" #include "ui/gfx/animation/tween.h" namespace base { @@ -36,6 +38,8 @@ bool is_cyclic = false; }; +using AnimationSmoothnessCallback = base::RepeatingCallback<void(int)>; + // Creates a LayerAnimationSequence containing the specified // LayerAnimationElements with the given |params|. The method caller assumes // ownership of the returned pointer. @@ -91,21 +95,27 @@ // Starts the specified |layer_animation_sequence| on the given // |layer_animator|. If an optional |observer| is supplied, it will be added to -// the sequence. +// the sequence. If an optional |smoothness_callback| is supplied, it +// will be attached to the animation to measure performance. COMPONENT_EXPORT(ASSISTANT_UTIL) void StartLayerAnimationSequence( ::ui::LayerAnimator* layer_animator, ::ui::LayerAnimationSequence* layer_animation_sequence, - ::ui::LayerAnimationObserver* observer = nullptr); + ::ui::LayerAnimationObserver* observer = nullptr, + base::Optional<AnimationSmoothnessCallback> smoothness_callback = + base::nullopt); // Starts the specified |layer_animation_sequence| on the layer of the given // |view|. If an optional |observer| is supplied, it will be added to the -// sequence. +// sequence. If an optional |smoothness_callback| is supplied, it will be +// attached to the animation to measure performance. COMPONENT_EXPORT(ASSISTANT_UTIL) void StartLayerAnimationSequence( views::View* view, ::ui::LayerAnimationSequence* layer_animation_sequence, - ::ui::LayerAnimationObserver* observer = nullptr); + ::ui::LayerAnimationObserver* observer = nullptr, + base::Optional<AnimationSmoothnessCallback> animation_smoothness_callback = + base::nullopt); // Starts the specified |layer_animation_sequences| together on the given // |layer_animator|. If an optional |observer| is supplied, it will be added
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 7ce1da1288..9f1d001d 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -1773,6 +1773,7 @@ UserState* state = FindStateForUser( view->auth_user()->current_user().basic_user_info.account_id); uint32_t to_update_auth; + bool show_pinpad = false; if (state->force_online_sign_in) { to_update_auth = LoginAuthUserView::AUTH_ONLINE_SIGN_IN; } else if (state->disable_auth) { @@ -1789,16 +1790,16 @@ // not interfere with PIN entry. const bool is_keyboard_visible_for_view = GetKeyboardControllerForView() ? keyboard_shown_ : false; - if ((state->show_pin || state->show_pin_pad_for_password) && - !is_keyboard_visible_for_view) { + show_pinpad = !is_keyboard_visible_for_view && + (state->show_pin || state->show_pin_pad_for_password); + if (state->show_pin) to_update_auth |= LoginAuthUserView::AUTH_PIN; - } if (state->enable_tap_auth) to_update_auth |= LoginAuthUserView::AUTH_TAP; if (state->fingerprint_state != FingerprintState::UNAVAILABLE) to_update_auth |= LoginAuthUserView::AUTH_FINGERPRINT; } - view->auth_user()->SetAuthMethods(to_update_auth, state->show_pin); + view->auth_user()->SetAuthMethods(to_update_auth, show_pinpad); } else if (view->public_account()) { view->public_account()->SetAuthEnabled(true /*enabled*/, animate); } @@ -1809,7 +1810,7 @@ return; if (view->auth_user()) { view->auth_user()->SetAuthMethods(LoginAuthUserView::AUTH_NONE, - false /*can_use_pin*/); + false /*show_pinpad*/); } else if (view->public_account()) { view->public_account()->SetAuthEnabled(false /*enabled*/, animate); }
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc index f697ef6..875560a 100644 --- a/ash/login/ui/login_auth_user_view.cc +++ b/ash/login/ui/login_auth_user_view.cc
@@ -745,16 +745,14 @@ non_pin_y_start_in_screen = view->GetBoundsInScreen().y(); pin_start_in_screen = view->pin_view_->GetBoundsInScreen().origin(); - had_pin = (view->auth_methods() & LoginAuthUserView::AUTH_PIN) != 0; - had_password = - (view->auth_methods() & LoginAuthUserView::AUTH_PASSWORD) != 0; - had_fingerprint = - (view->auth_methods() & LoginAuthUserView::AUTH_FINGERPRINT) != 0; + had_pinpad = view->show_pinpad_; + had_password = view->HasAuthMethod(LoginAuthUserView::AUTH_PASSWORD); + had_fingerprint = view->HasAuthMethod(LoginAuthUserView::AUTH_FINGERPRINT); } int non_pin_y_start_in_screen = 0; gfx::Point pin_start_in_screen; - bool had_pin = false; + bool had_pinpad = false; bool had_password = false; bool had_fingerprint = false; }; @@ -980,20 +978,20 @@ add_padding(kDistanceFromPinKeyboardToBigUserViewBottomDp); // Update authentication UI. - SetAuthMethods(auth_methods_, false /*can_use_pin*/); + SetAuthMethods(auth_methods_, false /*show_pinpad*/); user_view_->UpdateForUser(user, false /*animate*/); } LoginAuthUserView::~LoginAuthUserView() = default; void LoginAuthUserView::SetAuthMethods(uint32_t auth_methods, - bool can_use_pin) { - can_use_pin_ = can_use_pin; + bool show_pinpad) { + show_pinpad_ = show_pinpad; bool had_password = HasAuthMethod(AUTH_PASSWORD); auth_methods_ = static_cast<AuthMethods>(auth_methods); bool has_password = HasAuthMethod(AUTH_PASSWORD); - bool has_pin_pad = HasAuthMethod(AUTH_PIN); + bool has_pin = HasAuthMethod(AUTH_PIN); bool has_tap = HasAuthMethod(AUTH_TAP); bool force_online_sign_in = HasAuthMethod(AUTH_ONLINE_SIGN_IN); bool has_fingerprint = HasAuthMethod(AUTH_FINGERPRINT); @@ -1010,7 +1008,7 @@ // Adjust the PIN keyboard visibility before the password textfield's one, so // that when both are about to be hidden the focus doesn't jump to the "1" // keyboard button, causing unexpected accessibility effects. - pin_view_->SetVisible(has_pin_pad); + pin_view_->SetVisible(show_pinpad); password_view_->SetEnabled(has_password); password_view_->SetEnabledOnEmptyPassword(has_tap); @@ -1023,25 +1021,25 @@ password_view_->RequestFocus(); fingerprint_view_->SetVisible(has_fingerprint); - fingerprint_view_->SetCanUsePin(can_use_pin); + fingerprint_view_->SetCanUsePin(has_pin); challenge_response_view_->SetVisible(has_challenge_response); int padding_view_height = kDistanceBetweenPasswordFieldAndPinKeyboardDp; - if (has_fingerprint && !has_pin_pad) { + if (has_fingerprint && !show_pinpad) { padding_view_height = kDistanceBetweenPasswordFieldAndFingerprintViewDp; - } else if (has_challenge_response && !has_pin_pad) { + } else if (has_challenge_response && !show_pinpad) { padding_view_height = kDistanceBetweenPasswordFieldAndChallengeResponseViewDp; } padding_below_password_view_->SetPreferredSize( gfx::Size(kNonEmptyWidthDp, padding_view_height)); - // Note: |has_tap| must have higher priority than |has_pin_pad| when + // Note: |has_tap| must have higher priority than |has_pin| when // determining the placeholder. if (has_tap) { password_view_->SetPlaceholderText( l10n_util::GetStringUTF16(IDS_ASH_LOGIN_POD_PASSWORD_TAP_PLACEHOLDER)); - } else if (can_use_pin) { + } else if (has_pin) { password_view_->SetPlaceholderText( l10n_util::GetStringUTF16(IDS_ASH_LOGIN_POD_PASSWORD_PIN_PLACEHOLDER)); } else { @@ -1107,9 +1105,9 @@ void LoginAuthUserView::ApplyAnimationPostLayout() { DCHECK(cached_animation_state_); - bool has_password = (auth_methods() & AUTH_PASSWORD) != 0; - bool has_pin = (auth_methods() & AUTH_PIN) != 0; - bool has_fingerprint = (auth_methods() & AUTH_FINGERPRINT) != 0; + bool has_password = HasAuthMethod(AUTH_PASSWORD); + bool has_pinpad = show_pinpad_; + bool has_fingerprint = HasAuthMethod(AUTH_FINGERPRINT); //////// // Animate the user info (ie, icon, name) up or down the screen. @@ -1169,8 +1167,8 @@ //////// // Grow/shrink the PIN keyboard if it is being hidden or shown. - if (cached_animation_state_->had_pin != has_pin) { - if (!has_pin) { + if (cached_animation_state_->had_pinpad != has_pinpad) { + if (!has_pinpad) { gfx::Point pin_end_in_screen = pin_view_->GetBoundsInScreen().origin(); gfx::Rect pin_bounds = pin_view_->bounds(); pin_bounds.set_x(cached_animation_state_->pin_start_in_screen.x() - @@ -1185,7 +1183,7 @@ } auto transition = std::make_unique<PinKeyboardAnimation>( - has_pin /*grow*/, pin_view_->height(), + has_pinpad /*grow*/, pin_view_->height(), // TODO(https://crbug.com/955119): Implement proper animation. base::TimeDelta::FromMilliseconds( login_constants::kChangeUserAnimationDurationMs / 2.0f), @@ -1193,7 +1191,7 @@ auto* sequence = new ui::LayerAnimationSequence(std::move(transition)); // Hide the PIN keyboard after animation if needed. - if (!has_pin) { + if (!has_pinpad) { auto* observer = BuildObserverToHideView(pin_view_); sequence->AddObserver(observer); observer->SetActive(); @@ -1291,7 +1289,7 @@ password_view_->SetReadOnly(true); Shell::Get()->login_screen_controller()->AuthenticateUserWithPasswordOrPin( current_user().basic_user_info.account_id, base::UTF16ToUTF8(password), - can_use_pin_, + HasAuthMethod(AUTH_PIN), base::BindOnce(&LoginAuthUserView::OnAuthComplete, weak_factory_.GetWeakPtr())); }
diff --git a/ash/login/ui/login_auth_user_view.h b/ash/login/ui/login_auth_user_view.h index 5f05d3f..33aca56 100644 --- a/ash/login/ui/login_auth_user_view.h +++ b/ash/login/ui/login_auth_user_view.h
@@ -104,9 +104,9 @@ ~LoginAuthUserView() override; // Set the displayed set of auth methods. |auth_methods| contains or-ed - // together AuthMethod values. |can_use_pin| should be true if the user can - // authenticate using PIN, even if the PIN keyboard is not displayed. - void SetAuthMethods(uint32_t auth_methods, bool can_use_pin); + // together AuthMethod values. |show_pinpad| determines whether the pin pad + // should be visible. + void SetAuthMethods(uint32_t auth_methods, bool show_pinpad); AuthMethods auth_methods() const { return auth_methods_; } // Add an easy unlock icon. @@ -184,10 +184,9 @@ void AttemptAuthenticateWithChallengeResponse(); AuthMethods auth_methods_ = AUTH_NONE; - // True if the user's password might be a PIN. PIN is hashed differently from - // password. The PIN keyboard may not always be visible even when the user - // wants to submit a PIN, eg. the virtual keyboard hides the PIN keyboard. - bool can_use_pin_ = false; + + // Whether to show the pinpad. Sometimes hidden by the on screen keyboard + bool show_pinpad_ = false; LoginUserView* user_view_ = nullptr; LoginPasswordView* password_view_ = nullptr; NonAccessibleView* password_view_container_ = nullptr;
diff --git a/ash/login/ui/login_auth_user_view_unittest.cc b/ash/login/ui/login_auth_user_view_unittest.cc index f3bef543..cc3f8d2 100644 --- a/ash/login/ui/login_auth_user_view_unittest.cc +++ b/ash/login/ui/login_auth_user_view_unittest.cc
@@ -57,9 +57,8 @@ SetWidget(CreateWidgetWithContent(container_)); } - void SetAuthMethods(uint32_t auth_methods) { - bool can_use_pin = (auth_methods & LoginAuthUserView::AUTH_PIN) != 0; - view_->SetAuthMethods(auth_methods, can_use_pin); + void SetAuthMethods(uint32_t auth_methods, bool show_pinpad) { + view_->SetAuthMethods(auth_methods, show_pinpad); } LoginUserInfo user_; @@ -75,7 +74,7 @@ // Verifies showing the PIN keyboard makes the user view grow. TEST_F(LoginAuthUserViewUnittest, ShowingPinExpandsView) { gfx::Size start_size = view_->size(); - SetAuthMethods(LoginAuthUserView::AUTH_PIN); + SetAuthMethods(LoginAuthUserView::AUTH_PIN, true /*show_pinpad*/); container_->Layout(); gfx::Size expanded_size = view_->size(); EXPECT_GT(expanded_size.height(), start_size.height()); @@ -95,11 +94,11 @@ EXPECT_FALSE(auth_test.user_view()->HasFocus()); // If the user view is showing a password it must be opaque. - SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD); + SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD, false /*show_pinpad*/); EXPECT_TRUE(user_test.is_opaque()); - SetAuthMethods(LoginAuthUserView::AUTH_NONE); + SetAuthMethods(LoginAuthUserView::AUTH_NONE, false /*show_pinpad*/); EXPECT_FALSE(user_test.is_opaque()); - SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD); + SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD, false /*show_pinpad*/); EXPECT_TRUE(user_test.is_opaque()); } @@ -119,8 +118,8 @@ EXPECT_CALL(*client, AuthenticateUserWithEasyUnlock( user_view->current_user().basic_user_info.account_id)); - SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD | - LoginAuthUserView::AUTH_TAP); + SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD | LoginAuthUserView::AUTH_TAP, + false /*show_pinpad*/); password_view->Clear(); generator->PressKey(ui::KeyboardCode::VKEY_RETURN, 0); @@ -138,7 +137,7 @@ // When auth method is |AUTH_ONLINE_SIGN_IN|, the online sign-in message is // visible. The password field and PIN keyboard are invisible. - SetAuthMethods(LoginAuthUserView::AUTH_ONLINE_SIGN_IN); + SetAuthMethods(LoginAuthUserView::AUTH_ONLINE_SIGN_IN, false /*show_pinpad*/); EXPECT_TRUE(online_sign_in_message->GetVisible()); EXPECT_FALSE(password_view->GetVisible()); EXPECT_FALSE(pin_view->GetVisible()); @@ -153,13 +152,13 @@ base::RunLoop().RunUntilIdle(); // The online sign-in message is invisible for all other auth methods. - SetAuthMethods(LoginAuthUserView::AUTH_NONE); + SetAuthMethods(LoginAuthUserView::AUTH_NONE, false /*show_pinpad*/); EXPECT_FALSE(online_sign_in_message->GetVisible()); - SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD); + SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD, false /*show_pinpad*/); EXPECT_FALSE(online_sign_in_message->GetVisible()); - SetAuthMethods(LoginAuthUserView::AUTH_PIN); + SetAuthMethods(LoginAuthUserView::AUTH_PIN, true /*show_pinpad*/); EXPECT_FALSE(online_sign_in_message->GetVisible()); - SetAuthMethods(LoginAuthUserView::AUTH_TAP); + SetAuthMethods(LoginAuthUserView::AUTH_TAP, false /*show_pinpad*/); EXPECT_FALSE(online_sign_in_message->GetVisible()); } @@ -172,20 +171,20 @@ }; // Set a password. - SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD); + SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD, false /*show_pinpad*/); password_test.textfield()->SetText(base::ASCIIToUTF16("Hello")); // Enable some other auth method (PIN), password is not cleared. view_->CaptureStateForAnimationPreLayout(); - SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD | - LoginAuthUserView::AUTH_PIN); + SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD | LoginAuthUserView::AUTH_PIN, + true /*show_pinpad*/); EXPECT_TRUE(has_password()); view_->ApplyAnimationPostLayout(); EXPECT_TRUE(has_password()); // Disable password, password is cleared. view_->CaptureStateForAnimationPreLayout(); - SetAuthMethods(LoginAuthUserView::AUTH_NONE); + SetAuthMethods(LoginAuthUserView::AUTH_NONE, false /*show_pinpad*/); EXPECT_TRUE(has_password()); view_->ApplyAnimationPostLayout(); EXPECT_FALSE(has_password());
diff --git a/ash/system/message_center/notification_swipe_control_view.cc b/ash/system/message_center/notification_swipe_control_view.cc index 45e5d018..203ae61 100644 --- a/ash/system/message_center/notification_swipe_control_view.cc +++ b/ash/system/message_center/notification_swipe_control_view.cc
@@ -185,17 +185,25 @@ void NotificationSwipeControlView::ButtonPressed(views::Button* sender, const ui::Event& event) { DCHECK(sender); + std::string notification_id = message_view_->notification_id(); + auto weak_this = weak_factory_.GetWeakPtr(); + if (sender == settings_button_) { message_view_->OnSettingsButtonPressed(event); - metrics_utils::LogSettingsShown(message_view_->notification_id(), + metrics_utils::LogSettingsShown(notification_id, /*is_slide_controls=*/true, /*is_popup=*/false); } else if (sender == snooze_button_) { message_view_->OnSnoozeButtonPressed(event); - metrics_utils::LogSnoozed(message_view_->notification_id(), + metrics_utils::LogSnoozed(notification_id, /*is_slide_controls=*/true, /*is_popup=*/false); } + + // Button handlers of |message_view_| may have closed |this|. + if (!weak_this) + return; + HideButtons(); // Closing the swipe control is done in these button pressed handlers.
diff --git a/ash/system/message_center/notification_swipe_control_view.h b/ash/system/message_center/notification_swipe_control_view.h index 84bb0bc..d78f06bc 100644 --- a/ash/system/message_center/notification_swipe_control_view.h +++ b/ash/system/message_center/notification_swipe_control_view.h
@@ -6,7 +6,7 @@ #define ASH_SYSTEM_MESSAGE_CENTER_NOTIFICATION_SWIPE_CONTROL_VIEW_H_ #include "ash/ash_export.h" -#include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/observer_list_types.h" #include "third_party/skia/include/core/SkColor.h" @@ -35,6 +35,9 @@ explicit NotificationSwipeControlView( message_center::MessageView* message_view); + NotificationSwipeControlView(const NotificationSwipeControlView&) = delete; + NotificationSwipeControlView& operator=(const NotificationSwipeControlView&) = + delete; ~NotificationSwipeControlView() override; // views::View @@ -50,6 +53,11 @@ void UpdateCornerRadius(int top_radius, int bottom_radius); private: + FRIEND_TEST_ALL_PREFIXES(NotificationSwipeControlViewTest, + DeleteOnSettingsButtonPressed); + FRIEND_TEST_ALL_PREFIXES(NotificationSwipeControlViewTest, + DeleteOnSnoozeButtonPressed); + // Change the visibility of the settings button. void ShowButtons(ButtonPosition button_position, bool has_settings, @@ -68,7 +76,7 @@ views::ImageButton* settings_button_ = nullptr; views::ImageButton* snooze_button_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(NotificationSwipeControlView); + base::WeakPtrFactory<NotificationSwipeControlView> weak_factory_{this}; }; } // namespace ash
diff --git a/ash/system/message_center/notification_swipe_control_view_unittest.cc b/ash/system/message_center/notification_swipe_control_view_unittest.cc new file mode 100644 index 0000000..813b7aa8 --- /dev/null +++ b/ash/system/message_center/notification_swipe_control_view_unittest.cc
@@ -0,0 +1,151 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/message_center/notification_swipe_control_view.h" + +#include <memory> + +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/base_event_utils.h" +#include "ui/gfx/geometry/point_f.h" +#include "ui/gfx/image/image.h" +#include "ui/message_center/lock_screen/fake_lock_screen_controller.h" +#include "ui/message_center/message_center.h" +#include "ui/message_center/public/cpp/notification.h" +#include "ui/message_center/views/message_view.h" +#include "ui/message_center/views/notification_control_buttons_view.h" +#include "url/gurl.h" + +namespace { + +class MockMessageView : public message_center::MessageView { + public: + explicit MockMessageView(const message_center::Notification& notification) + : message_center::MessageView(notification), + buttons_view_( + std::make_unique<message_center::NotificationControlButtonsView>( + this)) { + buttons_view_->ShowSettingsButton( + notification.should_show_settings_button()); + buttons_view_->ShowSnoozeButton(notification.should_show_snooze_button()); + } + ~MockMessageView() override = default; + + message_center::NotificationControlButtonsView* GetControlButtonsView() + const override { + return buttons_view_.get(); + } + + MOCK_METHOD(void, + OnSettingsButtonPressed, + (const ui::Event& event), + (override)); + MOCK_METHOD(void, + OnSnoozeButtonPressed, + (const ui::Event& event), + (override)); + + private: + std::unique_ptr<message_center::NotificationControlButtonsView> buttons_view_; +}; + +} // namespace + +namespace ash { + +class NotificationSwipeControlViewTest : public testing::Test { + public: + NotificationSwipeControlViewTest() = default; + ~NotificationSwipeControlViewTest() override = default; + + void SetUp() override { + message_center::MessageCenter::Initialize( + std::make_unique<message_center::FakeLockScreenController>()); + + message_center::RichNotificationData rich_data; + rich_data.settings_button_handler = + message_center::SettingsButtonHandler::DELEGATE; + rich_data.should_show_snooze_button = true; + message_center::Notification notification( + message_center::NOTIFICATION_TYPE_SIMPLE, "id", + base::UTF8ToUTF16("title"), base::UTF8ToUTF16("id"), gfx::Image(), + base::string16(), GURL(), + message_center::NotifierId(message_center::NotifierType::APPLICATION, + "notifier_id"), + rich_data, nullptr); + + message_view_ = std::make_unique<MockMessageView>(notification); + } + + void TearDown() override { message_center::MessageCenter::Shutdown(); } + + protected: + MockMessageView* message_view() { return message_view_.get(); } + + private: + std::unique_ptr<MockMessageView> message_view_; +}; + +TEST_F(NotificationSwipeControlViewTest, DeleteOnSettingsButtonPressed) { + auto swipe_control_view = + std::make_unique<NotificationSwipeControlView>(message_view()); + + EXPECT_CALL(*message_view(), OnSettingsButtonPressed(testing::_)) + .WillOnce(testing::DoDefault()) + .WillOnce( + testing::InvokeWithoutArgs([&]() { swipe_control_view.reset(); })); + + ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::PointF(), gfx::PointF(), + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_NONE); + + // First click will do nothing, expect that to work. + swipe_control_view->ShowButtons( + NotificationSwipeControlView::ButtonPosition::LEFT, + /*has_settings_button=*/true, /*has_snooze_button=*/true); + swipe_control_view->ButtonPressed(swipe_control_view->settings_button_, + press); + EXPECT_TRUE(swipe_control_view); + + // Second click deletes |swipe_control_view| in the handler. + swipe_control_view->ShowButtons( + NotificationSwipeControlView::ButtonPosition::LEFT, + /*has_settings_button=*/true, /*has_snooze_button=*/true); + swipe_control_view->ButtonPressed(swipe_control_view->settings_button_, + press); + EXPECT_FALSE(swipe_control_view); +} + +TEST_F(NotificationSwipeControlViewTest, DeleteOnSnoozeButtonPressed) { + auto swipe_control_view = + std::make_unique<NotificationSwipeControlView>(message_view()); + + EXPECT_CALL(*message_view(), OnSnoozeButtonPressed(testing::_)) + .WillOnce(testing::DoDefault()) + .WillOnce( + testing::InvokeWithoutArgs([&]() { swipe_control_view.reset(); })); + + ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::PointF(), gfx::PointF(), + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_NONE); + + // First click will do nothing, expect that to work. + swipe_control_view->ShowButtons( + NotificationSwipeControlView::ButtonPosition::LEFT, + /*has_settings_button=*/true, /*has_snooze_button=*/true); + swipe_control_view->ButtonPressed(swipe_control_view->snooze_button_, press); + EXPECT_TRUE(swipe_control_view); + + // Second click deletes |swipe_control_view| in the handler. + swipe_control_view->ShowButtons( + NotificationSwipeControlView::ButtonPosition::LEFT, + /*has_settings_button=*/true, /*has_snooze_button=*/true); + swipe_control_view->ButtonPressed(swipe_control_view->snooze_button_, press); + EXPECT_FALSE(swipe_control_view); +} + +} // namespace ash
diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h index 42aa341..d977a0da 100644 --- a/base/memory/weak_ptr.h +++ b/base/memory/weak_ptr.h
@@ -324,7 +324,7 @@ ~WeakPtrFactory() = default; - WeakPtr<T> GetWeakPtr() { + WeakPtr<T> GetWeakPtr() const { return WeakPtr<T>(weak_reference_owner_.GetRef(), reinterpret_cast<T*>(ptr_)); }
diff --git a/build/android/pylib/local/emulator/avd.py b/build/android/pylib/local/emulator/avd.py index 4f8103f..a638f387 100644 --- a/build/android/pylib/local/emulator/avd.py +++ b/build/android/pylib/local/emulator/avd.py
@@ -263,6 +263,9 @@ 'hw.lcd.width': width, }) + if self.avd_settings.ram_size: + config_ini_contents['hw.ramSize'] = self.avd_settings.ram_size + # Start & stop the AVD. self._Initialize() instance = _AvdInstance(self._emulator_path, self._emulator_home,
diff --git a/build/android/pylib/local/emulator/proto/avd.proto b/build/android/pylib/local/emulator/proto/avd.proto index bbcdd530..b06da490 100644 --- a/build/android/pylib/local/emulator/proto/avd.proto +++ b/build/android/pylib/local/emulator/proto/avd.proto
@@ -50,6 +50,9 @@ // See https://bit.ly/2P1qK2X for all the available keys. // The values should be on, off, default, or null map<string, string> advanced_features = 3; + + // The physical RAM size on the device, in megabytes. + uint32 ram_size = 4; } message Avd {
diff --git a/build/android/pylib/local/emulator/proto/avd_pb2.py b/build/android/pylib/local/emulator/proto/avd_pb2.py index e48f3b05..49cc1aa8 100644 --- a/build/android/pylib/local/emulator/proto/avd_pb2.py +++ b/build/android/pylib/local/emulator/proto/avd_pb2.py
@@ -18,7 +18,7 @@ package='tools.android.avd.proto', syntax='proto3', serialized_options=None, - serialized_pb=b'\n\tavd.proto\x12\x17tools.android.avd.proto\"G\n\x0b\x43IPDPackage\x12\x14\n\x0cpackage_name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\x12\x11\n\tdest_path\x18\x03 \x01(\t\"@\n\x0eScreenSettings\x12\x0e\n\x06height\x18\x01 \x01(\r\x12\r\n\x05width\x18\x02 \x01(\r\x12\x0f\n\x07\x64\x65nsity\x18\x03 \x01(\r\"\x1e\n\x0eSdcardSettings\x12\x0c\n\x04size\x18\x01 \x01(\t\"\x8f\x02\n\x0b\x41vdSettings\x12\x37\n\x06screen\x18\x01 \x01(\x0b\x32\'.tools.android.avd.proto.ScreenSettings\x12\x37\n\x06sdcard\x18\x02 \x01(\x0b\x32\'.tools.android.avd.proto.SdcardSettings\x12U\n\x11\x61\x64vanced_features\x18\x03 \x03(\x0b\x32:.tools.android.avd.proto.AvdSettings.AdvancedFeaturesEntry\x1a\x37\n\x15\x41\x64vancedFeaturesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xad\x02\n\x03\x41vd\x12>\n\x10\x65mulator_package\x18\x01 \x01(\x0b\x32$.tools.android.avd.proto.CIPDPackage\x12\x42\n\x14system_image_package\x18\x02 \x01(\x0b\x32$.tools.android.avd.proto.CIPDPackage\x12\x19\n\x11system_image_name\x18\x03 \x01(\t\x12\x39\n\x0b\x61vd_package\x18\x04 \x01(\x0b\x32$.tools.android.avd.proto.CIPDPackage\x12\x10\n\x08\x61vd_name\x18\x05 \x01(\t\x12:\n\x0c\x61vd_settings\x18\x06 \x01(\x0b\x32$.tools.android.avd.proto.AvdSettingsb\x06proto3' + serialized_pb=b'\n\tavd.proto\x12\x17tools.android.avd.proto\"G\n\x0b\x43IPDPackage\x12\x14\n\x0cpackage_name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\x12\x11\n\tdest_path\x18\x03 \x01(\t\"@\n\x0eScreenSettings\x12\x0e\n\x06height\x18\x01 \x01(\r\x12\r\n\x05width\x18\x02 \x01(\r\x12\x0f\n\x07\x64\x65nsity\x18\x03 \x01(\r\"\x1e\n\x0eSdcardSettings\x12\x0c\n\x04size\x18\x01 \x01(\t\"\xa1\x02\n\x0b\x41vdSettings\x12\x37\n\x06screen\x18\x01 \x01(\x0b\x32\'.tools.android.avd.proto.ScreenSettings\x12\x37\n\x06sdcard\x18\x02 \x01(\x0b\x32\'.tools.android.avd.proto.SdcardSettings\x12U\n\x11\x61\x64vanced_features\x18\x03 \x03(\x0b\x32:.tools.android.avd.proto.AvdSettings.AdvancedFeaturesEntry\x12\x10\n\x08ram_size\x18\x04 \x01(\r\x1a\x37\n\x15\x41\x64vancedFeaturesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xad\x02\n\x03\x41vd\x12>\n\x10\x65mulator_package\x18\x01 \x01(\x0b\x32$.tools.android.avd.proto.CIPDPackage\x12\x42\n\x14system_image_package\x18\x02 \x01(\x0b\x32$.tools.android.avd.proto.CIPDPackage\x12\x19\n\x11system_image_name\x18\x03 \x01(\t\x12\x39\n\x0b\x61vd_package\x18\x04 \x01(\x0b\x32$.tools.android.avd.proto.CIPDPackage\x12\x10\n\x08\x61vd_name\x18\x05 \x01(\t\x12:\n\x0c\x61vd_settings\x18\x06 \x01(\x0b\x32$.tools.android.avd.proto.AvdSettingsb\x06proto3' ) @@ -178,8 +178,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=426, - serialized_end=481, + serialized_start=444, + serialized_end=499, ) _AVDSETTINGS = _descriptor.Descriptor( @@ -210,6 +210,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='ram_size', full_name='tools.android.avd.proto.AvdSettings.ram_size', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -223,7 +230,7 @@ oneofs=[ ], serialized_start=210, - serialized_end=481, + serialized_end=499, ) @@ -288,8 +295,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=484, - serialized_end=785, + serialized_start=502, + serialized_end=803, ) _AVDSETTINGS_ADVANCEDFEATURESENTRY.containing_type = _AVDSETTINGS
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 2202e3f..dbcddb3 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -694,6 +694,12 @@ ldflags += [ "-Wl,--no-rosegment" ] } + # Don't do call-graph-sorted binary layout on Android, as that increases the + # binary size due to more thunks for long jumps. + if (use_lld && is_android) { + ldflags += [ "-Wl,--no-call-graph-profile-sort" ] + } + # This flag enforces that member pointer base types are complete. It helps # prevent us from running into problems in the Microsoft C++ ABI (see # https://crbug.com/847724).
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index a01346de..e2de5d0 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200730.3.1 +0.20200731.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index a01346de..e2de5d0 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200730.3.1 +0.20200731.1.1
diff --git a/build_overrides/build.gni b/build_overrides/build.gni index 497ebae..fbfaa3e 100644 --- a/build_overrides/build.gni +++ b/build_overrides/build.gni
@@ -27,8 +27,7 @@ # TODO(crbug/1006769): Switch to perfetto's client library. use_perfetto_client_library = false - # If true, it assumes that //third_party/abseil-cpp is an available - # dependency for googletest. + # Allows googletest to pretty-print various absl types. gtest_enable_absl_printers = false }
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index abec2ebe..846ab9a3 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1485,6 +1485,7 @@ "java/src/org/chromium/chrome/browser/sync/settings/SignInPreference.java", "java/src/org/chromium/chrome/browser/sync/settings/SyncAndServicesSettings.java", "java/src/org/chromium/chrome/browser/sync/settings/SyncOffPreference.java", + "java/src/org/chromium/chrome/browser/sync/settings/SyncPromoPreference.java", "java/src/org/chromium/chrome/browser/sync/settings/SyncSettingsUtils.java", "java/src/org/chromium/chrome/browser/sync/ui/PassphraseActivity.java", "java/src/org/chromium/chrome/browser/sync/ui/PassphraseCreationDialogFragment.java",
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java index 221b8fb..8d824eb 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java
@@ -40,6 +40,7 @@ import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.content_public.browser.test.util.CriteriaHelper; +import org.chromium.ui.test.util.UiDisableIf; import java.util.concurrent.TimeoutException; @@ -109,6 +110,7 @@ @Test @SmallTest + @DisableIf.Device(type = {UiDisableIf.TABLET}) // https://crbug.com/1111770 public void testFillsPasswordOnTap() throws TimeoutException { mHelper.loadTestPage(false); mHelper.cacheCredentials("mpark@abc.com", "ShorterPassword");
diff --git a/chrome/android/java/res/drawable/ic_expand_more_in_circle_24dp.xml b/chrome/android/java/res/drawable/ic_expand_more_in_circle_24dp.xml index 08c0a50..1a240f3 100644 --- a/chrome/android/java/res/drawable/ic_expand_more_in_circle_24dp.xml +++ b/chrome/android/java/res/drawable/ic_expand_more_in_circle_24dp.xml
@@ -11,9 +11,9 @@ <path android:strokeWidth="1" android:pathData="M23.5,11.9999C23.5,18.3512 18.3513,23.4999 12,23.4999C5.6487,23.4999 0.5,18.3512 0.5,11.9999C0.5,5.6486 5.6487,0.4999 12,0.4999C18.3513,0.4999 23.5,5.6486 23.5,11.9999Z" - android:strokeColor="@color/default_chip_outline_color_light"/> + android:strokeColor="@color/hairline_stroke_color"/> <path android:pathData="M12.5892,14.7487C12.4383,14.9039 12.23,14.9999 12,14.9999C11.77,14.9999 11.5617,14.9039 11.4108,14.7487L7.2442,10.463C7.0933,10.3079 7,10.0936 7,9.857C7,9.3839 7.3733,8.9999 7.8333,8.9999C8.0633,8.9999 8.2717,9.0959 8.4225,9.251L12,12.9307L15.5775,9.251C15.7283,9.0959 15.9367,8.9999 16.1667,8.9999C16.6267,8.9999 17,9.3839 17,9.857C17,10.0936 16.9067,10.3079 16.7558,10.463L12.5892,14.7487Z" - android:fillColor="@color/default_chip_outline_color_dark" + android:fillColor="@color/default_control_color_normal" android:fillType="evenOdd"/> </vector>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionView.java index 7fa753cd..50d55a5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionView.java
@@ -356,7 +356,7 @@ String addition; switch (enforcement) { case CookieControlsEnforcement.ENFORCED_BY_POLICY: - iconRes = R.drawable.controlled_setting_mandatory; + iconRes = R.drawable.ic_business_small; addition = resources.getString(R.string.managed_by_your_organization); break; case CookieControlsEnforcement.ENFORCED_BY_COOKIE_SETTING:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java index c5fd6a5..7d03a23 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java
@@ -308,7 +308,9 @@ ChromeActivity.fromWebContents(mFactoryDelegate.getParams().getWebContents()); if (!PaymentOptionsUtils.requestAnyInformation( mFactoryDelegate.getParams().getPaymentOptions()) - && activity != null) { + && activity != null + && PaymentFeatureList.isEnabled( + PaymentFeatureList.WEB_PAYMENTS_APP_STORE_BILLING)) { findAppStoreBillingApp(activity, allInstalledPaymentApps); } @@ -359,6 +361,14 @@ GURL defaultUrlMethod = null; if (!TextUtils.isEmpty(defaultMethod)) { defaultUrlMethod = new GURL(defaultMethod); + + // Do not download any manifests for the app whose default payment method identifier + // is an app store payment method identifier, because app store method URLs are used + // only for identification and do not host manifest files. + if (mAppStores.values().contains(defaultUrlMethod)) { + continue; + } + if (UrlUtils.isURLValid(defaultUrlMethod)) { defaultMethod = urlToStringWithoutTrailingSlash(defaultUrlMethod); } @@ -394,6 +404,12 @@ continue; } + // Ignore payment method identifiers of app stores, because app store method URLs + // are used only for identification and do not host manifest files. + if (mAppStores.values().contains(supportedUrlMethod)) { + continue; + } + if (!methodToAppsMapping.containsKey(supportedMethod)) { methodToAppsMapping.put(supportedMethod, new HashSet<ResolveInfo>()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncPromoPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncPromoPreference.java new file mode 100644 index 0000000..e15b38a4 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncPromoPreference.java
@@ -0,0 +1,216 @@ +// Copyright 2020 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.sync.settings; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; + +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; +import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.signin.IdentityServicesProvider; +import org.chromium.chrome.browser.signin.PersonalizedSigninPromoView; +import org.chromium.chrome.browser.signin.ProfileDataCache; +import org.chromium.chrome.browser.signin.SigninPromoController; +import org.chromium.chrome.browser.signin.SigninPromoUtil; +import org.chromium.chrome.browser.sync.AndroidSyncSettings; +import org.chromium.chrome.browser.sync.ProfileSyncService; +import org.chromium.chrome.browser.sync.ProfileSyncService.SyncStateChangedListener; +import org.chromium.components.signin.AccountManagerFacade; +import org.chromium.components.signin.AccountManagerFacadeProvider; +import org.chromium.components.signin.AccountsChangeObserver; +import org.chromium.components.signin.identitymanager.ConsentLevel; +import org.chromium.components.signin.identitymanager.IdentityManager; +import org.chromium.components.signin.metrics.SigninAccessPoint; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * A preference that displays Personalized Sync Promo when the user is not syncing. + */ +// TODO(https://crbug.com/1110889): Move all promos from SigninPreference to this class. +public class SyncPromoPreference extends Preference + implements ProfileDataCache.Observer, AndroidSyncSettings.AndroidSyncSettingsObserver, + SyncStateChangedListener, AccountsChangeObserver { + @Retention(RetentionPolicy.SOURCE) + @IntDef({State.PROMO_HIDDEN, State.PERSONALIZED_SYNC_PROMO}) + public @interface State { + int PROMO_HIDDEN = 0; + int PERSONALIZED_SYNC_PROMO = 1; + } + + private final ProfileDataCache mProfileDataCache; + private final AccountManagerFacade mAccountManagerFacade; + private @SignInPreference.State int mState; + private @Nullable SigninPromoController mSigninPromoController; + + /** + * Constructor for inflating from XML. + */ + public SyncPromoPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + mProfileDataCache = + ProfileDataCache.createProfileDataCache(context, R.drawable.ic_sync_badge_off_20dp); + mAccountManagerFacade = AccountManagerFacadeProvider.getInstance(); + + // State will be updated in registerForUpdates. + mState = State.PROMO_HIDDEN; + setVisible(false); + } + + /** + * Starts listening for updates to the sign-in and sync state. + * TODO(https://crbug.com/1109713): Remove this method and use onAttached() instead + */ + public void registerForUpdates() { + mAccountManagerFacade.addObserver(this); + mProfileDataCache.addObserver(this); + FirstRunSignInProcessor.updateSigninManagerFirstRunCheckDone(); + AndroidSyncSettings.get().registerObserver(this); + ProfileSyncService syncService = ProfileSyncService.get(); + if (syncService != null) { + syncService.addSyncStateChangedListener(this); + } + + update(); + } + + /** + * Stops listening for updates to the sign-in and sync state. Every call to registerForUpdates() + * must be matched with a call to this method. + * TODO(https://crbug.com/1109713): Remove this method and use onAttached() instead + */ + public void unregisterForUpdates() { + mAccountManagerFacade.removeObserver(this); + mProfileDataCache.removeObserver(this); + AndroidSyncSettings.get().unregisterObserver(this); + ProfileSyncService syncService = ProfileSyncService.get(); + if (syncService != null) { + syncService.removeSyncStateChangedListener(this); + } + } + + /** + * Should be called when the {@link PreferenceFragmentCompat} which used {@link + * SyncPromoPreference} gets destroyed. Used to record "ImpressionsTilDismiss" histogram. + */ + public void onPreferenceFragmentDestroyed() { + if (mSigninPromoController != null) { + mSigninPromoController.onPromoDestroyed(); + } + } + + /** Returns the state of the preference. Not valid until registerForUpdates is called. */ + @State + public int getState() { + return mState; + } + + /** Updates the title, summary, and image based on the current sign-in state. */ + private void update() { + // If feature is not enabled keep the preference at the default PROMO_NONE state. + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)) { + return; + } + boolean personalizedPromoDismissed = SharedPreferencesManager.getInstance().readBoolean( + ChromePreferenceKeys.SIGNIN_PROMO_SETTINGS_PERSONALIZED_DISMISSED, false); + if (isSignedInButNotSyncing() && !personalizedPromoDismissed + && SigninPromoController.hasNotReachedImpressionLimit(SigninAccessPoint.SETTINGS)) { + setupPersonalizedSyncPromo(); + return; + } + + if (mSigninPromoController != null) { + // Don't change the promo type if the new promo is already being shown. + setupPersonalizedSyncPromo(); + return; + } + + setupPromoHidden(); + } + + private void setupPersonalizedSyncPromo() { + mState = State.PERSONALIZED_SYNC_PROMO; + setLayoutResource(R.layout.personalized_signin_promo_view_settings); + setVisible(true); + + if (mSigninPromoController == null) { + mSigninPromoController = new SigninPromoController(SigninAccessPoint.SETTINGS); + } + + notifyChanged(); + } + + private void setupPromoHidden() { + mState = State.PROMO_HIDDEN; + mSigninPromoController = null; + setVisible(false); + } + + private boolean isSignedInButNotSyncing() { + IdentityManager identityManager = IdentityServicesProvider.get().getIdentityManager( + Profile.getLastUsedRegularProfile()); + return !identityManager.hasPrimaryAccount() + && identityManager.getPrimaryAccountInfo(ConsentLevel.NOT_REQUIRED) != null; + } + + @Override + public void onBindViewHolder(PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + + if (mSigninPromoController == null) { + return; + } + + PersonalizedSigninPromoView syncPromoView = + (PersonalizedSigninPromoView) holder.findViewById(R.id.signin_promo_view_container); + // TODO(https://crbug.com/1095628): Use setupPersonalizedSyncPromo here. + SigninPromoUtil.setupPromoViewFromCache( + mSigninPromoController, mProfileDataCache, syncPromoView, () -> { + SharedPreferencesManager.getInstance().writeBoolean( + ChromePreferenceKeys.SIGNIN_PROMO_SETTINGS_PERSONALIZED_DISMISSED, + true); + setupPromoHidden(); + }); + syncPromoView.getStatusMessage().setVisibility(View.VISIBLE); + syncPromoView.getChooseAccountButton().setVisibility(View.GONE); + syncPromoView.getSigninButton().setText(R.string.sync_promo_turn_on_sync); + } + + // ProfileSyncServiceListener implementation. + @Override + public void syncStateChanged() { + update(); + } + + // ProfileDataCache.Observer implementation. + @Override + public void onProfileDataUpdated(String accountId) { + update(); + } + + // AndroidSyncSettings.AndroidSyncSettingsObserver implementation. + @Override + public void androidSyncSettingsChanged() { + update(); + } + + // AccountsChangeObserver implementation. + @Override + public void onAccountsChanged() { + update(); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java index 1dd78e5..5c88cf11 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
@@ -38,6 +38,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.night_mode.ChromeNightModeTestUtils; import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetCoordinator; import org.chromium.chrome.browser.signin.account_picker.AccountPickerDelegate; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; @@ -132,6 +133,18 @@ @Test @MediumTest + @Feature("RenderTest") + public void testCollapsedSheetWithAccountViewDarkMode() throws IOException { + TestThreadUtils.runOnUiThreadBlocking( + () -> { ChromeNightModeTestUtils.setUpNightModeForChromeActivity(true); }); + mRenderTestRule.setNightModeEnabled(true); + buildAndShowCollapsedBottomSheet(); + mRenderTestRule.render( + mCoordinator.getBottomSheetViewForTesting(), "collapsed_sheet_with_account_dark"); + } + + @Test + @MediumTest public void testExpandedSheet() { buildAndShowExpandedBottomSheet(); onView(allOf(withText(PROFILE_DATA1.getAccountName()), withEffectiveVisibility(VISIBLE)))
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tracing/settings/TracingSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tracing/settings/TracingSettingsTest.java index a5b5cbfd..61fe976c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tracing/settings/TracingSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tracing/settings/TracingSettingsTest.java
@@ -10,6 +10,7 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.os.Build.VERSION_CODES; import android.support.test.InstrumentationRegistry; import android.util.Pair; @@ -31,6 +32,7 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.ChromeActivity; @@ -144,7 +146,9 @@ @Test @MediumTest @Feature({"Preferences"}) - @DisableIf.Build(sdk_is_less_than = 21, message = "crbug.com/899894") + @DisabledTest + @DisableIf.Build(sdk_is_less_than = VERSION_CODES.M, + message = "crbug.com/899894 (for <L), crbug.com/1111816 (for L)") public void testRecordTrace() throws Exception { mActivityTestRule.startMainActivityOnBlankPage(); mSettingsActivityTestRule.startSettingsActivity();
diff --git a/chrome/app/nearby_share_strings.grdp b/chrome/app/nearby_share_strings.grdp index ad48cea..d36cffee 100644 --- a/chrome/app/nearby_share_strings.grdp +++ b/chrome/app/nearby_share_strings.grdp
@@ -14,6 +14,9 @@ <message name="IDS_NEARBY_FILE_ATTACHMENTS_VIDEOS" desc="Describes one or more videos being transfered via Nearby Share."> {COUNT, plural, =1 {1 video} other {# videos}} </message> + <message name="IDS_NEARBY_SECURE_CONNECTION_ID" desc="Description shown on both sender and receiver devices, to remind users to verify/compare tokens on both devices for security before sending/receiving data."> + Secure connection ID: <ph name="TOKEN">$1<ex>1234</ex></ph> + </message> <message name="IDS_NEARBY_TEXT_ATTACHMENTS_ADDRESSES" desc="Describes one or more addresses being transfered via Nearby Share."> {COUNT, plural, =1 {1 address} other {# addresses}} </message> @@ -49,12 +52,24 @@ <message name="IDS_NEARBY_NOTIFICATION_RECEIVE_ACTION" desc="Text shown on the notification action to accept receiving data via Nearby Share."> Receive </message> + <message name="IDS_NEARBY_NOTIFICATION_RECEIVE_FAILURE_TITLE" desc="Text shown as the title of a notfication when receiving data via Nearby Share failed."> + Failed to receive <ph name="ATTACHMENTS">$1<ex>3 items</ex></ph> from <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph> + </message> <message name="IDS_NEARBY_NOTIFICATION_RECEIVE_PROGRESS_TITLE" desc="Text shown as the title of a notfication when receiving data via Nearby Share."> Receiving <ph name="ATTACHMENTS">$1<ex>3 items</ex></ph> from <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph> </message> + <message name="IDS_NEARBY_NOTIFICATION_RECEIVE_SUCCESS_TITLE" desc="Text shown as the title of a notfication when data was sucessfully received via Nearby Share."> + <ph name="ATTACHMENTS">$1<ex>3 items</ex></ph> received from <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph> + </message> + <message name="IDS_NEARBY_NOTIFICATION_SEND_FAILURE_TITLE" desc="Text shown as the title of a notfication when sending data via Nearby Share failed."> + Failed to send <ph name="ATTACHMENTS">$1<ex>3 items</ex></ph> to <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph> + </message> <message name="IDS_NEARBY_NOTIFICATION_SEND_PROGRESS_TITLE" desc="Text shown as the title of a notfication when sending data via Nearby Share."> Sending <ph name="ATTACHMENTS">$1<ex>3 items</ex></ph> to <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph> </message> + <message name="IDS_NEARBY_NOTIFICATION_SEND_SUCCESS_TITLE" desc="Text shown as the title of a notfication when data was successfully sent via Nearby Share."> + <ph name="ATTACHMENTS">$1<ex>3 items</ex></ph> successfully sent to <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph> + </message> <message name="IDS_NEARBY_NOTIFICATION_SOURCE" desc="Text shown as the source of a Nearby Share notification."> Nearby Share </message>
diff --git a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_FAILURE_TITLE.png.sha1 b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_FAILURE_TITLE.png.sha1 new file mode 100644 index 0000000..2a267cc --- /dev/null +++ b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_FAILURE_TITLE.png.sha1
@@ -0,0 +1 @@ +7e4a3b15e25d39a118de05867196d7cb632030b0 \ No newline at end of file
diff --git a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_SUCCESS_TITLE.png.sha1 b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_SUCCESS_TITLE.png.sha1 new file mode 100644 index 0000000..f9fc8f2 --- /dev/null +++ b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_SUCCESS_TITLE.png.sha1
@@ -0,0 +1 @@ +7837c6e2c7ab0d48d50035a70e1cf1cc5a8d1da5 \ No newline at end of file
diff --git a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_SEND_FAILURE_TITLE.png.sha1 b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_SEND_FAILURE_TITLE.png.sha1 new file mode 100644 index 0000000..2c85a72 --- /dev/null +++ b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_SEND_FAILURE_TITLE.png.sha1
@@ -0,0 +1 @@ +09f41715f5eb5479ca90cf91f6c56985356ee03c \ No newline at end of file
diff --git a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_SEND_SUCCESS_TITLE.png.sha1 b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_SEND_SUCCESS_TITLE.png.sha1 new file mode 100644 index 0000000..8cba3e4 --- /dev/null +++ b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_SEND_SUCCESS_TITLE.png.sha1
@@ -0,0 +1 @@ +e469e9b7fe91b0ce18f6624ef3d13276cb47f459 \ No newline at end of file
diff --git a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_SECURE_CONNECTION_ID.png.sha1 b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_SECURE_CONNECTION_ID.png.sha1 new file mode 100644 index 0000000..a56b14fd --- /dev/null +++ b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_SECURE_CONNECTION_ID.png.sha1
@@ -0,0 +1 @@ +0c6d5805e7d2fca601540782782590f7fee3733c \ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index aa35b88..42e4c7aa 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -18,6 +18,15 @@ <message name="IDS_SETTINGS_SECONDARY_USER_BANNER" desc="Banner displayed in settings page when the user is secondary in a multi-profile session."> Some settings belonging to <ph name="PRIMARY_EMAIL">$1<ex>john@google.com</ex></ph> are being shared with you. These settings only affect your account when using multiple sign-in. </message> + <message name="IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_DAYS" desc="Banner displayed in OS settings page in case update is required by policy but device has reached end-of-life and the days remaining to return the device back to the enterprise is greater than one and less than seven."> + <ph name="DOMAIN">$1<ex>example.com</ex></ph> requires you to back up your data and return this device within <ph name="DAYS_COUNT">$2<ex>10</ex></ph> days.<ph name="LINK_BEGIN"><a target="_blank" href="$3<ex>https://google.com/</ex>"></ph>See details<ph name="LINK_END"></a></ph> + </message> + <message name="IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_LAST_DAY" desc="Banner displayed in OS settings page in case update is required by policy but device has reached end-of-life and it is the last day to return the device back to the enterprise."> + <ph name="DOMAIN">$1<ex>example.com</ex></ph> requires you to back up your data and return this device today.<ph name="LINK_BEGIN"><a target="_blank" href="$2<ex>https://google.com/</ex>"></ph>See details<ph name="LINK_END"></a></ph> + </message> + <message name="IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_ONE_WEEK" desc="Banner displayed in OS settings page in case update is required by policy but device has reached end-of-life and the days remaining to return the device back to the enterprise is equal to seven."> + <ph name="DOMAIN">$1<ex>example.com</ex></ph> requires you to back up your data and return this device within 1 week.<ph name="LINK_BEGIN"><a target="_blank" href="$2<ex>https://google.com/</ex>"></ph>See details<ph name="LINK_END"></a></ph> + </message> <!-- Settings Search Box --> <message name="IDS_OS_SEARCH_RESULT_ROW_A11Y_RESULT_SELECTED" desc="ChromeVox alert to indicate the position number of a selected result in a list of search results and the selected result text itself, and that the user can press enter to navigate to section described by the search result.">
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_DAYS.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_DAYS.png.sha1 new file mode 100644 index 0000000..9e106a1 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_DAYS.png.sha1
@@ -0,0 +1 @@ +932a1b84fef78d74fa7802ad184487feaa2e9e5f \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_LAST_DAY.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_LAST_DAY.png.sha1 new file mode 100644 index 0000000..e226813 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_LAST_DAY.png.sha1
@@ -0,0 +1 @@ +836fdeaa65fa654bd342623dd680ee6ff378b295 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_ONE_WEEK.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_ONE_WEEK.png.sha1 new file mode 100644 index 0000000..49bf1e6 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_ONE_WEEK.png.sha1
@@ -0,0 +1 @@ +6dcd6792924c36dc064038d41aba50c07f105a6f \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 934c20a..b3d125d 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1257,6 +1257,8 @@ "prefs/profile_pref_store_manager.h", "prefs/session_startup_pref.cc", "prefs/session_startup_pref.h", + "prerender/chrome_prerender_contents_delegate.cc", + "prerender/chrome_prerender_contents_delegate.h", "prerender/chrome_prerender_manager_delegate.cc", "prerender/chrome_prerender_manager_delegate.h", "prerender/isolated/isolated_prerender_features.cc", @@ -1290,6 +1292,7 @@ "prerender/prerende_manager_delegate.h", "prerender/prerender_contents.cc", "prerender/prerender_contents.h", + "prerender/prerender_contents_delegate.h", "prerender/prerender_field_trial.cc", "prerender/prerender_field_trial.h", "prerender/prerender_handle.cc", @@ -3310,11 +3313,8 @@ "metrics/tab_stats_tracker.cc", "metrics/tab_stats_tracker.h", "metrics/tab_stats_tracker_delegate.h", - "nearby_sharing/attachment.h", "nearby_sharing/fast_initiation_manager.cc", "nearby_sharing/fast_initiation_manager.h", - "nearby_sharing/file_attachment.cc", - "nearby_sharing/file_attachment.h", "nearby_sharing/incoming_frames_reader.cc", "nearby_sharing/incoming_frames_reader.h", "nearby_sharing/incoming_share_target_info.cc", @@ -3354,10 +3354,10 @@ "nearby_sharing/share_target.cc", "nearby_sharing/share_target.h", "nearby_sharing/share_target_discovered_callback.h", - "nearby_sharing/text_attachment.cc", - "nearby_sharing/text_attachment.h", "nearby_sharing/transfer_metadata.cc", "nearby_sharing/transfer_metadata.h", + "nearby_sharing/transfer_metadata_builder.cc", + "nearby_sharing/transfer_metadata_builder.h", "nearby_sharing/transfer_update_callback.h", "nearby_sharing/webrtc_signaling_messenger.cc", "nearby_sharing/webrtc_signaling_messenger.h", @@ -3442,8 +3442,6 @@ "resource_coordinator/discard_metrics_lifecycle_unit_observer.h", "resource_coordinator/intervention_policy_database.cc", "resource_coordinator/intervention_policy_database.h", - "resource_coordinator/leveldb_site_characteristics_database.cc", - "resource_coordinator/leveldb_site_characteristics_database.h", "resource_coordinator/lifecycle_unit.cc", "resource_coordinator/lifecycle_unit.h", "resource_coordinator/lifecycle_unit_base.cc", @@ -3454,28 +3452,6 @@ "resource_coordinator/lifecycle_unit_source_base.cc", "resource_coordinator/lifecycle_unit_source_base.h", "resource_coordinator/lifecycle_unit_source_observer.h", - "resource_coordinator/local_site_characteristics_data_impl.cc", - "resource_coordinator/local_site_characteristics_data_impl.h", - "resource_coordinator/local_site_characteristics_data_reader.cc", - "resource_coordinator/local_site_characteristics_data_reader.h", - "resource_coordinator/local_site_characteristics_data_store.cc", - "resource_coordinator/local_site_characteristics_data_store.h", - "resource_coordinator/local_site_characteristics_data_store_factory.cc", - "resource_coordinator/local_site_characteristics_data_store_factory.h", - "resource_coordinator/local_site_characteristics_data_store_inspector.cc", - "resource_coordinator/local_site_characteristics_data_store_inspector.h", - "resource_coordinator/local_site_characteristics_data_writer.cc", - "resource_coordinator/local_site_characteristics_data_writer.h", - "resource_coordinator/local_site_characteristics_database.h", - "resource_coordinator/local_site_characteristics_non_recording_data_store.cc", - "resource_coordinator/local_site_characteristics_non_recording_data_store.h", - "resource_coordinator/local_site_characteristics_noop_data_writer.cc", - "resource_coordinator/local_site_characteristics_noop_data_writer.h", - "resource_coordinator/local_site_characteristics_webcontents_observer.cc", - "resource_coordinator/local_site_characteristics_webcontents_observer.h", - "resource_coordinator/site_characteristics_data_reader.h", - "resource_coordinator/site_characteristics_data_store.h", - "resource_coordinator/site_characteristics_data_writer.h", "resource_coordinator/tab_activity_watcher.cc", "resource_coordinator/tab_activity_watcher.h", "resource_coordinator/tab_lifecycle_observer.h", @@ -3770,6 +3746,7 @@ "//base/util/timer", "//chrome/app/vector_icons", "//chrome/browser/media/kaleidoscope/mojom", + "//chrome/browser/nearby_sharing:share_target", "//chrome/browser/nearby_sharing/certificates", "//chrome/browser/nearby_sharing/client", "//chrome/browser/nearby_sharing/common",
diff --git a/chrome/browser/accessibility/caption_controller.cc b/chrome/browser/accessibility/caption_controller.cc index edb1a4d..d9d11a7f 100644 --- a/chrome/browser/accessibility/caption_controller.cc +++ b/chrome/browser/accessibility/caption_controller.cc
@@ -161,6 +161,15 @@ caption_bubble_controllers_.erase(browser); } +bool CaptionController::OnSpeechRecognitionReady( + content::WebContents* web_contents) { + Browser* browser = chrome::FindBrowserWithWebContents(web_contents); + if (!browser || !caption_bubble_controllers_.count(browser)) + return false; + return caption_bubble_controllers_[browser]->OnSpeechRecognitionReady( + web_contents); +} + bool CaptionController::DispatchTranscription( content::WebContents* web_contents, const chrome::mojom::TranscriptionResultPtr& transcription_result) {
diff --git a/chrome/browser/accessibility/caption_controller.h b/chrome/browser/accessibility/caption_controller.h index 274b46a..af1422d 100644 --- a/chrome/browser/accessibility/caption_controller.h +++ b/chrome/browser/accessibility/caption_controller.h
@@ -64,6 +64,12 @@ void Init(); + // Alerts the CaptionBubbleController that belongs to the appropriate browser + // that speech recognition is ready to start for the given web contents. + // Returns whether this message was routed successfully. Transcriptions will + // not proceed if this returns false. + bool OnSpeechRecognitionReady(content::WebContents* web_contents); + // Routes a transcription to the CaptionBubbleController that belongs to the // appropriate browser. Returns whether the transcription result was routed // successfully. Transcriptions will halt if this returns false.
diff --git a/chrome/browser/accessibility/caption_controller_browsertest.cc b/chrome/browser/accessibility/caption_controller_browsertest.cc index 968dad09..157e7ed 100644 --- a/chrome/browser/accessibility/caption_controller_browsertest.cc +++ b/chrome/browser/accessibility/caption_controller_browsertest.cc
@@ -83,6 +83,21 @@ ->GetCaptionBubbleControllerForBrowser(browser); } + bool OnSpeechRecognitionReady() { + return OnSpeechRecognitionReadyOnBrowser(browser()); + } + + bool OnSpeechRecognitionReadyOnBrowser(Browser* browser) { + return OnSpeechRecognitionReadyOnBrowserForProfile(browser, + browser->profile()); + } + + bool OnSpeechRecognitionReadyOnBrowserForProfile(Browser* browser, + Profile* profile) { + return GetControllerForProfile(profile)->OnSpeechRecognitionReady( + browser->tab_strip_model()->GetActiveWebContents()); + } + bool DispatchTranscription(std::string text) { return DispatchTranscriptionToBrowser(text, browser()); } @@ -173,9 +188,8 @@ IN_PROC_BROWSER_TEST_F(CaptionControllerTest, LiveCaptionEnabledChanged_BubbleVisible) { SetLiveCaptionEnabled(true); - // Make the bubble visible by dispatching a transcription. - DispatchTranscription( - "In Switzerland it is illegal to own just one guinea pig."); + // Make the bubble visible. + OnSpeechRecognitionReady(); // The CaptionBubbleController is currently only implemented in Views. #if defined(TOOLKIT_VIEWS) EXPECT_TRUE(IsWidgetVisible()); @@ -248,9 +262,8 @@ controller->GetCaptionBubbleControllerForBrowser(browser4)); EXPECT_EQ(3, NumBubbleControllers()); - // Make the bubble on browser3 visible by dispatching a transcription. - DispatchTranscriptionToBrowser( - "If you lift a kangaroo's tail off the ground it can't hop.", browser3); + // Make the bubble on browser3 visible. + OnSpeechRecognitionReadyOnBrowser(browser3); // The CaptionBubbleController is currently only implemented in Views. #if defined(TOOLKIT_VIEWS) EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser3)); @@ -263,9 +276,8 @@ controller->GetCaptionBubbleControllerForBrowser(browser3)); EXPECT_EQ(2, NumBubbleControllers()); - // Make the bubble on browser2 visible by dispatching a transcription. - DispatchTranscriptionToBrowser( - "A lion's roar can be heard from 5 miles away.", browser2); + // Make the bubble on browser2 visible. + OnSpeechRecognitionReadyOnBrowser(browser2); // The CaptionBubbleController is currently only implemented in Views. #if defined(TOOLKIT_VIEWS) EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser2)); @@ -301,11 +313,8 @@ incognito_browser2)); EXPECT_EQ(2, NumBubbleControllers()); - // Make the bubble on incognito_browser1 visible by dispatching a - // transcription. - DispatchTranscriptionToBrowser( - "If you lift a kangaroo's tail off the ground it can't hop.", - incognito_browser1); + // Make the bubble on incognito_browser1 visible. + OnSpeechRecognitionReadyOnBrowser(incognito_browser1); // The CaptionBubbleController is currently only implemented in Views. #if defined(TOOLKIT_VIEWS) EXPECT_TRUE(IsWidgetVisibleOnBrowser(incognito_browser1)); @@ -319,12 +328,77 @@ EXPECT_EQ(1, NumBubbleControllers()); } +IN_PROC_BROWSER_TEST_F(CaptionControllerTest, OnSpeechRecognitionReady) { + bool success = OnSpeechRecognitionReady(); + EXPECT_FALSE(success); + EXPECT_EQ(0, NumBubbleControllers()); + + SetLiveCaptionEnabled(true); + success = OnSpeechRecognitionReady(); + EXPECT_TRUE(success); +// The CaptionBubbleController is currently only implemented in Views. +#if defined(TOOLKIT_VIEWS) + EXPECT_TRUE(IsWidgetVisible()); +#else + EXPECT_FALSE(IsWidgetVisible()); +#endif + + SetLiveCaptionEnabled(false); + success = OnSpeechRecognitionReady(); + EXPECT_FALSE(success); + EXPECT_EQ(0, NumBubbleControllers()); +} + +IN_PROC_BROWSER_TEST_F(CaptionControllerTest, + OnSpeechRecognitionReady_MultipleBrowsers) { + Browser* browser1 = browser(); + Browser* browser2 = CreateBrowser(browser()->profile()); + Browser* incognito_browser = CreateIncognitoBrowser(); + SetLiveCaptionEnabled(true); + + // OnSpeechRecognitionReady routes to the right browser. + bool success = OnSpeechRecognitionReadyOnBrowser(browser1); + EXPECT_TRUE(success); +// The CaptionBubbleController is currently only implemented in Views. +#if defined(TOOLKIT_VIEWS) + EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser1)); + EXPECT_FALSE(IsWidgetVisibleOnBrowser(browser2)); + EXPECT_FALSE(IsWidgetVisibleOnBrowser(incognito_browser)); +#else + EXPECT_FALSE(IsWidgetVisibleOnBrowser(browser1)); +#endif + + success = OnSpeechRecognitionReadyOnBrowser(browser2); + EXPECT_TRUE(success); +// The CaptionBubbleController is currently only implemented in Views. +#if defined(TOOLKIT_VIEWS) + EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser1)); + EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser2)); + EXPECT_FALSE(IsWidgetVisibleOnBrowser(incognito_browser)); +#else + EXPECT_FALSE(IsWidgetVisibleOnBrowser(browser2)); +#endif + + success = OnSpeechRecognitionReadyOnBrowser(incognito_browser); + EXPECT_TRUE(success); +// The CaptionBubbleController is currently only implemented in Views. +#if defined(TOOLKIT_VIEWS) + EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser1)); + EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser2)); + EXPECT_TRUE(IsWidgetVisibleOnBrowser(incognito_browser)); +#else + EXPECT_FALSE(IsWidgetVisibleOnBrowser(incognito_browser)); +#endif +} + IN_PROC_BROWSER_TEST_F(CaptionControllerTest, DispatchTranscription) { + OnSpeechRecognitionReady(); bool success = DispatchTranscription("A baby spider is called a spiderling."); EXPECT_FALSE(success); EXPECT_EQ(0, NumBubbleControllers()); SetLiveCaptionEnabled(true); + OnSpeechRecognitionReady(); success = DispatchTranscription( "A baby octopus is about the size of a flea when it is born."); EXPECT_TRUE(success); @@ -338,6 +412,7 @@ #endif SetLiveCaptionEnabled(false); + OnSpeechRecognitionReady(); success = DispatchTranscription( "Approximately 10-20% of power outages in the US are caused by " "squirrels."); @@ -353,6 +428,7 @@ SetLiveCaptionEnabled(true); // Dispatch transcription routes the transcription to the right browser. + OnSpeechRecognitionReadyOnBrowser(browser1); bool success = DispatchTranscriptionToBrowser( "Honeybees can recognize human faces.", browser1); EXPECT_TRUE(success); @@ -369,6 +445,7 @@ EXPECT_FALSE(IsWidgetVisibleOnBrowser(browser1)); #endif + OnSpeechRecognitionReadyOnBrowser(browser2); success = DispatchTranscriptionToBrowser( "A blue whale's heart is the size of a small car.", browser2); EXPECT_TRUE(success); @@ -386,6 +463,7 @@ EXPECT_FALSE(IsWidgetVisibleOnBrowser(browser2)); #endif + OnSpeechRecognitionReadyOnBrowser(incognito_browser); success = DispatchTranscriptionToBrowser( "Squirrels forget where they hide about half of their nuts.", incognito_browser); @@ -501,10 +579,8 @@ EXPECT_EQ(1, NumBubbleControllersForProfile(profile1)); EXPECT_EQ(0, NumBubbleControllersForProfile(profile2)); - // Make the bubble on incognito_browser1 visible by dispatching a - // transcription. - DispatchTranscriptionToBrowser( - "If you lift a kangaroo's tail off the ground it can't hop.", browser1); + // Make the bubble on incognito_browser1 visible. + OnSpeechRecognitionReadyOnBrowser(browser1); // The CaptionBubbleController is currently only implemented in Views. #if defined(TOOLKIT_VIEWS) EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser1)); @@ -520,6 +596,52 @@ } IN_PROC_BROWSER_TEST_F(CaptionControllerTest, + OnSpeechRecognitionReady_MultipleProfiles) { + Profile* profile1 = browser()->profile(); + Profile* profile2 = CreateProfile(); + Browser* browser1 = browser(); + Browser* browser2 = CreateBrowser(profile2); + + // Enable live caption on both profiles. + SetLiveCaptionEnabled(true); + profile2->GetPrefs()->SetBoolean(prefs::kLiveCaptionEnabled, true); + + // OnSpeechRecognitionReady routes to the right browser on the right profile. + bool success = + OnSpeechRecognitionReadyOnBrowserForProfile(browser1, profile1); + EXPECT_TRUE(success); +// The CaptionBubbleController is currently only implemented in Views. +#if defined(TOOLKIT_VIEWS) + EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser1)); + EXPECT_FALSE(IsWidgetVisibleOnBrowser(browser2)); +#else + EXPECT_FALSE(IsWidgetVisibleOnBrowser(browser1)); +#endif + + success = OnSpeechRecognitionReadyOnBrowserForProfile(browser2, profile2); + EXPECT_TRUE(success); +// The CaptionBubbleController is currently only implemented in Views. +#if defined(TOOLKIT_VIEWS) + EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser1)); + EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser2)); +#else + EXPECT_FALSE(IsWidgetVisibleOnBrowser(browser1)); +#endif + + // OnSpeechRecognitionReady returns false for browsers on different profiles. + success = OnSpeechRecognitionReadyOnBrowserForProfile(browser1, profile2); + EXPECT_FALSE(success); +// The CaptionBubbleController is currently only implemented in Views. +#if defined(TOOLKIT_VIEWS) + EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser1)); + EXPECT_TRUE(IsWidgetVisibleOnBrowser(browser2)); +#else + EXPECT_FALSE(IsWidgetVisibleOnBrowser(browser1)); + EXPECT_FALSE(IsWidgetVisibleOnBrowser(browser2)); +#endif +} + +IN_PROC_BROWSER_TEST_F(CaptionControllerTest, DispatchTranscription_MultipleProfiles) { Profile* profile1 = browser()->profile(); Profile* profile2 = CreateProfile(); @@ -532,6 +654,7 @@ // Dispatch transcription routes the transcription to the right browser on the // right profile. + OnSpeechRecognitionReadyOnBrowserForProfile(browser1, profile1); bool success = DispatchTranscriptionToBrowserForProfile( "Only female mosquitos bite.", browser1, profile1); EXPECT_TRUE(success); @@ -546,6 +669,7 @@ EXPECT_FALSE(IsWidgetVisibleOnBrowser(browser1)); #endif + OnSpeechRecognitionReadyOnBrowserForProfile(browser2, profile2); success = DispatchTranscriptionToBrowserForProfile( "Mosquitos were around at the time of the dinosaurs.", browser2, profile2);
diff --git a/chrome/browser/accessibility/caption_host_impl.cc b/chrome/browser/accessibility/caption_host_impl.cc index deaa6ec..b549c9bb 100644 --- a/chrome/browser/accessibility/caption_host_impl.cc +++ b/chrome/browser/accessibility/caption_host_impl.cc
@@ -39,6 +39,29 @@ CaptionHostImpl::~CaptionHostImpl() = default; +void CaptionHostImpl::OnSpeechRecognitionReady( + OnSpeechRecognitionReadyCallback reply) { + if (!frame_host_) { + std::move(reply).Run(false); + return; + } + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost(frame_host_); + if (!web_contents) { + frame_host_ = nullptr; + std::move(reply).Run(false); + return; + } + Profile* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + if (!profile) { + std::move(reply).Run(false); + return; + } + std::move(reply).Run(CaptionControllerFactory::GetForProfile(profile) + ->OnSpeechRecognitionReady(web_contents)); +} + void CaptionHostImpl::OnTranscription( chrome::mojom::TranscriptionResultPtr transcription_result, OnTranscriptionCallback reply) {
diff --git a/chrome/browser/accessibility/caption_host_impl.h b/chrome/browser/accessibility/caption_host_impl.h index 3e3615e6..23be8ed 100644 --- a/chrome/browser/accessibility/caption_host_impl.h +++ b/chrome/browser/accessibility/caption_host_impl.h
@@ -37,6 +37,8 @@ mojo::PendingReceiver<chrome::mojom::CaptionHost> receiver); // chrome::mojom::CaptionHost: + void OnSpeechRecognitionReady( + OnSpeechRecognitionReadyCallback reply) override; void OnTranscription( chrome::mojom::TranscriptionResultPtr transcription_result, OnTranscriptionCallback reply) override;
diff --git a/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc b/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc index 1e4865f..4fcccfb 100644 --- a/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc +++ b/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/apps/intent_helper/intent_picker_auto_display_service.h" #include "chrome/browser/apps/intent_helper/page_transition_util.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" @@ -253,7 +254,8 @@ // Do not create the throttle if no apps can be installed. // Do not create the throttle in incognito or for a prerender navigation. if (web_contents->GetBrowserContext()->IsOffTheRecord() || - prerender::PrerenderContents::FromWebContents(web_contents) != nullptr) { + prerender::ChromePrerenderContentsDelegate::FromWebContents( + web_contents) != nullptr) { return false; }
diff --git a/chrome/browser/apps/platform_apps/platform_app_navigation_redirector.cc b/chrome/browser/apps/platform_apps/platform_app_navigation_redirector.cc index f60040d..e30a336 100644 --- a/chrome/browser/apps/platform_apps/platform_app_navigation_redirector.cc +++ b/chrome/browser/apps/platform_apps/platform_app_navigation_redirector.cc
@@ -7,6 +7,7 @@ #include "apps/launcher.h" #include "base/bind.h" #include "base/logging.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_finder.h" @@ -43,7 +44,7 @@ // If prerendering, don't launch the app but abort the navigation. prerender::PrerenderContents* prerender_contents = - prerender::PrerenderContents::FromWebContents(source); + prerender::ChromePrerenderContentsDelegate::FromWebContents(source); if (prerender_contents) { prerender_contents->Destroy(prerender::FINAL_STATUS_NAVIGATION_INTERCEPTED); return true;
diff --git a/chrome/browser/browser_switcher/browser_switcher_navigation_throttle.cc b/chrome/browser/browser_switcher/browser_switcher_navigation_throttle.cc index 7c7f17b..20c626ae 100644 --- a/chrome/browser/browser_switcher/browser_switcher_navigation_throttle.cc +++ b/chrome/browser/browser_switcher/browser_switcher_navigation_throttle.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/browser_switcher/browser_switcher_service.h" #include "chrome/browser/browser_switcher/browser_switcher_service_factory.h" #include "chrome/browser/browser_switcher/browser_switcher_sitelist.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/webui_url_constants.h" @@ -62,7 +63,7 @@ // If prerendering, don't launch the alternative browser but abort the // navigation. prerender::PrerenderContents* prerender_contents = - prerender::PrerenderContents::FromWebContents(web_contents); + prerender::ChromePrerenderContentsDelegate::FromWebContents(web_contents); if (prerender_contents) { prerender_contents->Destroy(prerender::FINAL_STATUS_BROWSER_SWITCH); return true;
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 59cc6a5b..e339ba9 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/navigation_predictor/navigation_predictor.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/predictors/network_hints_handler_impl.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/prerender/prerender_processor_impl.h" #include "chrome/browser/profiles/profile.h" @@ -284,7 +285,7 @@ return; auto* prerender_contents = - prerender::PrerenderContents::FromWebContents(web_contents); + prerender::ChromePrerenderContentsDelegate::FromWebContents(web_contents); if (!prerender_contents) return; prerender_contents->AddPrerenderCancelerReceiver(std::move(receiver));
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index da405a9f3..96077da 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -91,6 +91,7 @@ #include "chrome/browser/platform_util.h" #include "chrome/browser/plugins/pdf_iframe_navigation_throttle.h" #include "chrome/browser/plugins/plugin_utils.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/isolated/isolated_prerender_features.h" #include "chrome/browser/prerender/isolated/isolated_prerender_service.h" #include "chrome/browser/prerender/isolated/isolated_prerender_service_factory.h" @@ -945,7 +946,8 @@ mojo::PendingRemote<prerender::mojom::PrerenderCanceler> GetPrerenderCanceler( base::OnceCallback<content::WebContents*()> wc_getter) { mojo::PendingRemote<prerender::mojom::PrerenderCanceler> canceler; - prerender::PrerenderContents::FromWebContents(std::move(wc_getter).Run()) + prerender::ChromePrerenderContentsDelegate::FromWebContents( + std::move(wc_getter).Run()) ->AddPrerenderCancelerReceiver(canceler.InitWithNewPipeAndPassReceiver()); return canceler; } @@ -980,7 +982,7 @@ // Do not launch external requests attached to unswapped prerenders. prerender::PrerenderContents* prerender_contents = - prerender::PrerenderContents::FromWebContents(web_contents); + prerender::ChromePrerenderContentsDelegate::FromWebContents(web_contents); if (prerender_contents) { prerender_contents->Destroy(prerender::FINAL_STATUS_UNSUPPORTED_SCHEME); return; @@ -2869,7 +2871,7 @@ // If the tab is being prerendered, cancel the prerender and the request. prerender::PrerenderContents* prerender_contents = - prerender::PrerenderContents::FromWebContents(web_contents); + prerender::ChromePrerenderContentsDelegate::FromWebContents(web_contents); if (prerender_contents) { prerender_contents->Destroy(prerender::FINAL_STATUS_SSL_ERROR); if (!callback.is_null()) { @@ -2960,7 +2962,7 @@ net::ClientCertIdentityList client_certs, std::unique_ptr<content::ClientCertificateDelegate> delegate) { prerender::PrerenderContents* prerender_contents = - prerender::PrerenderContents::FromWebContents(web_contents); + prerender::ChromePrerenderContentsDelegate::FromWebContents(web_contents); if (prerender_contents) { prerender_contents->Destroy( prerender::FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED); @@ -3141,7 +3143,8 @@ } #endif - DCHECK(!prerender::PrerenderContents::FromWebContents(web_contents)); + DCHECK(!prerender::ChromePrerenderContentsDelegate::FromWebContents( + web_contents)); BlockedWindowParams blocked_params( target_url, source_origin, opener->GetSiteInstance(), referrer, @@ -3946,7 +3949,8 @@ // TODO(davidben): This is insufficient to integrate with prerender properly. // https://crbug.com/370595 prerender::PrerenderContents* prerender_contents = - prerender::PrerenderContents::FromWebContents(handle->GetWebContents()); + prerender::ChromePrerenderContentsDelegate::FromWebContents( + handle->GetWebContents()); if (!prerender_contents && handle->IsInMainFrame()) { throttles.push_back( navigation_interception::InterceptNavigationDelegate::CreateThrottleFor(
diff --git a/chrome/browser/chrome_service_worker_browsertest.cc b/chrome/browser/chrome_service_worker_browsertest.cc index 34d5d18..803c9ae 100644 --- a/chrome/browser/chrome_service_worker_browsertest.cc +++ b/chrome/browser/chrome_service_worker_browsertest.cc
@@ -219,11 +219,11 @@ embedded_test_server()->GetURL("/scope/done.html")); EXPECT_EQ(expected_title2, title_watcher2.WaitAndGetTitle()); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_TRUE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents) - ->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); + content::RenderFrameHost* main_frame = + browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(); + EXPECT_TRUE( + content_settings::TabSpecificContentSettings::GetForFrame(main_frame) + ->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); } IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerTest,
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index cc07952..a7d40e3 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1990,6 +1990,10 @@ "policy/display_rotation_default_handler.h", "policy/display_settings_handler.cc", "policy/display_settings_handler.h", + "policy/dlp/dlp_content_manager.cc", + "policy/dlp/dlp_content_manager.h", + "policy/dlp/dlp_content_tab_helper.cc", + "policy/dlp/dlp_content_tab_helper.h", "policy/dlp/enterprise_clipboard_dlp_controller.cc", "policy/dlp/enterprise_clipboard_dlp_controller.h", "policy/dm_token_storage.cc", @@ -3279,6 +3283,8 @@ "policy/device_dock_mac_address_source_handler_unittest.cc", "policy/device_local_account_policy_service_unittest.cc", "policy/device_policy_decoder_chromeos_unittest.cc", + "policy/dlp/dlp_content_manager_unittest.cc", + "policy/dlp/dlp_content_tab_helper_unittest.cc", "policy/dm_token_storage_unittest.cc", "policy/extension_cache_unittest.cc", "policy/extension_install_event_log_collector_unittest.cc",
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_manager.cc b/chrome/browser/chromeos/policy/dlp/dlp_content_manager.cc new file mode 100644 index 0000000..1844ddb --- /dev/null +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_manager.cc
@@ -0,0 +1,107 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h" + +#include "base/stl_util.h" +#include "content/public/browser/visibility.h" +#include "content/public/browser/web_contents.h" +#include "url/gurl.h" + +namespace policy { + +static DlpContentManager* g_dlp_content_manager = nullptr; + +// static +DlpContentManager* DlpContentManager::Get() { + if (!g_dlp_content_manager) + g_dlp_content_manager = new DlpContentManager(); + return g_dlp_content_manager; +} + +bool DlpContentManager::IsWebContentsConfidential( + const content::WebContents* web_contents) const { + return base::Contains(confidential_web_contents_, web_contents); +} + +bool DlpContentManager::IsConfidentialDataPresentOnScreen() const { + return is_confidential_web_contents_visible_; +} + +/* static */ +void DlpContentManager::SetDlpContentManagerForTesting( + DlpContentManager* dlp_content_manager) { + if (g_dlp_content_manager) + delete g_dlp_content_manager; + g_dlp_content_manager = dlp_content_manager; +} + +/* static */ +void DlpContentManager::ResetDlpContentManagerForTesting() { + g_dlp_content_manager = nullptr; +} + +DlpContentManager::DlpContentManager() = default; + +DlpContentManager::~DlpContentManager() = default; + +void DlpContentManager::OnConfidentialityChanged( + content::WebContents* web_contents, + bool confidential) { + if (confidential) { + AddToConfidential(web_contents); + } else { + RemoveFromConfidential(web_contents); + } +} + +void DlpContentManager::OnWebContentsDestroyed( + const content::WebContents* web_contents) { + RemoveFromConfidential(web_contents); +} + +bool DlpContentManager::IsURLConfidential(const GURL& url) const { + // TODO(crbug/1109783): Implement based on the policy. + return false; +} + +void DlpContentManager::OnVisibilityChanged(content::WebContents* web_contents, + bool visible) { + MaybeChangeVisibilityFlag(); +} + +void DlpContentManager::AddToConfidential(content::WebContents* web_contents) { + confidential_web_contents_.insert(web_contents); + if (web_contents->GetVisibility() == content::Visibility::VISIBLE) { + MaybeChangeVisibilityFlag(); + } +} + +void DlpContentManager::RemoveFromConfidential( + const content::WebContents* web_contents) { + confidential_web_contents_.erase(web_contents); + MaybeChangeVisibilityFlag(); +} + +void DlpContentManager::MaybeChangeVisibilityFlag() { + bool is_confidential_web_contents_currently_visible = false; + for (auto* web_contents : confidential_web_contents_) { + if (web_contents->GetVisibility() == content::Visibility::VISIBLE) { + is_confidential_web_contents_currently_visible = true; + break; + } + } + if (is_confidential_web_contents_visible_ != + is_confidential_web_contents_currently_visible) { + is_confidential_web_contents_visible_ = + is_confidential_web_contents_currently_visible; + OnScreenConfidentialityStateChanged(is_confidential_web_contents_visible_); + } +} + +void DlpContentManager::OnScreenConfidentialityStateChanged(bool visible) { + // TODO(crbug/1105991): Implement enforcing/releasing of restrictions. +} + +} // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_manager.h b/chrome/browser/chromeos/policy/dlp/dlp_content_manager.h new file mode 100644 index 0000000..3a353f8 --- /dev/null +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_manager.h
@@ -0,0 +1,87 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_POLICY_DLP_DLP_CONTENT_MANAGER_H_ +#define CHROME_BROWSER_CHROMEOS_POLICY_DLP_DLP_CONTENT_MANAGER_H_ + +#include "base/containers/flat_set.h" + +class GURL; + +namespace content { +class WebContents; +} // namespace content + +namespace policy { + +// System-wide class that tracks the set of currently known confidential +// WebContents and whether any of them are currently visible. +// If any confidential WebContents is visible, the corresponding restrictions +// will be enforced according to the current enterprise policy. +class DlpContentManager { + public: + // Creates the instance if not yet created. + // There will always be a single instance created on the first access. + static DlpContentManager* Get(); + + // Checks whether |web_contents| is confidential according to the policy. + bool IsWebContentsConfidential( + const content::WebContents* web_contents) const; + + // Returns whether any WebContents with a confidential content is currently + // visible. + bool IsConfidentialDataPresentOnScreen() const; + + // The caller (test) should manage |dlp_content_manager| lifetime. + // Reset doesn't delete the object. + static void SetDlpContentManagerForTesting( + DlpContentManager* dlp_content_manager); + static void ResetDlpContentManagerForTesting(); + + private: + friend class DlpContentManagerTest; + friend class DlpContentTabHelper; + friend class MockDlpContentManager; + + DlpContentManager(); + virtual ~DlpContentManager(); + DlpContentManager(const DlpContentManager&) = delete; + DlpContentManager& operator=(const DlpContentManager&) = delete; + + // Called from DlpContentTabHelper: + // Being called when confidentiality state changes for |web_contents|, e.g. + // because of navigation. + virtual void OnConfidentialityChanged(content::WebContents* web_contents, + bool confidential); + // Called when |web_contents| is about to be destroyed. + virtual void OnWebContentsDestroyed(const content::WebContents* web_contents); + // Should return whether |url| is considered as confidential according to + // the policies. + virtual bool IsURLConfidential(const GURL& url) const; + // Called when |web_contents| becomes visible or not. + virtual void OnVisibilityChanged(content::WebContents* web_contents, + bool visible); + + // Helpers to add/remove WebContents from confidential sets. + void AddToConfidential(content::WebContents* web_contents); + void RemoveFromConfidential(const content::WebContents* web_contents); + + // Updates |is_confidential_web_contents_visible_| and calls + // OnScreenConfidentialityStateChanged() if needed. + void MaybeChangeVisibilityFlag(); + + // Called when a confidential content becomes visible or all confidential + // content becomes not visible. + void OnScreenConfidentialityStateChanged(bool visible); + + // Set of currently known confidential WebContents. + base::flat_set<content::WebContents*> confidential_web_contents_; + // Flag the indicates whether any confidential WebContents is currently + // visible or not. + bool is_confidential_web_contents_visible_ = false; +}; + +} // namespace policy + +#endif // CHROME_BROWSER_CHROMEOS_POLICY_DLP_DLP_CONTENT_MANAGER_H_
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_manager_unittest.cc b/chrome/browser/chromeos/policy/dlp/dlp_content_manager_unittest.cc new file mode 100644 index 0000000..b3cc879 --- /dev/null +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_manager_unittest.cc
@@ -0,0 +1,141 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h" + +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/browser_task_environment.h" +#include "content/public/test/test_renderer_host.h" +#include "content/public/test/web_contents_tester.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +class DlpContentManagerTest : public testing::Test { + protected: + void SetUp() override { + testing::Test::SetUp(); + + profile_ = std::make_unique<TestingProfile>(); + } + + std::unique_ptr<content::WebContents> CreateWebContents() { + return content::WebContentsTester::CreateTestWebContents(profile_.get(), + nullptr); + } + + void ChangeConfidentiality(content::WebContents* web_contents, + bool confidential) { + manager_.OnConfidentialityChanged(web_contents, confidential); + } + + void ChangeVisibility(content::WebContents* web_contents, bool visible) { + if (visible) { + web_contents->WasShown(); + } else { + web_contents->WasHidden(); + } + manager_.OnVisibilityChanged(web_contents, visible); + } + + void DestroyWebContents(content::WebContents* web_contents) { + manager_.OnWebContentsDestroyed(web_contents); + } + + DlpContentManager manager_; + + private: + content::BrowserTaskEnvironment task_environment_; + content::RenderViewHostTestEnabler rvh_test_enabler_; + std::unique_ptr<TestingProfile> profile_; +}; + +TEST_F(DlpContentManagerTest, NoConfidentialDataShown) { + std::unique_ptr<content::WebContents> web_contents = CreateWebContents(); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents.get())); + EXPECT_FALSE(manager_.IsConfidentialDataPresentOnScreen()); +} + +TEST_F(DlpContentManagerTest, ConfidentialDataShown) { + std::unique_ptr<content::WebContents> web_contents = CreateWebContents(); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents.get())); + EXPECT_FALSE(manager_.IsConfidentialDataPresentOnScreen()); + + ChangeConfidentiality(web_contents.get(), /*confidential=*/true); + EXPECT_TRUE(manager_.IsWebContentsConfidential(web_contents.get())); + EXPECT_TRUE(manager_.IsConfidentialDataPresentOnScreen()); + + DestroyWebContents(web_contents.get()); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents.get())); + EXPECT_FALSE(manager_.IsConfidentialDataPresentOnScreen()); +} + +TEST_F(DlpContentManagerTest, ConfidentialDataVisibilityChanged) { + std::unique_ptr<content::WebContents> web_contents = CreateWebContents(); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents.get())); + EXPECT_FALSE(manager_.IsConfidentialDataPresentOnScreen()); + + ChangeConfidentiality(web_contents.get(), /*confidential=*/true); + EXPECT_TRUE(manager_.IsWebContentsConfidential(web_contents.get())); + EXPECT_TRUE(manager_.IsConfidentialDataPresentOnScreen()); + + ChangeVisibility(web_contents.get(), /*visible=*/false); + EXPECT_TRUE(manager_.IsWebContentsConfidential(web_contents.get())); + EXPECT_FALSE(manager_.IsConfidentialDataPresentOnScreen()); + + ChangeVisibility(web_contents.get(), /*visible=*/true); + EXPECT_TRUE(manager_.IsWebContentsConfidential(web_contents.get())); + EXPECT_TRUE(manager_.IsConfidentialDataPresentOnScreen()); + + DestroyWebContents(web_contents.get()); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents.get())); + EXPECT_FALSE(manager_.IsConfidentialDataPresentOnScreen()); +} + +TEST_F(DlpContentManagerTest, + TwoWebContentsVisibilityAndConfidentialityChanged) { + std::unique_ptr<content::WebContents> web_contents1 = CreateWebContents(); + std::unique_ptr<content::WebContents> web_contents2 = CreateWebContents(); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents1.get())); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents2.get())); + EXPECT_FALSE(manager_.IsConfidentialDataPresentOnScreen()); + + // WebContents 1 becomes confidential. + ChangeConfidentiality(web_contents1.get(), /*confidential=*/true); + EXPECT_TRUE(manager_.IsWebContentsConfidential(web_contents1.get())); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents2.get())); + EXPECT_TRUE(manager_.IsConfidentialDataPresentOnScreen()); + + // WebContents 2 is hidden. + ChangeVisibility(web_contents2.get(), /*visible=*/false); + EXPECT_TRUE(manager_.IsWebContentsConfidential(web_contents1.get())); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents2.get())); + EXPECT_TRUE(manager_.IsConfidentialDataPresentOnScreen()); + + // WebContents 1 becomes non-confidential. + ChangeConfidentiality(web_contents1.get(), /*confidential=*/false); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents1.get())); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents2.get())); + EXPECT_FALSE(manager_.IsConfidentialDataPresentOnScreen()); + + // WebContents 2 becomes confidential. + ChangeConfidentiality(web_contents2.get(), /*confidential=*/true); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents1.get())); + EXPECT_TRUE(manager_.IsWebContentsConfidential(web_contents2.get())); + EXPECT_FALSE(manager_.IsConfidentialDataPresentOnScreen()); + + // WebContents 2 is visible. + ChangeVisibility(web_contents2.get(), /*visible=*/true); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents1.get())); + EXPECT_TRUE(manager_.IsWebContentsConfidential(web_contents2.get())); + EXPECT_TRUE(manager_.IsConfidentialDataPresentOnScreen()); + + DestroyWebContents(web_contents1.get()); + DestroyWebContents(web_contents2.get()); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents1.get())); + EXPECT_FALSE(manager_.IsWebContentsConfidential(web_contents2.get())); + EXPECT_FALSE(manager_.IsConfidentialDataPresentOnScreen()); +} + +} // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper.cc b/chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper.cc new file mode 100644 index 0000000..e5945a6 --- /dev/null +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper.cc
@@ -0,0 +1,81 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper.h" + +#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" +#include "url/gurl.h" + +namespace policy { + +DlpContentTabHelper::~DlpContentTabHelper() = default; + +void DlpContentTabHelper::RenderFrameCreated( + content::RenderFrameHost* render_frame_host) { + if (DlpContentManager::Get()->IsURLConfidential( + render_frame_host->GetLastCommittedURL())) { + const bool inserted = confidential_frames_.insert(render_frame_host).second; + if (inserted && confidential_frames_.size() == 1) { + DlpContentManager::Get()->OnConfidentialityChanged(web_contents(), + /*confidential=*/true); + } + } +} + +void DlpContentTabHelper::RenderFrameDeleted( + content::RenderFrameHost* render_frame_host) { + const bool erased = confidential_frames_.erase(render_frame_host); + if (erased && confidential_frames_.empty()) + DlpContentManager::Get()->OnConfidentialityChanged(web_contents(), + /*confidential=*/false); +} + +void DlpContentTabHelper::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + if (!navigation_handle->HasCommitted() || navigation_handle->IsErrorPage()) + return; + if (DlpContentManager::Get()->IsURLConfidential( + navigation_handle->GetURL())) { + const bool inserted = + confidential_frames_.insert(navigation_handle->GetRenderFrameHost()) + .second; + if (inserted && confidential_frames_.size() == 1) { + DlpContentManager::Get()->OnConfidentialityChanged(web_contents(), + /*confidential=*/true); + } + } else { + const bool erased = + confidential_frames_.erase(navigation_handle->GetRenderFrameHost()); + if (erased && confidential_frames_.empty()) + DlpContentManager::Get()->OnConfidentialityChanged( + web_contents(), + /*confidential=*/false); + } +} + +void DlpContentTabHelper::WebContentsDestroyed() { + DlpContentManager::Get()->OnWebContentsDestroyed(web_contents()); +} + +void DlpContentTabHelper::OnVisibilityChanged(content::Visibility visibility) { + // DlpContentManager tracks visibility only for confidential WebContents. + if (!IsConfidential()) + return; + DlpContentManager::Get()->OnVisibilityChanged( + web_contents(), visibility == content::Visibility::VISIBLE); +} + +DlpContentTabHelper::DlpContentTabHelper(content::WebContents* web_contents) + : content::WebContentsObserver(web_contents) {} + +bool DlpContentTabHelper::IsConfidential() const { + return !confidential_frames_.empty(); +} + +WEB_CONTENTS_USER_DATA_KEY_IMPL(DlpContentTabHelper) + +} // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper.h b/chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper.h new file mode 100644 index 0000000..bffff1f --- /dev/null +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper.h
@@ -0,0 +1,60 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_POLICY_DLP_DLP_CONTENT_TAB_HELPER_H_ +#define CHROME_BROWSER_CHROMEOS_POLICY_DLP_DLP_CONTENT_TAB_HELPER_H_ + +#include "base/containers/flat_set.h" +#include "content/public/browser/visibility.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace content { +class NavigationHandle; +class RenderFrameHost; +class WebContents; +} // namespace content + +namespace policy { + +// DlpContentTabHelper attaches to relevant WebContents that are covered by +// DLP (Data Leak Prevention) feature and observes navigation in all sub-frames +// as well as visibility of the WebContents and reports it to system-wide +// DlpContentManager. +// WebContents is considered as confidential if either the main frame or any +// of sub-frames are confidential according to the current policy. +class DlpContentTabHelper + : public content::WebContentsUserData<DlpContentTabHelper>, + public content::WebContentsObserver { + public: + ~DlpContentTabHelper() override; + + // content::WebContentsObserver: + void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; + void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; + void WebContentsDestroyed() override; + void OnVisibilityChanged(content::Visibility visibility) override; + + private: + friend class content::WebContentsUserData<DlpContentTabHelper>; + + explicit DlpContentTabHelper(content::WebContents* web_contents); + DlpContentTabHelper(const DlpContentTabHelper&) = delete; + DlpContentTabHelper& operator=(const DlpContentTabHelper&) = delete; + + // WebContents is considered as confidential if either the main frame or any + // of sub-frames are confidential. + bool IsConfidential() const; + + // Set of the currently known confidential frames. + base::flat_set<content::RenderFrameHost*> confidential_frames_; + + WEB_CONTENTS_USER_DATA_KEY_DECL(); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_CHROMEOS_POLICY_DLP_DLP_CONTENT_TAB_HELPER_H_
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper_unittest.cc b/chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper_unittest.cc new file mode 100644 index 0000000..1bf4eb8 --- /dev/null +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper_unittest.cc
@@ -0,0 +1,176 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper.h" + +#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_activity_simulator.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "chrome/test/base/test_browser_window.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/test/navigation_simulator.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +using testing::_; +using testing::Return; + +class MockDlpContentManager : public DlpContentManager { + public: + MOCK_METHOD2(OnConfidentialityChanged, void(content::WebContents*, bool)); + MOCK_METHOD1(OnWebContentsDestroyed, void(const content::WebContents*)); + MOCK_CONST_METHOD1(IsURLConfidential, bool(const GURL&)); + MOCK_METHOD2(OnVisibilityChanged, void(content::WebContents*, bool)); +}; + +class DlpContentTabHelperTest : public ChromeRenderViewHostTestHarness { + protected: + void SetUp() override { + ChromeRenderViewHostTestHarness::SetUp(); + + DlpContentManager::SetDlpContentManagerForTesting( + &mock_dlp_content_manager_); + + // Initialize browser. + params_ = std::make_unique<Browser::CreateParams>(profile(), + /*user_gesture=*/true); + browser_ = CreateBrowserWithTestWindowForParams(params_.get()); + tab_strip_model_ = browser_->tab_strip_model(); + } + + void TearDown() override { + tab_strip_model_->CloseAllTabs(); + browser_.reset(); + params_.reset(); + + DlpContentManager::ResetDlpContentManagerForTesting(); + + ChromeRenderViewHostTestHarness::TearDown(); + } + + MockDlpContentManager mock_dlp_content_manager_; + TabActivitySimulator tab_activity_simulator_; + TabStripModel* tab_strip_model_; + std::unique_ptr<Browser::CreateParams> params_; + std::unique_ptr<Browser> browser_; +}; + +TEST_F(DlpContentTabHelperTest, SingleNotConfidentialWebContents) { + GURL kUrl = GURL("https://example.com"); + EXPECT_CALL(mock_dlp_content_manager_, IsURLConfidential(GURL())) + .Times(1) + .WillOnce(Return(false)); + EXPECT_CALL(mock_dlp_content_manager_, IsURLConfidential(kUrl)) + .Times(1) + .WillOnce(Return(false)); + EXPECT_CALL(mock_dlp_content_manager_, OnConfidentialityChanged(_, _)) + .Times(0); + EXPECT_CALL(mock_dlp_content_manager_, OnVisibilityChanged(_, _)).Times(0); + + content::WebContents* web_contents = + tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model_, kUrl); + EXPECT_NE(nullptr, DlpContentTabHelper::FromWebContents(web_contents)); + + EXPECT_CALL(mock_dlp_content_manager_, OnWebContentsDestroyed(_)).Times(1); +} + +TEST_F(DlpContentTabHelperTest, SingleConfidentialWebContents) { + GURL kUrl = GURL("https://example.com"); + EXPECT_CALL(mock_dlp_content_manager_, IsURLConfidential(GURL())) + .Times(1) + .WillOnce(Return(false)); + EXPECT_CALL(mock_dlp_content_manager_, IsURLConfidential(kUrl)) + .Times(1) + .WillOnce(Return(true)); + EXPECT_CALL(mock_dlp_content_manager_, OnConfidentialityChanged(_, true)) + .Times(1); + EXPECT_CALL(mock_dlp_content_manager_, OnVisibilityChanged(_, _)).Times(0); + + content::WebContents* web_contents = + tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model_, kUrl); + EXPECT_NE(nullptr, DlpContentTabHelper::FromWebContents(web_contents)); + + EXPECT_CALL(mock_dlp_content_manager_, OnConfidentialityChanged(_, false)) + .Times(1); + EXPECT_CALL(mock_dlp_content_manager_, OnWebContentsDestroyed(_)).Times(1); +} + +TEST_F(DlpContentTabHelperTest, TwoWebContentsVisibilityChanged) { + GURL kUrl1 = GURL("https://example1.com"); + GURL kUrl2 = GURL("https://example2.com"); + EXPECT_CALL(mock_dlp_content_manager_, IsURLConfidential(GURL())) + .WillRepeatedly(Return(false)); + EXPECT_CALL(mock_dlp_content_manager_, IsURLConfidential(kUrl1)) + .Times(1) + .WillOnce(Return(true)); + EXPECT_CALL(mock_dlp_content_manager_, IsURLConfidential(kUrl2)) + .Times(1) + .WillOnce(Return(false)); + EXPECT_CALL(mock_dlp_content_manager_, OnConfidentialityChanged(_, true)) + .Times(1); + EXPECT_CALL(mock_dlp_content_manager_, OnVisibilityChanged(_, _)).Times(0); + + content::WebContents* web_contents1 = + tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model_, + kUrl1); + content::WebContents* web_contents2 = + tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model_, + kUrl2); + EXPECT_NE(nullptr, DlpContentTabHelper::FromWebContents(web_contents1)); + EXPECT_NE(nullptr, DlpContentTabHelper::FromWebContents(web_contents2)); + EXPECT_CALL(mock_dlp_content_manager_, OnVisibilityChanged(_, false)) + .Times(1); + + tab_activity_simulator_.SwitchToTabAt(tab_strip_model_, 1); + + EXPECT_CALL(mock_dlp_content_manager_, OnVisibilityChanged(_, true)).Times(1); + + tab_activity_simulator_.SwitchToTabAt(tab_strip_model_, 0); + + EXPECT_CALL(mock_dlp_content_manager_, OnConfidentialityChanged(_, false)) + .Times(1); + EXPECT_CALL(mock_dlp_content_manager_, OnWebContentsDestroyed(_)).Times(2); +} + +TEST_F(DlpContentTabHelperTest, SubFrameNavigation) { + GURL kNonConfidentialUrl = GURL("https://example.com"); + GURL kConfidentialUrl = GURL("https://google.com"); + EXPECT_CALL(mock_dlp_content_manager_, IsURLConfidential(GURL())) + .WillRepeatedly(Return(false)); + EXPECT_CALL(mock_dlp_content_manager_, IsURLConfidential(kNonConfidentialUrl)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(mock_dlp_content_manager_, IsURLConfidential(kConfidentialUrl)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(mock_dlp_content_manager_, OnConfidentialityChanged(_, _)) + .Times(0); + EXPECT_CALL(mock_dlp_content_manager_, OnVisibilityChanged(_, _)).Times(0); + + // Create WebContents. + content::WebContents* web_contents = + tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model_, + kNonConfidentialUrl); + EXPECT_NE(nullptr, DlpContentTabHelper::FromWebContents(web_contents)); + + // Add subframe and navigate to confidential URL. + EXPECT_CALL(mock_dlp_content_manager_, OnConfidentialityChanged(_, true)) + .Times(1); + content::RenderFrameHost* subframe = + content::NavigationSimulator::NavigateAndCommitFromDocument( + kConfidentialUrl, + content::RenderFrameHostTester::For(web_contents->GetMainFrame()) + ->AppendChild("child")); + + // Navigate away from confidential URL. + EXPECT_CALL(mock_dlp_content_manager_, OnConfidentialityChanged(_, false)) + .Times(1); + content::NavigationSimulator::NavigateAndCommitFromDocument( + kNonConfidentialUrl, subframe); + + EXPECT_CALL(mock_dlp_content_manager_, OnWebContentsDestroyed(_)).Times(1); +} + +} // namespace policy
diff --git a/chrome/browser/chromeos/policy/extension_install_event_log_collector.cc b/chrome/browser/chromeos/policy/extension_install_event_log_collector.cc index 8e68bc6..aeb18c1 100644 --- a/chrome/browser/chromeos/policy/extension_install_event_log_collector.cc +++ b/chrome/browser/chromeos/policy/extension_install_event_log_collector.cc
@@ -153,6 +153,38 @@ } } +// Helper method to convert ExtensionDownloaderDelegate::Stage to the +// DownloadingStage proto. +em::ExtensionInstallReportLogEvent_DownloadingStage +ConvertDownloadingStageToProto( + extensions::ExtensionDownloaderDelegate::Stage stage) { + using DownloadingStage = extensions::ExtensionDownloaderDelegate::Stage; + switch (stage) { + case DownloadingStage::PENDING: + return em::ExtensionInstallReportLogEvent::DOWNLOAD_PENDING; + case DownloadingStage::QUEUED_FOR_MANIFEST: + return em::ExtensionInstallReportLogEvent::QUEUED_FOR_MANIFEST; + case DownloadingStage::DOWNLOADING_MANIFEST: + return em::ExtensionInstallReportLogEvent::DOWNLOADING_MANIFEST; + case DownloadingStage::DOWNLOADING_MANIFEST_RETRY: + return em::ExtensionInstallReportLogEvent::DOWNLOADING_MANIFEST_RETRY; + case DownloadingStage::PARSING_MANIFEST: + return em::ExtensionInstallReportLogEvent::PARSING_MANIFEST; + case DownloadingStage::MANIFEST_LOADED: + return em::ExtensionInstallReportLogEvent::MANIFEST_LOADED; + case DownloadingStage::QUEUED_FOR_CRX: + return em::ExtensionInstallReportLogEvent::QUEUED_FOR_CRX; + case DownloadingStage::DOWNLOADING_CRX: + return em::ExtensionInstallReportLogEvent::DOWNLOADING_CRX; + case DownloadingStage::DOWNLOADING_CRX_RETRY: + return em::ExtensionInstallReportLogEvent::DOWNLOADING_CRX_RETRY; + case DownloadingStage::FINISHED: + return em::ExtensionInstallReportLogEvent::FINISHED; + default: + NOTREACHED(); + } +} + } // namespace ExtensionInstallEventLogCollector::ExtensionInstallEventLogCollector( @@ -248,6 +280,16 @@ delegate_->Add(id, true /* gather_disk_space_info */, std::move(event)); } +void ExtensionInstallEventLogCollector::OnExtensionDownloadingStageChanged( + const extensions::ExtensionId& id, + extensions::ExtensionDownloaderDelegate::Stage stage) { + if (!delegate_->IsExtensionPending(id)) + return; + auto event = std::make_unique<em::ExtensionInstallReportLogEvent>(); + event->set_downloading_stage(ConvertDownloadingStageToProto(stage)); + delegate_->Add(id, true /* gather_disk_space_info */, std::move(event)); +} + void ExtensionInstallEventLogCollector::OnExtensionLoaded( content::BrowserContext* browser_context, const extensions::Extension* extension) {
diff --git a/chrome/browser/chromeos/policy/extension_install_event_log_collector.h b/chrome/browser/chromeos/policy/extension_install_event_log_collector.h index 4428878..8676121 100644 --- a/chrome/browser/chromeos/policy/extension_install_event_log_collector.h +++ b/chrome/browser/chromeos/policy/extension_install_event_log_collector.h
@@ -100,6 +100,9 @@ void OnExtensionInstallationStageChanged( const extensions::ExtensionId& id, extensions::InstallStageTracker::Stage stage) override; + void OnExtensionDownloadingStageChanged( + const extensions::ExtensionId& id, + extensions::ExtensionDownloaderDelegate::Stage stage) override; // Reports success events for the extensions which are requested from policy // and are already loaded.
diff --git a/chrome/browser/chromeos/policy/extension_install_event_log_collector_unittest.cc b/chrome/browser/chromeos/policy/extension_install_event_log_collector_unittest.cc index da44860..771155c 100644 --- a/chrome/browser/chromeos/policy/extension_install_event_log_collector_unittest.cc +++ b/chrome/browser/chromeos/policy/extension_install_event_log_collector_unittest.cc
@@ -420,4 +420,42 @@ 0 /*expected_add_all_count*/)); } +// Verifies that a new event is created when the downloading stage is changed +// during the downloading process. +TEST_F(ExtensionInstallEventLogCollectorTest, DownloadingStageChanged) { + std::unique_ptr<ExtensionInstallEventLogCollector> collector = + std::make_unique<ExtensionInstallEventLogCollector>( + registry(), delegate(), profile()); + + auto ext = extensions::ExtensionBuilder(kExtensionName1) + .SetID(kExtensionId1) + .Build(); + collector->OnExtensionDownloadingStageChanged( + kExtensionId1, extensions::ExtensionDownloaderDelegate::Stage::PENDING); + ASSERT_TRUE(VerifyEventAddedSuccessfully(1 /*expected_add_count*/, + 0 /*expected_add_all_count*/)); + EXPECT_EQ(em::ExtensionInstallReportLogEvent::DOWNLOAD_PENDING, + delegate()->last_request().event.downloading_stage()); + collector->OnExtensionDownloadingStageChanged( + kExtensionId1, + extensions::ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST); + ASSERT_TRUE(VerifyEventAddedSuccessfully(2 /*expected_add_count*/, + 0 /*expected_add_all_count*/)); + EXPECT_EQ(em::ExtensionInstallReportLogEvent::DOWNLOADING_MANIFEST, + delegate()->last_request().event.downloading_stage()); + collector->OnExtensionDownloadingStageChanged( + kExtensionId1, + extensions::ExtensionDownloaderDelegate::Stage::DOWNLOADING_CRX); + ASSERT_TRUE(VerifyEventAddedSuccessfully(3 /*expected_add_count*/, + 0 /*expected_add_all_count*/)); + EXPECT_EQ(em::ExtensionInstallReportLogEvent::DOWNLOADING_CRX, + delegate()->last_request().event.downloading_stage()); + collector->OnExtensionDownloadingStageChanged( + kExtensionId1, extensions::ExtensionDownloaderDelegate::Stage::FINISHED); + ASSERT_TRUE(VerifyEventAddedSuccessfully(4 /*expected_add_count*/, + 0 /*expected_add_all_count*/)); + EXPECT_EQ(em::ExtensionInstallReportLogEvent::FINISHED, + delegate()->last_request().event.downloading_stage()); +} + } // namespace policy
diff --git a/chrome/browser/chromeos/policy/install_event_log_util.cc b/chrome/browser/chromeos/policy/install_event_log_util.cc index 89465c7..f321b2f 100644 --- a/chrome/browser/chromeos/policy/install_event_log_util.cc +++ b/chrome/browser/chromeos/policy/install_event_log_util.cc
@@ -41,6 +41,7 @@ // Chrome Reporting API. constexpr char kExtensionId[] = "extensionId"; constexpr char kExtensionInstallEvent[] = "extensionAppInstallEvent"; +constexpr char kDownloadStage[] = "downloadStage"; // Calculates hash for the given |event| and |context|, and stores the hash in // |hash|. Returns true if |event| and |context| are json serializable and @@ -159,6 +160,11 @@ extension_install_report_log_event.session_state_change_type()); } + if (extension_install_report_log_event.has_downloading_stage()) { + event.SetIntKey(kDownloadStage, + extension_install_report_log_event.downloading_stage()); + } + event.SetStringKey(kSerialNumber, GetSerialNumber()); base::Value wrapper(base::Value::Type::DICTIONARY);
diff --git a/chrome/browser/chromeos/policy/minimum_version_policy_handler.cc b/chrome/browser/chromeos/policy/minimum_version_policy_handler.cc index 7a443bb..6c8b48d 100644 --- a/chrome/browser/chromeos/policy/minimum_version_policy_handler.cc +++ b/chrome/browser/chromeos/policy/minimum_version_policy_handler.cc
@@ -102,10 +102,13 @@ } // namespace +const char MinimumVersionPolicyHandler::kRequirements[] = "requirements"; const char MinimumVersionPolicyHandler::kChromeOsVersion[] = "chromeos_version"; const char MinimumVersionPolicyHandler::kWarningPeriod[] = "warning_period"; const char MinimumVersionPolicyHandler::kEolWarningPeriod[] = "aue_warning_period"; +const char MinimumVersionPolicyHandler::kUnmanagedUserRestricted[] = + "unmanaged_user_restricted"; MinimumVersionRequirement::MinimumVersionRequirement( const base::Version version, @@ -218,16 +221,23 @@ return; } - const base::ListValue* entries; - std::vector<std::unique_ptr<MinimumVersionRequirement>> configs; - if (!cros_settings_->GetList(chromeos::kDeviceMinimumVersion, &entries) || - !entries->GetSize()) { - // Reset state and hide update required screen if policy is not set or set - // to empty list. + const base::DictionaryValue* policy_value; + if (!cros_settings_->GetDictionary(chromeos::kDeviceMinimumVersion, + &policy_value)) { + VLOG(1) << "Revoke policy - policy is unset or value is incorrect."; HandleUpdateNotRequired(); return; } + const base::Value* entries = policy_value->FindListKey(kRequirements); + if (!entries || entries->GetList().empty()) { + VLOG(1) << "Revoke policy - empty policy requirements."; + HandleUpdateNotRequired(); + return; + } + auto restricted = policy_value->FindBoolKey(kUnmanagedUserRestricted); + unmanaged_user_restricted_ = restricted.value_or(false); + std::vector<std::unique_ptr<MinimumVersionRequirement>> configs; for (const auto& item : entries->GetList()) { const base::DictionaryValue* dict; if (item.GetAsDictionary(&dict)) { @@ -440,25 +450,29 @@ build_state->AddObserver(this); } -void MinimumVersionPolicyHandler::MaybeShowNotificationOnLogin() { +base::Optional<int> MinimumVersionPolicyHandler::GetTimeRemainingInDays() { const base::Time now = clock_->Now(); - // This should only be true if |update_required_deadline_timer_| expired while + if (!state_ || update_required_deadline_ <= now) + return base::nullopt; + base::TimeDelta time_remaining = update_required_deadline_ - now; + return GetDaysRounded(time_remaining); +} + +void MinimumVersionPolicyHandler::MaybeShowNotificationOnLogin() { + // |days| could be null if |update_required_deadline_timer_| expired while // login was in progress, else we would have shown the update required screen // at startup. - if (update_required_deadline_ <= now) - return; - - base::TimeDelta time_remaining = update_required_deadline_ - now; - int days_remaining = GetDaysRounded(time_remaining); - if (days_remaining <= 1) - MaybeShowNotification(base::TimeDelta::FromDays(days_remaining)); + base::Optional<int> days = GetTimeRemainingInDays(); + if (days && days.value() <= 1) + MaybeShowNotification(base::TimeDelta::FromDays(days.value())); } void MinimumVersionPolicyHandler::MaybeShowNotification( base::TimeDelta warning) { const NetworkStatus status = GetCurrentNetworkStatus(); if ((!eol_reached_ && status == NetworkStatus::kAllowed) || - !delegate_->IsUserLoggedIn() || !delegate_->IsUserManaged()) { + !delegate_->IsUserLoggedIn() || + (!delegate_->IsUserEnterpriseManaged() && !unmanaged_user_restricted_)) { return; } @@ -611,9 +625,12 @@ if (delegate_->IsLoginSessionState() && !delegate_->IsLoginInProgress()) { // Show update required screen over the login screen. delegate_->ShowUpdateRequiredScreen(); - } else if (delegate_->IsUserLoggedIn() && delegate_->IsUserManaged()) { + } else if (delegate_->IsUserLoggedIn() && + (delegate_->IsUserEnterpriseManaged() || + unmanaged_user_restricted_)) { // Terminate the current user session to show update required - // screen on the login screen if user is managed. + // screen on the login screen if the user is managed or + // |unmanaged_user_restricted_| is set to true. delegate_->RestartToLoginScreen(); } // No action is required if -
diff --git a/chrome/browser/chromeos/policy/minimum_version_policy_handler.h b/chrome/browser/chromeos/policy/minimum_version_policy_handler.h index 7b0a7bc9..3a841e6 100644 --- a/chrome/browser/chromeos/policy/minimum_version_policy_handler.h +++ b/chrome/browser/chromeos/policy/minimum_version_policy_handler.h
@@ -24,11 +24,11 @@ class Clock; class DictionaryValue; class Time; -} +} // namespace base namespace chromeos { class UpdateRequiredNotification; -} +} // namespace chromeos namespace policy { @@ -44,9 +44,11 @@ public chromeos::NetworkStateHandlerObserver, public chromeos::UpdateEngineClient::Observer { public: + static const char kRequirements[]; static const char kChromeOsVersion[]; static const char kWarningPeriod[]; static const char kEolWarningPeriod[]; + static const char kUnmanagedUserRestricted[]; class Observer { public: @@ -69,8 +71,8 @@ // Checks if a user is logged in. virtual bool IsUserLoggedIn() const = 0; - // Checks if the user logged in is a managed user. - virtual bool IsUserManaged() const = 0; + // Checks if the user logged in is managed and not a child user. + virtual bool IsUserEnterpriseManaged() const = 0; // Checks if we are currently on the login screen. virtual bool IsLoginSessionState() const = 0; @@ -156,13 +158,19 @@ static void RegisterPrefs(PrefRegistrySimple* registry); - // Show notification on managed user login if it is the last day to deadline. + // Show notification on login if the user is managed or + // |unmanaged_user_restricted_| is set to true if it is the last day to + // deadline. void MaybeShowNotificationOnLogin(); // Returns true if an update is required and the device has reached // End Of Life (Auto Update Expiration). bool IsUpdateRequiredEol() const; + // Returns the number of days to deadline if update is required and deadline + // has not been reached. Returns null if update is not required. + base::Optional<int> GetTimeRemainingInDays(); + // Callback used in tests and invoked after end-of-life status has been // fetched from the update_engine. void set_fetch_eol_callback_for_testing(base::OnceClosure callback) { @@ -253,6 +261,10 @@ // version in all the configurations. std::unique_ptr<MinimumVersionRequirement> state_; + // If this flag is true, unmanaged user sessions receive update required + // notifications and are force logged out when deadline is reached. + bool unmanaged_user_restricted_ = false; + bool eol_reached_ = false; // If this flag is true, user should restricted to use the session by logging
diff --git a/chrome/browser/chromeos/policy/minimum_version_policy_handler_browsertest.cc b/chrome/browser/chromeos/policy/minimum_version_policy_handler_browsertest.cc index d6afe5c..d5ca2a5d2 100644 --- a/chrome/browser/chromeos/policy/minimum_version_policy_handler_browsertest.cc +++ b/chrome/browser/chromeos/policy/minimum_version_policy_handler_browsertest.cc
@@ -130,6 +130,9 @@ int warning, int eol_warning) const; + base::Value CreatePolicyValue(base::Value requirements, + bool unmanaged_user_restricted) const; + void SetUpdateEngineStatus(update_engine::Operation operation); protected: @@ -184,6 +187,17 @@ return dict; } +base::Value MinimumVersionPolicyTestBase::CreatePolicyValue( + base::Value requirements, + bool unmanaged_user_restricted) const { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetKey(MinimumVersionPolicyHandler::kRequirements, + std::move(requirements)); + dict.SetBoolKey(MinimumVersionPolicyHandler::kUnmanagedUserRestricted, + unmanaged_user_restricted); + return dict; +} + void MinimumVersionPolicyTestBase::SetUpdateEngineStatus( update_engine::Operation operation) { update_engine::StatusResult status; @@ -273,21 +287,22 @@ EXPECT_EQ(ash::LoginScreenTestApi::GetUsersCount(), 2); EXPECT_FALSE(ash::LoginScreenTestApi::IsOobeDialogVisible()); - // Create policy value as a list of requirements. + // Create policy value. base::Value requirement_list(base::Value::Type::LIST); - base::Value new_version_no_warning = - CreateRequirement(kNewVersion, kNoWarning, kNoWarning); - requirement_list.Append(std::move(new_version_no_warning)); + requirement_list.Append( + CreateRequirement(kNewVersion, kNoWarning, kNoWarning)); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); // Set new value for policy and check update required screen is shown on the // login screen. - SetDevicePolicyAndWaitForSettingChange(requirement_list); + SetDevicePolicyAndWaitForSettingChange(policy_value); chromeos::OobeScreenWaiter(chromeos::UpdateRequiredView::kScreenId).Wait(); EXPECT_TRUE(ash::LoginScreenTestApi::IsOobeDialogVisible()); // Revoke policy and check update required screen is hidden. - base::Value empty_list(base::Value::Type::LIST); - SetDevicePolicyAndWaitForSettingChange(empty_list); + base::Value empty_policy(base::Value::Type::DICTIONARY); + SetDevicePolicyAndWaitForSettingChange(empty_policy); chromeos::OobeScreenExitWaiter(chromeos::UpdateRequiredView::kScreenId) .Wait(); EXPECT_FALSE(ash::LoginScreenTestApi::IsOobeDialogVisible()); @@ -297,11 +312,13 @@ // Login the user into the session and mark as managed. LoginManagedUser(); - // Create policy value as a list of requirements. + // Create policy value. base::Value requirement_list(base::Value::Type::LIST); base::Value new_version_no_warning = CreateRequirement(kNewVersion, kNoWarning, kNoWarning); requirement_list.Append(std::move(new_version_no_warning)); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); // Create waiter to observe termination notification. content::WindowedNotificationObserver termination_waiter( @@ -309,7 +326,7 @@ content::NotificationService::AllSources()); // Set new value for policy and check that user is logged out of the session. - SetDevicePolicyAndWaitForSettingChange(requirement_list); + SetDevicePolicyAndWaitForSettingChange(policy_value); termination_waiter.Wait(); EXPECT_TRUE(chrome::IsAttemptingShutdown()); } @@ -342,7 +359,10 @@ base::Value requirement_short_warning(base::Value::Type::LIST); requirement_short_warning.Append( CreateRequirement(kNewVersion, kShortWarningInDays, kShortWarningInDays)); - SetDevicePolicyAndWaitForSettingChange(requirement_short_warning); + base::Value policy_short_warning( + CreatePolicyValue(std::move(requirement_short_warning), + false /* unmanaged_user_restricted */)); + SetDevicePolicyAndWaitForSettingChange(policy_short_warning); // Policy handler sets the local state and starts the deadline timer. timer_start_time = prefs->GetTime(prefs::kUpdateRequiredTimerStartTime); @@ -358,7 +378,10 @@ base::Value requirement_long_warning(base::Value::Type::LIST); requirement_long_warning.Append( CreateRequirement(kNewVersion, kLongWarningInDays, kLongWarningInDays)); - SetDevicePolicyAndWaitForSettingChange(requirement_long_warning); + base::Value policy_long_warning( + CreatePolicyValue(std::move(requirement_long_warning), + false /* unmanaged_user_restricted */)); + SetDevicePolicyAndWaitForSettingChange(policy_long_warning); // Warning time is increased but timer start time does not change. EXPECT_EQ(prefs->GetTime(prefs::kUpdateRequiredTimerStartTime), @@ -372,7 +395,10 @@ base::Value requirement_no_warning(base::Value::Type::LIST); requirement_no_warning.Append( CreateRequirement(kNewVersion, kNoWarning, kNoWarning)); - SetDevicePolicyAndWaitForSettingChange(requirement_no_warning); + base::Value policy_no_warning( + CreatePolicyValue(std::move(requirement_no_warning), + false /* unmanaged_user_restricted */)); + SetDevicePolicyAndWaitForSettingChange(policy_no_warning); // Warning time is not reduced as policy does not allow to reduce deadline. EXPECT_EQ(prefs->GetTime(prefs::kUpdateRequiredTimerStartTime), @@ -399,7 +425,10 @@ base::Value requirement_very_long_warning(base::Value::Type::LIST); requirement_very_long_warning.Append( CreateRequirement(kNewVersion, kVeryLongWarningInDays, kNoWarning)); - SetDevicePolicyAndWaitForSettingChange(requirement_very_long_warning); + base::Value policy_very_long_warning( + CreatePolicyValue(std::move(requirement_very_long_warning), + false /* unmanaged_user_restricted */)); + SetDevicePolicyAndWaitForSettingChange(policy_very_long_warning); EXPECT_EQ(prefs->GetTime(prefs::kUpdateRequiredTimerStartTime), timer_start_time); EXPECT_EQ(prefs->GetTimeDelta(prefs::kUpdateRequiredWarningPeriod), @@ -417,7 +446,10 @@ base::Value requirement_short_warning(base::Value::Type::LIST); requirement_short_warning.Append( CreateRequirement(kNewVersion, kShortWarningInDays, kShortWarningInDays)); - SetDevicePolicyAndWaitForSettingChange(requirement_short_warning); + base::Value policy_value( + CreatePolicyValue(std::move(requirement_short_warning), + false /* unmanaged_user_restricted */)); + SetDevicePolicyAndWaitForSettingChange(policy_value); // Policy handler starts the deadline timer. EXPECT_TRUE( @@ -460,33 +492,51 @@ // Login the user into the session. LoginUnmanagedUser(); - // Create policy value as a list of requirements. + // Create and set policy value. base::Value requirement_list(base::Value::Type::LIST); - base::Value new_version_no_warning = - CreateRequirement(kNewVersion, kNoWarning, kNoWarning); - requirement_list.Append(std::move(new_version_no_warning)); + requirement_list.Append( + CreateRequirement(kNewVersion, kNoWarning, kNoWarning)); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); // Set new value for pref and check that user session is not terminated. - SetDevicePolicyAndWaitForSettingChange(requirement_list); + SetDevicePolicyAndWaitForSettingChange(policy_value); EXPECT_FALSE(chrome::IsAttemptingShutdown()); } +IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyTest, + CriticalUpdateInSessionUnmanagedUserEnabled) { + LoginUnmanagedUser(); + + // Create and set policy value. + base::Value requirement_list(base::Value::Type::LIST); + requirement_list.Append( + CreateRequirement(kNewVersion, kNoWarning, kNoWarning)); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), true /* unmanaged_user_restricted */)); + SetDevicePolicyAndWaitForSettingChange(policy_value); + + EXPECT_TRUE(chrome::IsAttemptingShutdown()); +} + IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyTest, NoNetworkNotificationClick) { // Login the user into the session. DisconectAllNetworks(); LoginManagedUser(); - // Create policy value as a list of requirements. + // Create policy value. base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append( CreateRequirement(kNewVersion, kShortWarningInDays, kShortWarningInDays)); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); EXPECT_FALSE( display_service_tester_->GetNotification(kUpdateRequiredNotificationId)); EXPECT_FALSE(tray_test_api_->IsTrayBubbleOpen()); // Set new policy value and check that update required notification is shown. - SetDevicePolicyAndWaitForSettingChange(requirement_list); + SetDevicePolicyAndWaitForSettingChange(policy_value); EXPECT_TRUE( display_service_tester_->GetNotification(kUpdateRequiredNotificationId)); @@ -506,16 +556,18 @@ DisconectAllNetworks(); LoginManagedUser(); - // Create policy value as a list of requirements. + // Create policy value. base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append( CreateRequirement(kNewVersion, kShortWarningInDays, kShortWarningInDays)); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); EXPECT_FALSE( display_service_tester_->GetNotification(kUpdateRequiredNotificationId)); // Set new policy value and check that update required notification is shown. - SetDevicePolicyAndWaitForSettingChange(requirement_list); + SetDevicePolicyAndWaitForSettingChange(policy_value); EXPECT_TRUE( display_service_tester_->GetNotification(kUpdateRequiredNotificationId)); @@ -535,11 +587,13 @@ EXPECT_FALSE( display_service_tester_->GetNotification(kUpdateRequiredNotificationId)); - // Create and set policy value as a list of requirements. + // Create and set policy value. base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append(CreateRequirement(kNewVersion, kLastDayWarningInDays, kShortWarningInDays)); - SetDevicePolicyAndWaitForSettingChange(requirement_list); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); + SetDevicePolicyAndWaitForSettingChange(policy_value); // Login the user into the session and check that notification is shown. LoginManagedUser(); @@ -563,11 +617,13 @@ EXPECT_FALSE( display_service_tester_->GetNotification(kUpdateRequiredNotificationId)); - // Create and set policy value as a list of requirements. + // Create and set policy value. base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append(CreateRequirement(kNewVersion, kLastDayWarningInDays, kShortWarningInDays)); - SetDevicePolicyAndWaitForSettingChange(requirement_list); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); + SetDevicePolicyAndWaitForSettingChange(policy_value); // Login the user into the session and check that notification is not shown // for unmanaged user. @@ -576,16 +632,39 @@ display_service_tester_->GetNotification(kUpdateRequiredNotificationId)); } +IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyTest, + NotificationOnUnmanagedUserEnabled) { + DisconectAllNetworks(); + LoginUnmanagedUser(); + EXPECT_FALSE( + display_service_tester_->GetNotification(kUpdateRequiredNotificationId)); + + // Create and set policy value. + base::Value requirement_list(base::Value::Type::LIST); + requirement_list.Append( + CreateRequirement(kNewVersion, kShortWarningInDays, kShortWarningInDays)); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), true /* unmanaged_user_restricted */)); + SetDevicePolicyAndWaitForSettingChange(policy_value); + + // Notifications should be shown to unmanaged user if it has been set in the + // policy. + EXPECT_TRUE( + display_service_tester_->GetNotification(kUpdateRequiredNotificationId)); +} + IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyTest, NotificationsOnLogin) { DisconectAllNetworks(); EXPECT_FALSE( display_service_tester_->GetNotification(kUpdateRequiredNotificationId)); - // Create policy value as a list of requirements. + // Create and set policy value. base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append( CreateRequirement(kNewVersion, kShortWarningInDays, kShortWarningInDays)); - SetDevicePolicyAndWaitForSettingChange(requirement_list); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); + SetDevicePolicyAndWaitForSettingChange(policy_value); // Login the user into the session and check that notification is not shown as // it is not the last day to update device. @@ -601,16 +680,18 @@ ConnectCellularNetwork(); LoginManagedUser(); - // Create policy value as a list of requirements. + // Create policy value. base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append( CreateRequirement(kNewVersion, kShortWarningInDays, kShortWarningInDays)); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); EXPECT_FALSE( display_service_tester_->GetNotification(kUpdateRequiredNotificationId)); // Set new policy value and check that update required notification is shown. - SetDevicePolicyAndWaitForSettingChange(requirement_list); + SetDevicePolicyAndWaitForSettingChange(policy_value); EXPECT_TRUE( GetMinimumVersionPolicyHandler()->IsDeadlineTimerRunningForTesting()); EXPECT_TRUE( @@ -650,15 +731,17 @@ base::DefaultClock::GetInstance()->Now() - base::TimeDelta::FromDays(1)); LoginManagedUser(); - // Create policy value as a list of requirements. + // Create policy value. base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append( CreateRequirement(kNewVersion, kShortWarningInDays, kShortWarningInDays)); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); EXPECT_FALSE( display_service_tester_->GetNotification(kUpdateRequiredNotificationId)); // Set new policy value and check that update required notification is shown. - SetDevicePolicyAndWaitForSettingChange(requirement_list); + SetDevicePolicyAndWaitForSettingChange(policy_value); EXPECT_TRUE( GetMinimumVersionPolicyHandler()->IsDeadlineTimerRunningForTesting()); EXPECT_TRUE( @@ -680,11 +763,14 @@ IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyTest, RelaunchNotificationOverride) { LoginManagedUser(); - // Set policy value as a list of requirements. + // Create and set policy value. base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append( CreateRequirement(kNewVersion, kShortWarningInDays, kShortWarningInDays)); - SetDevicePolicyAndWaitForSettingChange(requirement_list); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); + SetDevicePolicyAndWaitForSettingChange(policy_value); + base::Time deadline = GetMinimumVersionPolicyHandler()->update_required_deadline_for_testing(); @@ -699,7 +785,8 @@ // Revoking update required should reset the overridden the relaunch // notifications. - SetDevicePolicyAndWaitForSettingChange(base::Value(base::Value::Type::LIST)); + SetDevicePolicyAndWaitForSettingChange( + base::Value(base::Value::Type::DICTIONARY)); EXPECT_NE(upgrade_detector->GetHighAnnoyanceDeadline(), deadline); } @@ -717,22 +804,22 @@ chromeos::OobeScreenWaiter(chromeos::GaiaView::kScreenId).Wait(); EXPECT_EQ(ash::LoginScreenTestApi::GetUsersCount(), 0); - // Create policy value as a list of requirements. + // Create and set policy value. base::Value requirement_list(base::Value::Type::LIST); - base::Value new_version_no_warning = - CreateRequirement(kNewVersion, kNoWarning, kNoWarning); - requirement_list.Append(std::move(new_version_no_warning)); + requirement_list.Append( + CreateRequirement(kNewVersion, kNoWarning, kNoWarning)); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); + SetDevicePolicyAndWaitForSettingChange(policy_value); - // Set new value for policy and check update required screen is shown on the - // login screen. - SetDevicePolicyAndWaitForSettingChange(requirement_list); + // Check update required screen is shown on the login screen. chromeos::OobeScreenWaiter(chromeos::UpdateRequiredView::kScreenId).Wait(); EXPECT_TRUE(ash::LoginScreenTestApi::IsOobeDialogVisible()); // Revoke policy and check update required screen is hidden and gaia screen is // shown. - base::Value empty_list(base::Value::Type::LIST); - SetDevicePolicyAndWaitForSettingChange(empty_list); + base::Value empty_policy(base::Value::Type::DICTIONARY); + SetDevicePolicyAndWaitForSettingChange(empty_policy); chromeos::OobeScreenExitWaiter(chromeos::UpdateRequiredView::kScreenId) .Wait(); chromeos::OobeScreenWaiter(chromeos::GaiaView::kScreenId).Wait(); @@ -746,14 +833,13 @@ void SetUpInProcessBrowserTestFixture() override { MinimumVersionPolicyTestBase::SetUpInProcessBrowserTestFixture(); - // Create policy value as a list of requirements. + // Create and set policy value. base::Value requirement_list(base::Value::Type::LIST); - base::Value new_version_no_warning = - CreateRequirement(kNewVersion, kNoWarning, kNoWarning); - requirement_list.Append(std::move(new_version_no_warning)); - - // Set new policy value. - SetAndRefreshMinimumChromeVersionPolicy(requirement_list); + requirement_list.Append( + CreateRequirement(kNewVersion, kNoWarning, kNoWarning)); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); + SetAndRefreshMinimumChromeVersionPolicy(policy_value); } }; @@ -875,11 +961,13 @@ // MinimumVersionPolicyTestBase: void SetUpInProcessBrowserTestFixture() override { MinimumVersionPolicyTestBase::SetUpInProcessBrowserTestFixture(); - // Create and set policy value as a list of requirements. + // Create and set policy value. base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append(CreateRequirement(kNewVersion, kShortWarningInDays, kShortWarningInDays)); - SetAndRefreshMinimumChromeVersionPolicy(requirement_list); + base::Value policy_value(CreatePolicyValue( + std::move(requirement_list), false /* unmanaged_user_restricted */)); + SetAndRefreshMinimumChromeVersionPolicy(policy_value); } private:
diff --git a/chrome/browser/chromeos/policy/minimum_version_policy_handler_delegate_impl.cc b/chrome/browser/chromeos/policy/minimum_version_policy_handler_delegate_impl.cc index 34db6580..d7f8943c 100644 --- a/chrome/browser/chromeos/policy/minimum_version_policy_handler_delegate_impl.cc +++ b/chrome/browser/chromeos/policy/minimum_version_policy_handler_delegate_impl.cc
@@ -41,7 +41,7 @@ user_manager::UserManager::Get()->IsUserLoggedIn(); } -bool MinimumVersionPolicyHandlerDelegateImpl::IsUserManaged() const { +bool MinimumVersionPolicyHandlerDelegateImpl::IsUserEnterpriseManaged() const { if (!IsUserLoggedIn()) return false; Profile* const profile = ProfileManager::GetPrimaryUserProfile(); @@ -50,7 +50,8 @@ // TODO(https://crbug.com/1048607): Handle the case when |IsUserLoggedIn| // returns true after Auth success but |IsManaged| returns false before user // policy fetched. - return profile->GetProfilePolicyConnector()->IsManaged(); + return profile->GetProfilePolicyConnector()->IsManaged() && + !profile->IsChild(); } bool MinimumVersionPolicyHandlerDelegateImpl::IsLoginSessionState() const {
diff --git a/chrome/browser/chromeos/policy/minimum_version_policy_handler_delegate_impl.h b/chrome/browser/chromeos/policy/minimum_version_policy_handler_delegate_impl.h index 9653099..9dc955c 100644 --- a/chrome/browser/chromeos/policy/minimum_version_policy_handler_delegate_impl.h +++ b/chrome/browser/chromeos/policy/minimum_version_policy_handler_delegate_impl.h
@@ -18,7 +18,7 @@ bool IsKioskMode() const override; bool IsEnterpriseManaged() const override; bool IsUserLoggedIn() const override; - bool IsUserManaged() const override; + bool IsUserEnterpriseManaged() const override; bool IsLoginSessionState() const override; bool IsLoginInProgress() const override; void ShowUpdateRequiredScreen() override;
diff --git a/chrome/browser/chromeos/policy/minimum_version_policy_handler_unittest.cc b/chrome/browser/chromeos/policy/minimum_version_policy_handler_unittest.cc index bc62f2f..1a48d45 100644 --- a/chrome/browser/chromeos/policy/minimum_version_policy_handler_unittest.cc +++ b/chrome/browser/chromeos/policy/minimum_version_policy_handler_unittest.cc
@@ -67,7 +67,7 @@ bool IsKioskMode() const; bool IsEnterpriseManaged() const; base::Version GetCurrentVersion() const; - bool IsUserManaged() const; + bool IsUserEnterpriseManaged() const; bool IsUserLoggedIn() const; bool IsLoginInProgress() const; MOCK_METHOD0(ShowUpdateRequiredScreen, void()); @@ -89,6 +89,9 @@ int warning, int eol_warning) const; + base::Value CreatePolicyValue(base::Value requirements, + bool unmanaged_user_restricted); + void VerifyUpdateRequiredNotification(const base::string16& expected_title, const base::string16& expected_message); @@ -184,7 +187,7 @@ return true; } -bool MinimumVersionPolicyHandlerTest::IsUserManaged() const { +bool MinimumVersionPolicyHandlerTest::IsUserEnterpriseManaged() const { return user_managed_; } @@ -222,6 +225,17 @@ return dict; } +base::Value MinimumVersionPolicyHandlerTest::CreatePolicyValue( + base::Value requirements, + bool unmanaged_user_restricted) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetKey(MinimumVersionPolicyHandler::kRequirements, + std::move(requirements)); + dict.SetBoolKey(MinimumVersionPolicyHandler::kUnmanagedUserRestricted, + unmanaged_user_restricted); + return dict; +} + void MinimumVersionPolicyHandlerTest::VerifyUpdateRequiredNotification( const base::string16& expected_title, const base::string16& expected_message) { @@ -236,6 +250,12 @@ // No policy applied yet. Check requirements are satisfied. EXPECT_TRUE(GetMinimumVersionPolicyHandler()->RequirementsAreSatisfied()); EXPECT_FALSE(GetState()); + EXPECT_FALSE(GetMinimumVersionPolicyHandler()->GetTimeRemainingInDays()); + + // This is needed to wait till EOL status is fetched from the update_engine. + base::RunLoop run_loop; + GetMinimumVersionPolicyHandler()->set_fetch_eol_callback_for_testing( + run_loop.QuitClosure()); // Create policy value as a list of requirements. base::Value requirement_list(base::Value::Type::LIST); @@ -243,30 +263,34 @@ CreateRequirement(kNewVersion, kShortWarning, kNoWarning); auto strongest_requirement = MinimumVersionRequirement::CreateInstanceIfValid( &base::Value::AsDictionaryValue(new_version_short_warning)); - base::Value newer_version_long_warning = - CreateRequirement(kNewerVersion, kLongWarning, kNoWarning); - base::Value newest_version_no_warning = - CreateRequirement(kNewestVersion, kNoWarning, kNoWarning); requirement_list.Append(std::move(new_version_short_warning)); - requirement_list.Append(std::move(newer_version_long_warning)); - requirement_list.Append(std::move(newest_version_no_warning)); + requirement_list.Append( + CreateRequirement(kNewerVersion, kLongWarning, kNoWarning)); + requirement_list.Append( + CreateRequirement(kNewestVersion, kNoWarning, kNoWarning)); // Set new value for pref and check that requirements are not satisfied. // The state in |MinimumVersionPolicyHandler| should be equal to the strongest // requirement as defined in the policy description. - SetPolicyPref(std::move(requirement_list)); + SetPolicyPref(CreatePolicyValue(std::move(requirement_list), + false /* unmanaged_user_restricted */)); + run_loop.Run(); EXPECT_FALSE(GetMinimumVersionPolicyHandler()->RequirementsAreSatisfied()); EXPECT_TRUE(GetState()); EXPECT_TRUE(strongest_requirement); EXPECT_EQ(GetState()->Compare(strongest_requirement.get()), 0); + EXPECT_TRUE(GetMinimumVersionPolicyHandler()->GetTimeRemainingInDays()); + EXPECT_EQ(GetMinimumVersionPolicyHandler()->GetTimeRemainingInDays().value(), + kShortWarning); // Reset the pref to empty list and verify state is reset. base::Value requirement_list2(base::Value::Type::LIST); SetPolicyPref(std::move(requirement_list2)); EXPECT_TRUE(GetMinimumVersionPolicyHandler()->RequirementsAreSatisfied()); EXPECT_FALSE(GetState()); + EXPECT_FALSE(GetMinimumVersionPolicyHandler()->GetTimeRemainingInDays()); } TEST_F(MinimumVersionPolicyHandlerTest, CriticalUpdates) { @@ -300,7 +324,8 @@ // Set new value for pref and check that requirements are not satisfied. // As the warning time is set to zero, the user should be logged out of the // session. - SetPolicyPref(std::move(requirement_list)); + SetPolicyPref(CreatePolicyValue(std::move(requirement_list), + false /* unmanaged_user_restricted */)); // Start the run loop to wait for EOL status fetch. run_loop.Run(); EXPECT_FALSE(GetMinimumVersionPolicyHandler()->RequirementsAreSatisfied()); @@ -338,7 +363,8 @@ // Set new value for pref and check that requirements are not satisfied. // Unmanaged user should not be logged out of the session. - SetPolicyPref(std::move(requirement_list)); + SetPolicyPref(CreatePolicyValue(std::move(requirement_list), + false /* unmanaged_user_restricted */)); // Start the run loop to wait for EOL status fetch. run_loop.Run(); EXPECT_FALSE(GetMinimumVersionPolicyHandler()->RequirementsAreSatisfied()); @@ -361,7 +387,8 @@ // Set new value for pref and check that requirements are still satisfied // as none of the requirements has version greater than current version. - SetPolicyPref(std::move(requirement_list)); + SetPolicyPref(CreatePolicyValue(std::move(requirement_list), + false /* unmanaged_user_restricted */)); EXPECT_TRUE(GetMinimumVersionPolicyHandler()->RequirementsAreSatisfied()); EXPECT_FALSE(GetState()); } @@ -384,7 +411,8 @@ base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append( CreateRequirement(kNewVersion, kLongWarning, kLongWarning)); - SetPolicyPref(std::move(requirement_list)); + SetPolicyPref(CreatePolicyValue(std::move(requirement_list), + false /* unmanaged_user_restricted */)); run_loop.Run(); EXPECT_TRUE( @@ -422,7 +450,8 @@ base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append( CreateRequirement(kNewVersion, kLongWarning, kLongWarning)); - SetPolicyPref(std::move(requirement_list)); + SetPolicyPref(CreatePolicyValue(std::move(requirement_list), + false /* unmanaged_user_restricted */)); run_loop.Run(); EXPECT_TRUE( @@ -472,7 +501,8 @@ base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append( CreateRequirement(kNewVersion, kLongWarning, kLongWarning)); - SetPolicyPref(std::move(requirement_list)); + SetPolicyPref(CreatePolicyValue(std::move(requirement_list), + false /* unmanaged_user_restricted */)); run_loop.Run(); EXPECT_TRUE( GetMinimumVersionPolicyHandler()->IsDeadlineTimerRunningForTesting()); @@ -513,7 +543,8 @@ base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append( CreateRequirement(kNewVersion, kLongWarning, kLongWarning)); - SetPolicyPref(std::move(requirement_list)); + SetPolicyPref(CreatePolicyValue(std::move(requirement_list), + false /* unmanaged_user_restricted */)); run_loop.Run(); EXPECT_TRUE( GetMinimumVersionPolicyHandler()->IsDeadlineTimerRunningForTesting()); @@ -571,7 +602,8 @@ base::Value requirement_list(base::Value::Type::LIST); requirement_list.Append( CreateRequirement(kNewVersion, kShortWarning, kShortWarning)); - SetPolicyPref(std::move(requirement_list)); + SetPolicyPref(CreatePolicyValue(std::move(requirement_list), + false /* unmanaged_user_restricted */)); run_loop.Run(); EXPECT_TRUE( GetMinimumVersionPolicyHandler()->IsDeadlineTimerRunningForTesting());
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc index a8e7879..74673a05 100644 --- a/chrome/browser/client_hints/client_hints_browsertest.cc +++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -300,15 +300,10 @@ // Verify that the user is not notified that cookies or JavaScript were // blocked on the webpage due to the checks done by client hints. void VerifyContentSettingsNotNotified() const { - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_FALSE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents) - ->IsContentBlocked(ContentSettingsType::COOKIES)); - - EXPECT_FALSE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents) - ->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); + auto* tscs = content_settings::TabSpecificContentSettings::GetForFrame( + browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()); + EXPECT_FALSE(tscs->IsContentBlocked(ContentSettingsType::COOKIES)); + EXPECT_FALSE(tscs->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); } void SetExpectedEffectiveConnectionType(
diff --git a/chrome/browser/content_settings/content_settings_browsertest.cc b/chrome/browser/content_settings/content_settings_browsertest.cc index 3b9c651..47b4ecb 100644 --- a/chrome/browser/content_settings/content_settings_browsertest.cc +++ b/chrome/browser/content_settings/content_settings_browsertest.cc
@@ -75,16 +75,16 @@ browsing_data::CannedCookieHelper* GetSiteSettingsCookieContainer( Browser* browser) { TabSpecificContentSettings* settings = - TabSpecificContentSettings::FromWebContents( - browser->tab_strip_model()->GetActiveWebContents()); + TabSpecificContentSettings::GetForFrame( + browser->tab_strip_model()->GetActiveWebContents()->GetMainFrame()); return settings->allowed_local_shared_objects().cookies(); } browsing_data::CannedCookieHelper* GetSiteSettingsBlockedCookieContainer( Browser* browser) { TabSpecificContentSettings* settings = - TabSpecificContentSettings::FromWebContents( - browser->tab_strip_model()->GetActiveWebContents()); + TabSpecificContentSettings::GetForFrame( + browser->tab_strip_model()->GetActiveWebContents()->GetMainFrame()); return settings->blocked_local_shared_objects().cookies(); } @@ -730,8 +730,9 @@ ASSERT_TRUE(::testing::Mock::VerifyAndClearExpectations(&observer)); - EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::COOKIES)); + EXPECT_TRUE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::COOKIES)); } // Any cookie access during a navigation does not end up in a new document (e.g. @@ -751,8 +752,9 @@ ui_test_utils::NavigateToURL(browser(), test_url); - EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::COOKIES)); + EXPECT_FALSE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::COOKIES)); } class ContentSettingsBackForwardCacheBrowserTest : public ContentSettingsTest { @@ -789,19 +791,22 @@ browser()->tab_strip_model()->GetActiveWebContents(); content::RenderFrameHost* main_frame = web_contents->GetMainFrame(); - EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::COOKIES)); + EXPECT_TRUE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::COOKIES)); ui_test_utils::NavigateToURL(browser(), other_url); EXPECT_TRUE(main_frame->IsInBackForwardCache()); - EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::COOKIES)); + EXPECT_FALSE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::COOKIES)); web_contents->GetController().GoBack(); EXPECT_TRUE(WaitForLoadStop(web_contents)); EXPECT_EQ(main_frame, web_contents->GetMainFrame()); - EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::COOKIES)); + EXPECT_TRUE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::COOKIES)); } IN_PROC_BROWSER_TEST_F(ContentSettingsBackForwardCacheBrowserTest, @@ -817,12 +822,14 @@ ->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK); ui_test_utils::NavigateToURL(browser(), test_url); - EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::COOKIES)); + EXPECT_TRUE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::COOKIES)); ui_test_utils::NavigateToURL(browser(), other_url); - EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::COOKIES)); + EXPECT_FALSE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::COOKIES)); // This triggers a OnContentSettingChanged notification that should be // processed by the page in the cache. @@ -831,8 +838,9 @@ web_contents->GetController().GoBack(); EXPECT_TRUE(WaitForLoadStop(web_contents)); - EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::COOKIES)); + EXPECT_FALSE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::COOKIES)); } // TODO(jww): This should be removed after strict secure cookies is enabled for @@ -887,8 +895,9 @@ browser()->tab_strip_model()->GetActiveWebContents(); ASSERT_EQ(base::UTF8ToUTF16("Data URL"), web_contents->GetTitle()); - EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); + EXPECT_TRUE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); } // Tests that if redirect across origins occurs, the new process still gets the @@ -912,8 +921,9 @@ content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::COOKIES)); + EXPECT_TRUE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::COOKIES)); } class ContentSettingsWorkerModulesBrowserTest : public ContentSettingsTest { @@ -1051,8 +1061,9 @@ // The import must be blocked. ui_test_utils::WaitForViewVisibility( browser(), VIEW_ID_CONTENT_SETTING_JAVASCRIPT, true); - EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); + EXPECT_TRUE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); } @@ -1200,7 +1211,8 @@ ui_test_utils::NavigateToURL(browser(), url); EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); - auto* tscs = TabSpecificContentSettings::FromWebContents(web_contents); + auto* tscs = + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); EXPECT_EQ(!expect_loaded, tscs && tscs->IsContentBlocked(ContentSettingsType::PLUGINS)); } @@ -1242,7 +1254,7 @@ } TabSpecificContentSettings* tab_settings = - TabSpecificContentSettings::FromWebContents(web_contents); + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); EXPECT_EQ(expect_is_javascript_content_blocked, tab_settings->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); EXPECT_FALSE(tab_settings->IsContentBlocked(ContentSettingsType::PLUGINS));
diff --git a/chrome/browser/content_settings/sound_content_setting_observer.cc b/chrome/browser/content_settings/sound_content_setting_observer.cc index e7db3b9..a8e905b 100644 --- a/chrome/browser/content_settings/sound_content_setting_observer.cc +++ b/chrome/browser/content_settings/sound_content_setting_observer.cc
@@ -158,9 +158,12 @@ void SoundContentSettingObserver::CheckSoundBlocked(bool is_audible) { if (is_audible && GetCurrentContentSetting() == CONTENT_SETTING_BLOCK) { // The tab has tried to play sound, but was muted. + // This is a page level event so it is OK to get the main frame here. + // TODO(https://crbug.com/1103176): We should figure a way of not having to + // use GetMainFrame here. (pass the source frame somehow) content_settings::TabSpecificContentSettings* settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents()); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents()->GetMainFrame()); if (settings) settings->OnAudioBlocked();
diff --git a/chrome/browser/content_settings/tab_specific_content_settings_delegate.cc b/chrome/browser/content_settings/tab_specific_content_settings_delegate.cc index c2f8bcc..b4afc9c 100644 --- a/chrome/browser/content_settings/tab_specific_content_settings_delegate.cc +++ b/chrome/browser/content_settings/tab_specific_content_settings_delegate.cc
@@ -43,12 +43,8 @@ TabSpecificContentSettingsDelegate* TabSpecificContentSettingsDelegate::FromWebContents( content::WebContents* web_contents) { - auto* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents); - if (!content_settings) - return nullptr; return static_cast<TabSpecificContentSettingsDelegate*>( - content_settings->delegate()); + TabSpecificContentSettings::GetDelegateForWebContents(web_contents)); } void TabSpecificContentSettingsDelegate::UpdateLocationBar() {
diff --git a/chrome/browser/engagement/site_engagement_helper.cc b/chrome/browser/engagement/site_engagement_helper.cc index 655294c..68204cbc 100644 --- a/chrome/browser/engagement/site_engagement_helper.cc +++ b/chrome/browser/engagement/site_engagement_helper.cc
@@ -10,6 +10,7 @@ #include "base/stl_util.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/navigation_handle.h" @@ -232,7 +233,8 @@ // // Prerenders trigger WasShown() when they are swapped in, so input engagement // will activate even if navigation engagement is not scored. - if (prerender::PrerenderContents::FromWebContents(web_contents()) != nullptr) + if (prerender::ChromePrerenderContentsDelegate::FromWebContents( + web_contents()) != nullptr) return; service_->HandleNavigation(web_contents(), handle->GetPageTransition());
diff --git a/chrome/browser/extensions/DEPS b/chrome/browser/extensions/DEPS index cb789af..2c31981 100644 --- a/chrome/browser/extensions/DEPS +++ b/chrome/browser/extensions/DEPS
@@ -1,6 +1,6 @@ include_rules = [ "+extensions/strings/grit/extensions_strings.h", - "+services/network", + "+services/network/public", "+third_party/ink/grit", "+ui/base", @@ -23,12 +23,30 @@ "extension_protocols_unittest\.cc": [ "+services/network/test", ], + "extension_gcm_app_handler_unittest\.cc": [ + "+services/network/test", + ], "zipfile_installer_unittest.cc": [ "+services/data_decoder", ], "test_extension_system.cc": [ "+services/data_decoder", ], + "updater/extension_updater_unittest\.cc": [ + "+services/network/test", + ], + + "chrome_extension_cookies\.h": [ + # TODO(crbug.com/1049894): Remove. + "+services/network/cookie_settings.h", + ], + + "chrome_extension_cookies\.cc": [ + # TODO(crbug.com/1049894): Remove. + "+services/network/cookie_manager.h", + "+services/network/restricted_cookie_manager.h", + ], + "webstore_private_apitest.cc" : [ # TODO(crbug/1095814): Remove this layering violation. "+chrome/browser/ui/views/supervised_user/parent_permission_dialog_view.h",
diff --git a/chrome/browser/extensions/api/DEPS b/chrome/browser/extensions/api/DEPS index 5dc13a5..5b31a7ff 100644 --- a/chrome/browser/extensions/api/DEPS +++ b/chrome/browser/extensions/api/DEPS
@@ -5,7 +5,6 @@ # Enable remote assistance on Chrome OS "+remoting/base", "+remoting/host", - "+services/network", ] specific_include_rules = { @@ -13,4 +12,13 @@ "+chrome/browser/ui/views/frame", "+components/captive_portal", ], + "tls_socket_unittest\.cc": [ + "+services/network/network_context.h", + ], + "tcp_socket_unittest\.cc": [ + "+services/network/network_context.h", + ], + "udp_socket_unittest\.cc": [ + "+services/network/network_context.h", + ], }
diff --git a/chrome/browser/extensions/api/streams_private/streams_private_api.cc b/chrome/browser/extensions/api/streams_private/streams_private_api.cc index 70a275c8..4b26fec 100644 --- a/chrome/browser/extensions/api/streams_private/streams_private_api.cc +++ b/chrome/browser/extensions/api/streams_private/streams_private_api.cc
@@ -7,6 +7,7 @@ #include <utility> #include "chrome/browser/extensions/extension_tab_util.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "components/sessions/core/session_id.h" #include "content/public/browser/browser_thread.h" @@ -45,7 +46,7 @@ // continue. This is because plugins cancel prerender, see // http://crbug.com/343590. prerender::PrerenderContents* prerender_contents = - prerender::PrerenderContents::FromWebContents(web_contents); + prerender::ChromePrerenderContentsDelegate::FromWebContents(web_contents); if (prerender_contents) { prerender_contents->Destroy(prerender::FINAL_STATUS_DOWNLOAD); return;
diff --git a/chrome/browser/extensions/forced_extensions/install_stage_tracker.cc b/chrome/browser/extensions/forced_extensions/install_stage_tracker.cc index c50a36c07..437367bc 100644 --- a/chrome/browser/extensions/forced_extensions/install_stage_tracker.cc +++ b/chrome/browser/extensions/forced_extensions/install_stage_tracker.cc
@@ -152,7 +152,9 @@ data.download_CRX_started_time = base::Time::Now(); else if (stage == ExtensionDownloaderDelegate::Stage::FINISHED) data.download_CRX_finish_time = base::Time::Now(); + for (auto& observer : observers_) { + observer.OnExtensionDownloadingStageChanged(id, stage); observer.OnExtensionDataChangedForTesting(id, browser_context_, data); } }
diff --git a/chrome/browser/extensions/forced_extensions/install_stage_tracker.h b/chrome/browser/extensions/forced_extensions/install_stage_tracker.h index 178f8fa..48e5c06 100644 --- a/chrome/browser/extensions/forced_extensions/install_stage_tracker.h +++ b/chrome/browser/extensions/forced_extensions/install_stage_tracker.h
@@ -333,6 +333,11 @@ // Called when installation stage of extension is updated. virtual void OnExtensionInstallationStageChanged(const ExtensionId& id, Stage stage) {} + + // Called when downloading stage of extension is updated. + virtual void OnExtensionDownloadingStageChanged( + const ExtensionId& id, + ExtensionDownloaderDelegate::Stage stage) {} }; explicit InstallStageTracker(const content::BrowserContext* context);
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 21dfb2a..dcef6f4 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -3834,6 +3834,11 @@ "expiry_milestone": 90 }, { + "name": "scroll-to-text-ios", + "owners": [ "tmartino" ], + "expiry_milestone": 90 + }, + { "name": "scroll-unification", "owners": [ "bokan@chromium.org", "input-dev@chromium.org" ], "expiry_milestone": 90
diff --git a/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc index 4d99d806..d09a3a6 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc
@@ -77,8 +77,8 @@ void CheckTabContentsState(const GURL& requesting_frame, ContentSetting expected_content_setting) { content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents()); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents()->GetMainFrame()); const ContentSettingsUsagesState::StateMap& state_map = content_settings->geolocation_usages_state().state_map(); EXPECT_EQ(1U, state_map.count(requesting_frame.GetOrigin()));
diff --git a/chrome/browser/history/history_tab_helper.cc b/chrome/browser/history/history_tab_helper.cc index 94af992..7c936dd 100644 --- a/chrome/browser/history/history_tab_helper.cc +++ b/chrome/browser/history/history_tab_helper.cc
@@ -10,9 +10,6 @@ #include "base/stl_util.h" #include "build/build_config.h" #include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/prerender/prerender_contents.h" -#include "chrome/browser/prerender/prerender_manager.h" -#include "chrome/browser/prerender/prerender_manager_factory.h" #include "chrome/browser/profiles/profile.h" #include "components/history/content/browser/history_context_helper.h" #include "components/history/core/browser/history_constants.h" @@ -146,18 +143,6 @@ web_contents()->GetLastCommittedURL(), last_committed->GetTimestamp(), last_committed->GetUniqueID(), navigation_handle); - prerender::PrerenderManager* prerender_manager = - prerender::PrerenderManagerFactory::GetForBrowserContext( - web_contents()->GetBrowserContext()); - if (prerender_manager) { - prerender::PrerenderContents* prerender_contents = - prerender_manager->GetPrerenderContents(web_contents()); - if (prerender_contents) { - prerender_contents->DidNavigate(add_page_args); - return; - } - } - #if defined(OS_ANDROID) auto* background_tab_manager = BackgroundTabManager::GetInstance(); if (background_tab_manager->IsBackgroundTab(web_contents())) {
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc index 1541e85..2f4db69 100644 --- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc +++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/lookalikes/lookalike_url_controller_client.h" #include "chrome/browser/lookalikes/lookalike_url_service.h" #include "chrome/browser/lookalikes/lookalike_url_tab_storage.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/reputation/safety_tips_config.h" @@ -255,7 +256,8 @@ content::NavigationHandle* navigation_handle) { // If the tab is being prerendered, stop here before it breaks metrics content::WebContents* web_contents = navigation_handle->GetWebContents(); - if (prerender::PrerenderContents::FromWebContents(web_contents)) { + if (prerender::ChromePrerenderContentsDelegate::FromWebContents( + web_contents)) { return nullptr; }
diff --git a/chrome/browser/media/media_engagement_service.cc b/chrome/browser/media/media_engagement_service.cc index 62d8688..bf12369 100644 --- a/chrome/browser/media/media_engagement_service.cc +++ b/chrome/browser/media/media_engagement_service.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/media/media_engagement_contents_observer.h" #include "chrome/browser/media/media_engagement_score.h" #include "chrome/browser/media/media_engagement_service_factory.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" @@ -83,7 +84,7 @@ DCHECK(IsEnabled()); // Ignore WebContents that are used for prerender/prefetch. - if (prerender::PrerenderContents::FromWebContents(web_contents)) + if (prerender::ChromePrerenderContentsDelegate::FromWebContents(web_contents)) return; MediaEngagementService* service =
diff --git a/chrome/browser/media/webrtc/media_stream_capture_indicator_unittest.cc b/chrome/browser/media/webrtc/media_stream_capture_indicator_unittest.cc index a359972..9105781a 100644 --- a/chrome/browser/media/webrtc/media_stream_capture_indicator_unittest.cc +++ b/chrome/browser/media/webrtc/media_stream_capture_indicator_unittest.cc
@@ -10,7 +10,7 @@ #include "content/public/test/web_contents_tester.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/common/tokens/portal_token.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h" namespace {
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc index 24c7ed42..3914c71 100644 --- a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc +++ b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc
@@ -68,7 +68,8 @@ const GURL& example_url() const { return example_url_; } TabSpecificContentSettings* GetContentSettings() { - return TabSpecificContentSettings::FromWebContents(GetWebContents()); + return TabSpecificContentSettings::GetForFrame( + GetWebContents()->GetMainFrame()); } const std::string& example_audio_id() const { return example_audio_id_; }
diff --git a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc index 9f2f4cf1..883e426 100644 --- a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc +++ b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
@@ -67,9 +67,10 @@ if (!web_contents) return; + // TODO(https://crbug.com/1103176): We should extract the frame from |request| auto* content_settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()); if (!content_settings) return;
diff --git a/chrome/browser/nearby_sharing/BUILD.gn b/chrome/browser/nearby_sharing/BUILD.gn new file mode 100644 index 0000000..2dc5a81 --- /dev/null +++ b/chrome/browser/nearby_sharing/BUILD.gn
@@ -0,0 +1,22 @@ +# Copyright 2020 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. + +source_set("share_target") { + sources = [ + "attachment.h", + "file_attachment.cc", + "file_attachment.h", + "share_target.cc", + "share_target.h", + "text_attachment.cc", + "text_attachment.h", + ] + + deps = [ + "//base", + "//chrome/browser/ui/webui/nearby_share:nearby_share_target_types", + "//chrome/services/sharing/public/mojom", + "//url", + ] +}
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc index 2d63936..5a6a24af 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc
@@ -176,7 +176,35 @@ } NearbySharePrivateCertificate::NearbySharePrivateCertificate( - NearbySharePrivateCertificate&&) = default; + const NearbySharePrivateCertificate& other) { + *this = other; +} + +NearbySharePrivateCertificate& NearbySharePrivateCertificate::operator=( + const NearbySharePrivateCertificate& other) { + if (this == &other) + return *this; + + visibility_ = other.visibility_; + not_before_ = other.not_before_; + not_after_ = other.not_after_; + key_pair_ = other.key_pair_->Copy(); + secret_key_ = crypto::SymmetricKey::Import( + crypto::SymmetricKey::Algorithm::AES, other.secret_key_->key()); + metadata_encryption_key_ = other.metadata_encryption_key_; + id_ = other.id_; + unencrypted_metadata_ = other.unencrypted_metadata_; + consumed_salts_ = other.consumed_salts_; + next_salts_for_testing_ = other.next_salts_for_testing_; + offset_for_testing_ = other.offset_for_testing_; + return *this; +} + +NearbySharePrivateCertificate::NearbySharePrivateCertificate( + NearbySharePrivateCertificate&& other) = default; + +NearbySharePrivateCertificate& NearbySharePrivateCertificate::operator=( + NearbySharePrivateCertificate&& other) = default; NearbySharePrivateCertificate::~NearbySharePrivateCertificate() = default;
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.h b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.h index f9e8a85e..85d5d62 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.h +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.h
@@ -58,7 +58,12 @@ nearbyshare::proto::EncryptedMetadata unencrypted_metadata, std::set<std::vector<uint8_t>> consumed_salts); - NearbySharePrivateCertificate(NearbySharePrivateCertificate&&); + NearbySharePrivateCertificate(const NearbySharePrivateCertificate& other); + NearbySharePrivateCertificate& operator=( + const NearbySharePrivateCertificate& other); + NearbySharePrivateCertificate(NearbySharePrivateCertificate&& other); + NearbySharePrivateCertificate& operator=( + NearbySharePrivateCertificate&& other); virtual ~NearbySharePrivateCertificate();
diff --git a/chrome/browser/nearby_sharing/fake_nearby_connection.cc b/chrome/browser/nearby_sharing/fake_nearby_connection.cc new file mode 100644 index 0000000..93a07d3 --- /dev/null +++ b/chrome/browser/nearby_sharing/fake_nearby_connection.cc
@@ -0,0 +1,46 @@ +// Copyright 2020 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/nearby_sharing/fake_nearby_connection.h" + +FakeNearbyConnection::FakeNearbyConnection() = default; +FakeNearbyConnection::~FakeNearbyConnection() = default; + +void FakeNearbyConnection::Read(ReadCallback callback) { + callback_ = std::move(callback); + MaybeRunCallback(); +} + +void FakeNearbyConnection::Write(std::vector<uint8_t> bytes, + WriteCallback callback) { + NOTIMPLEMENTED(); +} + +void FakeNearbyConnection::Close() { + closed_ = true; + if (callback_) + std::move(callback_).Run(base::nullopt); +} + +bool FakeNearbyConnection::IsClosed() const { + return closed_; +} + +void FakeNearbyConnection::RegisterForDisconnection( + base::OnceClosure callback) { + NOTIMPLEMENTED(); +} + +void FakeNearbyConnection::AppendReadableData(std::vector<uint8_t> bytes) { + data_.push(std::move(bytes)); + MaybeRunCallback(); +} + +void FakeNearbyConnection::MaybeRunCallback() { + if (!callback_ || data_.empty()) + return; + auto item = std::move(data_.front()); + data_.pop(); + std::move(callback_).Run(std::move(item)); +}
diff --git a/chrome/browser/nearby_sharing/fake_nearby_connection.h b/chrome/browser/nearby_sharing/fake_nearby_connection.h new file mode 100644 index 0000000..9c3f188 --- /dev/null +++ b/chrome/browser/nearby_sharing/fake_nearby_connection.h
@@ -0,0 +1,33 @@ +// Copyright 2020 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_NEARBY_SHARING_FAKE_NEARBY_CONNECTION_H_ +#define CHROME_BROWSER_NEARBY_SHARING_FAKE_NEARBY_CONNECTION_H_ + +#include <queue> +#include <vector> + +#include "chrome/browser/nearby_sharing/nearby_connection.h" + +class FakeNearbyConnection : public NearbyConnection { + public: + FakeNearbyConnection(); + ~FakeNearbyConnection() override; + + void Read(ReadCallback callback) override; + void Write(std::vector<uint8_t> bytes, WriteCallback callback) override; + void Close() override; + bool IsClosed() const override; + void RegisterForDisconnection(base::OnceClosure callback) override; + void AppendReadableData(std::vector<uint8_t> bytes); + + private: + void MaybeRunCallback(); + + bool closed_ = false; + ReadCallback callback_; + std::queue<std::vector<uint8_t>> data_; +}; + +#endif // CHROME_BROWSER_NEARBY_SHARING_FAKE_NEARBY_CONNECTION_H_
diff --git a/chrome/browser/nearby_sharing/file_attachment.h b/chrome/browser/nearby_sharing/file_attachment.h index 65ed319..19590c7 100644 --- a/chrome/browser/nearby_sharing/file_attachment.h +++ b/chrome/browser/nearby_sharing/file_attachment.h
@@ -10,23 +10,13 @@ #include "base/files/file_path.h" #include "base/optional.h" #include "chrome/browser/nearby_sharing/attachment.h" +#include "chrome/services/sharing/public/mojom/nearby_decoder_types.mojom.h" // A single attachment to be sent by / received from a |ShareTarget|, can be // either a file or text. class FileAttachment : public Attachment { public: - // Different types are used to offer richer experiences on Receiver side, - // mainly for: 1. displaying notification of attachment types, 2. opening - // different types with different apps. Remember to update Notifications, - // ShareTarget, etc once more types are introduced here. - enum class Type { - kUnknown, - kImage, - kVideo, - kApp, - kAudio, - kMaxValue = kAudio - }; + using Type = sharing::mojom::FileMetadata::Type; FileAttachment(std::string file_name, Type type,
diff --git a/chrome/browser/nearby_sharing/incoming_frames_reader_unittest.cc b/chrome/browser/nearby_sharing/incoming_frames_reader_unittest.cc index 5c0ca3a0..0a03a1a 100644 --- a/chrome/browser/nearby_sharing/incoming_frames_reader_unittest.cc +++ b/chrome/browser/nearby_sharing/incoming_frames_reader_unittest.cc
@@ -4,15 +4,14 @@ #include "chrome/browser/nearby_sharing/incoming_frames_reader.h" -#include <queue> #include <vector> #include "base/run_loop.h" #include "base/test/bind_test_util.h" #include "base/time/time.h" +#include "chrome/browser/nearby_sharing/fake_nearby_connection.h" #include "chrome/browser/nearby_sharing/mock_nearby_process_manager.h" #include "chrome/browser/nearby_sharing/mock_nearby_sharing_decoder.h" -#include "chrome/browser/nearby_sharing/nearby_connection.h" #include "chrome/services/sharing/public/proto/wire_format.pb.h" #include "chrome/test/base/testing_profile.h" #include "content/public/test/browser_task_environment.h" @@ -56,51 +55,6 @@ } // namespace -class FakeNearbyConnection : public NearbyConnection { - public: - FakeNearbyConnection() = default; - ~FakeNearbyConnection() override = default; - - void Read(ReadCallback callback) override { - callback_ = std::move(callback); - MaybeRunCallback(); - } - - void Write(std::vector<uint8_t> bytes, WriteCallback callback) override { - NOTIMPLEMENTED(); - } - - void Close() override { - closed_ = true; - if (callback_) - std::move(callback_).Run(base::nullopt); - } - - bool IsClosed() const override { return closed_; } - - void RegisterForDisconnection(base::OnceClosure callback) override { - NOTIMPLEMENTED(); - } - - void AppendReadableData(std::vector<uint8_t> bytes) { - data_.push(std::move(bytes)); - MaybeRunCallback(); - } - - private: - void MaybeRunCallback() { - if (!callback_ || data_.empty()) - return; - auto item = std::move(data_.front()); - data_.pop(); - std::move(callback_).Run(std::move(item)); - } - - bool closed_ = false; - ReadCallback callback_; - std::queue<std::vector<uint8_t>> data_; -}; - class IncomingFramesReaderTest : public testing::Test { public: IncomingFramesReaderTest()
diff --git a/chrome/browser/nearby_sharing/nearby_notification_manager.cc b/chrome/browser/nearby_sharing/nearby_notification_manager.cc index db2c504..baca16e 100644 --- a/chrome/browser/nearby_sharing/nearby_notification_manager.cc +++ b/chrome/browser/nearby_sharing/nearby_notification_manager.cc
@@ -4,11 +4,11 @@ #include "chrome/browser/nearby_sharing/nearby_notification_manager.h" +#include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/nearby_sharing/nearby_sharing_service.h" #include "chrome/browser/notifications/notification_display_service.h" -#include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/browser_thread.h" #include "ui/base/l10n/l10n_util.h" @@ -119,16 +119,44 @@ return l10n_util::GetStringFUTF16(resource_id, attachments, device_name); } +base::string16 GetSuccessNotificationTitle(const ShareTarget& share_target) { + int resource_id = share_target.is_incoming + ? IDS_NEARBY_NOTIFICATION_RECEIVE_SUCCESS_TITLE + : IDS_NEARBY_NOTIFICATION_SEND_SUCCESS_TITLE; + base::string16 attachments = GetAttachmentsString(share_target); + base::string16 device_name = base::ASCIIToUTF16(share_target.device_name); + + return l10n_util::GetStringFUTF16(resource_id, attachments, device_name); +} + +base::string16 GetFailureNotificationTitle(const ShareTarget& share_target) { + int resource_id = share_target.is_incoming + ? IDS_NEARBY_NOTIFICATION_RECEIVE_FAILURE_TITLE + : IDS_NEARBY_NOTIFICATION_SEND_FAILURE_TITLE; + base::string16 attachments = GetAttachmentsString(share_target); + base::string16 device_name = base::ASCIIToUTF16(share_target.device_name); + + return l10n_util::GetStringFUTF16(resource_id, attachments, device_name); +} + base::string16 GetConnectionRequestNotificationMessage( const ShareTarget& share_target, const TransferMetadata& transfer_metadata) { base::string16 attachments = GetAttachmentsString(share_target); base::string16 device_name = base::ASCIIToUTF16(share_target.device_name); - // TODO(crbug.com/1102348): Show |transfer_metadata.token()| if present. - return l10n_util::GetStringFUTF16( + base::string16 message = l10n_util::GetStringFUTF16( IDS_NEARBY_NOTIFICATION_CONNECTION_REQUEST_MESSAGE, device_name, attachments); + + if (transfer_metadata.token()) { + base::string16 token = l10n_util::GetStringFUTF16( + IDS_NEARBY_SECURE_CONNECTION_ID, + base::UTF8ToUTF16(*transfer_metadata.token())); + message = base::StrCat({message, base::UTF8ToUTF16("\n"), token}); + } + + return message; } gfx::Image GetImageFromShareTarget(const ShareTarget& share_target) { @@ -139,10 +167,11 @@ } // namespace NearbyNotificationManager::NearbyNotificationManager( - Profile* profile, + NotificationDisplayService* notification_display_service, NearbySharingService* nearby_service) - : profile_(profile), nearby_service_(nearby_service) { - DCHECK(profile_); + : notification_display_service_(notification_display_service), + nearby_service_(nearby_service) { + DCHECK(notification_display_service_); DCHECK(nearby_service_); nearby_service_->RegisterReceiveSurface( this, NearbySharingService::ReceiveSurfaceState::kBackground); @@ -220,7 +249,7 @@ notification_actions.emplace_back(l10n_util::GetStringUTF16(IDS_APP_CANCEL)); notification.set_buttons(notification_actions); - NotificationDisplayServiceFactory::GetForProfile(profile_)->Display( + notification_display_service_->Display( NotificationHandler::Type::NEARBY_SHARE, notification, /*metadata=*/nullptr); } @@ -249,7 +278,7 @@ l10n_util::GetStringUTF16(IDS_NEARBY_NOTIFICATION_DECLINE_ACTION)); notification.set_buttons(notification_actions); - NotificationDisplayServiceFactory::GetForProfile(profile_)->Display( + notification_display_service_->Display( NotificationHandler::Type::NEARBY_SHARE, notification, /*metadata=*/nullptr); } @@ -264,20 +293,38 @@ notification.set_message( l10n_util::GetStringUTF16(IDS_NEARBY_NOTIFICATION_ONBOARDING_MESSAGE)); - NotificationDisplayServiceFactory::GetForProfile(profile_)->Display( + notification_display_service_->Display( NotificationHandler::Type::NEARBY_SHARE, notification, /*metadata=*/nullptr); } void NearbyNotificationManager::ShowSuccess(const ShareTarget& share_target) { - // TODO(crbug.com/1102348): Show success notification. + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + message_center::Notification notification = + CreateNearbyNotification(kNearbyNotificationId); + notification.set_title(GetSuccessNotificationTitle(share_target)); + + // TODO(crbug.com/1102348): Show content specific actions and preview images. + + notification_display_service_->Display( + NotificationHandler::Type::NEARBY_SHARE, notification, + /*metadata=*/nullptr); } void NearbyNotificationManager::ShowFailure(const ShareTarget& share_target) { - // TODO(crbug.com/1102348): Show failure notification. + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + message_center::Notification notification = + CreateNearbyNotification(kNearbyNotificationId); + notification.set_title(GetFailureNotificationTitle(share_target)); + + notification_display_service_->Display( + NotificationHandler::Type::NEARBY_SHARE, notification, + /*metadata=*/nullptr); } void NearbyNotificationManager::CloseTransfer() { - NotificationDisplayServiceFactory::GetForProfile(profile_)->Close( - NotificationHandler::Type::NEARBY_SHARE, kNearbyNotificationId); + notification_display_service_->Close(NotificationHandler::Type::NEARBY_SHARE, + kNearbyNotificationId); }
diff --git a/chrome/browser/nearby_sharing/nearby_notification_manager.h b/chrome/browser/nearby_sharing/nearby_notification_manager.h index b9e7096d..adad78e 100644 --- a/chrome/browser/nearby_sharing/nearby_notification_manager.h +++ b/chrome/browser/nearby_sharing/nearby_notification_manager.h
@@ -13,8 +13,8 @@ #include "chrome/browser/nearby_sharing/transfer_metadata.h" #include "chrome/browser/nearby_sharing/transfer_update_callback.h" -class Profile; class NearbySharingService; +class NotificationDisplayService; // Manages notifications shown for Nearby Share. Only a single notification will // be shown as simultaneous connections are not supported. All methods should be @@ -22,8 +22,9 @@ class NearbyNotificationManager : public TransferUpdateCallback, public ShareTargetDiscoveredCallback { public: - NearbyNotificationManager(Profile* profile, - NearbySharingService* nearby_service); + NearbyNotificationManager( + NotificationDisplayService* notification_display_service, + NearbySharingService* nearby_service); ~NearbyNotificationManager() override; // TransferUpdateCallback: @@ -61,7 +62,7 @@ void CloseTransfer(); private: - Profile* profile_; + NotificationDisplayService* notification_display_service_; NearbySharingService* nearby_service_; };
diff --git a/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc b/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc index a8f239c6..9011732 100644 --- a/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include <vector> +#include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" #include "chrome/app/vector_icons/vector_icons.h" @@ -15,6 +16,7 @@ #include "chrome/browser/nearby_sharing/share_target.h" #include "chrome/browser/nearby_sharing/transfer_metadata.h" #include "chrome/browser/nearby_sharing/transfer_metadata_builder.h" +#include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/grit/generated_resources.h" #include "chrome/test/base/testing_profile.h" @@ -43,8 +45,7 @@ scoped_feature_list_.InitAndEnableFeature(features::kNearbySharing); notification_tester_ = std::make_unique<NotificationDisplayServiceTester>(&profile_); - manager_ = std::make_unique<NearbyNotificationManager>(&profile_, - &nearby_service_); + manager_ = CreateManager(); } ~NearbyNotificationManagerTest() override = default; @@ -55,6 +56,13 @@ NotificationHandler::Type::NEARBY_SHARE); } + std::unique_ptr<NearbyNotificationManager> CreateManager() { + NotificationDisplayService* notification_display_service = + NotificationDisplayServiceFactory::GetForProfile(&profile_); + return std::make_unique<NearbyNotificationManager>( + notification_display_service, &nearby_service_); + } + protected: base::test::ScopedFeatureList scoped_feature_list_; content::BrowserTaskEnvironment task_environment_; @@ -64,13 +72,13 @@ std::unique_ptr<NearbyNotificationManager> manager_; }; -struct ProgressNotificationTestParamInternal { +struct AttachmentsTestParamInternal { std::vector<TextAttachment::Type> text_attachments; std::vector<FileAttachment::Type> file_attachments; int expected_resource_id; }; -ProgressNotificationTestParamInternal kProgressNotificationTestParams[] = { +AttachmentsTestParamInternal kAttachmentsTestParams[] = { // No attachments. {{}, {}, IDS_NEARBY_UNKNOWN_ATTACHMENTS}, @@ -108,16 +116,17 @@ IDS_NEARBY_FILE_ATTACHMENTS_UNKNOWN}, }; -using ProgressNotificationTestParam = - std::tuple<ProgressNotificationTestParamInternal, bool>; +using AttachmentsTestParam = std::tuple<AttachmentsTestParamInternal, bool>; -class NearbyNotificationManagerProgressNotificationTest +class NearbyNotificationManagerAttachmentsTest : public NearbyNotificationManagerTest, - public testing::WithParamInterface<ProgressNotificationTestParam> {}; + public testing::WithParamInterface<AttachmentsTestParam> {}; + +using ConnectionRequestTestParam = std::tuple<TransferMetadata::Status, bool>; class NearbyNotificationManagerConnectionRequestTest : public NearbyNotificationManagerTest, - public testing::WithParamInterface<TransferMetadata::Status> {}; + public testing::WithParamInterface<ConnectionRequestTestParam> {}; } // namespace @@ -142,8 +151,7 @@ testing::SaveArg<0>(&send_transfer_callback), testing::SaveArg<1>(&send_discovery_callback), testing::Return(NearbySharingService::StatusCodes::kOk))); - manager_ = - std::make_unique<NearbyNotificationManager>(&profile_, &nearby_service_); + manager_ = CreateManager(); EXPECT_EQ(manager(), receive_transfer_callback); EXPECT_EQ(manager(), send_transfer_callback); @@ -221,8 +229,8 @@ EXPECT_EQ(100.0 * progress, notification.progress()); } -TEST_P(NearbyNotificationManagerProgressNotificationTest, Test) { - const ProgressNotificationTestParamInternal& param = std::get<0>(GetParam()); +TEST_P(NearbyNotificationManagerAttachmentsTest, ShowProgress) { + const AttachmentsTestParamInternal& param = std::get<0>(GetParam()); bool is_incoming = std::get<1>(GetParam()); std::string device_name = "device"; @@ -256,21 +264,98 @@ EXPECT_EQ(expected, notification.title()); } +TEST_P(NearbyNotificationManagerAttachmentsTest, ShowSuccess) { + const AttachmentsTestParamInternal& param = std::get<0>(GetParam()); + bool is_incoming = std::get<1>(GetParam()); + + std::string device_name = "device"; + ShareTarget share_target; + share_target.device_name = device_name; + share_target.is_incoming = is_incoming; + + for (TextAttachment::Type type : param.text_attachments) + share_target.text_attachments.push_back(CreateTextAttachment(type)); + + for (FileAttachment::Type type : param.file_attachments) + share_target.file_attachments.push_back(CreateFileAttachment(type)); + + manager()->ShowSuccess(share_target); + + int expected_resource_id = is_incoming + ? IDS_NEARBY_NOTIFICATION_RECEIVE_SUCCESS_TITLE + : IDS_NEARBY_NOTIFICATION_SEND_SUCCESS_TITLE; + size_t total = param.text_attachments.size() + param.file_attachments.size(); + base::string16 expected = l10n_util::GetStringFUTF16( + expected_resource_id, + l10n_util::GetPluralStringFUTF16(param.expected_resource_id, total), + base::ASCIIToUTF16(device_name)); + + std::vector<message_center::Notification> notifications = + GetDisplayedNotifications(); + ASSERT_EQ(1u, notifications.size()); + + const message_center::Notification& notification = notifications[0]; + EXPECT_EQ(expected, notification.title()); +} + +TEST_P(NearbyNotificationManagerAttachmentsTest, ShowFailure) { + const AttachmentsTestParamInternal& param = std::get<0>(GetParam()); + bool is_incoming = std::get<1>(GetParam()); + + std::string device_name = "device"; + ShareTarget share_target; + share_target.device_name = device_name; + share_target.is_incoming = is_incoming; + + for (TextAttachment::Type type : param.text_attachments) + share_target.text_attachments.push_back(CreateTextAttachment(type)); + + for (FileAttachment::Type type : param.file_attachments) + share_target.file_attachments.push_back(CreateFileAttachment(type)); + + manager()->ShowFailure(share_target); + + int expected_resource_id = is_incoming + ? IDS_NEARBY_NOTIFICATION_RECEIVE_FAILURE_TITLE + : IDS_NEARBY_NOTIFICATION_SEND_FAILURE_TITLE; + size_t total = param.text_attachments.size() + param.file_attachments.size(); + base::string16 expected = l10n_util::GetStringFUTF16( + expected_resource_id, + l10n_util::GetPluralStringFUTF16(param.expected_resource_id, total), + base::ASCIIToUTF16(device_name)); + + std::vector<message_center::Notification> notifications = + GetDisplayedNotifications(); + ASSERT_EQ(1u, notifications.size()); + + const message_center::Notification& notification = notifications[0]; + EXPECT_EQ(expected, notification.title()); +} + INSTANTIATE_TEST_SUITE_P( - NearbyNotificationManagerProgressNotificationTest, - NearbyNotificationManagerProgressNotificationTest, - testing::Combine(testing::ValuesIn(kProgressNotificationTestParams), + NearbyNotificationManagerAttachmentsTest, + NearbyNotificationManagerAttachmentsTest, + testing::Combine(testing::ValuesIn(kAttachmentsTestParams), testing::Bool())); TEST_P(NearbyNotificationManagerConnectionRequestTest, ShowConnectionRequest_ShowsNotification) { + TransferMetadata::Status status = std::get<0>(GetParam()); + bool with_token = std::get<1>(GetParam()); + std::string device_name = "device"; + std::string token = "3141"; + ShareTarget share_target; share_target.device_name = device_name; share_target.file_attachments.push_back( CreateFileAttachment(FileAttachment::Type::kImage)); - TransferMetadata transfer_metadata = - TransferMetadataBuilder().set_status(GetParam()).build(); + + TransferMetadataBuilder transfer_metadata_builder; + transfer_metadata_builder.set_status(status); + if (with_token) + transfer_metadata_builder.set_token(token); + TransferMetadata transfer_metadata = transfer_metadata_builder.build(); manager()->ShowConnectionRequest(share_target, transfer_metadata); @@ -287,7 +372,13 @@ IDS_NEARBY_NOTIFICATION_CONNECTION_REQUEST_MESSAGE, base::ASCIIToUTF16(device_name), l10n_util::GetPluralStringFUTF16(IDS_NEARBY_FILE_ATTACHMENTS_IMAGES, 1)); - // TODO(crbug.com/1102348): Verify |transfer_metadata.token()| if present. + + if (with_token) { + expected_message = base::StrCat( + {expected_message, base::UTF8ToUTF16("\n"), + l10n_util::GetStringFUTF16(IDS_NEARBY_SECURE_CONNECTION_ID, + base::UTF8ToUTF16(token))}); + } EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, notification.type()); EXPECT_EQ(expected_title, notification.title()); @@ -301,7 +392,7 @@ notification.display_source()); std::vector<base::string16> expected_button_titles; - if (GetParam() == TransferMetadata::Status::kAwaitingLocalConfirmation) { + if (status == TransferMetadata::Status::kAwaitingLocalConfirmation) { expected_button_titles.push_back( l10n_util::GetStringUTF16(IDS_NEARBY_NOTIFICATION_RECEIVE_ACTION)); } @@ -319,8 +410,10 @@ INSTANTIATE_TEST_SUITE_P( NearbyNotificationManagerConnectionRequestTest, NearbyNotificationManagerConnectionRequestTest, - testing::Values(TransferMetadata::Status::kAwaitingLocalConfirmation, - TransferMetadata::Status::kAwaitingRemoteAcceptance)); + testing::Combine( + testing::Values(TransferMetadata::Status::kAwaitingLocalConfirmation, + TransferMetadata::Status::kAwaitingRemoteAcceptance), + testing::Bool())); TEST_F(NearbyNotificationManagerTest, ShowOnboarding_ShowsNotification) { manager()->ShowOnboarding(); @@ -348,12 +441,44 @@ TEST_F(NearbyNotificationManagerTest, ShowSuccess_ShowsNotification) { manager()->ShowSuccess(ShareTarget()); - // TODO(crbug.com/1102348): Verify success notification. + + std::vector<message_center::Notification> notifications = + GetDisplayedNotifications(); + ASSERT_EQ(1u, notifications.size()); + + const message_center::Notification& notification = notifications[0]; + EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, notification.type()); + + EXPECT_EQ(base::string16(), notification.message()); + EXPECT_TRUE(notification.icon().IsEmpty()); + EXPECT_EQ(GURL(), notification.origin_url()); + EXPECT_FALSE(notification.never_timeout()); + EXPECT_FALSE(notification.renotify()); + EXPECT_EQ(&kNearbyShareIcon, ¬ification.vector_small_image()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_NEARBY_NOTIFICATION_SOURCE), + notification.display_source()); + EXPECT_EQ(0u, notification.buttons().size()); } TEST_F(NearbyNotificationManagerTest, ShowFailure_ShowsNotification) { manager()->ShowFailure(ShareTarget()); - // TODO(crbug.com/1102348): Verify failure notification. + + std::vector<message_center::Notification> notifications = + GetDisplayedNotifications(); + ASSERT_EQ(1u, notifications.size()); + + const message_center::Notification& notification = notifications[0]; + EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, notification.type()); + + EXPECT_EQ(base::string16(), notification.message()); + EXPECT_TRUE(notification.icon().IsEmpty()); + EXPECT_EQ(GURL(), notification.origin_url()); + EXPECT_FALSE(notification.never_timeout()); + EXPECT_FALSE(notification.renotify()); + EXPECT_EQ(&kNearbyShareIcon, ¬ification.vector_small_image()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_NEARBY_NOTIFICATION_SOURCE), + notification.display_source()); + EXPECT_EQ(0u, notification.buttons().size()); } TEST_F(NearbyNotificationManagerTest,
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_factory.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_factory.cc index 50830a1027..706d6e7 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_factory.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_factory.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" #include "chrome/browser/nearby_sharing/nearby_process_manager.h" #include "chrome/browser/nearby_sharing/nearby_sharing_service_impl.h" +#include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" @@ -47,6 +48,7 @@ kServiceName, BrowserContextDependencyManager::GetInstance()) { DependsOn(IdentityManagerFactory::GetInstance()); + DependsOn(NotificationDisplayServiceFactory::GetInstance()); } NearbySharingServiceFactory::~NearbySharingServiceFactory() = default; @@ -59,15 +61,18 @@ return nullptr; } + NearbyProcessManager& process_manager = NearbyProcessManager::GetInstance(); Profile* profile = Profile::FromBrowserContext(context); PrefService* pref_service = profile->GetPrefs(); + NotificationDisplayService* notification_display_service = + NotificationDisplayServiceFactory::GetForProfile(profile); auto nearby_connections_manager = - std::make_unique<NearbyConnectionsManagerImpl>( - &NearbyProcessManager::GetInstance(), profile); + std::make_unique<NearbyConnectionsManagerImpl>(&process_manager, profile); NS_LOG(VERBOSE) << __func__ << ": creating NearbySharingService."; - return new NearbySharingServiceImpl(pref_service, profile, - std::move(nearby_connections_manager)); + return new NearbySharingServiceImpl( + pref_service, notification_display_service, profile, + std::move(nearby_connections_manager), &process_manager); } content::BrowserContext* NearbySharingServiceFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc index 5a9dc3a8b..a5006b8 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -17,10 +17,9 @@ #include "chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager_impl.h" #include "chrome/browser/nearby_sharing/logging/logging.h" #include "chrome/browser/nearby_sharing/nearby_connections_manager.h" +#include "chrome/browser/nearby_sharing/transfer_metadata_builder.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" -#include "chrome/browser/nearby_sharing/client/nearby_share_client_impl.h" -#include "chrome/browser/profiles/profile.h" #include "chrome/services/sharing/public/cpp/advertisement.h" #include "chrome/services/sharing/public/mojom/nearby_connections_types.mojom.h" #include "components/prefs/pref_service.h" @@ -31,6 +30,8 @@ namespace { constexpr base::TimeDelta kReadFramesTimeout = base::TimeDelta::FromSeconds(15); +constexpr base::TimeDelta kReadResponseFrameTimeout = + base::TimeDelta::FromSeconds(60); std::string ReceiveSurfaceStateToString( NearbySharingService::ReceiveSurfaceState state) { @@ -123,12 +124,15 @@ NearbySharingServiceImpl::NearbySharingServiceImpl( PrefService* prefs, + NotificationDisplayService* notification_display_service, Profile* profile, - std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager) + std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager, + NearbyProcessManager* process_manager) : prefs_(prefs), profile_(profile), settings_(prefs), nearby_connections_manager_(std::move(nearby_connections_manager)), + process_manager_(process_manager), http_client_factory_(std::make_unique<NearbyShareClientFactoryImpl>( IdentityManagerFactory::GetForProfile(profile), profile->GetURLLoaderFactory(), @@ -144,21 +148,20 @@ DCHECK(profile_); DCHECK(nearby_connections_manager_); - NearbyProcessManager& process_manager = NearbyProcessManager::GetInstance(); - nearby_process_observer_.Add(&process_manager); + nearby_process_observer_.Add(process_manager_); - if (process_manager.IsActiveProfile(profile_)) { + if (process_manager_->IsActiveProfile(profile_)) { // TODO(crbug.com/1084576): Initialize NearbyConnectionsManager with // NearbyConnectionsMojom from |process_manager|: - // process_manager.GetOrStartNearbyConnections(profile_) + // process_manager_->GetOrStartNearbyConnections(profile_) } settings_.AddSettingsObserver(settings_receiver_.BindNewPipeAndPassRemote()); GetBluetoothAdapter(); - nearby_notification_manager_ = - std::make_unique<NearbyNotificationManager>(profile_, this); + nearby_notification_manager_ = std::make_unique<NearbyNotificationManager>( + notification_display_service, this); } NearbySharingServiceImpl::~NearbySharingServiceImpl() { @@ -318,14 +321,12 @@ } void NearbySharingServiceImpl::OnNearbyProcessStarted() { - NearbyProcessManager& process_manager = NearbyProcessManager::GetInstance(); - if (process_manager.IsActiveProfile(profile_)) + if (process_manager_->IsActiveProfile(profile_)) NS_LOG(VERBOSE) << __func__ << ": Nearby process started!"; } void NearbySharingServiceImpl::OnNearbyProcessStopped() { - NearbyProcessManager& process_manager = NearbyProcessManager::GetInstance(); - if (process_manager.IsActiveProfile(profile_)) { + if (process_manager_->IsActiveProfile(profile_)) { // TODO(crbug.com/1084576): Check if process should be running and restart // it after a delay. } @@ -336,7 +337,19 @@ const std::vector<uint8_t>& endpoint_info, NearbyConnection* connection) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(connection); // TODO(crbug/1085068): Handle incoming connection; use CertificateManager + + // TODO(himanshujaju) - Update placeholder implementation + ShareTarget share_target; + share_target.is_incoming = true; + + incoming_share_target_info_map_[share_target.id].set_connection(connection); + connection->RegisterForDisconnection( + base::BindOnce(&NearbySharingServiceImpl::UnregisterShareTarget, + weak_ptr_factory_.GetWeakPtr(), share_target)); + + ReceiveIntroduction(std::move(share_target), /*token=*/base::nullopt); } void NearbySharingServiceImpl::OnEnabledChanged(bool enabled) { @@ -671,12 +684,81 @@ void NearbySharingServiceImpl::OnIncomingTransferUpdate( const ShareTarget& share_target, TransferMetadata metadata) { - // TODO(himanshujaju) - Implement. + if (metadata.status() != TransferMetadata::Status::kCancelled && + metadata.status() != TransferMetadata::Status::kRejected) { + last_incoming_metadata_ = std::make_pair(share_target, metadata); + } else { + last_incoming_metadata_ = base::nullopt; + } + + // TODO(himanshujaju) - Handle is_final_status() + + base::ObserverList<TransferUpdateCallback>& transfer_callbacks = + foreground_receive_callbacks_.might_have_observers() + ? foreground_receive_callbacks_ + : background_receive_callbacks_; + + for (TransferUpdateCallback& callback : transfer_callbacks) { + callback.OnTransferUpdate(share_target, metadata); + } +} + +void NearbySharingServiceImpl::WriteResponse( + NearbyConnection& connection, + sharing::nearby::ConnectionResponseFrame::Status status) { + sharing::nearby::Frame frame; + sharing::nearby::V1Frame* v1_frame = frame.mutable_v1(); + v1_frame->mutable_connection_response()->set_status(status); + + std::vector<uint8_t> data(frame.ByteSize()); + frame.SerializeToArray(data.data(), frame.ByteSize()); + + connection.Write(std::move(data), base::DoNothing()); +} + +void NearbySharingServiceImpl::Fail(const ShareTarget& share_target, + TransferMetadata::Status status) { + NearbyConnection* connection = GetIncomingConnection(share_target); + if (!connection) { + NS_LOG(WARNING) << __func__ << ": Fail invoked for unknown share target."; + return; + } + + // TODO(himanshujaju) - Create alarm and cancel in RegisterForDisconnection(). + + // Send response to remote device. + sharing::nearby::ConnectionResponseFrame::Status response_status; + switch (status) { + case TransferMetadata::Status::kNotEnoughSpace: + response_status = + sharing::nearby::ConnectionResponseFrame::NOT_ENOUGH_SPACE; + break; + + case TransferMetadata::Status::kUnsupportedAttachmentType: + response_status = + sharing::nearby::ConnectionResponseFrame::UNSUPPORTED_ATTACHMENT_TYPE; + break; + + case TransferMetadata::Status::kTimedOut: + response_status = sharing::nearby::ConnectionResponseFrame::TIMED_OUT; + break; + + default: + response_status = sharing::nearby::ConnectionResponseFrame::UNKNOWN; + break; + } + + WriteResponse(*connection, response_status); + + if (incoming_share_target_info_map_.count(share_target.id)) { + OnIncomingTransferUpdate( + share_target, TransferMetadataBuilder().set_status(status).build()); + } } void NearbySharingServiceImpl::ReceiveIntroduction( - const ShareTarget& share_target, - const std::string& token) { + ShareTarget share_target, + base::Optional<std::string> token) { NS_LOG(INFO) << __func__ << ": Receiving introduction from " << share_target.device_name; @@ -689,20 +771,29 @@ } auto frames_reader = std::make_unique<IncomingFramesReader>( - &NearbyProcessManager::GetInstance(), profile_, connection); + process_manager_, profile_, connection); frames_reader->ReadFrame( sharing::mojom::V1Frame::Tag::INTRODUCTION, base::BindOnce(&NearbySharingServiceImpl::OnReceivedIntroduction, - weak_ptr_factory_.GetWeakPtr(), connection, - std::move(frames_reader)), + weak_ptr_factory_.GetWeakPtr(), std::move(share_target), + std::move(token), std::move(frames_reader)), kReadFramesTimeout); } void NearbySharingServiceImpl::OnReceivedIntroduction( - NearbyConnection* connection, + ShareTarget share_target, + base::Optional<std::string> token, std::unique_ptr<IncomingFramesReader> frames_reader, base::Optional<sharing::mojom::V1FramePtr> frame) { + NearbyConnection* connection = GetIncomingConnection(share_target); + if (!connection) { + NS_LOG(WARNING) + << __func__ + << ": Ignore received introduction, due to no connection established."; + return; + } + if (!frame) { connection->Close(); NS_LOG(WARNING) << __func__ << ": Invalid introduction frame"; @@ -710,7 +801,132 @@ } NS_LOG(INFO) << __func__ << ": Successfully read the introduction frame."; - // TODO(himanshujaju) - Implement OnReceiveIntroduction + + sharing::mojom::IntroductionFramePtr introduction_frame = + std::move((*frame)->get_introduction()); + for (const auto& file : introduction_frame->file_metadata) { + if (file->size <= 0) { + Fail(share_target, TransferMetadata::Status::kUnsupportedAttachmentType); + NS_LOG(WARNING) + << __func__ + << ": Ignore introduction, due to invalid attachment size"; + return; + } + + NS_LOG(VERBOSE) << __func__ << "Found file attachment " << file->name + << " of type " << file->type << " with mimeType " + << file->mime_type; + FileAttachment attachment(file->name, file->type, file->size, + /*file_path=*/base::nullopt, file->mime_type); + // TODO(himanshujaju) - setAttachmentPayloadId(); + share_target.file_attachments.push_back(std::move(attachment)); + } + + for (const auto& text : introduction_frame->text_metadata) { + if (text->size <= 0) { + Fail(share_target, TransferMetadata::Status::kUnsupportedAttachmentType); + NS_LOG(WARNING) + << __func__ + << ": Ignore introduction, due to invalid attachment size"; + return; + } + + NS_LOG(VERBOSE) << __func__ << "Found text attachment " << text->text_title + << " of type " << text->type; + TextAttachment attachment(text->text_title, text->type, text->size); + // TODO(himanshujaju) - setAttachmentPayloadId(); + share_target.text_attachments.push_back(std::move(attachment)); + } + + if (!share_target.has_attachments()) { + NS_LOG(WARNING) << __func__ + << ": No attachment is found for this share target. It can " + "be result of unrecognizable attachment type"; + Fail(share_target, TransferMetadata::Status::kUnsupportedAttachmentType); + + NS_LOG(VERBOSE) << __func__ + << ": We don't support the attachments sent by the sender. " + "We have informed " + << share_target.device_name; + return; + } + + if (IsOutOfStorage(share_target)) { + Fail(share_target, TransferMetadata::Status::kNotEnoughSpace); + NS_LOG(WARNING) << __func__ + << ": Not enough space on the receiver. We have informed " + << share_target.device_name; + return; + } + + mutual_acceptance_timeout_alarm_.Reset(base::BindOnce( + &NearbySharingServiceImpl::OnIncomingMutualAcceptanceTimeout, + weak_ptr_factory_.GetWeakPtr(), share_target)); + + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::BindOnce(mutual_acceptance_timeout_alarm_.callback()), + kReadResponseFrameTimeout); + + OnIncomingTransferUpdate( + share_target, + TransferMetadataBuilder() + .set_status(TransferMetadata::Status::kAwaitingLocalConfirmation) + .build()); + + if (!incoming_share_target_info_map_.count(share_target.id)) { + connection->Close(); + NS_LOG(VERBOSE) << __func__ + << ": IncomingShareTarget not found, disconnecting " + << share_target.device_name; + return; + } + + connection->RegisterForDisconnection(base::BindOnce( + &NearbySharingServiceImpl::OnIncomingConnectionDisconnected, + weak_ptr_factory_.GetWeakPtr(), share_target)); + + // TODO(himanshujaju) - start reader thread. +} + +void NearbySharingServiceImpl::OnIncomingConnectionDisconnected( + const ShareTarget& share_target) { + OnIncomingTransferUpdate(share_target, + TransferMetadataBuilder() + .set_status(TransferMetadata::Status::kFailed) + .build()); + UnregisterShareTarget(share_target); +} + +void NearbySharingServiceImpl::UnregisterShareTarget( + const ShareTarget& share_target) { + if (share_target.is_incoming) { + incoming_share_target_info_map_.erase(share_target.id); + nearby_connections_manager_->ClearIncomingPayloads(); + } else { + // TODO(crbug.com/1084644) - Clear from outgoing map. + } + mutual_acceptance_timeout_alarm_.Cancel(); +} + +bool NearbySharingServiceImpl::IsOutOfStorage(const ShareTarget& share_target) { + // TODO(himanshujaju) - Check storage space based on file path. + return false; +} + +void NearbySharingServiceImpl::OnIncomingMutualAcceptanceTimeout( + const ShareTarget& share_target) { + DCHECK(share_target.is_incoming); + + NS_LOG(VERBOSE) + << __func__ + << ": Incoming mutual acceptance timed out, closing connection for " + << share_target.device_name; + + OnIncomingTransferUpdate(share_target, + TransferMetadataBuilder() + .set_status(TransferMetadata::Status::kTimedOut) + .build()); + Fail(share_target, TransferMetadata::Status::kTimedOut); } IncomingShareTargetInfo& NearbySharingServiceImpl::GetIncomingShareTargetInfo( @@ -724,7 +940,7 @@ } OutgoingShareTargetInfo& NearbySharingServiceImpl::GetOutgoingShareTargetInfo( - ShareTarget share_target) { + const ShareTarget& share_target) { return outgoing_share_target_info_map_[share_target.id]; }
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h index a621e2a..b1abe04 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
@@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "base/cancelable_callback.h" #include "base/containers/flat_map.h" #include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" @@ -27,8 +28,10 @@ #include "chrome/browser/nearby_sharing/nearby_sharing_service.h" #include "chrome/browser/nearby_sharing/outgoing_share_target_info.h" #include "chrome/browser/nearby_sharing/share_target.h" +#include "chrome/browser/nearby_sharing/transfer_metadata.h" #include "chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom.h" #include "chrome/services/sharing/public/mojom/nearby_decoder_types.mojom.h" +#include "chrome/services/sharing/public/proto/wire_format.pb.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" @@ -38,6 +41,7 @@ class NearbyShareCertificateManager; class NearbyShareClientFactory; class NearbyShareLocalDeviceDataManager; +class NotificationDisplayService; class PrefService; class Profile; @@ -52,8 +56,10 @@ public: explicit NearbySharingServiceImpl( PrefService* prefs, + NotificationDisplayService* notification_display_service, Profile* profile, - std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager); + std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager, + NearbyProcessManager* process_manager); ~NearbySharingServiceImpl() override; // NearbySharingService: @@ -127,25 +133,37 @@ void InvalidateReceiveSurfaceState(); void InvalidateAdvertisingState(); void StopAdvertising(); + void WriteResponse( + NearbyConnection& connection, + sharing::nearby::ConnectionResponseFrame::Status reponse_status); + void Fail(const ShareTarget& share_target, TransferMetadata::Status status); void OnIncomingTransferUpdate(const ShareTarget& share_target, TransferMetadata metadata); - void ReceiveIntroduction(const ShareTarget& share_target, - const std::string& token); + void ReceiveIntroduction(ShareTarget share_target, + base::Optional<std::string> token); void OnReceivedIntroduction( - NearbyConnection* connection, + ShareTarget share_target, + base::Optional<std::string> token, std::unique_ptr<IncomingFramesReader> frames_reader, base::Optional<sharing::mojom::V1FramePtr> frame); + void OnIncomingConnectionDisconnected(const ShareTarget& share_target); + void UnregisterShareTarget(const ShareTarget& share_target); + bool IsOutOfStorage(const ShareTarget& share_target); + + void OnIncomingMutualAcceptanceTimeout(const ShareTarget& share_target); IncomingShareTargetInfo& GetIncomingShareTargetInfo( const ShareTarget& share_target); NearbyConnection* GetIncomingConnection(const ShareTarget& share_target); - OutgoingShareTargetInfo& GetOutgoingShareTargetInfo(ShareTarget share_target); + OutgoingShareTargetInfo& GetOutgoingShareTargetInfo( + const ShareTarget& share_target); void ClearOutgoingShareTargetInfoMap(); PrefService* prefs_; Profile* profile_; NearbyShareSettings settings_; std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager_; + NearbyProcessManager* process_manager_; ScopedObserver<NearbyProcessManager, NearbyProcessManager::Observer> nearby_process_observer_{this}; scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_; @@ -181,6 +199,10 @@ base::flat_map<base::UnguessableToken, OutgoingShareTargetInfo> outgoing_share_target_info_map_; + // This alarm is used to disconnect the sharing connection if both sides do + // not press accept within the timeout. + base::CancelableOnceClosure mutual_acceptance_timeout_alarm_; + // The current advertising power level. PowerLevel::kUnknown while not // advertising. PowerLevel advertising_power_level_ = PowerLevel::kUnknown;
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc index 4aa859e..6c5bb0a 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -10,11 +10,18 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" +#include "base/strings/string_number_conversions.h" #include "base/test/bind_test_util.h" #include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h" +#include "chrome/browser/nearby_sharing/fake_nearby_connection.h" #include "chrome/browser/nearby_sharing/fake_nearby_connections_manager.h" #include "chrome/browser/nearby_sharing/fast_initiation_manager.h" +#include "chrome/browser/nearby_sharing/mock_nearby_process_manager.h" +#include "chrome/browser/nearby_sharing/mock_nearby_sharing_decoder.h" #include "chrome/browser/nearby_sharing/nearby_connections_manager.h" +#include "chrome/browser/notifications/notification_display_service_factory.h" +#include "chrome/browser/notifications/notification_display_service_tester.h" +#include "chrome/services/sharing/public/proto/wire_format.pb.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" @@ -119,13 +126,15 @@ this}; }; -class FakeTransferUpdateCallback : public TransferUpdateCallback { +class MockTransferUpdateCallback : public TransferUpdateCallback { public: - void OnTransferUpdate(const ShareTarget& shareTarget, - const TransferMetadata& transferMetadata) override { - // TODO(crbug/1085068): Test transfer update callback when incoming - // connection is handled. - } + ~MockTransferUpdateCallback() override = default; + + MOCK_METHOD(void, + OnTransferUpdate, + (const ShareTarget& shareTarget, + const TransferMetadata& transferMetadata), + (override)); }; namespace { @@ -165,8 +174,14 @@ const std::string& profile_name) { Profile* profile = profile_manager_.CreateTestingProfile(profile_name); fake_nearby_connections_manager_ = new FakeNearbyConnectionsManager(); + notification_tester_ = + std::make_unique<NotificationDisplayServiceTester>(profile); + NotificationDisplayService* notification_display_service = + NotificationDisplayServiceFactory::GetForProfile(profile); auto service = std::make_unique<NearbySharingServiceImpl>( - &prefs_, profile, base::WrapUnique(fake_nearby_connections_manager_)); + &prefs_, notification_display_service, profile, + base::WrapUnique(fake_nearby_connections_manager_), + &mock_nearby_process_manager_); // Allow the posted task to fetch the BluetoothAdapter to finish. base::RunLoop().RunUntilIdle(); @@ -196,12 +211,17 @@ network_notifier_->GetConnectionType()); } + NiceMock<MockNearbyProcessManager>& mock_nearby_process_manager() { + return mock_nearby_process_manager_; + } + protected: content::BrowserTaskEnvironment task_environment_; ui::ScopedSetIdleState idle_state_{ui::IDLE_STATE_IDLE}; TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal()}; sync_preferences::TestingPrefServiceSyncable prefs_; FakeNearbyConnectionsManager* fake_nearby_connections_manager_ = nullptr; + std::unique_ptr<NotificationDisplayServiceTester> notification_tester_; std::unique_ptr<NearbySharingServiceImpl> service_; std::unique_ptr<FakeFastInitiationManagerFactory> fast_initiation_manager_factory_; @@ -209,6 +229,7 @@ bool is_bluetooth_powered_ = true; device::BluetoothAdapter::Observer* adapter_observer_ = nullptr; scoped_refptr<NiceMock<device::MockBluetoothAdapter>> mock_bluetooth_adapter_; + NiceMock<MockNearbyProcessManager> mock_nearby_process_manager_; std::unique_ptr<net::test::MockNetworkChangeNotifier> network_notifier_ = net::test::MockNetworkChangeNotifier::Create(); }; @@ -216,14 +237,13 @@ } // namespace TEST_F(NearbySharingServiceImplTest, AddsNearbyProcessObserver) { - NearbyProcessManager& manager = NearbyProcessManager::GetInstance(); - EXPECT_TRUE(manager.observers_.HasObserver(service_.get())); + EXPECT_TRUE( + mock_nearby_process_manager().observers_.HasObserver(service_.get())); } TEST_F(NearbySharingServiceImplTest, RemovesNearbyProcessObserver) { service_.reset(); - NearbyProcessManager& manager = NearbyProcessManager::GetInstance(); - EXPECT_FALSE(manager.observers_.might_have_observers()); + EXPECT_FALSE(mock_nearby_process_manager().observers_.might_have_observers()); } TEST_F(NearbySharingServiceImplTest, DisableNearbyShutdownConnections) { @@ -323,7 +343,7 @@ ForegroundRegisterReceiveSurfaceIsAdvertising) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -338,7 +358,7 @@ SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kSelectedContacts)); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -351,7 +371,7 @@ RegisterReceiveSurfaceTwiceSameCallbackKeepAdvertising) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -367,13 +387,13 @@ RegisterReceiveSurfaceTwiceKeepAdvertising) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); - FakeTransferUpdateCallback callback2; + MockTransferUpdateCallback callback2; NearbySharingService::StatusCodes result2 = service_->RegisterReceiveSurface( &callback2, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result2, NearbySharingService::StatusCodes::kOk); @@ -384,7 +404,7 @@ ScreenLockedRegisterReceiveSurfaceNotAdvertising) { ui::ScopedSetIdleState locked(ui::IDLE_STATE_LOCKED); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -400,7 +420,7 @@ prefs_.SetInteger(prefs::kNearbySharingDataUsageName, static_cast<int>(DataUsage::kOffline)); service_->FlushMojoForTesting(); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -419,7 +439,7 @@ TEST_F(NearbySharingServiceImplTest, NoNetworkRegisterReceiveSurfaceIsAdvertising) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -431,7 +451,7 @@ NoBluetoothNoNetworkRegisterReceiveSurfaceNotAdvertising) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); is_bluetooth_present_ = false; - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -442,7 +462,7 @@ TEST_F(NearbySharingServiceImplTest, WifiRegisterReceiveSurfaceIsAdvertising) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -453,7 +473,7 @@ EthernetRegisterReceiveSurfaceIsAdvertising) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -464,7 +484,7 @@ ThreeGRegisterReceiveSurfaceIsAdvertising) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_3G); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -477,7 +497,7 @@ ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); is_bluetooth_present_ = false; SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -489,7 +509,7 @@ ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); is_bluetooth_present_ = false; SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -501,7 +521,7 @@ ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); is_bluetooth_present_ = false; SetConnectionType(net::NetworkChangeNotifier::CONNECTION_3G); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -515,7 +535,7 @@ prefs_.SetBoolean(prefs::kNearbySharingEnabledPrefName, false); service_->FlushMojoForTesting(); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -527,7 +547,7 @@ DisableFeatureReceiveSurfaceStopsAdvertising) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -545,7 +565,7 @@ SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kNoOne)); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -559,7 +579,7 @@ prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kNoOne)); service_->FlushMojoForTesting(); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -574,7 +594,7 @@ prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kSelectedContacts)); service_->FlushMojoForTesting(); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -594,7 +614,7 @@ prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kNoOne)); service_->FlushMojoForTesting(); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -613,7 +633,7 @@ SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kSelectedContacts)); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -626,7 +646,7 @@ SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kSelectedContacts)); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -639,7 +659,7 @@ SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kAllContacts)); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -652,7 +672,7 @@ SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kAllContacts)); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kBackground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -662,7 +682,7 @@ TEST_F(NearbySharingServiceImplTest, UnregisterReceiveSurfaceStopsAdvertising) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); @@ -679,13 +699,13 @@ UnregisterReceiveSurfaceDifferentCallbackKeepAdvertising) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); - FakeTransferUpdateCallback callback2; + MockTransferUpdateCallback callback2; NearbySharingService::StatusCodes result2 = service_->UnregisterReceiveSurface(&callback2); EXPECT_EQ(result2, NearbySharingService::StatusCodes::kError); @@ -695,9 +715,112 @@ TEST_F(NearbySharingServiceImplTest, UnregisterReceiveSurfaceNeverRegistered) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); - FakeTransferUpdateCallback callback; + MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->UnregisterReceiveSurface(&callback); EXPECT_EQ(result, NearbySharingService::StatusCodes::kError); EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); } + +TEST_F(NearbySharingServiceImplTest, + IncomingConnection_EmptyIntroductionFrame) { + std::string intro = "introduction_frame"; + std::vector<uint8_t> bytes(intro.begin(), intro.end()); + NiceMock<MockNearbySharingDecoder> mock_decoder; + EXPECT_CALL(mock_decoder, DecodeFrame(testing::Eq(bytes), testing::_)) + .WillOnce(testing::Invoke( + [&](const std::vector<uint8_t>& data, + MockNearbySharingDecoder::DecodeFrameCallback callback) { + sharing::mojom::V1FramePtr mojo_v1frame = + sharing::mojom::V1Frame::New(); + mojo_v1frame->set_introduction( + sharing::mojom::IntroductionFrame::New()); + + sharing::mojom::FramePtr mojo_frame = sharing::mojom::Frame::New(); + mojo_frame->set_v1(std::move(mojo_v1frame)); + std::move(callback).Run(std::move(mojo_frame)); + })); + + EXPECT_CALL(mock_nearby_process_manager(), + GetOrStartNearbySharingDecoder(testing::_)) + .WillRepeatedly(testing::Return(&mock_decoder)); + + FakeNearbyConnection connection; + connection.AppendReadableData(bytes); + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + NiceMock<MockTransferUpdateCallback> callback; + base::RunLoop run_loop; + EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_)) + .WillOnce(testing::Invoke([&run_loop](const ShareTarget& share_target, + TransferMetadata metadata) { + EXPECT_EQ(TransferMetadata::Status::kUnsupportedAttachmentType, + metadata.status()); + run_loop.Quit(); + })); + + NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( + &callback, NearbySharingService::ReceiveSurfaceState::kForeground); + EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); + EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); + + service_->OnIncomingConnection("endpoint_id", {}, &connection); + run_loop.Run(); +} + +TEST_F(NearbySharingServiceImplTest, + IncomingConnection_ValidIntroductionFrame) { + std::string intro = "introduction_frame"; + std::vector<uint8_t> bytes(intro.begin(), intro.end()); + NiceMock<MockNearbySharingDecoder> mock_decoder; + EXPECT_CALL(mock_decoder, DecodeFrame(testing::Eq(bytes), testing::_)) + .WillOnce(testing::Invoke( + [&](const std::vector<uint8_t>& data, + MockNearbySharingDecoder::DecodeFrameCallback callback) { + // TODO(himanshujaju) - Write helper functions for these. + std::vector<sharing::mojom::TextMetadataPtr> mojo_text_metadatas; + for (int i = 1; i <= 3; i++) { + mojo_text_metadatas.push_back(sharing::mojom::TextMetadata::New( + "title " + base::NumberToString(i), + static_cast<sharing::mojom::TextMetadata::Type>(i), i, i, i)); + } + + sharing::mojom::V1FramePtr mojo_v1frame = + sharing::mojom::V1Frame::New(); + mojo_v1frame->set_introduction( + sharing::mojom::IntroductionFrame::New( + std::vector<sharing::mojom::FileMetadataPtr>(), + std::move(mojo_text_metadatas), base::nullopt, + std::vector<sharing::mojom::WifiCredentialsMetadataPtr>())); + + sharing::mojom::FramePtr mojo_frame = sharing::mojom::Frame::New(); + mojo_frame->set_v1(std::move(mojo_v1frame)); + std::move(callback).Run(std::move(mojo_frame)); + })); + + EXPECT_CALL(mock_nearby_process_manager(), + GetOrStartNearbySharingDecoder(testing::_)) + .WillRepeatedly(testing::Return(&mock_decoder)); + + FakeNearbyConnection connection; + connection.AppendReadableData(bytes); + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + NiceMock<MockTransferUpdateCallback> callback; + base::RunLoop run_loop; + EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_)) + .WillOnce(testing::Invoke([&run_loop](const ShareTarget& share_target, + TransferMetadata metadata) { + EXPECT_EQ(TransferMetadata::Status::kAwaitingLocalConfirmation, + metadata.status()); + run_loop.Quit(); + })); + + NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( + &callback, NearbySharingService::ReceiveSurfaceState::kForeground); + EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); + EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); + + service_->OnIncomingConnection("endpoint_id", {}, &connection); + run_loop.Run(); +}
diff --git a/chrome/browser/nearby_sharing/share_target.h b/chrome/browser/nearby_sharing/share_target.h index 67e7ca5..696f03a 100644 --- a/chrome/browser/nearby_sharing/share_target.h +++ b/chrome/browser/nearby_sharing/share_target.h
@@ -12,7 +12,7 @@ #include "base/unguessable_token.h" #include "chrome/browser/nearby_sharing/file_attachment.h" #include "chrome/browser/nearby_sharing/text_attachment.h" -#include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom-shared.h" +#include "chrome/browser/ui/webui/nearby_share/nearby_share_target_types.mojom.h" #include "url/gurl.h" // A remote device. @@ -33,6 +33,10 @@ ShareTarget& operator=(ShareTarget&&); ~ShareTarget(); + bool has_attachments() const { + return !text_attachments.empty() || !file_attachments.empty(); + } + base::UnguessableToken id = base::UnguessableToken::Create(); std::string device_name; // Uri that points to an image of the ShareTarget, if one exists.
diff --git a/chrome/browser/nearby_sharing/text_attachment.h b/chrome/browser/nearby_sharing/text_attachment.h index e9863ce..78ddacf 100644 --- a/chrome/browser/nearby_sharing/text_attachment.h +++ b/chrome/browser/nearby_sharing/text_attachment.h
@@ -9,21 +9,12 @@ #include "base/optional.h" #include "chrome/browser/nearby_sharing/attachment.h" +#include "chrome/services/sharing/public/mojom/nearby_decoder_types.mojom.h" // Represents a text attachment. class TextAttachment : public Attachment { public: - // Different types are used to offer richer experiences on Receiver side, - // mainly for: 1. displaying notification of attachment types, 2. opening - // different types with different apps. Remember to update Notifications, - // ShareTarget, etc once more types are introduced here. - enum class Type { - kText, - kUrl, - kAddress, - kPhoneNumber, - kMaxValue = kPhoneNumber - }; + using Type = sharing::mojom::TextMetadata::Type; TextAttachment(std::string text_body, Type type, int64_t size); ~TextAttachment() override;
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc index 095c5f3..b435bc67 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
@@ -38,6 +38,7 @@ #include "chrome/browser/page_load_metrics/observers/tab_restore_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/third_party_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/search.h" @@ -165,8 +166,8 @@ } bool PageLoadMetricsEmbedder::IsPrerendering() const { - return prerender::PrerenderContents::FromWebContents(web_contents()) != - nullptr; + return prerender::ChromePrerenderContentsDelegate::FromWebContents( + web_contents()) != nullptr; } bool PageLoadMetricsEmbedder::IsNewTabPageUrl(const GURL& url) { @@ -178,7 +179,8 @@ } bool PageLoadMetricsEmbedder::IsPrerender(content::WebContents* web_contents) { - return prerender::PrerenderContents::FromWebContents(web_contents); + return prerender::ChromePrerenderContentsDelegate::FromWebContents( + web_contents); } bool PageLoadMetricsEmbedder::IsExtensionUrl(const GURL& url) {
diff --git a/chrome/browser/password_check/android/internal/BUILD.gn b/chrome/browser/password_check/android/internal/BUILD.gn index fc79408..65998f8 100644 --- a/chrome/browser/password_check/android/internal/BUILD.gn +++ b/chrome/browser/password_check/android/internal/BUILD.gn
@@ -105,6 +105,7 @@ deps = [ ":java_strings_grd" ] sources = [ "java/res/layout/password_check_compromised_credential_item.xml", + "java/res/layout/password_check_compromised_credential_with_script_item.xml", "java/res/layout/password_check_header_item.xml", "java/res/values/dimens.xml", ]
diff --git a/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_item.xml b/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_item.xml index 8d4d84e..83456ca 100644 --- a/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_item.xml +++ b/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_item.xml
@@ -46,7 +46,6 @@ android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="@string/password_check_credential_row_change_button_caption" - android:visibility="gone" style="@style/FilledButton.Flat" /> </LinearLayout>
diff --git a/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_with_script_item.xml b/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_with_script_item.xml new file mode 100644 index 0000000..31005bb --- /dev/null +++ b/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_with_script_item.xml
@@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 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. --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:fillViewport="true" + android:gravity="center" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:orientation="horizontal"> + + <!-- TODO(crbug.com/1106277): Remove the paddingStart if favicons fill that space. --> + <LinearLayout + android:gravity="start" + android:layout_gravity="top" + android:layout_height="wrap_content" + android:layout_width="0dp" + android:layout_weight="1" + android:orientation="vertical" + android:paddingStart="@dimen/compromised_credential_row_padding_start" + android:paddingBottom="@dimen/compromised_credential_row_padding_bottom" + android:paddingTop="@dimen/compromised_credential_row_padding_top"> + + <TextView + android:id="@+id/credential_origin" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> + + <TextView + android:id="@+id/compromised_username" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:textAppearance="@style/TextAppearance.TextMedium.Secondary" /> + + <TextView + android:id="@+id/compromised_reason" + android:layout_marginTop="@dimen/compromised_credential_row_reason_margin_top" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:textAppearance="@style/TextAppearance.TextSmall.Secondary" /> + + <!-- TODO(crbug.com/1086114): Correct the style of the button and explanation text. --> + <org.chromium.ui.widget.ButtonCompat + android:id="@+id/credential_change_button_with_script" + android:layout_marginTop="@dimen/compromised_credential_row_button_margin_top" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:text="@string/password_check_credential_row_change_button_with_script_caption" + style="@style/FilledButton.Flat" /> + + <TextView + android:id="@+id/script_button_explanation" + android:layout_marginTop="@dimen/compromised_credential_row_reason_margin_top" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/password_check_credential_row_script_button_explanation" + android:textAppearance="@style/TextAppearance.TextSmall.Secondary" /> + + <org.chromium.ui.widget.ButtonCompat + android:id="@+id/credential_change_button" + android:layout_marginTop="@dimen/compromised_credential_row_button_margin_top" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:text="@string/password_check_credential_row_change_button_caption" /> + + </LinearLayout> + + <org.chromium.components.browser_ui.widget.listmenu.ListMenuButton + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/credential_menu_button" + android:background="@null" + android:contentDescription="@string/more" + android:layout_gravity="top" + android:layout_height="@dimen/compromised_credential_row_more_size" + android:layout_width="wrap_content" + android:paddingEnd="@dimen/compromised_credential_row_more_padding_end" + android:paddingStart="@dimen/compromised_credential_row_more_padding_start" + android:src="@drawable/ic_more_vert_24dp" + app:tint="@color/default_icon_color_tint_list" /> + +</LinearLayout>
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java index aa20591d..4a6a88e 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java
@@ -62,8 +62,10 @@ } private static void insertCredential(CompromisedCredential[] credentials, int index, - String originUrl, String username, String password, boolean phished) { - credentials[index] = new CompromisedCredential(originUrl, username, password, phished); + String originUrl, String username, String password, boolean phished, + boolean hasScript) { + credentials[index] = + new CompromisedCredential(originUrl, username, password, phished, hasScript); } /**
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java index 99fed90..5dd28c63 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java
@@ -35,7 +35,9 @@ assert items.size() == 1; for (CompromisedCredential credential : credentials) { - items.add(new ListItem(PasswordCheckProperties.ItemType.COMPROMISED_CREDENTIAL, + items.add(new ListItem(credential.hasScript() + ? PasswordCheckProperties.ItemType.COMPROMISED_CREDENTIAL_WITH_SCRIPT + : PasswordCheckProperties.ItemType.COMPROMISED_CREDENTIAL, new PropertyModel .Builder(PasswordCheckProperties.CompromisedCredentialProperties .ALL_KEYS)
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckProperties.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckProperties.java index 85042ce..9881cc623 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckProperties.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckProperties.java
@@ -55,7 +55,8 @@ private HeaderProperties() {} } - @IntDef({ItemType.HEADER, ItemType.COMPROMISED_CREDENTIAL}) + @IntDef({ItemType.HEADER, ItemType.COMPROMISED_CREDENTIAL, + ItemType.COMPROMISED_CREDENTIAL_WITH_SCRIPT}) @Retention(RetentionPolicy.SOURCE) @interface ItemType { /** @@ -67,6 +68,12 @@ * A section containing a user's name and password. */ int COMPROMISED_CREDENTIAL = 2; + + /** + * A section containing a user's name and password for a domain where a password change + * script is available. + */ + int COMPROMISED_CREDENTIAL_WITH_SCRIPT = 3; } /**
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java index 5a44706..1496562 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java
@@ -71,6 +71,10 @@ return new PasswordCheckViewHolder(parent, R.layout.password_check_compromised_credential_item, PasswordCheckViewBinder::bindCredentialView); + case ItemType.COMPROMISED_CREDENTIAL_WITH_SCRIPT: + return new PasswordCheckViewHolder(parent, + R.layout.password_check_compromised_credential_with_script_item, + PasswordCheckViewBinder::bindCredentialView); } assert false : "Cannot create view for ItemType: " + itemType; return null; @@ -113,6 +117,10 @@ reason.setText(credential.isPhished() ? R.string.password_check_credential_row_reason_phished : R.string.password_check_credential_row_reason_leaked); + if (credential.hasScript()) { + assert view.findViewById(R.id.credential_change_button_with_script) != null; + assert view.findViewById(R.id.script_button_explanation) != null; + } ListMenuButton more = view.findViewById(R.id.credential_menu_button); more.setDelegate(() -> {
diff --git a/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings.grd b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings.grd index 8b2593b..a5a305e 100644 --- a/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings.grd +++ b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings.grd
@@ -175,13 +175,18 @@ <message name="IDS_PASSWORD_CHECK_CREDENTIAL_ROW_CHANGE_BUTTON_CAPTION" desc="Caption for the button that links to a site where the user can change a compromised credential."> Change password </message> + <message name="IDS_PASSWORD_CHECK_CREDENTIAL_ROW_CHANGE_BUTTON_WITH_SCRIPT_CAPTION" desc="Caption for the button that starts a script that changes a compromised credential."> + Change password automatically + </message> <message name="IDS_PASSWORD_CHECK_CREDENTIAL_ROW_REASON_LEAKED" desc="Small description explaining that a credential is compromised because it was part of a data breach."> Found in data breach </message> <message name="IDS_PASSWORD_CHECK_CREDENTIAL_ROW_REASON_PHISHED" desc="Small description explaining that a credential is compromised because it was entered on a deceptive site."> Entered on a deceptive site </message> - + <message name="IDS_PASSWORD_CHECK_CREDENTIAL_ROW_SCRIPT_BUTTON_EXPLANATION" desc="Small description explaining that an automated password change can be done with a script."> + Let Google Assistant help you change your password + </message> <!-- Accessibility strings --> <message name="IDS_ACCESSIBILITY_PASSWORD_CHECK_RESTART_BUTTON" desc="Content description for the button to restart the password check."> Restart password check
diff --git a/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_CHANGE_BUTTON_WITH_SCRIPT_CAPTION.png.sha1 b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_CHANGE_BUTTON_WITH_SCRIPT_CAPTION.png.sha1 new file mode 100644 index 0000000..353e7a92 --- /dev/null +++ b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_CHANGE_BUTTON_WITH_SCRIPT_CAPTION.png.sha1
@@ -0,0 +1 @@ +68c54c7c1d83797946c4652935284033a9ed10be \ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_SCRIPT_BUTTON_EXPLANATION.png.sha1 b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_SCRIPT_BUTTON_EXPLANATION.png.sha1 new file mode 100644 index 0000000..353e7a92 --- /dev/null +++ b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_SCRIPT_BUTTON_EXPLANATION.png.sha1
@@ -0,0 +1 @@ +68c54c7c1d83797946c4652935284033a9ed10be \ No newline at end of file
diff --git a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/CompromisedCredential.java b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/CompromisedCredential.java index bbcd4fe..b23793b 100644 --- a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/CompromisedCredential.java +++ b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/CompromisedCredential.java
@@ -15,18 +15,20 @@ private final String mPassword; private final String mOriginUrl; private final boolean mPhished; + private final boolean mHasScript; /** * @param username Username shown to the user. * @param originUrl Origin URL shown to the user in case this credential is a PSL match. */ - public CompromisedCredential( - String originUrl, String username, String password, boolean phished) { + public CompromisedCredential(String originUrl, String username, String password, + boolean phished, boolean hasScript) { assert originUrl != null : "Credential origin is null! Pass an empty one instead."; mOriginUrl = originUrl; mUsername = username; mPassword = password; mPhished = phished; + mHasScript = hasScript; } public String getOriginUrl() { @@ -41,18 +43,22 @@ public boolean isPhished() { return mPhished; } + public boolean hasScript() { + return mHasScript; + } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CompromisedCredential that = (CompromisedCredential) o; - return mPhished == that.mPhished && mUsername.equals(that.mUsername) - && mPassword.equals(that.mPassword) && mOriginUrl.equals(that.mOriginUrl); + return mPhished == that.mPhished && mHasScript == that.mHasScript + && mUsername.equals(that.mUsername) && mPassword.equals(that.mPassword) + && mOriginUrl.equals(that.mOriginUrl); } @Override public int hashCode() { - return Objects.hash(mUsername, mPassword, mOriginUrl, mPhished); + return Objects.hash(mUsername, mPassword, mOriginUrl, mPhished, mHasScript); } }
diff --git a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java index a5fae1d7..a0940ea8 100644 --- a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java +++ b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java
@@ -60,11 +60,13 @@ @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class PasswordCheckViewTest { private static final CompromisedCredential ANA = - new CompromisedCredential("some-url.com", "Ana", "password", false); + new CompromisedCredential("some-url.com", "Ana", "password", false, false); private static final CompromisedCredential PHISHED = - new CompromisedCredential("example.com", "Baub", "DoSomething", true); + new CompromisedCredential("example.com", "Baub", "DoSomething", true, false); private static final CompromisedCredential LEAKED = - new CompromisedCredential("some-other-url.com", "AZiegler", "N0M3rcy", false); + new CompromisedCredential("some-other-url.com", "AZiegler", "N0M3rcy", false, false); + private static final CompromisedCredential SCRIPTED = + new CompromisedCredential("script.com", "Charlie", "secret", false, true); private PropertyModel mModel = PasswordCheckProperties.createDefaultModel(); private PasswordCheckFragmentView mPasswordCheckView; @@ -102,8 +104,7 @@ pollUiThread(() -> Criteria.checkThat(getPasswordCheckViewList().getChildCount(), is(2))); // Has a change passwords button. assertNotNull(getCredentialChangeButtonAt(1)); - // TODO(crbug.com/1092444): Ensure the button is visible as soon as it does something! - assertThat(getCredentialChangeButtonAt(1).getVisibility(), is(View.GONE)); + assertThat(getCredentialChangeButtonAt(1).getVisibility(), is(View.VISIBLE)); assertThat(getCredentialChangeButtonAt(1).getText(), is(getString(R.string.password_check_credential_row_change_button_caption))); @@ -154,6 +155,37 @@ @Test @MediumTest + public void testCrendentialDisplaysChangeButtonWithScript() { + runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildCredentialItem(SCRIPTED)); }); + pollUiThread(() -> Criteria.checkThat(getPasswordCheckViewList().getChildCount(), is(1))); + + // Origin and username. + assertThat(getCredentialOriginAt(0).getText(), is(SCRIPTED.getOriginUrl())); + assertThat(getCredentialUserAt(0).getText(), is(SCRIPTED.getUsername())); + + // Reason to show credential. + assertThat(getCredentialReasonAt(0).getText(), + is(getString(R.string.password_check_credential_row_reason_leaked))); + + // Change button with script. + assertNotNull(getCredentialChangeButtonWithScriptAt(0)); + assertThat(getCredentialChangeButtonWithScriptAt(0).getText(), + is(getString( + R.string.password_check_credential_row_change_button_with_script_caption))); + + // Explanation for change button with script. + assertNotNull(getCredentialChangeButtonWithScriptExplanationAt(0)); + assertThat(getCredentialChangeButtonWithScriptExplanationAt(0).getText(), + is(getString(R.string.password_check_credential_row_script_button_explanation))); + + // Change button without script. + assertNotNull(getCredentialChangeButtonAt(0)); + assertThat(getCredentialChangeButtonAt(0).getText(), + is(getString(R.string.password_check_credential_row_change_button_caption))); + } + + @Test + @MediumTest public void testClickingDeleteInMoreMenuTriggersHandler() { runOnUiThreadBlocking(() -> mModel.get(ITEMS).add(buildCredentialItem(ANA))); pollUiThread(() -> Criteria.checkThat(getPasswordCheckViewList().getChildCount(), is(1))); @@ -176,7 +208,9 @@ } private MVCListAdapter.ListItem buildCredentialItem(CompromisedCredential credential) { - return new MVCListAdapter.ListItem(PasswordCheckProperties.ItemType.COMPROMISED_CREDENTIAL, + return new MVCListAdapter.ListItem(credential.hasScript() + ? PasswordCheckProperties.ItemType.COMPROMISED_CREDENTIAL_WITH_SCRIPT + : PasswordCheckProperties.ItemType.COMPROMISED_CREDENTIAL, new PropertyModel .Builder(PasswordCheckProperties.CompromisedCredentialProperties.ALL_KEYS) .with(COMPROMISED_CREDENTIAL, credential) @@ -220,6 +254,16 @@ R.id.credential_change_button); } + private ButtonCompat getCredentialChangeButtonWithScriptAt(int index) { + return getPasswordCheckViewList().getChildAt(index).findViewById( + R.id.credential_change_button_with_script); + } + + private TextView getCredentialChangeButtonWithScriptExplanationAt(int index) { + return getPasswordCheckViewList().getChildAt(index).findViewById( + R.id.script_button_explanation); + } + private ListMenuButton getCredentialMoreButtonAt(int index) { return getPasswordCheckViewList().getChildAt(index).findViewById( R.id.credential_menu_button);
diff --git a/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java b/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java index 528c1a26..8bbbecc 100644 --- a/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java +++ b/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java
@@ -37,9 +37,9 @@ @RunWith(BaseRobolectricTestRunner.class) public class PasswordCheckControllerTest { private static final CompromisedCredential ANA = - new CompromisedCredential("https://m.a.xyz/", "Ana", "password", false); + new CompromisedCredential("https://m.a.xyz/", "Ana", "password", false, false); private static final CompromisedCredential BOB = - new CompromisedCredential("https://www.b.ch/", "Baub", "DoneSth", true); + new CompromisedCredential("https://www.b.ch/", "Baub", "DoneSth", true, false); @Mock private PasswordCheckComponentUi.Delegate mDelegate;
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index 55517ef..7d57fe2 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -860,6 +860,12 @@ RunTestsInJsModule("viewer_pdf_toolbar_new_test.js", "test.pdf"); } +IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, ViewerPdfSidenav) { + // Although this test file does not require a PDF to be loaded, loading the + // elements without loading a PDF is difficult. + RunTestsInJsModule("viewer_pdf_sidenav_test.js", "test.pdf"); +} + IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, ToolbarManager) { RunTestsInJsModule("toolbar_manager_test.js", "test.pdf"); }
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.cc b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.cc index 845aa13..4a7dbb8 100644 --- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.cc +++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.h" #include "base/memory/ptr_util.h" +#include "base/run_loop.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade.h" #include "chrome/browser/profiles/incognito_helpers.h" @@ -21,13 +22,8 @@ SiteDataCacheFacadeFactory* g_instance = nullptr; -} - -// static -SiteDataCacheFacade* SiteDataCacheFacadeFactory::GetForProfile( - Profile* profile) { - return static_cast<SiteDataCacheFacade*>( - GetInstance()->GetServiceForBrowserContext(profile, true)); +// Tests that want to use this factory will have to explicitly enable it. +bool g_enable_for_testing = false; } SiteDataCacheFacadeFactory* SiteDataCacheFacadeFactory::GetInstance() { @@ -37,6 +33,31 @@ return g_instance; } +// static +std::unique_ptr<base::AutoReset<bool>> +SiteDataCacheFacadeFactory::EnableForTesting() { + // Only one AutoReset served by this function can exists, otherwise the first + // one being released would set g_enable_for_testing to false while there's + // other AutoReset still existing. + DCHECK(!g_enable_for_testing); + return std::make_unique<base::AutoReset<bool>>(&g_enable_for_testing, true); +} + +// static +void SiteDataCacheFacadeFactory::DisassociateForTesting(Profile* profile) { + GetInstance()->Disassociate(profile); +} + +// static +void SiteDataCacheFacadeFactory::ReleaseInstanceForTesting() { + base::RunLoop run_loop; + g_instance->cache_factory()->ResetWithCallbackAfterDestruction( + run_loop.QuitClosure()); + run_loop.Run(); + delete g_instance; + DCHECK(!g_instance); +} + SiteDataCacheFacadeFactory::SiteDataCacheFacadeFactory() : BrowserContextKeyedServiceFactory( "SiteDataCacheFacadeFactory", @@ -69,8 +90,7 @@ } bool SiteDataCacheFacadeFactory::ServiceIsNULLWhileTesting() const { - // Tests that want to use this factory will have to explicitly enable it. - return true; + return !g_enable_for_testing; } } // namespace performance_manager
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.h b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.h index a4a4ec5..0c86f15 100644 --- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.h +++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_PERSISTENCE_SITE_DATA_SITE_DATA_CACHE_FACADE_FACTORY_H_ #define CHROME_BROWSER_PERFORMANCE_MANAGER_PERSISTENCE_SITE_DATA_SITE_DATA_CACHE_FACADE_FACTORY_H_ +#include "base/auto_reset.h" #include "base/memory/weak_ptr.h" #include "base/no_destructor.h" #include "base/threading/sequence_bound.h" @@ -49,9 +50,12 @@ public: ~SiteDataCacheFacadeFactory() override; - static SiteDataCacheFacade* GetForProfile(Profile* profile); static SiteDataCacheFacadeFactory* GetInstance(); + static std::unique_ptr<base::AutoReset<bool>> EnableForTesting(); + static void DisassociateForTesting(Profile* profile); + static void ReleaseInstanceForTesting(); + protected: friend class base::NoDestructor<SiteDataCacheFacadeFactory>; friend class SiteDataCacheFacade;
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc index 359e1ff..93c0a0814 100644 --- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc +++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc
@@ -106,15 +106,14 @@ void SetUp() override { testing::TestWithPerformanceManager::SetUp(); profile_ = std::make_unique<TestingProfile>(); - facade_factory_ = base::WrapUnique(new SiteDataCacheFacadeFactory()); use_in_memory_db_for_testing_ = LevelDBSiteDataStore::UseInMemoryDBForTesting(); } void TearDown() override { use_in_memory_db_for_testing_.reset(); - facade_factory_.reset(); profile_.reset(); + SiteDataCacheFacadeFactory::ReleaseInstanceForTesting(); testing::TestWithPerformanceManager::TearDown(); } @@ -144,7 +143,6 @@ private: std::unique_ptr<TestingProfile> profile_; - std::unique_ptr<SiteDataCacheFacadeFactory> facade_factory_; std::unique_ptr<base::AutoReset<bool>> use_in_memory_db_for_testing_; };
diff --git a/chrome/browser/performance_manager/test_support/site_data_utils.cc b/chrome/browser/performance_manager/test_support/site_data_utils.cc new file mode 100644 index 0000000..d127f83 --- /dev/null +++ b/chrome/browser/performance_manager/test_support/site_data_utils.cc
@@ -0,0 +1,117 @@ +// Copyright 2020 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/performance_manager/test_support/site_data_utils.h" +#include <memory> + +#include "base/callback_forward.h" +#include "base/memory/weak_ptr.h" +#include "base/run_loop.h" +#include "base/test/bind_test_util.h" +#include "chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.h" +#include "components/performance_manager/persistence/site_data/leveldb_site_data_store.h" +#include "components/performance_manager/persistence/site_data/site_data_impl.h" +#include "components/performance_manager/persistence/site_data/site_data_writer.h" +#include "components/performance_manager/public/decorators/site_data_recorder.h" +#include "components/performance_manager/public/performance_manager.h" + +namespace performance_manager { + +SiteDataTestHarness::SiteDataTestHarness() + : use_in_memory_db_for_testing_( + LevelDBSiteDataStore::UseInMemoryDBForTesting()), + enable_cache_factory_for_testing_( + SiteDataCacheFacadeFactory::EnableForTesting()) {} + +SiteDataTestHarness::~SiteDataTestHarness() = default; + +void SiteDataTestHarness::SetUp() { + PerformanceManagerTestHarnessHelper::SetUp(); + base::RunLoop run_loop; + auto quit_closure = run_loop.QuitClosure(); + auto recorder = std::make_unique<SiteDataRecorder>(); + PerformanceManager::CallOnGraph( + FROM_HERE, + base::BindLambdaForTesting([&](performance_manager::Graph* graph) { + graph->PassToGraph(std::move(recorder)); + std::move(quit_closure).Run(); + })); + run_loop.Run(); +} + +void SiteDataTestHarness::TearDown(Profile* profile) { + SiteDataCacheFacadeFactory::DisassociateForTesting(profile); + TearDown(); +} + +void SiteDataTestHarness::TearDown() { + SiteDataCacheFacadeFactory::ReleaseInstanceForTesting(); + PerformanceManagerTestHarnessHelper::TearDown(); +} + +internal::SiteDataImpl* GetSiteDataImplForPageNode(PageNode* page_node) { + auto* writer = SiteDataRecorder::Data::FromPageNode(page_node)->writer(); + + if (!writer) + return nullptr; + + return writer->impl_for_testing(); +} + +void MarkWebContentsAsLoadedInBackgroundInSiteDataDb( + content::WebContents* web_contents) { + base::RunLoop run_loop; + PerformanceManager::CallOnGraph( + FROM_HERE, + base::BindOnce( + [](base::WeakPtr<PageNode> page_node, base::OnceClosure closure) { + DCHECK(page_node); + auto* impl = GetSiteDataImplForPageNode(page_node.get()); + DCHECK(impl); + impl->NotifySiteLoaded(); + impl->NotifyLoadedSiteBackgrounded(); + std::move(closure).Run(); + }, + PerformanceManager::GetPageNodeForWebContents(web_contents), + run_loop.QuitClosure())); + run_loop.Run(); +} + +void MarkWebContentsAsUnloadedInBackgroundInSiteDataDb( + content::WebContents* web_contents) { + base::RunLoop run_loop; + PerformanceManager::CallOnGraph( + FROM_HERE, + base::BindOnce( + [](base::WeakPtr<PageNode> page_node, base::OnceClosure closure) { + DCHECK(page_node); + auto* impl = GetSiteDataImplForPageNode(page_node.get()); + DCHECK(impl); + impl->NotifySiteUnloaded(TabVisibility::kBackground); + std::move(closure).Run(); + }, + PerformanceManager::GetPageNodeForWebContents(web_contents), + run_loop.QuitClosure())); + run_loop.Run(); +} + +void ExpireSiteDataObservationWindowsForWebContents( + content::WebContents* web_contents) { + base::RunLoop run_loop; + PerformanceManager::CallOnGraph( + FROM_HERE, + base::BindOnce( + [](base::WeakPtr<PageNode> page_node, base::OnceClosure closure) { + DCHECK(page_node); + auto* impl = GetSiteDataImplForPageNode(page_node.get()); + DCHECK(impl); + impl->ExpireAllObservationWindowsForTesting(); + std::move(closure).Run(); + }, + PerformanceManager::GetPageNodeForWebContents(web_contents), + run_loop.QuitClosure())); + run_loop.Run(); +} + +} // namespace performance_manager
diff --git a/chrome/browser/performance_manager/test_support/site_data_utils.h b/chrome/browser/performance_manager/test_support/site_data_utils.h new file mode 100644 index 0000000..e384a16 --- /dev/null +++ b/chrome/browser/performance_manager/test_support/site_data_utils.h
@@ -0,0 +1,74 @@ +// Copyright 2020 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_PERFORMANCE_MANAGER_TEST_SUPPORT_SITE_DATA_UTILS_H_ +#define CHROME_BROWSER_PERFORMANCE_MANAGER_TEST_SUPPORT_SITE_DATA_UTILS_H_ + +#include <memory> +#include "base/auto_reset.h" +#include "components/performance_manager/test_support/test_harness_helper.h" + +class Profile; + +namespace content { +class WebContents; +} + +namespace performance_manager { + +namespace internal { +class SiteDataImpl; +} + +class PageNode; + +// A test harness that initializes all the components required to use the +// SiteData database in unit_tests. This doesn't support tests that use multiple +// profiles. See comment in the PerformanceManagerTestHarnessHelper class for +// directions on how this should be used in tests. +class SiteDataTestHarness : public PerformanceManagerTestHarnessHelper { + public: + SiteDataTestHarness(); + SiteDataTestHarness(const SiteDataTestHarness& other) = delete; + SiteDataTestHarness& operator=(const SiteDataTestHarness&) = delete; + ~SiteDataTestHarness() override; + + void SetUp() override; + // During tear down it's necessary to release the global + // SiteDataCacheFacadeFactory instance to ensure that it doesn't get reused + // from tests to tests. Before doing this it's necessary to disassociate it + // from any profile. This harness assumes that tests are only using one + // profile. + void TearDown(Profile* profile); + + private: + void TearDown() override; + + // Use an in memory database to avoid creating some unnecessary files on disk. + std::unique_ptr<base::AutoReset<bool>> use_in_memory_db_for_testing_; + std::unique_ptr<base::AutoReset<bool>> enable_cache_factory_for_testing_; +}; + +// Return the SiteDataImpl instance backing a PageNode, this might be null if +// this PageNode isn't loaded with a valid URL. +// +// This function can only be called from the graph's sequence. +internal::SiteDataImpl* GetSiteDataImplForPageNode(PageNode* page_node); + +// Pretend that this WebContents has been loaded and is in background. +void MarkWebContentsAsLoadedInBackgroundInSiteDataDb( + content::WebContents* web_contents); + +// Pretend that this WebContents has been unloaded and is in background. +void MarkWebContentsAsUnloadedInBackgroundInSiteDataDb( + content::WebContents* web_contents); + +// Expire all the Site Data Database observation windows for a given +// WebContents. +void ExpireSiteDataObservationWindowsForWebContents( + content::WebContents* web_contents); + +} // namespace performance_manager + +#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_TEST_SUPPORT_SITE_DATA_UTILS_H_
diff --git a/chrome/browser/plugins/flash_download_interception.cc b/chrome/browser/plugins/flash_download_interception.cc index d2fa416..689c74c2 100644 --- a/chrome/browser/plugins/flash_download_interception.cc +++ b/chrome/browser/plugins/flash_download_interception.cc
@@ -82,13 +82,16 @@ if (flash_setting == CONTENT_SETTING_DETECT_IMPORTANT_CONTENT) { permissions::PermissionManager* manager = PermissionManagerFactory::GetForProfile(profile); + // TODO(https://crbug.com/1103176): Plumb the actual frame reference here + // (FlashDownloadInterception is created only for renderer-initiated + // navigations, so we always should have a reference to the originating + // RenderFrameHost) manager->RequestPermission( ContentSettingsType::PLUGINS, web_contents->GetMainFrame(), web_contents->GetLastCommittedURL(), true, base::DoNothing()); } else if (flash_setting == CONTENT_SETTING_BLOCK) { - auto* settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents); + auto* settings = content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()); if (settings) settings->FlashDownloadBlocked(); }
diff --git a/chrome/browser/prerender/chrome_prerender_contents_delegate.cc b/chrome/browser/prerender/chrome_prerender_contents_delegate.cc new file mode 100644 index 0000000..cb5204c --- /dev/null +++ b/chrome/browser/prerender/chrome_prerender_contents_delegate.cc
@@ -0,0 +1,51 @@ +// Copyright 2020 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/prerender/chrome_prerender_contents_delegate.h" + +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/prerender/prerender_contents.h" +#include "chrome/browser/prerender/prerender_manager.h" +#include "chrome/browser/prerender/prerender_manager_factory.h" +#include "chrome/browser/task_manager/web_contents_tags.h" +#include "chrome/browser/ui/tab_helpers.h" +#include "chrome/common/chrome_render_frame.mojom.h" +#include "components/prerender/browser/prerender_histograms.h" +#include "content/public/browser/web_contents.h" + +namespace prerender { + +// static +PrerenderContents* ChromePrerenderContentsDelegate::FromWebContents( + content::WebContents* web_contents) { + if (!web_contents) + return nullptr; + PrerenderManager* prerender_manager = + PrerenderManagerFactory::GetForBrowserContext( + web_contents->GetBrowserContext()); + if (!prerender_manager) + return nullptr; + return prerender_manager->GetPrerenderContents(web_contents); +} + +void ChromePrerenderContentsDelegate::OnPrerenderContentsCreated( + content::WebContents* web_contents) { + DCHECK(web_contents); + TabHelpers::AttachTabHelpers(web_contents); + + // Tag the prerender contents with the task manager specific prerender tag, so + // that it shows up in the task manager. + task_manager::WebContentsTags::CreateForPrerenderContents(web_contents); +} + +void ChromePrerenderContentsDelegate::ReleasePrerenderContents( + content::WebContents* web_contents) { + DCHECK(web_contents); + + // Clear the task manager tag we added earlier to our + // WebContents since it's no longer a prerender contents. + task_manager::WebContentsTags::ClearTag(web_contents); +} + +} // namespace prerender
diff --git a/chrome/browser/prerender/chrome_prerender_contents_delegate.h b/chrome/browser/prerender/chrome_prerender_contents_delegate.h new file mode 100644 index 0000000..fe90149a --- /dev/null +++ b/chrome/browser/prerender/chrome_prerender_contents_delegate.h
@@ -0,0 +1,36 @@ +// Copyright 2020 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_PRERENDER_CHROME_PRERENDER_CONTENTS_DELEGATE_H_ +#define CHROME_BROWSER_PRERENDER_CHROME_PRERENDER_CONTENTS_DELEGATE_H_ + +#include "chrome/browser/prerender/prerender_contents_delegate.h" +#include "mojo/public/cpp/bindings/associated_remote.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" + +namespace content { +class WebContents; +} + +namespace prerender { + +class PrerenderContents; + +class ChromePrerenderContentsDelegate : public PrerenderContentsDelegate { + public: + // Returns a PrerenderContents from the given web_contents, if it's used for + // prerendering. Otherwise returns nullptr. Handles a nullptr input for + // convenience. + static PrerenderContents* FromWebContents(content::WebContents* web_contents); + + ChromePrerenderContentsDelegate() = default; + ~ChromePrerenderContentsDelegate() override = default; + + // PrerenderContentsDelegate overrides. + void OnPrerenderContentsCreated(content::WebContents* web_contents) override; + void ReleasePrerenderContents(content::WebContents* web_contents) override; +}; + +} // namespace prerender + +#endif // CHROME_BROWSER_PRERENDER_CHROME_PRERENDER_CONTENTS_DELEGATE_H_
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc index 8279210..f265b722 100644 --- a/chrome/browser/prerender/prerender_contents.cc +++ b/chrome/browser/prerender/prerender_contents.cc
@@ -15,24 +15,17 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "build/build_config.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/history/history_tab_helper.h" -#include "chrome/browser/prerender/prerender_field_trial.h" -#include "chrome/browser/prerender/prerender_handle.h" +#include "chrome/browser/prerender/prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_manager.h" -#include "chrome/browser/prerender/prerender_manager_factory.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/task_manager/web_contents_tags.h" -#include "chrome/browser/ui/tab_helpers.h" -#include "chrome/common/chrome_render_frame.mojom.h" -#include "components/history/core/browser/history_types.h" #include "components/prerender/common/prerender_final_status.h" #include "components/prerender/common/prerender_util.h" #include "components/prerender/common/render_frame_prerender_messages.mojom.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_types.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" @@ -41,7 +34,6 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/common/frame_navigate_params.h" -#include "mojo/public/cpp/bindings/associated_remote.h" #include "net/http/http_response_headers.h" #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h" #include "services/service_manager/public/cpp/binder_registry.h" @@ -60,13 +52,15 @@ class PrerenderContentsFactoryImpl : public PrerenderContents::Factory { public: PrerenderContents* CreatePrerenderContents( + std::unique_ptr<PrerenderContentsDelegate> delegate, PrerenderManager* prerender_manager, - Profile* profile, + content::BrowserContext* browser_context, const GURL& url, const content::Referrer& referrer, const base::Optional<url::Origin>& initiator_origin, Origin origin) override { - return new PrerenderContents(prerender_manager, profile, url, referrer, + return new PrerenderContents(std::move(delegate), prerender_manager, + browser_context, url, referrer, initiator_origin, origin); } }; @@ -129,8 +123,9 @@ PrerenderContents::Observer::~Observer() {} PrerenderContents::PrerenderContents( + std::unique_ptr<PrerenderContentsDelegate> delegate, PrerenderManager* prerender_manager, - Profile* profile, + content::BrowserContext* browser_context, const GURL& url, const content::Referrer& referrer, const base::Optional<url::Origin>& initiator_origin, @@ -138,10 +133,11 @@ : prerender_mode_(prerender::mojom::PrerenderMode::kNoPrerender), prerendering_has_started_(false), prerender_manager_(prerender_manager), + delegate_(std::move(delegate)), prerender_url_(url), referrer_(referrer), initiator_origin_(initiator_origin), - profile_(profile), + browser_context_(browser_context), has_finished_loading_(false), final_status_(FINAL_STATUS_UNKNOWN), prerendering_has_been_cancelled_(false), @@ -187,23 +183,10 @@ return new PrerenderContentsFactoryImpl(); } -// static -PrerenderContents* PrerenderContents::FromWebContents( - content::WebContents* web_contents) { - if (!web_contents) - return NULL; - PrerenderManager* prerender_manager = - PrerenderManagerFactory::GetForBrowserContext( - web_contents->GetBrowserContext()); - if (!prerender_manager) - return NULL; - return prerender_manager->GetPrerenderContents(web_contents); -} - void PrerenderContents::StartPrerendering( const gfx::Rect& bounds, SessionStorageNamespace* session_storage_namespace) { - DCHECK(profile_); + DCHECK(browser_context_); DCHECK(!bounds.IsEmpty()); DCHECK(!prerendering_has_started_); DCHECK(!prerender_contents_); @@ -218,13 +201,8 @@ prerendering_has_started_ = true; prerender_contents_ = CreateWebContents(session_storage_namespace); - TabHelpers::AttachTabHelpers(prerender_contents_.get()); content::WebContentsObserver::Observe(prerender_contents_.get()); - - // Tag the prerender contents with the task manager specific prerender tag, so - // that it shows up in the task manager. - task_manager::WebContentsTags::CreateForPrerenderContents( - prerender_contents_.get()); + delegate_->OnPrerenderContentsCreated(prerender_contents_.get()); web_contents_delegate_.reset(new WebContentsDelegateImpl(this)); prerender_contents_.get()->SetDelegate(web_contents_delegate_.get()); @@ -244,10 +222,6 @@ NotifyPrerenderStart(); - // Close ourselves when the application is shutting down. - notification_registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, - content::NotificationService::AllSources()); - // Register to inform new RenderViews that we're prerendering. notification_registrar_.Add( this, content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED, @@ -320,12 +294,6 @@ const content::NotificationSource& source, const content::NotificationDetails& details) { switch (type) { - // TODO(davidben): Try to remove this in favor of relying on - // FINAL_STATUS_PROFILE_DESTROYED. - case chrome::NOTIFICATION_APP_TERMINATING: - Destroy(FINAL_STATUS_APP_TERMINATING); - return; - case content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED: { if (prerender_contents_.get()) { DCHECK_EQ(content::Source<WebContents>(source).ptr(), @@ -362,7 +330,8 @@ content::SessionStorageNamespaceMap session_storage_namespace_map; session_storage_namespace_map[std::string()] = session_storage_namespace; return WebContents::CreateWithSessionStorage( - WebContents::CreateParams(profile_), session_storage_namespace_map); + WebContents::CreateParams(browser_context_), + session_storage_namespace_map); } void PrerenderContents::NotifyPrerenderStart() { @@ -595,9 +564,7 @@ prerender_contents_->SetDelegate(nullptr); content::WebContentsObserver::Observe(nullptr); - // Clear the task manager tag we added earlier to our - // WebContents since it's no longer a prerender contents. - task_manager::WebContentsTags::ClearTag(prerender_contents_.get()); + delegate_->ReleasePrerenderContents(prerender_contents_.get()); return std::move(prerender_contents_); } @@ -607,17 +574,6 @@ : nullptr; } -void PrerenderContents::DidNavigate( - const history::HistoryAddPageArgs& add_page_args) { - add_page_vector_.push_back(add_page_args); -} - -void PrerenderContents::CommitHistory(WebContents* tab) { - HistoryTabHelper* history_tab_helper = HistoryTabHelper::FromWebContents(tab); - for (size_t i = 0; i < add_page_vector_.size(); ++i) - history_tab_helper->UpdateHistoryForNavigation(add_page_vector_[i]); -} - std::unique_ptr<base::DictionaryValue> PrerenderContents::GetAsValue() const { if (!prerender_contents_) return nullptr;
diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h index 15cde43..516e2b92 100644 --- a/chrome/browser/prerender/prerender_contents.h +++ b/chrome/browser/prerender/prerender_contents.h
@@ -18,6 +18,7 @@ #include "base/optional.h" #include "base/time/time.h" #include "base/values.h" +#include "chrome/browser/prerender/prerender_contents_delegate.h" #include "components/prerender/common/prerender_canceler.mojom.h" #include "components/prerender/common/prerender_final_status.h" #include "components/prerender/common/prerender_origin.h" @@ -30,22 +31,17 @@ #include "ui/gfx/geometry/rect.h" #include "url/origin.h" -class Profile; - namespace base { class ProcessMetrics; } namespace content { +class BrowserContext; class RenderViewHost; class SessionStorageNamespace; class WebContents; } // namespace content -namespace history { -struct HistoryAddPageArgs; -} - namespace memory_instrumentation { class GlobalMemoryDump; } @@ -65,11 +61,12 @@ Factory() {} virtual ~Factory() {} - // Ownership is not transfered through this interface as prerender_manager - // and profile are stored as weak pointers. + // Ownership is not transferred through this interface as prerender_manager + // and browser_context are stored as weak pointers. virtual PrerenderContents* CreatePrerenderContents( + std::unique_ptr<PrerenderContentsDelegate> delegate, PrerenderManager* prerender_manager, - Profile* profile, + content::BrowserContext* browser_context, const GURL& url, const content::Referrer& referrer, const base::Optional<url::Origin>& initiator_origin, @@ -123,11 +120,6 @@ static Factory* CreateFactory(); - // Returns a PrerenderContents from the given web_contents, if it's used for - // prerendering. Otherwise returns NULL. Handles a NULL input for - // convenience. - static PrerenderContents* FromWebContents(content::WebContents* web_contents); - // Start rendering the contents in the prerendered state. If // |is_control_group| is true, this will go through some of the mechanics of // starting a prerender, without actually creating the RenderView. |bounds| @@ -210,15 +202,6 @@ // PrerenderManager's pending deletes list. void Destroy(FinalStatus reason); - // Called by the history tab helper with the information that it woudl have - // added to the history service had this web contents not been used for - // prerendering. - void DidNavigate(const history::HistoryAddPageArgs& add_page_args); - - // Applies all the URL history encountered during prerendering to the - // new tab. - void CommitHistory(content::WebContents* tab); - std::unique_ptr<base::DictionaryValue> GetAsValue() const; // Marks prerender as used and releases any throttled resource requests. @@ -238,8 +221,9 @@ mojo::PendingReceiver<prerender::mojom::PrerenderCanceler> receiver); protected: - PrerenderContents(PrerenderManager* prerender_manager, - Profile* profile, + PrerenderContents(std::unique_ptr<PrerenderContentsDelegate> delegate, + PrerenderManager* prerender_manager, + content::BrowserContext* browser_context, const GURL& url, const content::Referrer& referrer, const base::Optional<url::Origin>& initiator_origin, @@ -304,6 +288,9 @@ // The prerender manager owning this object. PrerenderManager* prerender_manager_; + // The delegate that content embedders use to override this class's logic. + std::unique_ptr<PrerenderContentsDelegate> delegate_; + // The URL being prerendered. GURL prerender_url_; @@ -314,8 +301,8 @@ // is browser initiated. base::Optional<url::Origin> initiator_origin_; - // The profile being used - Profile* profile_; + // The browser context being used + content::BrowserContext* browser_context_; content::NotificationRegistrar notification_registrar_; @@ -349,11 +336,6 @@ // The bounds of the WebView from the launching page. gfx::Rect bounds_; - typedef std::vector<history::HistoryAddPageArgs> AddPageVector; - - // Caches pages to be added to the history. - AddPageVector add_page_vector_; - // A running tally of the number of bytes this prerender has caused to be // transferred over the network for resources. Updated with AddNetworkBytes. int64_t network_bytes_;
diff --git a/chrome/browser/prerender/prerender_contents_delegate.h b/chrome/browser/prerender/prerender_contents_delegate.h new file mode 100644 index 0000000..df22257 --- /dev/null +++ b/chrome/browser/prerender/prerender_contents_delegate.h
@@ -0,0 +1,33 @@ +// Copyright 2020 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_PRERENDER_PRERENDER_CONTENTS_DELEGATE_H_ +#define CHROME_BROWSER_PRERENDER_PRERENDER_CONTENTS_DELEGATE_H_ + +#include "components/prerender/common/prerender_types.mojom.h" +#include "content/public/browser/render_frame_host.h" + +namespace content { +class WebContents; +} + +namespace prerender { + +// PrerenderContentsDelegate allows a content embedder to customize +// PrerenderContents logic. +class PrerenderContentsDelegate { + public: + virtual ~PrerenderContentsDelegate() = default; + + // Handle creation of new PrerenderContents. + virtual void OnPrerenderContentsCreated( + content::WebContents* web_contents) = 0; + + // Prepare for |web_contents| to no longer be PrerenderContents. + virtual void ReleasePrerenderContents(content::WebContents* web_contents) = 0; +}; + +} // namespace prerender + +#endif // CHROME_BROWSER_PRERENDER_PRERENDER_CONTENTS_DELEGATE_H_
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index e112b7c9..e5c55ba0 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc
@@ -32,11 +32,13 @@ #include "base/timer/elapsed_timer.h" #include "base/values.h" #include "chrome/browser/net/prediction_options.h" +#include "chrome/browser/predictors/loading_predictor.h" +#include "chrome/browser/predictors/loading_predictor_factory.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/prerender/prerender_field_trial.h" #include "chrome/browser/prerender/prerender_handle.h" #include "chrome/browser/prerender/prerender_manager_delegate.h" -#include "chrome/browser/prerender/prerender_manager_factory.h" #include "chrome/browser/prerender/prerender_tab_helper.h" #include "chrome/browser/prerender/prerender_util.h" #include "chrome/browser/profiles/profile.h" @@ -793,7 +795,8 @@ Origin origin) { DCHECK_CURRENTLY_ON(BrowserThread::UI); return base::WrapUnique(prerender_contents_factory_->CreatePrerenderContents( - this, profile_, url, referrer, initiator_origin, origin)); + std::make_unique<ChromePrerenderContentsDelegate>(), this, profile_, url, + referrer, initiator_origin, origin)); } void PrerenderManager::SortActivePrerenders() {
diff --git a/chrome/browser/prerender/prerender_test_utils.cc b/chrome/browser/prerender/prerender_test_utils.cc index 20136364..0ac1a9b 100644 --- a/chrome/browser/prerender/prerender_test_utils.cc +++ b/chrome/browser/prerender/prerender_test_utils.cc
@@ -137,15 +137,16 @@ TestPrerenderContents::TestPrerenderContents( PrerenderManager* prerender_manager, - Profile* profile, + content::BrowserContext* browser_context, const GURL& url, const content::Referrer& referrer, const base::Optional<url::Origin>& initiator_origin, Origin origin, FinalStatus expected_final_status, bool ignore_final_status) - : PrerenderContents(prerender_manager, - profile, + : PrerenderContents(std::make_unique<ChromePrerenderContentsDelegate>(), + prerender_manager, + browser_context, url, referrer, initiator_origin, @@ -388,8 +389,9 @@ } PrerenderContents* TestPrerenderContentsFactory::CreatePrerenderContents( + std::unique_ptr<PrerenderContentsDelegate> delegate, PrerenderManager* prerender_manager, - Profile* profile, + content::BrowserContext* browser_context, const GURL& url, const content::Referrer& referrer, const base::Optional<url::Origin>& initiator_origin, @@ -400,8 +402,8 @@ expected_contents_queue_.pop_front(); } TestPrerenderContents* contents = new TestPrerenderContents( - prerender_manager, profile, url, referrer, initiator_origin, origin, - expected.final_status, expected.ignore); + prerender_manager, browser_context, url, referrer, initiator_origin, + origin, expected.final_status, expected.ignore); if (expected.handle) expected.handle->OnPrerenderCreated(contents); return contents;
diff --git a/chrome/browser/prerender/prerender_test_utils.h b/chrome/browser/prerender/prerender_test_utils.h index 3c0b13c..5f6a0bd 100644 --- a/chrome/browser/prerender/prerender_test_utils.h +++ b/chrome/browser/prerender/prerender_test_utils.h
@@ -20,7 +20,9 @@ #include "base/synchronization/lock.h" #include "base/test/metrics/histogram_tester.h" #include "chrome/browser/external_protocol/external_protocol_handler.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" +#include "chrome/browser/prerender/prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/safe_browsing/test_safe_browsing_service.h" #include "chrome/test/base/in_process_browser_test.h" @@ -81,7 +83,7 @@ public content::RenderWidgetHostObserver { public: TestPrerenderContents(PrerenderManager* prerender_manager, - Profile* profile, + content::BrowserContext* browser_context, const GURL& url, const content::Referrer& referrer, const base::Optional<url::Origin>& initiator_origin, @@ -261,8 +263,9 @@ void IgnorePrerenderContents(); PrerenderContents* CreatePrerenderContents( + std::unique_ptr<PrerenderContentsDelegate> delegate, PrerenderManager* prerender_manager, - Profile* profile, + content::BrowserContext* browser_context, const GURL& url, const content::Referrer& referrer, const base::Optional<url::Origin>& initiator_origin,
diff --git a/chrome/browser/prerender/prerender_unittest.cc b/chrome/browser/prerender/prerender_unittest.cc index 1e73ab2..b9ef96d8 100644 --- a/chrome/browser/prerender/prerender_unittest.cc +++ b/chrome/browser/prerender/prerender_unittest.cc
@@ -309,7 +309,8 @@ Origin origin, const base::Optional<url::Origin>& initiator_origin, FinalStatus expected_final_status) - : PrerenderContents(test_prerender_manager, + : PrerenderContents(std::make_unique<ChromePrerenderContentsDelegate>(), + test_prerender_manager, nullptr, url, Referrer(),
diff --git a/chrome/browser/profiles/DEPS b/chrome/browser/profiles/DEPS new file mode 100644 index 0000000..0a1ba26 --- /dev/null +++ b/chrome/browser/profiles/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + "chrome_browser_main_extra_parts_profiles.cc": [ + # This is required to create the SiteDataCacheFacadeFactory when a profile + # is created. + "+chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.h" + ], +}
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc index ea3d371..6dc8c6a 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -110,8 +110,8 @@ #include "chrome/browser/feedback/feedback_uploader_factory_chrome.h" #include "chrome/browser/media/feeds/media_feeds_service_factory.h" #include "chrome/browser/metrics/desktop_session_duration/desktop_profile_session_durations_service_factory.h" +#include "chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.h" #include "chrome/browser/profiles/profile_theme_update_service_factory.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h" #include "chrome/browser/search/instant_service_factory.h" #include "chrome/browser/storage/storage_notification_service_factory.h" #include "chrome/browser/ui/global_error/global_error_service_factory.h" @@ -335,7 +335,7 @@ ProtocolHandlerRegistryFactory::GetInstance(); RendererUpdaterFactory::GetInstance(); #if !defined(OS_ANDROID) - resource_coordinator::LocalSiteCharacteristicsDataStoreFactory::GetInstance(); + performance_manager::SiteDataCacheFacadeFactory::GetInstance(); #endif #if BUILDFLAG(FULL_SAFE_BROWSING) safe_browsing::AdvancedProtectionStatusManagerFactory::GetInstance();
diff --git a/chrome/browser/profiles/profile_attributes_entry.cc b/chrome/browser/profiles/profile_attributes_entry.cc index c0d9664..6b79bd1c 100644 --- a/chrome/browser/profiles/profile_attributes_entry.cc +++ b/chrome/browser/profiles/profile_attributes_entry.cc
@@ -85,6 +85,19 @@ } // namespace +bool ProfileThemeColors::operator==(const ProfileThemeColors& other) const { + return std::tie(this->profile_highlight_color, + this->default_avatar_fill_color, + this->default_avatar_stroke_color) == + std::tie(other.profile_highlight_color, + other.default_avatar_fill_color, + other.default_avatar_stroke_color); +} + +bool ProfileThemeColors::operator!=(const ProfileThemeColors& other) const { + return !(*this == other); +} + const char ProfileAttributesEntry::kSupervisedUserId[] = "managed_user_id"; const char ProfileAttributesEntry::kIsOmittedFromProfileListKey[] = "is_omitted_from_profile_list";
diff --git a/chrome/browser/profiles/profile_attributes_entry.h b/chrome/browser/profiles/profile_attributes_entry.h index 1575109..36426b28 100644 --- a/chrome/browser/profiles/profile_attributes_entry.h +++ b/chrome/browser/profiles/profile_attributes_entry.h
@@ -46,6 +46,10 @@ SkColor profile_highlight_color; SkColor default_avatar_fill_color; SkColor default_avatar_stroke_color; + + // Equality operators for testing. + bool operator==(const ProfileThemeColors& other) const; + bool operator!=(const ProfileThemeColors& other) const; }; class ProfileAttributesEntry {
diff --git a/chrome/browser/profiles/profile_attributes_storage_unittest.cc b/chrome/browser/profiles/profile_attributes_storage_unittest.cc index 09ca6bd..19a97d2 100644 --- a/chrome/browser/profiles/profile_attributes_storage_unittest.cc +++ b/chrome/browser/profiles/profile_attributes_storage_unittest.cc
@@ -931,12 +931,7 @@ base::Optional<ProfileThemeColors> actual_colors = entry->GetProfileThemeColors(); ASSERT_TRUE(actual_colors.has_value()); - EXPECT_EQ(colors.profile_highlight_color, - actual_colors->profile_highlight_color); - EXPECT_EQ(colors.default_avatar_fill_color, - actual_colors->default_avatar_fill_color); - EXPECT_EQ(colors.default_avatar_stroke_color, - actual_colors->default_avatar_stroke_color); + EXPECT_EQ(colors, actual_colors); entry->SetProfileThemeColors(base::nullopt); EXPECT_EQ(base::nullopt, entry->GetProfileThemeColors());
diff --git a/chrome/browser/profiles/profile_theme_update_service_browsertest.cc b/chrome/browser/profiles/profile_theme_update_service_browsertest.cc new file mode 100644 index 0000000..f60ee2f --- /dev/null +++ b/chrome/browser/profiles/profile_theme_update_service_browsertest.cc
@@ -0,0 +1,85 @@ +// Copyright 2020 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/optional.h" +#include "chrome/browser/profiles/profile_theme_update_service.h" + +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/profiles/profile_attributes_entry.h" +#include "chrome/browser/profiles/profile_attributes_storage.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/themes/theme_service.h" +#include "chrome/browser/themes/theme_service_factory.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/ui_features.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/test/browser_test.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkColor.h" + +class ProfileThemeUpdateServiceBrowserTest : public InProcessBrowserTest { + public: + ProfileThemeUpdateServiceBrowserTest() { + feature_list_.InitAndEnableFeature(features::kNewProfilePicker); + } + + ProfileAttributesEntry* GetProfileAttributesEntry() { + ProfileAttributesEntry* entry; + CHECK(browser()); + CHECK(browser()->profile()); + CHECK(g_browser_process->profile_manager() + ->GetProfileAttributesStorage() + .GetProfileAttributesWithPath(browser()->profile()->GetPath(), + &entry)); + return entry; + } + + ThemeService* theme_service() { + return ThemeServiceFactory::GetForProfile(browser()->profile()); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +// Tests that the profile theme colors are updated when an autogenerated theme +// is set up. +IN_PROC_BROWSER_TEST_F(ProfileThemeUpdateServiceBrowserTest, + PRE_AutogeneratedTheme) { + EXPECT_FALSE( + GetProfileAttributesEntry()->GetProfileThemeColors().has_value()); + + theme_service()->BuildAutogeneratedThemeFromColor(SK_ColorDKGRAY); + base::Optional<ProfileThemeColors> theme_colors = + GetProfileAttributesEntry()->GetProfileThemeColors(); + EXPECT_TRUE(theme_colors.has_value()); + + // Check that a switch to another autogenerated theme updates the colors. + theme_service()->BuildAutogeneratedThemeFromColor(SK_ColorMAGENTA); + base::Optional<ProfileThemeColors> theme_colors2 = + GetProfileAttributesEntry()->GetProfileThemeColors(); + EXPECT_TRUE(theme_colors2.has_value()); + EXPECT_NE(theme_colors, theme_colors2); + + // Reset the cached colors to test that they're recreated on the next startup. + GetProfileAttributesEntry()->SetProfileThemeColors(base::nullopt); +} + +// Tests that the profile theme colors are updated on startup. +IN_PROC_BROWSER_TEST_F(ProfileThemeUpdateServiceBrowserTest, + AutogeneratedTheme) { + EXPECT_TRUE(GetProfileAttributesEntry()->GetProfileThemeColors().has_value()); +} + +// Tests that switching to the default theme resets the colors. +IN_PROC_BROWSER_TEST_F(ProfileThemeUpdateServiceBrowserTest, DefaultTheme) { + theme_service()->BuildAutogeneratedThemeFromColor(SK_ColorDKGRAY); + EXPECT_TRUE(GetProfileAttributesEntry()->GetProfileThemeColors().has_value()); + + theme_service()->UseDefaultTheme(); + EXPECT_FALSE( + GetProfileAttributesEntry()->GetProfileThemeColors().has_value()); +}
diff --git a/chrome/browser/push_messaging/push_messaging_app_identifier.cc b/chrome/browser/push_messaging/push_messaging_app_identifier.cc index b5d68923..a801aa85 100644 --- a/chrome/browser/push_messaging/push_messaging_app_identifier.cc +++ b/chrome/browser/push_messaging/push_messaging_app_identifier.cc
@@ -34,16 +34,16 @@ std::string FromTimeToString(base::Time time) { DCHECK(!time.is_null()); - return base::NumberToString(time.ToDeltaSinceWindowsEpoch().InSeconds()); + return base::NumberToString(time.ToDeltaSinceWindowsEpoch().InMilliseconds()); } bool FromStringToTime(const std::string& time_string, base::Optional<base::Time>* time) { DCHECK(!time_string.empty()); - int64_t seconds; - if (base::StringToInt64(time_string, &seconds) && seconds > 0) { + int64_t milliseconds; + if (base::StringToInt64(time_string, &milliseconds) && milliseconds > 0) { *time = base::make_optional(base::Time::FromDeltaSinceWindowsEpoch( - base::TimeDelta::FromSeconds(seconds))); + base::TimeDelta::FromMilliseconds(milliseconds))); return true; } return false; @@ -75,9 +75,8 @@ return false; *origin = GURL(parts[0]); - if (!origin->is_valid()) { + if (!origin->is_valid()) return false; - } if (parts.size() == 3) return FromStringToTime(parts[2], expiration_time);
diff --git a/chrome/browser/push_messaging/push_messaging_app_identifier.h b/chrome/browser/push_messaging/push_messaging_app_identifier.h index 3e48380a3..d7e9dac 100644 --- a/chrome/browser/push_messaging/push_messaging_app_identifier.h +++ b/chrome/browser/push_messaging/push_messaging_app_identifier.h
@@ -100,6 +100,10 @@ return service_worker_registration_id_; } + void set_expiration_time(const base::Optional<base::Time>& expiration_time) { + expiration_time_ = expiration_time; + } + base::Optional<base::Time> expiration_time() const { DCHECK(!is_null()); return expiration_time_;
diff --git a/chrome/browser/push_messaging/push_messaging_browsertest.cc b/chrome/browser/push_messaging/push_messaging_browsertest.cc index fa8645d..3e889aa 100644 --- a/chrome/browser/push_messaging/push_messaging_browsertest.cc +++ b/chrome/browser/push_messaging/push_messaging_browsertest.cc
@@ -2627,7 +2627,8 @@ : public PushMessagingBrowserTest { public: PushMessagingDisallowSenderIdsBrowserTest() { - scoped_feature_list_.InitAndEnableFeature(kPushMessagingDisallowSenderIDs); + scoped_feature_list_.InitAndEnableFeature( + features::kPushMessagingDisallowSenderIDs); } ~PushMessagingDisallowSenderIdsBrowserTest() override = default; @@ -2660,3 +2661,109 @@ "supported, please upgrade to VAPID authentication instead", script_result); } + +class PushSubscriptionWithExpirationTimeTest : public PushMessagingBrowserTest { + public: + PushSubscriptionWithExpirationTimeTest() { + scoped_feature_list_.InitAndEnableFeature( + features::kPushSubscriptionWithExpirationTime); + } + + ~PushSubscriptionWithExpirationTimeTest() override = default; + + // Checks whether |expiration_time| lies in the future and is in the + // valid format (seconds elapsed since Unix time) + bool IsExpirationTimeValid(const std::string& expiration_time); + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +bool PushSubscriptionWithExpirationTimeTest::IsExpirationTimeValid( + const std::string& expiration_time) { + int64_t output; + if (!base::StringToInt64(expiration_time, &output)) + return false; + return base::Time::Now().ToJsTimeIgnoringNull() < output; +} + +IN_PROC_BROWSER_TEST_F(PushSubscriptionWithExpirationTimeTest, + SubscribeGetSubscriptionWithExpirationTime) { + std::string script_result; + + ASSERT_TRUE(RunScript("registerServiceWorker()", &script_result)); + ASSERT_EQ("ok - service worker registered", script_result); + + ASSERT_NO_FATAL_FAILURE(RequestAndAcceptPermission()); + + LoadTestPage(); // Reload to become controlled. + + ASSERT_TRUE(RunScript("isControlled()", &script_result)); + ASSERT_EQ("true - is controlled", script_result); + + // Subscribe with expiration time enabled, should get a subscription with + // expiration time in the future back + std::string subscription_expiration_time; + ASSERT_TRUE(RunScript("documentSubscribePushGetExpirationTime()", + &subscription_expiration_time)); + EXPECT_TRUE(IsExpirationTimeValid(subscription_expiration_time)); + + std::string get_subscription_expiration_time; + // Get subscription should also yield a subscription with expiration time + ASSERT_TRUE(RunScript("GetSubscriptionExpirationTime()", + &get_subscription_expiration_time)); + EXPECT_TRUE(IsExpirationTimeValid(get_subscription_expiration_time)); + // Both methods should return the same expiration time + ASSERT_EQ(subscription_expiration_time, get_subscription_expiration_time); +} + +IN_PROC_BROWSER_TEST_F(PushSubscriptionWithExpirationTimeTest, + GetSubscriptionWithExpirationTime) { + std::string script_result; + + ASSERT_NO_FATAL_FAILURE(SubscribeSuccessfully()); + + ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); + EXPECT_EQ("true - subscribed", script_result); + + // Get subscription should also yield a subscription with expiration time + ASSERT_TRUE(RunScript("GetSubscriptionExpirationTime()", &script_result)); + EXPECT_TRUE(IsExpirationTimeValid(script_result)); +} + +class PushSubscriptionWithoutExpirationTimeTest + : public PushMessagingBrowserTest { + public: + PushSubscriptionWithoutExpirationTimeTest() { + // Override current feature list to ensure having + // |kPushSubscriptionWithExpirationTime| disabled + scoped_feature_list_.InitAndDisableFeature( + features::kPushSubscriptionWithExpirationTime); + } + + ~PushSubscriptionWithoutExpirationTimeTest() override = default; + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(PushSubscriptionWithoutExpirationTimeTest, + SubscribeDocumentExpirationTimeNull) { + std::string script_result; + + ASSERT_TRUE(RunScript("registerServiceWorker()", &script_result)); + ASSERT_EQ("ok - service worker registered", script_result); + + ASSERT_NO_FATAL_FAILURE(RequestAndAcceptPermission()); + + LoadTestPage(); // Reload to become controlled. + + ASSERT_TRUE(RunScript("isControlled()", &script_result)); + ASSERT_EQ("true - is controlled", script_result); + + // When |features::kPushSubscriptionWithExpirationTime| is disabled, + // expiration time should be null + ASSERT_TRUE( + RunScript("documentSubscribePushGetExpirationTime()", &script_result)); + EXPECT_EQ("null", script_result); +}
diff --git a/chrome/browser/push_messaging/push_messaging_constants.h b/chrome/browser/push_messaging/push_messaging_constants.h index f6c9e4bf..41094fdc 100644 --- a/chrome/browser/push_messaging/push_messaging_constants.h +++ b/chrome/browser/push_messaging/push_messaging_constants.h
@@ -5,10 +5,18 @@ #ifndef CHROME_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_CONSTANTS_H_ #define CHROME_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_CONSTANTS_H_ +#include "base/time/time.h" + extern const char kPushMessagingGcmEndpoint[]; // The tag of the notification that will be automatically shown if a webapp // receives a push message then fails to show a notification. extern const char kPushMessagingForcedNotificationTag[]; +// Chrome decided cadence on subscription refreshes. According to the standards: +// https://w3c.github.io/push-api/#dfn-subscription-expiration-time it is +// optional and set by the browser. +constexpr base::TimeDelta kPushSubscriptionExpirationPeriodTimeDelta = + base::TimeDelta::FromDays(90); + #endif // CHROME_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_CONSTANTS_H_
diff --git a/chrome/browser/push_messaging/push_messaging_features.cc b/chrome/browser/push_messaging/push_messaging_features.cc index 644b543c..11ad3a97 100644 --- a/chrome/browser/push_messaging/push_messaging_features.cc +++ b/chrome/browser/push_messaging/push_messaging_features.cc
@@ -4,5 +4,12 @@ #include "chrome/browser/push_messaging/push_messaging_features.h" +namespace features { + const base::Feature kPushMessagingDisallowSenderIDs{ "PushMessagingDisallowSenderIDs", base::FEATURE_DISABLED_BY_DEFAULT}; + +const base::Feature kPushSubscriptionWithExpirationTime{ + "PushSubscriptionWithExpirationTime", base::FEATURE_DISABLED_BY_DEFAULT}; + +} // namespace features
diff --git a/chrome/browser/push_messaging/push_messaging_features.h b/chrome/browser/push_messaging/push_messaging_features.h index 1dc1384..1bdc923 100644 --- a/chrome/browser/push_messaging/push_messaging_features.h +++ b/chrome/browser/push_messaging/push_messaging_features.h
@@ -7,7 +7,15 @@ #include "base/feature_list.h" +namespace features { + // Feature flag to disallow creation of push messages with GCM Sender IDs. extern const base::Feature kPushMessagingDisallowSenderIDs; +// Feature flag to enable push subscription with expiration times specified in +// /chrome/browser/push_messaging/push_messaging_constants.h +extern const base::Feature kPushSubscriptionWithExpirationTime; + +} // namespace features + #endif // CHROME_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_FEATURES_H_
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.cc b/chrome/browser/push_messaging/push_messaging_service_impl.cc index 4ae450ac..a8cf117 100644 --- a/chrome/browser/push_messaging/push_messaging_service_impl.cc +++ b/chrome/browser/push_messaging/push_messaging_service_impl.cc
@@ -55,6 +55,7 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/common/child_process_host.h" +#include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" #include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom.h" @@ -589,7 +590,7 @@ ContentSettingsType::NOTIFICATIONS, render_frame_host, requesting_origin, user_gesture, base::BindOnce(&PushMessagingServiceImpl::DoSubscribe, - weak_factory_.GetWeakPtr(), app_identifier, + weak_factory_.GetWeakPtr(), std::move(app_identifier), std::move(options), std::move(callback), render_process_id, render_frame_id)); } @@ -627,7 +628,8 @@ return; } - DoSubscribe(app_identifier, std::move(options), std::move(register_callback), + DoSubscribe(std::move(app_identifier), std::move(options), + std::move(register_callback), /* render_process_id= */ -1, /* render_frame_id= */ -1, CONTENT_SETTING_ALLOW); } @@ -653,7 +655,7 @@ } void PushMessagingServiceImpl::DoSubscribe( - const PushMessagingAppIdentifier& app_identifier, + PushMessagingAppIdentifier app_identifier, blink::mojom::PushSubscriptionOptionsPtr options, RegisterCallback register_callback, int render_process_id, @@ -679,7 +681,8 @@ content::RenderFrameHost* main_frame = GetMainFrameForRenderFrameHost(render_frame_host); - if (base::FeatureList::IsEnabled(kPushMessagingDisallowSenderIDs)) { + if (base::FeatureList::IsEnabled( + features::kPushMessagingDisallowSenderIDs)) { if (main_frame) { main_frame->AddMessageToConsole( blink::mojom::ConsoleMessageLevel::kError, @@ -698,11 +701,21 @@ IncreasePushSubscriptionCount(1, true /* is_pending */); + // Set time to live for GCM registration + base::TimeDelta ttl = base::TimeDelta(); + + if (base::FeatureList::IsEnabled( + features::kPushSubscriptionWithExpirationTime)) { + app_identifier.set_expiration_time( + base::Time::Now() + kPushSubscriptionExpirationPeriodTimeDelta); + DCHECK(app_identifier.expiration_time()); + ttl = kPushSubscriptionExpirationPeriodTimeDelta; + } + GetInstanceIDDriver() ->GetInstanceID(app_identifier.app_id()) ->GetToken(NormalizeSenderInfo(application_server_key_string), kGCMScope, - base::TimeDelta() /* time_to_live */, - std::map<std::string, std::string>() /* options */, + ttl, std::map<std::string, std::string>() /* options */, {} /* flags */, base::BindOnce(&PushMessagingServiceImpl::DidSubscribe, weak_factory_.GetWeakPtr(), app_identifier, @@ -714,12 +727,12 @@ RegisterCallback callback, const std::string& subscription_id, const GURL& endpoint, + const base::Optional<base::Time>& expiration_time, const std::vector<uint8_t>& p256dh, const std::vector<uint8_t>& auth, blink::mojom::PushRegistrationStatus status) { - std::move(callback).Run(subscription_id, endpoint, - base::nullopt /* expiration_time*/, p256dh, auth, - status); + std::move(callback).Run(subscription_id, endpoint, expiration_time, p256dh, + auth, status); } void PushMessagingServiceImpl::SubscribeEndWithError( @@ -727,6 +740,7 @@ blink::mojom::PushRegistrationStatus status) { SubscribeEnd(std::move(callback), std::string() /* subscription_id */, GURL::EmptyGURL() /* endpoint */, + base::nullopt /* expiration_time */, std::vector<uint8_t>() /* p256dh */, std::vector<uint8_t>() /* auth */, status); } @@ -793,6 +807,7 @@ IncreasePushSubscriptionCount(1, false /* is_pending */); SubscribeEnd(std::move(callback), subscription_id, endpoint, + app_identifier.expiration_time(), std::vector<uint8_t>(p256dh.begin(), p256dh.end()), std::vector<uint8_t>(auth_secret.begin(), auth_secret.end()), blink::mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE); @@ -800,8 +815,6 @@ // GetSubscriptionInfo methods ------------------------------------------------- -// TODO(crbug.com/1104215): Get |expiration_time| from |app_identifier|, where -// it is stored in profile preferences void PushMessagingServiceImpl::GetSubscriptionInfo( const GURL& origin, int64_t service_worker_registration_id, @@ -822,10 +835,12 @@ const GURL endpoint = CreateEndpoint(subscription_id); const std::string& app_id = app_identifier.app_id(); + base::Optional<base::Time> expiration_time = app_identifier.expiration_time(); + base::OnceCallback<void(bool)> validate_cb = base::BindOnce(&PushMessagingServiceImpl::DidValidateSubscription, weak_factory_.GetWeakPtr(), app_id, sender_id, endpoint, - std::move(callback)); + expiration_time, std::move(callback)); if (PushMessagingAppIdentifier::UseInstanceID(app_id)) { GetInstanceIDDriver()->GetInstanceID(app_id)->ValidateToken( @@ -842,6 +857,7 @@ const std::string& app_id, const std::string& sender_id, const GURL& endpoint, + const base::Optional<base::Time>& expiration_time, SubscriptionInfoCallback callback, bool is_valid) { if (!is_valid) { @@ -855,19 +871,20 @@ GetEncryptionInfoForAppId( app_id, sender_id, base::BindOnce(&PushMessagingServiceImpl::DidGetEncryptionInfo, - weak_factory_.GetWeakPtr(), endpoint, + weak_factory_.GetWeakPtr(), endpoint, expiration_time, std::move(callback))); } void PushMessagingServiceImpl::DidGetEncryptionInfo( const GURL& endpoint, + const base::Optional<base::Time>& expiration_time, SubscriptionInfoCallback callback, std::string p256dh, std::string auth_secret) const { // I/O errors might prevent the GCM Driver from retrieving a key-pair. bool is_valid = !p256dh.empty(); std::move(callback).Run( - is_valid, endpoint, base::nullopt /* expiration_time */, + is_valid, endpoint, expiration_time, std::vector<uint8_t>(p256dh.begin(), p256dh.end()), std::vector<uint8_t>(auth_secret.begin(), auth_secret.end())); }
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.h b/chrome/browser/push_messaging/push_messaging_service_impl.h index 6572ceb..9056f929 100644 --- a/chrome/browser/push_messaging/push_messaging_service_impl.h +++ b/chrome/browser/push_messaging/push_messaging_service_impl.h
@@ -16,6 +16,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" +#include "base/time/time.h" #include "chrome/browser/push_messaging/push_messaging_notification_manager.h" #include "chrome/common/buildflags.h" #include "components/content_settings/core/browser/content_settings_observer.h" @@ -165,7 +166,7 @@ // Subscribe methods --------------------------------------------------------- - void DoSubscribe(const PushMessagingAppIdentifier& app_identifier, + void DoSubscribe(PushMessagingAppIdentifier app_identifier, blink::mojom::PushSubscriptionOptionsPtr options, RegisterCallback callback, int render_process_id, @@ -175,6 +176,7 @@ void SubscribeEnd(RegisterCallback callback, const std::string& subscription_id, const GURL& endpoint, + const base::Optional<base::Time>& expiration_time, const std::vector<uint8_t>& p256dh, const std::vector<uint8_t>& auth, blink::mojom::PushRegistrationStatus status); @@ -198,13 +200,16 @@ // GetSubscriptionInfo methods ----------------------------------------------- - void DidValidateSubscription(const std::string& app_id, - const std::string& sender_id, - const GURL& endpoint, - SubscriptionInfoCallback callback, - bool is_valid); + void DidValidateSubscription( + const std::string& app_id, + const std::string& sender_id, + const GURL& endpoint, + const base::Optional<base::Time>& expiration_time, + SubscriptionInfoCallback callback, + bool is_valid); void DidGetEncryptionInfo(const GURL& endpoint, + const base::Optional<base::Time>& expiration_time, SubscriptionInfoCallback callback, std::string p256dh, std::string auth_secret) const;
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 34c88da..7b1ef11 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1216,6 +1216,10 @@ menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); + // Place QR Generator close to send-tab-to-self feature for link images. + if (params_.has_image_contents) + AppendQRCodeGeneratorItem(/*for_image=*/true, /*draw_icon=*/true); + if (browser && send_tab_to_self::ShouldOfferFeatureForLink( active_web_contents, params_.link_url)) { if (send_tab_to_self::GetValidDeviceCount(GetBrowser()->profile()) == 1) { @@ -1353,6 +1357,10 @@ IDS_CONTENT_CONTEXT_COPYIMAGE); menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYIMAGELOCATION, IDS_CONTENT_CONTEXT_COPYIMAGELOCATION); + + // Don't double-add for linked images, which also add the item. + if (params_.link_url.is_empty()) + AppendQRCodeGeneratorItem(/*for_image=*/true, /*draw_icon=*/false); } void RenderViewContextMenu::AppendSearchWebForImageItems() { @@ -1497,15 +1505,7 @@ if (!send_tab_to_self_menu_present) menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); -#if defined(OS_MAC) - menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_GENERATE_QR_CODE, - IDS_CONTEXT_MENU_GENERATE_QR_CODE_PAGE); -#else - menu_model_.AddItemWithStringIdAndIcon( - IDC_CONTENT_CONTEXT_GENERATE_QR_CODE, - IDS_CONTEXT_MENU_GENERATE_QR_CODE_PAGE, - ui::ImageModel::FromVectorIcon(kQrcodeGeneratorIcon)); -#endif + AppendQRCodeGeneratorItem(/*for_image=*/false, /*draw_icon=*/true); menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); } else if (send_tab_to_self_menu_present) { @@ -2265,9 +2265,17 @@ GetBrowser()->tab_strip_model()->GetActiveWebContents(); auto* bubble_controller = qrcode_generator::QRCodeGeneratorBubbleController::Get(web_contents); - NavigationEntry* entry = - embedder_web_contents_->GetController().GetLastCommittedEntry(); - bubble_controller->ShowBubble(entry->GetURL()); + if (params_.media_type == ContextMenuDataMediaType::kImage) { + base::RecordAction( + UserMetricsAction("SharingQRCode.DialogLaunched.ContextMenuImage")); + bubble_controller->ShowBubble(params_.src_url); + } else { + base::RecordAction( + UserMetricsAction("SharingQRCode.DialogLaunched.ContextMenuPage")); + NavigationEntry* entry = + embedder_web_contents_->GetController().GetLastCommittedEntry(); + bubble_controller->ShowBubble(entry->GetURL()); + } break; } @@ -2639,6 +2647,25 @@ IsGeneratorAvailable(entry->GetURL(), incognito); } +void RenderViewContextMenu::AppendQRCodeGeneratorItem(bool for_image, + bool draw_icon) { + if (!IsQRCodeGeneratorEnabled()) + return; + auto string_id = for_image ? IDS_CONTEXT_MENU_GENERATE_QR_CODE_IMAGE + : IDS_CONTEXT_MENU_GENERATE_QR_CODE_PAGE; +#if defined(OS_MAC) + draw_icon = false; +#endif + if (draw_icon) { + menu_model_.AddItemWithStringIdAndIcon( + IDC_CONTENT_CONTEXT_GENERATE_QR_CODE, string_id, + ui::ImageModel::FromVectorIcon(kQrcodeGeneratorIcon)); + } else { + menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_GENERATE_QR_CODE, + string_id); + } +} + bool RenderViewContextMenu::IsRouteMediaEnabled() const { if (!media_router::MediaRouterEnabled(browser_context_)) return false;
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.h b/chrome/browser/renderer_context_menu/render_view_context_menu.h index 4915817..93b1df8 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.h +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -193,6 +193,7 @@ void AppendSharingItems(); void AppendClickToCallItem(); void AppendSharedClipboardItem(); + void AppendQRCodeGeneratorItem(bool for_image, bool draw_icon); // Command enabled query functions. bool IsReloadEnabled() const;
diff --git a/chrome/browser/renderer_host/chrome_navigation_ui_data.cc b/chrome/browser/renderer_host/chrome_navigation_ui_data.cc index d58691a8..a71c780 100644 --- a/chrome/browser/renderer_host/chrome_navigation_ui_data.cc +++ b/chrome/browser/renderer_host/chrome_navigation_ui_data.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/renderer_host/chrome_navigation_ui_data.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "components/prerender/browser/prerender_histograms.h" #include "content/public/browser/navigation_handle.h" @@ -35,7 +36,7 @@ #endif auto* prerender_contents = - prerender::PrerenderContents::FromWebContents(web_contents); + prerender::ChromePrerenderContentsDelegate::FromWebContents(web_contents); if (prerender_contents) { prerender_mode_ = prerender_contents->prerender_mode(); prerender_histogram_prefix_ =
diff --git a/chrome/browser/resource_coordinator/leveldb_site_characteristics_database.cc b/chrome/browser/resource_coordinator/leveldb_site_characteristics_database.cc deleted file mode 100644 index 95c866a..0000000 --- a/chrome/browser/resource_coordinator/leveldb_site_characteristics_database.cc +++ /dev/null
@@ -1,491 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/leveldb_site_characteristics_database.h" - -#include <limits> -#include <string> - -#include "base/bind.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/memory/ptr_util.h" -#include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" -#include "base/strings/string_number_conversions.h" -#include "base/task_runner_util.h" -#include "base/threading/scoped_blocking_call.h" -#include "build/build_config.h" -#include "chrome/browser/resource_coordinator/utils.h" -#include "third_party/leveldatabase/env_chromium.h" -#include "third_party/leveldatabase/leveldb_chrome.h" -#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" - -namespace resource_coordinator { - -namespace { - -const char kInitStatusHistogramLabel[] = - "ResourceCoordinator.LocalDB.DatabaseInit"; -const char kInitStatusAfterRepairHistogramLabel[] = - "ResourceCoordinator.LocalDB.DatabaseInitAfterRepair"; -const char kInitStatusAfterDeleteHistogramLabel[] = - "ResourceCoordinator.LocalDB.DatabaseInitAfterDelete"; - -enum class InitStatus { - kInitStatusOk, - kInitStatusCorruption, - kInitStatusIOError, - kInitStatusUnknownError, - kInitStatusMax -}; - -// Report the database's initialization status metrics. -void ReportInitStatus(const char* histogram_name, - const leveldb::Status& status) { - if (status.ok()) { - base::UmaHistogramEnumeration(histogram_name, InitStatus::kInitStatusOk, - InitStatus::kInitStatusMax); - } else if (status.IsCorruption()) { - base::UmaHistogramEnumeration(histogram_name, - InitStatus::kInitStatusCorruption, - InitStatus::kInitStatusMax); - } else if (status.IsIOError()) { - base::UmaHistogramEnumeration(histogram_name, - InitStatus::kInitStatusIOError, - InitStatus::kInitStatusMax); - } else { - base::UmaHistogramEnumeration(histogram_name, - InitStatus::kInitStatusUnknownError, - InitStatus::kInitStatusMax); - } -} - -// Attempt to repair the database stored in |db_path|. -bool RepairDatabase(const std::string& db_path) { - leveldb_env::Options options; - options.reuse_logs = false; - options.max_open_files = 0; - bool repair_succeeded = leveldb::RepairDB(db_path, options).ok(); - UMA_HISTOGRAM_BOOLEAN("ResourceCoordinator.LocalDB.DatabaseRepair", - repair_succeeded); - return repair_succeeded; -} - -bool ShouldAttemptDbRepair(const leveldb::Status& status) { - // A corrupt database might be repaired (some data might be loss but it's - // better than losing everything). - if (status.IsCorruption()) - return true; - // An I/O error might be caused by a missing manifest, it's sometime possible - // to repair this (some data might be loss). - if (status.IsIOError()) - return true; - - return false; -} - -struct DatabaseSizeResult { - base::Optional<int64_t> num_rows; - base::Optional<int64_t> on_disk_size_kb; -}; - -} // namespace - -// Version history: -// -// - {no version}: -// - Initial launch of the Database. -// - 1: -// - Ignore the title/favicon events happening during the first fews seconds -// after a tab being loaded. -// - Ignore the audio events happening during the first fews seconds after a -// tab being backgrounded. -// - 2: -// - Ignore events that happen shortly after a tab is backgrounded. This is -// because such events are likely a response to a recent user action -// rather than an attempt from the tab to communicate in background. -// See https://crbug.com/1865601. -// -// Transform logic: -// - From any version to v1: The database is erased entirely. -// - From any version to v2: The database is erased entirely. -const size_t LevelDBSiteCharacteristicsDatabase::kDbVersion = 2U; - -const char LevelDBSiteCharacteristicsDatabase::kDbMetadataKey[] = - "database_metadata"; - -// Helper class used to run all the blocking operations posted by -// LocalSiteCharacteristicDatabase on a ThreadPool sequence with the -// |MayBlock()| trait. -// -// Instances of this class should only be destructed once all the posted tasks -// have been run, in practice it means that they should ideally be stored in a -// std::unique_ptr<AsyncHelper, base::OnTaskRunnerDeleter>. -class LevelDBSiteCharacteristicsDatabase::AsyncHelper { - public: - explicit AsyncHelper(const base::FilePath& db_path) : db_path_(db_path) { - DETACH_FROM_SEQUENCE(sequence_checker_); - // Setting |sync| to false might cause some data loss if the system crashes - // but it'll make the write operations faster (no data will be lost if only - // the process crashes). - write_options_.sync = false; - } - ~AsyncHelper() = default; - - // Open the database from |db_path_| after creating it if it didn't exist, - // this reset the database if it's not at the expected version. - void OpenOrCreateDatabase(); - - // Implementations of the DB manipulation functions of - // LevelDBSiteCharacteristicsDatabase that run on a blocking sequence. - base::Optional<SiteDataProto> ReadSiteCharacteristicsFromDB( - const url::Origin& origin); - void WriteSiteCharacteristicsIntoDB( - const url::Origin& origin, - const SiteDataProto& site_characteristic_proto); - void RemoveSiteCharacteristicsFromDB( - const std::vector<url::Origin>& site_origin); - void ClearDatabase(); - // Returns a struct with unset fields on failure. - DatabaseSizeResult GetDatabaseSize(); - - bool DBIsInitialized() { return db_ != nullptr; } - - leveldb::DB* GetDBForTesting() { - DCHECK(DBIsInitialized()); - return db_.get(); - } - - private: - enum class OpeningType { - // A new database has been created. - kNewDb, - // An existing database has been used. - kExistingDb, - }; - - // Implementation for the OpenOrCreateDatabase function. - OpeningType OpenOrCreateDatabaseImpl(); - - // The on disk location of the database. - const base::FilePath db_path_; - // The connection to the LevelDB database. - std::unique_ptr<leveldb::DB> db_; - // The options to be used for all database read operations. - leveldb::ReadOptions read_options_; - // The options to be used for all database write operations. - leveldb::WriteOptions write_options_; - - SEQUENCE_CHECKER(sequence_checker_); - DISALLOW_COPY_AND_ASSIGN(AsyncHelper); -}; - -void LevelDBSiteCharacteristicsDatabase::AsyncHelper::OpenOrCreateDatabase() { - OpeningType opening_type = OpenOrCreateDatabaseImpl(); - if (!db_) - return; - std::string db_metadata; - leveldb::Status s = db_->Get( - read_options_, LevelDBSiteCharacteristicsDatabase::kDbMetadataKey, - &db_metadata); - bool is_expected_version = false; - if (s.ok()) { - // The metadata only contains the version of the database as a size_t value - // for now. - size_t version = std::numeric_limits<size_t>::max(); - CHECK(base::StringToSizeT(db_metadata, &version)); - if (version == LevelDBSiteCharacteristicsDatabase::kDbVersion) - is_expected_version = true; - } - // TODO(sebmarchand): Add a migration engine rather than flushing the database - // for every version change, https://crbug.com/866540. - if ((opening_type == OpeningType::kExistingDb) && !is_expected_version) { - DLOG(ERROR) << "Invalid DB version, recreating it."; - ClearDatabase(); - // The database might fail to open. - if (!db_) - return; - opening_type = OpeningType::kNewDb; - } - if (opening_type == OpeningType::kNewDb) { - std::string metadata = - base::NumberToString(LevelDBSiteCharacteristicsDatabase::kDbVersion); - s = db_->Put(write_options_, - LevelDBSiteCharacteristicsDatabase::kDbMetadataKey, - metadata); - if (!s.ok()) { - DLOG(ERROR) << "Error while inserting the metadata in the site " - << "characteristics database: " << s.ToString(); - } - } -} - -base::Optional<SiteDataProto> -LevelDBSiteCharacteristicsDatabase::AsyncHelper::ReadSiteCharacteristicsFromDB( - const url::Origin& origin) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (!db_) - return base::nullopt; - - leveldb::Status s; - std::string protobuf_value; - { - base::ScopedBlockingCall scoped_blocking_call( - FROM_HERE, base::BlockingType::MAY_BLOCK); - s = db_->Get(read_options_, SerializeOriginIntoDatabaseKey(origin), - &protobuf_value); - } - base::Optional<SiteDataProto> site_characteristic_proto; - if (s.ok()) { - site_characteristic_proto = SiteDataProto(); - if (!site_characteristic_proto->ParseFromString(protobuf_value)) { - site_characteristic_proto = base::nullopt; - DLOG(ERROR) << "Error while trying to parse a SiteDataProto " - << "protobuf."; - } - } - return site_characteristic_proto; -} - -void LevelDBSiteCharacteristicsDatabase::AsyncHelper:: - WriteSiteCharacteristicsIntoDB( - const url::Origin& origin, - const SiteDataProto& site_characteristic_proto) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (!db_) - return; - - leveldb::Status s; - { - base::ScopedBlockingCall scoped_blocking_call( - FROM_HERE, base::BlockingType::MAY_BLOCK); - s = db_->Put(write_options_, SerializeOriginIntoDatabaseKey(origin), - site_characteristic_proto.SerializeAsString()); - } - - if (!s.ok()) { - DLOG(ERROR) - << "Error while inserting an element in the site characteristics " - << "database: " << s.ToString(); - } -} - -void LevelDBSiteCharacteristicsDatabase::AsyncHelper:: - RemoveSiteCharacteristicsFromDB( - const std::vector<url::Origin>& site_origins) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (!db_) - return; - - base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, - base::BlockingType::MAY_BLOCK); - leveldb::WriteBatch batch; - for (const auto& iter : site_origins) - batch.Delete(SerializeOriginIntoDatabaseKey(iter)); - leveldb::Status status = db_->Write(write_options_, &batch); - if (!status.ok()) { - LOG(WARNING) << "Failed to remove some entries from the site " - << "characteristics database: " << status.ToString(); - } -} - -void LevelDBSiteCharacteristicsDatabase::AsyncHelper::ClearDatabase() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!db_) - return; - - base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, - base::BlockingType::MAY_BLOCK); - db_.reset(); - leveldb_env::Options options; - leveldb::Status status = leveldb::DestroyDB(db_path_.AsUTF8Unsafe(), options); - if (status.ok()) { - OpenOrCreateDatabaseImpl(); - } else { - LOG(WARNING) << "Failed to destroy the site characteristics database: " - << status.ToString(); - } -} - -DatabaseSizeResult -LevelDBSiteCharacteristicsDatabase::AsyncHelper::GetDatabaseSize() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!db_) - return DatabaseSizeResult(); - - base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, - base::BlockingType::MAY_BLOCK); - DatabaseSizeResult ret; -#if defined(OS_WIN) - // Windows has an annoying mis-feature that the size of an open file is not - // written to the parent directory until the file is closed. Since this is a - // diagnostic interface that should be rarely called, go to the trouble of - // closing and re-opening the database in order to get an up-to date size to - // report. - db_.reset(); -#endif - ret.on_disk_size_kb = base::ComputeDirectorySize(db_path_) / 1024; -#if defined(OS_WIN) - OpenOrCreateDatabase(); - if (!db_) - return DatabaseSizeResult(); -#endif - - // Default read options will fill the cache as we go. - std::unique_ptr<leveldb::Iterator> iterator( - db_->NewIterator(leveldb::ReadOptions())); - int64_t num_rows = 0; - for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) - ++num_rows; - - ret.num_rows = num_rows; - return ret; -} - -LevelDBSiteCharacteristicsDatabase::AsyncHelper::OpeningType -LevelDBSiteCharacteristicsDatabase::AsyncHelper::OpenOrCreateDatabaseImpl() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!db_) << "Database already open"; - base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, - base::BlockingType::MAY_BLOCK); - - OpeningType opening_type = OpeningType::kNewDb; - - // Report the on disk size of the database if it already exists. - if (base::DirectoryExists(db_path_)) { - opening_type = OpeningType::kExistingDb; - int64_t db_ondisk_size_in_bytes = base::ComputeDirectorySize(db_path_); - UMA_HISTOGRAM_MEMORY_KB("ResourceCoordinator.LocalDB.OnDiskSize", - db_ondisk_size_in_bytes / 1024); - } - - leveldb_env::Options options; - options.create_if_missing = true; - leveldb::Status status = - leveldb_env::OpenDB(options, db_path_.AsUTF8Unsafe(), &db_); - - ReportInitStatus(kInitStatusHistogramLabel, status); - - if (status.ok()) - return opening_type; - - if (!ShouldAttemptDbRepair(status)) - return opening_type; - - if (RepairDatabase(db_path_.AsUTF8Unsafe())) { - status = leveldb_env::OpenDB(options, db_path_.AsUTF8Unsafe(), &db_); - ReportInitStatus(kInitStatusAfterRepairHistogramLabel, status); - if (status.ok()) - return opening_type; - } - - // Delete the database and try to open it one last time. - if (leveldb_chrome::DeleteDB(db_path_, options).ok()) { - status = leveldb_env::OpenDB(options, db_path_.AsUTF8Unsafe(), &db_); - ReportInitStatus(kInitStatusAfterDeleteHistogramLabel, status); - if (!status.ok()) - db_.reset(); - } - - return opening_type; -} - -LevelDBSiteCharacteristicsDatabase::LevelDBSiteCharacteristicsDatabase( - const base::FilePath& db_path) - : blocking_task_runner_(base::ThreadPool::CreateSequencedTaskRunner( - // The |BLOCK_SHUTDOWN| trait is required to ensure that a clearing of - // the database won't be skipped. - {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN})), - async_helper_(new AsyncHelper(db_path), - base::OnTaskRunnerDeleter(blocking_task_runner_)) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - blocking_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&LevelDBSiteCharacteristicsDatabase:: - AsyncHelper::OpenOrCreateDatabase, - base::Unretained(async_helper_.get()))); -} - -LevelDBSiteCharacteristicsDatabase::~LevelDBSiteCharacteristicsDatabase() = - default; - -void LevelDBSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDB( - const url::Origin& origin, - LocalSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDBCallback - callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // Trigger the asynchronous task and make it run the callback on this thread - // once it returns. - base::PostTaskAndReplyWithResult( - blocking_task_runner_.get(), FROM_HERE, - base::BindOnce(&LevelDBSiteCharacteristicsDatabase::AsyncHelper:: - ReadSiteCharacteristicsFromDB, - base::Unretained(async_helper_.get()), origin), - base::BindOnce(std::move(callback))); -} - -void LevelDBSiteCharacteristicsDatabase::WriteSiteCharacteristicsIntoDB( - const url::Origin& origin, - const SiteDataProto& site_characteristic_proto) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - blocking_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&LevelDBSiteCharacteristicsDatabase:: - AsyncHelper::WriteSiteCharacteristicsIntoDB, - base::Unretained(async_helper_.get()), origin, - std::move(site_characteristic_proto))); -} - -void LevelDBSiteCharacteristicsDatabase::RemoveSiteCharacteristicsFromDB( - const std::vector<url::Origin>& site_origins) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - blocking_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&LevelDBSiteCharacteristicsDatabase::AsyncHelper:: - RemoveSiteCharacteristicsFromDB, - base::Unretained(async_helper_.get()), - std::move(site_origins))); -} - -void LevelDBSiteCharacteristicsDatabase::ClearDatabase() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - blocking_task_runner_->PostTask( - FROM_HERE, - base::BindOnce( - &LevelDBSiteCharacteristicsDatabase::AsyncHelper::ClearDatabase, - base::Unretained(async_helper_.get()))); -} - -void LevelDBSiteCharacteristicsDatabase::GetDatabaseSize( - GetDatabaseSizeCallback callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // Adapt the callback with a lambda to allow using PostTaskAndReplyWithResult. - auto reply_callback = base::BindOnce( - [](GetDatabaseSizeCallback callback, const DatabaseSizeResult& result) { - std::move(callback).Run(result.num_rows, result.on_disk_size_kb); - }, - std::move(callback)); - - base::PostTaskAndReplyWithResult( - blocking_task_runner_.get(), FROM_HERE, - base::BindOnce( - &LevelDBSiteCharacteristicsDatabase::AsyncHelper::GetDatabaseSize, - base::Unretained(async_helper_.get())), - std::move(reply_callback)); -} - -bool LevelDBSiteCharacteristicsDatabase::DatabaseIsInitializedForTesting() { - return async_helper_->DBIsInitialized(); -} - -leveldb::DB* LevelDBSiteCharacteristicsDatabase::GetDBForTesting() { - return async_helper_->GetDBForTesting(); -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/leveldb_site_characteristics_database.h b/chrome/browser/resource_coordinator/leveldb_site_characteristics_database.h deleted file mode 100644 index 092c4ef..0000000 --- a/chrome/browser/resource_coordinator/leveldb_site_characteristics_database.h +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LEVELDB_SITE_CHARACTERISTICS_DATABASE_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_LEVELDB_SITE_CHARACTERISTICS_DATABASE_H_ - -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/sequence_checker.h" -#include "base/sequenced_task_runner.h" -#include "base/task/post_task.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_database.h" -#include "third_party/leveldatabase/src/include/leveldb/db.h" - -namespace resource_coordinator { - -// Manages a LevelDB database used by a site characteristic data store. -// TODO(sebmarchand): -// - Constraint the size of the database: Use a background task to trim the -// database if it becomes too big and ensure that this fail nicely when the -// disk is full. -// - Batch the write operations to reduce the number of I/O events. -// -// All the DB operations are done asynchronously on a sequence allowed to do -// I/O operations. -class LevelDBSiteCharacteristicsDatabase - : public LocalSiteCharacteristicsDatabase { - public: - explicit LevelDBSiteCharacteristicsDatabase(const base::FilePath& db_path); - - ~LevelDBSiteCharacteristicsDatabase() override; - - // LocalSiteCharacteristicDatabase: - void ReadSiteCharacteristicsFromDB( - const url::Origin& origin, - LocalSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDBCallback - callback) override; - void WriteSiteCharacteristicsIntoDB( - const url::Origin& origin, - const SiteDataProto& site_characteristic_proto) override; - void RemoveSiteCharacteristicsFromDB( - const std::vector<url::Origin>& site_origins) override; - void ClearDatabase() override; - void GetDatabaseSize(GetDatabaseSizeCallback callback) override; - - bool DatabaseIsInitializedForTesting(); - - // Returns a raw pointer to the database for testing purposes. Note that as - // the DB operations are made on a separate sequence it's recommended to call - // TaskEnvironment::RunUntilIdle before calling this function to ensure - // that the database has been fully initialized. The LevelDB implementation is - // thread safe. - leveldb::DB* GetDBForTesting(); - - static const size_t kDbVersion; - static const char kDbMetadataKey[]; - - private: - class AsyncHelper; - - // The task runner used to run all the blocking operations. - const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; - - // Helper object that should be used to trigger all the operations that need - // to run on |blocking_task_runner_|, it is guaranteed that the AsyncHelper - // held by this object will only be destructed once all the tasks that have - // been posted to it have completed. - std::unique_ptr<AsyncHelper, base::OnTaskRunnerDeleter> async_helper_; - - SEQUENCE_CHECKER(sequence_checker_); - - DISALLOW_COPY_AND_ASSIGN(LevelDBSiteCharacteristicsDatabase); -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_LEVELDB_SITE_CHARACTERISTICS_DATABASE_H_
diff --git a/chrome/browser/resource_coordinator/leveldb_site_characteristics_database_unittest.cc b/chrome/browser/resource_coordinator/leveldb_site_characteristics_database_unittest.cc deleted file mode 100644 index d0a39aad..0000000 --- a/chrome/browser/resource_coordinator/leveldb_site_characteristics_database_unittest.cc +++ /dev/null
@@ -1,305 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/leveldb_site_characteristics_database.h" - -#include <limits> - -#include "base/bind.h" -#include "base/files/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/test/bind_test_util.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/test/task_environment.h" -#include "base/test/test_file_util.h" -#include "build/build_config.h" -#include "components/performance_manager/persistence/site_data/site_data.pb.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/leveldatabase/leveldb_chrome.h" -#include "url/gurl.h" - -namespace resource_coordinator { - -namespace { - -class ScopedReadOnlyDirectory { - public: - explicit ScopedReadOnlyDirectory(const base::FilePath& root_dir); - ~ScopedReadOnlyDirectory() { - permission_restorer_.reset(); - EXPECT_TRUE(base::DeletePathRecursively(read_only_path_)); - } - - const base::FilePath& GetReadOnlyPath() { return read_only_path_; } - - private: - base::FilePath read_only_path_; - std::unique_ptr<base::FilePermissionRestorer> permission_restorer_; -}; - -ScopedReadOnlyDirectory::ScopedReadOnlyDirectory( - const base::FilePath& root_dir) { - EXPECT_TRUE(base::CreateTemporaryDirInDir( - root_dir, FILE_PATH_LITERAL("read_only_path"), &read_only_path_)); - permission_restorer_ = - std::make_unique<base::FilePermissionRestorer>(read_only_path_); -#if defined(OS_WIN) - base::DenyFilePermission(read_only_path_, GENERIC_WRITE); -#else // defined(OS_WIN) - EXPECT_TRUE(base::MakeFileUnwritable(read_only_path_)); -#endif - EXPECT_FALSE(base::PathIsWritable(read_only_path_)); -} - -// Initialize a SiteDataProto object with a test value (the same -// value is used to initialize all fields). -void InitSiteCharacteristicProto(SiteDataProto* proto, - ::google::protobuf::int64 test_value) { - proto->set_last_loaded(test_value); - - SiteDataFeatureProto feature_proto; - feature_proto.set_observation_duration(test_value); - feature_proto.set_use_timestamp(test_value); - - proto->mutable_updates_favicon_in_background()->CopyFrom(feature_proto); - proto->mutable_updates_title_in_background()->CopyFrom(feature_proto); - proto->mutable_uses_audio_in_background()->CopyFrom(feature_proto); -} - -} // namespace - -class LevelDBSiteCharacteristicsDatabaseTest : public ::testing::Test { - public: - LevelDBSiteCharacteristicsDatabaseTest() {} - - void SetUp() override { - EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); - OpenDB(); - } - - void TearDown() override { - db_.reset(); - WaitForAsyncOperationsToComplete(); - EXPECT_TRUE(temp_dir_.Delete()); - } - - void OpenDB() { - OpenDB(temp_dir_.GetPath().Append(FILE_PATH_LITERAL("LocalDB"))); - } - - void OpenDB(base::FilePath path) { - db_ = std::make_unique<LevelDBSiteCharacteristicsDatabase>(path); - WaitForAsyncOperationsToComplete(); - EXPECT_TRUE(db_); - db_path_ = path; - } - - const base::FilePath& GetTempPath() { return temp_dir_.GetPath(); } - const base::FilePath& GetDBPath() { return db_path_; } - - protected: - // Try to read an entry from the database, returns true if the entry is - // present and false otherwise. |receiving_proto| will receive the protobuf - // corresponding to this entry on success. - bool ReadFromDB(const url::Origin& origin, SiteDataProto* receiving_proto) { - EXPECT_TRUE(receiving_proto); - bool success = false; - auto init_callback = base::BindOnce( - [](SiteDataProto* receiving_proto, bool* success, - base::Optional<SiteDataProto> proto_opt) { - *success = proto_opt.has_value(); - if (proto_opt) - receiving_proto->CopyFrom(proto_opt.value()); - }, - base::Unretained(receiving_proto), base::Unretained(&success)); - db_->ReadSiteCharacteristicsFromDB(origin, std::move(init_callback)); - WaitForAsyncOperationsToComplete(); - return success; - } - - // Add some entries to the database and returns a vector with their origins. - std::vector<url::Origin> AddDummyEntriesToDB(size_t num_entries) { - std::vector<url::Origin> site_origins; - for (size_t i = 0; i < num_entries; ++i) { - SiteDataProto proto_temp; - std::string origin_str = base::StringPrintf("http://%zu.com", i); - InitSiteCharacteristicProto(&proto_temp, - static_cast<::google::protobuf::int64>(i)); - EXPECT_TRUE(proto_temp.IsInitialized()); - url::Origin origin = url::Origin::Create(GURL(origin_str)); - db_->WriteSiteCharacteristicsIntoDB(origin, proto_temp); - site_origins.emplace_back(origin); - } - WaitForAsyncOperationsToComplete(); - return site_origins; - } - - void WaitForAsyncOperationsToComplete() { task_env_.RunUntilIdle(); } - - const url::Origin kDummyOrigin = url::Origin::Create(GURL("http://foo.com")); - - base::FilePath db_path_; - base::test::TaskEnvironment task_env_; - base::ScopedTempDir temp_dir_; - std::unique_ptr<LevelDBSiteCharacteristicsDatabase> db_; -}; - -TEST_F(LevelDBSiteCharacteristicsDatabaseTest, InitAndStoreSiteCharacteristic) { - // Initializing an entry that doesn't exist in the database should fail. - SiteDataProto early_read_proto; - EXPECT_FALSE(ReadFromDB(kDummyOrigin, &early_read_proto)); - - // Add an entry to the database and make sure that we can read it back. - ::google::protobuf::int64 test_value = 42; - SiteDataProto stored_proto; - InitSiteCharacteristicProto(&stored_proto, test_value); - db_->WriteSiteCharacteristicsIntoDB(kDummyOrigin, stored_proto); - SiteDataProto read_proto; - EXPECT_TRUE(ReadFromDB(kDummyOrigin, &read_proto)); - EXPECT_TRUE(read_proto.IsInitialized()); - EXPECT_EQ(stored_proto.SerializeAsString(), read_proto.SerializeAsString()); -} - -TEST_F(LevelDBSiteCharacteristicsDatabaseTest, RemoveEntries) { - std::vector<url::Origin> site_origins = AddDummyEntriesToDB(10); - - // Remove half the origins from the database. - std::vector<url::Origin> site_origins_to_remove( - site_origins.begin(), site_origins.begin() + site_origins.size() / 2); - db_->RemoveSiteCharacteristicsFromDB(site_origins_to_remove); - - WaitForAsyncOperationsToComplete(); - - // Verify that the origins were removed correctly. - SiteDataProto proto_temp; - for (const auto& iter : site_origins_to_remove) - EXPECT_FALSE(ReadFromDB(iter, &proto_temp)); - - for (auto iter = site_origins.begin() + site_origins.size() / 2; - iter != site_origins.end(); ++iter) { - EXPECT_TRUE(ReadFromDB(*iter, &proto_temp)); - } - - // Clear the database. - db_->ClearDatabase(); - - WaitForAsyncOperationsToComplete(); - - // Verify that no origin remains. - for (auto iter : site_origins) - EXPECT_FALSE(ReadFromDB(iter, &proto_temp)); -} - -TEST_F(LevelDBSiteCharacteristicsDatabaseTest, GetDatabaseSize) { - std::vector<url::Origin> site_origins = AddDummyEntriesToDB(200); - - auto size_callback = - base::BindLambdaForTesting([&](base::Optional<int64_t> num_rows, - base::Optional<int64_t> on_disk_size_kb) { - EXPECT_TRUE(num_rows); - // The DB contains an extra row for metadata. - int64_t expected_rows = site_origins.size() + 1; - EXPECT_EQ(expected_rows, num_rows.value()); - - EXPECT_TRUE(on_disk_size_kb); - EXPECT_LT(0, on_disk_size_kb.value()); - }); - - db_->GetDatabaseSize(std::move(size_callback)); - - WaitForAsyncOperationsToComplete(); - - // Verify that the DB is still operational (see implementation detail - // for Windows). - SiteDataProto read_proto; - EXPECT_TRUE(ReadFromDB(site_origins[0], &read_proto)); -} - -TEST_F(LevelDBSiteCharacteristicsDatabaseTest, DatabaseRecoveryTest) { - std::vector<url::Origin> site_origins = AddDummyEntriesToDB(10); - - db_.reset(); - - EXPECT_TRUE(leveldb_chrome::CorruptClosedDBForTesting(GetDBPath())); - - base::HistogramTester histogram_tester; - histogram_tester.ExpectTotalCount("ResourceCoordinator.LocalDB.DatabaseInit", - 0); - // Open the corrupt DB and ensure that the appropriate histograms gets - // updated. - OpenDB(); - EXPECT_TRUE(db_->DatabaseIsInitializedForTesting()); - histogram_tester.ExpectUniqueSample( - "ResourceCoordinator.LocalDB.DatabaseInit", 1 /* kInitStatusCorruption */, - 1); - histogram_tester.ExpectUniqueSample( - "ResourceCoordinator.LocalDB.DatabaseInitAfterRepair", - 0 /* kInitStatusOk */, 1); - - // TODO(sebmarchand): try to induce an I/O error by deleting one of the - // manifest files. -} - -// Ensure that there's no fatal failures if we try using the database after -// failing to open it (all the events will be ignored). -TEST_F(LevelDBSiteCharacteristicsDatabaseTest, DatabaseOpeningFailure) { - db_.reset(); - ScopedReadOnlyDirectory read_only_dir(GetTempPath()); - - OpenDB(read_only_dir.GetReadOnlyPath()); - EXPECT_FALSE(db_->DatabaseIsInitializedForTesting()); - - SiteDataProto proto_temp; - EXPECT_FALSE( - ReadFromDB(url::Origin::Create(GURL("https://foo.com")), &proto_temp)); - WaitForAsyncOperationsToComplete(); - db_->WriteSiteCharacteristicsIntoDB( - url::Origin::Create(GURL("https://foo.com")), proto_temp); - WaitForAsyncOperationsToComplete(); - db_->RemoveSiteCharacteristicsFromDB({}); - WaitForAsyncOperationsToComplete(); - db_->ClearDatabase(); - WaitForAsyncOperationsToComplete(); -} - -TEST_F(LevelDBSiteCharacteristicsDatabaseTest, DBGetsClearedOnVersionUpgrade) { - leveldb::DB* raw_db = db_->GetDBForTesting(); - EXPECT_TRUE(raw_db); - - // Remove the entry containing the DB version number, this will cause the DB - // to be cleared the next time it gets opened. - leveldb::Status s = - raw_db->Delete(leveldb::WriteOptions(), - LevelDBSiteCharacteristicsDatabase::kDbMetadataKey); - EXPECT_TRUE(s.ok()); - - // Add some dummy data to the database to ensure the database gets cleared - // when upgrading it to the new version. - ::google::protobuf::int64 test_value = 42; - SiteDataProto stored_proto; - InitSiteCharacteristicProto(&stored_proto, test_value); - db_->WriteSiteCharacteristicsIntoDB(kDummyOrigin, stored_proto); - WaitForAsyncOperationsToComplete(); - - db_.reset(); - - // Reopen the database and ensure that it has been cleared. - OpenDB(); - raw_db = db_->GetDBForTesting(); - std::string db_metadata; - s = raw_db->Get(leveldb::ReadOptions(), - LevelDBSiteCharacteristicsDatabase::kDbMetadataKey, - &db_metadata); - EXPECT_TRUE(s.ok()); - size_t version = std::numeric_limits<size_t>::max(); - EXPECT_TRUE(base::StringToSizeT(db_metadata, &version)); - EXPECT_EQ(LevelDBSiteCharacteristicsDatabase::kDbVersion, version); - - SiteDataProto proto_temp; - EXPECT_FALSE(ReadFromDB(kDummyOrigin, &proto_temp)); -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.cc deleted file mode 100644 index 0ed6699..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.cc +++ /dev/null
@@ -1,452 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h" - -#include <algorithm> -#include <vector> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" -#include "base/strings/stringprintf.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_database.h" -#include "chrome/browser/resource_coordinator/time.h" - -namespace resource_coordinator { -namespace internal { - -namespace { - -// The sample weighing factor for the exponential moving averages for -// performance measurements. A factor of 1/2 gives each sample an equal weight -// to the entire previous history. As we don't know much noise there is to the -// measurement, this is essentially a shot in the dark. -// TODO(siggi): Consider adding UMA metrics to capture e.g. the fractional delta -// from the current average, or some such. -constexpr float kSampleWeightFactor = 0.5; - -// Observations windows have a default value of 2 hours, 95% of backgrounded -// tabs don't use any of these features in this time window. -static constexpr base::TimeDelta kObservationWindowLength = - base::TimeDelta::FromHours(2); - -base::TimeDelta GetTickDeltaSinceEpoch() { - return NowTicks() - base::TimeTicks::UnixEpoch(); -} - -// Returns all the SiteDataFeatureProto elements contained in a -// SiteDataProto protobuf object. -std::vector<SiteDataFeatureProto*> GetAllFeaturesFromProto( - SiteDataProto* proto) { - std::vector<SiteDataFeatureProto*> ret( - {proto->mutable_updates_favicon_in_background(), - proto->mutable_updates_title_in_background(), - proto->mutable_uses_audio_in_background()}); - - return ret; -} - -const char* FeatureTypeToFeatureName( - const LocalSiteCharacteristicsDataImpl::TrackedBackgroundFeatures feature) { - switch (feature) { - case LocalSiteCharacteristicsDataImpl::TrackedBackgroundFeatures:: - kFaviconUpdate: - return "FaviconUpdateInBackground"; - case LocalSiteCharacteristicsDataImpl::TrackedBackgroundFeatures:: - kTitleUpdate: - return "TitleUpdateInBackground"; - case LocalSiteCharacteristicsDataImpl::TrackedBackgroundFeatures:: - kAudioUsage: - return "AudioUsageInBackground"; - } -} - -} // namespace - -void LocalSiteCharacteristicsDataImpl::NotifySiteLoaded() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Update the last loaded time when this origin gets loaded for the first - // time. - if (loaded_tabs_count_ == 0) { - site_characteristics_.set_last_loaded( - TimeDeltaToInternalRepresentation(GetTickDeltaSinceEpoch())); - - is_dirty_ = true; - } - loaded_tabs_count_++; -} - -void LocalSiteCharacteristicsDataImpl::NotifySiteUnloaded( - performance_manager::TabVisibility tab_visibility) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (tab_visibility == performance_manager::TabVisibility::kBackground) - DecrementNumLoadedBackgroundTabs(); - - loaded_tabs_count_--; - // Only update the last loaded time when there's no more loaded instance of - // this origin. - if (loaded_tabs_count_ > 0U) - return; - - base::TimeDelta current_unix_time = GetTickDeltaSinceEpoch(); - - // Update the |last_loaded_time_| field, as the moment this site gets unloaded - // also corresponds to the last moment it was loaded. - site_characteristics_.set_last_loaded( - TimeDeltaToInternalRepresentation(current_unix_time)); -} - -void LocalSiteCharacteristicsDataImpl::NotifyLoadedSiteBackgrounded() { - if (loaded_tabs_in_background_count_ == 0) - background_session_begin_ = NowTicks(); - - loaded_tabs_in_background_count_++; - - DCHECK_LE(loaded_tabs_in_background_count_, loaded_tabs_count_); -} - -void LocalSiteCharacteristicsDataImpl::NotifyLoadedSiteForegrounded() { - DecrementNumLoadedBackgroundTabs(); -} - -performance_manager::SiteFeatureUsage -LocalSiteCharacteristicsDataImpl::UpdatesFaviconInBackground() const { - return GetFeatureUsage(site_characteristics_.updates_favicon_in_background()); -} - -performance_manager::SiteFeatureUsage -LocalSiteCharacteristicsDataImpl::UpdatesTitleInBackground() const { - return GetFeatureUsage(site_characteristics_.updates_title_in_background()); -} - -performance_manager::SiteFeatureUsage -LocalSiteCharacteristicsDataImpl::UsesAudioInBackground() const { - return GetFeatureUsage(site_characteristics_.uses_audio_in_background()); -} - -bool LocalSiteCharacteristicsDataImpl::DataLoaded() const { - return fully_initialized_; -} - -void LocalSiteCharacteristicsDataImpl::RegisterDataLoadedCallback( - base::OnceClosure&& callback) { - if (fully_initialized_) { - std::move(callback).Run(); - return; - } - data_loaded_callbacks_.emplace_back(std::move(callback)); -} - -void LocalSiteCharacteristicsDataImpl::NotifyUpdatesFaviconInBackground() { - NotifyFeatureUsage( - site_characteristics_.mutable_updates_favicon_in_background(), - TrackedBackgroundFeatures::kFaviconUpdate); -} - -void LocalSiteCharacteristicsDataImpl::NotifyUpdatesTitleInBackground() { - NotifyFeatureUsage( - site_characteristics_.mutable_updates_title_in_background(), - TrackedBackgroundFeatures::kTitleUpdate); -} - -void LocalSiteCharacteristicsDataImpl::NotifyUsesAudioInBackground() { - NotifyFeatureUsage(site_characteristics_.mutable_uses_audio_in_background(), - TrackedBackgroundFeatures::kAudioUsage); -} - -void LocalSiteCharacteristicsDataImpl::NotifyLoadTimePerformanceMeasurement( - base::TimeDelta load_duration, - base::TimeDelta cpu_usage_estimate, - uint64_t private_footprint_kb_estimate) { - is_dirty_ = true; - - load_duration_.AppendDatum(load_duration.InMicroseconds()); - cpu_usage_estimate_.AppendDatum(cpu_usage_estimate.InMicroseconds()); - private_footprint_kb_estimate_.AppendDatum(private_footprint_kb_estimate); -} - -void LocalSiteCharacteristicsDataImpl::ExpireAllObservationWindowsForTesting() { - for (auto* iter : GetAllFeaturesFromProto(&site_characteristics_)) - IncrementFeatureObservationDuration(iter, kObservationWindowLength); -} - -void LocalSiteCharacteristicsDataImpl::RegisterFeatureUsageCallbackForTesting( - const TrackedBackgroundFeatures feature_type, - base::OnceClosure callback) { - DCHECK( - !feature_usage_callback_for_testing_[static_cast<size_t>(feature_type)]); - feature_usage_callback_for_testing_[static_cast<size_t>(feature_type)] = - std::move(callback); -} - -LocalSiteCharacteristicsDataImpl::LocalSiteCharacteristicsDataImpl( - const url::Origin& origin, - OnDestroyDelegate* delegate, - LocalSiteCharacteristicsDatabase* database) - : load_duration_(kSampleWeightFactor), - cpu_usage_estimate_(kSampleWeightFactor), - private_footprint_kb_estimate_(kSampleWeightFactor), - origin_(origin), - loaded_tabs_count_(0U), - loaded_tabs_in_background_count_(0U), - database_(database), - delegate_(delegate), - fully_initialized_(false), - is_dirty_(false) { - DCHECK(database_); - DCHECK(delegate_); - - database_->ReadSiteCharacteristicsFromDB( - origin_, base::BindOnce(&LocalSiteCharacteristicsDataImpl::OnInitCallback, - weak_factory_.GetWeakPtr())); -} - -LocalSiteCharacteristicsDataImpl::~LocalSiteCharacteristicsDataImpl() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // All users of this object should make sure that they send the same number of - // NotifySiteLoaded and NotifySiteUnloaded events, in practice this mean - // tracking the loaded state and sending an unload event in their destructor - // if needed. - DCHECK(!IsLoaded()); - DCHECK_EQ(0U, loaded_tabs_in_background_count_); - - DCHECK(delegate_); - delegate_->OnLocalSiteCharacteristicsDataImplDestroyed(this); - - // TODO(sebmarchand): Some data might be lost here if the read operation has - // not completed, add some metrics to measure if this is really an issue. - if (is_dirty_ && fully_initialized_) - database_->WriteSiteCharacteristicsIntoDB(origin_, FlushStateToProto()); -} - -base::TimeDelta LocalSiteCharacteristicsDataImpl::FeatureObservationDuration( - const SiteDataFeatureProto& feature_proto) const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Get the current observation duration value if available. - base::TimeDelta observation_time_for_feature; - if (feature_proto.has_observation_duration()) { - observation_time_for_feature = - InternalRepresentationToTimeDelta(feature_proto.observation_duration()); - } - - // If this site is still in background and the feature isn't in use then the - // observation time since load needs to be added. - if (loaded_tabs_in_background_count_ > 0U && - InternalRepresentationToTimeDelta(feature_proto.use_timestamp()) - .is_zero()) { - base::TimeDelta observation_time_since_backgrounded = - NowTicks() - background_session_begin_; - observation_time_for_feature += observation_time_since_backgrounded; - } - - return observation_time_for_feature; -} - -// static: -void LocalSiteCharacteristicsDataImpl::IncrementFeatureObservationDuration( - SiteDataFeatureProto* feature_proto, - base::TimeDelta extra_observation_duration) { - if (!feature_proto->has_use_timestamp() || - InternalRepresentationToTimeDelta(feature_proto->use_timestamp()) - .is_zero()) { - feature_proto->set_observation_duration(TimeDeltaToInternalRepresentation( - InternalRepresentationToTimeDelta( - feature_proto->observation_duration()) + - extra_observation_duration)); - } -} - -void LocalSiteCharacteristicsDataImpl:: - ClearObservationsAndInvalidateReadOperation() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // Invalidate the weak pointer that have been served, this will ensure that - // this object doesn't get initialized from the database after being cleared. - weak_factory_.InvalidateWeakPtrs(); - - // Reset all the observations. - site_characteristics_.Clear(); - - // Clear the performance estimates, both the local state and the proto. - cpu_usage_estimate_.Clear(); - private_footprint_kb_estimate_.Clear(); - site_characteristics_.clear_load_time_estimates(); - - // Set the last loaded time to the current time if there's some loaded - // instances of this site. - if (IsLoaded()) { - site_characteristics_.set_last_loaded( - TimeDeltaToInternalRepresentation(GetTickDeltaSinceEpoch())); - } - - // This object is now in a valid state and can be written in the database. - TransitionToFullyInitialized(); -} - -performance_manager::SiteFeatureUsage -LocalSiteCharacteristicsDataImpl::GetFeatureUsage( - const SiteDataFeatureProto& feature_proto) const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - UMA_HISTOGRAM_BOOLEAN( - "ResourceCoordinator.LocalDB.ReadHasCompletedBeforeQuery", - fully_initialized_); - - // Checks if this feature has already been observed. - // TODO(sebmarchand): Check the timestamp and reset features that haven't been - // observed in a long time, https://crbug.com/826446. - if (feature_proto.has_use_timestamp()) - return performance_manager::SiteFeatureUsage::kSiteFeatureInUse; - - if (FeatureObservationDuration(feature_proto) >= kObservationWindowLength) - return performance_manager::SiteFeatureUsage::kSiteFeatureNotInUse; - - return performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown; -} - -void LocalSiteCharacteristicsDataImpl::NotifyFeatureUsage( - SiteDataFeatureProto* feature_proto, - const TrackedBackgroundFeatures feature_type) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(IsLoaded()); - DCHECK_GT(loaded_tabs_in_background_count_, 0U); - - // Report the observation time if this is the first time this feature is - // observed. - if (feature_proto->observation_duration() != 0) { - base::UmaHistogramCustomTimes( - base::StringPrintf( - "ResourceCoordinator.LocalDB.ObservationTimeBeforeFirstUse.%s", - FeatureTypeToFeatureName(feature_type)), - InternalRepresentationToTimeDelta( - feature_proto->observation_duration()), - base::TimeDelta::FromSeconds(1), base::TimeDelta::FromDays(1), 100); - } - - feature_proto->Clear(); - feature_proto->set_use_timestamp( - TimeDeltaToInternalRepresentation(GetTickDeltaSinceEpoch())); - - if (feature_usage_callback_for_testing_[static_cast<size_t>(feature_type)]) { - std::move( - feature_usage_callback_for_testing_[static_cast<size_t>(feature_type)]) - .Run(); - } -} - -void LocalSiteCharacteristicsDataImpl::OnInitCallback( - base::Optional<SiteDataProto> db_site_characteristics) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Check if the initialization has succeeded. - if (db_site_characteristics) { - // If so, iterates over all the features and initialize them. - auto this_features = GetAllFeaturesFromProto(&site_characteristics_); - auto db_features = - GetAllFeaturesFromProto(&db_site_characteristics.value()); - auto this_features_iter = this_features.begin(); - auto db_features_iter = db_features.begin(); - for (; this_features_iter != this_features.end() && - db_features_iter != db_features.end(); - ++this_features_iter, ++db_features_iter) { - // If the |use_timestamp| field is set for the in-memory entry for this - // feature then there's nothing to do, otherwise update it with the values - // from the database. - if (!(*this_features_iter)->has_use_timestamp()) { - if ((*db_features_iter)->has_use_timestamp() && - (*db_features_iter)->use_timestamp() != 0) { - (*this_features_iter)->Clear(); - // Keep the use timestamp from the database, if any. - (*this_features_iter) - ->set_use_timestamp((*db_features_iter)->use_timestamp()); - } else { - // Else, add the observation duration from the database to the - // in-memory observation duration. - IncrementFeatureObservationDuration( - (*this_features_iter), - InternalRepresentationToTimeDelta( - (*db_features_iter)->observation_duration())); - } - } - } - // Only update the last loaded field if we haven't updated it since the - // creation of this object. - if (!site_characteristics_.has_last_loaded()) { - site_characteristics_.set_last_loaded( - db_site_characteristics->last_loaded()); - } - // If there was on-disk data, update the in-memory performance averages. - if (db_site_characteristics->has_load_time_estimates()) { - const auto& estimates = db_site_characteristics->load_time_estimates(); - if (estimates.has_avg_load_duration_us()) - load_duration_.PrependDatum(estimates.avg_load_duration_us()); - if (estimates.has_avg_cpu_usage_us()) - cpu_usage_estimate_.PrependDatum(estimates.avg_cpu_usage_us()); - if (estimates.has_avg_footprint_kb()) { - private_footprint_kb_estimate_.PrependDatum( - estimates.avg_footprint_kb()); - } - } - } - - TransitionToFullyInitialized(); -} - -void LocalSiteCharacteristicsDataImpl::DecrementNumLoadedBackgroundTabs() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK_GT(loaded_tabs_in_background_count_, 0U); - loaded_tabs_in_background_count_--; - // Only update the observation durations if there's no more backgounded - // instance of this origin. - if (loaded_tabs_in_background_count_ == 0U) - FlushFeaturesObservationDurationToProto(); -} - -const SiteDataProto& LocalSiteCharacteristicsDataImpl::FlushStateToProto() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Update the proto with the most current performance measurement averages. - if (cpu_usage_estimate_.num_datums() || - private_footprint_kb_estimate_.num_datums()) { - auto* estimates = site_characteristics_.mutable_load_time_estimates(); - if (load_duration_.num_datums()) - estimates->set_avg_load_duration_us(load_duration_.value()); - if (cpu_usage_estimate_.num_datums()) - estimates->set_avg_cpu_usage_us(cpu_usage_estimate_.value()); - if (private_footprint_kb_estimate_.num_datums()) { - estimates->set_avg_footprint_kb(private_footprint_kb_estimate_.value()); - } - } - - if (loaded_tabs_in_background_count_ > 0U) - FlushFeaturesObservationDurationToProto(); - - return site_characteristics_; -} - -void LocalSiteCharacteristicsDataImpl:: - FlushFeaturesObservationDurationToProto() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!background_session_begin_.is_null()); - - base::TimeTicks now = NowTicks(); - - base::TimeDelta extra_observation_duration = now - background_session_begin_; - background_session_begin_ = now; - - // Update the observation duration fields. - for (auto* iter : GetAllFeaturesFromProto(&site_characteristics_)) - IncrementFeatureObservationDuration(iter, extra_observation_duration); -} - -void LocalSiteCharacteristicsDataImpl::TransitionToFullyInitialized() { - fully_initialized_ = true; - for (size_t i = 0; i < data_loaded_callbacks_.size(); ++i) - std::move(data_loaded_callbacks_[i]).Run(); - data_loaded_callbacks_.clear(); -} - -} // namespace internal -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h b/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h deleted file mode 100644 index d80f8d2..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h +++ /dev/null
@@ -1,313 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_IMPL_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_IMPL_H_ - -#include "base/callback_forward.h" -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/sequence_checker.h" -#include "base/time/time.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_database.h" -#include "chrome/browser/resource_coordinator/tab_manager_features.h" -#include "components/performance_manager/persistence/site_data/exponential_moving_average.h" -#include "components/performance_manager/persistence/site_data/feature_usage.h" -#include "components/performance_manager/persistence/site_data/site_data.pb.h" -#include "components/performance_manager/persistence/site_data/tab_visibility.h" -#include "url/origin.h" - -namespace resource_coordinator { - -class LocalSiteCharacteristicsDatabase; -class LocalSiteCharacteristicsDataStore; -class LocalSiteCharacteristicsDataStoreTest; -class LocalSiteCharacteristicsDataReaderTest; -class LocalSiteCharacteristicsDataWriterTest; - -FORWARD_DECLARE_TEST(LocalSiteCharacteristicsDataReaderTest, - DestroyingReaderCancelsPendingCallbacks); -FORWARD_DECLARE_TEST(LocalSiteCharacteristicsDataReaderTest, - FreeingReaderDoesntCauseWriteOperation); -FORWARD_DECLARE_TEST(LocalSiteCharacteristicsDataReaderTest, - OnDataLoadedCallbackInvoked); - -namespace internal { - -FORWARD_DECLARE_TEST(LocalSiteCharacteristicsDataImplTest, - LateAsyncReadDoesntBypassClearEvent); - -// Internal class used to read/write site characteristics. This is a wrapper -// class around a SiteDataProto object and offers various to query -// and/or modify it. This class shouldn't be used directly, instead it should be -// created by a LocalSiteCharacteristicsDataStore that will serve reader and -// writer objects. -// -// Reader and writers objects that are interested in reading/writing information -// about the same origin will share a unique ref counted instance of this -// object, because of this all the operations done on these objects should be -// done on the same thread, this class isn't thread safe. -// -// By default tabs associated with instances of this class are assumed to be -// running in foreground, |NotifyTabBackgrounded| should get called to indicate -// that the tab is running in background. -class LocalSiteCharacteristicsDataImpl - : public base::RefCounted<LocalSiteCharacteristicsDataImpl> { - public: - // Interface that should be implemented in order to receive notifications when - // this object is about to get destroyed. - class OnDestroyDelegate { - public: - // Called when this object is about to get destroyed. - virtual void OnLocalSiteCharacteristicsDataImplDestroyed( - LocalSiteCharacteristicsDataImpl* impl) = 0; - }; - - enum class TrackedBackgroundFeatures { - kFaviconUpdate, - kTitleUpdate, - kAudioUsage, - kMaxValue = kAudioUsage, - }; - - // Must be called when a load event is received for this site, this can be - // invoked several times if instances of this class are shared between - // multiple tabs. - void NotifySiteLoaded(); - - // Must be called when an unload event is received for this site, this can be - // invoked several times if instances of this class are shared between - // multiple tabs. - void NotifySiteUnloaded(performance_manager::TabVisibility tab_visibility); - - // Must be called when a loaded tab gets backgrounded. - void NotifyLoadedSiteBackgrounded(); - - // Must be called when a loaded tab gets foregrounded. - void NotifyLoadedSiteForegrounded(); - - // Returns the usage of a given feature for this origin. - performance_manager::SiteFeatureUsage UpdatesFaviconInBackground() const; - performance_manager::SiteFeatureUsage UpdatesTitleInBackground() const; - performance_manager::SiteFeatureUsage UsesAudioInBackground() const; - - // Returns true if the most authoritative data has been loaded from the - // backing store. - bool DataLoaded() const; - - // Registers a callback to be invoked when the data backing this object is - // loaded from disk, or otherwise authoritatively initialized. - void RegisterDataLoadedCallback(base::OnceClosure&& callback); - - // Accessors for load-time performance measurement estimates. - // If |num_datum| is zero, there's no estimate available. - const performance_manager::ExponentialMovingAverage& load_duration() const { - return load_duration_; - } - const performance_manager::ExponentialMovingAverage& cpu_usage_estimate() - const { - return cpu_usage_estimate_; - } - const performance_manager::ExponentialMovingAverage& - private_footprint_kb_estimate() const { - return private_footprint_kb_estimate_; - } - - // Must be called when a feature is used, calling this function updates the - // last observed timestamp for this feature. - void NotifyUpdatesFaviconInBackground(); - void NotifyUpdatesTitleInBackground(); - void NotifyUsesAudioInBackground(); - - // Call when a load-time performance measurement becomes available. - void NotifyLoadTimePerformanceMeasurement( - base::TimeDelta load_duration, - base::TimeDelta cpu_usage_estimate, - uint64_t private_footprint_kb_estimate); - - base::TimeDelta last_loaded_time_for_testing() const { - return InternalRepresentationToTimeDelta( - site_characteristics_.last_loaded()); - } - - const SiteDataProto& site_characteristics_for_testing() const { - return site_characteristics_; - } - - size_t loaded_tabs_count_for_testing() const { return loaded_tabs_count_; } - - size_t loaded_tabs_in_background_count_for_testing() const { - return loaded_tabs_in_background_count_; - } - - base::TimeTicks background_session_begin_for_testing() const { - return background_session_begin_; - } - - const url::Origin& origin() const { return origin_; } - bool is_dirty() const { return is_dirty_; } - - void ExpireAllObservationWindowsForTesting(); - - void ClearObservationsAndInvalidateReadOperationForTesting() { - ClearObservationsAndInvalidateReadOperation(); - } - - bool fully_initialized_for_testing() const { return fully_initialized_; } - - void RegisterFeatureUsageCallbackForTesting( - const TrackedBackgroundFeatures feature_type, - base::OnceClosure callback); - - protected: - friend class base::RefCounted<LocalSiteCharacteristicsDataImpl>; - friend class resource_coordinator::LocalSiteCharacteristicsDataStore; - - // Friend all the tests. - friend class LocalSiteCharacteristicsDataImplTest; - friend class resource_coordinator::LocalSiteCharacteristicsDataReaderTest; - friend class resource_coordinator::LocalSiteCharacteristicsDataStoreTest; - friend class resource_coordinator::LocalSiteCharacteristicsDataWriterTest; - - LocalSiteCharacteristicsDataImpl(const url::Origin& origin, - OnDestroyDelegate* delegate, - LocalSiteCharacteristicsDatabase* database); - - virtual ~LocalSiteCharacteristicsDataImpl(); - - // Helper functions to convert from/to the internal representation that is - // used to store TimeDelta values in the |SiteDataProto| protobuf. - static base::TimeDelta InternalRepresentationToTimeDelta( - ::google::protobuf::int64 value) { - return base::TimeDelta::FromSeconds(value); - } - static int64_t TimeDeltaToInternalRepresentation(base::TimeDelta delta) { - return delta.InSeconds(); - } - - // Returns for how long a given feature has been observed, this is the sum of - // the recorded observation duration and the current observation duration - // since this site has been loaded (if applicable). If a feature has been - // used then it returns 0. - base::TimeDelta FeatureObservationDuration( - const SiteDataFeatureProto& feature_proto) const; - - private: - FRIEND_TEST_ALL_PREFIXES(LocalSiteCharacteristicsDataImplTest, - FlushingStateToProtoDoesntAffectData); - FRIEND_TEST_ALL_PREFIXES(LocalSiteCharacteristicsDataImplTest, - LateAsyncReadDoesntBypassClearEvent); - FRIEND_TEST_ALL_PREFIXES( - resource_coordinator::LocalSiteCharacteristicsDataReaderTest, - DestroyingReaderCancelsPendingCallbacks); - FRIEND_TEST_ALL_PREFIXES( - resource_coordinator::LocalSiteCharacteristicsDataReaderTest, - FreeingReaderDoesntCauseWriteOperation); - FRIEND_TEST_ALL_PREFIXES( - resource_coordinator::LocalSiteCharacteristicsDataReaderTest, - OnDataLoadedCallbackInvoked); - - // Add |extra_observation_duration| to the observation window of a given - // feature if it hasn't been used yet, do nothing otherwise. - static void IncrementFeatureObservationDuration( - SiteDataFeatureProto* feature_proto, - base::TimeDelta extra_observation_duration); - - // Clear all the past observations about this site and invalidate the pending - // read observations from the database. - void ClearObservationsAndInvalidateReadOperation(); - - // Returns the usage of |site_feature| for this site. - performance_manager::SiteFeatureUsage GetFeatureUsage( - const SiteDataFeatureProto& feature_proto) const; - - // Helper function to update a given |SiteDataFeatureProto| when a - // feature gets used. - void NotifyFeatureUsage(SiteDataFeatureProto* feature_proto, - const TrackedBackgroundFeatures feature_type); - - bool IsLoaded() const { return loaded_tabs_count_ > 0U; } - - // Callback that needs to be called by the database once it has finished - // trying to read the protobuf. - void OnInitCallback(base::Optional<SiteDataProto> site_characteristic_proto); - - // Decrement the |loaded_tabs_in_background_count_| counter and update the - // local feature observation durations if necessary. - void DecrementNumLoadedBackgroundTabs(); - - // Flush any state that's maintained in member variables to the proto. - const SiteDataProto& FlushStateToProto(); - - // Updates the proto with the current total observation duration and updates - // |background_session_begin_| to NowTicks(). - void FlushFeaturesObservationDurationToProto(); - - void TransitionToFullyInitialized(); - - // This site's characteristics, contains the features and other values are - // measured. - SiteDataProto site_characteristics_; - - // The in-memory storage for the moving performance averages. - performance_manager::ExponentialMovingAverage - load_duration_; // microseconds. - performance_manager::ExponentialMovingAverage - cpu_usage_estimate_; // microseconds. - performance_manager::ExponentialMovingAverage private_footprint_kb_estimate_; - - // This site's origin. - const url::Origin origin_; - - // The number of loaded tabs for this origin. Several tabs with the - // same origin might share the same instance of this object, this counter - // will allow to properly update the observation time (starts when the first - // tab gets loaded, stops when the last one gets unloaded). - size_t loaded_tabs_count_; - - // Number of loaded tabs currently in background for this origin, the - // implementation doesn't need to track unloaded tabs running in background. - size_t loaded_tabs_in_background_count_; - - // The time at which the |loaded_tabs_in_background_count_| counter changed - // from 0 to 1. - base::TimeTicks background_session_begin_; - - // The database used to store the site characteristics, it should outlive - // this object. - LocalSiteCharacteristicsDatabase* const database_; - - // The delegate that should get notified when this object is about to get - // destroyed, it should outlive this object. - OnDestroyDelegate* const delegate_; - - // Indicates if this object has been fully initialized, either because the - // read operation from the database has completed or because it has been - // cleared. - bool fully_initialized_; - - // Dirty bit, indicates if any of the fields in |site_characteristics_| has - // changed since it has been initialized. - bool is_dirty_; - - // A collection of callbacks to be invoked when this object becomes fully - // initialized. - std::vector<base::OnceClosure> data_loaded_callbacks_; - - base::OnceClosure feature_usage_callback_for_testing_[static_cast<size_t>( - TrackedBackgroundFeatures::kMaxValue) + 1]; - - SEQUENCE_CHECKER(sequence_checker_); - - base::WeakPtrFactory<LocalSiteCharacteristicsDataImpl> weak_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(LocalSiteCharacteristicsDataImpl); -}; - -} // namespace internal -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_IMPL_H_
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_impl_unittest.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_impl_unittest.cc deleted file mode 100644 index 6da9851..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_impl_unittest.cc +++ /dev/null
@@ -1,721 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h" - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/test/bind_test_util.h" -#include "base/test/simple_test_tick_clock.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" -#include "chrome/browser/resource_coordinator/time.h" -#include "components/performance_manager/persistence/site_data/feature_usage.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace resource_coordinator { -namespace internal { - -namespace { - -constexpr base::TimeDelta kInitialTimeSinceEpoch = - base::TimeDelta::FromSeconds(1); - -constexpr base::TimeDelta kObservationWindowLength = - base::TimeDelta::FromHours(2); - -class TestLocalSiteCharacteristicsDataImpl - : public LocalSiteCharacteristicsDataImpl { - public: - using LocalSiteCharacteristicsDataImpl::FeatureObservationDuration; - using LocalSiteCharacteristicsDataImpl::OnDestroyDelegate; - using LocalSiteCharacteristicsDataImpl::site_characteristics_for_testing; - using LocalSiteCharacteristicsDataImpl::TimeDeltaToInternalRepresentation; - - explicit TestLocalSiteCharacteristicsDataImpl( - const url::Origin& origin, - LocalSiteCharacteristicsDataImpl::OnDestroyDelegate* delegate, - LocalSiteCharacteristicsDatabase* database) - : LocalSiteCharacteristicsDataImpl(origin, delegate, database) {} - - base::TimeDelta FeatureObservationTimestamp( - const SiteDataFeatureProto& feature_proto) { - return InternalRepresentationToTimeDelta(feature_proto.use_timestamp()); - } - - protected: - ~TestLocalSiteCharacteristicsDataImpl() override {} -}; - -class MockLocalSiteCharacteristicsDatabase - : public testing::NoopLocalSiteCharacteristicsDatabase { - public: - MockLocalSiteCharacteristicsDatabase() = default; - ~MockLocalSiteCharacteristicsDatabase() = default; - - // Note: As move-only parameters (e.g. OnceCallback) aren't supported by mock - // methods, add On... methods to pass a non-const reference to OnceCallback. - void ReadSiteCharacteristicsFromDB( - const url::Origin& origin, - LocalSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDBCallback - callback) override { - OnReadSiteCharacteristicsFromDB(origin, callback); - } - MOCK_METHOD2(OnReadSiteCharacteristicsFromDB, - void(const url::Origin&, - LocalSiteCharacteristicsDatabase:: - ReadSiteCharacteristicsFromDBCallback&)); - - MOCK_METHOD2(WriteSiteCharacteristicsIntoDB, - void(const url::Origin&, const SiteDataProto&)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockLocalSiteCharacteristicsDatabase); -}; - -// Returns a SiteDataFeatureProto that indicates that a feature -// hasn't been used. -SiteDataFeatureProto GetUnusedFeatureProto() { - SiteDataFeatureProto unused_feature_proto; - unused_feature_proto.set_observation_duration(1U); - unused_feature_proto.set_use_timestamp(0U); - return unused_feature_proto; -} - -// Returns a SiteDataFeatureProto that indicates that a feature -// has been used. -SiteDataFeatureProto GetUsedFeatureProto() { - SiteDataFeatureProto used_feature_proto; - used_feature_proto.set_observation_duration(0U); - used_feature_proto.set_use_timestamp(1U); - return used_feature_proto; -} - -} // namespace - -class LocalSiteCharacteristicsDataImplTest : public ::testing::Test { - public: - LocalSiteCharacteristicsDataImplTest() - : scoped_set_tick_clock_for_testing_(&test_clock_) {} - - void SetUp() override { - test_clock_.SetNowTicks(base::TimeTicks::UnixEpoch()); - // Advance the test clock by a small delay, as some tests will fail if the - // current time is equal to Epoch. - test_clock_.Advance(kInitialTimeSinceEpoch); - } - - protected: - scoped_refptr<TestLocalSiteCharacteristicsDataImpl> GetDataImpl( - const url::Origin& origin, - LocalSiteCharacteristicsDataImpl::OnDestroyDelegate* destroy_delegate, - LocalSiteCharacteristicsDatabase* database) { - return base::MakeRefCounted<TestLocalSiteCharacteristicsDataImpl>( - origin, destroy_delegate, database); - } - - // Use a mock database to intercept the initialization callback and save it - // locally so it can be run later. - scoped_refptr<TestLocalSiteCharacteristicsDataImpl> - GetDataImplAndInterceptReadCallback( - const url::Origin& origin, - LocalSiteCharacteristicsDataImpl::OnDestroyDelegate* destroy_delegate, - MockLocalSiteCharacteristicsDatabase* mock_db, - LocalSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDBCallback* - read_cb) { - auto read_from_db_mock_impl = - [&](const url::Origin& origin, - LocalSiteCharacteristicsDatabase:: - ReadSiteCharacteristicsFromDBCallback& callback) { - *read_cb = std::move(callback); - }; - - EXPECT_CALL(*mock_db, - OnReadSiteCharacteristicsFromDB(::testing::_, ::testing::_)) - .WillOnce(::testing::Invoke(read_from_db_mock_impl)); - auto local_site_data = GetDataImpl(origin, &destroy_delegate_, mock_db); - ::testing::Mock::VerifyAndClear(mock_db); - return local_site_data; - } - - const url::Origin kDummyOrigin = url::Origin::Create(GURL("foo.com")); - const url::Origin kDummyOrigin2 = url::Origin::Create(GURL("bar.com")); - - base::SimpleTestTickClock test_clock_; - ScopedSetTickClockForTesting scoped_set_tick_clock_for_testing_; - // Use a NiceMock as there's no need to add expectations in these tests, - // there's a dedicated test that ensure that the delegate works as expected. - ::testing::NiceMock< - testing::MockLocalSiteCharacteristicsDataImplOnDestroyDelegate> - destroy_delegate_; - - testing::NoopLocalSiteCharacteristicsDatabase database_; -}; - -TEST_F(LocalSiteCharacteristicsDataImplTest, BasicTestEndToEnd) { - auto local_site_data = - GetDataImpl(kDummyOrigin, &destroy_delegate_, &database_); - - local_site_data->NotifySiteLoaded(); - local_site_data->NotifyLoadedSiteBackgrounded(); - - // Initially the feature usage should be reported as unknown. - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - local_site_data->UsesAudioInBackground()); - - // Advance the clock by a time lower than the miniumum observation time for - // the audio feature. - test_clock_.Advance(kObservationWindowLength - - base::TimeDelta::FromSeconds(1)); - - // The audio feature usage is still unknown as the observation window hasn't - // expired. - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - local_site_data->UsesAudioInBackground()); - - // Report that the audio feature has been used. - local_site_data->NotifyUsesAudioInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - local_site_data->UsesAudioInBackground()); - - // When a feature is in use it's expected that its recorded observation - // timestamp is equal to the time delta since Unix Epoch when the observation - // has been made. - EXPECT_EQ(local_site_data->FeatureObservationTimestamp( - local_site_data->site_characteristics_for_testing() - .uses_audio_in_background()), - (test_clock_.NowTicks() - base::TimeTicks::UnixEpoch())); - EXPECT_EQ(local_site_data->FeatureObservationDuration( - local_site_data->site_characteristics_for_testing() - .uses_audio_in_background()), - base::TimeDelta()); - - // Advance the clock and make sure that title update feature gets reported as - // unused. - test_clock_.Advance(kObservationWindowLength); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureNotInUse, - local_site_data->UpdatesTitleInBackground()); - - // Observing that a feature has been used after its observation window has - // expired should still be recorded, the feature should then be reported as - // used. - local_site_data->NotifyUpdatesTitleInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - local_site_data->UpdatesTitleInBackground()); - - local_site_data->NotifySiteUnloaded( - performance_manager::TabVisibility::kBackground); -} - -TEST_F(LocalSiteCharacteristicsDataImplTest, LastLoadedTime) { - auto local_site_data = - GetDataImpl(kDummyOrigin, &destroy_delegate_, &database_); - - // Create a second instance of this object, simulates having several tab - // owning it. - auto local_site_data2(local_site_data); - - local_site_data->NotifySiteLoaded(); - base::TimeDelta last_loaded_time = - local_site_data->last_loaded_time_for_testing(); - - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - - // Loading the site a second time shouldn't change the last loaded time. - local_site_data2->NotifySiteLoaded(); - EXPECT_EQ(last_loaded_time, local_site_data2->last_loaded_time_for_testing()); - - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - - // Unloading the site shouldn't update the last loaded time as there's still - // a loaded instance. - local_site_data2->NotifySiteUnloaded( - performance_manager::TabVisibility::kForeground); - EXPECT_EQ(last_loaded_time, local_site_data->last_loaded_time_for_testing()); - - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - - local_site_data->NotifySiteUnloaded( - performance_manager::TabVisibility::kForeground); - EXPECT_NE(last_loaded_time, local_site_data->last_loaded_time_for_testing()); -} - -TEST_F(LocalSiteCharacteristicsDataImplTest, GetFeatureUsageForUnloadedSite) { - auto local_site_data = - GetDataImpl(kDummyOrigin, &destroy_delegate_, &database_); - - local_site_data->NotifySiteLoaded(); - local_site_data->NotifyLoadedSiteBackgrounded(); - local_site_data->NotifyUsesAudioInBackground(); - - test_clock_.Advance(kObservationWindowLength - - base::TimeDelta::FromSeconds(1)); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - local_site_data->UsesAudioInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - local_site_data->UpdatesTitleInBackground()); - - const base::TimeDelta observation_duration_before_unload = - local_site_data->FeatureObservationDuration( - local_site_data->site_characteristics_for_testing() - .updates_title_in_background()); - - local_site_data->NotifySiteUnloaded( - performance_manager::TabVisibility::kBackground); - - // Once unloaded the feature observations should still be accessible. - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - local_site_data->UsesAudioInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - local_site_data->UpdatesTitleInBackground()); - - // Advancing the clock shouldn't affect the observation duration for this - // feature. - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - EXPECT_EQ(observation_duration_before_unload, - local_site_data->FeatureObservationDuration( - local_site_data->site_characteristics_for_testing() - .updates_title_in_background())); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - local_site_data->UpdatesTitleInBackground()); - - local_site_data->NotifySiteLoaded(); - local_site_data->NotifyLoadedSiteBackgrounded(); - - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - local_site_data->UsesAudioInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureNotInUse, - local_site_data->UpdatesTitleInBackground()); - - local_site_data->NotifySiteUnloaded( - performance_manager::TabVisibility::kBackground); -} - -TEST_F(LocalSiteCharacteristicsDataImplTest, AllDurationGetSavedOnUnload) { - // This test helps making sure that the observation/timestamp fields get saved - // for all the features being tracked. - auto local_site_data = - GetDataImpl(kDummyOrigin, &destroy_delegate_, &database_); - - const base::TimeDelta kInterval = base::TimeDelta::FromSeconds(1); - const auto kIntervalInternalRepresentation = - TestLocalSiteCharacteristicsDataImpl::TimeDeltaToInternalRepresentation( - kInterval); - const auto kZeroIntervalInternalRepresentation = - TestLocalSiteCharacteristicsDataImpl::TimeDeltaToInternalRepresentation( - base::TimeDelta()); - - // The internal representation of a zero interval is expected to be equal to - // zero as the protobuf use variable size integers and so storing zero values - // is really efficient (uses only one bit). - EXPECT_EQ(0U, kZeroIntervalInternalRepresentation); - - local_site_data->NotifySiteLoaded(); - local_site_data->NotifyLoadedSiteBackgrounded(); - test_clock_.Advance(kInterval); - // Makes use of a feature to make sure that the observation timestamps get - // saved. - local_site_data->NotifyUsesAudioInBackground(); - local_site_data->NotifySiteUnloaded( - performance_manager::TabVisibility::kBackground); - - SiteDataProto expected_proto; - - auto expected_last_loaded_time = - TestLocalSiteCharacteristicsDataImpl::TimeDeltaToInternalRepresentation( - kInterval + kInitialTimeSinceEpoch); - - expected_proto.set_last_loaded(expected_last_loaded_time); - - // Features that haven't been used should have an observation duration of - // |kIntervalInternalRepresentation| and an observation timestamp equal to - // zero. - SiteDataFeatureProto unused_feature_proto; - unused_feature_proto.set_observation_duration( - kIntervalInternalRepresentation); - - expected_proto.mutable_updates_favicon_in_background()->CopyFrom( - unused_feature_proto); - expected_proto.mutable_updates_title_in_background()->CopyFrom( - unused_feature_proto); - - // The audio feature has been used, so its observation duration value should - // be equal to zero, and its observation timestamp should be equal to the last - // loaded time in this case (as this feature has been used right before - // unloading). - SiteDataFeatureProto used_feature_proto; - used_feature_proto.set_use_timestamp(expected_last_loaded_time); - expected_proto.mutable_uses_audio_in_background()->CopyFrom( - used_feature_proto); - - EXPECT_EQ( - expected_proto.SerializeAsString(), - local_site_data->site_characteristics_for_testing().SerializeAsString()); -} - -// Verify that the OnDestroyDelegate gets notified when a -// LocalSiteCharacteristicsDataImpl object gets destroyed. -TEST_F(LocalSiteCharacteristicsDataImplTest, DestroyNotifiesDelegate) { - ::testing::StrictMock< - testing::MockLocalSiteCharacteristicsDataImplOnDestroyDelegate> - strict_delegate; - { - auto local_site_data = - GetDataImpl(kDummyOrigin, &strict_delegate, &database_); - EXPECT_CALL(strict_delegate, OnLocalSiteCharacteristicsDataImplDestroyed( - local_site_data.get())); - } - ::testing::Mock::VerifyAndClear(&strict_delegate); -} - -TEST_F(LocalSiteCharacteristicsDataImplTest, - OnInitCallbackMergePreviousObservations) { - // Use a mock database to intercept the initialization callback and save it - // locally so it can be run later. This simulates an asynchronous - // initialization of this object and is used to test that the observations - // made between the time this object has been created and the callback is - // called get properly merged. - ::testing::StrictMock<MockLocalSiteCharacteristicsDatabase> mock_db; - LocalSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDBCallback - read_cb; - - auto local_site_data = GetDataImplAndInterceptReadCallback( - kDummyOrigin, &destroy_delegate_, &mock_db, &read_cb); - - // Simulates audio in background usage before the callback gets called. - local_site_data->NotifySiteLoaded(); - local_site_data->NotifyLoadedSiteBackgrounded(); - local_site_data->NotifyUsesAudioInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - local_site_data->UsesAudioInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - local_site_data->UpdatesFaviconInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - local_site_data->UpdatesTitleInBackground()); - - // Unload the site and save the last loaded time to make sure the - // initialization doesn't overwrite it. - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - local_site_data->NotifySiteUnloaded( - performance_manager::TabVisibility::kBackground); - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - auto last_loaded = local_site_data->last_loaded_time_for_testing(); - - // Add a couple of performance samples. - local_site_data->NotifyLoadTimePerformanceMeasurement( - base::TimeDelta::FromMicroseconds(100), - base::TimeDelta::FromMicroseconds(1000), 2000u); - local_site_data->NotifyLoadTimePerformanceMeasurement( - base::TimeDelta::FromMicroseconds(200), - base::TimeDelta::FromMicroseconds(500), 1000u); - - // Make sure the local performance samples are averaged as expected. - EXPECT_EQ(2U, local_site_data->load_duration().num_datums()); - EXPECT_EQ(150, local_site_data->load_duration().value()); - - EXPECT_EQ(2U, local_site_data->cpu_usage_estimate().num_datums()); - EXPECT_EQ(750.0, local_site_data->cpu_usage_estimate().value()); - - EXPECT_EQ(2U, local_site_data->private_footprint_kb_estimate().num_datums()); - EXPECT_EQ(1500.0, local_site_data->private_footprint_kb_estimate().value()); - - // This protobuf should have a valid |last_loaded| field and valid observation - // durations for each features, but the |use_timestamp| field shouldn't have - // been initialized for the features that haven't been used. - EXPECT_TRUE( - local_site_data->site_characteristics_for_testing().has_last_loaded()); - EXPECT_TRUE(local_site_data->site_characteristics_for_testing() - .uses_audio_in_background() - .has_use_timestamp()); - EXPECT_FALSE(local_site_data->site_characteristics_for_testing() - .has_load_time_estimates()); - - // Initialize a fake protobuf that indicates that this site updates its title - // while in background and set a fake last loaded time (this should be - // overriden once the callback runs). - base::Optional<SiteDataProto> test_proto = SiteDataProto(); - SiteDataFeatureProto unused_feature_proto = GetUnusedFeatureProto(); - test_proto->mutable_updates_title_in_background()->CopyFrom( - GetUsedFeatureProto()); - test_proto->mutable_updates_favicon_in_background()->CopyFrom( - unused_feature_proto); - test_proto->mutable_uses_audio_in_background()->CopyFrom( - unused_feature_proto); - test_proto->set_last_loaded(42); - - // Set the previously saved performance averages. - auto* estimates = test_proto->mutable_load_time_estimates(); - estimates->set_avg_load_duration_us(50); - estimates->set_avg_cpu_usage_us(250); - estimates->set_avg_footprint_kb(500); - - // Run the callback to indicate that the initialization has completed. - std::move(read_cb).Run(test_proto); - - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - local_site_data->UsesAudioInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - local_site_data->UpdatesTitleInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - local_site_data->UpdatesFaviconInBackground()); - EXPECT_EQ(last_loaded, local_site_data->last_loaded_time_for_testing()); - - // Make sure the local performance samples have been updated with the previous - // averages. - EXPECT_EQ(3U, local_site_data->load_duration().num_datums()); - EXPECT_EQ(137.5, local_site_data->load_duration().value()); - - EXPECT_EQ(3U, local_site_data->cpu_usage_estimate().num_datums()); - EXPECT_EQ(562.5, local_site_data->cpu_usage_estimate().value()); - - EXPECT_EQ(3U, local_site_data->private_footprint_kb_estimate().num_datums()); - EXPECT_EQ(1125, local_site_data->private_footprint_kb_estimate().value()); - - - // Verify that the in-memory data is flushed to the protobuffer on write. - EXPECT_CALL(mock_db, - WriteSiteCharacteristicsIntoDB(::testing::_, ::testing::_)) - .WillOnce(::testing::Invoke( - [](const url::Origin& origin, const SiteDataProto& proto) { - ASSERT_TRUE(proto.has_load_time_estimates()); - const auto& estimates = proto.load_time_estimates(); - ASSERT_TRUE(estimates.has_avg_load_duration_us()); - EXPECT_EQ(137.5, estimates.avg_load_duration_us()); - ASSERT_TRUE(estimates.has_avg_cpu_usage_us()); - EXPECT_EQ(562.5, estimates.avg_cpu_usage_us()); - ASSERT_TRUE(estimates.has_avg_footprint_kb()); - EXPECT_EQ(1125, estimates.avg_footprint_kb()); - })); - - local_site_data = nullptr; - ::testing::Mock::VerifyAndClear(&mock_db); -} - -TEST_F(LocalSiteCharacteristicsDataImplTest, LateAsyncReadDoesntEraseData) { - // Ensure that no historical data get lost if an asynchronous read from the - // database finishes after the last reference to a - // LocalSiteCharacteristicsDataImpl gets destroyed. - - ::testing::StrictMock<MockLocalSiteCharacteristicsDatabase> mock_db; - LocalSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDBCallback - read_cb; - - auto local_site_data_writer = GetDataImplAndInterceptReadCallback( - kDummyOrigin, &destroy_delegate_, &mock_db, &read_cb); - - local_site_data_writer->NotifySiteLoaded(); - local_site_data_writer->NotifyLoadedSiteBackgrounded(); - local_site_data_writer->NotifyUsesAudioInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - local_site_data_writer->UsesAudioInBackground()); - - local_site_data_writer->NotifySiteUnloaded( - performance_manager::TabVisibility::kBackground); - - // Releasing |local_site_data_writer| should cause this object to get - // destroyed but there shouldn't be any write operation as the read hasn't - // completed. - EXPECT_CALL(destroy_delegate_, - OnLocalSiteCharacteristicsDataImplDestroyed(::testing::_)); - EXPECT_CALL(mock_db, - WriteSiteCharacteristicsIntoDB(::testing::_, ::testing::_)) - .Times(0); - local_site_data_writer = nullptr; - ::testing::Mock::VerifyAndClear(&destroy_delegate_); - ::testing::Mock::VerifyAndClear(&mock_db); - - EXPECT_TRUE(read_cb.IsCancelled()); -} - -TEST_F(LocalSiteCharacteristicsDataImplTest, - LateAsyncReadDoesntBypassClearEvent) { - ::testing::NiceMock<MockLocalSiteCharacteristicsDatabase> mock_db; - LocalSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDBCallback - read_cb; - - auto local_site_data = GetDataImplAndInterceptReadCallback( - kDummyOrigin, &destroy_delegate_, &mock_db, &read_cb); - - local_site_data->NotifySiteLoaded(); - local_site_data->NotifyLoadedSiteBackgrounded(); - local_site_data->NotifyUsesAudioInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - local_site_data->UsesAudioInBackground()); - local_site_data->NotifySiteUnloaded( - performance_manager::TabVisibility::kBackground); - - // TODO(sebmarchand): Test that data is cleared here. - local_site_data->ClearObservationsAndInvalidateReadOperation(); - - EXPECT_TRUE(read_cb.IsCancelled()); -} - -TEST_F(LocalSiteCharacteristicsDataImplTest, BackgroundedCountTests) { - auto local_site_data = - GetDataImpl(kDummyOrigin, &destroy_delegate_, &database_); - - // By default the tabs are expected to be foregrounded. - EXPECT_EQ(0U, local_site_data->loaded_tabs_in_background_count_for_testing()); - - local_site_data->NotifySiteLoaded(); - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - local_site_data->NotifyLoadedSiteBackgrounded(); - - auto background_session_begin = - local_site_data->background_session_begin_for_testing(); - EXPECT_EQ(test_clock_.NowTicks(), background_session_begin); - - EXPECT_EQ(1U, local_site_data->loaded_tabs_in_background_count_for_testing()); - - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - - // Add a second instance of this object, this one pretending to be in - // foreground. - auto local_site_data_copy(local_site_data); - local_site_data_copy->NotifySiteLoaded(); - EXPECT_EQ(1U, local_site_data->loaded_tabs_in_background_count_for_testing()); - - EXPECT_EQ(background_session_begin, - local_site_data->background_session_begin_for_testing()); - - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - - local_site_data->NotifyLoadedSiteForegrounded(); - EXPECT_EQ(0U, local_site_data->loaded_tabs_in_background_count_for_testing()); - - auto expected_observation_duration = - test_clock_.NowTicks() - background_session_begin; - - auto observed_observation_duration = - local_site_data->FeatureObservationDuration( - local_site_data->site_characteristics_for_testing() - .updates_title_in_background()); - - EXPECT_EQ(expected_observation_duration, observed_observation_duration); - - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - - local_site_data->NotifyLoadedSiteBackgrounded(); - EXPECT_EQ(1U, local_site_data->loaded_tabs_in_background_count_for_testing()); - background_session_begin = - local_site_data->background_session_begin_for_testing(); - EXPECT_EQ(test_clock_.NowTicks(), background_session_begin); - - local_site_data->NotifySiteUnloaded( - performance_manager::TabVisibility::kBackground); - local_site_data_copy->NotifySiteUnloaded( - performance_manager::TabVisibility::kForeground); -} - -TEST_F(LocalSiteCharacteristicsDataImplTest, - OptionalFieldsNotPopulatedWhenClean) { - ::testing::StrictMock<MockLocalSiteCharacteristicsDatabase> mock_db; - LocalSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDBCallback - read_cb; - - auto local_site_data = GetDataImplAndInterceptReadCallback( - kDummyOrigin, &destroy_delegate_, &mock_db, &read_cb); - - EXPECT_EQ(0u, local_site_data->cpu_usage_estimate().num_datums()); - EXPECT_EQ(0u, local_site_data->private_footprint_kb_estimate().num_datums()); - - base::Optional<SiteDataProto> test_proto = SiteDataProto(); - - // Run the callback to indicate that the initialization has completed. - std::move(read_cb).Run(test_proto); - - // There still should be no perf data. - EXPECT_EQ(0u, local_site_data->cpu_usage_estimate().num_datums()); - EXPECT_EQ(0u, local_site_data->private_footprint_kb_estimate().num_datums()); - - // Dirty the record to force a write. - local_site_data->NotifySiteLoaded(); - local_site_data->NotifyLoadedSiteBackgrounded(); - local_site_data->NotifyUsesAudioInBackground(); - - // Verify that the saved protobuffer isn't populated with the perf fields. - EXPECT_CALL(mock_db, - WriteSiteCharacteristicsIntoDB(::testing::_, ::testing::_)) - .WillOnce(::testing::Invoke( - [](const url::Origin& origin, const SiteDataProto& proto) { - ASSERT_FALSE(proto.has_load_time_estimates()); - })); - - local_site_data->NotifySiteUnloaded( - performance_manager::TabVisibility::kBackground); - local_site_data = nullptr; - ::testing::Mock::VerifyAndClear(&mock_db); -} - -TEST_F(LocalSiteCharacteristicsDataImplTest, - FlushingStateToProtoDoesntAffectData) { - // Create 2 DataImpl object and do the same operations on them, ensures that - // calling FlushStateToProto doesn't affect the data that gets recorded. - - auto local_site_data = - GetDataImpl(kDummyOrigin, &destroy_delegate_, &database_); - auto local_site_data_ref = - GetDataImpl(kDummyOrigin2, &destroy_delegate_, &database_); - - local_site_data->NotifySiteLoaded(); - local_site_data->NotifyLoadedSiteBackgrounded(); - local_site_data_ref->NotifySiteLoaded(); - local_site_data_ref->NotifyLoadedSiteBackgrounded(); - - test_clock_.Advance(base::TimeDelta::FromSeconds(15)); - local_site_data->FlushStateToProto(); - test_clock_.Advance(base::TimeDelta::FromSeconds(15)); - - local_site_data->NotifyUsesAudioInBackground(); - local_site_data_ref->NotifyUsesAudioInBackground(); - - local_site_data->FlushStateToProto(); - - EXPECT_EQ(local_site_data->FeatureObservationTimestamp( - local_site_data->site_characteristics_for_testing() - .uses_audio_in_background()), - local_site_data_ref->FeatureObservationTimestamp( - local_site_data_ref->site_characteristics_for_testing() - .uses_audio_in_background())); - - EXPECT_EQ(local_site_data->FeatureObservationDuration( - local_site_data->site_characteristics_for_testing() - .updates_title_in_background()), - local_site_data_ref->FeatureObservationDuration( - local_site_data_ref->site_characteristics_for_testing() - .updates_title_in_background())); - - local_site_data->NotifySiteUnloaded( - performance_manager::TabVisibility::kBackground); - local_site_data_ref->NotifySiteUnloaded( - performance_manager::TabVisibility::kBackground); -} - -TEST_F(LocalSiteCharacteristicsDataImplTest, DataLoadedCallbackInvoked) { - ::testing::StrictMock<MockLocalSiteCharacteristicsDatabase> mock_db; - LocalSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDBCallback - read_cb; - - auto local_site_data = GetDataImplAndInterceptReadCallback( - kDummyOrigin, &destroy_delegate_, &mock_db, &read_cb); - - EXPECT_FALSE(local_site_data->DataLoaded()); - - bool callback_invoked = false; - local_site_data->RegisterDataLoadedCallback( - base::BindLambdaForTesting([&]() { callback_invoked = true; })); - - // Run the callback to indicate that the initialization has completed. - base::Optional<SiteDataProto> test_proto = SiteDataProto(); - std::move(read_cb).Run(test_proto); - - EXPECT_TRUE(callback_invoked); - EXPECT_TRUE(local_site_data->DataLoaded()); -} - -} // namespace internal -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.cc deleted file mode 100644 index 5cdda44..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.cc +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h" - -#include <utility> - -#include "base/bind.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h" - -namespace resource_coordinator { - -LocalSiteCharacteristicsDataReader::LocalSiteCharacteristicsDataReader( - scoped_refptr<internal::LocalSiteCharacteristicsDataImpl> impl) - : impl_(std::move(impl)) {} - -LocalSiteCharacteristicsDataReader::~LocalSiteCharacteristicsDataReader() {} - -performance_manager::SiteFeatureUsage -LocalSiteCharacteristicsDataReader::UpdatesFaviconInBackground() const { - return impl_->UpdatesFaviconInBackground(); -} - -performance_manager::SiteFeatureUsage -LocalSiteCharacteristicsDataReader::UpdatesTitleInBackground() const { - return impl_->UpdatesTitleInBackground(); -} - -performance_manager::SiteFeatureUsage -LocalSiteCharacteristicsDataReader::UsesAudioInBackground() const { - return impl_->UsesAudioInBackground(); -} - -bool LocalSiteCharacteristicsDataReader::DataLoaded() const { - return impl_->DataLoaded(); -} - -void LocalSiteCharacteristicsDataReader::RegisterDataLoadedCallback( - base::OnceClosure&& callback) { - // Register a closure that is bound using a weak pointer to this instance. - // In that way it won't be invoked by the underlying |impl_| after this - // reader is destroyed. - base::OnceClosure closure( - base::BindOnce(&LocalSiteCharacteristicsDataReader::RunClosure, - weak_factory_.GetWeakPtr(), std::move(callback))); - impl_->RegisterDataLoadedCallback(std::move(closure)); -} - -void LocalSiteCharacteristicsDataReader::RunClosure( - base::OnceClosure&& closure) { - std::move(closure).Run(); -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h b/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h deleted file mode 100644 index 9649582..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_READER_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_READER_H_ - -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "chrome/browser/resource_coordinator/site_characteristics_data_reader.h" - -namespace resource_coordinator { - -FORWARD_DECLARE_TEST(LocalSiteCharacteristicsDataReaderTest, - FreeingReaderDoesntCauseWriteOperation); - -namespace internal { -class LocalSiteCharacteristicsDataImpl; -} // namespace internal - -// Specialization of a SiteCharacteristicDataReader that delegates to a -// LocalSiteCharacteristicsDataImpl. -class LocalSiteCharacteristicsDataReader - : public SiteCharacteristicsDataReader { - public: - ~LocalSiteCharacteristicsDataReader() override; - - // SiteCharacteristicsDataReader: - performance_manager::SiteFeatureUsage UpdatesFaviconInBackground() - const override; - performance_manager::SiteFeatureUsage UpdatesTitleInBackground() - const override; - performance_manager::SiteFeatureUsage UsesAudioInBackground() const override; - bool DataLoaded() const override; - void RegisterDataLoadedCallback(base::OnceClosure&& callback) override; - - internal::LocalSiteCharacteristicsDataImpl* impl_for_testing() const { - return impl_.get(); - } - - private: - friend class LocalSiteCharacteristicsDataReaderTest; - friend class LocalSiteCharacteristicsDataStoreTest; - friend class LocalSiteCharacteristicsDataStore; - FRIEND_TEST_ALL_PREFIXES(LocalSiteCharacteristicsDataReaderTest, - DestroyingReaderCancelsPendingCallbacks); - FRIEND_TEST_ALL_PREFIXES(LocalSiteCharacteristicsDataReaderTest, - FreeingReaderDoesntCauseWriteOperation); - FRIEND_TEST_ALL_PREFIXES(LocalSiteCharacteristicsDataReaderTest, - OnDataLoadedCallbackInvoked); - - // Private constructor, these objects are meant to be created by a site - // characteristics data store. - explicit LocalSiteCharacteristicsDataReader( - scoped_refptr<internal::LocalSiteCharacteristicsDataImpl> impl); - - // Runs the provided closure. This is used as a wrapper so that callbacks - // registered with the |impl_| by this reader are invalidated when the - // reader is destroyed. - void RunClosure(base::OnceClosure&& closure); - - // The LocalSiteCharacteristicDataInternal object we delegate to. - const scoped_refptr<internal::LocalSiteCharacteristicsDataImpl> impl_; - - // Used for invalidating callbacks. - base::WeakPtrFactory<LocalSiteCharacteristicsDataReader> weak_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(LocalSiteCharacteristicsDataReader); -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_READER_H_
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_reader_unittest.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_reader_unittest.cc deleted file mode 100644 index 441e909..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_reader_unittest.cc +++ /dev/null
@@ -1,245 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h" - -#include <memory> - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/test/bind_test_util.h" -#include "base/test/simple_test_tick_clock.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" -#include "chrome/browser/resource_coordinator/time.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace resource_coordinator { - -namespace { - -class MockLocalSiteCharacteristicsDatabase - : public testing::NoopLocalSiteCharacteristicsDatabase { - public: - MockLocalSiteCharacteristicsDatabase() = default; - ~MockLocalSiteCharacteristicsDatabase() = default; - - // Note: As move-only parameters (e.g. OnceCallback) aren't supported by mock - // methods, add On... methods to pass a non-const reference to OnceCallback. - void ReadSiteCharacteristicsFromDB( - const url::Origin& origin, - LocalSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDBCallback - callback) override { - OnReadSiteCharacteristicsFromDB(std::move(origin), callback); - } - MOCK_METHOD2(OnReadSiteCharacteristicsFromDB, - void(const url::Origin&, - LocalSiteCharacteristicsDatabase:: - ReadSiteCharacteristicsFromDBCallback&)); - - MOCK_METHOD2(WriteSiteCharacteristicsIntoDB, - void(const url::Origin&, const SiteDataProto&)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockLocalSiteCharacteristicsDatabase); -}; - -void InitializeSiteDataProto(SiteDataProto* site_characteristics) { - DCHECK(site_characteristics); - site_characteristics->set_last_loaded(42); - - SiteDataFeatureProto used_feature_proto; - used_feature_proto.set_observation_duration(0U); - used_feature_proto.set_use_timestamp(1U); - - site_characteristics->mutable_updates_favicon_in_background()->CopyFrom( - used_feature_proto); - site_characteristics->mutable_updates_title_in_background()->CopyFrom( - used_feature_proto); - site_characteristics->mutable_uses_audio_in_background()->CopyFrom( - used_feature_proto); - - DCHECK(site_characteristics->IsInitialized()); -} - -} // namespace - -class LocalSiteCharacteristicsDataReaderTest : public ::testing::Test { - protected: - // The constructors needs to call 'new' directly rather than using the - // base::MakeRefCounted helper function because the constructor of - // LocalSiteCharacteristicsDataImpl is protected and not visible to - // base::MakeRefCounted. - LocalSiteCharacteristicsDataReaderTest() - : scoped_set_tick_clock_for_testing_(&test_clock_) { - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - test_impl_ = - base::WrapRefCounted(new internal::LocalSiteCharacteristicsDataImpl( - url::Origin::Create(GURL("foo.com")), &delegate_, &database_)); - test_impl_->NotifySiteLoaded(); - test_impl_->NotifyLoadedSiteBackgrounded(); - LocalSiteCharacteristicsDataReader* reader = - new LocalSiteCharacteristicsDataReader(test_impl_.get()); - reader_ = base::WrapUnique(reader); - } - - ~LocalSiteCharacteristicsDataReaderTest() override { - test_impl_->NotifySiteUnloaded( - performance_manager::TabVisibility::kBackground); - } - - base::SimpleTestTickClock test_clock_; - ScopedSetTickClockForTesting scoped_set_tick_clock_for_testing_; - - // The mock delegate used by the LocalSiteCharacteristicsDataImpl objects - // created by this class, NiceMock is used to avoid having to set expectations - // in test cases that don't care about this. - ::testing::NiceMock< - testing::MockLocalSiteCharacteristicsDataImplOnDestroyDelegate> - delegate_; - - // The LocalSiteCharacteristicsDataImpl object used in these tests. - scoped_refptr<internal::LocalSiteCharacteristicsDataImpl> test_impl_; - - // A LocalSiteCharacteristicsDataReader object associated with the origin used - // to create this object. - std::unique_ptr<LocalSiteCharacteristicsDataReader> reader_; - - testing::NoopLocalSiteCharacteristicsDatabase database_; - - DISALLOW_COPY_AND_ASSIGN(LocalSiteCharacteristicsDataReaderTest); -}; - -TEST_F(LocalSiteCharacteristicsDataReaderTest, TestAccessors) { - // Initially we have no information about any of the features. - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader_->UpdatesFaviconInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader_->UpdatesTitleInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader_->UsesAudioInBackground()); - - // Simulates a title update event, make sure it gets reported directly. - test_impl_->NotifyUpdatesTitleInBackground(); - - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader_->UpdatesTitleInBackground()); - - // Advance the clock by a large amount of time, enough for the unused features - // observation windows to expire. - test_clock_.Advance(base::TimeDelta::FromDays(31)); - - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureNotInUse, - reader_->UpdatesFaviconInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader_->UpdatesTitleInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureNotInUse, - reader_->UsesAudioInBackground()); -} - -TEST_F(LocalSiteCharacteristicsDataReaderTest, - FreeingReaderDoesntCauseWriteOperation) { - const url::Origin kOrigin = url::Origin::Create(GURL("foo.com")); - ::testing::StrictMock<MockLocalSiteCharacteristicsDatabase> database; - - // Override the read callback to simulate a successful read from the - // database. - SiteDataProto proto = {}; - InitializeSiteDataProto(&proto); - auto read_from_db_mock_impl = - [&](const url::Origin& origin, - LocalSiteCharacteristicsDatabase:: - ReadSiteCharacteristicsFromDBCallback& callback) { - std::move(callback).Run(base::Optional<SiteDataProto>(proto)); - }; - - EXPECT_CALL(database, OnReadSiteCharacteristicsFromDB( - ::testing::Property(&url::Origin::Serialize, - kOrigin.Serialize()), - ::testing::_)) - .WillOnce(::testing::Invoke(read_from_db_mock_impl)); - - std::unique_ptr<LocalSiteCharacteristicsDataReader> reader = - base::WrapUnique(new LocalSiteCharacteristicsDataReader( - base::WrapRefCounted(new internal::LocalSiteCharacteristicsDataImpl( - kOrigin, &delegate_, &database)))); - ::testing::Mock::VerifyAndClear(&database); - - EXPECT_TRUE(reader->impl_for_testing()->fully_initialized_for_testing()); - - // Resetting the reader shouldn't cause any write operation to the database. - EXPECT_CALL(database, - WriteSiteCharacteristicsIntoDB(::testing::_, ::testing::_)) - .Times(0); - reader.reset(); - ::testing::Mock::VerifyAndClear(&database); -} - -TEST_F(LocalSiteCharacteristicsDataReaderTest, OnDataLoadedCallbackInvoked) { - const url::Origin kOrigin = url::Origin::Create(GURL("foo.com")); - ::testing::StrictMock<MockLocalSiteCharacteristicsDatabase> database; - - // Create the impl. - EXPECT_CALL(database, OnReadSiteCharacteristicsFromDB( - ::testing::Property(&url::Origin::Serialize, - kOrigin.Serialize()), - ::testing::_)); - scoped_refptr<internal::LocalSiteCharacteristicsDataImpl> impl = - base::WrapRefCounted(new internal::LocalSiteCharacteristicsDataImpl( - kOrigin, &delegate_, &database)); - - // Create the reader. - std::unique_ptr<LocalSiteCharacteristicsDataReader> reader = - base::WrapUnique(new LocalSiteCharacteristicsDataReader(impl)); - EXPECT_FALSE(reader->DataLoaded()); - - // Register a data ready closure. - bool on_data_loaded = false; - reader->RegisterDataLoadedCallback(base::BindLambdaForTesting( - [&on_data_loaded]() { on_data_loaded = true; })); - - // Transition the impl to fully initialized, which should cause the callbacks - // to fire. - EXPECT_FALSE(impl->DataLoaded()); - EXPECT_FALSE(on_data_loaded); - impl->TransitionToFullyInitialized(); - EXPECT_TRUE(impl->DataLoaded()); - EXPECT_TRUE(on_data_loaded); -} - -TEST_F(LocalSiteCharacteristicsDataReaderTest, - DestroyingReaderCancelsPendingCallbacks) { - const url::Origin kOrigin = url::Origin::Create(GURL("foo.com")); - ::testing::StrictMock<MockLocalSiteCharacteristicsDatabase> database; - - // Create the impl. - EXPECT_CALL(database, OnReadSiteCharacteristicsFromDB( - ::testing::Property(&url::Origin::Serialize, - kOrigin.Serialize()), - ::testing::_)); - scoped_refptr<internal::LocalSiteCharacteristicsDataImpl> impl = - base::WrapRefCounted(new internal::LocalSiteCharacteristicsDataImpl( - kOrigin, &delegate_, &database)); - - // Create the reader. - std::unique_ptr<LocalSiteCharacteristicsDataReader> reader = - base::WrapUnique(new LocalSiteCharacteristicsDataReader(impl)); - EXPECT_FALSE(reader->DataLoaded()); - - // Register a data ready closure. - reader->RegisterDataLoadedCallback( - base::MakeExpectedNotRunClosure(FROM_HERE)); - - // Reset the reader. - reader.reset(); - - // Transition the impl to fully initialized, which should cause the callbacks - // to fire. The reader's callback should *not* be invoked. - EXPECT_FALSE(impl->DataLoaded()); - impl->TransitionToFullyInitialized(); - EXPECT_TRUE(impl->DataLoaded()); -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_store.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_store.cc deleted file mode 100644 index df64491..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_store.cc +++ /dev/null
@@ -1,193 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store.h" - -#include "base/feature_list.h" -#include "base/memory/ptr_util.h" -#include "base/stl_util.h" -#include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/resource_coordinator/leveldb_site_characteristics_database.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_writer.h" -#include "chrome/browser/resource_coordinator/tab_manager_features.h" -#include "components/history/core/browser/url_row.h" -#include "url/gurl.h" - -namespace resource_coordinator { - -namespace { - -constexpr char kSiteCharacteristicsDirectoryName[] = - "Site Characteristics Database"; - -size_t CountOriginsInURLRows(const history::URLRows& rows) { - std::set<GURL> origins; - for (auto& row : rows) - origins.insert(row.url().GetOrigin()); - return origins.size(); -} - -} // namespace - -LocalSiteCharacteristicsDataStore::LocalSiteCharacteristicsDataStore( - Profile* profile) - : profile_(profile) { - database_ = std::make_unique<LevelDBSiteCharacteristicsDatabase>( - profile->GetPath().AppendASCII(kSiteCharacteristicsDirectoryName)); - - history::HistoryService* history = - HistoryServiceFactory::GetForProfileWithoutCreating(profile); - if (history) - history_observer_.Add(history); - - // Register the debug interface against the profile. - LocalSiteCharacteristicsDataStoreInspector::SetForProfile(this, profile); -} - -LocalSiteCharacteristicsDataStore::~LocalSiteCharacteristicsDataStore() { - LocalSiteCharacteristicsDataStoreInspector::SetForProfile(nullptr, profile_); -} - -std::unique_ptr<SiteCharacteristicsDataReader> -LocalSiteCharacteristicsDataStore::GetReaderForOrigin( - const url::Origin& origin) { - internal::LocalSiteCharacteristicsDataImpl* impl = - GetOrCreateFeatureImpl(origin); - DCHECK(impl); - SiteCharacteristicsDataReader* data_reader = - new LocalSiteCharacteristicsDataReader(impl); - return base::WrapUnique(data_reader); -} - -std::unique_ptr<SiteCharacteristicsDataWriter> -LocalSiteCharacteristicsDataStore::GetWriterForOrigin( - const url::Origin& origin, - performance_manager::TabVisibility tab_visibility) { - internal::LocalSiteCharacteristicsDataImpl* impl = - GetOrCreateFeatureImpl(origin); - DCHECK(impl); - LocalSiteCharacteristicsDataWriter* data_writer = - new LocalSiteCharacteristicsDataWriter(impl, tab_visibility); - return base::WrapUnique(data_writer); -} - -bool LocalSiteCharacteristicsDataStore::IsRecordingForTesting() { - return true; -} - -const char* LocalSiteCharacteristicsDataStore::GetDataStoreName() { - return "LocalSiteCharacteristicsDataStore"; -} - -std::vector<url::Origin> -LocalSiteCharacteristicsDataStore::GetAllInMemoryOrigins() { - std::vector<url::Origin> ret; - - ret.reserve(origin_data_map_.size()); - for (const auto& entry : origin_data_map_) - ret.push_back(entry.first); - - return ret; -} - -void LocalSiteCharacteristicsDataStore::GetDatabaseSize( - DatabaseSizeCallback on_have_data) { - database_->GetDatabaseSize(std::move(on_have_data)); -} - -bool LocalSiteCharacteristicsDataStore::GetDataForOrigin( - const url::Origin& origin, - bool* is_dirty, - std::unique_ptr<SiteDataProto>* data) { - DCHECK_NE(nullptr, data); - const auto it = origin_data_map_.find(origin); - if (it == origin_data_map_.end()) - return false; - - std::unique_ptr<SiteDataProto> ret = std::make_unique<SiteDataProto>(); - ret->CopyFrom(it->second->FlushStateToProto()); - *is_dirty = it->second->is_dirty(); - *data = std::move(ret); - return true; -} - -LocalSiteCharacteristicsDataStore* -LocalSiteCharacteristicsDataStore::GetDataStore() { - return this; -} - -internal::LocalSiteCharacteristicsDataImpl* -LocalSiteCharacteristicsDataStore::GetOrCreateFeatureImpl( - const url::Origin& origin) { - // Start by checking if there's already an entry for this origin. - auto iter = origin_data_map_.find(origin); - if (iter != origin_data_map_.end()) - return iter->second; - - // If not create a new one and add it to the map. - internal::LocalSiteCharacteristicsDataImpl* site_characteristic_data = - new internal::LocalSiteCharacteristicsDataImpl(origin, this, - database_.get()); - - // internal::LocalSiteCharacteristicsDataImpl is a ref-counted object, it's - // safe to store a raw pointer to it here as this class will get notified when - // it's about to be destroyed and it'll be removed from the map. - origin_data_map_.insert(std::make_pair(origin, site_characteristic_data)); - return site_characteristic_data; -} - -void LocalSiteCharacteristicsDataStore:: - OnLocalSiteCharacteristicsDataImplDestroyed( - internal::LocalSiteCharacteristicsDataImpl* impl) { - DCHECK(impl); - DCHECK(base::Contains(origin_data_map_, impl->origin())); - // Remove the entry for this origin as this is about to get destroyed. - auto num_erased = origin_data_map_.erase(impl->origin()); - DCHECK_EQ(1U, num_erased); -} - -void LocalSiteCharacteristicsDataStore::OnURLsDeleted( - history::HistoryService* history_service, - const history::DeletionInfo& deletion_info) { - // It's not necessary to invalidate the pending DB write operations as they - // run on a sequenced task and so it's guaranteed that the remove operations - // posted here will run after any other pending operation. - if (deletion_info.IsAllHistory()) { - for (auto& data : origin_data_map_) - data.second->ClearObservationsAndInvalidateReadOperation(); - database_->ClearDatabase(); - } else { - std::vector<url::Origin> origins_to_remove; - - DCHECK_EQ(deletion_info.deleted_urls_origin_map().size(), - CountOriginsInURLRows(deletion_info.deleted_rows())); - for (const auto& it : deletion_info.deleted_urls_origin_map()) { - const url::Origin origin = url::Origin::Create(it.first); - const int remaining_visits_in_history = it.second.first; - - // If the origin no longer exists in history, clear the site - // characteristics from memory and from the database. - DCHECK_GE(remaining_visits_in_history, 0); - if (remaining_visits_in_history == 0) { - auto map_iter = origin_data_map_.find(origin); - if (map_iter != origin_data_map_.end()) - map_iter->second->ClearObservationsAndInvalidateReadOperation(); - - origins_to_remove.emplace_back(origin); - } - } - - if (!origins_to_remove.empty()) - database_->RemoveSiteCharacteristicsFromDB(origins_to_remove); - } -} - -void LocalSiteCharacteristicsDataStore::HistoryServiceBeingDeleted( - history::HistoryService* history_service) { - history_observer_.Remove(history_service); -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_store.h b/chrome/browser/resource_coordinator/local_site_characteristics_data_store.h deleted file mode 100644 index de68f331..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_store.h +++ /dev/null
@@ -1,114 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_STORE_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_STORE_H_ - -#include "base/containers/flat_map.h" -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/scoped_observer.h" -#include "base/sequence_checker.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h" -#include "chrome/browser/resource_coordinator/site_characteristics_data_store.h" -#include "chrome/browser/resource_coordinator/site_characteristics_data_writer.h" -#include "components/history/core/browser/history_service.h" -#include "components/history/core/browser/history_service_observer.h" - -class Profile; - -namespace resource_coordinator { - -class LocalSiteCharacteristicsDatabase; - -// Implementation of a SiteCharacteristicsDataStore that use the local site -// characteristics database as a backend. -// -// This class should never be used for off the record profiles, the -// LocalSiteCharacteristicsNonRecordingDataStore class should be used instead. -class LocalSiteCharacteristicsDataStore - : public SiteCharacteristicsDataStore, - public LocalSiteCharacteristicsDataStoreInspector, - public internal::LocalSiteCharacteristicsDataImpl::OnDestroyDelegate, - public history::HistoryServiceObserver { - public: - using LocalSiteCharacteristicsMap = - base::flat_map<url::Origin, internal::LocalSiteCharacteristicsDataImpl*>; - - explicit LocalSiteCharacteristicsDataStore(Profile* profile); - ~LocalSiteCharacteristicsDataStore() override; - - // SiteCharacteristicDataStore: - std::unique_ptr<SiteCharacteristicsDataReader> GetReaderForOrigin( - const url::Origin& origin) override; - std::unique_ptr<SiteCharacteristicsDataWriter> GetWriterForOrigin( - const url::Origin& origin, - performance_manager::TabVisibility tab_visibility) override; - bool IsRecordingForTesting() override; - - const LocalSiteCharacteristicsMap& origin_data_map_for_testing() const { - return origin_data_map_; - } - - // NOTE: This should be called before creating any - // LocalSiteCharacteristicsDataImpl object (this doesn't update the database - // used by these objects). - void SetDatabaseForTesting( - std::unique_ptr<LocalSiteCharacteristicsDatabase> database) { - database_ = std::move(database); - } - - // LocalSiteCharacteristicsDataStoreInspector: - const char* GetDataStoreName() override; - std::vector<url::Origin> GetAllInMemoryOrigins() override; - void GetDatabaseSize(DatabaseSizeCallback on_have_data) override; - bool GetDataForOrigin(const url::Origin& origin, - bool* is_dirty, - std::unique_ptr<SiteDataProto>* data) override; - LocalSiteCharacteristicsDataStore* GetDataStore() override; - - private: - FRIEND_TEST_ALL_PREFIXES(LocalSiteCharacteristicsDataStoreTest, EndToEnd); - FRIEND_TEST_ALL_PREFIXES(LocalSiteCharacteristicsDataStoreTest, - OnURLsDeleted_Partial_OriginNotReferenced); - FRIEND_TEST_ALL_PREFIXES(LocalSiteCharacteristicsDataStoreTest, - OnURLsDeleted_Partial_OriginStillReferenced); - FRIEND_TEST_ALL_PREFIXES(LocalSiteCharacteristicsDataStoreTest, - OnURLsDeleted_Full); - - // Returns a pointer to the LocalSiteCharacteristicsDataImpl object - // associated with |origin|, create one and add it to |origin_data_map_| - // if it doesn't exist. - internal::LocalSiteCharacteristicsDataImpl* GetOrCreateFeatureImpl( - const url::Origin& origin); - - // internal::LocalSiteCharacteristicsDataImpl::OnDestroyDelegate: - void OnLocalSiteCharacteristicsDataImplDestroyed( - internal::LocalSiteCharacteristicsDataImpl* impl) override; - - // history::HistoryServiceObserver: - void OnURLsDeleted(history::HistoryService* history_service, - const history::DeletionInfo& deletion_info) override; - void HistoryServiceBeingDeleted( - history::HistoryService* history_service) override; - - // Map a serialized origin to a LocalSiteCharacteristicDataInternal - // pointer. - LocalSiteCharacteristicsMap origin_data_map_; - - ScopedObserver<history::HistoryService, history::HistoryServiceObserver> - history_observer_{this}; - - std::unique_ptr<LocalSiteCharacteristicsDatabase> database_; - - // The profile this data store is associated with. - Profile* profile_; - - DISALLOW_COPY_AND_ASSIGN(LocalSiteCharacteristicsDataStore); -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_STORE_H_
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.cc deleted file mode 100644 index 0a87020..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.cc +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h" - -#include "base/feature_list.h" -#include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/profiles/incognito_helpers.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_non_recording_data_store.h" -#include "chrome/browser/resource_coordinator/tab_manager_features.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" -#include "content/public/browser/browser_context.h" - -namespace resource_coordinator { - -namespace { - -bool g_enable_for_testing = false; - -} // namespace - -// static -SiteCharacteristicsDataStore* -LocalSiteCharacteristicsDataStoreFactory::GetForProfile(Profile* profile) { - return static_cast<SiteCharacteristicsDataStore*>( - GetInstance()->GetServiceForBrowserContext(profile, true)); -} - -LocalSiteCharacteristicsDataStoreFactory* -LocalSiteCharacteristicsDataStoreFactory::GetInstance() { - static base::NoDestructor<LocalSiteCharacteristicsDataStoreFactory> instance; - return instance.get(); -} - -void LocalSiteCharacteristicsDataStoreFactory::EnableForTesting() { - g_enable_for_testing = true; -} - -LocalSiteCharacteristicsDataStoreFactory:: - LocalSiteCharacteristicsDataStoreFactory() - : BrowserContextKeyedServiceFactory( - "LocalSiteCharacteristicsDataStore", - BrowserContextDependencyManager::GetInstance()) { - DependsOn(HistoryServiceFactory::GetInstance()); -} - -LocalSiteCharacteristicsDataStoreFactory:: - ~LocalSiteCharacteristicsDataStoreFactory() = default; - -SiteCharacteristicsDataStore* -LocalSiteCharacteristicsDataStoreFactory::GetExistingDataStoreForContext( - content::BrowserContext* context) const { - DCHECK(context); - // Remove the const attribute from |this| and calls - // |GetServiceForBrowserContext| with the |create| parameter set to false. - // This is basically a getter that returns the data store associated with a - // context without creating it if it doesn't exits. - SiteCharacteristicsDataStore* data_store = - static_cast<SiteCharacteristicsDataStore*>( - const_cast<LocalSiteCharacteristicsDataStoreFactory*>(this) - ->GetServiceForBrowserContext(context, false /* create */)); - DCHECK(data_store); - return data_store; -} - -KeyedService* LocalSiteCharacteristicsDataStoreFactory::BuildServiceInstanceFor( - content::BrowserContext* context) const { - SiteCharacteristicsDataStore* data_store = nullptr; - Profile* profile = Profile::FromBrowserContext(context); - DCHECK(profile); - if (context->IsOffTheRecord()) { - content::BrowserContext* parent_context = - chrome::GetBrowserContextRedirectedInIncognito(context); - DCHECK(parent_context); - // Off the record profiles correspond to incognito profile and are derived - // from a parent profile that is on record. - DCHECK(!parent_context->IsOffTheRecord()); - LocalSiteCharacteristicsDataStoreInspector* parent_debug = - LocalSiteCharacteristicsDataStoreInspector::GetForProfile( - Profile::FromBrowserContext(parent_context)); - SiteCharacteristicsDataStore* data_store_for_readers = - GetExistingDataStoreForContext(parent_context); - DCHECK(data_store_for_readers); - data_store = new LocalSiteCharacteristicsNonRecordingDataStore( - profile, parent_debug, data_store_for_readers); - } else { - data_store = new LocalSiteCharacteristicsDataStore(profile); - } - DCHECK(data_store); - return data_store; -} - -content::BrowserContext* -LocalSiteCharacteristicsDataStoreFactory::GetBrowserContextToUse( - content::BrowserContext* context) const { - return chrome::GetBrowserContextOwnInstanceInIncognito(context); -} - -bool LocalSiteCharacteristicsDataStoreFactory:: - ServiceIsCreatedWithBrowserContext() const { - // If this factory is enabled for tests then it's preferable to create this - // service on demand so tests can use custom factories (via the - // SetTestingFactory function). - if (g_enable_for_testing) - return false; - - // Otherwise it's fine to initialize this service when the browser context - // gets created so the database will be ready when we need it. - return true; -} - -bool LocalSiteCharacteristicsDataStoreFactory::ServiceIsNULLWhileTesting() - const { - return !g_enable_for_testing; -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h b/chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h deleted file mode 100644 index 926f739..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_STORE_FACTORY_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_STORE_FACTORY_H_ - -#include "base/containers/flat_map.h" -#include "base/no_destructor.h" -#include "chrome/browser/resource_coordinator/site_characteristics_data_store.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" - -class Profile; - -namespace resource_coordinator { - -// Singleton that owns all the LocalSiteCharacteristicsDataStore instances and -// associates them with Profiles. -class LocalSiteCharacteristicsDataStoreFactory - : public BrowserContextKeyedServiceFactory { - public: - static SiteCharacteristicsDataStore* GetForProfile(Profile* profile); - static LocalSiteCharacteristicsDataStoreFactory* GetInstance(); - - // In production, an instance is created with the profile. In unit tests, no - // instance is created by default. If this method is called, an instance will - // be created the first time GetInstance() is called. In most unit tests, a - // custom factory should be set before the first call to GetInstance(). - static void EnableForTesting(); - - private: - friend class base::NoDestructor<LocalSiteCharacteristicsDataStoreFactory>; - - LocalSiteCharacteristicsDataStoreFactory(); - ~LocalSiteCharacteristicsDataStoreFactory() override; - - // Returns the |SiteCharacteristicsDataStore| instance associated with - // |context|. This is basically a wrapper around GetServiceForBrowserContext - // that allows calling it from a const function. - SiteCharacteristicsDataStore* GetExistingDataStoreForContext( - content::BrowserContext* context) const; - - // BrowserContextKeyedServiceFactory: - KeyedService* BuildServiceInstanceFor( - content::BrowserContext* context) const override; - content::BrowserContext* GetBrowserContextToUse( - content::BrowserContext* context) const override; - bool ServiceIsCreatedWithBrowserContext() const override; - bool ServiceIsNULLWhileTesting() const override; -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_STORE_FACTORY_H_
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory_browsertest.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory_browsertest.cc deleted file mode 100644 index f916f9d..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory_browsertest.cc +++ /dev/null
@@ -1,94 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h" - -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/profiles/profile_window.h" -#include "chrome/browser/resource_coordinator/tab_manager_features.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "content/public/browser/notification_service.h" -#include "content/public/test/browser_test.h" -#include "content/public/test/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_CHROMEOS) -#include "chromeos/constants/chromeos_switches.h" -#endif - -namespace resource_coordinator { - -namespace { - -// Ensures that a SiteCharacteristicsDataStore respect the |IsOffTheRecord| of -// its corresponding profile. -bool DataStoreRespectsOffTheRecordValue( - Profile* profile, - SiteCharacteristicsDataStore* data_store) { - return profile->IsOffTheRecord() == !data_store->IsRecordingForTesting(); -} - -} // namespace - -class LocalSiteCharacteristicsDataStoreFactoryTest - : public InProcessBrowserTest { - protected: - LocalSiteCharacteristicsDataStoreFactoryTest() = default; - ~LocalSiteCharacteristicsDataStoreFactoryTest() override = default; - - void SetUp() override { - InProcessBrowserTest::SetUp(); - } - -#if defined(OS_CHROMEOS) - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitch( - chromeos::switches::kIgnoreUserProfileMappingForTests); - } -#endif - - DISALLOW_COPY_AND_ASSIGN(LocalSiteCharacteristicsDataStoreFactoryTest); -}; - -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDataStoreFactoryTest, EndToEnd) { - Profile* regular_profile = browser()->profile(); - ASSERT_TRUE(regular_profile); - SiteCharacteristicsDataStore* recording_data_store = - LocalSiteCharacteristicsDataStoreFactory::GetForProfile(regular_profile); - ASSERT_TRUE(recording_data_store); - EXPECT_TRUE(DataStoreRespectsOffTheRecordValue(regular_profile, - recording_data_store)); - - Profile* incognito_profile = regular_profile->GetPrimaryOTRProfile(); - ASSERT_TRUE(incognito_profile); - SiteCharacteristicsDataStore* incognito_data_store = - static_cast<SiteCharacteristicsDataStore*>( - LocalSiteCharacteristicsDataStoreFactory::GetForProfile( - incognito_profile)); - ASSERT_TRUE(incognito_data_store); - EXPECT_NE(recording_data_store, incognito_data_store); - EXPECT_TRUE(DataStoreRespectsOffTheRecordValue(incognito_profile, - incognito_data_store)); - - profiles::SwitchToGuestProfile(ProfileManager::CreateCallback()); - ui_test_utils::WaitForBrowserToOpen(); - - ProfileManager* profile_manager = g_browser_process->profile_manager(); - Profile* guest_profile = - profile_manager->GetProfileByPath(ProfileManager::GetGuestProfilePath()); - ASSERT_TRUE(guest_profile); - SiteCharacteristicsDataStore* guest_data_store = - static_cast<SiteCharacteristicsDataStore*>( - LocalSiteCharacteristicsDataStoreFactory::GetForProfile( - guest_profile)); - ASSERT_TRUE(guest_data_store); - EXPECT_NE(recording_data_store, guest_data_store); - EXPECT_TRUE( - DataStoreRespectsOffTheRecordValue(guest_profile, guest_data_store)); -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.cc deleted file mode 100644 index 7732700..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.cc +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h" - -#include "base/macros.h" -#include "chrome/browser/profiles/profile.h" - -namespace resource_coordinator { - -namespace { - -const void* const kSiteCharacteristicsDataStoreInspectorUserKey = - &kSiteCharacteristicsDataStoreInspectorUserKey; - -class SiteCharacteristicsUserData : public base::SupportsUserData::Data { - public: - explicit SiteCharacteristicsUserData( - LocalSiteCharacteristicsDataStoreInspector* inspector) - : inspector_(inspector) {} - - LocalSiteCharacteristicsDataStoreInspector* inspector() const { - return inspector_; - } - - private: - LocalSiteCharacteristicsDataStoreInspector* inspector_; -}; - -} // namespace - -// static -LocalSiteCharacteristicsDataStoreInspector* -LocalSiteCharacteristicsDataStoreInspector::GetForProfile(Profile* profile) { - SiteCharacteristicsUserData* data = static_cast<SiteCharacteristicsUserData*>( - profile->GetUserData(kSiteCharacteristicsDataStoreInspectorUserKey)); - - if (!data) - return nullptr; - - return data->inspector(); -} - -// static -void LocalSiteCharacteristicsDataStoreInspector::SetForProfile( - LocalSiteCharacteristicsDataStoreInspector* inspector, - Profile* profile) { - if (inspector) { - DCHECK_EQ(nullptr, GetForProfile(profile)); - - profile->SetUserData( - kSiteCharacteristicsDataStoreInspectorUserKey, - std::make_unique<SiteCharacteristicsUserData>(inspector)); - } else { - DCHECK_NE(nullptr, GetForProfile(profile)); - profile->RemoveUserData(kSiteCharacteristicsDataStoreInspectorUserKey); - } -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h b/chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h deleted file mode 100644 index 812e815f..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h +++ /dev/null
@@ -1,77 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_STORE_INSPECTOR_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_STORE_INSPECTOR_H_ - -#include <cstdint> -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/optional.h" -#include "base/supports_user_data.h" -#include "components/performance_manager/persistence/site_data/site_data.pb.h" -#include "url/origin.h" - -class Profile; - -namespace resource_coordinator { - -class SiteCharacteristicsDataStore; - -// An interface that allows LocalSite data stores to expose diagnostic -// information for the associated web UI. -class LocalSiteCharacteristicsDataStoreInspector { - public: - // Retrieves the instance associated with a given profile, or nullptr - // if none is associated with that profile. - static LocalSiteCharacteristicsDataStoreInspector* GetForProfile( - Profile* profile); - - // Returns the name of the data store, which should uniquely identify the kind - // of storage it implements. - virtual const char* GetDataStoreName() = 0; - - // Retrieves the origins that are current represented by in-memory data - // at the present time. - virtual std::vector<url::Origin> GetAllInMemoryOrigins() = 0; - - // Retrieves the number of rows and the on-disk size of the DB. Invokes - // the |on_have_data| callback once the data has been collected, or once it's - // determined that the data can't be retrieved. - // On callback |num_rows| is the number of rows in the database, or -1 if - // the number can't be determined. |on_disk_size_kb| is the on-disk size of - // the database, or -1 if the on-disk size can't be determined. - using DatabaseSizeCallback = - base::OnceCallback<void(base::Optional<int64_t> num_rows, - base::Optional<int64_t> on_disk_size_kb)>; - virtual void GetDatabaseSize(DatabaseSizeCallback on_have_data) = 0; - - // Retrieves the in-memory data for a given origin. - // On return |data| contains the available data for |origin| if available, - // and |is_dirty| is true if the entry needs flushing to disk. - // Returns true if an entry exists for |origin|. - virtual bool GetDataForOrigin(const url::Origin& origin, - bool* is_dirty, - std::unique_ptr<SiteDataProto>* data) = 0; - - // Retrieves the data store this inspector is associated with. - virtual SiteCharacteristicsDataStore* GetDataStore() = 0; - - protected: - // Sets the inspector instance associated with a given profile. - // If |inspector| is nullptr the association is cleared. - // The caller must ensure that |inspector|'s registration is cleared before - // |inspector| or |profile| are deleted. - // The intent is for this to be called from implementation class' constructors - // and destructors. - static void SetForProfile( - LocalSiteCharacteristicsDataStoreInspector* inspector, - Profile* profile); -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_STORE_INSPECTOR_H_
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_store_unittest.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_store_unittest.cc deleted file mode 100644 index da1af9c2..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_store_unittest.cc +++ /dev/null
@@ -1,327 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store.h" - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/test/scoped_feature_list.h" -#include "base/test/simple_test_tick_clock.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" -#include "chrome/browser/resource_coordinator/time.h" -#include "chrome/test/base/testing_profile.h" -#include "components/history/core/browser/history_types.h" -#include "components/history/core/browser/url_row.h" -#include "content/public/test/browser_task_environment.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace resource_coordinator { - -namespace { - -constexpr base::TimeDelta kDelay = base::TimeDelta::FromMinutes(1); - -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -url::Origin Origin1() { - return url::Origin::Create(GURL("http://www.foo.com")); -} -url::Origin Origin2() { - return url::Origin::Create(GURL("http://www.bar.com")); -} - -class MockLocalSiteCharacteristicsDatabase - : public testing::NoopLocalSiteCharacteristicsDatabase { - public: - MockLocalSiteCharacteristicsDatabase() = default; - ~MockLocalSiteCharacteristicsDatabase() = default; - - MOCK_METHOD1(RemoveSiteCharacteristicsFromDB, - void(const std::vector<url::Origin>&)); - MOCK_METHOD0(ClearDatabase, void()); - - private: - DISALLOW_COPY_AND_ASSIGN(MockLocalSiteCharacteristicsDatabase); -}; - -} // namespace - -class LocalSiteCharacteristicsDataStoreTest : public ::testing::Test { - protected: - LocalSiteCharacteristicsDataStoreTest() - : scoped_set_tick_clock_for_testing_(&test_clock_) { - data_store_ = - std::make_unique<LocalSiteCharacteristicsDataStore>(&profile_); - mock_db_ = - new ::testing::StrictMock<MockLocalSiteCharacteristicsDatabase>(); - data_store_->SetDatabaseForTesting(base::WrapUnique(mock_db_)); - test_clock_.SetNowTicks(base::TimeTicks::UnixEpoch()); - test_clock_.Advance(base::TimeDelta::FromHours(1)); - WaitForAsyncOperationsToComplete(); - } - - void TearDown() override { WaitForAsyncOperationsToComplete(); } - - void WaitForAsyncOperationsToComplete() { task_environment_.RunUntilIdle(); } - - // Populates |writer_|, |reader_| and |data_| to refer to a tab navigated to - // |Origin1()| that updated its title in background. Populates |writer2_|, - // |reader2_| and |data2_| to refer to a tab navigated to |Origin2()| that - // updates its favicon in background. - void SetupTwoSitesUsingFeaturesInBackground() { - // Load a first origin, and then make use of a feature on it. - ASSERT_FALSE(reader_); - reader_ = data_store_->GetReaderForOrigin(Origin1()); - EXPECT_TRUE(reader_); - - ASSERT_FALSE(writer_); - writer_ = data_store_->GetWriterForOrigin( - Origin1(), performance_manager::TabVisibility::kBackground); - EXPECT_TRUE(writer_); - - ASSERT_FALSE(data_); - data_ = data_store_->origin_data_map_for_testing().find(Origin1())->second; - EXPECT_TRUE(data_); - - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader_->UpdatesTitleInBackground()); - writer_->NotifySiteLoaded(); - writer_->NotifyUpdatesTitleInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader_->UpdatesTitleInBackground()); - test_clock_.Advance(kDelay); - - // Load a second origin, make use of a feature on it too. - ASSERT_FALSE(reader2_); - reader2_ = data_store_->GetReaderForOrigin(Origin2()); - EXPECT_TRUE(reader2_); - - ASSERT_FALSE(writer2_); - writer2_ = data_store_->GetWriterForOrigin( - Origin2(), performance_manager::TabVisibility::kBackground); - EXPECT_TRUE(writer2_); - - ASSERT_FALSE(data2_); - data2_ = data_store_->origin_data_map_for_testing().find(Origin2())->second; - EXPECT_TRUE(data2_); - - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader2_->UpdatesFaviconInBackground()); - writer2_->NotifySiteLoaded(); - writer2_->NotifyUpdatesFaviconInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader2_->UpdatesFaviconInBackground()); - test_clock_.Advance(kDelay); - } - - base::SimpleTestTickClock test_clock_; - ScopedSetTickClockForTesting scoped_set_tick_clock_for_testing_; - content::BrowserTaskEnvironment task_environment_; - TestingProfile profile_; - - // Owned by |data_store_|. - ::testing::StrictMock<MockLocalSiteCharacteristicsDatabase>* mock_db_ = - nullptr; - std::unique_ptr<LocalSiteCharacteristicsDataStore> data_store_; - - std::unique_ptr<SiteCharacteristicsDataReader> reader_; - std::unique_ptr<SiteCharacteristicsDataWriter> writer_; - internal::LocalSiteCharacteristicsDataImpl* data_ = nullptr; - - std::unique_ptr<SiteCharacteristicsDataReader> reader2_; - std::unique_ptr<SiteCharacteristicsDataWriter> writer2_; - internal::LocalSiteCharacteristicsDataImpl* data2_ = nullptr; -}; - -TEST_F(LocalSiteCharacteristicsDataStoreTest, EndToEnd) { - auto reader = data_store_->GetReaderForOrigin(Origin1()); - EXPECT_TRUE(reader); - auto writer = data_store_->GetWriterForOrigin( - Origin1(), performance_manager::TabVisibility::kBackground); - EXPECT_TRUE(writer); - - EXPECT_EQ(1U, data_store_->origin_data_map_for_testing().size()); - - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UpdatesTitleInBackground()); - writer->NotifySiteLoaded(); - writer->NotifyUpdatesTitleInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader->UpdatesTitleInBackground()); - writer->NotifySiteUnloaded(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader->UpdatesTitleInBackground()); - - auto reader_copy = data_store_->GetReaderForOrigin(Origin1()); - EXPECT_EQ(1U, data_store_->origin_data_map_for_testing().size()); - auto reader2 = data_store_->GetReaderForOrigin(Origin2()); - EXPECT_EQ(2U, data_store_->origin_data_map_for_testing().size()); - reader2.reset(); - - WaitForAsyncOperationsToComplete(); - EXPECT_EQ(1U, data_store_->origin_data_map_for_testing().size()); - reader_copy.reset(); - - reader.reset(); - writer.reset(); - EXPECT_TRUE(data_store_->origin_data_map_for_testing().empty()); - - EXPECT_CALL(*mock_db_, ClearDatabase()); - data_store_->OnURLsDeleted(nullptr, history::DeletionInfo::ForAllHistory()); -} - -// Verify that an origin is removed from the data store (in memory and on disk) -// when there are no more references to it in the history, after the history is -// partially cleared. -TEST_F(LocalSiteCharacteristicsDataStoreTest, - OnURLsDeleted_Partial_OriginNotReferenced) { - SetupTwoSitesUsingFeaturesInBackground(); - - const base::TimeDelta last_loaded_time2_before_urls_deleted = - data2_->last_loaded_time_for_testing(); - - // Make sure that all data passed to |OnURLsDeleted| get passed to the - // database, even if they're not in the internal map used by the data store. - const url::Origin kOriginNotInMap = - url::Origin::Create(GURL("http://www.url-not-in-map.com")); - history::URLRows urls_to_delete = {history::URLRow(Origin1().GetURL()), - history::URLRow(kOriginNotInMap.GetURL())}; - history::DeletionInfo deletion_info = - history::DeletionInfo::ForUrls(urls_to_delete, std::set<GURL>()); - deletion_info.set_deleted_urls_origin_map({ - {Origin1().GetURL(), {0, base::Time::Now()}}, - {kOriginNotInMap.GetURL(), {0, base::Time::Now()}}, - }); - EXPECT_CALL(*mock_db_, - RemoveSiteCharacteristicsFromDB(::testing::WhenSorted( - ::testing::ElementsAre(Origin1(), kOriginNotInMap)))); - data_store_->OnURLsDeleted(nullptr, deletion_info); - ::testing::Mock::VerifyAndClear(mock_db_); - - // The information for the first site should have been cleared. The last - // loaded time should be equal to the current time. - EXPECT_EQ(data_->last_loaded_time_for_testing(), - test_clock_.NowTicks() - base::TimeTicks::UnixEpoch()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader_->UpdatesTitleInBackground()); - // The second site shouldn't have been cleared. - EXPECT_EQ(data2_->last_loaded_time_for_testing(), - last_loaded_time2_before_urls_deleted); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader2_->UpdatesFaviconInBackground()); - - writer_->NotifySiteUnloaded(); - writer2_->NotifySiteUnloaded(); -} - -// Verify that an origin is *not* removed from the data store (in memory and on -// disk) when there remain references to it in the history, after the history is -// partially cleared. -TEST_F(LocalSiteCharacteristicsDataStoreTest, - OnURLsDeleted_Partial_OriginStillReferenced) { - SetupTwoSitesUsingFeaturesInBackground(); - - const base::TimeDelta last_loaded_time_before_urls_deleted = - data_->last_loaded_time_for_testing(); - const base::TimeDelta last_loaded_time2_before_urls_deleted = - data2_->last_loaded_time_for_testing(); - - // Make sure that all data passed to |OnURLsDeleted| get passed to the - // database, even if they're not in the internal map used by the data store. - const url::Origin kOriginNotInMap = - url::Origin::Create(GURL("http://www.url-not-in-map.com")); - history::URLRows urls_to_delete = {history::URLRow(Origin1().GetURL()), - history::URLRow(kOriginNotInMap.GetURL())}; - history::DeletionInfo deletion_info = - history::DeletionInfo::ForUrls(urls_to_delete, std::set<GURL>()); - deletion_info.set_deleted_urls_origin_map({ - {Origin1().GetURL(), {4, base::Time::Now()}}, - {kOriginNotInMap.GetURL(), {3, base::Time::Now()}}, - }); - data_store_->OnURLsDeleted(nullptr, deletion_info); - ::testing::Mock::VerifyAndClear(mock_db_); - - // Sites shouldn't have been cleared. - EXPECT_EQ(data_->last_loaded_time_for_testing(), - last_loaded_time_before_urls_deleted); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader_->UpdatesTitleInBackground()); - EXPECT_EQ(data2_->last_loaded_time_for_testing(), - last_loaded_time2_before_urls_deleted); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader2_->UpdatesFaviconInBackground()); - - writer_->NotifySiteUnloaded(); - writer2_->NotifySiteUnloaded(); -} - -// Verify that origins are removed from the data store (in memory and on disk) -// when the history is completely cleared. -TEST_F(LocalSiteCharacteristicsDataStoreTest, OnURLsDeleted_Full) { - SetupTwoSitesUsingFeaturesInBackground(); - - // Delete all the information stored in the data store. - EXPECT_CALL(*mock_db_, ClearDatabase()); - data_store_->OnURLsDeleted(nullptr, history::DeletionInfo::ForAllHistory()); - ::testing::Mock::VerifyAndClear(mock_db_); - - // The information for both sites should have been cleared. - EXPECT_EQ(data_->last_loaded_time_for_testing(), - test_clock_.NowTicks() - base::TimeTicks::UnixEpoch()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader_->UpdatesTitleInBackground()); - EXPECT_EQ(data2_->last_loaded_time_for_testing(), - test_clock_.NowTicks() - base::TimeTicks::UnixEpoch()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader2_->UpdatesFaviconInBackground()); - - writer_->NotifySiteUnloaded(); - writer2_->NotifySiteUnloaded(); -} - -TEST_F(LocalSiteCharacteristicsDataStoreTest, InspectorWorks) { - // Make sure the inspector interface was registered at construction. - LocalSiteCharacteristicsDataStoreInspector* inspector = - LocalSiteCharacteristicsDataStoreInspector::GetForProfile(&profile_); - EXPECT_NE(nullptr, inspector); - EXPECT_EQ(data_store_.get(), inspector); - - EXPECT_STREQ("LocalSiteCharacteristicsDataStore", - inspector->GetDataStoreName()); - - // We expect an empty data store at the outset. - EXPECT_EQ(0U, inspector->GetAllInMemoryOrigins().size()); - std::unique_ptr<SiteDataProto> data; - bool is_dirty = false; - EXPECT_FALSE(inspector->GetDataForOrigin(Origin1(), &is_dirty, &data)); - EXPECT_FALSE(is_dirty); - EXPECT_EQ(nullptr, data.get()); - - { - // Add an entry, see that it's reflected in the inspector interface. - auto writer = data_store_->GetWriterForOrigin( - Origin1(), performance_manager::TabVisibility::kBackground); - - EXPECT_EQ(1U, inspector->GetAllInMemoryOrigins().size()); - EXPECT_TRUE(inspector->GetDataForOrigin(Origin1(), &is_dirty, &data)); - EXPECT_FALSE(is_dirty); - ASSERT_NE(nullptr, data.get()); - - // Touch the underlying data, see that the dirty bit updates. - writer->NotifySiteLoaded(); - EXPECT_TRUE(inspector->GetDataForOrigin(Origin1(), &is_dirty, &data)); - EXPECT_TRUE(is_dirty); - } - - // Make sure the interface is unregistered from the profile on destruction. - data_store_.reset(); - EXPECT_EQ(nullptr, LocalSiteCharacteristicsDataStoreInspector::GetForProfile( - &profile_)); -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc deleted file mode 100644 index 3812f80..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc +++ /dev/null
@@ -1,127 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" - -#include <utility> - -#include "base/bind_helpers.h" -#include "base/task/post_task.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h" -#include "chrome/browser/resource_coordinator/tab_helper.h" -#include "chrome/browser/tab_contents/form_interaction_tab_helper.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/system_connector.h" -#include "content/public/browser/web_contents.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" - -namespace resource_coordinator { -namespace testing { - -internal::LocalSiteCharacteristicsDataImpl* -GetLocalSiteCharacteristicsDataImplForWC(content::WebContents* web_contents) { - ResourceCoordinatorTabHelper* tab_helper = - ResourceCoordinatorTabHelper::FromWebContents(web_contents); - DCHECK(tab_helper); - auto* wc_observer = tab_helper->local_site_characteristics_wc_observer(); - DCHECK(wc_observer); - - auto* writer = static_cast<LocalSiteCharacteristicsDataWriter*>( - wc_observer->GetWriterForTesting()); - - if (!writer) - return nullptr; - - return writer->impl_for_testing(); -} - -void WaitForLocalDBEntryToBeInitialized( - content::WebContents* web_contents, - base::RepeatingClosure run_pending_tasks) { - internal::LocalSiteCharacteristicsDataImpl* impl = - GetLocalSiteCharacteristicsDataImplForWC(web_contents); - DCHECK(impl); - while (!impl->fully_initialized_for_testing()) - run_pending_tasks.Run(); -} - -void ExpireLocalDBObservationWindows(content::WebContents* web_contents) { - internal::LocalSiteCharacteristicsDataImpl* impl = - GetLocalSiteCharacteristicsDataImplForWC(web_contents); - DCHECK(impl); - impl->ExpireAllObservationWindowsForTesting(); -} - -void MarkWebContentsAsLoadedInBackground(content::WebContents* web_contents) { - internal::LocalSiteCharacteristicsDataImpl* impl = - GetLocalSiteCharacteristicsDataImplForWC(web_contents); - DCHECK(impl); - impl->NotifySiteLoaded(); - impl->NotifyLoadedSiteBackgrounded(); -} - -MockLocalSiteCharacteristicsDataImplOnDestroyDelegate:: - MockLocalSiteCharacteristicsDataImplOnDestroyDelegate() = default; -MockLocalSiteCharacteristicsDataImplOnDestroyDelegate:: - ~MockLocalSiteCharacteristicsDataImplOnDestroyDelegate() = default; - -NoopLocalSiteCharacteristicsDatabase::NoopLocalSiteCharacteristicsDatabase() = - default; -NoopLocalSiteCharacteristicsDatabase::~NoopLocalSiteCharacteristicsDatabase() = - default; - -void NoopLocalSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDB( - const url::Origin& origin, - ReadSiteCharacteristicsFromDBCallback callback) { - std::move(callback).Run(base::nullopt); -} - -void NoopLocalSiteCharacteristicsDatabase::WriteSiteCharacteristicsIntoDB( - const url::Origin& origin, - const SiteDataProto& site_characteristic_proto) {} - -void NoopLocalSiteCharacteristicsDatabase::RemoveSiteCharacteristicsFromDB( - const std::vector<url::Origin>& site_origins) {} - -void NoopLocalSiteCharacteristicsDatabase::ClearDatabase() {} - -void NoopLocalSiteCharacteristicsDatabase::GetDatabaseSize( - GetDatabaseSizeCallback callback) { - std::move(callback).Run(base::nullopt, base::nullopt); -} - -ChromeTestHarnessWithLocalDB::~ChromeTestHarnessWithLocalDB() = default; - -void ChromeTestHarnessWithLocalDB::SetUp() { - // TODO(siggi): Can this die now? - mojo::PendingReceiver<service_manager::mojom::Connector> connector_receiver; - content::SetSystemConnectorForTesting( - service_manager::Connector::Create(&connector_receiver)); - - // Enable the LocalSiteCharacteristicsDataStoreFactory before calling - // ChromeRenderViewHostTestHarness::SetUp(), this will prevent the creation - // of a non-mock version of a data store when browser_context() gets - // initialized. - pm_harness_.SetUp(); - - performance_manager::PerformanceManagerImpl::CallOnGraph( - FROM_HERE, base::BindOnce([](performance_manager::Graph* graph) { - graph->PassToGraph(FormInteractionTabHelper::CreateGraphObserver()); - })); - - LocalSiteCharacteristicsDataStoreFactory::EnableForTesting(); - - ChromeRenderViewHostTestHarness::SetUp(); -} - -void ChromeTestHarnessWithLocalDB::TearDown() { - pm_harness_.TearDown(); - content::SetSystemConnectorForTesting(nullptr); - ChromeRenderViewHostTestHarness::TearDown(); -} - -} // namespace testing -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h b/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h deleted file mode 100644 index 9416e085..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_UNITTEST_UTILS_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_UNITTEST_UTILS_H_ - -#include <memory> - -#include "base/callback_forward.h" -#include "base/macros.h" -#include "base/test/scoped_feature_list.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_database.h" -#include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "components/performance_manager/performance_manager_impl.h" -#include "components/performance_manager/test_support/test_harness_helper.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace content { -class WebContents; -} - -namespace resource_coordinator { - -namespace testing { - -// Return the LocalSiteCharacteristicsDataImpl instance backing a WebContents, -// this might be null if this WebContents isn't loaded with a valid URL. -internal::LocalSiteCharacteristicsDataImpl* -GetLocalSiteCharacteristicsDataImplForWC(content::WebContents* web_contents); - -// Wait for the Local Site Characteristics Database entry for a given -// WebContents to be initialized, run |run_pending_tasks| repeatedly while -// waiting. -void WaitForLocalDBEntryToBeInitialized( - content::WebContents* web_contents, - base::RepeatingClosure run_pending_tasks); - -// Expire all the Local Site Characteristics Database observation windows -// for a given WebContents. -void ExpireLocalDBObservationWindows(content::WebContents* web_contents); - -// Pretend that this WebContents has been loaded in background. -void MarkWebContentsAsLoadedInBackground(content::WebContents* web_contents); - -class MockLocalSiteCharacteristicsDataImplOnDestroyDelegate - : public internal::LocalSiteCharacteristicsDataImpl::OnDestroyDelegate { - public: - MockLocalSiteCharacteristicsDataImplOnDestroyDelegate(); - ~MockLocalSiteCharacteristicsDataImplOnDestroyDelegate(); - - MOCK_METHOD1(OnLocalSiteCharacteristicsDataImplDestroyed, - void(internal::LocalSiteCharacteristicsDataImpl*)); - - private: - DISALLOW_COPY_AND_ASSIGN( - MockLocalSiteCharacteristicsDataImplOnDestroyDelegate); -}; - -// An implementation of a LocalSiteCharacteristicsDatabase that doesn't record -// anything. -class NoopLocalSiteCharacteristicsDatabase - : public LocalSiteCharacteristicsDatabase { - public: - NoopLocalSiteCharacteristicsDatabase(); - ~NoopLocalSiteCharacteristicsDatabase() override; - - // LocalSiteCharacteristicsDatabase: - void ReadSiteCharacteristicsFromDB( - const url::Origin& origin, - ReadSiteCharacteristicsFromDBCallback callback) override; - void WriteSiteCharacteristicsIntoDB( - const url::Origin& origin, - const SiteDataProto& site_characteristic_proto) override; - void RemoveSiteCharacteristicsFromDB( - const std::vector<url::Origin>& site_origins) override; - void ClearDatabase() override; - void GetDatabaseSize(GetDatabaseSizeCallback callback) override; - - private: - DISALLOW_COPY_AND_ASSIGN(NoopLocalSiteCharacteristicsDatabase); -}; - -// A wrapper around ChromeRenderViewHostTestHarness that ensures that the Local -// Site Characteristics Database is initialized. -class ChromeTestHarnessWithLocalDB : public ChromeRenderViewHostTestHarness { - public: - // Construct a ChromeTestHarnessWithLocalDB with zero or more arguments - // passed to ChromeRenderViewHostTestHarness. - template <typename... TaskEnvironmentTraits> - explicit ChromeTestHarnessWithLocalDB(TaskEnvironmentTraits&&... traits) - : ChromeRenderViewHostTestHarness( - std::forward<TaskEnvironmentTraits>(traits)...) { - } - - ~ChromeTestHarnessWithLocalDB() override; - - protected: - void SetUp() override; - void TearDown() override; - - private: - performance_manager::PerformanceManagerTestHarnessHelper pm_harness_; -}; - -} // namespace testing -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_UNITTEST_UTILS_H_
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_writer.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_writer.cc deleted file mode 100644 index a1c65e6..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_writer.cc +++ /dev/null
@@ -1,92 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_writer.h" - -namespace resource_coordinator { - -LocalSiteCharacteristicsDataWriter::~LocalSiteCharacteristicsDataWriter() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (is_loaded_) - NotifySiteUnloaded(); -} - -void LocalSiteCharacteristicsDataWriter::NotifySiteLoaded() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - DCHECK(!is_loaded_); - is_loaded_ = true; - impl_->NotifySiteLoaded(); - - if (tab_visibility_ == performance_manager::TabVisibility::kBackground) - impl_->NotifyLoadedSiteBackgrounded(); -} - -void LocalSiteCharacteristicsDataWriter::NotifySiteUnloaded() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(is_loaded_); - - is_loaded_ = false; - - impl_->NotifySiteUnloaded(tab_visibility_); -} - -void LocalSiteCharacteristicsDataWriter::NotifySiteVisibilityChanged( - performance_manager::TabVisibility visibility) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // Ignore this if we receive the same event multiple times. - if (tab_visibility_ == visibility) - return; - - tab_visibility_ = visibility; - - if (is_loaded_) { - if (visibility == performance_manager::TabVisibility::kBackground) { - impl_->NotifyLoadedSiteBackgrounded(); - } else { - impl_->NotifyLoadedSiteForegrounded(); - } - } -} - -void LocalSiteCharacteristicsDataWriter::NotifyUpdatesFaviconInBackground() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK_EQ(performance_manager::TabVisibility::kBackground, tab_visibility_); - impl_->NotifyUpdatesFaviconInBackground(); -} - -void LocalSiteCharacteristicsDataWriter::NotifyUpdatesTitleInBackground() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK_EQ(performance_manager::TabVisibility::kBackground, tab_visibility_); - impl_->NotifyUpdatesTitleInBackground(); -} - -void LocalSiteCharacteristicsDataWriter::NotifyUsesAudioInBackground() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK_EQ(performance_manager::TabVisibility::kBackground, tab_visibility_); - // TODO(sebmarchand): Do not advance the background audio observation time - // when the WebContents has never played audio. - impl_->NotifyUsesAudioInBackground(); -} - -void LocalSiteCharacteristicsDataWriter::NotifyLoadTimePerformanceMeasurement( - base::TimeDelta load_duration, - base::TimeDelta cpu_usage_estimate, - uint64_t private_footprint_kb_estimate) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - impl_->NotifyLoadTimePerformanceMeasurement(load_duration, cpu_usage_estimate, - private_footprint_kb_estimate); -} - -LocalSiteCharacteristicsDataWriter::LocalSiteCharacteristicsDataWriter( - scoped_refptr<internal::LocalSiteCharacteristicsDataImpl> impl, - performance_manager::TabVisibility tab_visibility) - : impl_(std::move(impl)), - tab_visibility_(tab_visibility), - is_loaded_(false) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_writer.h b/chrome/browser/resource_coordinator/local_site_characteristics_data_writer.h deleted file mode 100644 index d06f5fc6..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_writer.h +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_WRITER_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_WRITER_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h" -#include "chrome/browser/resource_coordinator/site_characteristics_data_writer.h" - -namespace resource_coordinator { - -// Specialization of a SiteCharacteristicsDataWriter that delegates to a -// LocalSiteCharacteristicsDataImpl. -// -// This writer is initially in an unloaded state, a |NotifySiteLoaded| event -// should be sent if/when the tab using it gets loaded. -class LocalSiteCharacteristicsDataWriter - : public SiteCharacteristicsDataWriter { - public: - ~LocalSiteCharacteristicsDataWriter() override; - - // SiteCharacteristicsDataWriter: - void NotifySiteLoaded() override; - void NotifySiteUnloaded() override; - void NotifySiteVisibilityChanged( - performance_manager::TabVisibility visibility) override; - void NotifyUpdatesFaviconInBackground() override; - void NotifyUpdatesTitleInBackground() override; - void NotifyUsesAudioInBackground() override; - void NotifyLoadTimePerformanceMeasurement( - base::TimeDelta load_duration, - base::TimeDelta cpu_usage_estimate, - uint64_t private_footprint_kb_estimate) override; - - internal::LocalSiteCharacteristicsDataImpl* impl_for_testing() const { - return impl_.get(); - } - - private: - friend class LocalSiteCharacteristicsDataWriterTest; - friend class LocalSiteCharacteristicsDataStoreTest; - friend class LocalSiteCharacteristicsDataStore; - - // Private constructor, these objects are meant to be created by a site - // characteristics data store. - LocalSiteCharacteristicsDataWriter( - scoped_refptr<internal::LocalSiteCharacteristicsDataImpl> impl, - performance_manager::TabVisibility tab_visibility); - - // The LocalSiteCharacteristicDataInternal object we delegate to. - const scoped_refptr<internal::LocalSiteCharacteristicsDataImpl> impl_; - - // The visibility of the tab using this writer. - performance_manager::TabVisibility tab_visibility_; - - // Indicates if the tab using this writer is loaded. - bool is_loaded_; - - SEQUENCE_CHECKER(sequence_checker_); - - DISALLOW_COPY_AND_ASSIGN(LocalSiteCharacteristicsDataWriter); -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_WRITER_H_
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_writer_unittest.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_writer_unittest.cc deleted file mode 100644 index aabae6e8..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_writer_unittest.cc +++ /dev/null
@@ -1,202 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_writer.h" - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/time/time.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" -#include "components/performance_manager/persistence/site_data/feature_usage.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace resource_coordinator { - -class LocalSiteCharacteristicsDataWriterTest : public ::testing::Test { - protected: - // The constructors needs to call 'new' directly rather than using the - // base::MakeRefCounted helper function because the constructor of - // LocalSiteCharacteristicsDataImpl is protected and not visible to - // base::MakeRefCounted. - LocalSiteCharacteristicsDataWriterTest() - : test_impl_( - base::WrapRefCounted(new internal::LocalSiteCharacteristicsDataImpl( - url::Origin::Create(GURL("foo.com")), - &delegate_, - &database_))) { - LocalSiteCharacteristicsDataWriter* writer = - new LocalSiteCharacteristicsDataWriter( - test_impl_.get(), performance_manager::TabVisibility::kBackground); - writer_ = base::WrapUnique(writer); - } - - ~LocalSiteCharacteristicsDataWriterTest() override = default; - - bool TabIsLoaded() { return test_impl_->IsLoaded(); } - - bool TabIsLoadedAndInBackground() { - return test_impl_->loaded_tabs_in_background_count_for_testing() != 0U; - } - - // The mock delegate used by the LocalSiteCharacteristicsDataImpl objects - // created by this class, NiceMock is used to avoid having to set - // expectations in test cases that don't care about this. - ::testing::NiceMock< - testing::MockLocalSiteCharacteristicsDataImplOnDestroyDelegate> - delegate_; - - testing::NoopLocalSiteCharacteristicsDatabase database_; - - // The LocalSiteCharacteristicsDataImpl object used in these tests. - scoped_refptr<internal::LocalSiteCharacteristicsDataImpl> test_impl_; - - // A LocalSiteCharacteristicsDataWriter object associated with the origin used - // to create this object. - std::unique_ptr<LocalSiteCharacteristicsDataWriter> writer_; - - DISALLOW_COPY_AND_ASSIGN(LocalSiteCharacteristicsDataWriterTest); -}; - -TEST_F(LocalSiteCharacteristicsDataWriterTest, TestModifiers) { - // Make sure that we initially have no information about any of the features - // and that the site is in an unloaded state. - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - test_impl_->UpdatesFaviconInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - test_impl_->UpdatesTitleInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - test_impl_->UsesAudioInBackground()); - - // Test the OnTabLoaded function. - EXPECT_FALSE(TabIsLoaded()); - writer_->NotifySiteLoaded(); - EXPECT_TRUE(TabIsLoaded()); - - // Test all the modifiers. - - writer_->NotifyUpdatesFaviconInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - test_impl_->UpdatesFaviconInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - test_impl_->UpdatesTitleInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - test_impl_->UsesAudioInBackground()); - - writer_->NotifyUpdatesTitleInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - test_impl_->UpdatesFaviconInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - test_impl_->UpdatesTitleInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - test_impl_->UsesAudioInBackground()); - - writer_->NotifyUsesAudioInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - test_impl_->UpdatesFaviconInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - test_impl_->UpdatesTitleInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - test_impl_->UsesAudioInBackground()); - - writer_->NotifyLoadTimePerformanceMeasurement( - base::TimeDelta::FromMicroseconds(202), - base::TimeDelta::FromMicroseconds(101), 1005); - EXPECT_EQ(1u, test_impl_->load_duration().num_datums()); - EXPECT_EQ(202.0, test_impl_->load_duration().value()); - EXPECT_EQ(1u, test_impl_->cpu_usage_estimate().num_datums()); - EXPECT_EQ(101.0, test_impl_->cpu_usage_estimate().value()); - - EXPECT_EQ(1u, test_impl_->private_footprint_kb_estimate().num_datums()); - EXPECT_EQ(1005.0, test_impl_->private_footprint_kb_estimate().value()); - - writer_->NotifySiteUnloaded(); -} - -TEST_F(LocalSiteCharacteristicsDataWriterTest, - LoadAndBackgroundStateTransitions) { - // There's 4 different states a tab can be in: - // - Unloaded + Background - // - Unloaded + Foreground (might not be possible in practice but this - // will depend on the order of the events when an unloaded background tab - // gets foregrounded, so it's safer to consider this state). - // - Loaded + Background - // - Loaded + Foreground - // - // Only one of these parameter can change at a time, so you have the following - // possible transitions: - // - // +-------------+ +-------------+ - // |Unloaded + Bg|<--------->|Unloaded + Fg| - // +-------------+ 1 2 +-------------+ - // /|\ 3 /|\ 5 - // | | - // \|/ 4 \|/ 6 - // +-------------+ +-------------+ - // | Loaded + Bg |<--------->| Loaded + Fg | - // +-------------+ 7 8 +-------------+ - // - // - 1,2: There's nothing to do, the tab is already unloaded so |impl_| - // shouldn't count it as a background tab anyway. - // - 3: The tab gets unloaded while in background, |impl_| should be - // notified so it can *decrement* the counter of loaded AND backgrounded - // tabs. - // - 4: The tab gets loaded while in background, |impl_| should be notified - // so it can *increment* the counter of loaded AND backgrounded tabs. - // - 5: The tab gets unloaded while in foreground, this should theorically - // not happen, but if it does then |impl_| should just be notified about - // the unload event so it can update its last loaded timestamp. - // - 6: The tab gets loaded while in foreground, |impl_| should only be - // notified about the load event, the background state hasn't changed. - // - 7: A loaded foreground tab gets backgrounded, |impl_| should be - // notified that the tab has been background so it can *increment* the - // counter of loaded AND backgrounded tabs. - // - 8: A loaded background tab gets foregrounded, |impl_| should be - // notified that the tab has been background so it can *decrement* the - // counter of loaded AND backgrounded tabs. - EXPECT_FALSE(TabIsLoaded()); - - // Transition #4: Unloaded + Bg -> Loaded + Bg. - writer_->NotifySiteLoaded(); - EXPECT_TRUE(TabIsLoadedAndInBackground()); - - // Transition #8: Loaded + Bg -> Loaded + Fg. - writer_->NotifySiteVisibilityChanged( - performance_manager::TabVisibility::kForeground); - EXPECT_TRUE(TabIsLoaded()); - EXPECT_FALSE(TabIsLoadedAndInBackground()); - - // Transition #5: Loaded + Fg -> Unloaded + Fg. - writer_->NotifySiteUnloaded(); - EXPECT_FALSE(TabIsLoaded()); - - // Transition #1: Unloaded + Fg -> Unloaded + Bg. - writer_->NotifySiteVisibilityChanged( - performance_manager::TabVisibility::kBackground); - EXPECT_FALSE(TabIsLoaded()); - - // Transition #2: Unloaded + Bg -> Unloaded + Fg. - writer_->NotifySiteVisibilityChanged( - performance_manager::TabVisibility::kForeground); - EXPECT_FALSE(TabIsLoaded()); - - // Transition #6: Unloaded + Fg -> Loaded + Fg. - writer_->NotifySiteLoaded(); - EXPECT_TRUE(TabIsLoaded()); - EXPECT_FALSE(TabIsLoadedAndInBackground()); - - // Transition #7: Loaded + Fg -> Loaded + Bg. - writer_->NotifySiteVisibilityChanged( - performance_manager::TabVisibility::kBackground); - EXPECT_TRUE(TabIsLoaded()); - EXPECT_TRUE(TabIsLoadedAndInBackground()); - - // Transition #3: Loaded + Bg -> Unloaded + Bg. - writer_->NotifySiteUnloaded(); - EXPECT_FALSE(TabIsLoaded()); - EXPECT_FALSE(TabIsLoadedAndInBackground()); -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_database.h b/chrome/browser/resource_coordinator/local_site_characteristics_database.h deleted file mode 100644 index 2d8cd25..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_database.h +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATABASE_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATABASE_H_ - -#include <vector> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/optional.h" -#include "components/performance_manager/persistence/site_data/site_data.pb.h" -#include "url/origin.h" - -namespace resource_coordinator { - -// Interface for a local site characteristic database. -class LocalSiteCharacteristicsDatabase { - public: - // Callback to call once the initialization from the database has completed, - // |site_characteristic_proto| should be equal to base::nullopt if the - // initialization has failed. - using ReadSiteCharacteristicsFromDBCallback = base::OnceCallback<void( - base::Optional<SiteDataProto> site_characteristic_proto)>; - using GetDatabaseSizeCallback = - base::OnceCallback<void(base::Optional<int64_t> num_rows, - base::Optional<int64_t> on_disk_size_kb)>; - - LocalSiteCharacteristicsDatabase() = default; - virtual ~LocalSiteCharacteristicsDatabase() {} - - // Checks the if there's an entry with the key |site_origin| and if so use it - // to initialize |site_characteristic_proto|. Calls |callback| to indicate - // whether or not the initialization has been successful. - virtual void ReadSiteCharacteristicsFromDB( - const url::Origin& origin, - ReadSiteCharacteristicsFromDBCallback callback) = 0; - - // Store an entry in the database, create it if it doesn't exist and update it - // if it does. - virtual void WriteSiteCharacteristicsIntoDB( - const url::Origin& origin, - const SiteDataProto& site_characteristic_proto) = 0; - - // Removes some entries from the database. - virtual void RemoveSiteCharacteristicsFromDB( - const std::vector<url::Origin>& site_origins) = 0; - - // Clear the database, removes every entries that it contains. - virtual void ClearDatabase() = 0; - - // Retrieve the size of the database. - virtual void GetDatabaseSize(GetDatabaseSizeCallback callback) = 0; -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATABASE_H_
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_database_browsertest.cc b/chrome/browser/resource_coordinator/local_site_characteristics_database_browsertest.cc deleted file mode 100644 index 1907fca3c..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_database_browsertest.cc +++ /dev/null
@@ -1,630 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <algorithm> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "base/test/simple_test_tick_clock.h" -#include "build/build_config.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h" -#include "chrome/browser/resource_coordinator/site_characteristics_data_reader.h" -#include "chrome/browser/resource_coordinator/tab_load_tracker.h" -#include "chrome/browser/resource_coordinator/tab_load_tracker_test_support.h" -#include "chrome/browser/resource_coordinator/tab_manager_features.h" -#include "chrome/browser/resource_coordinator/time.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "components/content_settings/core/browser/host_content_settings_map.h" -#include "components/network_session_configurator/common/network_switches.h" -#include "content/public/test/browser_test.h" -#include "content/public/test/browser_test_utils.h" -#include "content/public/test/test_utils.h" -#include "content/public/test/web_contents_tester.h" -#include "media/base/media_switches.h" -#include "net/dns/mock_host_resolver.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/origin.h" - -#if defined(OS_CHROMEOS) -#include "chromeos/constants/chromeos_switches.h" -#endif - -namespace resource_coordinator { - -namespace { - -using WebContents = content::WebContents; -using WebContentsTester = content::WebContentsTester; - -constexpr char kTestPage[] = - "/resource_coordinator/site_characteristics_test_page.html"; - -constexpr base::TimeDelta kObservationWindowLength = - base::TimeDelta::FromHours(2); -constexpr base::TimeDelta kLongestGracePeriod = - base::TimeDelta::FromSeconds(20); - -// Returns the LocalSiteCharacteristicsDataImpl that backs |reader|. -internal::LocalSiteCharacteristicsDataImpl* GetImplFromReader( - SiteCharacteristicsDataReader* reader) { - return static_cast<LocalSiteCharacteristicsDataReader*>(reader) - ->impl_for_testing(); -} - -// Returns the SiteDataProto that backs |reader|. -const SiteDataProto* GetSiteDataProtoFromReader( - SiteCharacteristicsDataReader* reader) { - return &GetImplFromReader(reader)->site_characteristics_for_testing(); -} - -} // namespace - -class LocalSiteCharacteristicsDatabaseTest : public InProcessBrowserTest { - public: - LocalSiteCharacteristicsDatabaseTest() - : scoped_set_tick_clock_for_testing_(&test_clock_), - test_server_(net::test_server::EmbeddedTestServer::TYPE_HTTPS) {} - ~LocalSiteCharacteristicsDatabaseTest() override = default; - - void SetUp() override { - test_clock_.Advance(base::TimeDelta::FromSeconds(1)); - InProcessBrowserTest::SetUp(); - } - - void SetUpOnMainThread() override { - InProcessBrowserTest::SetUpOnMainThread(); - - // Setup the test server. - base::FilePath test_data_dir; - ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir)); - test_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK); - test_server_.ServeFilesFromDirectory( - test_data_dir.AppendASCII("chrome/test/data/")); - ASSERT_TRUE(test_server_.InitializeAndListen()); - test_server_.StartAcceptingConnections(); - const std::string real_host = test_server_.host_port_pair().host(); - host_resolver()->AddRule("*", real_host); - } - - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitchASCII( - switches::kAutoplayPolicy, - switches::autoplay::kNoUserGestureRequiredPolicy); - - // HTTPS server only serves a valid cert for localhost, so this is needed - // to load pages from other origins without an interstitial. - command_line->AppendSwitch(switches::kIgnoreCertificateErrors); - -#if defined(OS_CHROMEOS) - command_line->AppendSwitch( - chromeos::switches::kIgnoreUserProfileMappingForTests); -#endif - InProcessBrowserTest::SetUpCommandLine(command_line); - } - - WebContents* GetActiveWebContents() { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - - std::unique_ptr<SiteCharacteristicsDataReader> GetReaderForOrigin( - Profile* profile, - const url::Origin& origin) { - SiteCharacteristicsDataStore* data_store = - LocalSiteCharacteristicsDataStoreFactory::GetForProfile(profile); - EXPECT_TRUE(data_store); - std::unique_ptr<SiteCharacteristicsDataReader> reader = - data_store->GetReaderForOrigin(origin); - base::RunLoop run_loop; - reader->RegisterDataLoadedCallback(run_loop.QuitClosure()); - run_loop.Run(); - - const internal::LocalSiteCharacteristicsDataImpl* impl = - GetImplFromReader(reader.get()); - EXPECT_TRUE(impl->fully_initialized_for_testing()); - return reader; - } - - // Test that feature usage is tracked correctly: - // - kSiteFeatureUsageUnknown if never observed and observation window - // hasn't expired. - // - kSiteFeatureNotInUse if never observed and observation window has - // expired. - // - kSiteFeatureInUse if observed. - // |feature_detection_method| is the SiteCharacteristicsDataReader method that - // will be called to query the status of this feature. |triggering_closure| is - // the closure to run to cause this feature to be used (this will get called - // while the tab is in background) and |allowing_closure| is an optional - // closure that should run before testing the feature usage (to allow it to - // be used). - void TestFeatureUsageDetection( - performance_manager::SiteFeatureUsage ( - SiteCharacteristicsDataReader::*feature_detection_method)() const, - internal::LocalSiteCharacteristicsDataImpl::TrackedBackgroundFeatures - feature_type, - base::RepeatingClosure triggering_closure, - base::RepeatingClosure allowing_closure = base::DoNothing::Repeatedly()) { - // Test that feature usage is tracked correctly before the expiration of its - // observation window. - TestFeatureUsageDetectionImpl(feature_detection_method, feature_type, - allowing_closure, triggering_closure, false); - // Test that feature usage is tracked correctly after the expiration of its - // observation window. - TestFeatureUsageDetectionImpl(feature_detection_method, feature_type, - std::move(allowing_closure), - std::move(triggering_closure), true); - } - - void ExecuteScriptInMainFrame(const char* script) { - content::RenderFrameHost* main_frame = - GetActiveWebContents()->GetMainFrame(); - EXPECT_TRUE(content::ExecuteScript(main_frame, script)); - } - - void PlayAudioInActiveWebContents() { - ExecuteScriptInMainFrame("PlayAudio();"); - } - - void ChangeTitleOfActiveWebContents() { - ExecuteScriptInMainFrame("ChangeTitle('new_title')"); - } - - void ChangeFaviconOfActiveWebContents() { - ExecuteScriptInMainFrame("ChangeFavicon()"); - } - - // By default a tab has to play audio while being visible if it wants to be - // able to play audio in background (see - // ChromeContentRendererClient::DeferMediaLoad). This makes the current active - // WebContents visible, play some audio and background it. After calling - // this the background tab is allowed play audio. - void AllowBackgroundAudioInActiveTab() { - content::WebContents* active_webcontents = GetActiveWebContents(); - active_webcontents->WasShown(); - PlayAudioInActiveWebContents(); - // Wait for the audio to start playing. - while (!active_webcontents->WasEverAudible()) - base::RunLoop().RunUntilIdle(); - - active_webcontents->GetController().Reload(content::ReloadType::NORMAL, - false); - EXPECT_TRUE(content::WaitForLoadStop(GetActiveWebContents())); - // Background the tab and reload it so the audio will stop playing if it's - // still playing. - GetActiveWebContents()->WasHidden(); - test_clock_.Advance(kLongestGracePeriod); - } - - void ExpireTitleOrFaviconGracePeriod() { - test_clock_.Advance(kLongestGracePeriod); - } - - base::SimpleTestTickClock& test_clock() { return test_clock_; } - net::test_server::EmbeddedTestServer& test_server() { return test_server_; } - - private: - void TestFeatureUsageDetectionImpl( - performance_manager::SiteFeatureUsage ( - SiteCharacteristicsDataReader::*feature_detection_method)() const, - const internal::LocalSiteCharacteristicsDataImpl:: - TrackedBackgroundFeatures feature_type, - base::OnceClosure allowing_closure, - base::RepeatingClosure triggering_closure, - bool wait_for_observation_window_to_expire); - - base::SimpleTestTickClock test_clock_; - ScopedSetTickClockForTesting scoped_set_tick_clock_for_testing_; - base::test::ScopedFeatureList scoped_feature_list_; - net::test_server::EmbeddedTestServer test_server_; - - DISALLOW_COPY_AND_ASSIGN(LocalSiteCharacteristicsDatabaseTest); -}; - -void LocalSiteCharacteristicsDatabaseTest::TestFeatureUsageDetectionImpl( - performance_manager::SiteFeatureUsage ( - SiteCharacteristicsDataReader::*feature_detection_method)() const, - const internal::LocalSiteCharacteristicsDataImpl::TrackedBackgroundFeatures - feature_type, - base::OnceClosure allowing_closure, - base::RepeatingClosure triggering_closure, - bool wait_for_observation_window_to_expire) { - // Use a different origin depending on the type of test to make sure that - // previous observations don't get re-used. - const char* kOrigin = - wait_for_observation_window_to_expire ? "foo.com" : "bar.com"; - GURL test_url(test_server_.GetURL(kOrigin, kTestPage)); - - // Get the reader for this origin. - auto reader = - GetReaderForOrigin(browser()->profile(), url::Origin::Create(test_url)); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - (reader.get()->*feature_detection_method)()); - - // Navigate to the test url and background it. - ui_test_utils::NavigateToURLWithDisposition( - browser(), test_url, WindowOpenDisposition::CURRENT_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); - GetActiveWebContents()->WasHidden(); - WaitForTransitionToLoaded(GetActiveWebContents()); - - // If needed, wait for all feature observation windows to expire. - if (wait_for_observation_window_to_expire) { - test_clock_.Advance(kObservationWindowLength); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureNotInUse, - (reader.get()->*feature_detection_method)()); - } - - // Call the allowing closure. - std::move(allowing_closure).Run(); - - // Ensure that the closure hasn't caused the feature usage status to - // change. - if (wait_for_observation_window_to_expire) { - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureNotInUse, - (reader.get()->*feature_detection_method)()); - } else { - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - (reader.get()->*feature_detection_method)()); - } - - base::RunLoop run_loop; - GetImplFromReader(reader.get()) - ->RegisterFeatureUsageCallbackForTesting(feature_type, - run_loop.QuitClosure()); - - // Cause the feature to be used. - triggering_closure.Run(); - - run_loop.Run(); - - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - (reader.get()->*feature_detection_method)()); - - // Advance the clock, make sure that the feature usage status doesn't - // change. - test_clock_.Advance(kObservationWindowLength); - - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - (reader.get()->*feature_detection_method)()); -} - -// Test that doesn't use any feature. -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDatabaseTest, NoFeatureUsed) { - GURL test_url(test_server().GetURL("foo.com", kTestPage)); - - ui_test_utils::NavigateToURLWithDisposition( - browser(), test_url, WindowOpenDisposition::NEW_BACKGROUND_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); - - content::WebContents* contents = - browser()->tab_strip_model()->GetWebContentsAt(1); - EXPECT_EQ(test_url, contents->GetLastCommittedURL()); - WaitForTransitionToLoaded(contents); - - auto reader = - GetReaderForOrigin(browser()->profile(), url::Origin::Create(test_url)); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UpdatesFaviconInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UpdatesTitleInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UsesAudioInBackground()); - - test_clock().Advance(kObservationWindowLength); - - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureNotInUse, - reader->UpdatesFaviconInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureNotInUse, - reader->UpdatesTitleInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureNotInUse, - reader->UsesAudioInBackground()); -} - -// Test that use features while in foreground, this shouldn't be recorded. -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDatabaseTest, - FeatureUsedInForegroundOnly) { - GURL test_url(test_server().GetURL("foo.com", kTestPage)); - - ui_test_utils::NavigateToURLWithDisposition( - browser(), test_url, WindowOpenDisposition::CURRENT_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); - - GetActiveWebContents()->WasShown(); - - ChangeTitleOfActiveWebContents(); - ChangeFaviconOfActiveWebContents(); - PlayAudioInActiveWebContents(); - - auto reader = - GetReaderForOrigin(browser()->profile(), url::Origin::Create(test_url)); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UpdatesFaviconInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UpdatesTitleInBackground()); - - // Advance the clock while the tab is still in foreground and make sure that - // the state hasn't changed. - test_clock().Advance(kObservationWindowLength); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UpdatesFaviconInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UpdatesTitleInBackground()); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UsesAudioInBackground()); -} - -// Test that the audio feature usage in background gets detected properly. -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDatabaseTest, - AudioFeatureUsage) { - TestFeatureUsageDetection( - &SiteCharacteristicsDataReader::UsesAudioInBackground, - internal::LocalSiteCharacteristicsDataImpl::TrackedBackgroundFeatures:: - kAudioUsage, - base::BindRepeating( - &LocalSiteCharacteristicsDatabaseTest::PlayAudioInActiveWebContents, - base::Unretained(this)), - base::BindRepeating(&LocalSiteCharacteristicsDatabaseTest:: - AllowBackgroundAudioInActiveTab, - base::Unretained(this))); -} - -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDatabaseTest, - TitleUpdateFeatureUsage) { - TestFeatureUsageDetection( - &SiteCharacteristicsDataReader::UpdatesTitleInBackground, - internal::LocalSiteCharacteristicsDataImpl::TrackedBackgroundFeatures:: - kTitleUpdate, - base::BindRepeating( - &LocalSiteCharacteristicsDatabaseTest::ChangeTitleOfActiveWebContents, - base::Unretained(this)), - base::BindRepeating(&LocalSiteCharacteristicsDatabaseTest:: - ExpireTitleOrFaviconGracePeriod, - base::Unretained(this))); -} - -// Test that the favicon update feature usage in background gets detected -// properly. -// TODO(crbug.com/1004641): Investigate and reenable. -#if defined(OS_WIN) -#define MAYBE_FaviconUpdateFeatureUsage DISABLED_FaviconUpdateFeatureUsage -#else -#define MAYBE_FaviconUpdateFeatureUsage FaviconUpdateFeatureUsage -#endif -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDatabaseTest, - MAYBE_FaviconUpdateFeatureUsage) { - TestFeatureUsageDetection( - &SiteCharacteristicsDataReader::UpdatesFaviconInBackground, - internal::LocalSiteCharacteristicsDataImpl::TrackedBackgroundFeatures:: - kFaviconUpdate, - base::BindRepeating(&LocalSiteCharacteristicsDatabaseTest:: - ChangeFaviconOfActiveWebContents, - base::Unretained(this)), - base::BindRepeating(&LocalSiteCharacteristicsDatabaseTest:: - ExpireTitleOrFaviconGracePeriod, - base::Unretained(this))); -} - -// Test that loads the same origin into multiple tabs and ensure that they get -// tracked properly. -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDatabaseTest, - LoadedStateGetsTrackedProperly) { - GURL test_url(test_server().GetURL("foo.com", kTestPage)); - auto test_reader = - GetReaderForOrigin(browser()->profile(), url::Origin::Create(test_url)); - - const size_t kTabCount = 3; - - // Load all the tabs and background them. - for (size_t i = 0; i < kTabCount; ++i) { - ui_test_utils::NavigateToURLWithDisposition( - browser(), test_url, - i == 0 ? WindowOpenDisposition::CURRENT_TAB - : WindowOpenDisposition::NEW_FOREGROUND_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); - content::WebContents* contents = - browser()->tab_strip_model()->GetWebContentsAt(i); - WaitForTransitionToLoaded(contents); - EXPECT_EQ(TabLoadTracker::LoadingState::LOADED, - TabLoadTracker::Get()->GetLoadingState(contents)); - contents->WasHidden(); - } - - const internal::LocalSiteCharacteristicsDataImpl* impl = - GetImplFromReader(test_reader.get()); - EXPECT_TRUE(impl); - EXPECT_EQ(3U, impl->loaded_tabs_count_for_testing()); - EXPECT_EQ(3U, impl->loaded_tabs_in_background_count_for_testing()); - - // Change the visibility of the tabs. - for (size_t i = 0; i < kTabCount; ++i) { - browser()->tab_strip_model()->GetWebContentsAt(i)->WasShown(); - - EXPECT_EQ(kTabCount, impl->loaded_tabs_count_for_testing()); - EXPECT_EQ(kTabCount - (i + 1), - impl->loaded_tabs_in_background_count_for_testing()); - } - - for (size_t i = 0; i < kTabCount; ++i) - browser()->tab_strip_model()->GetWebContentsAt(i)->WasHidden(); - - EXPECT_EQ(3U, impl->loaded_tabs_in_background_count_for_testing()); - - // Close the tabs. - for (size_t i = 0; i < kTabCount; ++i) { - EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt(0, 0)); - EXPECT_EQ(kTabCount - (i + 1), impl->loaded_tabs_count_for_testing()); - EXPECT_EQ(kTabCount - (i + 1), - impl->loaded_tabs_in_background_count_for_testing()); - } -} - -// Ensure that the observations gets persisted on disk. -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDatabaseTest, - PRE_DatabaseGetsPersisted) { - GURL test_url(test_server().GetURL("foo.com", kTestPage)); - - // Get the reader for this origin. - auto reader = - GetReaderForOrigin(browser()->profile(), url::Origin::Create(test_url)); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UpdatesTitleInBackground()); - - // Navigate to the test url and background it. - ui_test_utils::NavigateToURLWithDisposition( - browser(), test_url, WindowOpenDisposition::CURRENT_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); - WaitForTransitionToLoaded(GetActiveWebContents()); - GetActiveWebContents()->WasHidden(); - - test_clock().Advance(kLongestGracePeriod); - - base::RunLoop run_loop; - GetImplFromReader(reader.get()) - ->RegisterFeatureUsageCallbackForTesting( - internal::LocalSiteCharacteristicsDataImpl:: - TrackedBackgroundFeatures::kTitleUpdate, - run_loop.QuitClosure()); - - // Cause the "title update in background" feature to be used. - ChangeTitleOfActiveWebContents(); - - run_loop.Run(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader->UpdatesTitleInBackground()); -} - -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDatabaseTest, - DatabaseGetsPersisted) { - GURL test_url(test_server().GetURL("foo.com", kTestPage)); - - // Get the reader for this origin. - auto reader = - GetReaderForOrigin(browser()->profile(), url::Origin::Create(test_url)); - - // We should remember the observation made previously. - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader->UpdatesTitleInBackground()); -} - -// Ensure that clearing the history removes the observations from disk. -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDatabaseTest, PRE_ClearHistory) { - GURL test_url(test_server().GetURL("foo.com", kTestPage)); - - // Get the reader for this origin. - auto reader = - GetReaderForOrigin(browser()->profile(), url::Origin::Create(test_url)); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UpdatesTitleInBackground()); - - // Navigate to the test url and background it. - ui_test_utils::NavigateToURLWithDisposition( - browser(), test_url, WindowOpenDisposition::CURRENT_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); - WaitForTransitionToLoaded(GetActiveWebContents()); - GetActiveWebContents()->WasHidden(); - - test_clock().Advance(kLongestGracePeriod); - - base::RunLoop run_loop; - GetImplFromReader(reader.get()) - ->RegisterFeatureUsageCallbackForTesting( - internal::LocalSiteCharacteristicsDataImpl:: - TrackedBackgroundFeatures::kTitleUpdate, - run_loop.QuitClosure()); - - // Cause the "title update in background" feature to be used. - ChangeTitleOfActiveWebContents(); - - run_loop.Run(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader->UpdatesTitleInBackground()); - - HistoryServiceFactory::GetForProfile(browser()->profile(), - ServiceAccessType::IMPLICIT_ACCESS) - ->DeleteURLs({test_url}); - // The history gets cleared asynchronously. - while (reader->UpdatesTitleInBackground() != - performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown) { - base::RunLoop().RunUntilIdle(); - } -} - -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDatabaseTest, ClearHistory) { - GURL test_url(test_server().GetURL("foo.com", kTestPage)); - - // Get the reader for this origin. - auto reader = - GetReaderForOrigin(browser()->profile(), url::Origin::Create(test_url)); - - // The history has been cleared, we shouldn't know if this feature is used. - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UpdatesTitleInBackground()); -} - -// Ensure that the observation time gets tracked across sessions. -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDatabaseTest, - PRE_DatabaseObservationTimeTrackedAcrossSessions) { - GURL test_url(test_server().GetURL("foo.com", kTestPage)); - - auto reader = - GetReaderForOrigin(browser()->profile(), url::Origin::Create(test_url)); - const SiteDataProto* site_characteristics = - GetSiteDataProtoFromReader(reader.get()); - - EXPECT_EQ(0, site_characteristics->updates_title_in_background() - .observation_duration()); - - // Navigate to the test url and background it. - ui_test_utils::NavigateToURLWithDisposition( - browser(), test_url, WindowOpenDisposition::CURRENT_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); - WaitForTransitionToLoaded(GetActiveWebContents()); - GetActiveWebContents()->WasHidden(); - - test_clock().Advance(base::TimeDelta::FromSeconds(10)); - EXPECT_GE(10, site_characteristics->updates_title_in_background() - .observation_duration()); -} - -IN_PROC_BROWSER_TEST_F(LocalSiteCharacteristicsDatabaseTest, - DatabaseObservationTimeTrackedAcrossSessions) { - GURL test_url(test_server().GetURL("foo.com", kTestPage)); - - auto reader = - GetReaderForOrigin(browser()->profile(), url::Origin::Create(test_url)); - const SiteDataProto* site_characteristics = - GetSiteDataProtoFromReader(reader.get()); - - auto observation_duration = - site_characteristics->updates_title_in_background() - .observation_duration(); - // The observation duration shouldn't be null as this has been augmented in - // the 'PRE' part of this test. - EXPECT_NE(0, observation_duration); - - // Advance the clock and reset this reader. This should increase the - // observation duration that we have for this origin in the database. - test_clock().Advance(base::TimeDelta::FromSeconds(10)); - reader.reset(); - - reader = - GetReaderForOrigin(browser()->profile(), url::Origin::Create(test_url)); - site_characteristics = GetSiteDataProtoFromReader(reader.get()); - - EXPECT_GE(observation_duration, - site_characteristics->updates_title_in_background() - .observation_duration()); -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_non_recording_data_store.cc b/chrome/browser/resource_coordinator/local_site_characteristics_non_recording_data_store.cc deleted file mode 100644 index ef7cada7..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_non_recording_data_store.cc +++ /dev/null
@@ -1,88 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_non_recording_data_store.h" - -#include "base/check.h" -#include "base/memory/ptr_util.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_noop_data_writer.h" - -namespace resource_coordinator { - -LocalSiteCharacteristicsNonRecordingDataStore:: - LocalSiteCharacteristicsNonRecordingDataStore( - Profile* profile, - LocalSiteCharacteristicsDataStoreInspector* data_store_inspector, - SiteCharacteristicsDataStore* data_store_for_readers) - : data_store_for_readers_(data_store_for_readers), - data_store_inspector_(data_store_inspector), - profile_(profile) { - DCHECK(data_store_for_readers_); - // Register the debug interface against the profile. - LocalSiteCharacteristicsDataStoreInspector::SetForProfile(this, profile); -} - -LocalSiteCharacteristicsNonRecordingDataStore:: - ~LocalSiteCharacteristicsNonRecordingDataStore() { - LocalSiteCharacteristicsDataStoreInspector::SetForProfile(nullptr, profile_); -} - -std::unique_ptr<SiteCharacteristicsDataReader> -LocalSiteCharacteristicsNonRecordingDataStore::GetReaderForOrigin( - const url::Origin& origin) { - return data_store_for_readers_->GetReaderForOrigin(origin); -} - -std::unique_ptr<SiteCharacteristicsDataWriter> -LocalSiteCharacteristicsNonRecordingDataStore::GetWriterForOrigin( - const url::Origin& origin, - performance_manager::TabVisibility tab_visibility) { - // Return a fake data writer. - SiteCharacteristicsDataWriter* writer = - new LocalSiteCharacteristicsNoopDataWriter(); - return base::WrapUnique(writer); -} - -bool LocalSiteCharacteristicsNonRecordingDataStore::IsRecordingForTesting() { - return false; -} - -const char* LocalSiteCharacteristicsNonRecordingDataStore::GetDataStoreName() { - return "LocalSiteCharacteristicsNonRecordingDataStore"; -} - -std::vector<url::Origin> -LocalSiteCharacteristicsNonRecordingDataStore::GetAllInMemoryOrigins() { - if (!data_store_inspector_) - return std::vector<url::Origin>(); - - return data_store_inspector_->GetAllInMemoryOrigins(); -} - -void LocalSiteCharacteristicsNonRecordingDataStore::GetDatabaseSize( - DatabaseSizeCallback on_have_data) { - if (!data_store_inspector_) { - std::move(on_have_data).Run(base::nullopt, base::nullopt); - return; - } - - data_store_inspector_->GetDatabaseSize(std::move(on_have_data)); -} - -bool LocalSiteCharacteristicsNonRecordingDataStore::GetDataForOrigin( - const url::Origin& origin, - bool* is_dirty, - std::unique_ptr<SiteDataProto>* data) { - if (!data_store_inspector_) - return false; - - return data_store_inspector_->GetDataForOrigin(origin, is_dirty, data); -} - -SiteCharacteristicsDataStore* -LocalSiteCharacteristicsNonRecordingDataStore::GetDataStore() { - return this; -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_non_recording_data_store.h b/chrome/browser/resource_coordinator/local_site_characteristics_non_recording_data_store.h deleted file mode 100644 index 4bed7e4..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_non_recording_data_store.h +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_NON_RECORDING_DATA_STORE_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_NON_RECORDING_DATA_STORE_H_ - -#include "base/macros.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h" -#include "chrome/browser/resource_coordinator/site_characteristics_data_store.h" - -class Profile; - -namespace resource_coordinator { - -// Specialization of a SiteCharacteristicsDataStore whose -// SiteCharacteristicsDataWriters don't persist observations and whose -// SiteCharacteristicsDataReader are obtained from another -// SiteCharacteristicsDataStore. -class LocalSiteCharacteristicsNonRecordingDataStore - : public SiteCharacteristicsDataStore, - public LocalSiteCharacteristicsDataStoreInspector { - public: - // |profile| is the profile this data store is associated with. - // |data_store_inspector| is the inspector instance this instance will - // delegate to, may be null, but this is typically the inspector instance - // associated with |data_store_for_readers|. |data_store_for_readers| should - // outlive this object. - LocalSiteCharacteristicsNonRecordingDataStore( - Profile* profile, - LocalSiteCharacteristicsDataStoreInspector* data_store_inspector, - SiteCharacteristicsDataStore* data_store_for_readers); - ~LocalSiteCharacteristicsNonRecordingDataStore() override; - - // SiteCharacteristicDataStore: - std::unique_ptr<SiteCharacteristicsDataReader> GetReaderForOrigin( - const url::Origin& origin) override; - std::unique_ptr<SiteCharacteristicsDataWriter> GetWriterForOrigin( - const url::Origin& origin, - performance_manager::TabVisibility tab_visibility) override; - bool IsRecordingForTesting() override; - - // LocalSiteCharacteristicsDataStoreInspector: - const char* GetDataStoreName() override; - std::vector<url::Origin> GetAllInMemoryOrigins() override; - void GetDatabaseSize(DatabaseSizeCallback on_have_data) override; - bool GetDataForOrigin(const url::Origin& origin, - bool* is_dirty, - std::unique_ptr<SiteDataProto>* data) override; - SiteCharacteristicsDataStore* GetDataStore() override; - - private: - // The data store to use to create the readers served by this data store. E.g. - // during an incognito session it should point to the data store used by the - // parent session. - SiteCharacteristicsDataStore* data_store_for_readers_; - - // The inspector implementation this instance delegates to. - LocalSiteCharacteristicsDataStoreInspector* data_store_inspector_; - - // The profile this data store is associated with. - Profile* profile_; - - DISALLOW_COPY_AND_ASSIGN(LocalSiteCharacteristicsNonRecordingDataStore); -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_NON_RECORDING_DATA_STORE_H_
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_non_recording_data_store_unittest.cc b/chrome/browser/resource_coordinator/local_site_characteristics_non_recording_data_store_unittest.cc deleted file mode 100644 index c955f3b8..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_non_recording_data_store_unittest.cc +++ /dev/null
@@ -1,135 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_non_recording_data_store.h" - -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h" -#include "chrome/test/base/testing_profile.h" -#include "content/public/test/browser_task_environment.h" -#include "content/public/test/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace resource_coordinator { - -namespace { -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -url::Origin TestOrigin() { - return url::Origin::Create(GURL("http://www.foo.com")); -} - -class LocalSiteCharacteristicsNonRecordingDataStoreTest : public testing::Test { - public: - void SetUp() override { - recording_data_store_ = - std::make_unique<LocalSiteCharacteristicsDataStore>(&parent_profile_); - non_recording_data_store_ = - std::make_unique<LocalSiteCharacteristicsNonRecordingDataStore>( - &profile_, recording_data_store_.get(), - recording_data_store_.get()); - - WaitForAsyncOperationsToComplete(); - } - - void WaitForAsyncOperationsToComplete() { task_environment_.RunUntilIdle(); } - - protected: - content::BrowserTaskEnvironment task_environment_; - TestingProfile parent_profile_; - TestingProfile profile_; - std::unique_ptr<LocalSiteCharacteristicsDataStore> recording_data_store_; - std::unique_ptr<LocalSiteCharacteristicsNonRecordingDataStore> - non_recording_data_store_; -}; - -} // namespace - -TEST_F(LocalSiteCharacteristicsNonRecordingDataStoreTest, EndToEnd) { - // Ensures that the observation made via a writer created by the non - // recording data store aren't recorded. - auto reader = non_recording_data_store_->GetReaderForOrigin(TestOrigin()); - EXPECT_TRUE(reader); - auto fake_writer = non_recording_data_store_->GetWriterForOrigin( - TestOrigin(), performance_manager::TabVisibility::kBackground); - EXPECT_TRUE(fake_writer); - auto real_writer = recording_data_store_->GetWriterForOrigin( - TestOrigin(), performance_manager::TabVisibility::kBackground); - EXPECT_TRUE(real_writer); - - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UpdatesTitleInBackground()); - fake_writer->NotifySiteLoaded(); - fake_writer->NotifyUpdatesTitleInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - reader->UpdatesTitleInBackground()); - - real_writer->NotifySiteLoaded(); - real_writer->NotifyUpdatesTitleInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse, - reader->UpdatesTitleInBackground()); - - // These unload events shouldn't be registered, make sure that they aren't by - // unloading the site more time than it has been loaded. - fake_writer->NotifySiteUnloaded(); - fake_writer->NotifySiteUnloaded(); - - real_writer->NotifySiteUnloaded(); - - real_writer.reset(); - reader.reset(); - - WaitForAsyncOperationsToComplete(); - - recording_data_store_.reset(); - - // Wait for the database of the recording store to be flushed to disk before - // terminating this test, otherwise the profile might get deleted while the - // database is still being flushed to disk and this could prevent from - // deleting its temporary directory. - WaitForAsyncOperationsToComplete(); -} - -TEST_F(LocalSiteCharacteristicsNonRecordingDataStoreTest, InspectorWorks) { - // Make sure the inspector interface was registered at construction. - LocalSiteCharacteristicsDataStoreInspector* inspector = - LocalSiteCharacteristicsDataStoreInspector::GetForProfile(&profile_); - EXPECT_NE(nullptr, inspector); - EXPECT_EQ(non_recording_data_store_.get(), inspector); - - EXPECT_STREQ("LocalSiteCharacteristicsNonRecordingDataStore", - inspector->GetDataStoreName()); - - // We expect an empty data store at the outset. - EXPECT_EQ(0U, inspector->GetAllInMemoryOrigins().size()); - std::unique_ptr<SiteDataProto> data; - bool is_dirty = false; - EXPECT_FALSE(inspector->GetDataForOrigin(TestOrigin(), &is_dirty, &data)); - EXPECT_FALSE(is_dirty); - EXPECT_EQ(nullptr, data.get()); - - { - // Add an entry through the writing data store, see that it's reflected in - // the inspector interface. - auto writer = recording_data_store_->GetWriterForOrigin( - TestOrigin(), performance_manager::TabVisibility::kBackground); - - EXPECT_EQ(1U, inspector->GetAllInMemoryOrigins().size()); - EXPECT_TRUE(inspector->GetDataForOrigin(TestOrigin(), &is_dirty, &data)); - EXPECT_FALSE(is_dirty); - ASSERT_NE(nullptr, data.get()); - - // Touch the underlying data, see that the dirty bit updates. - writer->NotifySiteLoaded(); - EXPECT_TRUE(inspector->GetDataForOrigin(TestOrigin(), &is_dirty, &data)); - } - - // Make sure the interface is unregistered from the profile on destruction. - non_recording_data_store_.reset(); - EXPECT_EQ(nullptr, LocalSiteCharacteristicsDataStoreInspector::GetForProfile( - &profile_)); -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_noop_data_writer.cc b/chrome/browser/resource_coordinator/local_site_characteristics_noop_data_writer.cc deleted file mode 100644 index 8ba7a0b0..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_noop_data_writer.cc +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_noop_data_writer.h" - -namespace resource_coordinator { - -LocalSiteCharacteristicsNoopDataWriter:: - LocalSiteCharacteristicsNoopDataWriter() = default; -LocalSiteCharacteristicsNoopDataWriter:: - ~LocalSiteCharacteristicsNoopDataWriter() = default; - -void LocalSiteCharacteristicsNoopDataWriter::NotifySiteLoaded() {} - -void LocalSiteCharacteristicsNoopDataWriter::NotifySiteUnloaded() {} - -void LocalSiteCharacteristicsNoopDataWriter::NotifySiteVisibilityChanged( - performance_manager::TabVisibility visibility) {} - -void LocalSiteCharacteristicsNoopDataWriter:: - NotifyUpdatesFaviconInBackground() {} - -void LocalSiteCharacteristicsNoopDataWriter::NotifyUpdatesTitleInBackground() {} - -void LocalSiteCharacteristicsNoopDataWriter::NotifyUsesAudioInBackground() {} - -void LocalSiteCharacteristicsNoopDataWriter:: - NotifyLoadTimePerformanceMeasurement( - base::TimeDelta load_duration, - base::TimeDelta cpu_usage_estimate, - uint64_t private_footprint_kb_estimate) {} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_noop_data_writer.h b/chrome/browser/resource_coordinator/local_site_characteristics_noop_data_writer.h deleted file mode 100644 index ca6d0cc49..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_noop_data_writer.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_NOOP_DATA_WRITER_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_NOOP_DATA_WRITER_H_ - -#include "base/macros.h" -#include "chrome/browser/resource_coordinator/site_characteristics_data_writer.h" - -namespace resource_coordinator { - -// Specialization of a SiteCharacteristicsDataWriter that doesn't record -// anyting. -class LocalSiteCharacteristicsNoopDataWriter - : public SiteCharacteristicsDataWriter { - public: - LocalSiteCharacteristicsNoopDataWriter(); - ~LocalSiteCharacteristicsNoopDataWriter() override; - - // SiteCharacteristicsDataWriter: - void NotifySiteLoaded() override; - void NotifySiteUnloaded() override; - void NotifySiteVisibilityChanged( - performance_manager::TabVisibility visibility) override; - void NotifyUpdatesFaviconInBackground() override; - void NotifyUpdatesTitleInBackground() override; - void NotifyUsesAudioInBackground() override; - void NotifyLoadTimePerformanceMeasurement( - base::TimeDelta load_duration, - base::TimeDelta cpu_usage_estimate, - uint64_t private_footprint_kb_estimate) override; - - private: - DISALLOW_COPY_AND_ASSIGN(LocalSiteCharacteristicsNoopDataWriter); -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_NOOP_DATA_WRITER_H_
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.cc b/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.cc deleted file mode 100644 index 3a4a243..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.cc +++ /dev/null
@@ -1,272 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h" - -#include "base/bind.h" -#include "base/metrics/histogram_macros.h" -#include "base/threading/sequenced_task_runner_handle.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h" -#include "chrome/browser/resource_coordinator/tab_helper.h" -#include "chrome/browser/resource_coordinator/time.h" -#include "chrome/browser/resource_coordinator/utils.h" -#include "components/performance_manager/performance_manager_impl.h" -#include "components/performance_manager/public/graph/frame_node.h" -#include "components/performance_manager/public/graph/graph.h" -#include "components/performance_manager/public/graph/page_node.h" -#include "components/performance_manager/public/web_contents_proxy.h" -#include "content/public/browser/navigation_handle.h" -#include "content/public/browser/web_contents.h" - -namespace resource_coordinator { - -namespace { - -using LoadingState = TabLoadTracker::LoadingState; - -// The period of time after loading during which we ignore title/favicon -// change events. It's possible for some site that are loaded in background to -// use some of these features without this being an attempt to communicate -// with the user (e.g. the tab is just really finishing to load). -constexpr base::TimeDelta kTitleOrFaviconChangePostLoadGracePeriod = - base::TimeDelta::FromSeconds(20); - -// The period of time during which we ignore events after a tab gets -// backgrounded. It's necessary because some events might happen shortly after -// backgrounding a tab without this being an attempt to communicate with the -// user: -// - There might be a delay between a media request gets initiated and the -// time the audio actually starts. -// - Same-document navigation can cause the title or favicon to change, if -// the user switch tab before this completes this will be recorded as a -// background communication event while in reality it's just a navigation -// event. -constexpr base::TimeDelta kFeatureUsagePostBackgroundGracePeriod = - base::TimeDelta::FromSeconds(10); - -performance_manager::TabVisibility ContentVisibilityToRCVisibility( - content::Visibility visibility) { - if (visibility == content::Visibility::VISIBLE) - return performance_manager::TabVisibility::kForeground; - return performance_manager::TabVisibility::kBackground; -} - -} // namespace - -LocalSiteCharacteristicsWebContentsObserver:: - LocalSiteCharacteristicsWebContentsObserver( - content::WebContents* web_contents) - : content::WebContentsObserver(web_contents) { - // May not be present in some tests. - if (performance_manager::PerformanceManagerImpl::IsAvailable()) { - TabLoadTracker::Get()->AddObserver(this); - } -} - -LocalSiteCharacteristicsWebContentsObserver:: - ~LocalSiteCharacteristicsWebContentsObserver() { - DCHECK(!writer_); -} - -void LocalSiteCharacteristicsWebContentsObserver::OnVisibilityChanged( - content::Visibility visibility) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!writer_) - return; - - auto rc_visibility = ContentVisibilityToRCVisibility(visibility); - UpdateBackgroundedTime(rc_visibility); - writer_->NotifySiteVisibilityChanged(rc_visibility); -} - -void LocalSiteCharacteristicsWebContentsObserver::WebContentsDestroyed() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (performance_manager::PerformanceManagerImpl::IsAvailable()) - TabLoadTracker::Get()->RemoveObserver(this); - writer_.reset(); - writer_origin_ = url::Origin(); -} - -void LocalSiteCharacteristicsWebContentsObserver::DidFinishNavigation( - content::NavigationHandle* navigation_handle) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(navigation_handle); - - // Ignore the navigation events happening in a subframe of in the same - // document. - if (!navigation_handle->IsInMainFrame() || - navigation_handle->IsSameDocument()) { - return; - } - - first_time_title_set_ = false; - first_time_favicon_set_ = false; - - if (!navigation_handle->HasCommitted()) - return; - - const url::Origin new_origin = - url::Origin::Create(navigation_handle->GetURL()); - - if (writer_ && new_origin == writer_origin_) - return; - - writer_.reset(); - writer_origin_ = url::Origin(); - - if (!URLShouldBeStoredInLocalDatabase(navigation_handle->GetURL())) - return; - - Profile* profile = - Profile::FromBrowserContext(web_contents()->GetBrowserContext()); - DCHECK(profile); - SiteCharacteristicsDataStore* data_store = - LocalSiteCharacteristicsDataStoreFactory::GetForProfile(profile); - - // A data store might not be available in some unit tests. - if (data_store) { - auto rc_visibility = - ContentVisibilityToRCVisibility(web_contents()->GetVisibility()); - writer_ = data_store->GetWriterForOrigin(new_origin, rc_visibility); - UpdateBackgroundedTime(rc_visibility); - } - - // The writer is initially in an unloaded state, load it if necessary. - if (TabLoadTracker::Get()->GetLoadingState(web_contents()) == - LoadingState::LOADED) { - OnSiteLoaded(); - } - - writer_origin_ = new_origin; -} - -void LocalSiteCharacteristicsWebContentsObserver::TitleWasSet( - content::NavigationEntry* entry) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // TODO(sebmarchand): Check if the title is always set at least once before - // loading completes, in which case this check could be removed. - if (!first_time_title_set_) { - first_time_title_set_ = true; - return; - } - - MaybeNotifyBackgroundFeatureUsage( - &SiteCharacteristicsDataWriter::NotifyUpdatesTitleInBackground, - FeatureType::kTitleChange); -} - -void LocalSiteCharacteristicsWebContentsObserver::DidUpdateFaviconURL( - content::RenderFrameHost* rfh, - const std::vector<blink::mojom::FaviconURLPtr>& candidates) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (!first_time_favicon_set_) { - first_time_favicon_set_ = true; - return; - } - - MaybeNotifyBackgroundFeatureUsage( - &SiteCharacteristicsDataWriter::NotifyUpdatesFaviconInBackground, - FeatureType::kFaviconChange); -} - -void LocalSiteCharacteristicsWebContentsObserver::OnAudioStateChanged( - bool audible) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (!audible) - return; - - MaybeNotifyBackgroundFeatureUsage( - &SiteCharacteristicsDataWriter::NotifyUsesAudioInBackground, - FeatureType::kAudioUsage); -} - -void LocalSiteCharacteristicsWebContentsObserver::OnLoadingStateChange( - content::WebContents* contents, - LoadingState old_loading_state, - LoadingState new_loading_state) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (web_contents() != contents) - return; - - if (!writer_) - return; - - // Ignore the transitions from/to an UNLOADED state. - if (new_loading_state == LoadingState::LOADED) { - OnSiteLoaded(); - } else if (old_loading_state == LoadingState::LOADED) { - writer_->NotifySiteUnloaded(); - loaded_time_ = base::TimeTicks(); - } -} - -bool LocalSiteCharacteristicsWebContentsObserver::ShouldIgnoreFeatureUsageEvent( - FeatureType feature_type) { - // The feature usage should be ignored if there's no writer for this tab. - if (!writer_) - return true; - - // Ignore all features happening before the website gets fully loaded. - if (TabLoadTracker::Get()->GetLoadingState(web_contents()) != - LoadingState::LOADED) { - return true; - } - - // Ignore events if the tab is not in background. - if (ContentVisibilityToRCVisibility(web_contents()->GetVisibility()) != - performance_manager::TabVisibility::kBackground) { - return true; - } - - if (feature_type == FeatureType::kTitleChange || - feature_type == FeatureType::kFaviconChange) { - DCHECK(!loaded_time_.is_null()); - if (NowTicks() - loaded_time_ < kTitleOrFaviconChangePostLoadGracePeriod) { - return true; - } - } - - // Ignore events happening shortly after the tab being backgrounded, they're - // usually false positives. - DCHECK(!backgrounded_time_.is_null()); - if ((NowTicks() - backgrounded_time_ < - kFeatureUsagePostBackgroundGracePeriod)) { - return true; - } - - return false; -} - -void LocalSiteCharacteristicsWebContentsObserver:: - MaybeNotifyBackgroundFeatureUsage( - void (SiteCharacteristicsDataWriter::*method)(), - FeatureType feature_type) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (ShouldIgnoreFeatureUsageEvent(feature_type)) - return; - - (writer_.get()->*method)(); -} - -void LocalSiteCharacteristicsWebContentsObserver::OnSiteLoaded() { - DCHECK(writer_); - writer_->NotifySiteLoaded(); - loaded_time_ = NowTicks(); -} - -void LocalSiteCharacteristicsWebContentsObserver::UpdateBackgroundedTime( - performance_manager::TabVisibility visibility) { - if (visibility == performance_manager::TabVisibility::kBackground) { - backgrounded_time_ = NowTicks(); - } else { - backgrounded_time_ = base::TimeTicks(); - } -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h b/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h deleted file mode 100644 index 16b6a78..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h +++ /dev/null
@@ -1,108 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_WEBCONTENTS_OBSERVER_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_WEBCONTENTS_OBSERVER_H_ - -#include "base/macros.h" -#include "base/sequence_checker.h" -#include "base/time/time.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_writer.h" -#include "chrome/browser/resource_coordinator/tab_load_tracker.h" -#include "content/public/browser/visibility.h" -#include "content/public/browser/web_contents_observer.h" -#include "third_party/blink/public/mojom/favicon/favicon_url.mojom-forward.h" -#include "url/origin.h" - -namespace content { -class NavigationHandle; -} - -namespace resource_coordinator { - -// WebContents observer that manages a SiteCharacteristicsDataWriter associated -// with a WebContents and forwards the appropriate events to it. -class LocalSiteCharacteristicsWebContentsObserver - : public content::WebContentsObserver, - public TabLoadTracker::Observer { - public: - explicit LocalSiteCharacteristicsWebContentsObserver( - content::WebContents* contents); - ~LocalSiteCharacteristicsWebContentsObserver() override; - - // WebContentsObserver implementation. - void OnVisibilityChanged(content::Visibility visibility) override; - void WebContentsDestroyed() override; - void DidFinishNavigation( - content::NavigationHandle* navigation_handle) override; - void TitleWasSet(content::NavigationEntry* entry) override; - void DidUpdateFaviconURL( - content::RenderFrameHost* rfh, - const std::vector<blink::mojom::FaviconURLPtr>& candidates) override; - void OnAudioStateChanged(bool audible) override; - - // TabLoadTracker::Observer: - void OnLoadingStateChange(content::WebContents* web_contents, - LoadingState old_loading_state, - LoadingState new_loading_state) override; - - const url::Origin& writer_origin() const { return writer_origin_; } - - SiteCharacteristicsDataWriter* GetWriterForTesting() const { - return writer_.get(); - } - void ResetWriterForTesting() { writer_.reset(); } - - private: - enum class FeatureType { - kTitleChange, - kFaviconChange, - kAudioUsage, - }; - - // Indicates if the feature usage event just received should be ignored. - bool ShouldIgnoreFeatureUsageEvent(FeatureType feature_type); - - // Helper function to maybe notify |writer_| that a feature event has been - // received while in background. Doesn't do anything if - // ShouldIgnoreFeatureUsageEvent returns true. - void MaybeNotifyBackgroundFeatureUsage( - void (SiteCharacteristicsDataWriter::*method)(), - FeatureType feature_type); - - // Function to call when the site switch to the loaded state. - void OnSiteLoaded(); - - // Updates |backgrounded_time_| based on |visibility|. - void UpdateBackgroundedTime(performance_manager::TabVisibility visibility); - - // The writer that processes the event received by this class. - std::unique_ptr<SiteCharacteristicsDataWriter> writer_; - - // The Origin tracked by the writer. - url::Origin writer_origin_; - - // Favicon and title are set when a page is loaded, we only want to send - // signals to the database about title and favicon update from the previous - // title and favicon, thus we want to ignore the very first update since it is - // always supposed to happen. - bool first_time_favicon_set_ = false; - bool first_time_title_set_ = false; - - // The time at which this tab switched to the loaded state, null if this tab - // is not currently loaded. - base::TimeTicks loaded_time_; - - // The time at which this tab has been backgrounded, null if this tab is - // currently visible. - base::TimeTicks backgrounded_time_; - - SEQUENCE_CHECKER(sequence_checker_); - - DISALLOW_COPY_AND_ASSIGN(LocalSiteCharacteristicsWebContentsObserver); -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_WEBCONTENTS_OBSERVER_H_
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer_unittest.cc b/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer_unittest.cc deleted file mode 100644 index a8ddd6b..0000000 --- a/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer_unittest.cc +++ /dev/null
@@ -1,339 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h" - -#include "base/bind.h" -#include "base/macros.h" -#include "base/test/simple_test_tick_clock.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" -#include "chrome/browser/resource_coordinator/site_characteristics_data_store.h" -#include "chrome/browser/resource_coordinator/time.h" -#include "content/public/browser/web_contents.h" -#include "content/public/test/mock_navigation_handle.h" -#include "content/public/test/web_contents_tester.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" - -namespace resource_coordinator { - -using LoadingState = TabLoadTracker::LoadingState; - -constexpr base::TimeDelta kTitleOrFaviconChangePostLoadGracePeriod = - base::TimeDelta::FromSeconds(20); -constexpr base::TimeDelta kFeatureUsagePostBackgroundGracePeriod = - base::TimeDelta::FromSeconds(10); - -// A mock implementation of a SiteCharacteristicsDataWriter. -class LenientMockDataWriter : public SiteCharacteristicsDataWriter { - public: - explicit LenientMockDataWriter(const url::Origin& origin) : origin_(origin) {} - ~LenientMockDataWriter() override { OnDestroy(); } - - // Mock function to be notified when this object gets destroyed. - MOCK_METHOD0(OnDestroy, void()); - - MOCK_METHOD0(NotifySiteLoaded, void()); - MOCK_METHOD0(NotifySiteUnloaded, void()); - MOCK_METHOD1(NotifySiteVisibilityChanged, - void(performance_manager::TabVisibility)); - MOCK_METHOD0(NotifyUpdatesFaviconInBackground, void()); - MOCK_METHOD0(NotifyUpdatesTitleInBackground, void()); - MOCK_METHOD0(NotifyUsesAudioInBackground, void()); - MOCK_METHOD3(NotifyLoadTimePerformanceMeasurement, - void(base::TimeDelta, base::TimeDelta, uint64_t)); - - const url::Origin& Origin() const { return origin_; } - - private: - url::Origin origin_; - - DISALLOW_COPY_AND_ASSIGN(LenientMockDataWriter); -}; -using MockDataWriter = ::testing::StrictMock<LenientMockDataWriter>; - -// A data store that serves MockDataWriter objects. -class MockDataStore : public SiteCharacteristicsDataStore { - public: - MockDataStore() = default; - ~MockDataStore() override {} - - // SiteCharacteristicsDataStore: - std::unique_ptr<SiteCharacteristicsDataReader> GetReaderForOrigin( - const url::Origin& origin) override { - return nullptr; - } - std::unique_ptr<SiteCharacteristicsDataWriter> GetWriterForOrigin( - const url::Origin& origin, - performance_manager::TabVisibility tab_visibility) override { - return std::make_unique<MockDataWriter>(origin); - } - bool IsRecordingForTesting() override { return true; } - - private: - DISALLOW_COPY_AND_ASSIGN(MockDataStore); -}; - -std::unique_ptr<KeyedService> BuildMockDataStoreForContext( - content::BrowserContext* browser_context) { - return std::make_unique<MockDataStore>(); -} - -class LocalSiteCharacteristicsWebContentsObserverTest - : public testing::ChromeTestHarnessWithLocalDB { - protected: - LocalSiteCharacteristicsWebContentsObserverTest() - : scoped_set_tick_clock_for_testing_(&test_clock_) {} - ~LocalSiteCharacteristicsWebContentsObserverTest() override = default; - - void SetUp() override { - testing::ChromeTestHarnessWithLocalDB::SetUp(); - - test_clock().Advance(base::TimeDelta::FromSeconds(1)); - // Set the testing factory for the test browser context. - LocalSiteCharacteristicsDataStoreFactory::GetInstance()->SetTestingFactory( - browser_context(), base::BindRepeating(&BuildMockDataStoreForContext)); - - TabLoadTracker::Get()->StartTracking(web_contents()); - observer_ = std::make_unique<LocalSiteCharacteristicsWebContentsObserver>( - web_contents()); - } - - void TearDown() override { - TabLoadTracker::Get()->StopTracking(web_contents()); - DeleteContents(); - observer_.reset(); - testing::ChromeTestHarnessWithLocalDB::TearDown(); - } - - MockDataWriter* NavigateAndReturnMockWriter(const GURL& url) { - content::WebContentsTester* web_contents_tester = - content::WebContentsTester::For(web_contents()); - EXPECT_TRUE(web_contents_tester); - web_contents_tester->NavigateAndCommit(url); - return static_cast<MockDataWriter*>(observer_->GetWriterForTesting()); - } - - const GURL kTestUrl1 = GURL("http://foo.com"); - const GURL kTestUrl2 = GURL("http://bar.com"); - - LocalSiteCharacteristicsWebContentsObserver* observer() { - return observer_.get(); - } - - base::SimpleTestTickClock& test_clock() { return test_clock_; } - - private: - std::unique_ptr<LocalSiteCharacteristicsWebContentsObserver> observer_; - base::SimpleTestTickClock test_clock_; - ScopedSetTickClockForTesting scoped_set_tick_clock_for_testing_; - - DISALLOW_COPY_AND_ASSIGN(LocalSiteCharacteristicsWebContentsObserverTest); -}; - -TEST_F(LocalSiteCharacteristicsWebContentsObserverTest, - NavigationEventsBasicTests) { - // Send a navigation event with the |committed| bit set and make sure that a - // writer has been created for this origin. - - EXPECT_FALSE(observer()->GetWriterForTesting()); - MockDataWriter* mock_writer = NavigateAndReturnMockWriter(kTestUrl1); - EXPECT_TRUE(mock_writer); - - auto writer_origin = observer()->writer_origin(); - - EXPECT_EQ(url::Origin::Create(kTestUrl1), writer_origin); - - // A navigation to the same origin shouldn't cause caused this writer to get - // destroyed. - mock_writer = NavigateAndReturnMockWriter(kTestUrl1); - ::testing::Mock::VerifyAndClear(mock_writer); - - // Navigate to a different origin but don't set the |committed| bit, this - // shouldn't affect the writer. - content::MockNavigationHandle navigation_handle( - kTestUrl2, web_contents()->GetMainFrame()); - observer()->DidFinishNavigation(&navigation_handle); - ::testing::Mock::VerifyAndClear(mock_writer); - - // Set the |committed| bit and ensure that the navigation event cause the - // destruction of the writer. - EXPECT_CALL(*mock_writer, OnDestroy()); - mock_writer = NavigateAndReturnMockWriter(kTestUrl2); - ::testing::Mock::VerifyAndClear(mock_writer); - - EXPECT_FALSE(writer_origin == observer()->writer_origin()); - writer_origin = observer()->writer_origin(); - - EXPECT_EQ(url::Origin::Create(kTestUrl2), mock_writer->Origin()); - - EXPECT_CALL(*mock_writer, OnDestroy()); -} - -// Test that the feature usage events get forwarded to the writer when the tab -// is in background. -TEST_F(LocalSiteCharacteristicsWebContentsObserverTest, - FeatureEventsGetForwardedWhenInBackground) { - MockDataWriter* mock_writer = NavigateAndReturnMockWriter(kTestUrl1); - - // Send dummy events to simulate the initial title/favicon update (as these - // are ignored). - observer()->DidUpdateFaviconURL(web_contents()->GetMainFrame(), - std::vector<blink::mojom::FaviconURLPtr>()); - observer()->TitleWasSet(nullptr); - - EXPECT_CALL(*mock_writer, NotifySiteLoaded()); - TabLoadTracker::Get()->TransitionStateForTesting(web_contents(), - LoadingState::LOADED); - EXPECT_CALL(*mock_writer, - NotifySiteVisibilityChanged( - performance_manager::TabVisibility::kForeground)); - EXPECT_CALL(*mock_writer, NotifySiteLoaded()); - web_contents()->WasShown(); - observer()->OnLoadingStateChange(web_contents(), - TabLoadTracker::LoadingState::LOADING, - TabLoadTracker::LoadingState::LOADED); - ::testing::Mock::VerifyAndClear(mock_writer); - - // Ensure that no event gets forwarded if the tab is not in background. - observer()->DidUpdateFaviconURL(web_contents()->GetMainFrame(), {}); - ::testing::Mock::VerifyAndClear(mock_writer); - observer()->TitleWasSet(nullptr); - ::testing::Mock::VerifyAndClear(mock_writer); - observer()->OnAudioStateChanged(true); - ::testing::Mock::VerifyAndClear(mock_writer); - - EXPECT_CALL(*mock_writer, - NotifySiteVisibilityChanged( - performance_manager::TabVisibility::kBackground)); - web_contents()->WasHidden(); - ::testing::Mock::VerifyAndClear(mock_writer); - - // Title and Favicon should be ignored during the post-loading grace period. - observer()->DidUpdateFaviconURL(web_contents()->GetMainFrame(), {}); - observer()->TitleWasSet(nullptr); - ::testing::Mock::VerifyAndClear(mock_writer); - - test_clock().Advance(kTitleOrFaviconChangePostLoadGracePeriod); - - EXPECT_CALL(*mock_writer, NotifyUpdatesFaviconInBackground()); - observer()->DidUpdateFaviconURL(web_contents()->GetMainFrame(), {}); - ::testing::Mock::VerifyAndClear(mock_writer); - EXPECT_CALL(*mock_writer, NotifyUpdatesTitleInBackground()); - observer()->TitleWasSet(nullptr); - ::testing::Mock::VerifyAndClear(mock_writer); - - // Brievly switch the tab to foreground to reset the last backgrounded time. - EXPECT_CALL(*mock_writer, - NotifySiteVisibilityChanged( - performance_manager::TabVisibility::kForeground)); - EXPECT_CALL(*mock_writer, - NotifySiteVisibilityChanged( - performance_manager::TabVisibility::kBackground)); - web_contents()->WasShown(); - web_contents()->WasHidden(); - ::testing::Mock::VerifyAndClear(mock_writer); - - // These events should be ignored during the post-background grace period. - observer()->OnAudioStateChanged(true); - observer()->DidUpdateFaviconURL(web_contents()->GetMainFrame(), {}); - observer()->TitleWasSet(nullptr); - ::testing::Mock::VerifyAndClear(mock_writer); - - test_clock().Advance(kFeatureUsagePostBackgroundGracePeriod); - EXPECT_CALL(*mock_writer, NotifyUsesAudioInBackground()); - EXPECT_CALL(*mock_writer, NotifyUpdatesFaviconInBackground()); - EXPECT_CALL(*mock_writer, NotifyUpdatesTitleInBackground()); - observer()->OnAudioStateChanged(true); - observer()->DidUpdateFaviconURL(web_contents()->GetMainFrame(), {}); - observer()->TitleWasSet(nullptr); - ::testing::Mock::VerifyAndClear(mock_writer); - - EXPECT_CALL(*mock_writer, OnDestroy()); -} - -TEST_F(LocalSiteCharacteristicsWebContentsObserverTest, - FeatureEventsIgnoredWhenLoadingInBackground) { - MockDataWriter* mock_writer = NavigateAndReturnMockWriter(kTestUrl1); - - // Send dummy events to simulate the initial title/favicon update (as these - // are ignored). - observer()->DidUpdateFaviconURL(web_contents()->GetMainFrame(), {}); - observer()->TitleWasSet(nullptr); - - TabLoadTracker::Get()->TransitionStateForTesting(web_contents(), - LoadingState::LOADING); - - EXPECT_CALL(*mock_writer, - NotifySiteVisibilityChanged( - performance_manager::TabVisibility::kBackground)); - web_contents()->WasHidden(); - ::testing::Mock::VerifyAndClear(mock_writer); - - observer()->DidUpdateFaviconURL(web_contents()->GetMainFrame(), {}); - ::testing::Mock::VerifyAndClear(mock_writer); - observer()->TitleWasSet(nullptr); - ::testing::Mock::VerifyAndClear(mock_writer); - observer()->OnAudioStateChanged(true); - ::testing::Mock::VerifyAndClear(mock_writer); - - EXPECT_CALL(*mock_writer, OnDestroy()); -} - -TEST_F(LocalSiteCharacteristicsWebContentsObserverTest, VisibilityEvent) { - MockDataWriter* mock_writer = NavigateAndReturnMockWriter(kTestUrl1); - - // Test that the visibility events get forwarded to the writer. - - EXPECT_CALL(*mock_writer, - NotifySiteVisibilityChanged( - performance_manager::TabVisibility::kBackground)) - .Times(2); - observer()->OnVisibilityChanged(content::Visibility::OCCLUDED); - observer()->OnVisibilityChanged(content::Visibility::HIDDEN); - ::testing::Mock::VerifyAndClear(mock_writer); - - EXPECT_CALL(*mock_writer, - NotifySiteVisibilityChanged( - performance_manager::TabVisibility::kForeground)); - observer()->OnVisibilityChanged(content::Visibility::VISIBLE); - ::testing::Mock::VerifyAndClear(mock_writer); - - EXPECT_CALL(*mock_writer, OnDestroy()); -} - -TEST_F(LocalSiteCharacteristicsWebContentsObserverTest, LoadEvent) { - MockDataWriter* mock_writer = NavigateAndReturnMockWriter(kTestUrl1); - - // Test that the load/unload events get forwarded to the writer. - - EXPECT_CALL(*mock_writer, NotifySiteLoaded()); - observer()->OnLoadingStateChange(web_contents(), - TabLoadTracker::LoadingState::LOADING, - TabLoadTracker::LoadingState::LOADED); - ::testing::Mock::VerifyAndClear(mock_writer); - - EXPECT_CALL(*mock_writer, NotifySiteUnloaded()); - observer()->OnLoadingStateChange(web_contents(), - TabLoadTracker::LoadingState::LOADED, - TabLoadTracker::LoadingState::LOADING); - ::testing::Mock::VerifyAndClear(mock_writer); - - observer()->OnLoadingStateChange(web_contents(), - TabLoadTracker::LoadingState::LOADING, - TabLoadTracker::LoadingState::UNLOADED); - ::testing::Mock::VerifyAndClear(mock_writer); - - // Ensure that a transition from UNLOADED to LOADING doesn't cause any call to - // NotifySiteUnloaded. - observer()->OnLoadingStateChange(web_contents(), - TabLoadTracker::LoadingState::LOADING, - TabLoadTracker::LoadingState::UNLOADED); - - EXPECT_CALL(*mock_writer, OnDestroy()); -} - -} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/session_restore_policy.cc b/chrome/browser/resource_coordinator/session_restore_policy.cc index da732c4..fca3755 100644 --- a/chrome/browser/resource_coordinator/session_restore_policy.cc +++ b/chrome/browser/resource_coordinator/session_restore_policy.cc
@@ -10,9 +10,11 @@ #include <utility> #include "base/bind.h" +#include "base/callback_forward.h" #include "base/feature_list.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" +#include "base/sequence_checker.h" #include "base/stl_util.h" #include "base/system/sys_info.h" #include "base/threading/sequenced_task_runner_handle.h" @@ -20,14 +22,18 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/resource_coordinator/tab_manager_features.h" #include "chrome/common/url_constants.h" +#include "components/performance_manager/public/decorators/site_data_recorder.h" +#include "components/performance_manager/public/graph/graph.h" +#include "components/performance_manager/public/performance_manager.h" +#include "components/performance_manager/public/persistence/site_data/site_data_reader.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/web_contents.h" #if !defined(OS_ANDROID) #include "chrome/browser/permissions/permission_manager_factory.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h" -#include "chrome/browser/resource_coordinator/site_characteristics_data_reader.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -108,96 +114,98 @@ TabDataAccess(const TabDataAccess&) = delete; TabDataAccess& operator=(const TabDataAccess&) = delete; - // Schedule the task that will initialize |TabData::used_in_bg| from the local - // site characteristics database. This will either call - // |SetUsedInBgFromSiteCharacteristicsDataReader| if the data is available - // immediately, or will schedule a call to |OnSiteDataLoaded| once the data is - // available. - static void SetUsedInBgFromSiteCharacteristicsDB( + // Schedule the task that will initialize |TabData::used_in_bg| from the site + // data database. This will schedule a call to |OnSiteDataLoaded| once the + // data is available. + static void SetUsedInBgFromSiteDataDB( base::WeakPtr<SessionRestorePolicy> policy, TabData* tab_data, content::WebContents* contents); - // Set the |TabData::used_in_bg| bit based on the data provided by |reader|. - static void SetUsedInBgFromSiteCharacteristicsDataReader( - TabData* tab_data, - content::WebContents* contents, - std::unique_ptr<SiteCharacteristicsDataReader> reader); + // Set the |TabData::used_in_bg| bit based on the data returned from the site + // data database. + static void SetUsedInBgFromSiteData(TabData* tab_data, + content::WebContents* contents, + TabData::SiteDataReaderData reader_data); - // Callback that is invoked when the SiteCharacteristicsDataReader associated - // with a WebContents is ready to use. This will initialize - // |tab_data->used_in_bg| to the proper value and call - // |DispatchNotifyAllTabsScoredIfNeeded|. - static void OnSiteDataLoaded( - base::WeakPtr<SessionRestorePolicy> policy, - content::WebContents* contents, - std::unique_ptr<SiteCharacteristicsDataReader> reader); + // Callback that is invoked when the SiteData associated with a WebContents is + // ready to use. This will initialize |tab_data->used_in_bg| to the proper + // value and call |DispatchNotifyAllTabsScoredIfNeeded|. + static void OnSiteDataAvailable(base::WeakPtr<SessionRestorePolicy> policy, + content::WebContents* contents, + TabData::SiteDataReaderData reader_data); }; -void TabDataAccess::SetUsedInBgFromSiteCharacteristicsDB( +void TabDataAccess::SetUsedInBgFromSiteDataDB( base::WeakPtr<SessionRestorePolicy> policy, TabData* tab_data, content::WebContents* contents) { - // Get a reader for the local site characteristics data corresponding to this - // tab's origin. This makes it possible to determine if the tab has been - // observed communicating with the user while in the background. This can be - // ready immediately in which case a final score is emitted immediately. - // Otherwise, it will be loaded asynchronously and the score will potentially - // be updated. - Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); - DCHECK(profile); - auto* factory = LocalSiteCharacteristicsDataStoreFactory::GetInstance(); - auto* store = factory->GetForProfile(profile); + tab_data->used_in_bg_setter_cancel_callback.Reset(base::BindOnce( + &TabDataAccess::OnSiteDataAvailable, std::move(policy), contents)); - // The local database isn't always available. - // TODO(chrisha): Note that the reader can only not exist in tests. Once we - // have a single point to check for the availability of the performance - // manager, gate the following logic behind that. - if (!store) { - tab_data->used_in_bg = false; - return; - } + auto call_on_graph_cb = base::BindOnce( + [](base::WeakPtr<performance_manager::PageNode> page_node, + base::OnceCallback<void(TabData::SiteDataReaderData)> reply_cb, + scoped_refptr<base::SequencedTaskRunner> reply_task_runner) { + if (!page_node) { + reply_task_runner->PostTask( + FROM_HERE, base::BindOnce(std::move(reply_cb), + TabData::SiteDataReaderData())); + return; + } + auto* reader = + performance_manager::SiteDataRecorder::Data::FromPageNode( + page_node.get()) + ->reader(); + // The tab won't have a reader if it doesn't have an URL tracked in the + // site data database. + if (!reader) { + reply_task_runner->PostTask( + FROM_HERE, base::BindOnce(std::move(reply_cb), + TabData::SiteDataReaderData())); + return; + } - auto reader = store->GetReaderForOrigin( - url::Origin::Create(contents->GetLastCommittedURL())); + // The reader will call |reply_cb| once the data is available. + reader->RegisterDataLoadedCallback(base::BindOnce( + [](const performance_manager::SiteDataReader* reader, + base::OnceCallback<void(TabData::SiteDataReaderData)> reply_cb, + scoped_refptr<base::SequencedTaskRunner> reply_task_runner) { + static const performance_manager::SiteFeatureUsage kNotUsed = + performance_manager::SiteFeatureUsage::kSiteFeatureNotInUse; + TabData::SiteDataReaderData reader_data = {}; + reader_data.updates_favicon_in_bg = + reader->UpdatesFaviconInBackground() != kNotUsed; + reader_data.updates_title_in_bg = + reader->UpdatesTitleInBackground() != kNotUsed; + reply_task_runner->PostTask( + FROM_HERE, base::BindOnce(std::move(reply_cb), reader_data)); + }, + base::Unretained(reader), std::move(reply_cb), reply_task_runner)); + }, + performance_manager::PerformanceManager::GetPageNodeForWebContents( + contents), + tab_data->used_in_bg_setter_cancel_callback.callback(), + base::SequencedTaskRunnerHandle::Get()); - if (reader->DataLoaded()) { - SetUsedInBgFromSiteCharacteristicsDataReader(tab_data, contents, - std::move(reader)); - DCHECK(tab_data->used_in_bg.has_value()); - if (tab_data->used_in_bg) - ++policy->tabs_used_in_bg_; - } else { - auto* reader_raw = reader.get(); - tab_data->used_in_bg_setter_cancel_closure.Reset( - base::BindOnce(&TabDataAccess::OnSiteDataLoaded, std::move(policy), - contents, std::move(reader))); - reader_raw->RegisterDataLoadedCallback( - tab_data->used_in_bg_setter_cancel_closure.callback()); - } + performance_manager::PerformanceManager::CallOnGraph( + FROM_HERE, std::move(call_on_graph_cb)); } -void TabDataAccess::SetUsedInBgFromSiteCharacteristicsDataReader( +void TabDataAccess::SetUsedInBgFromSiteData( TabData* tab_data, content::WebContents* contents, - std::unique_ptr<SiteCharacteristicsDataReader> reader) { - static const performance_manager::SiteFeatureUsage kNotUsed = - performance_manager::SiteFeatureUsage::kSiteFeatureNotInUse; - DCHECK(reader->DataLoaded()); - + TabData::SiteDataReaderData reader_data) { // Determine if background communication with the user is used. A pinned tab // has no visible tab title, so tab title updates can be ignored in that case. // The audio bit is ignored as tab can't play audio until they have been // visible at least once. We err on the side of caution, if unsure about a // feature (usually because of a lack of observation) then the feature is // considered as used. - bool used_in_bg = reader->UpdatesFaviconInBackground() != kNotUsed; - if (!tab_data->is_pinned && (reader->UpdatesTitleInBackground() != kNotUsed)) + bool used_in_bg = reader_data.updates_favicon_in_bg; + if (!tab_data->is_pinned && reader_data.updates_title_in_bg) used_in_bg = true; - // TODO(sebmarchand): Consider that the tabs that are still under observation - // could be used in background. - auto notif_permission = PermissionManagerFactory::GetForProfile( Profile::FromBrowserContext(contents->GetBrowserContext())) @@ -207,20 +215,13 @@ if (notif_permission.content_setting == CONTENT_SETTING_ALLOW) used_in_bg = true; - // Persist this data and detach from the reader. We need to detach from the - // reader in a separate task because this callback is actually being invoked - // by the reader itself; as we're the sole owner, we'll cause it to be deleted - // while several stack frames deep in its code, causing an immediate use - // after free. tab_data->used_in_bg = used_in_bg; - base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, - std::move(reader)); } -void TabDataAccess::OnSiteDataLoaded( +void TabDataAccess::OnSiteDataAvailable( base::WeakPtr<SessionRestorePolicy> policy, content::WebContents* contents, - std::unique_ptr<SiteCharacteristicsDataReader> reader) { + TabData::SiteDataReaderData reader_data) { if (!policy) return; @@ -228,8 +229,7 @@ DCHECK(it != policy->tab_data_.end()); auto* tab_data = it->second.get(); - SetUsedInBgFromSiteCharacteristicsDataReader(tab_data, contents, - std::move(reader)); + SetUsedInBgFromSiteData(tab_data, contents, reader_data); // Score the tab and notify observers if the score has changed. if (policy->RescoreTabAfterDataLoaded(contents, tab_data)) @@ -300,8 +300,8 @@ // The local database doesn't exist on Android at all. #if !defined(OS_ANDROID) - TabDataAccess::SetUsedInBgFromSiteCharacteristicsDB( - weak_factory_.GetWeakPtr(), tab_data, contents); + TabDataAccess::SetUsedInBgFromSiteDataDB(weak_factory_.GetWeakPtr(), tab_data, + contents); #endif // !defined(OS_ANDROID) // Another tab has been added, so an existing all tabs scored notification may @@ -557,7 +557,7 @@ SessionRestorePolicy::TabData::TabData() = default; SessionRestorePolicy::TabData::~TabData() { - used_in_bg_setter_cancel_closure.Cancel(); + used_in_bg_setter_cancel_callback.Cancel(); } bool SessionRestorePolicy::TabData::UsedInBg() const {
diff --git a/chrome/browser/resource_coordinator/session_restore_policy.h b/chrome/browser/resource_coordinator/session_restore_policy.h index 3b71654..c97f51e 100644 --- a/chrome/browser/resource_coordinator/session_restore_policy.h +++ b/chrome/browser/resource_coordinator/session_restore_policy.h
@@ -184,9 +184,15 @@ // change as new data becomes available. float score = 0.0f; - // Cancelable closure used to cancel the async initialization of the - // |used_in_bg| if it comes too late. - base::CancelableOnceClosure used_in_bg_setter_cancel_closure; + struct SiteDataReaderData { + bool updates_favicon_in_bg = false; + bool updates_title_in_bg = false; + }; + + // Cancelable callback used to cancel the async initialization of the + // |used_in_bg| bit. + base::CancelableOnceCallback<void(SiteDataReaderData)> + used_in_bg_setter_cancel_callback; }; // This is safe to call from the constructor if |delegate_| is already
diff --git a/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc b/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc index df850e0c..2c04494 100644 --- a/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc +++ b/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
@@ -8,6 +8,7 @@ #include <vector> #include "base/bind.h" +#include "base/memory/weak_ptr.h" #include "base/rand_util.h" #include "base/run_loop.h" #include "base/test/bind_test_util.h" @@ -15,10 +16,16 @@ #include "base/test/simple_test_tick_clock.h" #include "build/build_config.h" #include "chrome/browser/notifications/notification_permission_context.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" +#if !defined(OS_ANDROID) +#include "chrome/browser/performance_manager/test_support/site_data_utils.h" +#endif #include "chrome/browser/resource_coordinator/tab_helper.h" #include "chrome/browser/resource_coordinator/tab_manager_features.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "components/performance_manager/persistence/site_data/site_data_impl.h" +#include "components/performance_manager/persistence/site_data/site_data_writer.h" +#include "components/performance_manager/public/decorators/site_data_recorder.h" +#include "components/performance_manager/public/performance_manager.h" #include "content/public/browser/web_contents.h" #include "content/public/test/web_contents_tester.h" #include "testing/gmock/include/gmock/gmock.h" @@ -132,14 +139,19 @@ } // namespace -class SessionRestorePolicyTest : public testing::ChromeTestHarnessWithLocalDB { +class SessionRestorePolicyTest : public ChromeRenderViewHostTestHarness { public: SessionRestorePolicyTest() : delegate_(&clock_) {} ~SessionRestorePolicyTest() override {} void SetUp() override { - testing::ChromeTestHarnessWithLocalDB::SetUp(); + ChromeRenderViewHostTestHarness::SetUp(); + +#if !defined(OS_ANDROID) + // Some tests requires the SiteData database to be initialized. + site_data_harness_.SetUp(); +#endif // Set some reasonable delegate constants. delegate_.SetNumberOfCores(4); @@ -154,15 +166,12 @@ void TearDown() override { #if !defined(OS_ANDROID) - resource_coordinator::testing::GetLocalSiteCharacteristicsDataImplForWC( - contents1_.get()) - ->NotifySiteUnloaded(performance_manager::TabVisibility::kBackground); - resource_coordinator::testing::GetLocalSiteCharacteristicsDataImplForWC( - contents2_.get()) - ->NotifySiteUnloaded(performance_manager::TabVisibility::kBackground); - resource_coordinator::testing::GetLocalSiteCharacteristicsDataImplForWC( - contents3_.get()) - ->NotifySiteUnloaded(performance_manager::TabVisibility::kBackground); + performance_manager::MarkWebContentsAsUnloadedInBackgroundInSiteDataDb( + contents1_.get()); + performance_manager::MarkWebContentsAsUnloadedInBackgroundInSiteDataDb( + contents2_.get()); + performance_manager::MarkWebContentsAsUnloadedInBackgroundInSiteDataDb( + contents3_.get()); #endif if (policy_) policy_.reset(); @@ -175,7 +184,10 @@ tab_for_scoring_.clear(); - testing::ChromeTestHarnessWithLocalDB::TearDown(); +#if !defined(OS_ANDROID) + site_data_harness_.TearDown(profile()); +#endif + ChromeRenderViewHostTestHarness::TearDown(); } void CreateTestContents() { @@ -200,11 +212,10 @@ tester->SetLastActiveTime(last_active); #if !defined(OS_ANDROID) - ResourceCoordinatorTabHelper::CreateForWebContents(contents.get()); tester->NavigateAndCommit(url); - resource_coordinator::testing::MarkWebContentsAsLoadedInBackground( + performance_manager::MarkWebContentsAsLoadedInBackgroundInSiteDataDb( contents.get()); - resource_coordinator::testing::ExpireLocalDBObservationWindows( + performance_manager::ExpireSiteDataObservationWindowsForWebContents( contents.get()); #endif return contents; @@ -252,6 +263,10 @@ base::SimpleTestTickClock clock_; TestDelegate delegate_; +#if !defined(OS_ANDROID) + performance_manager::SiteDataTestHarness site_data_harness_; +#endif + TabScoreChangeMock mock_; std::unique_ptr<TestSessionRestorePolicy> policy_; @@ -486,13 +501,10 @@ policy_->AddTabForScoring(contents5.get()); WaitForFinalTabScores(); - resource_coordinator::testing::GetLocalSiteCharacteristicsDataImplForWC( - contents4.get()) - ->NotifySiteUnloaded(performance_manager::TabVisibility::kBackground); - - resource_coordinator::testing::GetLocalSiteCharacteristicsDataImplForWC( - contents5.get()) - ->NotifySiteUnloaded(performance_manager::TabVisibility::kBackground); + performance_manager::MarkWebContentsAsUnloadedInBackgroundInSiteDataDb( + contents4.get()); + performance_manager::MarkWebContentsAsUnloadedInBackgroundInSiteDataDb( + contents5.get()); } TEST_F(SessionRestorePolicyTest, CalculateAgeScore) { @@ -622,9 +634,23 @@ // Indicates that |contents1_| might update its title while in background, // this should set the |used_in_bg_| bit. - resource_coordinator::testing::GetLocalSiteCharacteristicsDataImplForWC( - contents1_.get()) - ->NotifyUpdatesTitleInBackground(); + base::RunLoop run_loop; + performance_manager::PerformanceManager::CallOnGraph( + FROM_HERE, + base::BindOnce( + [](base::WeakPtr<performance_manager::PageNode> page_node, + base::OnceClosure closure) { + EXPECT_TRUE(page_node); + auto* impl = performance_manager::GetSiteDataImplForPageNode( + page_node.get()); + EXPECT_TRUE(impl); + impl->NotifyUpdatesTitleInBackground(); + std::move(closure).Run(); + }, + performance_manager::PerformanceManager::GetPageNodeForWebContents( + contents1_.get()), + run_loop.QuitClosure())); + run_loop.Run(); // Adding/Removing the tab for scoring will cause the callback to be called a // few times, ignore this. @@ -655,12 +681,27 @@ CreatePolicy(true); WaitForFinalTabScores(); - performance_manager::SiteFeatureUsage title_feature_usage = - resource_coordinator::testing::GetLocalSiteCharacteristicsDataImplForWC( - contents.get()) - ->UpdatesTitleInBackground(); - EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, - title_feature_usage); + base::RunLoop run_loop; + performance_manager::PerformanceManager::CallOnGraph( + FROM_HERE, + base::BindOnce( + [](base::WeakPtr<performance_manager::PageNode> page_node, + base::OnceClosure closure) { + EXPECT_TRUE(page_node); + auto* impl = performance_manager::GetSiteDataImplForPageNode( + page_node.get()); + EXPECT_TRUE(impl); + performance_manager::SiteFeatureUsage title_feature_usage = + impl->UpdatesTitleInBackground(); + EXPECT_EQ( + performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown, + title_feature_usage); + std::move(closure).Run(); + }, + performance_manager::PerformanceManager::GetPageNodeForWebContents( + contents.get()), + run_loop.QuitClosure())); + run_loop.Run(); auto iter = policy_->tab_data_.find(contents.get()); EXPECT_TRUE(iter != policy_->tab_data_.end());
diff --git a/chrome/browser/resource_coordinator/site_characteristics_data_reader.h b/chrome/browser/resource_coordinator/site_characteristics_data_reader.h deleted file mode 100644 index 6f0c4868..0000000 --- a/chrome/browser/resource_coordinator/site_characteristics_data_reader.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_SITE_CHARACTERISTICS_DATA_READER_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_SITE_CHARACTERISTICS_DATA_READER_H_ - -#include "components/performance_manager/persistence/site_data/feature_usage.h" - -#include "base/callback_forward.h" - -namespace resource_coordinator { - -// Pure virtual interface to read the characteristics of an origin. This is a -// usable abstraction for both the local and global database. -class SiteCharacteristicsDataReader { - public: - SiteCharacteristicsDataReader() = default; - virtual ~SiteCharacteristicsDataReader() {} - - // Accessors for the site characteristics usage. - virtual performance_manager::SiteFeatureUsage UpdatesFaviconInBackground() - const = 0; - virtual performance_manager::SiteFeatureUsage UpdatesTitleInBackground() - const = 0; - virtual performance_manager::SiteFeatureUsage UsesAudioInBackground() - const = 0; - - // Returns true if this reader is fully initialized and serving the most - // authoritative data. This can initially return false as the backing store is - // loaded asynchronously. - virtual bool DataLoaded() const = 0; - - // Registers a callback that will be invoked when the data backing this object - // has been loaded. Note that if "DataLoaded" is true at the time this is - // called it may immediately invoke the callback. The callback will not be - // invoked after this object has been destroyed. - virtual void RegisterDataLoadedCallback(base::OnceClosure&& callback) = 0; -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_SITE_CHARACTERISTICS_DATA_READER_H_
diff --git a/chrome/browser/resource_coordinator/site_characteristics_data_store.h b/chrome/browser/resource_coordinator/site_characteristics_data_store.h deleted file mode 100644 index 59037e23c..0000000 --- a/chrome/browser/resource_coordinator/site_characteristics_data_store.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_SITE_CHARACTERISTICS_DATA_STORE_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_SITE_CHARACTERISTICS_DATA_STORE_H_ - -#include <memory> - -#include "base/macros.h" -#include "chrome/browser/resource_coordinator/site_characteristics_data_reader.h" -#include "chrome/browser/resource_coordinator/site_characteristics_data_writer.h" -#include "components/keyed_service/core/keyed_service.h" -#include "components/performance_manager/persistence/site_data/tab_visibility.h" -#include "url/origin.h" - -namespace resource_coordinator { - -// Pure virtual interface for a site characteristics data store. -class SiteCharacteristicsDataStore : public KeyedService { - public: - SiteCharacteristicsDataStore() = default; - ~SiteCharacteristicsDataStore() override {} - - // Returns a SiteCharacteristicsDataReader for the given origin. - virtual std::unique_ptr<SiteCharacteristicsDataReader> GetReaderForOrigin( - const url::Origin& origin) = 0; - - // Returns a SiteCharacteristicsDataWriter for the given origin. - // - // |tab_visibility| indicates the current visibility of the tab. The writer - // starts in an unloaded state, NotifyTabLoaded() must be called explicitly - // afterwards if the site is loaded. - virtual std::unique_ptr<SiteCharacteristicsDataWriter> GetWriterForOrigin( - const url::Origin& origin, - performance_manager::TabVisibility tab_visibility) = 0; - - // Indicate if the SiteCharacteristicsDataWriter served by this data store - // actually persist informations. - virtual bool IsRecordingForTesting() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(SiteCharacteristicsDataStore); -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_SITE_CHARACTERISTICS_DATA_STORE_H_
diff --git a/chrome/browser/resource_coordinator/site_characteristics_data_writer.h b/chrome/browser/resource_coordinator/site_characteristics_data_writer.h deleted file mode 100644 index cbfff1c..0000000 --- a/chrome/browser/resource_coordinator/site_characteristics_data_writer.h +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_SITE_CHARACTERISTICS_DATA_WRITER_H_ -#define CHROME_BROWSER_RESOURCE_COORDINATOR_SITE_CHARACTERISTICS_DATA_WRITER_H_ - -#include "base/time/time.h" -#include "components/performance_manager/persistence/site_data/tab_visibility.h" - -namespace resource_coordinator { - -// Pure virtual interface to record the observations made for an origin. -class SiteCharacteristicsDataWriter { - public: - SiteCharacteristicsDataWriter() = default; - virtual ~SiteCharacteristicsDataWriter() {} - - // Records tab load/unload events. - virtual void NotifySiteLoaded() = 0; - virtual void NotifySiteUnloaded() = 0; - - // Records visibility change events. - virtual void NotifySiteVisibilityChanged( - performance_manager::TabVisibility visibility) = 0; - - // Records feature usage. - virtual void NotifyUpdatesFaviconInBackground() = 0; - virtual void NotifyUpdatesTitleInBackground() = 0; - virtual void NotifyUsesAudioInBackground() = 0; - - // Records performance measurements. - virtual void NotifyLoadTimePerformanceMeasurement( - base::TimeDelta load_duration, - base::TimeDelta cpu_usage_estimate, - uint64_t private_footprint_kb_estimate) = 0; -}; - -} // namespace resource_coordinator - -#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_SITE_CHARACTERISTICS_DATA_WRITER_H_
diff --git a/chrome/browser/resource_coordinator/tab_helper.cc b/chrome/browser/resource_coordinator/tab_helper.cc index bf8ff8db..ccf38154 100644 --- a/chrome/browser/resource_coordinator/tab_helper.cc +++ b/chrome/browser/resource_coordinator/tab_helper.cc
@@ -26,7 +26,6 @@ #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h" #if !defined(OS_ANDROID) -#include "chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h" #include "chrome/browser/resource_coordinator/tab_manager.h" #endif @@ -42,12 +41,6 @@ rc_parts->tab_memory_metrics_reporter()->StartReporting( TabLoadTracker::Get()); } - -#if !defined(OS_ANDROID) - local_site_characteristics_wc_observer_ = - std::make_unique<LocalSiteCharacteristicsWebContentsObserver>( - web_contents); -#endif } ResourceCoordinatorTabHelper::~ResourceCoordinatorTabHelper() = default;
diff --git a/chrome/browser/resource_coordinator/tab_helper.h b/chrome/browser/resource_coordinator/tab_helper.h index 744e552..d7619e4b 100644 --- a/chrome/browser/resource_coordinator/tab_helper.h +++ b/chrome/browser/resource_coordinator/tab_helper.h
@@ -21,8 +21,6 @@ namespace resource_coordinator { -class LocalSiteCharacteristicsWebContentsObserver; - class ResourceCoordinatorTabHelper : public content::WebContentsObserver, public content::WebContentsUserData<ResourceCoordinatorTabHelper> { @@ -45,13 +43,6 @@ ukm::SourceId ukm_source_id() const { return ukm_source_id_; } void SetUkmSourceIdForTest(ukm::SourceId id) { ukm_source_id_ = id; } -#if !defined(OS_ANDROID) - LocalSiteCharacteristicsWebContentsObserver* - local_site_characteristics_wc_observer() { - return local_site_characteristics_wc_observer_.get(); - } -#endif - private: explicit ResourceCoordinatorTabHelper(content::WebContents* web_contents); @@ -60,12 +51,6 @@ friend class content::WebContentsUserData<ResourceCoordinatorTabHelper>; -#if !defined(OS_ANDROID) - std::unique_ptr<LocalSiteCharacteristicsWebContentsObserver> - local_site_characteristics_wc_observer_; -#endif - - WEB_CONTENTS_USER_DATA_KEY_DECL(); DISALLOW_COPY_AND_ASSIGN(ResourceCoordinatorTabHelper);
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc index 927e4af..94e36de 100644 --- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc +++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -20,7 +20,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/resource_coordinator/intervention_policy_database.h" #include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h" #include "chrome/browser/resource_coordinator/tab_activity_watcher.h" #include "chrome/browser/resource_coordinator/tab_helper.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_observer.h"
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 aeb10384..628a7643 100644 --- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc
@@ -17,8 +17,6 @@ #include "chrome/browser/resource_coordinator/lifecycle_unit.h" #include "chrome/browser/resource_coordinator/lifecycle_unit_observer.h" #include "chrome/browser/resource_coordinator/lifecycle_unit_source_observer.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h" #include "chrome/browser/resource_coordinator/tab_helper.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_observer.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_unit.h" @@ -30,6 +28,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/test_tab_strip_model_delegate.h" #include "chrome/common/pref_names.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" #include "components/performance_manager/public/performance_manager.h" #include "components/performance_manager/test_support/graph_impl.h" @@ -93,17 +92,16 @@ return lifecycle_unit->GetLastFocusedTime() == base::TimeTicks::Max(); } -class TabLifecycleUnitSourceTest - : public testing::ChromeTestHarnessWithLocalDB { +class TabLifecycleUnitSourceTest : public ChromeRenderViewHostTestHarness { protected: TabLifecycleUnitSourceTest() - : testing::ChromeTestHarnessWithLocalDB( + : ChromeRenderViewHostTestHarness( base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME) { task_runner_ = task_environment()->GetMainThreadTaskRunner(); } void SetUp() override { - ChromeTestHarnessWithLocalDB::SetUp(); + ChromeRenderViewHostTestHarness::SetUp(); // Force TabManager/TabLifecycleUnitSource creation. g_browser_process->GetTabManager(); @@ -122,7 +120,7 @@ tab_strip_model_.reset(); task_environment()->RunUntilIdle(); - ChromeTestHarnessWithLocalDB::TearDown(); + ChromeRenderViewHostTestHarness::TearDown(); } // If |focus_tab_strip| is true, focuses the tab strip. Then, appends 2 tabs @@ -158,9 +156,6 @@ base::RepeatingClosure run_loop_cb = base::BindRepeating( &base::test::SingleThreadTaskEnvironment::RunUntilIdle, base::Unretained(task_environment())); - testing::WaitForLocalDBEntryToBeInitialized(raw_first_web_contents, - run_loop_cb); - testing::ExpireLocalDBObservationWindows(raw_first_web_contents); // Add another foreground tab to the focused tab strip. task_environment()->FastForwardBy(kShortDelay); @@ -186,9 +181,6 @@ tab_strip_model_->AppendWebContents(std::move(second_web_contents), true); ::testing::Mock::VerifyAndClear(&source_observer_); EXPECT_TRUE(source_->GetTabLifecycleUnitExternal(raw_second_web_contents)); - testing::WaitForLocalDBEntryToBeInitialized(raw_second_web_contents, - run_loop_cb); - testing::ExpireLocalDBObservationWindows(raw_second_web_contents); // TabStripModel doesn't update the visibility of its WebContents by itself. raw_first_web_contents->WasHidden();
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc index 19708380..c0cc5805 100644 --- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
@@ -21,8 +21,6 @@ #include "chrome/browser/notifications/notification_permission_context.h" #include "chrome/browser/resource_coordinator/intervention_policy_database.h" #include "chrome/browser/resource_coordinator/lifecycle_unit_observer.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h" #include "chrome/browser/resource_coordinator/tab_helper.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_observer.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h" @@ -40,6 +38,7 @@ #include "chrome/browser/usb/usb_chooser_context.h" #include "chrome/browser/usb/usb_chooser_context_factory.h" #include "chrome/browser/usb/usb_tab_helper.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" #include "content/public/browser/web_contents.h" #include "content/public/common/referrer.h" @@ -93,7 +92,7 @@ DISALLOW_COPY_AND_ASSIGN(MockLifecycleUnitObserver); }; -class TabLifecycleUnitTest : public testing::ChromeTestHarnessWithLocalDB { +class TabLifecycleUnitTest : public ChromeRenderViewHostTestHarness { protected: using TabLifecycleUnit = TabLifecycleUnitSource::TabLifecycleUnit; @@ -108,7 +107,7 @@ } void SetUp() override { - ChromeTestHarnessWithLocalDB::SetUp(); + ChromeRenderViewHostTestHarness::SetUp(); metrics::DesktopSessionDurationTracker::Initialize(); usage_clock_ = std::make_unique<UsageClock>(); @@ -139,12 +138,6 @@ tab_strip_model_->AppendWebContents(std::move(second_web_contents), /*foreground=*/true); raw_second_web_contents->WasHidden(); - - testing::WaitForLocalDBEntryToBeInitialized( - web_contents_, - base::BindRepeating([]() { base::RunLoop().RunUntilIdle(); })); - - testing::ExpireLocalDBObservationWindows(web_contents_); } void TearDown() override { @@ -153,13 +146,9 @@ tab_strip_model_.reset(); usage_clock_.reset(); metrics::DesktopSessionDurationTracker::CleanupForTesting(); - ChromeTestHarnessWithLocalDB::TearDown(); + ChromeRenderViewHostTestHarness::TearDown(); } - void TestCannotDiscardBasedOnHeuristicUsage( - DecisionFailureReason failure_reason, - void (SiteCharacteristicsDataWriter::*notify_feature_usage_method)()); - // Create a new test WebContents and append it to the tab strip to allow // testing discarding operations on it. The returned WebContents is in the // hidden state.
diff --git a/chrome/browser/resource_coordinator/tab_load_tracker.cc b/chrome/browser/resource_coordinator/tab_load_tracker.cc index f61f803c..d3baf1a 100644 --- a/chrome/browser/resource_coordinator/tab_load_tracker.cc +++ b/chrome/browser/resource_coordinator/tab_load_tracker.cc
@@ -9,6 +9,7 @@ #include "base/check_op.h" #include "base/stl_util.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/resource_coordinator/resource_coordinator_parts.h" #include "content/public/browser/navigation_controller.h" @@ -272,7 +273,8 @@ // tabstrip UI or use a platform-independent tabstrip observer interface to // learn about |web_contents| associated with the tabstrip, rather than // checking for specific cases where |web_contents| is not a ui tab. - if (prerender::PrerenderContents::FromWebContents(web_contents) != nullptr) + if (prerender::ChromePrerenderContentsDelegate::FromWebContents( + web_contents) != nullptr) return false; if (web_contents->GetOuterWebContents()) return false;
diff --git a/chrome/browser/resource_coordinator/tab_manager.cc b/chrome/browser/resource_coordinator/tab_manager.cc index c43f26d..a85f262 100644 --- a/chrome/browser/resource_coordinator/tab_manager.cc +++ b/chrome/browser/resource_coordinator/tab_manager.cc
@@ -35,7 +35,6 @@ #include "chrome/browser/performance_manager/policies/policy_features.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/resource_coordinator/background_tab_navigation_throttle.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h" #include "chrome/browser/resource_coordinator/resource_coordinator_parts.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h" #include "chrome/browser/resource_coordinator/tab_manager.h"
diff --git a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc index 9ecceefa2..d63cf659d 100644 --- a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
@@ -19,7 +19,6 @@ #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" #include "chrome/browser/performance_manager/policies/policy_features.h" #include "chrome/browser/resource_coordinator/lifecycle_unit_observer.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_observer.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_unit.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h" @@ -167,8 +166,6 @@ ui::PAGE_TRANSITION_TYPED, false); content::WebContents* web_contents = browser()->OpenURL(open1); load1.Wait(); - if (URLShouldBeStoredInLocalDatabase(first_url)) - testing::ExpireLocalDBObservationWindows(web_contents); content::WindowedNotificationObserver load2( content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, @@ -178,10 +175,6 @@ ui::PAGE_TRANSITION_TYPED, false); web_contents = browser()->OpenURL(open2); load2.Wait(); - // Expire all the observation windows to prevent the discarding intervention - // to fail because of a lack of observations. - if (URLShouldBeStoredInLocalDatabase(second_url)) - testing::ExpireLocalDBObservationWindows(web_contents); ASSERT_EQ(2, tsm()->count()); }
diff --git a/chrome/browser/resource_coordinator/tab_manager_stats_collector_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_stats_collector_unittest.cc index 87d60fa..38413f3 100644 --- a/chrome/browser/resource_coordinator/tab_manager_stats_collector_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_stats_collector_unittest.cc
@@ -18,7 +18,6 @@ #include "base/time/tick_clock.h" #include "base/time/time.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" #include "chrome/browser/resource_coordinator/tab_helper.h" #include "chrome/browser/resource_coordinator/tab_load_tracker.h" #include "chrome/browser/resource_coordinator/tab_manager_web_contents_data.h" @@ -47,8 +46,7 @@ constexpr TabLoadTracker::LoadingState LOADING = LoadingState::LOADING; constexpr TabLoadTracker::LoadingState LOADED = LoadingState::LOADED; -class TabManagerStatsCollectorTest - : public testing::ChromeTestHarnessWithLocalDB { +class TabManagerStatsCollectorTest : public ChromeRenderViewHostTestHarness { protected: TabManagerStatsCollectorTest() : scoped_context_( @@ -89,12 +87,8 @@ return tab_manager()->GetWebContentsData(contents); } - void RestoreTab(WebContents* contents) { - tab_manager()->OnWillRestoreTab(contents); - } - void SetUp() override { - ChromeTestHarnessWithLocalDB::SetUp(); + ChromeRenderViewHostTestHarness::SetUp(); // Call the tab manager so that it is created right away. tab_manager(); @@ -103,33 +97,7 @@ void TearDown() override { task_runner_->RunUntilIdle(); scoped_context_.reset(); - ChromeTestHarnessWithLocalDB::TearDown(); - } - - std::unique_ptr<WebContents> CreateWebContentsForUKM(ukm::SourceId id) { - std::unique_ptr<WebContents> contents(CreateTestWebContents()); - ResourceCoordinatorTabHelper::CreateForWebContents(contents.get()); - ResourceCoordinatorTabHelper::FromWebContents(contents.get()) - ->SetUkmSourceIdForTest(id); - return contents; - } - - std::unique_ptr<WebContents> CreateDiscardableWebContents(ukm::SourceId id) { - std::unique_ptr<WebContents> web_contents = CreateWebContentsForUKM(id); - - // Commit an URL and mark the tab as "loaded" to allow discarding. - content::WebContentsTester::For(web_contents.get()) - ->NavigateAndCommit(GURL("https://www.example.com")); - TabLoadTracker::Get()->TransitionStateForTesting(web_contents.get(), - LoadingState::LOADED); - - base::RepeatingClosure run_loop_cb = base::BindRepeating( - &base::TestMockTimeTaskRunner::RunUntilIdle, task_runner_); - - testing::WaitForLocalDBEntryToBeInitialized(web_contents.get(), - run_loop_cb); - testing::ExpireLocalDBObservationWindows(web_contents.get()); - return web_contents; + ChromeRenderViewHostTestHarness::TearDown(); } scoped_refptr<base::TestMockTimeTaskRunner> task_runner_ =
diff --git a/chrome/browser/resource_coordinator/tab_manager_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_unittest.cc index 9ea1982..59ef477 100644 --- a/chrome/browser/resource_coordinator/tab_manager_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_unittest.cc
@@ -29,8 +29,6 @@ #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/resource_coordinator/background_tab_navigation_throttle.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h" #include "chrome/browser/resource_coordinator/tab_helper.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_unit.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h" @@ -46,6 +44,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/test_tab_strip_model_delegate.h" #include "chrome/common/url_constants.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/test_browser_window.h" #include "chrome/test/base/testing_profile.h" #include "components/variations/variations_associated_data.h" @@ -110,7 +109,7 @@ } // namespace -class TabManagerTest : public testing::ChromeTestHarnessWithLocalDB { +class TabManagerTest : public ChromeRenderViewHostTestHarness { public: TabManagerTest() : scoped_context_( @@ -133,14 +132,11 @@ base::RepeatingClosure run_loop_cb = base::BindRepeating( &base::TestMockTimeTaskRunner::RunUntilIdle, task_runner_); - testing::WaitForLocalDBEntryToBeInitialized(web_contents.get(), - run_loop_cb); - testing::ExpireLocalDBObservationWindows(web_contents.get()); return web_contents; } void SetUp() override { - ChromeTestHarnessWithLocalDB::SetUp(); + ChromeRenderViewHostTestHarness::SetUp(); tab_manager_ = g_browser_process->GetTabManager(); } @@ -164,7 +160,7 @@ nav_handle3_.reset(); // WebContents must be deleted before - // ChromeTestHarnessWithLocalDB::TearDown() deletes the + // ChromeRenderViewHostTestHarness::TearDown() deletes the // RenderProcessHost. contents1_.reset(); contents2_.reset(); @@ -176,7 +172,7 @@ task_runner_->RunUntilIdle(); scoped_context_.reset(); - ChromeTestHarnessWithLocalDB::TearDown(); + ChromeRenderViewHostTestHarness::TearDown(); } void PrepareTabs(const char* url1 = kTestUrl,
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd index 3be4790..b4a38d65 100644 --- a/chrome/browser/resources/component_extension_resources.grd +++ b/chrome/browser/resources/component_extension_resources.grd
@@ -118,6 +118,7 @@ <include name="IDR_PDF_GESTURE_DETECTOR_JS" file="pdf/gesture_detector.js" type="BINDATA" /> <include name="IDR_PDF_BROWSER_API_JS" file="pdf/browser_api.js" type="BINDATA" /> <include name="IDR_PDF_METRICS_JS" file="pdf/metrics.js" type="BINDATA" /> + <include name="IDR_PDF_LOCAL_STORAGE_PROXY_JS" file="pdf/local_storage_proxy.js" type="BINDATA" /> <include name="IDR_PDF_ELEMENTS_SHARED_CSS_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/shared-css.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PDF_SHARED_VARS_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/shared-vars.js" use_base_dir="false" type="BINDATA" /> @@ -136,6 +137,7 @@ </if> <include name="IDR_PDF_VIEWER_PAGE_SELECTOR_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-page-selector.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PDF_VIEWER_PASSWORD_SCREEN_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-password-screen.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_PDF_VIEWER_PDF_SIDENAV_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-pdf-sidenav.js" use_base_dir="false" type="BINDATA"/> <include name="IDR_PDF_VIEWER_PDF_TOOLBAR_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js" use_base_dir="false" type="BINDATA" preprocess="true"/> <include name="IDR_PDF_VIEWER_PDF_TOOLBAR_NEW_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js" use_base_dir="false" type="BINDATA" preprocess="true"/> <include name="IDR_PDF_VIEWER_TOOLBAR_DROPDOWN_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.js" use_base_dir="false" type="BINDATA" />
diff --git a/chrome/browser/resources/discards/database_tab.js b/chrome/browser/resources/discards/database_tab.js index c93db1e4..893b0710 100644 --- a/chrome/browser/resources/discards/database_tab.js +++ b/chrome/browser/resources/discards/database_tab.js
@@ -15,10 +15,8 @@ /** * Compares two db rows by their origin. - * @param {discards.mojom.SiteCharacteristicsDatabaseEntry} a The first value - * being compared. - * @param {discards.mojom.SiteCharacteristicsDatabaseEntry} b The second value - * being compared. + * @param {discards.mojom.SiteDataEntry} a The first value being compared. + * @param {discards.mojom.SiteDataEntry} b The second value being compared. * @return {number} A negative number if a < b, 0 if a === b, and a positive * number if a > b. */ @@ -28,10 +26,8 @@ /** * Compares two db rows by their dirty bit. - * @param {discards.mojom.SiteCharacteristicsDatabaseEntry} a The first value - * being compared. - * @param {discards.mojom.SiteCharacteristicsDatabaseEntry} b The second value - * being compared. + * @param {discards.mojom.SiteDataEntry} a The first value being compared. + * @param {discards.mojom.SiteDataEntry} b The second value being compared. * @return {number} A negative number if a < b, 0 if a === b, and a positive * number if a > b. */ @@ -41,10 +37,8 @@ /** * Compares two db rows by their last load time. - * @param {discards.mojom.SiteCharacteristicsDatabaseEntry} a The first value - * being compared. - * @param {discards.mojom.SiteCharacteristicsDatabaseEntry} b The second value - * being compared. + * @param {discards.mojom.SiteDataEntry} a The first value being compared. + * @param {discards.mojom.SiteDataEntry} b The second value being compared. * @return {number} A negative number if a < b, 0 if a === b, and a positive * number if a > b. */ @@ -54,10 +48,8 @@ /** * Compares two db rows by their CPU usage. - * @param {discards.mojom.SiteCharacteristicsDatabaseEntry} a The first value - * being compared. - * @param {discards.mojom.SiteCharacteristicsDatabaseEntry} b The second value - * being compared. + * @param {discards.mojom.SiteDataEntry} a The first value being compared. + * @param {discards.mojom.SiteDataEntry} b The second value being compared. * @return {number} A negative number if a < b, 0 if a === b, and a positive * number if a > b. */ @@ -71,10 +63,8 @@ /** * Compares two db rows by their memory usage. - * @param {discards.mojom.SiteCharacteristicsDatabaseEntry} a The first value - * being compared. - * @param {discards.mojom.SiteCharacteristicsDatabaseEntry} b The second value - * being compared. + * @param {discards.mojom.SiteDataEntry} a The first value being compared. + * @param {discards.mojom.SiteDataEntry} b The second value being compared. * @return {number} A negative number if a < b, 0 if a === b, and a positive * number if a > b. */ @@ -88,10 +78,8 @@ /** * Compares two db rows by their load duration. - * @param {discards.mojom.SiteCharacteristicsDatabaseEntry} a The first value - * being compared. - * @param {discards.mojom.SiteCharacteristicsDatabaseEntry} b The second value - * being compared. + * @param {discards.mojom.SiteDataEntry} a The first value being compared. + * @param {discards.mojom.SiteDataEntry} b The second value being compared. * @return {number} A negative number if a < b, 0 if a === b, and a positive * number if a > b. */ @@ -107,8 +95,8 @@ /** * @param {string} sortKey The sort key to get a function for. - * @return {function(discards.mojom.SiteCharacteristicsDatabaseEntry, - discards.mojom.SiteCharacteristicsDatabaseEntry): number} + * @return {function(discards.mojom.SiteDataEntry, + discards.mojom.SiteDataEntry): number} * A comparison function that compares two tab infos, returns * negative number if a < b, 0 if a === b, and a positive * number if a > b. @@ -196,7 +184,7 @@ properties: { /** * List of database rows. - * @private {?Array<!discards.mojom.SiteCharacteristicsDatabaseEntry>} + * @private {?Array<!discards.mojom.SiteDataEntry>} */ rows_: { type: Array, @@ -204,7 +192,7 @@ /** * The database size response. - * @private {!discards.mojom.SiteCharacteristicsDatabaseSize} + * @private {!discards.mojom.SiteDataDatabaseSize} */ size_: { type: Object, @@ -269,10 +257,9 @@ * @private */ updateDbRows_() { - this.siteDataProvider_ - .getSiteCharacteristicsDatabase(Object.keys(this.requestedOrigins_)) + this.siteDataProvider_.getSiteDataArray(Object.keys(this.requestedOrigins_)) .then(response => { - // Bail if the SiteCharacteristicsDatabase is turned off. + // Bail if the SiteData database is turned off. if (!response.result) { return; } @@ -325,14 +312,13 @@ * @private */ updateDbSizes_() { - this.siteDataProvider_.getSiteCharacteristicsDatabaseSize().then( - response => { - // Bail if the SiteCharacteristicsDatabase is turned off. - if (!response.dbSize) { - return; - } - this.size_ = response.dbSize; - }); + this.siteDataProvider_.getSiteDataDatabaseSize().then(response => { + // Bail if the SiteData database is turned off. + if (!response.dbSize) { + return; + } + this.size_ = response.dbSize; + }); }, /** @@ -402,8 +388,7 @@ }, /** - * @param {?discards.mojom.SiteCharacteristicsFeature} feature The feature - * in question. + * @param {?discards.mojom.SiteDataFeature} feature The feature in question. * @return {string} A human-readable string representing the feature. * @private */
diff --git a/chrome/browser/resources/nearby_share/BUILD.gn b/chrome/browser/resources/nearby_share/BUILD.gn index eb7fb47..5a5d1fd9 100644 --- a/chrome/browser/resources/nearby_share/BUILD.gn +++ b/chrome/browser/resources/nearby_share/BUILD.gn
@@ -42,6 +42,7 @@ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_elements/cr_button:cr_button.m", "//ui/webui/resources/cr_elements/cr_checkbox:cr_checkbox.m", + "//ui/webui/resources/js:i18n_behavior.m", ] }
diff --git a/chrome/browser/resources/nearby_share/app.js b/chrome/browser/resources/nearby_share/app.js index 30c3354..c295756 100644 --- a/chrome/browser/resources/nearby_share/app.js +++ b/chrome/browser/resources/nearby_share/app.js
@@ -12,7 +12,6 @@ import './shared/nearby_onboarding_page.m.js'; import './nearby_confirmation_page.js'; import './nearby_discovery_page.js'; -import './strings.m.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/nearby_share/discovery_manager.js b/chrome/browser/resources/nearby_share/discovery_manager.js index cf357f8..ab68433 100644 --- a/chrome/browser/resources/nearby_share/discovery_manager.js +++ b/chrome/browser/resources/nearby_share/discovery_manager.js
@@ -9,6 +9,7 @@ import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; import 'chrome://resources/mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js'; +import './nearby_share_target_types.mojom-lite.js'; import './nearby_share.mojom-lite.js'; /** @type {?nearbyShare.mojom.DiscoveryManagerInterface} */
diff --git a/chrome/browser/resources/nearby_share/nearby_confirmation_page.html b/chrome/browser/resources/nearby_share/nearby_confirmation_page.html index e2e2bd0..6ff74f3 100644 --- a/chrome/browser/resources/nearby_share/nearby_confirmation_page.html +++ b/chrome/browser/resources/nearby_share/nearby_confirmation_page.html
@@ -78,7 +78,7 @@ <div id="process-row"> <nearby-preview title="Doggo.jpg"></nearby-preview> <div id="confirmation-token"> - Secure connection ID: [[confirmationToken]] + [[i18n('secureConnectionId', confirmationToken)]] </div> <nearby-progress share-target="[[shareTarget]]"></nearby-progress> </div>
diff --git a/chrome/browser/resources/nearby_share/nearby_confirmation_page.js b/chrome/browser/resources/nearby_share/nearby_confirmation_page.js index 2aa4feaa..de2d74c7 100644 --- a/chrome/browser/resources/nearby_share/nearby_confirmation_page.js +++ b/chrome/browser/resources/nearby_share/nearby_confirmation_page.js
@@ -14,13 +14,18 @@ import 'chrome://resources/mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js'; import './nearby_preview.js'; import './nearby_progress.js'; +import './nearby_share_target_types.mojom-lite.js'; import './nearby_share.mojom-lite.js'; +import './strings.m.js'; +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; Polymer({ is: 'nearby-confirmation-page', + behaviors: [I18nBehavior], + _template: html`{__html_template__}`, properties: {
diff --git a/chrome/browser/resources/nearby_share/nearby_device.js b/chrome/browser/resources/nearby_share/nearby_device.js index 3a0110e..82706d9 100644 --- a/chrome/browser/resources/nearby_share/nearby_device.js +++ b/chrome/browser/resources/nearby_share/nearby_device.js
@@ -9,6 +9,7 @@ import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; import 'chrome://resources/mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js'; import './nearby_device_icon.js'; +import './nearby_share_target_types.mojom-lite.js'; import './nearby_share.mojom-lite.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/nearby_share/nearby_device_icon.js b/chrome/browser/resources/nearby_share/nearby_device_icon.js index b03adff..13486460 100644 --- a/chrome/browser/resources/nearby_share/nearby_device_icon.js +++ b/chrome/browser/resources/nearby_share/nearby_device_icon.js
@@ -12,6 +12,7 @@ import 'chrome://resources/mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js'; import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import './icons.js'; +import './nearby_share_target_types.mojom-lite.js'; import './nearby_share.mojom-lite.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/nearby_share/nearby_discovery_page.js b/chrome/browser/resources/nearby_share/nearby_discovery_page.js index 0b09848..70bfbd5 100644 --- a/chrome/browser/resources/nearby_share/nearby_discovery_page.js +++ b/chrome/browser/resources/nearby_share/nearby_discovery_page.js
@@ -12,6 +12,7 @@ import 'chrome://resources/mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js'; import './nearby_device.js'; import './nearby_preview.js'; +import './nearby_share_target_types.mojom-lite.js'; import './nearby_share.mojom-lite.js'; import {assert} from 'chrome://resources/js/assert.m.js';
diff --git a/chrome/browser/resources/nearby_share/nearby_progress.js b/chrome/browser/resources/nearby_share/nearby_progress.js index b0a5021b..ad2bf23 100644 --- a/chrome/browser/resources/nearby_share/nearby_progress.js +++ b/chrome/browser/resources/nearby_share/nearby_progress.js
@@ -12,6 +12,7 @@ import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; import 'chrome://resources/mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js'; import './nearby_device_icon.js'; +import './nearby_share_target_types.mojom-lite.js'; import './nearby_share.mojom-lite.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/nearby_share/nearby_share_dialog_resources.grd b/chrome/browser/resources/nearby_share/nearby_share_dialog_resources.grd index dcd22cb..cd4ae84 100644 --- a/chrome/browser/resources/nearby_share/nearby_share_dialog_resources.grd +++ b/chrome/browser/resources/nearby_share/nearby_share_dialog_resources.grd
@@ -19,6 +19,9 @@ <include name="IDR_NEARBY_SHARE_MOJO_JS" file="${root_gen_dir}/chrome/browser/ui/webui/nearby_share/nearby_share.mojom-lite.js" use_base_dir="false" type="BINDATA"/> + <include name="IDR_NEARBY_SHARE_TARGET_TYPES_MOJO_JS" + file="${root_gen_dir}/chrome/browser/ui/webui/nearby_share/nearby_share_target_types.mojom-lite.js" + use_base_dir="false" type="BINDATA"/> <include name="IDR_NEARBY_SHARE_SETTINGS_MOJOM_LITE_JS" file="${root_gen_dir}/chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom-lite.js" use_base_dir="false" type="BINDATA"/>
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn index aad74b7..1cbb07a1 100644 --- a/chrome/browser/resources/pdf/BUILD.gn +++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -113,6 +113,10 @@ ] } +js_library("local_storage_proxy") { + deps = [ "//ui/webui/resources/js:cr.m" ] +} + js_library("controller") { deps = [ ":viewport", @@ -150,6 +154,7 @@ ":constants", ":controller", ":ink_controller", + ":local_storage_proxy", ":metrics", ":navigator", ":pdf_scripting_api", @@ -214,6 +219,7 @@ ":controller", ":gesture_detector", ":ink_controller", + ":local_storage_proxy", ":main", ":metrics", ":navigator",
diff --git a/chrome/browser/resources/pdf/elements/BUILD.gn b/chrome/browser/resources/pdf/elements/BUILD.gn index d4dc2ec..8d05784 100644 --- a/chrome/browser/resources/pdf/elements/BUILD.gn +++ b/chrome/browser/resources/pdf/elements/BUILD.gn
@@ -14,6 +14,7 @@ ":viewer-page-indicator", ":viewer-page-selector", ":viewer-password-screen", + ":viewer-pdf-sidenav", ":viewer-pdf-toolbar", ":viewer-pdf-toolbar-new", ":viewer-toolbar-dropdown", @@ -94,6 +95,13 @@ ] } +js_library("viewer-pdf-sidenav") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m", + ] +} + js_library("viewer-pdf-toolbar") { deps = [ ":viewer-annotations-bar", @@ -148,6 +156,7 @@ "viewer-page-indicator.js", "viewer-page-selector.js", "viewer-password-screen.js", + "viewer-pdf-sidenav.js", "viewer-pdf-toolbar.js", "viewer-pdf-toolbar-new.js", "viewer-toolbar-dropdown.js",
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-sidenav.html b/chrome/browser/resources/pdf/elements/viewer-pdf-sidenav.html new file mode 100644 index 0000000..747024b --- /dev/null +++ b/chrome/browser/resources/pdf/elements/viewer-pdf-sidenav.html
@@ -0,0 +1,58 @@ +<style include="pdf-shared"> + :host { + background-color: var(--viewer-pdf-toolbar-background-color); + display: flex; + min-width: 300px; + } + + #icons { + display: flex; + flex-direction: column; + min-width: 48px; + } + + /* These are dummy styles currently - replace with real content. */ + #content { + color: white; + font-weight: 500; + line-height: 36px; + text-align: center; + width: 100%; + } + + .selected cr-icon-button { + --cr-icon-button-fill-color: var(--google-blue-refresh-700); + } + + .button-wrapper { + --highlight-border-width: 6px; + align-items: center; + border-inline-start: var(--highlight-border-width) solid transparent; + display: flex; + height: var(--cr-icon-button-size); + justify-content: center; + margin: 6px 0; + width: calc(100% - var(--highlight-border-width)); + } + + .button-wrapper.selected { + border-color: var(--google-blue-refresh-700); + } +</style> +<div id="icons"> + <!-- TODO(rbpotter): Localize titles once the strings are finalized. --> + <div class$="button-wrapper [[thumbnailButtonClass_(thumbnailView_)]]"> + <cr-icon-button iron-icon="pdf:thumbnails" role="tab" + title="Thumbnail view" on-click="onThumbnailClick_"> + </cr-icon-button> + </div> + <div class$="button-wrapper [[outlineButtonClass_(thumbnailView_)]]"> + <cr-icon-button iron-icon="pdf:doc-outline" role="tab" + title="Outline view" on-click="onOutlineClick_"> + </cr-icon-button> + </div> +</div> +<div id="content"> + <div id="thumbnails" hidden="[[!thumbnailView_]]">Thumbnails</div> + <div id="outline" hidden="[[thumbnailView_]]">Outline</div> +</div>
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-sidenav.js b/chrome/browser/resources/pdf/elements/viewer-pdf-sidenav.js new file mode 100644 index 0000000..5fabf858 --- /dev/null +++ b/chrome/browser/resources/pdf/elements/viewer-pdf-sidenav.js
@@ -0,0 +1,58 @@ +// Copyright 2020 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 './shared-vars.js'; +import '../pdf_viewer_shared_style.js'; +import './icons.js'; +import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js'; + +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +export class ViewerPdfSidenavElement extends PolymerElement { + static get is() { + return 'viewer-pdf-sidenav'; + } + + static get template() { + return html`{__html_template__}`; + } + + static get properties() { + return { + /** @private */ + thumbnailView_: { + type: Boolean, + value: true, + }, + }; + } + + /** @private */ + onThumbnailClick_() { + this.thumbnailView_ = true; + } + + /** @private */ + onOutlineClick_() { + this.thumbnailView_ = false; + } + + /** + * @return {string} + * @private + */ + outlineButtonClass_() { + return this.thumbnailView_ ? '' : 'selected'; + } + + /** + * @return {string} + * @private + */ + thumbnailButtonClass_() { + return this.thumbnailView_ ? 'selected' : ''; + } +} + +customElements.define(ViewerPdfSidenavElement.is, ViewerPdfSidenavElement);
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html index 182b20d7..c5efbd60 100644 --- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html +++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html
@@ -1,6 +1,5 @@ <style include="pdf-shared"> :host { - --pdf-toolbar-text-color: rgb(241, 241, 241); box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.09), 0 4px 8px rgba(0, 0, 0, 0.06),
diff --git a/chrome/browser/resources/pdf/local_storage_proxy.js b/chrome/browser/resources/pdf/local_storage_proxy.js new file mode 100644 index 0000000..92b36c31 --- /dev/null +++ b/chrome/browser/resources/pdf/local_storage_proxy.js
@@ -0,0 +1,35 @@ +// Copyright 2020 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 {addSingletonGetter} from 'chrome://resources/js/cr.m.js'; + +/** @interface */ +class LocalStorageProxy { + /** + * @param {string} key + * @return {?string} + */ + getItem(key) {} + + /** + * @param {string} key + * @param {string} value + */ + setItem(key, value) {} +} + +/** @implements {LocalStorageProxy} */ +export class LocalStorageProxyImpl { + /** @override */ + getItem(key) { + return window.localStorage.getItem(key); + } + + /** @override */ + setItem(key, value) { + window.localStorage.setItem(key, value); + } +} + +addSingletonGetter(LocalStorageProxyImpl);
diff --git a/chrome/browser/resources/pdf/pdf_viewer.html b/chrome/browser/resources/pdf/pdf_viewer.html index cb3c5891..799e1d44 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.html +++ b/chrome/browser/resources/pdf/pdf_viewer.html
@@ -1,4 +1,9 @@ -<style include="pdf-viewer-shared-style"> +<style include="pdf-viewer-shared-style cr-hidden-style"> + viewer-pdf-sidenav, + viewer-pdf-toolbar-new { + --pdf-toolbar-text-color: rgb(241, 241, 241); + } + #content-focus-rectangle { border: 2px solid white; border-radius: 2px; @@ -48,11 +53,6 @@ overflow: hidden; } - #sidenav { - background-color: var(--viewer-pdf-toolbar-background-color); - min-width: 260px; - } - :host-context([pdf-viewer-update-enabled]) #plugin { position: initial; } @@ -134,7 +134,8 @@ <template is="dom-if" if="[[pdfViewerUpdateEnabled_]]"> <div id="container"> - <div id="sidenav" hidden="[[sidenavCollapsed_]]"></div> + <viewer-pdf-sidenav id="sidenav" hidden="[[sidenavCollapsed_]]"> + </viewer-pdf-sidenav> <div id="main" on-scroll="onScroll_"> <div id="sizer"></div> <div id="content"></div> @@ -167,4 +168,4 @@ <div id="content"></div> </template> -<div id="content-focus-rectangle" hidden$="[[!documentHasFocus_]]"></div> \ No newline at end of file +<div id="content-focus-rectangle" hidden$="[[!documentHasFocus_]]"></div>
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js index 2f2be36b..60d607e8 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.js +++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -4,6 +4,7 @@ import './elements/viewer-error-screen.js'; import './elements/viewer-password-screen.js'; +import './elements/viewer-pdf-sidenav.js'; import './elements/viewer-pdf-toolbar.js'; import './elements/viewer-zoom-toolbar.js'; import './elements/shared-vars.js'; @@ -12,6 +13,7 @@ import './elements/viewer-form-warning.js'; // </if> import './pdf_viewer_shared_style.js'; +import 'chrome://resources/cr_elements/hidden_style_css.m.js'; import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; @@ -25,6 +27,7 @@ // <if expr="chromeos"> import {InkController} from './ink_controller.js'; //</if> +import {LocalStorageProxyImpl} from './local_storage_proxy.js'; import {PDFMetrics} from './metrics.js'; import {NavigatorDelegate, PdfNavigator} from './navigator.js'; import {OpenPdfParamsParser} from './open_pdf_params_parser.js'; @@ -83,6 +86,9 @@ } } +/** @type {string} */ +const LOCAL_STORAGE_SIDENAV_COLLAPSED_KEY = 'sidenavCollapsed'; + export class PDFViewerElement extends PDFViewerBaseElement { static get is() { return 'pdf-viewer'; @@ -132,14 +138,7 @@ isFormFieldFocused_: Boolean, - /** @private */ - pdfViewerUpdateEnabled_: { - type: Boolean, - value: function() { - return document.documentElement.hasAttribute( - 'pdf-viewer-update-enabled'); - }, - }, + pdfViewerUpdateEnabled_: Boolean, docLength_: Number, // <if expr="chromeos"> @@ -217,9 +216,6 @@ this.hadPassword_ = false; /** @private {boolean} */ - this.sidenavCollapsed_ = false; - - /** @private {boolean} */ this.toolbarEnabled_ = false; /** @private {?ToolbarManager} */ @@ -250,7 +246,19 @@ this.loadProgress_; /** @private {boolean} */ - this.pdfViewerUpdateEnabled_; + this.pdfViewerUpdateEnabled_ = + document.documentElement.hasAttribute('pdf-viewer-update-enabled'); + + /** @private {boolean} */ + this.sidenavCollapsed_ = false; + + if (this.pdfViewerUpdateEnabled_) { + // TODO(dpapad): Add tests after crbug.com/1111459 is fixed. + this.sidenavCollapsed_ = Boolean(Number.parseInt( + LocalStorageProxyImpl.getInstance().getItem( + LOCAL_STORAGE_SIDENAV_COLLAPSED_KEY), + 10)); + } } /** @override */ @@ -880,7 +888,10 @@ /** @private */ onSidenavToggleClick_() { + assert(this.pdfViewerUpdateEnabled_); this.sidenavCollapsed_ = !this.sidenavCollapsed_; + LocalStorageProxyImpl.getInstance().setItem( + LOCAL_STORAGE_SIDENAV_COLLAPSED_KEY, this.sidenavCollapsed_ ? 1 : 0); } /**
diff --git a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html index 5f2af5132..5e7041bb 100644 --- a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html +++ b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html
@@ -31,7 +31,7 @@ } </style> <cr-dialog id="dialog" close-text="$i18n{close}"> - <div slot="title">$i18n{passwordDetailsTitle}</div> + <div slot="title" id="title">[[getTitle_(isEditDialog_)]]</div> <div slot="body"> <div hidden="[[!shouldShowStorageDetails]]" id="storageDetails"> [[getStorageDetailsMessage_()]] @@ -45,7 +45,9 @@ <cr-input id="passwordInput" label="$i18n{editPasswordPasswordLabel}" type="[[getPasswordInputType_(password)]]" value="[[getPassword_(password)]]" on-blur="onInputBlur_" - class="password-input" readonly> + class="password-input" readonly="[[!isEditDialog_]]" + required="[[isEditDialog_]]" auto-validate="[[isEditDialog_]]" + invalid="{{inputInvalid_}}"> <cr-icon-button id="showPasswordButton" class$="[[getIconClass_(password)]]" slot="suffix" hidden$="[[entry.federationText]]" @@ -55,10 +57,18 @@ '$i18nPolymer{showPassword}')]]"> </cr-icon-button> </cr-input> + <div id="footnote" hidden="[[!isEditDialog_]]"> + [[getFootnote_()]] + </div> </div> <div slot="button-container"> - <cr-button class="action-button" on-click="onActionButtonTap_"> - $i18n{done} + <cr-button id="cancel" class="cancel-button" on-click="onCancel_" + hidden="[[!isEditDialog_]]"> + $i18n{cancel} + </cr-button> + <cr-button id="actionButton" class="action-button" + on-click="onActionButtonTap_" disabled="[[inputInvalid_]]"> + [[getActionButtonName_(isEditDialog_)]] </cr-button> </div> </cr-dialog>
diff --git a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js index ab68498..c63cac4e 100644 --- a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js +++ b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js
@@ -17,12 +17,14 @@ import '../settings_shared_css.m.js'; import '../settings_vars_css.m.js'; import './passwords_shared_css.js'; -import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {ShowPasswordBehavior} from './show_password_behavior.js'; +import {loadTimeData} from '../i18n_setup.js'; +import {PasswordManagerImpl, PasswordManagerProxy} from './password_manager_proxy.js'; +import {ShowPasswordBehavior} from './show_password_behavior.js'; Polymer({ is: 'password-edit-dialog', @@ -33,24 +35,89 @@ properties: { shouldShowStorageDetails: {type: Boolean, value: false}, + + /** @private */ + editPasswordsInSettings_: { + type: Boolean, + value() { + return loadTimeData.getBoolean('editPasswordsInSettings'); + } + }, + + /** + * Check if editPasswordsInSettings flag is true and entry isn't federation + * credential. + * @private + * */ + isEditDialog_: { + type: Boolean, + computed: 'computeIsEditDialog_(editPasswordsInSettings_, entry)' + }, + + /** + * Whether the input is invalid. + * @private + */ + inputInvalid_: Boolean, }, + /** @private {?PasswordManagerProxy} */ + passwordManager_: null, + /** @override */ attached() { + this.passwordManager_ = PasswordManagerImpl.getInstance(); this.$.dialog.showModal(); }, + /** + * Helper function that checks if editPasswordsInSettings flag is true and + * entry isn't federation credential. + * @return {boolean} + * @private + * */ + computeIsEditDialog_() { + return this.editPasswordsInSettings_ && !this.entry.federationText; + }, + /** Closes the dialog. */ close() { this.$.dialog.close(); }, /** - * Handler for tapping the 'done' button. Should just dismiss the dialog. + * Handler for tapping the 'cancel' button. Should just dismiss the dialog. + * @private + */ + onCancel_() { + this.close(); + }, + + /** + * Handler for tapping the 'done' or 'save' button depending on isEditDialog_. + * For 'save' button it should save new password. After pressing action button + * button the edit dialog should be closed. * @private */ onActionButtonTap_() { - this.close(); + if (this.isEditDialog_) { + this.passwordManager_ + .changeSavedPassword( + this.entry.getAnyId(), this.$.passwordInput.value) + .finally(() => { + this.close(); + }); + } else { + this.close(); + } + }, + + /** + * @return {string} + * @private + */ + getActionButtonName_() { + return this.isEditDialog_ ? this.i18n('save') : this.i18n('done'); }, /** Manually de-select texts for readonly inputs. */ @@ -69,5 +136,24 @@ return this.entry.isPresentInAccount() ? this.i18n('passwordStoredInAccount') : this.i18n('passwordStoredOnDevice'); + }, + + /** + * @return {string} + * @private + */ + getTitle_() { + // TODO(crbug.com/377410): Change strings like + // 'editCompromisedPasswordTitle' to 'editPasswordTitle'. + return this.isEditDialog_ ? this.i18n('editCompromisedPasswordTitle') : + this.i18n('passwordDetailsTitle'); + }, + + /** + * @return {string} The text to be displayed as the dialog's footnote. + * @private + */ + getFootnote_() { + return this.i18n('editCompromisedPasswordFootnote', this.entry.urls.shown); } });
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_list_handler.html b/chrome/browser/resources/settings/autofill_page/passwords_list_handler.html index fa957236..2401a5d 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_list_handler.html +++ b/chrome/browser/resources/settings/autofill_page/passwords_list_handler.html
@@ -18,7 +18,9 @@ on-click="onMenuCopyPasswordButtonTap_">$i18n{copyPassword}</button> </template> <button id="menuEditPassword" class="dropdown-item" - on-click="onMenuEditPasswordTap_">$i18n{passwordViewDetails}</button> + on-click="onMenuEditPasswordTap_"> + [[getMenuEditPasswordName_(isEditDialog_)]] + </button> <button id="menuRemovePassword" class="dropdown-item" on-click="onMenuRemovePasswordTap_">$i18n{removePassword}</button> <template is="dom-if" if="[[shouldShowMoveToAccountOption]]">
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_list_handler.js b/chrome/browser/resources/settings/autofill_page/passwords_list_handler.js index 6daf339..65a13dc4 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_list_handler.js +++ b/chrome/browser/resources/settings/autofill_page/passwords_list_handler.js
@@ -87,6 +87,16 @@ } }, + /** + * Check if editPasswordsInSettings flag is true and entry isn't federation + * credential. + * @private + * */ + isEditDialog_: { + type: Boolean, + computed: 'computeIsEditDialog_(editPasswordsInSettings_, activePassword)' + }, + /** @private */ showPasswordEditDialog_: {type: Boolean, value: false}, @@ -103,7 +113,6 @@ */ activeDialogAnchor_: {type: Object, value: null}, - /** * The message displayed in the toast following a password removal. */ @@ -131,6 +140,17 @@ }, /** + * Helper function that checks if editPasswordsInSettings flag is true and + * entry isn't federation credential. + * @return {boolean} + * @private + * */ + computeIsEditDialog_() { + return this.editPasswordsInSettings_ && + (!this.activePassword || !this.activePassword.entry.federationText); + }, + + /** * Closes the toast manager. */ onSavedPasswordOrExceptionRemoved() { @@ -151,16 +171,25 @@ }, /** - * Shows the edit password dialog. * @param {!Event} e * @private */ onMenuEditPasswordTap_(e) { + // TODO(crbug.com/377410): Add authentication if isEditDialog_ is true. e.preventDefault(); this.$.menu.close(); this.showPasswordEditDialog_ = true; }, + /** + * @return {string} + * @private + */ + getMenuEditPasswordName_() { + return this.isEditDialog_ ? this.i18n('editCompromisedPassword') : + this.i18n('passwordViewDetails'); + }, + /** @private */ onPasswordEditDialogClosed_() { this.showPasswordEditDialog_ = false;
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html index 00c722c..3f91f3c 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html +++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
@@ -2,6 +2,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html"> <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="main_page_behavior.html"> @@ -25,6 +26,10 @@ <dom-module id="os-settings-page"> <template> <style include="settings-page-styles cr-hidden-style settings-shared"> + :host { + --google-yellow-50: #fef7e0; + } + :host([is-subpage-animating]) { /* Prevent an unwanted horizontal scrollbar when transitioning back from * a sub-page. */ @@ -41,6 +46,21 @@ margin-top: var(--cr-section-vertical-margin); } + .eol-warning-icon { + align-items: center; + background: var(--google-yellow-50); + border-radius: 50%; + display: flex; + height: 40px; + justify-content: center; + margin-inline-end: var(--cr-section-padding); + width: 40px; + } + + .eol-warning-icon iron-icon { + margin: 0; + } + #advancedToggle { --ink-color: currentColor; align-items: center; @@ -97,6 +117,22 @@ <template is="dom-if" if="[[showBasicPage_( currentRoute_, inSearchMode, hasExpandedSection_)]]"> <div id="basicPage"> + <template is="dom-if" if="[[computeShowUpdateRequiredEolBanner_( + hasExpandedSection_, showUpdateRequiredEolBanner_)]]"> + <div id="updateRequiredEolBanner" + class="settings-box two-line banner"> + <div class="eol-warning-icon"> + <iron-icon icon="cr20:banner-warning"></iron-icon> + </div> + <settings-localized-link id="bannerText" class="start" + localized-string="$i18n{updateRequiredEolBannerText}"> + </settings-localized-link> + <cr-icon-button title="$i18n{close}" id="closeUpdateRequiredEol" + class="icon-clear" on-click="onCloseEolBannerClicked_" + aria-describedby="bannerText"> + </cr-icon-button> + </div> + </template> <div id="secondaryUserBanner" class="banner" hidden="[[!showSecondaryUserBanner_]]"> <div id="secondaryUserIcon"></div>
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.js b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.js index b88f4c4d..2ff2bfa 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.js +++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.js
@@ -87,6 +87,16 @@ computed: 'computeShowSecondaryUserBanner_(hasExpandedSection_)', }, + /** + * Whether to show banner indicating the user to return this device as an + * update is required as per policy but the device has reached end of life. + * @private + */ + showUpdateRequiredEolBanner_: { + type: Boolean, + value: !!loadTimeData.getString('updateRequiredEolBannerText'), + }, + /** @private {!settings.Route|undefined} */ currentRoute_: Object, }, @@ -201,6 +211,14 @@ }, /** + * @return {boolean} + * @private + */ + computeShowUpdateRequiredEolBanner_() { + return !this.hasExpandedSection_ && this.showUpdateRequiredEolBanner_; + }, + + /** * @param {!AndroidAppsInfo} info * @private */ @@ -209,6 +227,15 @@ }, /** + * Hides the update required EOL banner. It is shown again when Settings is + * re-opened. + * @private + */ + onCloseEolBannerClicked_() { + this.showUpdateRequiredEolBanner_ = false; + }, + + /** * Hides everything but the newly expanded subpage. * @private */
diff --git a/chrome/browser/resources/signin/profile_picker/navigation_behavior.js b/chrome/browser/resources/signin/profile_picker/navigation_behavior.js index c004c44..0c3fbda 100644 --- a/chrome/browser/resources/signin/profile_picker/navigation_behavior.js +++ b/chrome/browser/resources/signin/profile_picker/navigation_behavior.js
@@ -48,12 +48,17 @@ switch (path) { case `/${Routes.NEW_PROFILE}`: history.replaceState( - {route: Routes.NEW_PROFILE, step: computeStep(Routes.NEW_PROFILE)}, + { + route: Routes.NEW_PROFILE, + step: computeStep(Routes.NEW_PROFILE), + isFirst: true, + }, '', path); break; default: history.replaceState( - {route: Routes.MAIN, step: computeStep(Routes.MAIN)}, '', '/'); + {route: Routes.MAIN, step: computeStep(Routes.MAIN), isFirst: true}, + '', '/'); } } @@ -83,16 +88,24 @@ { route: route, step: computeStep(route), + isFirst: false, }, '', route === Routes.MAIN ? '/' : `/${route}`); notifyObservers(); } /** - * Navigates to the previous route. + * Navigates to the previous route if it belongs to the profile picker + * otherwise to the main route. */ export function navigateToPreviousRoute() { - // TODO(crbug.com/1063856): Add implementation. + // This can happen if the profile creation flow is opened directly from the + // profile menu. + if (history.state.isFirst) { + navigateTo(Routes.MAIN); + } else { + window.history.back(); + } } /** @polymerBehavior */ @@ -118,4 +131,4 @@ * @param {string} step */ onRouteChange: function(route, step) {}, -}; \ No newline at end of file +};
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker_app.html b/chrome/browser/resources/signin/profile_picker/profile_picker_app.html index d068857..23a2704 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_picker_app.html +++ b/chrome/browser/resources/signin/profile_picker/profile_picker_app.html
@@ -6,7 +6,7 @@ } </style> <cr-view-manager id="viewManager"> - <profile-picker-main-view id="mainView" slot="view" class="active"> + <profile-picker-main-view id="mainView" slot="view"> </profile-picker-main-view> <cr-lazy-render id="profileTypeChoice">
diff --git a/chrome/browser/safe_browsing/delayed_warning_navigation_throttle.cc b/chrome/browser/safe_browsing/delayed_warning_navigation_throttle.cc index 322de5c..c5b6cf5 100644 --- a/chrome/browser/safe_browsing/delayed_warning_navigation_throttle.cc +++ b/chrome/browser/safe_browsing/delayed_warning_navigation_throttle.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/safe_browsing/delayed_warning_navigation_throttle.h" #include "base/feature_list.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/safe_browsing/user_interaction_observer.h" #include "components/safe_browsing/core/features.h" @@ -29,7 +30,8 @@ content::NavigationHandle* navigation_handle) { // If the tab is being prerendered, stop here before it breaks metrics. content::WebContents* web_contents = navigation_handle->GetWebContents(); - if (prerender::PrerenderContents::FromWebContents(web_contents)) { + if (prerender::ChromePrerenderContentsDelegate::FromWebContents( + web_contents)) { return nullptr; }
diff --git a/chrome/browser/safe_browsing/ui_manager.cc b/chrome/browser/safe_browsing/ui_manager.cc index 8e7f709a..210d7af 100644 --- a/chrome/browser/safe_browsing/ui_manager.cc +++ b/chrome/browser/safe_browsing/ui_manager.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/interstitials/enterprise_util.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h" @@ -110,8 +111,10 @@ const security_interstitials::UnsafeResource& resource) { content::WebContents* web_contents = resource.web_contents_getter.Run(); prerender::PrerenderContents* prerender_contents = - web_contents ? prerender::PrerenderContents::FromWebContents(web_contents) - : nullptr; + web_contents + ? prerender::ChromePrerenderContentsDelegate::FromWebContents( + web_contents) + : nullptr; if (!web_contents || prerender_contents) { if (prerender_contents) { prerender_contents->Destroy(prerender::FINAL_STATUS_SAFE_BROWSING);
diff --git a/chrome/browser/safe_browsing/url_checker_delegate_impl.cc b/chrome/browser/safe_browsing/url_checker_delegate_impl.cc index 9e2f1f45..9642d29 100644 --- a/chrome/browser/safe_browsing/url_checker_delegate_impl.cc +++ b/chrome/browser/safe_browsing/url_checker_delegate_impl.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/feature_list.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_io_data.h" @@ -34,7 +35,8 @@ content::WebContents* web_contents = std::move(web_contents_getter).Run(); if (web_contents) { prerender::PrerenderContents* prerender_contents = - prerender::PrerenderContents::FromWebContents(web_contents); + prerender::ChromePrerenderContentsDelegate::FromWebContents( + web_contents); if (prerender_contents) prerender_contents->Destroy(prerender::FINAL_STATUS_SAFE_BROWSING); } @@ -48,7 +50,8 @@ content::WebContents* web_contents = web_contents_getter.Run(); // Don't delay the interstitial for prerender pages. if (!web_contents || - prerender::PrerenderContents::FromWebContents(web_contents)) { + prerender::ChromePrerenderContentsDelegate::FromWebContents( + web_contents)) { SafeBrowsingUIManager::StartDisplayingBlockingPage(ui_manager, resource); return; }
diff --git a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckViewBinder.java b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckViewBinder.java index b71c7085..ecd3983 100644 --- a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckViewBinder.java +++ b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckViewBinder.java
@@ -100,9 +100,10 @@ case SafeBrowsingState.ENABLED_ENHANCED: return R.drawable.ic_done_blue; case SafeBrowsingState.DISABLED: - case SafeBrowsingState.DISABLED_BY_ADMIN: case SafeBrowsingState.ERROR: return R.drawable.ic_info_outline_grey_24dp; + case SafeBrowsingState.DISABLED_BY_ADMIN: + return R.drawable.ic_business; default: assert false : "Unknown SafeBrowsingState value."; }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilder.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilder.java index f554b5bf..cb16aff 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilder.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilder.java
@@ -28,6 +28,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -44,7 +45,7 @@ // TODO(crbug/1022172): Should be package-protected once modularization is complete. public class ShareSheetPropertyModelBuilder { @IntDef({ContentType.LINK_PAGE_VISIBLE, ContentType.LINK_PAGE_NOT_VISIBLE, ContentType.TEXT, - ContentType.IMAGE, ContentType.OTHER_FILE_TYPE, ContentType.HIGHLIGHTED_TEXT}) + ContentType.IMAGE, ContentType.HIGHLIGHTED_TEXT, ContentType.OTHER_FILE_TYPE}) @Retention(RetentionPolicy.SOURCE) @interface ContentType { int LINK_PAGE_VISIBLE = 0; @@ -229,14 +230,14 @@ ShareHelper.getShareLinkAppCompatibilityIntent(), 0); } List<ResolveInfo> resolveInfoList = new ArrayList<>(); - if (contentTypes.contains(ContentType.LINK_PAGE_NOT_VISIBLE) - || contentTypes.contains(ContentType.LINK_PAGE_VISIBLE) - || contentTypes.contains(ContentType.TEXT)) { + if (!Collections.disjoint(contentTypes, + Arrays.asList(ContentType.LINK_PAGE_NOT_VISIBLE, ContentType.LINK_PAGE_VISIBLE, + ContentType.TEXT, ContentType.HIGHLIGHTED_TEXT))) { resolveInfoList.addAll(mPackageManager.queryIntentActivities( ShareHelper.getShareLinkAppCompatibilityIntent(), 0)); } - if (contentTypes.contains(ContentType.IMAGE) - || contentTypes.contains(ContentType.OTHER_FILE_TYPE)) { + if (!Collections.disjoint( + contentTypes, Arrays.asList(ContentType.IMAGE, ContentType.OTHER_FILE_TYPE))) { resolveInfoList.addAll(mPackageManager.queryIntentActivities( ShareHelper.createShareFileAppCompatibilityIntent(fileContentType), 0)); }
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index 1d8a3c1..5da0460 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -3507,7 +3507,8 @@ } EXPECT_EQ(expected_show_blocked, - content_settings::TabSpecificContentSettings::FromWebContents(tab) + content_settings::TabSpecificContentSettings::GetForFrame( + tab->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::MIXEDSCRIPT)); ssl_test_util::CheckSecurityState( tab, CertError::NONE, @@ -3530,7 +3531,8 @@ } EXPECT_EQ(expected_show_blocked_after_allow, - content_settings::TabSpecificContentSettings::FromWebContents(tab) + content_settings::TabSpecificContentSettings::GetForFrame( + tab->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::MIXEDSCRIPT)); ssl_test_util::CheckSecurityState( tab, CertError::NONE, @@ -3555,9 +3557,9 @@ void CheckErrorStateIsCleared() { WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_FALSE( - content_settings::TabSpecificContentSettings::FromWebContents(tab) - ->IsContentBlocked(ContentSettingsType::MIXEDSCRIPT)); + EXPECT_FALSE(content_settings::TabSpecificContentSettings::GetForFrame( + tab->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::MIXEDSCRIPT)); ssl_test_util::CheckSecurityState(tab, CertError::NONE, security_state::NONE, AuthState::NONE); EXPECT_FALSE(SecurityStateTabHelper::FromWebContents(tab)
diff --git a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc index 86fde3de..4f395895 100644 --- a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc +++ b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc
@@ -161,9 +161,13 @@ InfoBarService::FromWebContents(web_contents()); AdsBlockedInfobarDelegate::Create(infobar_service); #endif + // TODO(https://crbug.com/1103176): Plumb the actual frame reference here + // (it comes from + // ContentSubresourceFilterThrottleManager::DidDisallowFirstSubresource, which + // comes from a specific frame). content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents()); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::ADS); LogAction(SubresourceFilterAction::kUIShown);
diff --git a/chrome/browser/subresource_filter/subresource_filter_popup_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_popup_browsertest.cc index 7efd118..d5dda04 100644 --- a/chrome/browser/subresource_filter/subresource_filter_popup_browsertest.cc +++ b/chrome/browser/subresource_filter/subresource_filter_popup_browsertest.cc
@@ -135,8 +135,8 @@ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, "openWindow()", &opened_window)); EXPECT_TRUE(opened_window); - EXPECT_FALSE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents) + EXPECT_FALSE(content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); // Navigate again to trigger histogram logging. Make sure the navigation @@ -184,8 +184,8 @@ EXPECT_FALSE(opened_window); tester.ExpectTotalCount(kSubresourceFilterActionsHistogram, 0); // Make sure the popup UI was shown. - EXPECT_TRUE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents) + EXPECT_TRUE(content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); // Block again. @@ -203,8 +203,8 @@ &opened_window)); EXPECT_TRUE(opened_window); // Popup UI should not be shown. - EXPECT_FALSE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents) + EXPECT_FALSE(content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); } @@ -344,8 +344,8 @@ EXPECT_TRUE(content::ExecuteScript(web_contents, "openWindow()")); tester.ExpectTotalCount(kSubresourceFilterActionsHistogram, 0); - EXPECT_TRUE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents) + EXPECT_TRUE(content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); const bool enable_adblock_on_abusive_sites = GetParam(); EXPECT_EQ(enable_adblock_on_abusive_sites, AreDisallowedRequestsBlocked()); @@ -360,8 +360,8 @@ navigation_observer.Wait(); // Popup UI should not be shown. - EXPECT_FALSE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents) + EXPECT_FALSE(content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); EXPECT_FALSE(AreDisallowedRequestsBlocked()); } @@ -382,8 +382,8 @@ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, "openWindow()", &sent_open)); EXPECT_TRUE(sent_open); - EXPECT_TRUE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents) + EXPECT_TRUE(content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); const bool enable_adblock_on_abusive_sites = GetParam(); EXPECT_EQ(enable_adblock_on_abusive_sites, AreDisallowedRequestsBlocked()); @@ -405,8 +405,8 @@ content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_FALSE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents) + EXPECT_FALSE(content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); const bool enable_adblock_on_abusive_sites = GetParam(); EXPECT_EQ(enable_adblock_on_abusive_sites, AreDisallowedRequestsBlocked());
diff --git a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h index a75ab850..48d1199 100644 --- a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h +++ b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h
@@ -14,7 +14,7 @@ #include "content/public/browser/service_worker_context.h" #include "content/public/browser/service_worker_context_observer.h" #include "content/public/browser/shared_worker_service.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" class Profile;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 2c20670..97fe5ec2ac 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -925,6 +925,10 @@ "commander/commander_controller.h", "commander/commander_view_model.cc", "commander/commander_view_model.h", + "commander/fuzzy_finder.cc", + "commander/fuzzy_finder.h", + "commander/simple_command_source.cc", + "commander/simple_command_source.h", "confirm_bubble_model.cc", "confirm_bubble_model.h", "content_settings/content_setting_bubble_model.cc", @@ -1505,6 +1509,7 @@ "//components/keep_alive_registry", "//components/network_session_configurator/common", "//components/page_load_metrics/browser", + "//components/performance_manager:site_data_proto", "//components/profile_metrics", "//components/safety_check", "//components/search_provider_logos",
diff --git a/chrome/browser/ui/blocked_content/popup_tracker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_tracker_browsertest.cc index b3561a6..9312c47e2 100644 --- a/chrome/browser/ui/blocked_content/popup_tracker_browsertest.cc +++ b/chrome/browser/ui/blocked_content/popup_tracker_browsertest.cc
@@ -290,8 +290,8 @@ // Is blocked by the popup blocker. ui_test_utils::NavigateToURL(browser(), url); - EXPECT_TRUE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents) + EXPECT_TRUE(content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); // Click through to open the popup.
diff --git a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc index bd467db..1d3e081f 100644 --- a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc +++ b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc
@@ -247,8 +247,9 @@ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, "openWindow()", &opened_window)); EXPECT_TRUE(opened_window); - EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_FALSE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); } IN_PROC_BROWSER_TEST_F(SafeBrowsingTriggeredPopupBlockerDisabledTest, @@ -266,8 +267,9 @@ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, "openWindow()", &opened_window)); EXPECT_TRUE(opened_window); - EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_FALSE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); RoundTripAndVerifyLogMessages(console_observer, web_contents, {}, {blocked_content::kAbusiveWarnMessage, @@ -296,8 +298,9 @@ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, "openWindow()", &opened_window)); EXPECT_TRUE(opened_window); - EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_FALSE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); // Since the policy change can take effect without browser restart, verify // that enabling the policy here should disallow opening new tabs or windows @@ -321,8 +324,9 @@ web_contents1, "openWindow()", &opened_window)); EXPECT_FALSE(opened_window); // Make sure the popup UI was shown. - EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents1) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_TRUE( + TabSpecificContentSettings::GetForFrame(web_contents1->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); } IN_PROC_BROWSER_TEST_F(SafeBrowsingTriggeredPopupBlockerBrowserTest, @@ -343,8 +347,9 @@ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, "openWindow()", &opened_window)); EXPECT_TRUE(opened_window); - EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_FALSE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); } IN_PROC_BROWSER_TEST_F(SafeBrowsingTriggeredPopupBlockerBrowserTest, @@ -360,8 +365,9 @@ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, "openWindow()", &opened_window)); EXPECT_TRUE(opened_window); - EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_FALSE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); } IN_PROC_BROWSER_TEST_F(SafeBrowsingTriggeredPopupBlockerBrowserTest, @@ -380,8 +386,9 @@ &opened_window)); EXPECT_FALSE(opened_window); // Make sure the popup UI was shown. - EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_TRUE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); // Block again. EXPECT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, "openWindow()", @@ -395,8 +402,9 @@ &opened_window)); EXPECT_TRUE(opened_window); // Popup UI should not be shown. - EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_FALSE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); } IN_PROC_BROWSER_TEST_F(SafeBrowsingTriggeredPopupBlockerBrowserTest, @@ -417,8 +425,9 @@ EXPECT_FALSE(opened_window); // Make sure the popup UI was shown. - EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_TRUE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); // Click through. content::TestNavigationObserver navigation_observer(nullptr, 1); @@ -501,8 +510,9 @@ browser()->tab_strip_model()->GetActiveWebContents(); EXPECT_TRUE(content::ExecuteScript(web_contents, "openWindow()")); - EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_TRUE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); // Navigate to |b_url|, which should successfully open the popup. @@ -514,8 +524,9 @@ navigation_observer.Wait(); // Popup UI should not be shown. - EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_FALSE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); } IN_PROC_BROWSER_TEST_F(SafeBrowsingTriggeredPopupBlockerBrowserTest, @@ -532,8 +543,9 @@ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, "openWindow()", &sent_open)); EXPECT_TRUE(sent_open); - EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_TRUE( + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); } IN_PROC_BROWSER_TEST_F(SafeBrowsingTriggeredPopupBlockerBrowserTest, @@ -550,9 +562,10 @@ EXPECT_TRUE(content::ExecuteScriptAndExtractBool( web_contents, "openWindow()", &opened_window)); EXPECT_EQ(expect_block, !opened_window); - EXPECT_EQ(expect_block, - TabSpecificContentSettings::FromWebContents(web_contents) - ->IsContentBlocked(ContentSettingsType::POPUPS)); + EXPECT_EQ( + expect_block, + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + ->IsContentBlocked(ContentSettingsType::POPUPS)); }; ui_test_utils::NavigateToURL(browser(), url1);
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 4722dd6f84..66c4158 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -1437,9 +1437,12 @@ // Note: this is a browser-side-translation of the call to // DidBlockContentType from inside // ContentSettingsObserver::allowRunningInsecureContent. + // TODO(https://crbug.com/1103176): Plumb the actual frame reference here + // (MixedContentNavigationThrottle::ShouldBlockNavigation has + // |mixed_content_frame| reference) content_settings::TabSpecificContentSettings* tab_settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()); DCHECK(tab_settings); tab_settings->OnContentBlocked(ContentSettingsType::MIXEDSCRIPT); } @@ -2129,9 +2132,10 @@ return; } + // TODO(https://crbug.com/1103176): Plumb the actual frame reference here content_settings::TabSpecificContentSettings* tab_content_settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()); HostContentSettingsMap* content_settings = HostContentSettingsMapFactory::GetForProfile(profile); @@ -2160,7 +2164,9 @@ base::RecordAction(allowed ? base::UserMetricsAction("PPAPI.BrokerSettingAllow") : base::UserMetricsAction("PPAPI.BrokerSettingDeny")); - tab_content_settings->SetPepperBrokerAllowed(allowed); + if (tab_content_settings) { + tab_content_settings->SetPepperBrokerAllowed(allowed); + } std::move(callback).Run(allowed); #endif }
diff --git a/chrome/browser/ui/caption_bubble_controller.h b/chrome/browser/ui/caption_bubble_controller.h index 0be02b9..65e5e23d 100644 --- a/chrome/browser/ui/caption_bubble_controller.h +++ b/chrome/browser/ui/caption_bubble_controller.h
@@ -37,6 +37,8 @@ static std::unique_ptr<CaptionBubbleController> Create(Browser* browser); + virtual bool OnSpeechRecognitionReady(content::WebContents* web_contents) = 0; + // Called when a transcription is received from the service. Returns whether // the transcription result was set on the caption bubble successfully. // Transcriptions will halt if this returns false.
diff --git a/chrome/browser/ui/commander/fuzzy_finder.cc b/chrome/browser/ui/commander/fuzzy_finder.cc new file mode 100644 index 0000000..9aba2cf5 --- /dev/null +++ b/chrome/browser/ui/commander/fuzzy_finder.cc
@@ -0,0 +1,31 @@ +// Copyright 2020 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/commander/fuzzy_finder.h" + +#include "base/i18n/case_conversion.h" + +namespace commander { + +double FuzzyFind(const base::string16& needle, + const base::string16& haystack, + std::vector<gfx::Range>* matched_ranges) { + DCHECK(needle == base::i18n::FoldCase(needle)); + matched_ranges->clear(); + const base::string16& folded = base::i18n::FoldCase(haystack); + if (folded == needle) { + matched_ranges->emplace_back(0, needle.length()); + return 1.0; + } + size_t substring_position = folded.find(needle); + if (substring_position == std::string::npos) + return 0; + matched_ranges->emplace_back(substring_position, needle.length()); + if (substring_position == 0) + return .99; + return std::min(1 - static_cast<double>(substring_position) / folded.length(), + 0.01); +} + +} // namespace commander
diff --git a/chrome/browser/ui/commander/fuzzy_finder.h b/chrome/browser/ui/commander/fuzzy_finder.h new file mode 100644 index 0000000..708b981 --- /dev/null +++ b/chrome/browser/ui/commander/fuzzy_finder.h
@@ -0,0 +1,34 @@ +// Copyright 2020 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_COMMANDER_FUZZY_FINDER_H_ +#define CHROME_BROWSER_UI_COMMANDER_FUZZY_FINDER_H_ + +#include "base/strings/string16.h" +#include "ui/gfx/range/range.h" + +namespace commander { + +// TODO(lgrey): Make this actually fuzzy find. +// Returns a score from 0 to 1 based on how well |needle| matches |haystack|. +// 0 means no match. |matched_ranges| will be filled with the ranges of +// |haystack| that match |needle| so they can be highlighted in the UI; see +// comment on commander::CommandItem |matched_ranges| for a worked example. +// *** TEMPORARY *** +// Temporarily, a non-zero match means that |needle| is a substring of +// |haystack|, with a penalty applied based on how far into |haystack| +// |needle| begins. Exact matches are 1.0 (vs. a max of .99 for non-exact +// prefix). +// This will be replaced with a more sophisticated implementation in the +// near future. +// *** END TEMPORARY *** +// |needle| is expected to already be case folded (this is DCHECKED) to save +// redundant processing, as the needle will be checked with many haystacks. +double FuzzyFind(const base::string16& needle, + const base::string16& haystack, + std::vector<gfx::Range>* matched_ranges); + +} // namespace commander + +#endif // CHROME_BROWSER_UI_COMMANDER_FUZZY_FINDER_H_
diff --git a/chrome/browser/ui/commander/fuzzy_finder_unittest.cc b/chrome/browser/ui/commander/fuzzy_finder_unittest.cc new file mode 100644 index 0000000..362aa4f --- /dev/null +++ b/chrome/browser/ui/commander/fuzzy_finder_unittest.cc
@@ -0,0 +1,54 @@ +// Copyright 2020 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/commander/fuzzy_finder.h" + +#include "base/i18n/case_conversion.h" +#include "base/strings/utf_string_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace commander { +TEST(CommanderFuzzyFinder, NonmatchIsZero) { + std::vector<gfx::Range> ranges; + EXPECT_EQ(0, FuzzyFind(base::ASCIIToUTF16("orange"), + base::ASCIIToUTF16("orangutan"), &ranges)); + EXPECT_TRUE(ranges.empty()); + EXPECT_EQ(0, FuzzyFind(base::ASCIIToUTF16("elephant"), + base::ASCIIToUTF16("orangutan"), &ranges)); + EXPECT_TRUE(ranges.empty()); +} + +TEST(CommanderFuzzyFinder, ExactMatchIsOne) { + std::vector<gfx::Range> ranges; + EXPECT_EQ(1, FuzzyFind(base::ASCIIToUTF16("orange"), + base::ASCIIToUTF16("orange"), &ranges)); + EXPECT_EQ(ranges, std::vector<gfx::Range>({{0, 6}})); +} + +TEST(CommanderFuzzyFinder, CaseInsensitive) { + std::vector<gfx::Range> ranges; + EXPECT_EQ(1, FuzzyFind(base::ASCIIToUTF16("orange"), + base::ASCIIToUTF16("Orange"), &ranges)); + EXPECT_EQ(ranges, std::vector<gfx::Range>({{0, 6}})); +} + +TEST(CommanderFuzzyFinder, PrefixRanksHigherThanInternal) { + std::vector<gfx::Range> ranges; + + double prefix_rank = FuzzyFind(base::ASCIIToUTF16("orange"), + base::ASCIIToUTF16("Orange juice"), &ranges); + EXPECT_EQ(ranges, std::vector<gfx::Range>({{0, 6}})); + + double non_prefix_rank = + FuzzyFind(base::ASCIIToUTF16("orange"), + base::ASCIIToUTF16("William of Orange"), &ranges); + EXPECT_EQ(ranges, std::vector<gfx::Range>({{11, 6}})); + + EXPECT_GT(prefix_rank, 0); + EXPECT_GT(non_prefix_rank, 0); + EXPECT_LT(prefix_rank, 1); + EXPECT_LT(non_prefix_rank, 1); + EXPECT_GT(prefix_rank, non_prefix_rank); +} +} // namespace commander
diff --git a/chrome/browser/ui/commander/simple_command_source.cc b/chrome/browser/ui/commander/simple_command_source.cc new file mode 100644 index 0000000..e66c1a8e --- /dev/null +++ b/chrome/browser/ui/commander/simple_command_source.cc
@@ -0,0 +1,78 @@ +// Copyright 2020 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/commander/simple_command_source.h" + +#include "base/bind.h" +#include "base/i18n/case_conversion.h" +#include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/commander/fuzzy_finder.h" +#include "chrome/grit/generated_resources.h" +#include "components/strings/grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" + +namespace commander { + +SimpleCommandSource::SimpleCommandSource() { + weak_this_ = weak_ptr_factory_.GetWeakPtr(); +} +SimpleCommandSource::~SimpleCommandSource() = default; + +CommandSource::CommandResults SimpleCommandSource::GetCommands( + const base::string16& input, + Browser* browser) const { + static constexpr struct { + int command_id; + int string_constant; + } command_map[] = { + {IDC_SHOW_HISTORY, IDS_HISTORY_SHOWFULLHISTORY_LINK}, + {IDC_FIND, IDS_FIND}, + {IDC_RELOAD, IDS_TOOLTIP_RELOAD}, + {IDC_SAVE_PAGE, IDS_SAVE_PAGE}, + {IDC_PRINT, IDS_PRINT}, + }; + + CommandSource::CommandResults results; + const base::string16& folded_input = base::i18n::FoldCase(input); + std::vector<gfx::Range> ranges; + for (const auto& command_spec : command_map) { + if (!chrome::IsCommandEnabled(browser, command_spec.command_id)) + continue; + const base::string16 title = + l10n_util::GetStringUTF16(command_spec.string_constant); + double score = FuzzyFind(folded_input, title, &ranges); + if (score == 0) + continue; + + auto item = std::make_unique<CommandItem>(); + item->title = title; + item->score = score; + item->matched_ranges = ranges; + // TODO(lgrey): For base::Unretained to be safe here, we need to ensure + // that if |browser| is destroyed, the palette is reset. It's likely + // that this will be the case anyway, but leaving this comment so: + // - it doesn't get dropped/forgotten + // - as a reminder to replace the comment with the actual explanation + // when we have it + item->command = + base::BindOnce(&SimpleCommandSource::ExecuteCommand, weak_this_, + base::Unretained(browser), command_spec.command_id); + results.push_back(std::move(item)); + } + + return results; +} + +// Why this is necessary: +// chrome::ExecuteCommand has a third default argument |time_stamp| which +// makes it difficult to use with BindOnce. Pre-binding it at command creation +// is wrong since it defaults to base::TimeTicks::Now(); that means if pre-bound +// it would get the timestamp when the command was generated, rather than when +// it was invoked. +void SimpleCommandSource::ExecuteCommand(Browser* browser, int command_id) { + chrome::ExecuteCommand(browser, command_id); +} + +} // namespace commander
diff --git a/chrome/browser/ui/commander/simple_command_source.h b/chrome/browser/ui/commander/simple_command_source.h new file mode 100644 index 0000000..a81a6328 --- /dev/null +++ b/chrome/browser/ui/commander/simple_command_source.h
@@ -0,0 +1,40 @@ +// Copyright 2020 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_COMMANDER_SIMPLE_COMMAND_SOURCE_H_ +#define CHROME_BROWSER_UI_COMMANDER_SIMPLE_COMMAND_SOURCE_H_ + +#include "chrome/browser/ui/commander/command_source.h" + +#include "base/memory/weak_ptr.h" + +namespace commander { + +// A command source which hosts simple one-shot browser commands, most of which +// are accessible by hotkey. This is an alternative surface to provide for +// hotkey discovery. +class SimpleCommandSource : public CommandSource { + public: + SimpleCommandSource(); + ~SimpleCommandSource() override; + + // Disallow copy and assign + SimpleCommandSource(const SimpleCommandSource& other) = delete; + SimpleCommandSource& operator=(const SimpleCommandSource& other) = delete; + + // Command source overrides + CommandSource::CommandResults GetCommands(const base::string16& input, + Browser* browser) const override; + + private: + base::WeakPtr<SimpleCommandSource> weak_this_; + // Wrapper around chrome::ExecuteCommand. See implementation comment + // for details. + void ExecuteCommand(Browser* browser, int command_id); + base::WeakPtrFactory<SimpleCommandSource> weak_ptr_factory_{this}; +}; + +} // namespace commander + +#endif // CHROME_BROWSER_UI_COMMANDER_SIMPLE_COMMAND_SOURCE_H_
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc index de7fa27..7180227 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
@@ -208,8 +208,9 @@ } void ContentSettingSimpleBubbleModel::SetTitle() { + // TODO(https://crbug.com/1103176): Plumb the actual frame reference here TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); static const ContentSettingsTypeIdEntry kBlockedTitleIDs[] = { {ContentSettingsType::COOKIES, IDS_BLOCKED_COOKIES_TITLE}, @@ -244,7 +245,7 @@ void ContentSettingSimpleBubbleModel::SetMessage() { TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // TODO(https://crbug.com/978882): Make the two arrays below static again once // we no longer need to check base::FeatureList. @@ -537,7 +538,7 @@ void ContentSettingMidiSysExBubbleModel::SetDomainsAndCustomLink() { TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const ContentSettingsUsagesState& usages_state = content_settings->midi_usages_state(); ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state; @@ -567,7 +568,7 @@ // origins currently on the page. const GURL& embedder_url = web_contents()->GetURL(); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const ContentSettingsUsagesState::StateMap& state_map = content_settings->midi_usages_state().state_map(); HostContentSettingsMap* map = @@ -630,7 +631,7 @@ void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() { TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const ContentSettingsUsagesState& usages = content_settings->geolocation_usages_state(); ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state; @@ -660,7 +661,7 @@ // origins currently on the page. const GURL& embedder_url = web_contents()->GetURL(); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const ContentSettingsUsagesState::StateMap& state_map = content_settings->geolocation_usages_state().state_map(); HostContentSettingsMap* map = @@ -720,7 +721,7 @@ // Disable the "Run all plugins this time" link if the user already clicked // on the link and ran all plugins. set_custom_link_enabled( - TabSpecificContentSettings::FromWebContents(web_contents) + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->load_plugins_link_enabled()); } @@ -753,7 +754,7 @@ web_contents(), true, std::string()); #endif set_custom_link_enabled(false); - TabSpecificContentSettings::FromWebContents(web_contents()) + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()) ->set_load_plugins_link_enabled(false); } @@ -792,7 +793,7 @@ base::string16 display_host = url_formatter::FormatUrlForSecurityDisplay(url); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); bool allowed = !content_settings->IsContentBlocked(content_type()); // For the frame busting case the content is blocked but its content type is @@ -1050,7 +1051,7 @@ radio_item_setting_[1] = CONTENT_SETTING_BLOCK; TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents); + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); state_ = content_settings->GetMicrophoneCameraState(); DCHECK(CameraAccessed() || MicrophoneAccessed()); @@ -1186,7 +1187,7 @@ void ContentSettingMediaStreamBubbleModel::SetRadioGroup() { TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); GURL url = content_settings->media_stream_access_origin(); RadioGroup radio_group; radio_group.url = url; @@ -1265,7 +1266,7 @@ void ContentSettingMediaStreamBubbleModel::UpdateSettings( ContentSetting setting) { TabSpecificContentSettings* tab_content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // The same urls must be used as in other places (e.g. the infobar) in // order to override the existing rule. Otherwise a new rule is created. // TODO(markusheintz): Extract to a helper so that there is only a single @@ -1367,7 +1368,7 @@ void ContentSettingMediaStreamBubbleModel::SetMediaMenus() { TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const std::string& requested_microphone = content_settings->media_stream_requested_audio_device(); const std::string& requested_camera = @@ -1437,7 +1438,7 @@ void ContentSettingMediaStreamBubbleModel::SetCustomLink() { TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); if (content_settings->IsMicrophoneCameraStateChanged()) { set_custom_link( l10n_util::GetStringUTF16(IDS_MEDIASTREAM_SETTING_CHANGED_MESSAGE));
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc index 112437b..324a40b 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc
@@ -57,8 +57,8 @@ } TabSpecificContentSettings* GetActiveTabSpecificContentSettings() { - return TabSpecificContentSettings::FromWebContents( - browser()->tab_strip_model()->GetActiveWebContents()); + return TabSpecificContentSettings::GetForFrame( + browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()); } std::unique_ptr<net::EmbeddedTestServer> https_server_; @@ -173,7 +173,7 @@ content::WebContents* web_contents = GetActiveTab(); // Create a bubble with the given camera and microphone access state. - TabSpecificContentSettings::FromWebContents(web_contents) + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->OnMediaStreamPermissionSet(web_contents->GetLastCommittedURL(), state, std::string(), std::string(), std::string(), std::string());
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc index 9c3d97d..44c94b9e 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
@@ -94,7 +94,7 @@ WebContentsTester::For(web_contents())-> NavigateAndCommit(GURL("https://www.example.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::IMAGES); std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model( @@ -113,7 +113,7 @@ WebContentsTester::For(web_contents())-> NavigateAndCommit(GURL("https://www.example.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::COOKIES); std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model( @@ -131,7 +131,7 @@ WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentAllowed(ContentSettingsType::COOKIES); content_setting_bubble_model = ContentSettingBubbleModel::CreateContentSettingBubbleModel( @@ -160,7 +160,7 @@ DisableDeviceEnumerationForTesting(); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); std::string request_host = "google.com"; GURL security_origin("http://" + request_host); TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = @@ -216,7 +216,7 @@ setting); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = TabSpecificContentSettings::MICROPHONE_ACCESSED | TabSpecificContentSettings::MICROPHONE_BLOCKED | @@ -285,7 +285,7 @@ setting); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = TabSpecificContentSettings::MICROPHONE_ACCESSED | TabSpecificContentSettings::MICROPHONE_BLOCKED; @@ -377,7 +377,7 @@ audio_devices); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = TabSpecificContentSettings::MICROPHONE_ACCESSED | TabSpecificContentSettings::MICROPHONE_BLOCKED; @@ -523,7 +523,7 @@ DisableDeviceEnumerationForTesting(); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); std::string request_host = "google.com"; GURL security_origin("http://" + request_host); TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = @@ -596,7 +596,7 @@ DisableDeviceEnumerationForTesting(); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); std::string request_host = "google.com"; GURL security_origin("http://" + request_host); TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = @@ -670,7 +670,7 @@ DisableDeviceEnumerationForTesting(); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); std::string request_host = "google.com"; GURL security_origin("http://" + request_host); @@ -737,7 +737,7 @@ WebContentsTester::For(web_contents())-> NavigateAndCommit(GURL("https://www.example.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const base::string16 plugin_name = base::ASCIIToUTF16("plugin_name"); content_settings->OnContentBlocked(ContentSettingsType::PLUGINS); @@ -760,7 +760,7 @@ WebContentsTester::For(web_contents())-> NavigateAndCommit(GURL("https://www.example.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::PPAPI_BROKER); std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model( @@ -780,7 +780,7 @@ WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentAllowed(ContentSettingsType::PPAPI_BROKER); content_setting_bubble_model = ContentSettingBubbleModel::CreateContentSettingBubbleModel( @@ -804,7 +804,7 @@ NavigateAndCommit(page_url); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // One permitted frame, but not in the content map: requires reload. content_settings->OnGeolocationPermissionSet(frame1_url, true); @@ -850,7 +850,7 @@ NavigateAndCommit(origin_to_embargo); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnGeolocationPermissionSet(origin_to_embargo, false); // |origin_to_embargo| is not blocked or embargoed. Verify no clear link @@ -898,7 +898,7 @@ TEST_F(ContentSettingBubbleModelTest, FileURL) { std::string file_url("file:///tmp/test.html"); NavigateAndCommit(GURL(file_url)); - TabSpecificContentSettings::FromWebContents(web_contents()) + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()) ->OnContentBlocked(ContentSettingsType::IMAGES); std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model( ContentSettingBubbleModel::CreateContentSettingBubbleModel( @@ -1059,7 +1059,7 @@ WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); HostContentSettingsMap* settings_map = HostContentSettingsMapFactory::GetForProfile(profile()); @@ -1137,7 +1137,7 @@ WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Go from block by default to allow by default to block by default. { @@ -1213,7 +1213,7 @@ WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Block by default but allow a specific site. { @@ -1246,7 +1246,7 @@ WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Clear site-specific exceptions. settings_map->ClearSettingsForOneType(ContentSettingsType::SENSORS); @@ -1283,7 +1283,7 @@ const GURL url("https://www.example.test/"); WebContentsTester::For(web_contents())->NavigateAndCommit(url); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::POPUPS); blocked_content::PopupBlockerTabHelper::CreateForWebContents(web_contents()); @@ -1317,7 +1317,7 @@ NavigateAndCommit(GURL("https://www.example.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::COOKIES); std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model( @@ -1334,7 +1334,7 @@ NavigateAndCommit(GURL("about:blank")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::COOKIES); std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model(
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model.cc b/chrome/browser/ui/content_settings/content_setting_image_model.cc index 5907358..6b63e64 100644 --- a/chrome/browser/ui/content_settings/content_setting_image_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_image_model.cc
@@ -420,7 +420,7 @@ // If a content type is blocked by default and was accessed, display the // content blocked page action. TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents); + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings) return false; @@ -484,7 +484,7 @@ bool ContentSettingGeolocationImageModel::UpdateAndGetVisibility( WebContents* web_contents) { TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents); + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings) return false; const ContentSettingsUsagesState& usages_state = @@ -536,7 +536,7 @@ bool ContentSettingMIDISysExImageModel::UpdateAndGetVisibility( WebContents* web_contents) { TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents); + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings) return false; const ContentSettingsUsagesState& usages_state = @@ -603,7 +603,7 @@ bool ContentSettingClipboardReadWriteImageModel::UpdateAndGetVisibility( WebContents* web_contents) { TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents); + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings) return false; ContentSettingsType content_type = ContentSettingsType::CLIPBOARD_READ_WRITE; @@ -628,7 +628,7 @@ WebContents* web_contents) { set_should_auto_open_bubble(false); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents); + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings) return false; state_ = content_settings->GetMicrophoneCameraState(); @@ -820,7 +820,7 @@ bool ContentSettingSensorsImageModel::UpdateAndGetVisibility( WebContents* web_contents) { auto* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents); + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings) return false; @@ -861,7 +861,7 @@ bool ContentSettingPopupImageModel::UpdateAndGetVisibility( WebContents* web_contents) { TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents); + TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings || !content_settings->IsContentBlocked(content_type())) return false; set_icon(kWebIcon, vector_icons::kBlockedBadgeIcon);
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model_browsertest.cc b/chrome/browser/ui/content_settings/content_setting_image_model_browsertest.cc index 9fad6fb..914d8add 100644 --- a/chrome/browser/ui/content_settings/content_setting_image_model_browsertest.cc +++ b/chrome/browser/ui/content_settings/content_setting_image_model_browsertest.cc
@@ -28,8 +28,8 @@ WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()); content_settings->BlockAllContentForTesting(); // Automatic downloads are handled by DownloadRequestLimiter.
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_image_model_unittest.cc index 0658050..e71704fb 100644 --- a/chrome/browser/ui/content_settings/content_setting_image_model_unittest.cc +++ b/chrome/browser/ui/content_settings/content_setting_image_model_unittest.cc
@@ -119,7 +119,7 @@ std::make_unique<chrome::TabSpecificContentSettingsDelegate>( web_contents())); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); auto content_setting_image_model = ContentSettingImageModel::CreateForContentType( ContentSettingImageModel::ImageType::IMAGES); @@ -170,7 +170,7 @@ std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create( origin, "A=B", base::Time::Now(), base::nullopt /* server_time */)); ASSERT_TRUE(cookie); - TabSpecificContentSettings::FromWebContents(web_contents()) + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()) ->OnCookiesAccessed({content::CookieAccessDetails::Type::kChange, origin, origin, @@ -193,7 +193,7 @@ std::make_unique<chrome::TabSpecificContentSettingsDelegate>( web_contents())); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); auto content_setting_image_model = ContentSettingImageModel::CreateForContentType( @@ -213,7 +213,7 @@ NavigateAndCommit(controller_, GURL("http://www.google.com")); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Allowing by default but blocking (e.g. due to a feature policy) causes the // indicator to be shown. @@ -230,7 +230,7 @@ NavigateAndCommit(controller_, GURL("http://www.google.com")); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Blocking by default but allowing (e.g. via a site-specific exception) // causes the indicator to be shown. @@ -247,7 +247,7 @@ NavigateAndCommit(controller_, GURL("http://www.google.com")); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Blocking access by default also causes the indicator to be shown so users // can set an exception. @@ -277,7 +277,7 @@ web_contents())); NavigateAndCommit(controller_, GURL("https://www.example.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); HostContentSettingsMap* settings_map = HostContentSettingsMapFactory::GetForProfile(profile()); @@ -317,7 +317,7 @@ NavigateAndCommit(controller_, GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Go from block by default to allow by default to block by default. { @@ -352,7 +352,7 @@ NavigateAndCommit(controller_, GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Block by default but allow a specific site. { @@ -373,7 +373,7 @@ NavigateAndCommit(controller_, GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Clear site-specific exceptions. settings_map->ClearSettingsForOneType(ContentSettingsType::SENSORS); @@ -398,8 +398,8 @@ // Regression test for http://crbug.com/161854. TEST_F(ContentSettingImageModelTest, NULLTabSpecificContentSettings) { TabSpecificContentSettings::DeleteForWebContentsForTest(web_contents()); - EXPECT_EQ(nullptr, - TabSpecificContentSettings::FromWebContents(web_contents())); + EXPECT_EQ(nullptr, TabSpecificContentSettings::GetForFrame( + web_contents()->GetMainFrame())); // Should not crash. ContentSettingImageModel::CreateForContentType( ContentSettingImageModel::ImageType::IMAGES) @@ -412,7 +412,7 @@ std::make_unique<chrome::TabSpecificContentSettingsDelegate>( web_contents())); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); auto content_setting_image_model = ContentSettingImageModel::CreateForContentType( ContentSettingImageModel::ImageType::ADS); @@ -433,7 +433,7 @@ std::make_unique<chrome::TabSpecificContentSettingsDelegate>( web_contents())); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); auto content_setting_image_model = ContentSettingImageModel::CreateForContentType( ContentSettingImageModel::ImageType::NOTIFICATIONS_QUIET_PROMPT);
diff --git a/chrome/browser/ui/content_settings/content_setting_media_image_model_unittest.mm b/chrome/browser/ui/content_settings/content_setting_media_image_model_unittest.mm index edb702e9..20ae58aa 100644 --- a/chrome/browser/ui/content_settings/content_setting_media_image_model_unittest.mm +++ b/chrome/browser/ui/content_settings/content_setting_media_image_model_unittest.mm
@@ -91,7 +91,7 @@ std::make_unique<chrome::TabSpecificContentSettingsDelegate>( web_contents())); auto* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const GURL kTestOrigin("https://www.example.com"); auto content_setting_image_model = ContentSettingImageModel::CreateForContentType(
diff --git a/chrome/browser/ui/cookie_controls/cookie_controls_controller_unittest.cc b/chrome/browser/ui/cookie_controls/cookie_controls_controller_unittest.cc index 2040f651..8255692 100644 --- a/chrome/browser/ui/cookie_controls/cookie_controls_controller_unittest.cc +++ b/chrome/browser/ui/cookie_controls/cookie_controls_controller_unittest.cc
@@ -98,8 +98,8 @@ content_settings::TabSpecificContentSettings* tab_specific_content_settings() { - return content_settings::TabSpecificContentSettings::FromWebContents( - web_contents()); + return content_settings::TabSpecificContentSettings::GetForFrame( + web_contents()->GetMainFrame()); } private:
diff --git a/chrome/browser/ui/login/login_handler.cc b/chrome/browser/ui/login/login_handler.cc index fa652806..fb36970 100644 --- a/chrome/browser/ui/login/login_handler.cc +++ b/chrome/browser/ui/login/login_handler.cc
@@ -18,6 +18,7 @@ #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" +#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/tab_contents/tab_util.h" #include "chrome/common/chrome_features.h" @@ -520,7 +521,8 @@ return; } prerender::PrerenderContents* prerender_contents = - prerender::PrerenderContents::FromWebContents(web_contents()); + prerender::ChromePrerenderContentsDelegate::FromWebContents( + web_contents()); if (prerender_contents) { prerender_contents->Destroy(prerender::FINAL_STATUS_AUTH_NEEDED); CancelAuth();
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index 52cf2b1..f888e94 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -139,6 +139,7 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/child_accounts/time_limits/web_time_navigation_observer.h" +#include "chrome/browser/chromeos/policy/dlp/dlp_content_tab_helper.h" #include "chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h" #endif @@ -374,6 +375,7 @@ app_list::CrOSActionRecorderTabTracker::CreateForWebContents(web_contents); chromeos::app_time::WebTimeNavigationObserver::MaybeCreateForWebContents( web_contents); + policy::DlpContentTabHelper::CreateForWebContents(web_contents); #endif #if defined(OS_WIN) || defined(OS_MAC) || \
diff --git a/chrome/browser/ui/tab_helpers.h b/chrome/browser/ui/tab_helpers.h index 4652957..fb9d771 100644 --- a/chrome/browser/ui/tab_helpers.h +++ b/chrome/browser/ui/tab_helpers.h
@@ -18,7 +18,7 @@ } namespace prerender { -class PrerenderContents; +class ChromePrerenderContentsDelegate; } namespace thin_webview { @@ -56,7 +56,7 @@ // Prerendering loads pages that have arbitrary external content; it needs // the full set of tab helpers to deal with it. - friend class prerender::PrerenderContents; + friend class prerender::ChromePrerenderContentsDelegate; // ThinWebView is used to host WebContents on non-tab UIs in Android. Most // clients of ThinWebView will need a major subset of the tab helpers.
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble.cc b/chrome/browser/ui/views/accessibility/caption_bubble.cc index ee2bbba..aee33ad 100644 --- a/chrome/browser/ui/views/accessibility/caption_bubble.cc +++ b/chrome/browser/ui/views/accessibility/caption_bubble.cc
@@ -539,6 +539,16 @@ Redraw(); } +void CaptionBubble::OnReadyChanged() { + // There is a bug in RenderText in which the label text must not be empty when + // it is displayed, or otherwise subsequent calculation of the number of lines + // (CaptionBubble::GetNumLinesInLabel) will be incorrect. The label text here + // is set to a space character. + // TODO(1055150): Fix the bug in RenderText and then remove this workaround. + label_->SetText(base::ASCIIToUTF16("\u0020")); + UpdateBubbleAndWaitTextVisibility(); +} + void CaptionBubble::OnIsExpandedChanged() { expand_button_->SetVisible(!is_expanded_); collapse_button_->SetVisible(is_expanded_); @@ -566,14 +576,14 @@ // Hide the widget if there is no room for it or the model is closed. if (GetWidget()->IsVisible()) GetWidget()->Hide(); - } else if (label_->GetText().size() > 0 || model_->HasError()) { - // Show the widget if it has text or an error to display. Only show the - // widget if it isn't already visible. Always calling Widget::Show() will - // mean the widget gets focus each time. + } else if (model_->IsReady() || model_->HasError()) { + // Show the widget if it is ready to receive transcriptions or it has an + // error to display. Only show the widget if it isn't already visible. + // Always calling Widget::Show() will mean the widget gets focus each time. if (!GetWidget()->IsVisible()) GetWidget()->Show(); } else if (GetWidget()->IsVisible()) { - // No text and no error. Hide it. + // Not ready and no error. Hide it. GetWidget()->Hide(); } }
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble.h b/chrome/browser/ui/views/accessibility/caption_bubble.h index 0015a47..70d3fdd 100644 --- a/chrome/browser/ui/views/accessibility/caption_bubble.h +++ b/chrome/browser/ui/views/accessibility/caption_bubble.h
@@ -103,6 +103,11 @@ // the model has an error, otherwise displays the latest text. void OnErrorChanged(); + // Called by the CaptionBubbleModel to notify this object that the model's + // on ready state has changed. Makes the caption bubble become visible and + // show the wait text. + void OnReadyChanged(); + // Called when the caption bubble expanded state has changed. Changes the // number of lines displayed. void OnIsExpandedChanged();
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.cc b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.cc index 00f762f..2392db1 100644 --- a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.cc +++ b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.cc
@@ -69,6 +69,18 @@ browser_ = nullptr; } +bool CaptionBubbleControllerViews::OnSpeechRecognitionReady( + content::WebContents* web_contents) { + if (!caption_bubble_ || !caption_bubble_models_.count(web_contents) || + caption_bubble_models_[web_contents]->IsClosed()) + return false; + + CaptionBubbleModel* caption_bubble_model = + caption_bubble_models_[web_contents].get(); + caption_bubble_model->OnReady(); + return true; +} + bool CaptionBubbleControllerViews::OnTranscription( const chrome::mojom::TranscriptionResultPtr& transcription_result, content::WebContents* web_contents) {
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.h b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.h index 1ff69ed..d95d82cd 100644 --- a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.h +++ b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.h
@@ -38,6 +38,8 @@ CaptionBubbleControllerViews& operator=(const CaptionBubbleControllerViews&) = delete; + bool OnSpeechRecognitionReady(content::WebContents* web_contents) override; + // Called when a transcription is received from the service. Returns whether // the transcription result was set on the caption bubble successfully. // Transcriptions will halt if this returns false.
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc index f957580..32bd66f 100644 --- a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc +++ b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
@@ -136,6 +136,11 @@ browser()->tab_strip_model()->GetWebContentsAt(tab_index)); } + bool OnSpeechRecognitionReady(int tab_index = 0) { + return GetController()->OnSpeechRecognitionReady( + browser()->tab_strip_model()->GetWebContentsAt(tab_index)); + } + void ActivateTabAt(int index) { browser()->tab_strip_model()->ActivateTabAt(index); } @@ -162,33 +167,27 @@ }; IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, ShowsCaptionInBubble) { + OnSpeechRecognitionReady(); OnPartialTranscription("Taylor"); EXPECT_TRUE(IsWidgetVisible()); EXPECT_EQ("Taylor", GetLabelText()); - OnPartialTranscription( - "Taylor Alison Swift (born December 13, " - "1989)"); - EXPECT_EQ("Taylor Alison Swift (born December 13, 1989)", GetLabelText()); + OnPartialTranscription("Taylor Alison Swift\n(born December 13, 1989)"); + EXPECT_EQ("Taylor Alison Swift\n(born December 13, 1989)", GetLabelText()); + EXPECT_FALSE(GetWaitText()->GetVisible()); - // Hides the bubble when set to the empty string. + // The bubble is still visible when set to the empty string. The wait text + // becomes visible. OnPartialTranscription(""); - EXPECT_FALSE(IsWidgetVisible()); - - // Shows it again when the caption is no longer empty. - OnPartialTranscription( - "Taylor Alison Swift (born December 13, " - "1989) is an American singer-songwriter."); EXPECT_TRUE(IsWidgetVisible()); - EXPECT_EQ( - "Taylor Alison Swift (born December 13, 1989) is an American " - "singer-songwriter.", - GetLabelText()); + EXPECT_EQ("", GetLabelText()); + EXPECT_TRUE(GetWaitText()->GetVisible()); } IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, LaysOutCaptionLabel) { // A short caption is bottom-aligned with the bubble. The bubble bounds // are inset by 18 dip on the the sides and 24 dip on the bottom. The label // top can change, but the bubble height and width should not change. + OnSpeechRecognitionReady(); OnPartialTranscription("Cats rock"); gfx::Rect label_bounds = GetLabel()->GetBoundsInScreen(); gfx::Rect bubble_bounds = GetBubble()->GetBoundsInScreen(); @@ -217,6 +216,9 @@ IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, CaptionWaitTextShownAtFirst) { + OnSpeechRecognitionReady(); + EXPECT_TRUE(GetWaitText()->GetVisible()); + // With one line of text, the wait text is visible and positioned between the // top of the bubble and top of the label. OnPartialTranscription("Cats rock"); @@ -226,6 +228,14 @@ OnPartialTranscription("Cats rock\nDogs too"); EXPECT_FALSE(GetWaitText()->GetVisible()); + + OnPartialTranscription( + "Taylor Alison Swift (born December 13, 1989) is an American " + "singer-songwriter. She is known for narrative songs about her personal " + "life, which have received widespread media coverage. At age 14, Swift " + "became the youngest artist signed by the Sony/ATV Music publishing " + "house and, at age 15, she signed her first record deal."); + EXPECT_FALSE(GetWaitText()->GetVisible()); } IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, BubblePositioning) { @@ -235,6 +245,7 @@ BrowserView::GetBrowserViewForBrowser(browser())->GetContentsView(); browser()->window()->SetBounds(gfx::Rect(10, 10, 800, 600)); + OnSpeechRecognitionReady(); OnPartialTranscription("Mantis shrimp have 12-16 photoreceptors"); ExpectInBottomCenter(contents_view->GetBoundsInScreen(), GetCaptionWidget()->GetClientAreaBoundsInScreen()); @@ -363,6 +374,7 @@ } IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, ShowsAndHidesError) { + OnSpeechRecognitionReady(); OnPartialTranscription("Elephants' trunks average 6 feet long."); EXPECT_TRUE(GetWaitText()->GetVisible()); EXPECT_TRUE(GetLabel()->GetVisible()); @@ -387,7 +399,9 @@ } IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, CloseButtonCloses) { - bool success = OnFinalTranscription("Elephants have 3-4 toenails per foot"); + bool success = OnSpeechRecognitionReady(); + EXPECT_TRUE(success); + success = OnFinalTranscription("Elephants have 3-4 toenails per foot"); EXPECT_TRUE(success); EXPECT_TRUE(GetCaptionWidget()); EXPECT_TRUE(IsWidgetVisible()); @@ -395,6 +409,8 @@ ClickButton(GetCloseButton()); EXPECT_TRUE(GetCaptionWidget()); EXPECT_FALSE(IsWidgetVisible()); + success = OnSpeechRecognitionReady(); + EXPECT_FALSE(success); success = OnFinalTranscription( "Elephants wander 35 miles a day in search of water"); EXPECT_FALSE(success); @@ -403,7 +419,9 @@ IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, MovesWithArrowsWhenFocused) { - OnPartialTranscription("Nearly all ants are female."); + OnSpeechRecognitionReady(); + OnPartialTranscription( + "Honeybees have tiny hairs on their eyes to help them collect pollen"); // Not focused initially. EXPECT_FALSE(GetBubble()->HasFocus()); @@ -452,6 +470,7 @@ } IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, FocusableInTabOrder) { + OnSpeechRecognitionReady(); OnPartialTranscription( "A narwhal's tusk is an enlarged tooth containing " "millions of nerve endings"); @@ -518,6 +537,7 @@ int errorIconHeight = 20; GetController()->UpdateCaptionStyle(base::nullopt); + OnSpeechRecognitionReady(); OnPartialTranscription("Hamsters' teeth never stop growing"); EXPECT_EQ(textSize, GetLabel()->font_list().GetFontSize()); EXPECT_EQ(textSize, GetWaitText()->font_list().GetFontSize()); @@ -581,6 +601,7 @@ IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, PartialAndFinalTranscriptions) { + OnSpeechRecognitionReady(); OnPartialTranscription("No"); EXPECT_EQ("No", GetLabelText()); OnPartialTranscription("No human"); @@ -608,29 +629,25 @@ SetHasError(false); EXPECT_FALSE(IsWidgetVisible()); - // It is shown if there is text, and hidden if the text is removed. + // It is shown if the bubble is ready and should not show if it is not. OnPartialTranscription("Newborn kangaroos are less than 1 in long"); + EXPECT_FALSE(IsWidgetVisible()); + // Visible when the bubble is ready. + OnSpeechRecognitionReady(); EXPECT_TRUE(IsWidgetVisible()); - // Stays visible when switching to an error state. - SetHasError(true); - EXPECT_TRUE(IsWidgetVisible()); - // Even if the text is removed, because of the error. + // Even if the text is removed, still visible because it is ready. OnFinalTranscription(""); EXPECT_TRUE(IsWidgetVisible()); - // No error and no text means not visible. - SetHasError(false); - EXPECT_FALSE(IsWidgetVisible()); #if !defined(OS_MAC) // Shrink it so small the caption bubble can't fit. Ensure it's hidden. // Mac windows cannot be shrunk small enough to force the bubble to hide. - SetHasError(false); browser()->window()->SetBounds(gfx::Rect(50, 50, 200, 100)); EXPECT_FALSE(IsWidgetVisible()); // Make it bigger again and ensure it's still not visible. browser()->window()->SetBounds(gfx::Rect(50, 50, 800, 400)); - EXPECT_FALSE(IsWidgetVisible()); + EXPECT_TRUE(IsWidgetVisible()); // Now set some text, and ensure it hides when shrunk but re-shows when // grown. @@ -655,6 +672,7 @@ // Tab 1 will have the text "A snail can sleep for three years". // Tab 2 will have the text "A rhino's horn is made of hair". + OnSpeechRecognitionReady(0); OnPartialTranscription("Polar bears are the largest carnivores on land", 0); EXPECT_TRUE(IsWidgetVisible()); EXPECT_EQ("Polar bears are the largest carnivores on land", GetLabelText()); @@ -672,6 +690,7 @@ // Switch back to tab 1 and send transcriptions. ActivateTabAt(1); + OnSpeechRecognitionReady(1); OnFinalTranscription("A snail can sleep", 1); OnPartialTranscription("for two years", 1); EXPECT_TRUE(IsWidgetVisible()); @@ -679,6 +698,7 @@ // Send a transcription to tab 2 before activating it. InsertNewTab(); + OnSpeechRecognitionReady(2); OnPartialTranscription("A rhino's horn is made of hair", 2); ActivateTabAt(2); EXPECT_TRUE(IsWidgetVisible()); @@ -720,6 +740,7 @@ for (int i = 10; i < 40; i++) { text += base::NumberToString(i) + line + " "; } + OnSpeechRecognitionReady(); OnFinalTranscription(text); EXPECT_EQ(text.substr(10500, 15000), GetLabelText()); EXPECT_EQ(9u, GetBubble()->GetNumLinesInLabel()); @@ -735,6 +756,7 @@ ui_test_utils::NavigateToURL(browser(), GURL("http://www.google.com")); content::WaitForLoadStop( browser()->tab_strip_model()->GetActiveWebContents()); + OnSpeechRecognitionReady(); OnFinalTranscription("Elephant calves can stand within 20 minutes of birth"); EXPECT_TRUE(IsWidgetVisible()); EXPECT_EQ("Elephant calves can stand within 20 minutes of birth", @@ -748,6 +770,7 @@ // The caption bubble reappears when a transcription is received on the new // page. + OnSpeechRecognitionReady(); OnFinalTranscription("A group of toads is called a knot"); EXPECT_TRUE(IsWidgetVisible()); EXPECT_EQ("A group of toads is called a knot", GetLabelText()); @@ -759,6 +782,7 @@ EXPECT_FALSE(IsWidgetVisible()); // The caption bubble reappears when a transcription is received. + OnSpeechRecognitionReady(); OnFinalTranscription("Lemurs, like dogs, have wet noses"); EXPECT_TRUE(IsWidgetVisible()); EXPECT_EQ("Lemurs, like dogs, have wet noses", GetLabelText()); @@ -770,6 +794,7 @@ EXPECT_FALSE(IsWidgetVisible()); // The caption bubble reappears when a transcription is received. + OnSpeechRecognitionReady(); OnFinalTranscription("A blue whale's tongue weighs more than most elephants"); EXPECT_TRUE(IsWidgetVisible()); EXPECT_EQ("A blue whale's tongue weighs more than most elephants", @@ -782,6 +807,7 @@ EXPECT_FALSE(IsWidgetVisible()); // The caption bubble reappears when a transcription is received. + OnSpeechRecognitionReady(); OnFinalTranscription("All polar bears are left-pawed"); EXPECT_TRUE(IsWidgetVisible()); EXPECT_EQ("All polar bears are left-pawed", GetLabelText()); @@ -794,6 +820,7 @@ content::WaitForLoadStop( browser()->tab_strip_model()->GetActiveWebContents()); EXPECT_FALSE(IsWidgetVisible()); + OnSpeechRecognitionReady(); OnFinalTranscription("Rats laugh when they are tickled"); EXPECT_TRUE(IsWidgetVisible()); EXPECT_EQ("Rats laugh when they are tickled", GetLabelText()); @@ -810,9 +837,11 @@ IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, DestroysWithoutCrashing) { // Test passes if destroying the controller does not crash. + OnSpeechRecognitionReady(); OnPartialTranscription("Deer have a four-chambered stomach"); DestroyController(); + OnSpeechRecognitionReady(); OnPartialTranscription("Deer antlers fall off and regrow every year"); ClickButton(GetCloseButton()); DestroyController(); @@ -821,6 +850,7 @@ IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, ExpandsAndCollapses) { int line_height = 24; + OnSpeechRecognitionReady(); OnPartialTranscription("Seahorses are monogamous"); EXPECT_TRUE(GetExpandButton()->GetVisible()); EXPECT_FALSE(GetCollapseButton()->GetVisible()); @@ -836,8 +866,8 @@ ActivateTabAt(1); EXPECT_FALSE(IsWidgetVisible()); - OnPartialTranscription( - "Honeybees have tiny hairs on their eyes to help them collect pollen"); + OnSpeechRecognitionReady(1); + OnPartialTranscription("Nearly all ants are female."); EXPECT_TRUE(GetCollapseButton()->GetVisible()); EXPECT_FALSE(GetExpandButton()->GetVisible()); EXPECT_EQ(7 * line_height, GetLabel()->GetBoundsInScreen().height());
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_model.cc b/chrome/browser/ui/views/accessibility/caption_bubble_model.cc index b86ad571..0df6fab 100644 --- a/chrome/browser/ui/views/accessibility/caption_bubble_model.cc +++ b/chrome/browser/ui/views/accessibility/caption_bubble_model.cc
@@ -29,6 +29,7 @@ return; observer_ = observer; if (observer_) { + observer_->OnReadyChanged(); observer_->OnTextChanged(); observer_->OnErrorChanged(); } @@ -52,9 +53,23 @@ final_text_.clear(); partial_text_.clear(); is_closed_ = true; + is_ready_ = false; OnTextChanged(); } +void CaptionBubbleModel::OnReady() { + final_text_.clear(); + partial_text_.clear(); + is_ready_ = true; + // The label text must not be empty when it is displayed, so there is a + // special OnReadyChanged() function in the CaptionBubble that handles the + // on_ready state change. + // TODO(1055150): Fix the bug in RenderText and then change this to + // OnTextChanged(). + if (observer_) + observer_->OnReadyChanged(); +} + void CaptionBubbleModel::SetHasError(bool has_error) { has_error_ = has_error; if (observer_) @@ -70,6 +85,7 @@ final_text_.clear(); partial_text_.clear(); is_closed_ = false; + is_ready_ = false; has_error_ = false; OnTextChanged(); }
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_model.h b/chrome/browser/ui/views/accessibility/caption_bubble_model.h index e1a8765c..8356693 100644 --- a/chrome/browser/ui/views/accessibility/caption_bubble_model.h +++ b/chrome/browser/ui/views/accessibility/caption_bubble_model.h
@@ -57,7 +57,10 @@ // observer. void Close(); + void OnReady(); + bool IsClosed() const { return is_closed_; } + bool IsReady() const { return is_ready_; } bool HasError() const { return has_error_; } std::string GetFullText() const { return final_text_ + partial_text_; } @@ -76,6 +79,9 @@ // Whether the bubble has been closed by the user. bool is_closed_ = false; + // Whether bubble is ready to receive transcriptions. + bool is_ready_ = false; + // Whether an error should be displayed one the bubble. bool has_error_ = false;
diff --git a/chrome/browser/ui/views/collected_cookies_views.cc b/chrome/browser/ui/views/collected_cookies_views.cc index 088df85..e3b52d5 100644 --- a/chrome/browser/ui/views/collected_cookies_views.cc +++ b/chrome/browser/ui/views/collected_cookies_views.cc
@@ -415,9 +415,11 @@ } std::unique_ptr<views::View> CollectedCookiesViews::CreateAllowedPane() { + // This captures a snapshot of the allowed cookies of the current page so we + // are fine using WebContents::GetMainFrame() here content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents_); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents_->GetMainFrame()); // Create the controls that go into the pane. auto allowed_label = std::make_unique<views::Label>( @@ -473,8 +475,8 @@ std::unique_ptr<views::View> CollectedCookiesViews::CreateBlockedPane() { content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents_); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents_->GetMainFrame()); Profile* profile = Profile::FromBrowserContext(web_contents_->GetBrowserContext());
diff --git a/chrome/browser/ui/views/frame/browser_view_browsertest.cc b/chrome/browser/ui/views/frame/browser_view_browsertest.cc index df3b123..c72879d 100644 --- a/chrome/browser/ui/views/frame/browser_view_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_view_browsertest.cc
@@ -397,9 +397,11 @@ caption_controller->GetCaptionBubbleControllerForBrowser(browser())); EXPECT_FALSE(bubble_controller->GetFocusableCaptionBubble()); + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + caption_controller->OnSpeechRecognitionReady(contents); caption_controller->DispatchTranscription( - browser()->tab_strip_model()->GetActiveWebContents(), - chrome::mojom::TranscriptionResult::New("Hello, world", false)); + contents, chrome::mojom::TranscriptionResult::New("Hello, world", false)); // Now the caption bubble exists but is not focused. views::View* bubble = bubble_controller->GetFocusableCaptionBubble(); EXPECT_TRUE(bubble);
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc index 0910246..818abb8 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -536,11 +536,6 @@ : frame()->GetMinimizeButtonOffset(); } -bool GlassBrowserFrameView::IsToolbarVisible() const { - return browser_view()->IsToolbarVisible() && - !browser_view()->toolbar()->GetPreferredSize().IsEmpty(); -} - bool GlassBrowserFrameView::ShowCustomIcon() const { // Web-app windows don't include the window icon as per UI mocks. return !web_app_frame_toolbar() && ShouldCustomDrawSystemTitlebar() &&
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h index 966e712..9ee97faa 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -117,9 +117,6 @@ // edge of the caption buttons. int MinimizeButtonX() const; - // Returns whether the toolbar is currently visible. - bool IsToolbarVisible() const; - bool ShowCustomIcon() const; bool ShowCustomTitle() const; bool ShowSystemIcon() const;
diff --git a/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc b/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc index 3aab5544..abb8e0da 100644 --- a/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc
@@ -106,8 +106,8 @@ ? content_settings::TabSpecificContentSettings::CAMERA_ACCESSED : 0; content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::FromWebContents( - browser()->tab_strip_model()->GetActiveWebContents()); + content_settings::TabSpecificContentSettings::GetForFrame( + browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()); content_settings->OnMediaStreamPermissionSet( GURL("https://example.com/"), mic_setting | camera_setting, std::string(), std::string(), std::string(), std::string()); @@ -118,8 +118,8 @@ content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents->GetMainFrame()); switch (content_type) { case ContentSettingsType::AUTOMATIC_DOWNLOADS: { // Automatic downloads are handled by DownloadRequestLimiter.
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc index 0f8e82a1..adfd31f 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -305,8 +305,7 @@ // Sets up tests for the simplified domain field trials. void SetUpSimplifiedDomainTest() { - location_bar_model()->set_url( - GURL(base::ASCIIToUTF16("https://") + kSimplifiedDomainDisplayUrl)); + location_bar_model()->set_url(GURL(kSimplifiedDomainDisplayUrl)); location_bar_model()->set_url_for_display(kSimplifiedDomainDisplayUrl); omnibox_view()->model()->ResetDisplayTexts(); omnibox_view()->RevertAll(); @@ -1417,14 +1416,14 @@ // |subdomain_and_scheme| and |subdomain| should include a trailing ".", and // |path| should include a leading "/". void ExpectElidedToSimplifiedDomain(gfx::RenderText* render_text, - const base::string16& subdomain_and_scheme, + const base::string16& scheme, const base::string16& subdomain, const base::string16& hostname_and_scheme, const base::string16& path, bool should_elide_to_registrable_domain) { gfx::Rect subdomain_and_scheme_rect; for (const auto& rect : render_text->GetSubstringBounds( - gfx::Range(0, subdomain_and_scheme.size()))) { + gfx::Range(0, scheme.size() + subdomain.size()))) { subdomain_and_scheme_rect.Union(rect); } gfx::Rect path_rect; @@ -1437,20 +1436,38 @@ if (should_elide_to_registrable_domain) { EXPECT_FALSE( render_text->display_rect().Contains(subdomain_and_scheme_rect)); - EXPECT_EQ(subdomain_and_scheme_rect.width(), + gfx::Rect registrable_domain_rect; + for (const auto& rect : render_text->GetSubstringBounds(gfx::Range( + scheme.size() + subdomain.size(), hostname_and_scheme.size()))) { + registrable_domain_rect.Union(rect); + } + EXPECT_TRUE(render_text->display_rect().Contains(registrable_domain_rect)); + // The text should be scrolled to push the scheme and subdomain offscreen, + // so that the text starts at the registrable domain. Note that this code + // computes the expected offset by comparing x() values rather than + // comparing based on widths (for example, it wouldn't work to check that + // the display offset is equal to |subdomain_and_scheme_rect|'s width). This + // is because GetSubstringBounds() rounds outward, so the width of + // |subdomain_and_scheme_rect| could slightly overlap + // |registrable_domain_rect|. + EXPECT_EQ(registrable_domain_rect.x() - subdomain_and_scheme_rect.x(), -1 * render_text->GetUpdatedDisplayOffset().x()); } else { // When elision to registrable domain is disabled, the scheme should be // hidden but the subdomain should not be. EXPECT_FALSE( render_text->display_rect().Contains(subdomain_and_scheme_rect)); - gfx::Rect subdomain_rect; - for (const auto& rect : - render_text->GetSubstringBounds(gfx::Range(0, subdomain.size()))) { - subdomain_rect.Union(rect); + gfx::Rect hostname_rect; + for (const auto& rect : render_text->GetSubstringBounds( + gfx::Range(scheme.size(), hostname_and_scheme.size()))) { + hostname_rect.Union(rect); } - EXPECT_EQ(subdomain_rect.x() - render_text->display_rect().x(), - render_text->GetUpdatedDisplayOffset().x()); + // The text should be scrolled to push the scheme offscreen, so that the + // text starts at the subdomain. As above, it's important to compute the + // expected offset with x() values instead of width()s, since the width()s + // of different adjacent substring bounds could overlap. + EXPECT_EQ(hostname_rect.x() - subdomain_and_scheme_rect.x(), + -1 * render_text->GetUpdatedDisplayOffset().x()); } } @@ -1573,7 +1590,7 @@ SetUpSimplifiedDomainTest(); gfx::RenderText* render_text = omnibox_view()->GetRenderText(); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -1598,7 +1615,7 @@ // After the extended hover threshold has elapsed, the display text shouldn't // have changed yet. ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -1626,7 +1643,7 @@ hover_animation_as_element->Step(base::TimeTicks() + base::TimeDelta::FromSeconds(1)); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -1698,7 +1715,7 @@ elide_as_element->SetStartTime(base::TimeTicks()); elide_as_element->Step(base::TimeTicks() + base::TimeDelta::FromSeconds(1)); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -1804,7 +1821,7 @@ EXPECT_TRUE(elide_animation->IsAnimating()); omnibox_view()->OnBoundsChanged(gfx::Rect()); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -1817,7 +1834,7 @@ gfx::RenderText* render_text = omnibox_view()->GetRenderText(); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -1825,7 +1842,7 @@ // After the bounds change, the URL should remain elided. omnibox_view()->OnBoundsChanged(gfx::Rect()); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -1840,7 +1857,7 @@ EXPECT_TRUE(unelide_animation->IsAnimating()); omnibox_view()->OnBoundsChanged(gfx::Rect()); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -1915,11 +1932,14 @@ elide_animation->GetAnimationForTesting()); elide_as_element->SetStartTime(base::TimeTicks()); elide_as_element->Step(base::TimeTicks() + base::TimeDelta::FromSeconds(2)); + // Use should_elide_to_registrable_domain=true here regardless of how the + // field trial is set because the "www." should be elided as a trivial + // subdomain. ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, base::ASCIIToUTF16("https://www."), - base::ASCIIToUTF16("www."), + render_text, base::ASCIIToUTF16("https://"), base::ASCIIToUTF16("www."), base::ASCIIToUTF16("https://www.example.test"), - base::ASCIIToUTF16("/foo"), ShouldElideToRegistrableDomain())); + base::ASCIIToUTF16("/foo"), + /* should_elide_to_registrable_domain=*/true)); // Do another hover and check that the URL gets unelided to the full URL. omnibox_view()->OnMouseMoved(CreateMouseEvent(ui::ET_MOUSE_MOVED, {0, 0})); @@ -1946,10 +1966,10 @@ elide_as_element->SetStartTime(base::TimeTicks()); elide_as_element->Step(base::TimeTicks() + base::TimeDelta::FromSeconds(2)); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, base::ASCIIToUTF16("https://www."), - base::ASCIIToUTF16("www."), + render_text, base::ASCIIToUTF16("https://"), base::ASCIIToUTF16("www."), base::ASCIIToUTF16("https://www.example.test"), - base::ASCIIToUTF16("/foo"), ShouldElideToRegistrableDomain())); + base::ASCIIToUTF16("/foo"), + /* should_elide_to_registrable_domain=*/true)); EXPECT_EQ(SK_ColorTRANSPARENT, omnibox_view()->GetLatestColorForRange( gfx::Range(0, kSchemeAndSubdomainSize))); } @@ -2124,8 +2144,7 @@ // to the registrable domain because the www subdomain is considered // trivial. ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, base::ASCIIToUTF16("https://www."), - base::ASCIIToUTF16("www."), + render_text, base::ASCIIToUTF16("https://"), base::ASCIIToUTF16("www."), base::ASCIIToUTF16("https://www.example.test"), base::ASCIIToUTF16("/foo"), true /* should elide to registrable domain */)); @@ -2338,7 +2357,7 @@ elide_as_element->SetStartTime(base::TimeTicks()); elide_as_element->Step(base::TimeTicks() + base::TimeDelta::FromSeconds(1)); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -2350,7 +2369,7 @@ navigation.set_is_same_document(true); omnibox_view()->DidFinishNavigation(&navigation); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -2508,7 +2527,7 @@ elide_as_element->SetStartTime(base::TimeTicks()); elide_as_element->Step(base::TimeTicks() + base::TimeDelta::FromSeconds(1)); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -2528,7 +2547,7 @@ navigation.set_render_frame_host(subframe); omnibox_view()->DidFinishNavigation(&navigation); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -2555,7 +2574,7 @@ elide_as_element->SetStartTime(base::TimeTicks()); elide_as_element->Step(base::TimeTicks() + base::TimeDelta::FromSeconds(1)); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme, + render_text, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); @@ -2602,8 +2621,7 @@ omnibox_view()->OnFocus(); omnibox_view()->OnBlur(); ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( - omnibox_view()->GetRenderText(), - kSimplifiedDomainDisplayUrlSubdomainAndScheme, + omnibox_view()->GetRenderText(), kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain()));
diff --git a/chrome/browser/ui/webui/discards/DEPS b/chrome/browser/ui/webui/discards/DEPS new file mode 100644 index 0000000..43d1a4a --- /dev/null +++ b/chrome/browser/ui/webui/discards/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+components/performance_manager/persistence/site_data", +]
diff --git a/chrome/browser/ui/webui/discards/discards_ui.cc b/chrome/browser/ui/webui/discards/discards_ui.cc index 95448e0..74a7a2a 100644 --- a/chrome/browser/ui/webui/discards/discards_ui.cc +++ b/chrome/browser/ui/webui/discards/discards_ui.cc
@@ -18,7 +18,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/resource_coordinator/lifecycle_unit.h" #include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h" #include "chrome/browser/resource_coordinator/tab_activity_watcher.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h" #include "chrome/browser/resource_coordinator/tab_manager.h" @@ -46,10 +45,6 @@ #include "url/gurl.h" #include "url/origin.h" -namespace resource_coordinator { -class LocalSiteCharacteristicsDataStoreInspector; -} // namespace resource_coordinator - namespace { discards::mojom::LifecycleUnitVisibility GetLifecycleUnitVisibility( @@ -258,8 +253,7 @@ profile, std::make_unique<FaviconSource>( profile, chrome::FaviconUrlFormat::kFavicon2)); - data_store_inspector_ = resource_coordinator:: - LocalSiteCharacteristicsDataStoreInspector::GetForProfile(profile); + profile_id_ = profile->UniqueId(); } WEB_UI_CONTROLLER_TYPE_IMPL(DiscardsUI) @@ -274,8 +268,12 @@ void DiscardsUI::BindInterface( mojo::PendingReceiver<discards::mojom::SiteDataProvider> receiver) { - site_data_provider_ = std::make_unique<SiteDataProviderImpl>( - data_store_inspector_, std::move(receiver)); + if (performance_manager::PerformanceManager::IsAvailable()) { + // Forward the interface receiver directly to the service. + performance_manager::PerformanceManager::CallOnGraph( + FROM_HERE, base::BindOnce(&SiteDataProviderImpl::CreateAndBind, + std::move(receiver), profile_id_)); + } } void DiscardsUI::BindInterface(
diff --git a/chrome/browser/ui/webui/discards/discards_ui.h b/chrome/browser/ui/webui/discards/discards_ui.h index f454366..9f9baf3 100644 --- a/chrome/browser/ui/webui/discards/discards_ui.h +++ b/chrome/browser/ui/webui/discards/discards_ui.h
@@ -13,10 +13,6 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "ui/webui/mojo_web_ui_controller.h" -namespace resource_coordinator { -class LocalSiteCharacteristicsDataStoreInspector; -} // namespace resource_coordinator - // Controller for chrome://discards. Corresponding resources are in // file://chrome/browser/resources/discards. class DiscardsUI : public ui::MojoWebUIController { @@ -42,8 +38,7 @@ private: std::unique_ptr<discards::mojom::DetailsProvider> ui_handler_; std::unique_ptr<discards::mojom::SiteDataProvider> site_data_provider_; - resource_coordinator::LocalSiteCharacteristicsDataStoreInspector* - data_store_inspector_; + std::string profile_id_; WEB_UI_CONTROLLER_TYPE_DECL();
diff --git a/chrome/browser/ui/webui/discards/graph_dump_impl.h b/chrome/browser/ui/webui/discards/graph_dump_impl.h index d01ba675..79b4762 100644 --- a/chrome/browser/ui/webui/discards/graph_dump_impl.h +++ b/chrome/browser/ui/webui/discards/graph_dump_impl.h
@@ -213,9 +213,6 @@ int64_t serialization_id, scoped_refptr<base::RefCountedMemory> bitmap_data); - static void BindOnPMSequence( - mojo::PendingReceiver<discards::mojom::GraphDump> receiver, - performance_manager::Graph* graph); static void OnConnectionError(DiscardsGraphDumpImpl* impl); performance_manager::Graph* graph_ = nullptr;
diff --git a/chrome/browser/ui/webui/discards/site_data.mojom b/chrome/browser/ui/webui/discards/site_data.mojom index 1084c80..cb24e09 100644 --- a/chrome/browser/ui/webui/discards/site_data.mojom +++ b/chrome/browser/ui/webui/discards/site_data.mojom
@@ -4,7 +4,7 @@ module discards.mojom; -struct SiteCharacteristicsFeature { +struct SiteDataFeature { // The cumulative observation time for this feature in seconds, set to 0 once // this feature has been observed. int64 observation_duration; @@ -13,7 +13,7 @@ int64 use_timestamp; }; -struct SiteCharacteristicsPerformanceMeasurement { +struct SiteDataPerformanceMeasurement { // A decaying average of the CPU usage measurements. Units: microseconds. float avg_cpu_usage_us; // A decaying average of the process footprint measurements. Units: kilobytes. @@ -23,7 +23,7 @@ float avg_load_duration_us; }; -struct SiteCharacteristicsDatabaseSize { +struct SiteDataDatabaseSize { // The total number of rows in the database, or -1 if the value is not // available. int64 num_rows; @@ -36,24 +36,24 @@ // The data stored for a given origin, this should mirror the // SiteDataProto structure in // performance_manager/persistence/site_data/site_data.proto. -struct SiteCharacteristicsDatabaseValue { +struct SiteDataValue { // The last time this site has been in the loaded state, in seconds since // epoch. uint32 last_loaded; - SiteCharacteristicsFeature updates_favicon_in_background; - SiteCharacteristicsFeature updates_title_in_background; - SiteCharacteristicsFeature uses_audio_in_background; + SiteDataFeature updates_favicon_in_background; + SiteDataFeature updates_title_in_background; + SiteDataFeature uses_audio_in_background; // Load time performance measurement estimates. This maintains a decaying // average of the resource usage of a page until shortly after it becomes // idle. - SiteCharacteristicsPerformanceMeasurement? load_time_estimates; + SiteDataPerformanceMeasurement? load_time_estimates; }; // Provides the key and miscellaneous in-memory only data pertaining to a // row that potentially exists in a database. -struct SiteCharacteristicsDatabaseEntry { +struct SiteDataEntry { // The origin associated with this row. string origin; @@ -61,13 +61,13 @@ bool is_dirty; // NULL if the database entry doesn't exist on disk or in memory. - SiteCharacteristicsDatabaseValue? value; + SiteDataValue? value; }; -// Contains information about a specific DB instance. -struct SiteCharacteristicsDatabase { +// Contains information about a specific set of SiteData entries. +struct SiteDataArray { // Contains the entries requested. - array<SiteCharacteristicsDatabaseEntry> db_rows; + array<SiteDataEntry> db_rows; }; // Interface for providing information about the site data database. Lives in @@ -77,14 +77,14 @@ // Returns the in-memory entries and the entries for the requested origins. // Note that any entry may take some time to load from disk, and so there may // not be any data for a given entry until on the second or subsequent - // requests. The WebUI is expected to poll this function. - GetSiteCharacteristicsDatabase( + // requests. + GetSiteDataArray( array<string> explicitly_requested_origins) => - (SiteCharacteristicsDatabase? result); + (SiteDataArray? result); // Returns the size of the database in number of rows and kilobytes. // Note that this may be fairly expensive to acquire, and so shouldn't be // called frequently. - GetSiteCharacteristicsDatabaseSize() => - (SiteCharacteristicsDatabaseSize? db_size); + GetSiteDataDatabaseSize() => + (SiteDataDatabaseSize? db_size); };
diff --git a/chrome/browser/ui/webui/discards/site_data_provider_impl.cc b/chrome/browser/ui/webui/discards/site_data_provider_impl.cc index 8d701889f..8527dd8 100644 --- a/chrome/browser/ui/webui/discards/site_data_provider_impl.cc +++ b/chrome/browser/ui/webui/discards/site_data_provider_impl.cc
@@ -5,34 +5,46 @@ #include "chrome/browser/ui/webui/discards/site_data_provider_impl.h" #include "base/bind_helpers.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h" +#include "base/sequence_checker.h" +#include "components/performance_manager/persistence/site_data/site_data.pb.h" +#include "components/performance_manager/persistence/site_data/site_data_cache_factory.h" +#include "components/performance_manager/persistence/site_data/site_data_cache_inspector.h" +#include "components/performance_manager/public/graph/graph.h" +#include "components/performance_manager/public/graph/page_node.h" +#include "components/performance_manager/public/persistence/site_data/site_data_reader.h" +#include "url/gurl.h" namespace { -discards::mojom::SiteCharacteristicsFeaturePtr ConvertFeatureFromProto( +discards::mojom::SiteDataFeaturePtr ConvertFeatureFromProto( const SiteDataFeatureProto& proto) { - discards::mojom::SiteCharacteristicsFeaturePtr feature = - discards::mojom::SiteCharacteristicsFeature::New(); + discards::mojom::SiteDataFeaturePtr feature = + discards::mojom::SiteDataFeature::New(); - if (proto.has_observation_duration()) + if (proto.has_observation_duration()) { feature->observation_duration = proto.observation_duration(); + } else { + feature->observation_duration = 0; + } - if (proto.has_use_timestamp()) + if (proto.has_use_timestamp()) { feature->use_timestamp = proto.use_timestamp(); + } else { + feature->use_timestamp = 0; + } return feature; } -discards::mojom::SiteCharacteristicsDatabaseEntryPtr ConvertEntryFromProto( - SiteDataProto* proto) { - discards::mojom::SiteCharacteristicsDatabaseValuePtr value = - discards::mojom::SiteCharacteristicsDatabaseValue::New(); +discards::mojom::SiteDataEntryPtr ConvertEntryFromProto(SiteDataProto* proto) { + discards::mojom::SiteDataValuePtr value = + discards::mojom::SiteDataValue::New(); - if (proto->has_last_loaded()) + if (proto->has_last_loaded()) { value->last_loaded = proto->last_loaded(); - + } else { + value->last_loaded = 0; + } value->updates_favicon_in_background = ConvertFeatureFromProto(proto->updates_favicon_in_background()); value->updates_title_in_background = @@ -45,9 +57,8 @@ DCHECK(load_time_estimates_proto.has_avg_cpu_usage_us()); DCHECK(load_time_estimates_proto.has_avg_footprint_kb()); - discards::mojom::SiteCharacteristicsPerformanceMeasurementPtr - load_time_estimates = - discards::mojom::SiteCharacteristicsPerformanceMeasurement::New(); + discards::mojom::SiteDataPerformanceMeasurementPtr load_time_estimates = + discards::mojom::SiteDataPerformanceMeasurement::New(); if (load_time_estimates_proto.has_avg_cpu_usage_us()) { load_time_estimates->avg_cpu_usage_us = load_time_estimates_proto.avg_cpu_usage_us(); @@ -64,26 +75,42 @@ value->load_time_estimates = std::move(load_time_estimates); } - discards::mojom::SiteCharacteristicsDatabaseEntryPtr entry = - discards::mojom::SiteCharacteristicsDatabaseEntry::New(); + discards::mojom::SiteDataEntryPtr entry = + discards::mojom::SiteDataEntry::New(); entry->value = std::move(value); return entry; } } // namespace -SiteDataProviderImpl::SiteDataProviderImpl( - resource_coordinator::LocalSiteCharacteristicsDataStoreInspector* - data_store_inspector, - mojo::PendingReceiver<discards::mojom::SiteDataProvider> receiver) - : data_store_inspector_(data_store_inspector), - receiver_(this, std::move(receiver)) {} +SiteDataProviderImpl::SiteDataProviderImpl(const std::string& profile_id) + : profile_id_(profile_id) {} SiteDataProviderImpl::~SiteDataProviderImpl() = default; -void SiteDataProviderImpl::GetSiteCharacteristicsDatabase( +// static +void SiteDataProviderImpl::CreateAndBind( + mojo::PendingReceiver<discards::mojom::SiteDataProvider> receiver, + const std::string& profile_id_, + performance_manager::Graph* graph) { + std::unique_ptr<SiteDataProviderImpl> site_data_provider = + std::make_unique<SiteDataProviderImpl>(profile_id_); + + site_data_provider->Bind(std::move(receiver)); + graph->PassToGraph(std::move(site_data_provider)); +} + +void SiteDataProviderImpl::GetSiteDataArray( const std::vector<std::string>& explicitly_requested_origins, - GetSiteCharacteristicsDatabaseCallback callback) { + GetSiteDataArrayCallback callback) { + auto* inspector = performance_manager::SiteDataCacheFactory::GetInstance() + ->GetInspectorForBrowserContext(profile_id_); + if (!inspector) { + // Early return with a nullptr if there's no inspector. + std::move(callback).Run(nullptr); + return; + } + // Move all previously explicitly requested origins to this local map. // Move any currently requested origins over to the member variable, or // populate them if they weren't previously requested. @@ -91,30 +118,31 @@ // this function. OriginToReaderMap prev_requested_origins; prev_requested_origins.swap(requested_origins_); - resource_coordinator::SiteCharacteristicsDataStore* data_store = - data_store_inspector_->GetDataStore(); - DCHECK(data_store); + performance_manager::SiteDataCache* data_cache = inspector->GetDataCache(); + DCHECK(data_cache); + for (const std::string& origin : explicitly_requested_origins) { auto it = prev_requested_origins.find(origin); if (it == prev_requested_origins.end()) { GURL url(origin); requested_origins_[origin] = - data_store->GetReaderForOrigin(url::Origin::Create(url)); + data_cache->GetReaderForOrigin(url::Origin::Create(url)); } else { requested_origins_[origin] = std::move(it->second); + prev_requested_origins.erase(it); } } - discards::mojom::SiteCharacteristicsDatabasePtr result = - discards::mojom::SiteCharacteristicsDatabase::New(); + discards::mojom::SiteDataArrayPtr result = + discards::mojom::SiteDataArray::New(); std::vector<url::Origin> in_memory_origins = - data_store_inspector_->GetAllInMemoryOrigins(); + inspector->GetAllInMemoryOrigins(); for (const url::Origin& origin : in_memory_origins) { // Get the data for this origin and convert it from proto to the // corresponding mojo structure. std::unique_ptr<SiteDataProto> proto; bool is_dirty = false; - if (data_store_inspector_->GetDataForOrigin(origin, &is_dirty, &proto)) { + if (inspector->GetDataForOrigin(origin, &is_dirty, &proto)) { auto entry = ConvertEntryFromProto(proto.get()); entry->origin = origin.Serialize(); entry->is_dirty = is_dirty; @@ -126,15 +154,23 @@ std::move(callback).Run(std::move(result)); } -void SiteDataProviderImpl::GetSiteCharacteristicsDatabaseSize( - GetSiteCharacteristicsDatabaseSizeCallback callback) { +void SiteDataProviderImpl::GetSiteDataDatabaseSize( + GetSiteDataDatabaseSizeCallback callback) { + auto* inspector = performance_manager::SiteDataCacheFactory::GetInstance() + ->GetInspectorForBrowserContext(profile_id_); + if (!inspector) { + // Early return with a nullptr if there's no inspector. + std::move(callback).Run(nullptr); + return; + } + // Adapt the inspector callback to the mojom callback with this lambda. auto inspector_callback = base::BindOnce( - [](GetSiteCharacteristicsDatabaseSizeCallback callback, + [](GetSiteDataDatabaseSizeCallback callback, base::Optional<int64_t> num_rows, base::Optional<int64_t> on_disk_size_kb) { - discards::mojom::SiteCharacteristicsDatabaseSizePtr result = - discards::mojom::SiteCharacteristicsDatabaseSize::New(); + discards::mojom::SiteDataDatabaseSizePtr result = + discards::mojom::SiteDataDatabaseSize::New(); result->num_rows = num_rows.has_value() ? num_rows.value() : -1; result->on_disk_size_kb = on_disk_size_kb.has_value() ? on_disk_size_kb.value() : -1; @@ -143,5 +179,28 @@ }, std::move(callback)); - data_store_inspector_->GetDatabaseSize(std::move(inspector_callback)); + inspector->GetDataStoreSize(std::move(inspector_callback)); +} + +// static +void SiteDataProviderImpl::OnConnectionError(SiteDataProviderImpl* impl) { + std::unique_ptr<performance_manager::GraphOwned> owned_impl = + impl->graph_->TakeFromGraph(impl); +} + +void SiteDataProviderImpl::OnPassedToGraph(performance_manager::Graph* graph) { + DCHECK(!graph_); + graph_ = graph; +} + +void SiteDataProviderImpl::OnTakenFromGraph(performance_manager::Graph* graph) { + DCHECK_EQ(graph_, graph); + graph_ = nullptr; +} + +void SiteDataProviderImpl::Bind( + mojo::PendingReceiver<discards::mojom::SiteDataProvider> receiver) { + receiver_.Bind(std::move(receiver)); + receiver_.set_disconnect_handler(base::BindOnce( + &SiteDataProviderImpl::OnConnectionError, base::Unretained(this))); }
diff --git a/chrome/browser/ui/webui/discards/site_data_provider_impl.h b/chrome/browser/ui/webui/discards/site_data_provider_impl.h index 2d67c742..07efc00 100644 --- a/chrome/browser/ui/webui/discards/site_data_provider_impl.h +++ b/chrome/browser/ui/webui/discards/site_data_provider_impl.h
@@ -5,52 +5,64 @@ #ifndef CHROME_BROWSER_UI_WEBUI_DISCARDS_SITE_DATA_PROVIDER_IMPL_H_ #define CHROME_BROWSER_UI_WEBUI_DISCARDS_SITE_DATA_PROVIDER_IMPL_H_ -#include <map> #include <memory> #include "base/sequence_checker.h" #include "chrome/browser/ui/webui/discards/site_data.mojom.h" +#include "components/performance_manager/public/graph/graph.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" -namespace resource_coordinator { -class LocalSiteCharacteristicsDataStoreInspector; -class SiteCharacteristicsDataReader; -} // namespace resource_coordinator +namespace performance_manager { +class Graph; +class SiteDataReader; +} // namespace performance_manager -class SiteDataProviderImpl : public discards::mojom::SiteDataProvider { +class SiteDataProviderImpl : public discards::mojom::SiteDataProvider, + public performance_manager::GraphOwned { public: - SiteDataProviderImpl( - resource_coordinator::LocalSiteCharacteristicsDataStoreInspector* - data_store_inspector, - mojo::PendingReceiver<discards::mojom::SiteDataProvider> receiver); + explicit SiteDataProviderImpl(const std::string& profile_id); ~SiteDataProviderImpl() override; SiteDataProviderImpl(const SiteDataProviderImpl& other) = delete; SiteDataProviderImpl& operator=(const SiteDataProviderImpl&) = delete; - void GetSiteCharacteristicsDatabase( + // Creates a new SiteDataProviderImpl to service |receiver| and passes its + // ownership to |graph|. + static void CreateAndBind( + mojo::PendingReceiver<discards::mojom::SiteDataProvider> receiver, + const std::string& profile_id_, + performance_manager::Graph* graph); + + void GetSiteDataArray( const std::vector<std::string>& explicitly_requested_origins, - GetSiteCharacteristicsDatabaseCallback callback) override; - void GetSiteCharacteristicsDatabaseSize( - GetSiteCharacteristicsDatabaseSizeCallback callback) override; + GetSiteDataArrayCallback callback) override; + void GetSiteDataDatabaseSize( + GetSiteDataDatabaseSizeCallback callback) override; private: - using LocalSiteCharacteristicsDataStoreInspector = - resource_coordinator::LocalSiteCharacteristicsDataStoreInspector; - using SiteCharacteristicsDataReader = - resource_coordinator::SiteCharacteristicsDataReader; + using SiteDataReader = performance_manager::SiteDataReader; using OriginToReaderMap = - std::map<std::string, std::unique_ptr<SiteCharacteristicsDataReader>>; + base::flat_map<std::string, std::unique_ptr<SiteDataReader>>; + + static void OnConnectionError(SiteDataProviderImpl* impl); + + // GraphOwned implementation. + void OnPassedToGraph(performance_manager::Graph* graph) override; + void OnTakenFromGraph(performance_manager::Graph* graph) override; + + // Binds |receiver_| by consuming |receiver|, which must be valid. + void Bind(mojo::PendingReceiver<discards::mojom::SiteDataProvider> receiver); // This map pins requested readers and their associated data in memory until // after the next read finishes. This is necessary to allow the database reads // to go through and populate the requested entries. OriginToReaderMap requested_origins_; - resource_coordinator::LocalSiteCharacteristicsDataStoreInspector* - data_store_inspector_ = nullptr; + std::string profile_id_; + + performance_manager::Graph* graph_ = nullptr; mojo::Receiver<discards::mojom::SiteDataProvider> receiver_{this}; };
diff --git a/chrome/browser/ui/webui/nearby_share/BUILD.gn b/chrome/browser/ui/webui/nearby_share/BUILD.gn index 2f04001..d3d4329 100644 --- a/chrome/browser/ui/webui/nearby_share/BUILD.gn +++ b/chrome/browser/ui/webui/nearby_share/BUILD.gn
@@ -4,10 +4,17 @@ import("//mojo/public/tools/bindings/mojom.gni") +mojom("nearby_share_target_types") { + sources = [ "nearby_share_target_types.mojom" ] +} + mojom("mojom") { sources = [ "nearby_share.mojom" ] - public_deps = [ "//mojo/public/mojom/base" ] + public_deps = [ + ":nearby_share_target_types", + "//mojo/public/mojom/base", + ] cpp_typemaps = [ { @@ -19,6 +26,7 @@ ] traits_headers = [ "nearby_share_mojom_traits.h" ] traits_sources = [ "nearby_share_mojom_traits.cc" ] + traits_deps = [ "//chrome/browser/nearby_sharing:share_target" ] }, ] }
diff --git a/chrome/browser/ui/webui/nearby_share/nearby_share.mojom b/chrome/browser/ui/webui/nearby_share/nearby_share.mojom index aad18b6..edff98d4 100644 --- a/chrome/browser/ui/webui/nearby_share/nearby_share.mojom +++ b/chrome/browser/ui/webui/nearby_share/nearby_share.mojom
@@ -4,20 +4,9 @@ module nearby_share.mojom; +import "chrome/browser/ui/webui/nearby_share/nearby_share_target_types.mojom"; import "mojo/public/mojom/base/unguessable_token.mojom"; -// Describes the type of device for a share target. -enum ShareTargetType { - // Unknown device type. - kUnknown, - // A phone. - kPhone, - // A tablet. - kTablet, - // A laptop. - kLaptop, -}; - // Describes a nearby device that is able to receive data via Nearby Share. struct ShareTarget { // Unique identifier during the current discovery session. The same physical
diff --git a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc index 043562a..8e5076a 100644 --- a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc +++ b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc
@@ -47,8 +47,12 @@ html_source->AddResourcePath("nearby_share.mojom-lite.js", IDR_NEARBY_SHARE_MOJO_JS); + html_source->AddResourcePath("nearby_share_target_types.mojom-lite.js", + IDR_NEARBY_SHARE_TARGET_TYPES_MOJO_JS); RegisterNearbySharedMojoResources(html_source); + RegisterNearbySharedStrings(html_source); + html_source->UseStringsJs(); content::WebUIDataSource::Add(profile, html_source); }
diff --git a/chrome/browser/ui/webui/nearby_share/nearby_share_target_types.mojom b/chrome/browser/ui/webui/nearby_share/nearby_share_target_types.mojom new file mode 100644 index 0000000..64acbb05 --- /dev/null +++ b/chrome/browser/ui/webui/nearby_share/nearby_share_target_types.mojom
@@ -0,0 +1,17 @@ +// Copyright 2020 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 nearby_share.mojom; + +// Describes the type of device for a share target. +enum ShareTargetType { + // Unknown device type. + kUnknown, + // A phone. + kPhone, + // A tablet. + kTablet, + // A laptop. + kLaptop, +}; \ No newline at end of file
diff --git a/chrome/browser/ui/webui/nearby_share/shared_resources.cc b/chrome/browser/ui/webui/nearby_share/shared_resources.cc index b820b9d..8d98094 100644 --- a/chrome/browser/ui/webui/nearby_share/shared_resources.cc +++ b/chrome/browser/ui/webui/nearby_share/shared_resources.cc
@@ -4,9 +4,14 @@ #include "chrome/browser/ui/webui/nearby_share/shared_resources.h" +#include <string> + #include "base/containers/span.h" +#include "chrome/browser/ui/webui/webui_util.h" +#include "chrome/grit/generated_resources.h" #include "chrome/grit/nearby_share_dialog_resources.h" #include "chrome/grit/nearby_share_dialog_resources_map.h" +#include "ui/base/webui/web_ui_util.h" const char kNearbyShareGeneratedPath[] = "@out_folder@/gen/chrome/browser/resources/nearby_share/"; @@ -28,3 +33,10 @@ } RegisterNearbySharedMojoResources(data_source); } + +void RegisterNearbySharedStrings(content::WebUIDataSource* data_source) { + static constexpr webui::LocalizedString kLocalizedStrings[] = { + {"secureConnectionId", IDS_NEARBY_SECURE_CONNECTION_ID}, + }; + webui::AddLocalizedStringsBulk(data_source, kLocalizedStrings); +}
diff --git a/chrome/browser/ui/webui/nearby_share/shared_resources.h b/chrome/browser/ui/webui/nearby_share/shared_resources.h index 5f59b66..377cf86 100644 --- a/chrome/browser/ui/webui/nearby_share/shared_resources.h +++ b/chrome/browser/ui/webui/nearby_share/shared_resources.h
@@ -11,5 +11,6 @@ void RegisterNearbySharedMojoResources(content::WebUIDataSource* data_source); void RegisterNearbySharedResources(content::WebUIDataSource* data_source); +void RegisterNearbySharedStrings(content::WebUIDataSource* data_source); #endif // CHROME_BROWSER_UI_WEBUI_NEARBY_SHARE_SHARED_RESOURCES_H_
diff --git a/chrome/browser/ui/webui/settings/chromeos/main_section.cc b/chrome/browser/ui/webui/settings/chromeos/main_section.cc index 95363a7..2a1e91a 100644 --- a/chrome/browser/ui/webui/settings/chromeos/main_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/main_section.cc
@@ -6,8 +6,13 @@ #include "ash/public/cpp/resources/grit/ash_public_unscaled_resources.h" #include "base/feature_list.h" +#include "base/i18n/number_formatting.h" #include "base/no_destructor.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_process_platform_part.h" +#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" +#include "chrome/browser/chromeos/policy/minimum_version_policy_handler.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/metrics_handler.h" @@ -17,6 +22,7 @@ #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/browser/web_applications/system_web_app_manager.h" #include "chrome/common/url_constants.h" +#include "chrome/common/webui_url_constants.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" @@ -54,6 +60,45 @@ base::FeatureList::IsEnabled(::chromeos::features::kNewOsSettingsSearch)); } +void AddUpdateRequiredEolStrings(content::WebUIDataSource* html_source) { + policy::BrowserPolicyConnectorChromeOS* connector = + g_browser_process->platform_part()->browser_policy_connector_chromeos(); + policy::MinimumVersionPolicyHandler* handler = + connector->GetMinimumVersionPolicyHandler(); + + // |eol_return_banner_text| contains the update required end of life banner + // text which is left empty when the banner should not be shown. + base::string16 eol_return_banner_text; + if (handler && handler->IsUpdateRequiredEol()) { + base::Optional<int> days = handler->GetTimeRemainingInDays(); + // We only need to show the banner if less than equal to one week remains to + // reach the update required deadline. + if (days && days.value() <= 7) { + // |days| could have value equal to zero if we are very close to the + // deadline. + int days_remaining = days.value() ? days.value() : 1; + base::string16 domain_name = + base::UTF8ToUTF16(connector->GetEnterpriseDisplayDomain()); + base::string16 link_url = + base::UTF8ToUTF16(chrome::kChromeUIManagementURL); + if (days_remaining == 1) { + eol_return_banner_text = l10n_util::GetStringFUTF16( + IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_LAST_DAY, domain_name, + link_url); + } else if (days_remaining == 7) { + eol_return_banner_text = l10n_util::GetStringFUTF16( + IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_ONE_WEEK, domain_name, + link_url); + } else { + eol_return_banner_text = l10n_util::GetStringFUTF16( + IDS_SETTINGS_UPDATE_REQUIRED_EOL_BANNER_DAYS, domain_name, + base::FormatNumber(days_remaining), link_url); + } + } + } + html_source->AddString("updateRequiredEolBannerText", eol_return_banner_text); +} + } // namespace MainSection::MainSection(Profile* profile, @@ -148,6 +193,7 @@ AddSearchInSettingsStrings(html_source); AddChromeOSUserStrings(html_source); + AddUpdateRequiredEolStrings(html_source); policy_indicator::AddLocalizedStrings(html_source); }
diff --git a/chrome/browser/usb/usb_tab_helper_unittest.cc b/chrome/browser/usb/usb_tab_helper_unittest.cc index 0b901bc..c95d76d 100644 --- a/chrome/browser/usb/usb_tab_helper_unittest.cc +++ b/chrome/browser/usb/usb_tab_helper_unittest.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/usb/usb_tab_helper.h" -#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" #include "chrome/browser/usb/frame_usb_services.h" #include "chrome/browser/usb/usb_chooser_context.h" #include "chrome/browser/usb/usb_chooser_context_factory.h" @@ -12,6 +11,7 @@ #include "components/performance_manager/embedder/performance_manager_registry.h" #include "components/performance_manager/public/decorators/page_live_state_decorator.h" #include "components/performance_manager/test_support/decorators_utils.h" +#include "components/performance_manager/test_support/test_harness_helper.h" #include "services/device/public/cpp/test/fake_usb_device_manager.h" #include "services/service_manager/public/cpp/test/test_service.h" #include "services/service_manager/public/cpp/test/test_service_manager.h" @@ -19,14 +19,17 @@ #include "third_party/blink/public/mojom/usb/web_usb_service.mojom.h" #include "url/url_constants.h" -class UsbTabHelperTest - : public resource_coordinator::testing::ChromeTestHarnessWithLocalDB { +class UsbTabHelperTest : public ChromeRenderViewHostTestHarness { protected: UsbTabHelperTest() = default; ~UsbTabHelperTest() override = default; void SetUp() override { - resource_coordinator::testing::ChromeTestHarnessWithLocalDB::SetUp(); + ChromeRenderViewHostTestHarness::SetUp(); + pm_harness_.SetUp(); + // Reset the test contents to ensure that it has a PageNode associated to it + // in the PerformanceManager graph. + SetContents(CreateTestWebContents()); auto* chooser_context = UsbChooserContextFactory::GetForProfile(profile()); mojo::PendingRemote<device::mojom::UsbDeviceManager> device_manager; @@ -37,7 +40,13 @@ NavigateAndCommit(GURL("https://www.google.com")); } + void TearDown() override { + pm_harness_.TearDown(); + ChromeRenderViewHostTestHarness::TearDown(); + } + private: + performance_manager::PerformanceManagerTestHarnessHelper pm_harness_; device::FakeUsbDeviceManager device_manager_; };
diff --git a/chrome/browser/vr/ui_host/vr_ui_host_impl.cc b/chrome/browser/vr/ui_host/vr_ui_host_impl.cc index e2b5e0684..35dc73d 100644 --- a/chrome/browser/vr/ui_host/vr_ui_host_impl.cc +++ b/chrome/browser/vr/ui_host/vr_ui_host_impl.cc
@@ -391,9 +391,11 @@ // location, microphone, camera, midi. CapturingStateModel active_capturing = active_capturing_; + // TODO(https://crbug.com/1103176): Plumb the actual frame reference here (we + // should get a RFH from VRServiceImpl instead of WebContents) content_settings::TabSpecificContentSettings* settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents_); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents_->GetMainFrame()); if (settings) { const ContentSettingsUsagesState& usages_state = settings->geolocation_usages_state();
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index a3c42a83..953a100 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1596088294-d7afac6507733c270f9eabdc2010773cc2ccd03c.profdata +chrome-mac-master-1596193635-6128c4835e91dec9617eb88a5ffdf98aa76979d0.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 66031da..edc1710 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-master-1596160292-be7478816f9ea1c3a3e60ecafceb33fda007c691.profdata +chrome-win32-master-1596192746-6fea58b93463f5fc9ccbb164a8054cb0a38af6db.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index bb99fd8..108ca52 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-master-1596153340-6d725ede4117dca447ca41731e1643697c638085.profdata +chrome-win64-master-1596193635-02bce97a1becd63464acfea57c5b1e9a80097f4f.profdata
diff --git a/chrome/common/caption.mojom b/chrome/common/caption.mojom index 05ca09f..332ebf1 100644 --- a/chrome/common/caption.mojom +++ b/chrome/common/caption.mojom
@@ -7,6 +7,9 @@ // Browser process interface exposed to the renderer for communication about // the Live Caption feature. interface CaptionHost { + // Called when speech recognition service is ready to send transcriptions. + OnSpeechRecognitionReady() => (bool success); + // Called when the speech recognition client receives a transcription from the // speech service. Returns whether the transcription result was received // successfully. Transcriptions will halt if this returns false.
diff --git a/chrome/renderer/media/chrome_speech_recognition_client.cc b/chrome/renderer/media/chrome_speech_recognition_client.cc index 70da74b25..9f7d95f 100644 --- a/chrome/renderer/media/chrome_speech_recognition_client.cc +++ b/chrome/renderer/media/chrome_speech_recognition_client.cc
@@ -5,6 +5,7 @@ #include "chrome/renderer/media/chrome_speech_recognition_client.h" #include <utility> +#include <vector> #include "base/metrics/field_trial_params.h" #include "content/public/renderer/render_frame.h" @@ -57,7 +58,6 @@ bool is_multichannel_supported) { is_multichannel_supported_ = is_multichannel_supported; is_recognizer_bound_ = true; - if (on_ready_callback_) std::move(on_ready_callback_).Run(); } @@ -102,11 +102,11 @@ caption_host_->OnTranscription( chrome::mojom::TranscriptionResult::New(result->transcription, result->is_final), - base::BindOnce(&ChromeSpeechRecognitionClient::OnTranscriptionCallback, + base::BindOnce(&ChromeSpeechRecognitionClient::OnBrowserCallback, base::Unretained(this))); } -void ChromeSpeechRecognitionClient::OnTranscriptionCallback(bool success) { +void ChromeSpeechRecognitionClient::OnBrowserCallback(bool success) { is_browser_requesting_transcription_ = success; } @@ -145,6 +145,17 @@ if (IsSpeechRecognitionAvailable()) { speech_recognition_recognizer_->SendAudioToSpeechRecognitionService( std::move(audio_data)); + + // When the speech recognition client receives speech, it alerts the + // live caption host in the browser that it is ready so that the UI can + // display a message. This happens at the time of playing the video and not + // at the time of construction of this object. + if (!on_ready_message_sent_to_caption_host_) { + caption_host_->OnSpeechRecognitionReady( + base::BindOnce(&ChromeSpeechRecognitionClient::OnBrowserCallback, + base::Unretained(this))); + on_ready_message_sent_to_caption_host_ = true; + } } }
diff --git a/chrome/renderer/media/chrome_speech_recognition_client.h b/chrome/renderer/media/chrome_speech_recognition_client.h index df0e0574..82be158 100644 --- a/chrome/renderer/media/chrome_speech_recognition_client.h +++ b/chrome/renderer/media/chrome_speech_recognition_client.h
@@ -65,8 +65,8 @@ media::mojom::AudioDataS16Ptr ConvertToAudioDataS16( scoped_refptr<media::AudioBuffer> buffer); - // Called as a response to sending a transcription to the browser. - void OnTranscriptionCallback(bool success); + // Called as a response to sending a message to the browser. + void OnBrowserCallback(bool success); media::mojom::AudioDataS16Ptr ConvertToAudioDataS16( std::unique_ptr<media::AudioBus> audio_bus, @@ -108,6 +108,9 @@ bool is_recognizer_bound_ = false; + // Whether or not the on ready message has been sent to the caption host. + bool on_ready_message_sent_to_caption_host_ = false; + // The temporary audio bus used to mix multichannel audio into a single // channel. std::unique_ptr<media::AudioBus> monaural_audio_bus_;
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc index 747497b6..930636d1 100644 --- a/chrome/renderer/net/net_error_helper.cc +++ b/chrome/renderer/net/net_error_helper.cc
@@ -25,7 +25,6 @@ #include "chrome/common/render_messages.h" #include "chrome/renderer/chrome_render_thread_observer.h" #include "components/error_page/common/error.h" -#include "components/error_page/common/error_page_params.h" #include "components/error_page/common/localized_error.h" #include "components/error_page/common/net_error_info.h" #include "components/grit/components_resources.h" @@ -76,7 +75,6 @@ using content::kUnreachableWebDataURL; using error_page::DnsProbeStatus; using error_page::DnsProbeStatusToString; -using error_page::ErrorPageParams; using error_page::LocalizedError; namespace { @@ -249,7 +247,6 @@ const error_page::Error& error, bool is_failed_post, bool can_show_network_diagnostics_dialog, - std::unique_ptr<ErrorPageParams> params, std::string* error_html) const { error_html->clear(); @@ -266,8 +263,7 @@ error.stale_copy_in_cache(), can_show_network_diagnostics_dialog, ChromeRenderThreadObserver::is_incognito_process(), IsOfflineContentOnNetErrorFeatureEnabled(), IsAutoFetchFeatureEnabled(), - IsRunningInForcedAppMode(), RenderThread::Get()->GetLocale(), - std::move(params)); + IsRunningInForcedAppMode(), RenderThread::Get()->GetLocale()); DCHECK(!template_html.empty()) << "unable to load template."; // "t" is the id of the template's root node. *error_html = @@ -293,8 +289,7 @@ error.stale_copy_in_cache(), can_show_network_diagnostics_dialog, ChromeRenderThreadObserver::is_incognito_process(), IsOfflineContentOnNetErrorFeatureEnabled(), IsAutoFetchFeatureEnabled(), - IsRunningInForcedAppMode(), RenderThread::Get()->GetLocale(), - std::unique_ptr<ErrorPageParams>()); + IsRunningInForcedAppMode(), RenderThread::Get()->GetLocale()); std::string json; JSONWriter::Write(page_state.strings, &json);
diff --git a/chrome/renderer/net/net_error_helper.h b/chrome/renderer/net/net_error_helper.h index 7fde1e1..e2ed1cd9 100644 --- a/chrome/renderer/net/net_error_helper.h +++ b/chrome/renderer/net/net_error_helper.h
@@ -32,7 +32,6 @@ namespace error_page { class Error; -struct ErrorPageParams; } // Listens for NetErrorInfo messages from the NetErrorTabHelper on the @@ -95,7 +94,6 @@ const error_page::Error& error, bool is_failed_post, bool can_use_local_diagnostics_service, - std::unique_ptr<error_page::ErrorPageParams> params, std::string* html) const override; void EnablePageHelperFunctions() override;
diff --git a/chrome/renderer/net/net_error_helper_core.cc b/chrome/renderer/net/net_error_helper_core.cc index 8e5edea0..59bb789 100644 --- a/chrome/renderer/net/net_error_helper_core.cc +++ b/chrome/renderer/net/net_error_helper_core.cc
@@ -13,7 +13,6 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" -#include "components/error_page/common/error_page_params.h" #include "components/error_page/common/localized_error.h" #include "content/public/common/content_switches.h" #include "content/public/renderer/render_thread.h" @@ -163,8 +162,7 @@ } else if (error_html) { delegate_->GenerateLocalizedErrorPage( error, is_failed_post, - false /* No diagnostics dialogs allowed for subframes. */, nullptr, - error_html); + false /* No diagnostics dialogs allowed for subframes. */, error_html); } } @@ -215,7 +213,7 @@ if (error_html) { pending_error_page_info->page_state = delegate_->GenerateLocalizedErrorPage( error, pending_error_page_info->was_failed_post, - can_show_network_diagnostics_dialog_, nullptr, error_html); + can_show_network_diagnostics_dialog_, error_html); } }
diff --git a/chrome/renderer/net/net_error_helper_core.h b/chrome/renderer/net/net_error_helper_core.h index b2befb0..08e63ad 100644 --- a/chrome/renderer/net/net_error_helper_core.h +++ b/chrome/renderer/net/net_error_helper_core.h
@@ -26,9 +26,6 @@ namespace content { class RenderFrame; } -namespace error_page { -struct ErrorPageParams; -} // Class that contains the logic for how the NetErrorHelper. This allows for // testing the logic without a RenderView or WebFrame, which are difficult to @@ -64,7 +61,6 @@ const error_page::Error& error, bool is_failed_post, bool can_show_network_diagnostics_dialog, - std::unique_ptr<error_page::ErrorPageParams> params, std::string* html) const = 0; // Create extra Javascript bindings in the error page. Will only be invoked
diff --git a/chrome/renderer/net/net_error_helper_core_unittest.cc b/chrome/renderer/net/net_error_helper_core_unittest.cc index e9dbc64..91243ba 100644 --- a/chrome/renderer/net/net_error_helper_core_unittest.cc +++ b/chrome/renderer/net/net_error_helper_core_unittest.cc
@@ -25,7 +25,6 @@ #include "chrome/common/available_offline_content.mojom.h" #include "chrome/renderer/net/available_offline_content_helper.h" #include "components/error_page/common/error.h" -#include "components/error_page/common/error_page_params.h" #include "components/error_page/common/net_error_info.h" #include "content/public/common/service_names.mojom.h" #include "content/public/common/url_constants.h" @@ -199,7 +198,6 @@ const error_page::Error& error, bool is_failed_post, bool can_show_network_diagnostics_dialog, - std::unique_ptr<error_page::ErrorPageParams> params, std::string* html) const override { last_can_show_network_diagnostics_dialog_ = can_show_network_diagnostics_dialog;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 479b502..25ed99c 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1137,6 +1137,7 @@ "../browser/profiles/profile_browsertest.cc", "../browser/profiles/profile_list_desktop_browsertest.cc", "../browser/profiles/profile_manager_browsertest.cc", + "../browser/profiles/profile_theme_update_service_browsertest.cc", "../browser/push_messaging/push_messaging_browsertest.cc", "../browser/referrer_policy_browsertest.cc", "../browser/renderer_context_menu/accessibility_labels_menu_observer_browsertest.cc", @@ -1153,10 +1154,6 @@ "../browser/resource_coordinator/discard_before_unload_helper.cc", "../browser/resource_coordinator/discard_before_unload_helper.h", "../browser/resource_coordinator/discard_before_unload_helper_browsertest.cc", - "../browser/resource_coordinator/local_site_characteristics_data_store_factory_browsertest.cc", - "../browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc", - "../browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h", - "../browser/resource_coordinator/local_site_characteristics_database_browsertest.cc", "../browser/resource_coordinator/tab_activity_watcher_browsertest.cc", "../browser/resource_coordinator/tab_manager_browsertest.cc", "../browser/safe_browsing/chrome_cleaner/reporter_runner_browsertest_win.cc", @@ -3662,6 +3659,8 @@ "../browser/media/feeds/media_feeds_fetcher_unittest.cc", "../browser/media/feeds/media_feeds_service_unittest.cc", "../browser/media/kaleidoscope/kaleidoscope_switches_unittest.cc", + "../browser/nearby_sharing/fake_nearby_connection.cc", + "../browser/nearby_sharing/fake_nearby_connection.h", "../browser/nearby_sharing/fake_nearby_connections_manager.cc", "../browser/nearby_sharing/fake_nearby_connections_manager.h", "../browser/nearby_sharing/fast_initiation_manager_unittest.cc", @@ -3686,12 +3685,12 @@ "../browser/nearby_sharing/nearby_process_manager_unittest.cc", "../browser/nearby_sharing/nearby_share_settings_unittest.cc", "../browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc", - "../browser/nearby_sharing/transfer_metadata_builder.cc", - "../browser/nearby_sharing/transfer_metadata_builder.h", "../browser/nearby_sharing/webrtc_signaling_messenger_unittest.cc", "../browser/password_manager/generated_password_leak_detection_pref_unittest.cc", "../browser/performance_manager/test_support/page_discarding_utils.cc", "../browser/performance_manager/test_support/page_discarding_utils.h", + "../browser/performance_manager/test_support/site_data_utils.cc", + "../browser/performance_manager/test_support/site_data_utils.h", "../browser/profiles/profile_avatar_icon_util_unittest.cc", "../browser/profiles/profile_destroyer_unittest.cc", "../browser/safe_browsing/generated_safe_browsing_pref_unittest.cc", @@ -4130,17 +4129,8 @@ "../browser/resource_coordinator/decision_details_unittest.cc", "../browser/resource_coordinator/discard_metrics_lifecycle_unit_observer_unittest.cc", "../browser/resource_coordinator/intervention_policy_database_unittest.cc", - "../browser/resource_coordinator/leveldb_site_characteristics_database_unittest.cc", "../browser/resource_coordinator/lifecycle_unit_base_unittest.cc", "../browser/resource_coordinator/lifecycle_unit_unittest.cc", - "../browser/resource_coordinator/local_site_characteristics_data_impl_unittest.cc", - "../browser/resource_coordinator/local_site_characteristics_data_reader_unittest.cc", - "../browser/resource_coordinator/local_site_characteristics_data_store_unittest.cc", - "../browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc", - "../browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h", - "../browser/resource_coordinator/local_site_characteristics_data_writer_unittest.cc", - "../browser/resource_coordinator/local_site_characteristics_non_recording_data_store_unittest.cc", - "../browser/resource_coordinator/local_site_characteristics_webcontents_observer_unittest.cc", "../browser/resource_coordinator/session_restore_policy_unittest.cc", "../browser/resource_coordinator/tab_activity_watcher_unittest.cc", "../browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc", @@ -4239,6 +4229,7 @@ "../browser/ui/browser_unittest.cc", "../browser/ui/browser_window_state_unittest.cc", "../browser/ui/commander/commander_controller_unittest.cc", + "../browser/ui/commander/fuzzy_finder_unittest.cc", "../browser/ui/content_settings/content_setting_bubble_model_unittest.cc", "../browser/ui/content_settings/content_setting_image_model_unittest.cc", "../browser/ui/content_settings/content_setting_media_image_model_unittest.mm",
diff --git a/chrome/test/data/pdf/BUILD.gn b/chrome/test/data/pdf/BUILD.gn index 79c17d1d..e2d573e 100644 --- a/chrome/test/data/pdf/BUILD.gn +++ b/chrome/test/data/pdf/BUILD.gn
@@ -35,6 +35,7 @@ #":toolbar_manager_test", #":touch_handling_test", + ":viewer_pdf_sidenav_test", ":viewer_pdf_toolbar_new_test", #":viewport_test", @@ -159,6 +160,11 @@ externs_list = [ "$externs_path/test.js" ] } +js_library("viewer_pdf_sidenav_test") { + deps = [ "//chrome/browser/resources/pdf/elements:viewer-pdf-sidenav" ] + externs_list = [ "$externs_path/test.js" ] +} + js_library("viewer_pdf_toolbar_new_test") { deps = [ "//chrome/browser/resources/pdf:constants",
diff --git a/chrome/test/data/pdf/viewer_pdf_sidenav_test.js b/chrome/test/data/pdf/viewer_pdf_sidenav_test.js new file mode 100644 index 0000000..065d0d6 --- /dev/null +++ b/chrome/test/data/pdf/viewer_pdf_sidenav_test.js
@@ -0,0 +1,55 @@ +// Copyright 2020 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 {ViewerPdfSidenavElement} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/elements/viewer-pdf-sidenav.js'; + +/** @return {!ViewerPdfSidenavElement} */ +function createSidenav() { + document.body.innerHTML = ''; + const sidenav = /** @type {!ViewerPdfSidenavElement} */ ( + document.createElement('viewer-pdf-sidenav')); + document.body.appendChild(sidenav); + return sidenav; +} + +// Unit tests for the viewer-pdf-sidenav element. +const tests = [ + /** + * Test that the sidenav toggles between outline and thumbnail view. + */ + function testViewToggle() { + const sidenav = createSidenav(); + const content = sidenav.shadowRoot.querySelector('#content'); + const buttons = /** @type {!NodeList<!CrIconButtonElement>} */ ( + sidenav.shadowRoot.querySelectorAll('cr-icon-button')); + + let visibleContent = content.querySelector('div:not([hidden])'); + chrome.test.assertTrue( + buttons[0].parentNode.classList.contains('selected')); + chrome.test.assertFalse( + buttons[1].parentNode.classList.contains('selected')); + chrome.test.assertEq('Thumbnails', visibleContent.textContent); + + // Click on outline view. + buttons[1].click(); + visibleContent = content.querySelector('div:not([hidden])'); + chrome.test.assertFalse( + buttons[0].parentNode.classList.contains('selected')); + chrome.test.assertTrue( + buttons[1].parentNode.classList.contains('selected')); + chrome.test.assertEq('Outline', visibleContent.textContent); + + // Return to thumbnail view. + buttons[0].click(); + visibleContent = content.querySelector('div:not([hidden])'); + chrome.test.assertTrue( + buttons[0].parentNode.classList.contains('selected')); + chrome.test.assertFalse( + buttons[1].parentNode.classList.contains('selected')); + chrome.test.assertEq('Thumbnails', visibleContent.textContent); + chrome.test.succeed(); + }, +]; + +chrome.test.runTests(tests);
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index e49dc22..e98360f 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -5872,15 +5872,21 @@ "policy_pref_mapping_test": [ { "policies": { - "DeviceMinimumVersion": [ - {"chromeos_version" : "13121.0.0", "warning_period" : 0, "aue_warning_period" : 14} - ] + "DeviceMinimumVersion": { + "requirements": [ + {"chromeos_version" : "13121.0.0", "warning_period" : 0, "aue_warning_period" : 14} + ], + "unmanaged_user_restricted": true + } }, "prefs": { "cros.device.min_version": { - "value": [ - {"chromeos_version" : "13121.0.0", "warning_period" : 0, "aue_warning_period" : 14} - ] + "value": { + "requirements": [ + {"chromeos_version" : "13121.0.0", "warning_period" : 0, "aue_warning_period" : 14} + ], + "unmanaged_user_restricted": true + } } } }
diff --git a/chrome/test/data/push_messaging/push_test.js b/chrome/test/data/push_messaging/push_test.js index 4d8ea78..c5fdb63 100644 --- a/chrome/test/data/push_messaging/push_test.js +++ b/chrome/test/data/push_messaging/push_test.js
@@ -140,6 +140,18 @@ }).catch(sendErrorToTest); } +function documentSubscribePushGetExpirationTime() { + navigator.serviceWorker.ready.then(function(swRegistration) { + return swRegistration.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: kApplicationServerKey.buffer + }) + .then(function(subscription) { + sendResultToTest(subscription.expirationTime); + }); + }).catch(sendErrorToTest); +} + function workerSubscribePush() { // Send the message to the worker for it to subscribe navigator.serviceWorker.controller.postMessage({command: 'workerSubscribe'}); @@ -176,6 +188,15 @@ }).catch(sendErrorToTest); } +function GetSubscriptionExpirationTime() { + navigator.serviceWorker.ready.then(function(swRegistration) { + return swRegistration.pushManager.getSubscription() + .then(function(subscription) { + sendResultToTest(subscription.expirationTime); + }); + }).catch(sendErrorToTest); +} + function pushManagerPermissionState() { navigator.serviceWorker.ready.then(function(swRegistration) { return swRegistration.pushManager.permissionState({userVisibleOnly: true})
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_page_test.js b/chrome/test/data/webui/settings/chromeos/os_settings_page_test.js index 8198ad81..1db2500 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_page_test.js
@@ -123,4 +123,27 @@ assertTrue(!!section, 'Expected section ' + name); } }); + + test('Update required end of life banner visibility', function() { + Polymer.dom.flush(); + assertFalse(settingsPage.showUpdateRequiredEolBanner_); + assertFalse(!!settingsPage.$$('#updateRequiredEolBanner')); + + settingsPage.showUpdateRequiredEolBanner_ = true; + Polymer.dom.flush(); + assertTrue(!!settingsPage.$$('#updateRequiredEolBanner')); + }); + + test('Update required end of life banner close button click', function() { + settingsPage.showUpdateRequiredEolBanner_ = true; + Polymer.dom.flush(); + const banner = settingsPage.$$('#updateRequiredEolBanner'); + assertTrue(!!banner); + + const closeButton = assert(settingsPage.$$('#closeUpdateRequiredEol')); + closeButton.click(); + Polymer.dom.flush(); + assertFalse(settingsPage.showUpdateRequiredEolBanner_); + assertEquals('none', banner.style.display); + }); });
diff --git a/chrome/test/data/webui/settings/passwords_section_test.js b/chrome/test/data/webui/settings/passwords_section_test.js index c60c440b..e159f4e 100644 --- a/chrome/test/data/webui/settings/passwords_section_test.js +++ b/chrome/test/data/webui/settings/passwords_section_test.js
@@ -143,6 +143,46 @@ } /** + * Helper function to test for an element is visible. + */ +function isElementVisible(element) { + return element && !element.hidden; +} + +/** + * Helper function to test if all components of edit dialog are shown correctly. + */ +function editDialogPartsAreShownCorrectly(passwordDialog) { + assertEquals( + passwordDialog.i18n('editCompromisedPasswordTitle'), + passwordDialog.$.title.textContent.trim()); + assertFalse(passwordDialog.$.passwordInput.readonly); + assertTrue(passwordDialog.$.passwordInput.required); + assertTrue(isElementVisible(passwordDialog.$.footnote)); + assertTrue(isElementVisible(passwordDialog.$.cancel)); + assertEquals( + passwordDialog.i18n('save'), + passwordDialog.$.actionButton.textContent.trim()); +} + +/** + * Helper function to test if all components of details dialog are shown + * correctly. + */ +function detailsDialogPartsAreShownCorrectly(passwordDialog) { + assertEquals( + passwordDialog.i18n('passwordDetailsTitle'), + passwordDialog.$.title.textContent.trim()); + assertTrue(passwordDialog.$.passwordInput.readonly); + assertFalse(passwordDialog.$.passwordInput.required); + assertFalse(isElementVisible(passwordDialog.$.footnote)); + assertFalse(isElementVisible(passwordDialog.$.cancel)); + assertEquals( + passwordDialog.i18n('done'), + passwordDialog.$.actionButton.textContent.trim()); +} + +/** * Simulates user who is eligible and opted-in for account storage. Should be * called after the PasswordsSection element is created. The load time value for * enableAccountStorage must be overridden separately. @@ -562,6 +602,82 @@ passwordsSection.$.passwordsListHandler.$$('#menuCopyPassword').hidden); }); + // Test verifies that 'Edit' button is replaced to 'Details' for Federated + // (passwordless) credentials. Does not test Details and Edit button. + test('verifyEditReplacedToDetailsForFederatedPasswordInMenu', function() { + const passwordList = [ + createPasswordEntry({federationText: 'with chromium.org'}), + ]; + const passwordsSection = elementFactory.createPasswordsSection( + passwordManager, passwordList, []); + + getFirstPasswordListItem(passwordsSection).$.moreActionsButton.click(); + flush(); + assertEquals( + passwordsSection.i18n('passwordViewDetails'), + passwordsSection.$.passwordsListHandler.$$('#menuEditPassword') + .textContent.trim()); + }); + + // Test verifies that 'Edit' button is replaced to 'Details' for Federated + // (passwordless) credentials when EditPasswordsInSettings flag is enabled. + // Does not test Details and Edit button. + test( + 'verifyDetailsForFederatedPasswordInMenuEnabledEditPasswordsInSettings', + function() { + const passwordList = [ + createPasswordEntry({federationText: 'with chromium.org'}), + ]; + loadTimeData.overrideValues({editPasswordsInSettings: true}); + const passwordsSection = elementFactory.createPasswordsSection( + passwordManager, passwordList, []); + + getFirstPasswordListItem(passwordsSection).$.moreActionsButton.click(); + flush(); + assertEquals( + passwordsSection.i18n('passwordViewDetails'), + passwordsSection.$.passwordsListHandler.$$('#menuEditPassword') + .textContent.trim()); + }); + + // Test verifies that 'Edit' button is shown instead of 'Details' for + // common credentials when the flag editPasswordsInSettings is enabled. + // Does not test Details and Edit button. + test('verifyEditButtonInMenuEnabledEditPasswordsInSettings', function() { + const passwordList = [ + createPasswordEntry({url: 'one.com', username: 'hey'}), + ]; + loadTimeData.overrideValues({editPasswordsInSettings: true}); + const passwordsSection = elementFactory.createPasswordsSection( + passwordManager, passwordList, []); + + getFirstPasswordListItem(passwordsSection).$.moreActionsButton.click(); + flush(); + assertEquals( + passwordsSection.i18n('editCompromisedPassword'), + passwordsSection.$.passwordsListHandler.$$('#menuEditPassword') + .textContent.trim()); + }); + + // Test verifies that 'Details' button is shown instead of 'Edit' for + // non-federated credentials when the flag editPasswordsInSettings is + // disabled. Does not test Details and Edit button. + test('verifyDetailsButtonInMenuDisabledEditPasswordsInSettings', function() { + const passwordList = [ + createPasswordEntry({url: 'one.com', username: 'hey'}), + ]; + loadTimeData.overrideValues({editPasswordsInSettings: false}); + const passwordsSection = elementFactory.createPasswordsSection( + passwordManager, passwordList, []); + + getFirstPasswordListItem(passwordsSection).$.moreActionsButton.click(); + flush(); + assertEquals( + passwordsSection.i18n('passwordViewDetails'), + passwordsSection.$.passwordsListHandler.$$('#menuEditPassword') + .textContent.trim()); + }); + test('verifyFilterPasswords', function() { const passwordList = [ createPasswordEntry({url: 'one.com', username: 'SHOW', id: 0}), @@ -832,14 +948,81 @@ }); test('verifyFederatedPassword', function() { - const item = createMultiStorePasswordEntry( + const federationEntry = createMultiStorePasswordEntry( {federationText: 'with chromium.org', username: 'bart', deviceId: 42}); - const passwordDialog = elementFactory.createPasswordEditDialog(item); + const passwordDialog = + elementFactory.createPasswordEditDialog(federationEntry); - assertEquals(item.federationText, passwordDialog.$.passwordInput.value); + assertEquals( + federationEntry.federationText, passwordDialog.$.passwordInput.value); // Text should be readable. assertEquals('text', passwordDialog.$.passwordInput.type); assertTrue(passwordDialog.$.showPasswordButton.hidden); + detailsDialogPartsAreShownCorrectly(passwordDialog); + }); + + test('verifyDetailsDialogDisabledEditPasswordsInSettings', function() { + const federationEntry = createMultiStorePasswordEntry( + {federationText: 'with chromium.org', username: 'bart', deviceId: 42}); + loadTimeData.overrideValues({editPasswordsInSettings: false}); + const passwordDialogFederation = + elementFactory.createPasswordEditDialog(federationEntry); + detailsDialogPartsAreShownCorrectly(passwordDialogFederation); + + const commonEntry = createMultiStorePasswordEntry( + {url: 'goo.gl', username: 'bart', accountId: 42}); + const passwordDialogCommon = + elementFactory.createPasswordEditDialog(commonEntry); + detailsDialogPartsAreShownCorrectly(passwordDialogCommon); + }); + + test('verifyEditOrDetailsDialogEnabledEditPasswordsInSettings', function() { + const federationEntry = createMultiStorePasswordEntry( + {federationText: 'with chromium.org', username: 'bart', deviceId: 42}); + loadTimeData.overrideValues({editPasswordsInSettings: true}); + const passwordDialogFederation = + elementFactory.createPasswordEditDialog(federationEntry); + detailsDialogPartsAreShownCorrectly(passwordDialogFederation); + + const commonEntry = createMultiStorePasswordEntry( + {url: 'goo.gl', username: 'bart', accountId: 42}); + const passwordDialogCommon = + elementFactory.createPasswordEditDialog(commonEntry); + // Should show edit dialog for common credetial when editPasswordsInSettings + // flag is enabled. + editDialogPartsAreShownCorrectly(passwordDialogCommon); + }); + + test('editDialogChangePassword', async function() { + loadTimeData.overrideValues({editPasswordsInSettings: true}); + + const PASSWORD1 = 'hello_world'; + const commonEntry = createMultiStorePasswordEntry( + {url: 'goo.gl', username: 'bart', accountId: 42}); + + const editDialog = elementFactory.createPasswordEditDialog(commonEntry); + + editDialog.password = PASSWORD1; + flush(); + + assertEquals(PASSWORD1, editDialog.$.passwordInput.value); + + // Empty password should be consider invalid and disables the save button. + editDialog.$.passwordInput.value = ''; + assertTrue(editDialog.$.passwordInput.invalid); + assertTrue(editDialog.$.actionButton.disabled); + + const PASSWORD2 = 'hello_world_2'; + editDialog.$.passwordInput.value = PASSWORD2; + assertFalse(editDialog.$.passwordInput.invalid); + assertFalse(editDialog.$.actionButton.disabled); + + editDialog.$.actionButton.click(); + + // Check that the changeSavedPassword is called with the right arguments. + const {newPassword} = + await passwordManager.whenCalled('changeSavedPassword'); + assertEquals(PASSWORD2, newPassword); }); // Test verifies that the edit dialog informs the password is stored in the
diff --git a/chrome/test/data/webui/settings/test_password_manager_proxy.js b/chrome/test/data/webui/settings/test_password_manager_proxy.js index 7182551..f460916 100644 --- a/chrome/test/data/webui/settings/test_password_manager_proxy.js +++ b/chrome/test/data/webui/settings/test_password_manager_proxy.js
@@ -299,8 +299,8 @@ } /** override */ - changeSavedPassword(id, new_password) { - this.methodCalled('changeSavedPassword', {id, new_password}); + changeSavedPassword(id, newPassword) { + this.methodCalled('changeSavedPassword', {id, newPassword}); return Promise.resolve(); }
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index de42e5a8..1bec8d4 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -13379.0.0 \ No newline at end of file +13380.0.0 \ No newline at end of file
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt index 4fa984f..9500187c 100644 --- a/chromeos/profiles/orderfile.newest.txt +++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@ -chromeos-chrome-orderfile-field-86-4181.3-1594638142-benchmark-86.0.4205.0-r1.orderfile.xz +chromeos-chrome-orderfile-field-86-4183.39-1595842708-benchmark-86.0.4208.0-r1.orderfile.xz
diff --git a/chromeos/settings/cros_settings_names.cc b/chromeos/settings/cros_settings_names.cc index e476d859..68153c6 100644 --- a/chromeos/settings/cros_settings_names.cc +++ b/chromeos/settings/cros_settings_names.cc
@@ -386,9 +386,10 @@ // functionality. const char kTPMFirmwareUpdateSettings[] = "cros.tpm_firmware_update_settings"; -// A list of entries in JSON form representing the minimum version of Chrome OS -// along with warning times required to allow user sign in or stay in session. -// If the list is empty no restrictions will be applied. +// A dictionary containing a list of entries in JSON form representing the +// minimum version of Chrome OS along with warning times required to allow user +// sign in or stay in session. If the list is empty no restrictions will be +// applied. const char kDeviceMinimumVersion[] = "cros.device.min_version"; // String shown on the update required dialog on the the login screen containing
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_component.h b/components/autofill/core/browser/data_model/autofill_structured_address_component.h index 732570b..dbb085f 100644 --- a/components/autofill/core/browser/data_model/autofill_structured_address_component.h +++ b/components/autofill/core/browser/data_model/autofill_structured_address_component.h
@@ -17,17 +17,18 @@ namespace autofill { namespace structured_address { +// Represents the validation status of value stored in the AutofillProfile. enum class VerificationStatus { // No verification status assigned. kNoStatus, - // The user used the autofill settings to verify and store this token. - kUserVerified, - // The value was observed in a form transmission. - kObserved, - // Value was built from its subcomponents. - kFormatted, // The value token was parsed from a parent token. kParsed, + // Value was built from its subcomponents. + kFormatted, + // The value was observed in a form transmission. + kObserved, + // The user used the autofill settings to verify and store this token. + kUserVerified, }; // An AddressComponent is a tree structure that represents a semi-structured
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn index c574ac5..652fa5c 100644 --- a/components/autofill_assistant/browser/BUILD.gn +++ b/components/autofill_assistant/browser/BUILD.gn
@@ -95,6 +95,8 @@ "chip.cc", "chip.h", "client.h", + "client_context.cc", + "client_context.h", "client_settings.cc", "client_settings.h", "client_status.cc", @@ -268,6 +270,7 @@ "actions/wait_for_dom_action_unittest.cc", "basic_interactions_unittest.cc", "batch_element_checker_unittest.cc", + "client_context_unittest.cc", "controller_unittest.cc", "details_unittest.cc", "element_area_unittest.cc", @@ -282,7 +285,6 @@ "script_precondition_unittest.cc", "script_tracker_unittest.cc", "selector_unittest.cc", - "service_impl_unittest.cc", "string_conversions_util_unittest.cc", "trigger_context_unittest.cc", "user_data_util_unittest.cc", @@ -300,6 +302,7 @@ "//components/autofill/core/browser:test_support", "//components/password_manager/core/browser:test_support", "//components/strings:components_strings_grit", + "//components/version_info", "//content/test:test_support", "//testing/gmock", "//testing/gtest",
diff --git a/components/autofill_assistant/browser/client_context.cc b/components/autofill_assistant/browser/client_context.cc new file mode 100644 index 0000000..4d7c49a --- /dev/null +++ b/components/autofill_assistant/browser/client_context.cc
@@ -0,0 +1,81 @@ +// Copyright 2020 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/autofill_assistant/browser/client_context.h" +#include "base/metrics/field_trial.h" +#include "base/strings/string_util.h" +#include "components/version_info/version_info.h" +#include "crypto/sha2.h" + +namespace autofill_assistant { + +ClientContextImpl::ClientContextImpl(const Client* client) : client_(client) { + proto_.mutable_chrome()->set_chrome_version( + version_info::GetProductNameAndVersionForUserAgent()); + proto_.set_locale(client->GetLocale()); + proto_.set_country(client->GetCountryCode()); + + base::FieldTrial::ActiveGroups active_groups; + base::FieldTrialList::GetActiveFieldTrialGroups(&active_groups); + for (const auto& group : active_groups) { + FieldTrialProto* field_trial = + proto_.mutable_chrome()->add_active_field_trials(); + field_trial->set_trial_name(group.trial_name); + field_trial->set_group_name(group.group_name); + } + + client_->GetDeviceContext().ToProto(proto_.mutable_device_context()); + auto empty_trigger_context = TriggerContext::CreateEmpty(); + Update(*empty_trigger_context); +} + +void ClientContextImpl::Update(const TriggerContext& trigger_context) { + proto_.set_accessibility_enabled(client_->IsAccessibilityEnabled()); + std::string chrome_signed_in_email_address = + client_->GetChromeSignedInEmailAddress(); + proto_.set_signed_into_chrome_status(chrome_signed_in_email_address.empty() + ? ClientContextProto::NOT_SIGNED_IN + : ClientContextProto::SIGNED_IN); + + std::string experiment_ids = trigger_context.experiment_ids(); + if (!experiment_ids.empty()) { + proto_.set_experiment_ids(experiment_ids); + } + if (trigger_context.is_cct()) { + proto_.set_is_cct(true); + } + if (trigger_context.is_onboarding_shown()) { + proto_.set_is_onboarding_shown(true); + } + if (trigger_context.is_direct_action()) { + proto_.set_is_direct_action(true); + } + + // TODO(b/156882027): Add an integration test for accounts handling. + std::string chrome_account_sha_bin = + crypto::SHA256HashString(chrome_signed_in_email_address); + std::string client_account_hash = base::ToLowerASCII(base::HexEncode( + chrome_account_sha_bin.data(), chrome_account_sha_bin.size())); + if (trigger_context.get_caller_account_hash().empty()) { + proto_.set_accounts_matching_status(ClientContextProto::UNKNOWN); + } else { + if (trigger_context.get_caller_account_hash() == client_account_hash) { + proto_.set_accounts_matching_status( + ClientContextProto::ACCOUNTS_MATCHING); + } else { + proto_.set_accounts_matching_status( + ClientContextProto::ACCOUNTS_NOT_MATCHING); + } + } +} + +ClientContextProto ClientContextImpl::AsProto() const { + return proto_; +} + +ClientContextProto EmptyClientContext::AsProto() const { + return ClientContextProto(); +} + +} // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/client_context.h b/components/autofill_assistant/browser/client_context.h new file mode 100644 index 0000000..695807d5 --- /dev/null +++ b/components/autofill_assistant/browser/client_context.h
@@ -0,0 +1,48 @@ +// Copyright 2020 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_AUTOFILL_ASSISTANT_BROWSER_CLIENT_CONTEXT_H_ +#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_CLIENT_CONTEXT_H_ + +#include "components/autofill_assistant/browser/client.h" +#include "components/autofill_assistant/browser/service.pb.h" +#include "components/autofill_assistant/browser/trigger_context.h" + +namespace autofill_assistant { + +// Provides a ClientContextProto and a way to update its values dynamically. +class ClientContext { + public: + virtual ~ClientContext() = default; + // Updates the client context based on the current state of the client. + virtual void Update(const TriggerContext& trigger_context) = 0; + // Returns the proto representation of this client context. + virtual ClientContextProto AsProto() const = 0; +}; + +// Represents the client context for a given |client| instance. +class ClientContextImpl : public ClientContext { + public: + // |client| must outlive this instance. + ClientContextImpl(const Client* client); + ~ClientContextImpl() override = default; + void Update(const TriggerContext& trigger_context) override; + ClientContextProto AsProto() const override; + + private: + const Client* client_; + ClientContextProto proto_; +}; + +// An empty client context that does not contain any data. +class EmptyClientContext : public ClientContext { + public: + EmptyClientContext() = default; + ~EmptyClientContext() override = default; + void Update(const TriggerContext& trigger_context) override {} + ClientContextProto AsProto() const override; +}; + +} // namespace autofill_assistant +#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_CLIENT_CONTEXT_H_
diff --git a/components/autofill_assistant/browser/client_context_unittest.cc b/components/autofill_assistant/browser/client_context_unittest.cc new file mode 100644 index 0000000..e3247b6 --- /dev/null +++ b/components/autofill_assistant/browser/client_context_unittest.cc
@@ -0,0 +1,137 @@ +// Copyright 2020 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/autofill_assistant/browser/client_context.h" +#include "base/test/gmock_callback_support.h" +#include "base/test/mock_callback.h" +#include "components/autofill_assistant/browser/device_context.h" +#include "components/autofill_assistant/browser/mock_client.h" +#include "components/version_info/version_info.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace autofill_assistant { + +using ::testing::_; +using ::testing::ElementsAre; +using ::testing::Eq; +using ::testing::InSequence; +using ::testing::NiceMock; +using ::testing::Property; +using ::testing::Return; +using ::testing::StrEq; + +namespace { + +class ClientContextTest : public testing::Test { + protected: + ClientContextTest() {} + ~ClientContextTest() override {} + + NiceMock<MockClient> mock_client_; + DeviceContext device_context_; +}; + +TEST_F(ClientContextTest, Initialize) { + device_context_.version.sdk_int = 123; + device_context_.manufacturer.assign("manufacturer"); + device_context_.model.assign("model"); + + EXPECT_CALL(mock_client_, GetLocale()).WillOnce(Return("de-DE")); + EXPECT_CALL(mock_client_, GetCountryCode()).WillOnce(Return("ZZ")); + EXPECT_CALL(mock_client_, GetDeviceContext()) + .WillOnce(Return(device_context_)); + EXPECT_CALL(mock_client_, GetChromeSignedInEmailAddress()) + .WillOnce(Return("john.doe@chromium.org")); + EXPECT_CALL(mock_client_, IsAccessibilityEnabled()).WillOnce(Return(true)); + + ClientContextImpl client_context(&mock_client_); + + auto actual_client_context = client_context.AsProto(); + EXPECT_THAT(actual_client_context.chrome().chrome_version(), + Eq(version_info::GetProductNameAndVersionForUserAgent())); + EXPECT_THAT(actual_client_context.locale(), Eq("de-DE")); + EXPECT_THAT(actual_client_context.country(), Eq("ZZ")); + EXPECT_THAT(actual_client_context.experiment_ids(), Eq("")); + EXPECT_THAT(actual_client_context.is_cct(), Eq(false)); + EXPECT_THAT(actual_client_context.is_onboarding_shown(), Eq(false)); + EXPECT_THAT(actual_client_context.is_direct_action(), Eq(false)); + EXPECT_THAT(actual_client_context.accessibility_enabled(), Eq(true)); + EXPECT_THAT(actual_client_context.signed_into_chrome_status(), + Eq(ClientContextProto::SIGNED_IN)); + EXPECT_THAT(actual_client_context.accounts_matching_status(), + Eq(ClientContextProto::UNKNOWN)); + + auto actual_device_context = actual_client_context.device_context(); + EXPECT_THAT(actual_device_context.version().sdk_int(), Eq(123)); + EXPECT_THAT(actual_device_context.manufacturer(), Eq("manufacturer")); + EXPECT_THAT(actual_device_context.model(), Eq("model")); +} + +TEST_F(ClientContextTest, UpdateWithTriggerContext) { + EXPECT_CALL(mock_client_, GetChromeSignedInEmailAddress()) + .WillRepeatedly(Return("")); + EXPECT_CALL(mock_client_, IsAccessibilityEnabled()) + .WillRepeatedly(Return(true)); + + TriggerContextImpl trigger_context(/* params = */ {}, /* exp = */ "1,2,3"); + trigger_context.SetCCT(true); + trigger_context.SetOnboardingShown(true); + trigger_context.SetDirectAction(true); + trigger_context.SetCallerAccountHash("some_value"); + + ClientContextImpl client_context(&mock_client_); + client_context.Update(trigger_context); + + auto actual_client_context = client_context.AsProto(); + EXPECT_THAT(actual_client_context.experiment_ids(), Eq("1,2,3")); + EXPECT_THAT(actual_client_context.is_cct(), Eq(true)); + EXPECT_THAT(actual_client_context.is_onboarding_shown(), Eq(true)); + EXPECT_THAT(actual_client_context.is_direct_action(), Eq(true)); + EXPECT_THAT(actual_client_context.accessibility_enabled(), Eq(true)); + EXPECT_THAT(actual_client_context.experiment_ids(), Eq("1,2,3")); + EXPECT_THAT(actual_client_context.signed_into_chrome_status(), + Eq(ClientContextProto::NOT_SIGNED_IN)); + EXPECT_THAT(actual_client_context.accounts_matching_status(), + Eq(ClientContextProto::ACCOUNTS_NOT_MATCHING)); +} + +TEST_F(ClientContextTest, AccountMatching) { + EXPECT_CALL(mock_client_, GetChromeSignedInEmailAddress()) + .WillRepeatedly(Return("john.doe@chromium.org")); + + ClientContextImpl client_context(&mock_client_); + EXPECT_THAT(client_context.AsProto().accounts_matching_status(), + Eq(ClientContextProto::UNKNOWN)); + + // Should match john.doe@chromium.org. + TriggerContextImpl trigger_context; + trigger_context.SetCallerAccountHash( + "2c8fa87717fab622bb5cc4d18135fe30dae339efd274b450022d361be92b48c3"); + client_context.Update(trigger_context); + EXPECT_THAT(client_context.AsProto().accounts_matching_status(), + Eq(ClientContextProto::ACCOUNTS_MATCHING)); + + trigger_context.SetCallerAccountHash("different"); + client_context.Update(trigger_context); + EXPECT_THAT(client_context.AsProto().accounts_matching_status(), + Eq(ClientContextProto::ACCOUNTS_NOT_MATCHING)); +} + +TEST_F(ClientContextTest, SignedInStatus) { + EXPECT_CALL(mock_client_, GetChromeSignedInEmailAddress()) + .WillOnce(Return("")); + + ClientContextImpl client_context_a(&mock_client_); + EXPECT_THAT(client_context_a.AsProto().signed_into_chrome_status(), + Eq(ClientContextProto::NOT_SIGNED_IN)); + + EXPECT_CALL(mock_client_, GetChromeSignedInEmailAddress()) + .WillOnce(Return("john.doe@chromium.org")); + ClientContextImpl client_context_b(&mock_client_); + EXPECT_THAT(client_context_b.AsProto().signed_into_chrome_status(), + Eq(ClientContextProto::SIGNED_IN)); +} + +} // namespace +} // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc index cdca895e..b15ec88 100644 --- a/components/autofill_assistant/browser/controller.cc +++ b/components/autofill_assistant/browser/controller.cc
@@ -1154,13 +1154,10 @@ dict.SetKey("status", base::Value(status_message_)); if (trigger_context_) { - google::protobuf::RepeatedPtrField<ScriptParameterProto> parameters_proto; - trigger_context_->AddParameters(¶meters_proto); std::vector<base::Value> parameters_js; - for (const auto& parameter_proto : parameters_proto) { + for (const auto& parameter : trigger_context_->GetParameters()) { base::Value parameter_js = base::Value(base::Value::Type::DICTIONARY); - parameter_js.SetKey(parameter_proto.name(), - base::Value(parameter_proto.value())); + parameter_js.SetKey(parameter.first, base::Value(parameter.second)); parameters_js.push_back(std::move(parameter_js)); } dict.SetKey("parameters", base::Value(parameters_js));
diff --git a/components/autofill_assistant/browser/device_context.h b/components/autofill_assistant/browser/device_context.h index 4e0c143b..4b2272b 100644 --- a/components/autofill_assistant/browser/device_context.h +++ b/components/autofill_assistant/browser/device_context.h
@@ -15,7 +15,7 @@ Version(const Version& orig); ~Version(); - int sdk_int; + int sdk_int = -1; }; // Information about the device.
diff --git a/components/autofill_assistant/browser/mock_service.cc b/components/autofill_assistant/browser/mock_service.cc index 5951a6f..005ca78 100644 --- a/components/autofill_assistant/browser/mock_service.cc +++ b/components/autofill_assistant/browser/mock_service.cc
@@ -11,14 +11,7 @@ namespace autofill_assistant { MockService::MockService() - : ServiceImpl("api_key", - GURL("http://fake"), - nullptr, - nullptr, - "en_US", - "", - DeviceContext(), - nullptr) {} + : ServiceImpl("api_key", GURL("http://fake"), nullptr, nullptr, nullptr) {} MockService::~MockService() {} } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/protocol_utils.cc b/components/autofill_assistant/browser/protocol_utils.cc index acea58f..2f4d16f 100644 --- a/components/autofill_assistant/browser/protocol_utils.cc +++ b/components/autofill_assistant/browser/protocol_utils.cc
@@ -44,35 +44,13 @@ namespace { -void FillClientContext(const ClientContextProto& client_context, - const TriggerContext& trigger_context, - const std::string& client_account_hash, - ClientContextProto* proto) { - proto->CopyFrom(client_context); - std::string experiment_ids = trigger_context.experiment_ids(); - if (!experiment_ids.empty()) { - proto->set_experiment_ids(experiment_ids); - } - if (trigger_context.is_cct()) { - proto->set_is_cct(true); - } - if (trigger_context.is_onboarding_shown()) { - proto->set_is_onboarding_shown(true); - } - if (trigger_context.is_direct_action()) { - proto->set_is_direct_action(true); - } - // TODO(b/156882027): Add an integration test for accounts handling. - if (trigger_context.get_caller_account_hash().empty()) { - proto->set_accounts_matching_status(ClientContextProto::UNKNOWN); - } else { - if (trigger_context.get_caller_account_hash() == client_account_hash) { - proto->set_accounts_matching_status( - ClientContextProto::ACCOUNTS_MATCHING); - } else { - proto->set_accounts_matching_status( - ClientContextProto::ACCOUNTS_NOT_MATCHING); - } +void AppendScriptParametersToRepeatedField( + const std::map<std::string, std::string>& script_parameters, + google::protobuf::RepeatedPtrField<ScriptParameterProto>* dest) { + for (const auto& param_entry : script_parameters) { + ScriptParameterProto* parameter = dest->Add(); + parameter->set_name(param_entry.first); + parameter->set_value(param_entry.second); } } @@ -81,16 +59,15 @@ // static std::string ProtocolUtils::CreateGetScriptsRequest( const GURL& url, - const TriggerContext& trigger_context, const ClientContextProto& client_context, - const std::string& client_account_hash) { + const std::map<std::string, std::string>& script_parameters) { DCHECK(!url.is_empty()); SupportsScriptRequestProto script_proto; script_proto.set_url(url.spec()); - FillClientContext(client_context, trigger_context, client_account_hash, - script_proto.mutable_client_context()); - trigger_context.AddParameters(script_proto.mutable_script_parameters()); + *script_proto.mutable_client_context() = client_context; + AppendScriptParametersToRepeatedField( + script_parameters, script_proto.mutable_script_parameters()); std::string serialized_script_proto; bool success = script_proto.SerializeToString(&serialized_script_proto); DCHECK(success); @@ -137,11 +114,10 @@ std::string ProtocolUtils::CreateInitialScriptActionsRequest( const std::string& script_path, const GURL& url, - const TriggerContext& trigger_context, const std::string& global_payload, const std::string& script_payload, const ClientContextProto& client_context, - const std::string& client_account_hash) { + const std::map<std::string, std::string>& script_parameters) { ScriptActionRequestProto request_proto; InitialScriptActionsRequestProto* initial_request_proto = request_proto.mutable_initial_request(); @@ -150,10 +126,9 @@ query->add_script_path(script_path); query->set_url(url.spec()); query->set_policy(PolicyType::SCRIPT); - FillClientContext(client_context, trigger_context, client_account_hash, - request_proto.mutable_client_context()); - trigger_context.AddParameters( - initial_request_proto->mutable_script_parameters()); + *request_proto.mutable_client_context() = client_context; + AppendScriptParametersToRepeatedField( + script_parameters, initial_request_proto->mutable_script_parameters()); if (!global_payload.empty()) { request_proto.set_global_payload(global_payload); } @@ -170,12 +145,10 @@ // static std::string ProtocolUtils::CreateNextScriptActionsRequest( - const TriggerContext& trigger_context, const std::string& global_payload, const std::string& script_payload, const std::vector<ProcessedActionProto>& processed_actions, - const ClientContextProto& client_context, - const std::string& client_account_hash) { + const ClientContextProto& client_context) { ScriptActionRequestProto request_proto; request_proto.set_global_payload(global_payload); request_proto.set_script_payload(script_payload); @@ -184,8 +157,7 @@ for (const auto& processed_action : processed_actions) { next_request->add_processed_actions()->MergeFrom(processed_action); } - FillClientContext(client_context, trigger_context, client_account_hash, - request_proto.mutable_client_context()); + *request_proto.mutable_client_context() = client_context; std::string serialized_request_proto; bool success = request_proto.SerializeToString(&serialized_request_proto); DCHECK(success);
diff --git a/components/autofill_assistant/browser/protocol_utils.h b/components/autofill_assistant/browser/protocol_utils.h index 3ebfe51..11af7daa 100644 --- a/components/autofill_assistant/browser/protocol_utils.h +++ b/components/autofill_assistant/browser/protocol_utils.h
@@ -14,7 +14,6 @@ #include "components/autofill_assistant/browser/actions/action.h" #include "components/autofill_assistant/browser/script.h" #include "components/autofill_assistant/browser/service.pb.h" -#include "components/autofill_assistant/browser/trigger_context.h" class GURL; @@ -26,9 +25,8 @@ // |url|. static std::string CreateGetScriptsRequest( const GURL& url, - const TriggerContext& trigger_context, const ClientContextProto& client_context, - const std::string& client_account); + const std::map<std::string, std::string>& script_parameters); // Convert |script_proto| to a script struct and if the script is valid, add // it to |scripts|. @@ -42,20 +40,17 @@ static std::string CreateInitialScriptActionsRequest( const std::string& script_path, const GURL& url, - const TriggerContext& trigger_context, const std::string& global_payload, const std::string& script_payload, const ClientContextProto& client_context, - const std::string& client_account); + const std::map<std::string, std::string>& script_parameters); // Create request to get next sequence of actions for a script. static std::string CreateNextScriptActionsRequest( - const TriggerContext& trigger_context, const std::string& global_payload, const std::string& script_payload, const std::vector<ProcessedActionProto>& processed_actions, - const ClientContextProto& client_context, - const std::string& client_account); + const ClientContextProto& client_context); // Create an action from the |action|. static std::unique_ptr<Action> CreateAction(ActionDelegate* delegate,
diff --git a/components/autofill_assistant/browser/protocol_utils_unittest.cc b/components/autofill_assistant/browser/protocol_utils_unittest.cc index 4fb14bd0..481d1377 100644 --- a/components/autofill_assistant/browser/protocol_utils_unittest.cc +++ b/components/autofill_assistant/browser/protocol_utils_unittest.cc
@@ -16,26 +16,54 @@ using ::testing::Eq; using ::testing::IsEmpty; using ::testing::Not; +using ::testing::Pair; using ::testing::SizeIs; +using ::testing::UnorderedElementsAreArray; -ClientContextProto CreateClientContextProto() { - ClientContextProto context; - context.mutable_chrome()->set_chrome_version("v"); - auto* device_context = context.mutable_device_context(); - device_context->mutable_version()->set_sdk_int(1); - device_context->set_manufacturer("ma"); - device_context->set_model("mo"); - return context; -} +class ProtocolUtilsTest : public testing::Test { + protected: + ProtocolUtilsTest() { + client_context_proto_.set_experiment_ids("1,2,3"); + client_context_proto_.set_is_cct(true); + client_context_proto_.mutable_chrome()->set_chrome_version("v"); + auto* device_context = client_context_proto_.mutable_device_context(); + device_context->mutable_version()->set_sdk_int(1); + device_context->set_manufacturer("ma"); + device_context->set_model("mo"); + client_context_proto_.set_is_onboarding_shown(false); + client_context_proto_.set_is_direct_action(false); + client_context_proto_.set_accounts_matching_status( + ClientContextProto::UNKNOWN); + } + ~ProtocolUtilsTest() override {} + + ClientContextProto client_context_proto_; +}; void AssertClientContext(const ClientContextProto& context) { + EXPECT_EQ("1,2,3", context.experiment_ids()); + EXPECT_TRUE(context.is_cct()); EXPECT_EQ("v", context.chrome().chrome_version()); EXPECT_EQ(1, context.device_context().version().sdk_int()); EXPECT_EQ("ma", context.device_context().manufacturer()); EXPECT_EQ("mo", context.device_context().model()); + EXPECT_FALSE(context.is_onboarding_shown()); + EXPECT_FALSE(context.is_direct_action()); + EXPECT_THAT(context.accounts_matching_status(), + Eq(ClientContextProto::UNKNOWN)); } -TEST(ProtocolUtilsTest, ScriptMissingPath) { +void AssertScriptParameters( + const google::protobuf::RepeatedPtrField<ScriptParameterProto>& actual, + const std::map<std::string, std::string>& expected) { + std::map<std::string, std::string> actual_as_map; + for (const auto& actual_parameter : actual) { + actual_as_map[actual_parameter.name()] = actual_parameter.value(); + } + EXPECT_THAT(actual_as_map, UnorderedElementsAreArray(expected)); +} + +TEST_F(ProtocolUtilsTest, ScriptMissingPath) { SupportedScriptProto script; script.mutable_presentation()->mutable_chip()->set_text("missing path"); std::vector<std::unique_ptr<Script>> scripts; @@ -44,7 +72,7 @@ EXPECT_THAT(scripts, IsEmpty()); } -TEST(ProtocolUtilsTest, MinimalValidScript) { +TEST_F(ProtocolUtilsTest, MinimalValidScript) { SupportedScriptProto script; script.set_path("path"); script.mutable_presentation()->mutable_chip()->set_text("name"); @@ -57,7 +85,7 @@ EXPECT_NE(nullptr, scripts[0]->precondition); } -TEST(ProtocolUtilsTest, AllowInterruptsWithNoName) { +TEST_F(ProtocolUtilsTest, AllowInterruptsWithNoName) { SupportedScriptProto script_proto; script_proto.set_path("path"); auto* presentation = script_proto.mutable_presentation(); @@ -74,7 +102,7 @@ EXPECT_TRUE(scripts[0]->handle.interrupt); } -TEST(ProtocolUtilsTest, InterruptsCannotBeAutostart) { +TEST_F(ProtocolUtilsTest, InterruptsCannotBeAutostart) { SupportedScriptProto script_proto; script_proto.set_path("path"); auto* presentation = script_proto.mutable_presentation(); @@ -89,244 +117,59 @@ EXPECT_TRUE(scripts[0]->handle.interrupt); } -TEST(ProtocolUtilsTest, CreateInitialScriptActionsRequest) { - std::map<std::string, std::string> parameters; - parameters["a"] = "b"; - parameters["c"] = "d"; - TriggerContextImpl trigger_context(parameters, "1,2,3"); - trigger_context.SetCCT(true); - +TEST_F(ProtocolUtilsTest, CreateInitialScriptActionsRequest) { + std::map<std::string, std::string> parameters = {{"key_a", "value_a"}, + {"key_b", "value_b"}}; ScriptActionRequestProto request; EXPECT_TRUE( request.ParseFromString(ProtocolUtils::CreateInitialScriptActionsRequest( - "script_path", GURL("http://example.com/"), trigger_context, - "global_payload", "script_payload", CreateClientContextProto(), - "accountsha"))); - - AssertClientContext(request.client_context()); - EXPECT_THAT(request.client_context().experiment_ids(), Eq("1,2,3")); - EXPECT_TRUE(request.client_context().is_cct()); - EXPECT_FALSE(request.client_context().is_onboarding_shown()); - EXPECT_FALSE(request.client_context().is_direct_action()); - EXPECT_THAT(request.client_context().accounts_matching_status(), - Eq(ClientContextProto::UNKNOWN)); + "script_path", GURL("http://example.com/"), "global_payload", + "script_payload", client_context_proto_, parameters))); const InitialScriptActionsRequestProto& initial = request.initial_request(); EXPECT_THAT(initial.query().script_path(), ElementsAre("script_path")); EXPECT_EQ(initial.query().url(), "http://example.com/"); - ASSERT_EQ(2, initial.script_parameters_size()); - EXPECT_EQ("a", initial.script_parameters(0).name()); - EXPECT_EQ("b", initial.script_parameters(0).value()); - EXPECT_EQ("c", initial.script_parameters(1).name()); - EXPECT_EQ("d", initial.script_parameters(1).value()); + AssertScriptParameters(initial.script_parameters(), parameters); + + AssertClientContext(request.client_context()); EXPECT_EQ("global_payload", request.global_payload()); EXPECT_EQ("script_payload", request.script_payload()); } -TEST(ProtocolUtilsTest, TestCreateInitialScriptActionsRequestFlags) { - std::map<std::string, std::string> parameters; - - ScriptActionRequestProto request; - - // With flags. - TriggerContextImpl trigger_context_flags(parameters, std::string()); - trigger_context_flags.SetCCT(true); - trigger_context_flags.SetOnboardingShown(true); - trigger_context_flags.SetDirectAction(true); - trigger_context_flags.SetCallerAccountHash("accountsha"); - - EXPECT_TRUE( - request.ParseFromString(ProtocolUtils::CreateInitialScriptActionsRequest( - "script_path", GURL("http://example.com/"), trigger_context_flags, - "global_payload", "script_payload", CreateClientContextProto(), - "accountsha"))); - - AssertClientContext(request.client_context()); - EXPECT_TRUE(request.client_context().is_cct()); - EXPECT_TRUE(request.client_context().is_onboarding_shown()); - EXPECT_TRUE(request.client_context().is_direct_action()); - EXPECT_THAT(request.client_context().accounts_matching_status(), - Eq(ClientContextProto::ACCOUNTS_MATCHING)); - - // Without flags. - TriggerContextImpl trigger_context_no_flags(parameters, std::string()); - - EXPECT_TRUE( - request.ParseFromString(ProtocolUtils::CreateInitialScriptActionsRequest( - "script_path", GURL("http://example.com/"), trigger_context_no_flags, - "global_payload", "script_payload", CreateClientContextProto(), - "accountsha"))); - - AssertClientContext(request.client_context()); - EXPECT_FALSE(request.client_context().is_cct()); - EXPECT_FALSE(request.client_context().is_onboarding_shown()); - EXPECT_FALSE(request.client_context().is_direct_action()); - EXPECT_THAT(request.client_context().accounts_matching_status(), - Eq(ClientContextProto::UNKNOWN)); -} - -TEST(ProtocolUtilsTest, - TestCreateInitialScriptActionsRequestAccountsNotMatching) { - std::map<std::string, std::string> parameters; - - ScriptActionRequestProto request; - - // With flags. - TriggerContextImpl trigger_context_flags(parameters, std::string()); - trigger_context_flags.SetCCT(true); - trigger_context_flags.SetOnboardingShown(true); - trigger_context_flags.SetDirectAction(true); - trigger_context_flags.SetCallerAccountHash("accountsha"); - - EXPECT_TRUE( - request.ParseFromString(ProtocolUtils::CreateInitialScriptActionsRequest( - "script_path", GURL("http://example.com/"), trigger_context_flags, - "global_payload", "script_payload", CreateClientContextProto(), - "differentaccountsha"))); - - AssertClientContext(request.client_context()); - EXPECT_TRUE(request.client_context().is_cct()); - EXPECT_TRUE(request.client_context().is_onboarding_shown()); - EXPECT_TRUE(request.client_context().is_direct_action()); - EXPECT_THAT(request.client_context().accounts_matching_status(), - Eq(ClientContextProto::ACCOUNTS_NOT_MATCHING)); -} - -TEST(ProtocolUtilsTest, CreateNextScriptActionsRequest) { - std::map<std::string, std::string> parameters; - parameters["a"] = "b"; - parameters["c"] = "d"; - TriggerContextImpl trigger_context(parameters, "1,2,3"); - +TEST_F(ProtocolUtilsTest, CreateNextScriptActionsRequest) { ScriptActionRequestProto request; std::vector<ProcessedActionProto> processed_actions; processed_actions.emplace_back(ProcessedActionProto()); EXPECT_TRUE( request.ParseFromString(ProtocolUtils::CreateNextScriptActionsRequest( - trigger_context, "global_payload", "script_payload", - processed_actions, CreateClientContextProto(), "accountsha"))); + "global_payload", "script_payload", processed_actions, + client_context_proto_))); AssertClientContext(request.client_context()); - EXPECT_THAT(request.client_context().experiment_ids(), Eq("1,2,3")); EXPECT_EQ(1, request.next_request().processed_actions().size()); } -TEST(ProtocolUtilsTest, TestCreateNextScriptActionsRequestFlags) { - std::map<std::string, std::string> parameters; - - std::vector<ProcessedActionProto> processed_actions; - processed_actions.emplace_back(ProcessedActionProto()); - - ScriptActionRequestProto request; - - // With flags. - TriggerContextImpl trigger_context_flags(parameters, std::string()); - trigger_context_flags.SetCCT(true); - trigger_context_flags.SetOnboardingShown(true); - trigger_context_flags.SetDirectAction(true); - trigger_context_flags.SetCallerAccountHash("accountsha"); - - EXPECT_TRUE( - request.ParseFromString(ProtocolUtils::CreateNextScriptActionsRequest( - trigger_context_flags, "global_payload", "script_payload", - processed_actions, CreateClientContextProto(), "accountsha"))); - - AssertClientContext(request.client_context()); - EXPECT_TRUE(request.client_context().is_cct()); - EXPECT_TRUE(request.client_context().is_onboarding_shown()); - EXPECT_TRUE(request.client_context().is_direct_action()); - EXPECT_THAT(request.client_context().accounts_matching_status(), - Eq(ClientContextProto::ACCOUNTS_MATCHING)); - - // Without flags. - TriggerContextImpl trigger_context_no_flags(parameters, std::string()); - - EXPECT_TRUE( - request.ParseFromString(ProtocolUtils::CreateNextScriptActionsRequest( - trigger_context_no_flags, "global_payload", "script_payload", - processed_actions, CreateClientContextProto(), "accountsha"))); - - AssertClientContext(request.client_context()); - EXPECT_FALSE(request.client_context().is_cct()); - EXPECT_FALSE(request.client_context().is_onboarding_shown()); - EXPECT_FALSE(request.client_context().is_direct_action()); - EXPECT_THAT(request.client_context().accounts_matching_status(), - Eq(ClientContextProto::UNKNOWN)); -} - -TEST(ProtocolUtilsTest, CreateGetScriptsRequest) { - std::map<std::string, std::string> parameters; - parameters["a"] = "b"; - parameters["c"] = "d"; - TriggerContextImpl trigger_context(parameters, "1,2,3"); - trigger_context.SetDirectAction(true); +TEST_F(ProtocolUtilsTest, CreateGetScriptsRequest) { + std::map<std::string, std::string> parameters = {{"key_a", "value_a"}, + {"key_b", "value_b"}}; SupportsScriptRequestProto request; EXPECT_TRUE(request.ParseFromString(ProtocolUtils::CreateGetScriptsRequest( - GURL("http://example.com/"), trigger_context, CreateClientContextProto(), - "accountsha"))); + GURL("http://example.com/"), client_context_proto_, parameters))); AssertClientContext(request.client_context()); - EXPECT_THAT(request.client_context().experiment_ids(), Eq("1,2,3")); - EXPECT_FALSE(request.client_context().is_cct()); - EXPECT_FALSE(request.client_context().is_onboarding_shown()); - EXPECT_TRUE(request.client_context().is_direct_action()); - EXPECT_THAT(request.client_context().accounts_matching_status(), - Eq(ClientContextProto::UNKNOWN)); - + AssertScriptParameters(request.script_parameters(), parameters); EXPECT_EQ("http://example.com/", request.url()); - ASSERT_EQ(2, request.script_parameters_size()); - EXPECT_EQ("a", request.script_parameters(0).name()); - EXPECT_EQ("b", request.script_parameters(0).value()); - EXPECT_EQ("c", request.script_parameters(1).name()); - EXPECT_EQ("d", request.script_parameters(1).value()); } -TEST(ProtocolUtilsTest, TestCreateGetScriptsRequestFlags) { - std::map<std::string, std::string> parameters; - SupportsScriptRequestProto request; - - // With flags. - TriggerContextImpl trigger_context_flags(parameters, std::string()); - trigger_context_flags.SetCCT(true); - trigger_context_flags.SetOnboardingShown(true); - trigger_context_flags.SetDirectAction(true); - trigger_context_flags.SetCallerAccountHash("accountsha"); - - EXPECT_TRUE(request.ParseFromString(ProtocolUtils::CreateGetScriptsRequest( - GURL("http://example.com/"), trigger_context_flags, - CreateClientContextProto(), "accountsha"))); - - AssertClientContext(request.client_context()); - EXPECT_TRUE(request.client_context().is_cct()); - EXPECT_TRUE(request.client_context().is_onboarding_shown()); - EXPECT_TRUE(request.client_context().is_direct_action()); - EXPECT_THAT(request.client_context().accounts_matching_status(), - Eq(ClientContextProto::ACCOUNTS_MATCHING)); - - // Without flags. - TriggerContextImpl trigger_context_no_flags(parameters, std::string()); - - EXPECT_TRUE(request.ParseFromString(ProtocolUtils::CreateGetScriptsRequest( - GURL("http://example.com/"), trigger_context_no_flags, - CreateClientContextProto(), "accountsha"))); - - AssertClientContext(request.client_context()); - EXPECT_FALSE(request.client_context().is_cct()); - EXPECT_FALSE(request.client_context().is_onboarding_shown()); - EXPECT_FALSE(request.client_context().is_direct_action()); - EXPECT_THAT(request.client_context().accounts_matching_status(), - Eq(ClientContextProto::UNKNOWN)); -} - -TEST(ProtocolUtilsTest, AddScriptIgnoreInvalid) { +TEST_F(ProtocolUtilsTest, AddScriptIgnoreInvalid) { SupportedScriptProto script_proto; std::vector<std::unique_ptr<Script>> scripts; ProtocolUtils::AddScript(script_proto, &scripts); EXPECT_TRUE(scripts.empty()); } -TEST(ProtocolUtilsTest, AddScriptWithChip) { +TEST_F(ProtocolUtilsTest, AddScriptWithChip) { SupportedScriptProto script_proto; script_proto.set_path("path"); auto* presentation = script_proto.mutable_presentation(); @@ -346,7 +189,7 @@ EXPECT_NE(nullptr, script->precondition); } -TEST(ProtocolUtilsTest, AddScriptWithDirectAction) { +TEST_F(ProtocolUtilsTest, AddScriptWithDirectAction) { SupportedScriptProto script_proto; script_proto.set_path("path"); auto* presentation = script_proto.mutable_presentation(); @@ -365,7 +208,7 @@ EXPECT_NE(nullptr, script->precondition); } -TEST(ProtocolUtilsTest, AddAutostartableScript) { +TEST_F(ProtocolUtilsTest, AddAutostartableScript) { SupportedScriptProto script_proto; script_proto.set_path("path"); auto* presentation = script_proto.mutable_presentation(); @@ -384,7 +227,7 @@ EXPECT_NE(nullptr, script->precondition); } -TEST(ProtocolUtilsTest, SkipAutostartableScriptWithoutName) { +TEST_F(ProtocolUtilsTest, SkipAutostartableScriptWithoutName) { SupportedScriptProto script_proto; script_proto.set_path("path"); auto* presentation = script_proto.mutable_presentation(); @@ -396,7 +239,7 @@ EXPECT_THAT(scripts, IsEmpty()); } -TEST(ProtocolUtilsTest, ParseActionsParseError) { +TEST_F(ProtocolUtilsTest, ParseActionsParseError) { bool unused; std::vector<std::unique_ptr<Action>> unused_actions; std::vector<std::unique_ptr<Script>> unused_scripts; @@ -405,7 +248,7 @@ &unused)); } -TEST(ProtocolUtilsTest, ParseActionsValid) { +TEST_F(ProtocolUtilsTest, ParseActionsValid) { ActionsResponseProto proto; proto.set_global_payload("global_payload"); proto.set_script_payload("script_payload"); @@ -431,7 +274,7 @@ EXPECT_TRUE(scripts.empty()); } -TEST(ProtocolUtilsTest, ParseActionsEmptyUpdateScriptList) { +TEST_F(ProtocolUtilsTest, ParseActionsEmptyUpdateScriptList) { ActionsResponseProto proto; proto.mutable_update_script_list(); @@ -450,7 +293,7 @@ EXPECT_TRUE(scripts.empty()); } -TEST(ProtocolUtilsTest, ParseActionsUpdateScriptListFullFeatured) { +TEST_F(ProtocolUtilsTest, ParseActionsUpdateScriptListFullFeatured) { ActionsResponseProto proto; auto* script_list = proto.mutable_update_script_list(); auto* script_a = script_list->add_scripts();
diff --git a/components/autofill_assistant/browser/service_impl.cc b/components/autofill_assistant/browser/service_impl.cc index b18851ce..0c18a73a 100644 --- a/components/autofill_assistant/browser/service_impl.cc +++ b/components/autofill_assistant/browser/service_impl.cc
@@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/command_line.h" -#include "base/metrics/field_trial.h" #include "base/strings/strcat.h" #include "base/strings/stringprintf.h" #include "components/autofill_assistant/browser/client.h" @@ -20,7 +19,6 @@ #include "components/version_info/version_info.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h" -#include "crypto/sha2.h" #include "google_apis/google_api_keys.h" #include "net/base/load_flags.h" #include "net/http/http_request_headers.h" @@ -91,27 +89,37 @@ return std::make_unique<ServiceImpl>( GetAPIKey(client->GetChannel()), server_url, context, - client->GetAccessTokenFetcher(), client->GetLocale(), - client->GetCountryCode(), client->GetDeviceContext(), client); + std::make_unique<ClientContextImpl>(client), + client->GetAccessTokenFetcher()); } ServiceImpl::ServiceImpl(const std::string& api_key, const GURL& server_url, content::BrowserContext* context, + std::unique_ptr<ClientContext> client_context, + AccessTokenFetcher* access_token_fetcher) + : ServiceImpl( + api_key, + server_url, + context, + std::move(client_context), + access_token_fetcher, + /* auth_enabled = */ "false" != + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kAutofillAssistantAuth)) {} + +ServiceImpl::ServiceImpl(const std::string& api_key, + const GURL& server_url, + content::BrowserContext* context, + std::unique_ptr<ClientContext> client_context, AccessTokenFetcher* access_token_fetcher, - const std::string& locale, - const std::string& country_code, - const DeviceContext& device_context, - const Client* client, bool auth_enabled) : context_(context), api_key_(api_key), + client_context_(std::move(client_context)), access_token_fetcher_(access_token_fetcher), fetching_token_(false), auth_enabled_(auth_enabled), - client_context_( - CreateClientContext(locale, country_code, device_context)), - client_(client), weak_ptr_factory_(this) { DCHECK(server_url.is_valid()); @@ -125,27 +133,6 @@ VLOG(1) << "Using script domain " << script_action_server_url_.host(); } -ServiceImpl::ServiceImpl(const std::string& api_key, - const GURL& server_url, - content::BrowserContext* context, - AccessTokenFetcher* access_token_fetcher, - const std::string& locale, - const std::string& country_code, - const DeviceContext& device_context, - const Client* client) - : ServiceImpl( - api_key, - server_url, - context, - access_token_fetcher, - locale, - country_code, - device_context, - client, - /* auth_enabled = */ "false" != - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kAutofillAssistantAuth)) {} - ServiceImpl::~ServiceImpl() {} void ServiceImpl::GetScriptsForUrl(const GURL& url, @@ -153,11 +140,11 @@ ResponseCallback callback) { DCHECK(url.is_valid()); - UpdateMutableClientContextFields(); + client_context_->Update(trigger_context); SendRequest(AddLoader( script_server_url_, - ProtocolUtils::CreateGetScriptsRequest( - url, trigger_context, client_context_, GetClientAccountHash()), + ProtocolUtils::CreateGetScriptsRequest(url, client_context_->AsProto(), + trigger_context.GetParameters()), std::move(callback))); } @@ -169,13 +156,13 @@ ResponseCallback callback) { DCHECK(!script_path.empty()); - UpdateMutableClientContextFields(); - SendRequest( - AddLoader(script_action_server_url_, - ProtocolUtils::CreateInitialScriptActionsRequest( - script_path, url, trigger_context, global_payload, - script_payload, client_context_, GetClientAccountHash()), - std::move(callback))); + client_context_->Update(trigger_context); + SendRequest(AddLoader( + script_action_server_url_, + ProtocolUtils::CreateInitialScriptActionsRequest( + script_path, url, global_payload, script_payload, + client_context_->AsProto(), trigger_context.GetParameters()), + std::move(callback))); } void ServiceImpl::GetNextActions( @@ -184,13 +171,12 @@ const std::string& previous_script_payload, const std::vector<ProcessedActionProto>& processed_actions, ResponseCallback callback) { - UpdateMutableClientContextFields(); - SendRequest(AddLoader( - script_action_server_url_, - ProtocolUtils::CreateNextScriptActionsRequest( - trigger_context, previous_global_payload, previous_script_payload, - processed_actions, client_context_, GetClientAccountHash()), - std::move(callback))); + client_context_->Update(trigger_context); + SendRequest(AddLoader(script_action_server_url_, + ProtocolUtils::CreateNextScriptActionsRequest( + previous_global_payload, previous_script_payload, + processed_actions, client_context_->AsProto()), + std::move(callback))); } void ServiceImpl::SendRequest(Loader* loader) { @@ -328,42 +314,4 @@ } } -std::string ServiceImpl::GetClientAccountHash() const { - std::string chrome_account_sha_bin = - crypto::SHA256HashString(client_->GetChromeSignedInEmailAddress()); - return base::ToLowerASCII(base::HexEncode(chrome_account_sha_bin.data(), - chrome_account_sha_bin.size())); -} - -// static -ClientContextProto ServiceImpl::CreateClientContext( - const std::string& locale, - const std::string& country_code, - const DeviceContext& device_context) { - ClientContextProto context; - context.mutable_chrome()->set_chrome_version( - version_info::GetProductNameAndVersionForUserAgent()); - context.set_locale(locale); - context.set_country(country_code); - device_context.ToProto(context.mutable_device_context()); - - base::FieldTrial::ActiveGroups active_groups; - base::FieldTrialList::GetActiveFieldTrialGroups(&active_groups); - for (const auto& group : active_groups) { - FieldTrialProto* field_trial = - context.mutable_chrome()->add_active_field_trials(); - field_trial->set_trial_name(group.trial_name); - field_trial->set_group_name(group.group_name); - } - return context; -} - -void ServiceImpl::UpdateMutableClientContextFields() { - client_context_.set_accessibility_enabled(client_->IsAccessibilityEnabled()); - client_context_.set_signed_into_chrome_status( - client_->GetChromeSignedInEmailAddress().empty() - ? ClientContextProto::NOT_SIGNED_IN - : ClientContextProto::SIGNED_IN); -} - } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/service_impl.h b/components/autofill_assistant/browser/service_impl.h index 0f4c085..333e98e6 100644 --- a/components/autofill_assistant/browser/service_impl.h +++ b/components/autofill_assistant/browser/service_impl.h
@@ -13,6 +13,7 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" #include "components/autofill_assistant/browser/access_token_fetcher.h" +#include "components/autofill_assistant/browser/client_context.h" #include "components/autofill_assistant/browser/device_context.h" #include "components/autofill_assistant/browser/service.h" #include "components/autofill_assistant/browser/service.pb.h" @@ -33,8 +34,8 @@ // TODO(b/158998456): Add unit tests. class ServiceImpl : public Service { public: - // Convenience method for creating a service from a client. - // |client| must remain valid for the lifetime of the service instance. + // Convenience method for creating a service. |context| and |client| must + // remain valid for the lifetime of the service instance. static std::unique_ptr<ServiceImpl> Create(content::BrowserContext* context, Client* client); @@ -44,20 +45,14 @@ ServiceImpl(const std::string& api_key, const GURL& server_url, content::BrowserContext* context, - AccessTokenFetcher* token_fetcher, - const std::string& locale, - const std::string& country_code, - const DeviceContext& device_context, - const Client* client); + std::unique_ptr<ClientContext> client_context, + AccessTokenFetcher* access_token_fetcher); // Same as above, but allows overriding authentication settings. ServiceImpl(const std::string& api_key, const GURL& server_url, content::BrowserContext* context, - AccessTokenFetcher* token_fetcher, - const std::string& locale, - const std::string& country_code, - const DeviceContext& device_context, - const Client* client, + std::unique_ptr<ClientContext> client_context, + AccessTokenFetcher* access_token_fetcher, bool auth_enabled); ~ServiceImpl() override; @@ -115,16 +110,6 @@ // in |loaders_|. void FetchAccessToken(); void OnFetchAccessToken(bool success, const std::string& access_token); - std::string GetClientAccountHash() const; - - // Creates and fills a client context protobuf message. - static ClientContextProto CreateClientContext( - const std::string& locale, - const std::string& country_code, - const DeviceContext& device_context); - // Updates the subset of |client_context_| fields that may change during a - // flow. - void UpdateMutableClientContextFields(); content::BrowserContext* context_; GURL script_server_url_; @@ -136,6 +121,9 @@ // API key to add to the URL of unauthenticated requests. std::string api_key_; + // The client context to send to the backend. + std::unique_ptr<ClientContext> client_context_; + // Pointer must remain valid for the lifetime of the Service instance. AccessTokenFetcher* access_token_fetcher_; @@ -149,12 +137,6 @@ // invalidated. std::string access_token_; - // The client context is cached here to avoid having to recreate it for - // every message. - ClientContextProto client_context_; - - const Client* client_; - base::WeakPtrFactory<ServiceImpl> weak_ptr_factory_; FRIEND_TEST_ALL_PREFIXES(ServiceImplTestSignedInStatus, SetsSignedInStatus);
diff --git a/components/autofill_assistant/browser/service_impl_unittest.cc b/components/autofill_assistant/browser/service_impl_unittest.cc deleted file mode 100644 index ce97f93..0000000 --- a/components/autofill_assistant/browser/service_impl_unittest.cc +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright 2020 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/autofill_assistant/browser/service_impl.h" - -#include "components/autofill/core/browser/personal_data_manager.h" -#include "components/autofill_assistant/browser/client.h" -#include "components/autofill_assistant/browser/device_context.h" -#include "components/autofill_assistant/browser/metrics.h" -#include "components/autofill_assistant/browser/mock_client.h" -#include "components/autofill_assistant/browser/website_login_manager.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace autofill_assistant { - -using ::testing::Return; - -class ServiceImplTest : public ::testing::Test { - public: - ServiceImplTest() { - service_impl_ = ServiceImpl::Create(nullptr, &mock_client_); - } - - protected: - std::string GetClientAccountHash() { - return service_impl_->GetClientAccountHash(); - } - - MockClient mock_client_; - std::unique_ptr<ServiceImpl> service_impl_; -}; - -TEST_F(ServiceImplTest, CreatesValidHashFromEmail) { - ON_CALL(mock_client_, GetChromeSignedInEmailAddress) - .WillByDefault(Return("john.doe@chromium.org")); - EXPECT_EQ(GetClientAccountHash(), - "2c8fa87717fab622bb5cc4d18135fe30dae339efd274b450022d361be92b48c3"); -} - -class ServiceImplTestSignedInStatus - : public ServiceImplTest, - public testing::WithParamInterface< - std::pair<std::string, ClientContextProto::SignedIntoChromeStatus>> { -}; - -INSTANTIATE_TEST_SUITE_P( - ParametrizedTests, - ServiceImplTestSignedInStatus, - testing::Values(std::make_pair("", ClientContextProto::NOT_SIGNED_IN), - std::make_pair("bob@email.com", - ClientContextProto::SIGNED_IN))); - -TEST_P(ServiceImplTestSignedInStatus, SetsSignedInStatus) { - ON_CALL(mock_client_, GetChromeSignedInEmailAddress) - .WillByDefault(Return(GetParam().first)); - service_impl_->UpdateMutableClientContextFields(); - EXPECT_EQ(service_impl_->client_context_.signed_into_chrome_status(), - GetParam().second); -} - -} // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/trigger_context.cc b/components/autofill_assistant/browser/trigger_context.cc index ab59be5..ae904963 100644 --- a/components/autofill_assistant/browser/trigger_context.cc +++ b/components/autofill_assistant/browser/trigger_context.cc
@@ -38,13 +38,8 @@ TriggerContextImpl::~TriggerContextImpl() = default; -void TriggerContextImpl::AddParameters( - google::protobuf::RepeatedPtrField<ScriptParameterProto>* dest) const { - for (const auto& param_entry : parameters_) { - ScriptParameterProto* parameter = dest->Add(); - parameter->set_name(param_entry.first); - parameter->set_value(param_entry.second); - } +std::map<std::string, std::string> TriggerContextImpl::GetParameters() const { + return parameters_; } base::Optional<std::string> TriggerContextImpl::GetParameter( @@ -91,11 +86,14 @@ MergedTriggerContext::~MergedTriggerContext() {} -void MergedTriggerContext::AddParameters( - google::protobuf::RepeatedPtrField<ScriptParameterProto>* dest) const { +std::map<std::string, std::string> MergedTriggerContext::GetParameters() const { + std::map<std::string, std::string> merged_parameters; for (const TriggerContext* context : contexts_) { - context->AddParameters(dest); + for (const auto& parameter : context->GetParameters()) { + merged_parameters.insert(parameter); + } } + return merged_parameters; } base::Optional<std::string> MergedTriggerContext::GetParameter(
diff --git a/components/autofill_assistant/browser/trigger_context.h b/components/autofill_assistant/browser/trigger_context.h index 735a1b5c..5c6695f 100644 --- a/components/autofill_assistant/browser/trigger_context.h +++ b/components/autofill_assistant/browser/trigger_context.h
@@ -37,9 +37,8 @@ TriggerContext(); virtual ~TriggerContext(); - // Adds all parameters to the given proto field. - virtual void AddParameters( - google::protobuf::RepeatedPtrField<ScriptParameterProto>* dest) const = 0; + // Returns all parameters as a map. + virtual std::map<std::string, std::string> GetParameters() const = 0; // Returns the value of a specific parameter, if present. virtual base::Optional<std::string> GetParameter( @@ -86,8 +85,7 @@ } // Implements TriggerContext: - void AddParameters(google::protobuf::RepeatedPtrField<ScriptParameterProto>* - dest) const override; + std::map<std::string, std::string> GetParameters() const override; base::Optional<std::string> GetParameter( const std::string& name) const override; std::string experiment_ids() const override; @@ -123,8 +121,7 @@ ~MergedTriggerContext() override; // Implements TriggerContext: - void AddParameters(google::protobuf::RepeatedPtrField<ScriptParameterProto>* - dest) const override; + std::map<std::string, std::string> GetParameters() const override; base::Optional<std::string> GetParameter( const std::string& name) const override; std::string experiment_ids() const override;
diff --git a/components/autofill_assistant/browser/trigger_context_unittest.cc b/components/autofill_assistant/browser/trigger_context_unittest.cc index 2268ae16d..5773fdb1 100644 --- a/components/autofill_assistant/browser/trigger_context_unittest.cc +++ b/components/autofill_assistant/browser/trigger_context_unittest.cc
@@ -10,51 +10,40 @@ namespace autofill_assistant { namespace { +using ::testing::Eq; using ::testing::IsEmpty; +using ::testing::Pair; using ::testing::SizeIs; +using ::testing::UnorderedElementsAre; TEST(TriggerContextTest, Empty) { auto empty = TriggerContext::CreateEmpty(); ASSERT_TRUE(empty); - google::protobuf::RepeatedPtrField<ScriptParameterProto> parameters_proto; - empty->AddParameters(¶meters_proto); - EXPECT_THAT(parameters_proto, IsEmpty()); - + EXPECT_THAT(empty->GetParameters(), IsEmpty()); EXPECT_EQ("", empty->experiment_ids()); } TEST(TriggerContextTest, Create) { - std::map<std::string, std::string> parameters; - parameters["a"] = "b"; - parameters["c"] = "d"; + std::map<std::string, std::string> parameters = {{"key_a", "value_a"}, + {"key_b", "value_b"}}; auto context = TriggerContext::Create(parameters, "exps"); ASSERT_TRUE(context); - google::protobuf::RepeatedPtrField<ScriptParameterProto> parameters_proto; - context->AddParameters(¶meters_proto); - EXPECT_THAT(parameters_proto, SizeIs(2)); + EXPECT_THAT( + context->GetParameters(), + UnorderedElementsAre(Pair("key_a", "value_a"), Pair("key_b", "value_b"))); - EXPECT_EQ("a", parameters_proto.Get(0).name()); - EXPECT_EQ("b", parameters_proto.Get(0).value()); - EXPECT_EQ("c", parameters_proto.Get(1).name()); - EXPECT_EQ("d", parameters_proto.Get(1).value()); - - EXPECT_EQ("b", context->GetParameter("a").value_or("")); - EXPECT_EQ("d", context->GetParameter("c").value_or("")); - EXPECT_FALSE(context->GetParameter("not_found")); + EXPECT_THAT(context->GetParameter("key_a"), Eq("value_a")); + EXPECT_THAT(context->GetParameter("key_b"), Eq("value_b")); + EXPECT_THAT(context->GetParameter("not_found"), Eq(base::nullopt)); EXPECT_EQ("exps", context->experiment_ids()); } TEST(TriggerContextTest, Merge) { - std::map<std::string, std::string> parameters; - parameters["a"] = "b"; - auto context1 = TriggerContext::Create(parameters, "exp1"); - - parameters.clear(); - parameters["c"] = "d"; - auto context2 = TriggerContext::Create(parameters, "exp2"); + auto context1 = TriggerContext::Create({{"key_a", "value_a"}}, "exp1"); + auto context2 = TriggerContext::Create({{"key_b", "value_b"}}, "exp2"); // Adding empty to make sure empty contexts are properly skipped auto empty = TriggerContext::CreateEmpty(); @@ -64,20 +53,15 @@ ASSERT_TRUE(merged); - google::protobuf::RepeatedPtrField<ScriptParameterProto> parameters_proto; - merged->AddParameters(¶meters_proto); - EXPECT_THAT(parameters_proto, SizeIs(2)); + EXPECT_THAT( + merged->GetParameters(), + UnorderedElementsAre(Pair("key_a", "value_a"), Pair("key_b", "value_b"))); - EXPECT_EQ("a", parameters_proto.Get(0).name()); - EXPECT_EQ("b", parameters_proto.Get(0).value()); - EXPECT_EQ("c", parameters_proto.Get(1).name()); - EXPECT_EQ("d", parameters_proto.Get(1).value()); + EXPECT_THAT(merged->GetParameter("key_a"), Eq("value_a")); + EXPECT_THAT(merged->GetParameter("key_b"), Eq("value_b")); + EXPECT_THAT(merged->GetParameter("not_found"), Eq(base::nullopt)); - EXPECT_EQ("b", merged->GetParameter("a").value_or("")); - EXPECT_EQ("d", merged->GetParameter("c").value_or("")); - EXPECT_FALSE(merged->GetParameter("not_found")); - - EXPECT_EQ("exp1,exp2", merged->experiment_ids()); + EXPECT_EQ(merged->experiment_ids(), "exp1,exp2"); } TEST(TriggerContextTest, CCT) { @@ -162,15 +146,13 @@ } TEST(TriggerContextTest, HasExperimentId) { - std::map<std::string, std::string> parameters; - - auto context = TriggerContext::Create(parameters, "1,2,3"); + auto context = TriggerContext::Create({}, "1,2,3"); ASSERT_TRUE(context); EXPECT_TRUE(context->HasExperimentId("2")); EXPECT_FALSE(context->HasExperimentId("4")); - auto other_context = TriggerContext::Create(parameters, "4,5,6"); + auto other_context = TriggerContext::Create({}, "4,5,6"); ASSERT_TRUE(other_context); EXPECT_TRUE(other_context->HasExperimentId("4")); @@ -184,20 +166,20 @@ EXPECT_FALSE(merged->HasExperimentId("7")); // Double commas should not allow empty element to match. - auto double_comma = TriggerContext::Create(parameters, "1,,2"); + auto double_comma = TriggerContext::Create({}, "1,,2"); EXPECT_TRUE(double_comma->HasExperimentId("2")); EXPECT_FALSE(double_comma->HasExperimentId("")); // Empty context should not aloow empty element to match. - auto empty = TriggerContext::Create(parameters, ""); + auto empty = TriggerContext::Create({}, ""); EXPECT_FALSE(empty->HasExperimentId("")); // Lone comma does not create empty elements. - auto lone_comma = TriggerContext::Create(parameters, ","); + auto lone_comma = TriggerContext::Create({}, ","); EXPECT_FALSE(lone_comma->HasExperimentId("")); // Single element should match. - auto single_element = TriggerContext::Create(parameters, "1"); + auto single_element = TriggerContext::Create({}, "1"); EXPECT_TRUE(single_element->HasExperimentId("1")); }
diff --git a/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc b/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc index e9d3bdf2..cd89e47 100644 --- a/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc +++ b/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc
@@ -108,6 +108,7 @@ TEST_F(PopupBlockedInfoBarDelegateTest, ShowsBlockedPopups) { TestPopupNavigationDelegate::ResultHolder result; helper()->AddBlockedPopup( + web_contents()->GetMainFrame(), std::make_unique<TestPopupNavigationDelegate>(GURL(kPopupUrl), &result), blink::mojom::WindowFeatures(), PopupBlockType::kNoGesture); bool on_accept_called = false;
diff --git a/components/blocked_content/popup_blocker.cc b/components/blocked_content/popup_blocker.cc index 6b278ac2..a1d9226 100644 --- a/components/blocked_content/popup_blocker.cc +++ b/components/blocked_content/popup_blocker.cc
@@ -125,8 +125,8 @@ // first. content::RenderFrameHost* source_frame = GetSourceFrameForPopup(delegate.get(), open_url_params, web_contents); - popup_blocker->AddBlockedPopup(std::move(delegate), window_features, - block_type); + popup_blocker->AddBlockedPopup(source_frame, std::move(delegate), + window_features, block_type); auto* trigger = safe_browsing::AdPopupTrigger::FromWebContents(web_contents); if (trigger) { trigger->PopupWasBlocked(source_frame);
diff --git a/components/blocked_content/popup_blocker_tab_helper.cc b/components/blocked_content/popup_blocker_tab_helper.cc index c3537d8..97509a4 100644 --- a/components/blocked_content/popup_blocker_tab_helper.cc +++ b/components/blocked_content/popup_blocker_tab_helper.cc
@@ -75,13 +75,14 @@ } void PopupBlockerTabHelper::HidePopupNotification() { - auto* tscs = content_settings::TabSpecificContentSettings::FromWebContents( - web_contents()); + auto* tscs = content_settings::TabSpecificContentSettings::GetForFrame( + web_contents()->GetMainFrame()); if (tscs) tscs->ClearPopupsBlocked(); } void PopupBlockerTabHelper::AddBlockedPopup( + content::RenderFrameHost* source_frame, std::unique_ptr<PopupNavigationDelegate> delegate, const blink::mojom::WindowFeatures& window_features, PopupBlockType block_type) { @@ -93,9 +94,17 @@ next_id_++; blocked_popups_[id] = std::make_unique<BlockedRequest>( std::move(delegate), window_features, block_type); - content_settings::TabSpecificContentSettings::FromWebContents(web_contents()) - ->OnContentBlocked(ContentSettingsType::POPUPS); + + // TODO(carlscab): TabSpecificContentSettings is really + // PageSpecificContentSettings so it does not matter that we use the + // source_frame here and the main frame in HidePopupNotification + auto* content_settings = + content_settings::TabSpecificContentSettings::GetForFrame(source_frame); + if (content_settings) { + content_settings->OnContentBlocked(ContentSettingsType::POPUPS); + } auto* raw_delegate = blocked_popups_[id]->delegate.get(); + manager_.NotifyObservers(id, raw_delegate->GetURL()); raw_delegate->OnPopupBlocked(web_contents(), GetBlockedPopupsCount());
diff --git a/components/blocked_content/popup_blocker_tab_helper.h b/components/blocked_content/popup_blocker_tab_helper.h index 8d1381f..2da2c48 100644 --- a/components/blocked_content/popup_blocker_tab_helper.h +++ b/components/blocked_content/popup_blocker_tab_helper.h
@@ -19,6 +19,10 @@ #include "ui/base/window_open_disposition.h" #include "url/gurl.h" +namespace content { +class RenderFrameHost; +} + namespace blocked_content { class PopupNavigationDelegate; @@ -65,7 +69,8 @@ void ShowBlockedPopup(int32_t popup_id, WindowOpenDisposition disposition); // Adds a new blocked popup to the UI. - void AddBlockedPopup(std::unique_ptr<PopupNavigationDelegate> delegate, + void AddBlockedPopup(content::RenderFrameHost* source_frame, + std::unique_ptr<PopupNavigationDelegate> delegate, const blink::mojom::WindowFeatures& window_features, PopupBlockType block_type);
diff --git a/components/blocked_content/popup_blocker_tab_helper_unittest.cc b/components/blocked_content/popup_blocker_tab_helper_unittest.cc index 1eedfe04..1720115 100644 --- a/components/blocked_content/popup_blocker_tab_helper_unittest.cc +++ b/components/blocked_content/popup_blocker_tab_helper_unittest.cc
@@ -83,6 +83,7 @@ blink::mojom::WindowFeatures window_features; window_features.has_x = true; helper()->AddBlockedPopup( + web_contents()->GetMainFrame(), std::make_unique<TestPopupNavigationDelegate>(GURL(kUrl1), &result), window_features, PopupBlockType::kNoGesture); EXPECT_EQ(result.total_popups_blocked_on_page, 1); @@ -101,6 +102,7 @@ BlockedUrlListObserver observer(helper()); TestPopupNavigationDelegate::ResultHolder result1; helper()->AddBlockedPopup( + web_contents()->GetMainFrame(), std::make_unique<TestPopupNavigationDelegate>(GURL(kUrl1), &result1), blink::mojom::WindowFeatures(), PopupBlockType::kNoGesture); EXPECT_EQ(result1.total_popups_blocked_on_page, 1); @@ -110,6 +112,7 @@ TestPopupNavigationDelegate::ResultHolder result2; helper()->AddBlockedPopup( + web_contents()->GetMainFrame(), std::make_unique<TestPopupNavigationDelegate>(GURL(kUrl2), &result2), blink::mojom::WindowFeatures(), PopupBlockType::kNoGesture); EXPECT_EQ(result2.total_popups_blocked_on_page, 2); @@ -133,6 +136,7 @@ TEST_F(PopupBlockerTabHelperTest, DoesNotShowPopupWithInvalidID) { TestPopupNavigationDelegate::ResultHolder result; helper()->AddBlockedPopup( + web_contents()->GetMainFrame(), std::make_unique<TestPopupNavigationDelegate>(GURL(kUrl1), &result), blink::mojom::WindowFeatures(), PopupBlockType::kNoGesture); EXPECT_EQ(helper()->GetBlockedPopupsCount(), 1u); @@ -149,17 +153,19 @@ TEST_F(PopupBlockerTabHelperTest, SetsContentSettingsPopupState) { auto* content_settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents()); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents()->GetMainFrame()); EXPECT_FALSE(content_settings->IsContentBlocked(ContentSettingsType::POPUPS)); TestPopupNavigationDelegate::ResultHolder result; helper()->AddBlockedPopup( + web_contents()->GetMainFrame(), std::make_unique<TestPopupNavigationDelegate>(GURL(kUrl1), &result), blink::mojom::WindowFeatures(), PopupBlockType::kNoGesture); EXPECT_TRUE(content_settings->IsContentBlocked(ContentSettingsType::POPUPS)); helper()->AddBlockedPopup( + web_contents()->GetMainFrame(), std::make_unique<TestPopupNavigationDelegate>(GURL(kUrl2), &result), blink::mojom::WindowFeatures(), PopupBlockType::kNoGesture); EXPECT_TRUE(content_settings->IsContentBlocked(ContentSettingsType::POPUPS)); @@ -174,15 +180,16 @@ TEST_F(PopupBlockerTabHelperTest, ClearsContentSettingsPopupStateOnNavigation) { TestPopupNavigationDelegate::ResultHolder result; helper()->AddBlockedPopup( + web_contents()->GetMainFrame(), std::make_unique<TestPopupNavigationDelegate>(GURL(kUrl1), &result), blink::mojom::WindowFeatures(), PopupBlockType::kNoGesture); - EXPECT_TRUE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents()) + EXPECT_TRUE(content_settings::TabSpecificContentSettings::GetForFrame( + web_contents()->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); NavigateAndCommit(GURL(kUrl2)); - EXPECT_FALSE(content_settings::TabSpecificContentSettings::FromWebContents( - web_contents()) + EXPECT_FALSE(content_settings::TabSpecificContentSettings::GetForFrame( + web_contents()->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); }
diff --git a/components/browser_ui/settings/android/BUILD.gn b/components/browser_ui/settings/android/BUILD.gn index 037331e..0def3cf 100644 --- a/components/browser_ui/settings/android/BUILD.gn +++ b/components/browser_ui/settings/android/BUILD.gn
@@ -39,14 +39,14 @@ "//ui/android:ui_java_resources", ] sources = [ - "java/res/drawable-hdpi/controlled_setting_mandatory.png", "java/res/drawable-hdpi/ic_account_child_grey600_36dp.png", - "java/res/drawable-mdpi/controlled_setting_mandatory.png", + "java/res/drawable-hdpi/ic_business_small.png", "java/res/drawable-mdpi/ic_account_child_grey600_36dp.png", - "java/res/drawable-xhdpi/controlled_setting_mandatory.png", + "java/res/drawable-mdpi/ic_business_small.png", "java/res/drawable-xhdpi/ic_account_child_grey600_36dp.png", - "java/res/drawable-xxhdpi/controlled_setting_mandatory.png", + "java/res/drawable-xhdpi/ic_business_small.png", "java/res/drawable-xxhdpi/ic_account_child_grey600_36dp.png", + "java/res/drawable-xxhdpi/ic_business_small.png", "java/res/drawable-xxxhdpi/ic_account_child_grey600_36dp.png", "java/res/layout/button_preference_button.xml", "java/res/layout/button_preference_layout.xml",
diff --git a/components/browser_ui/settings/android/java/res/drawable-hdpi/controlled_setting_mandatory.png b/components/browser_ui/settings/android/java/res/drawable-hdpi/ic_business_small.png similarity index 100% rename from components/browser_ui/settings/android/java/res/drawable-hdpi/controlled_setting_mandatory.png rename to components/browser_ui/settings/android/java/res/drawable-hdpi/ic_business_small.png Binary files differ
diff --git a/components/browser_ui/settings/android/java/res/drawable-mdpi/controlled_setting_mandatory.png b/components/browser_ui/settings/android/java/res/drawable-mdpi/ic_business_small.png similarity index 100% rename from components/browser_ui/settings/android/java/res/drawable-mdpi/controlled_setting_mandatory.png rename to components/browser_ui/settings/android/java/res/drawable-mdpi/ic_business_small.png Binary files differ
diff --git a/components/browser_ui/settings/android/java/res/drawable-xhdpi/controlled_setting_mandatory.png b/components/browser_ui/settings/android/java/res/drawable-xhdpi/ic_business_small.png similarity index 100% rename from components/browser_ui/settings/android/java/res/drawable-xhdpi/controlled_setting_mandatory.png rename to components/browser_ui/settings/android/java/res/drawable-xhdpi/ic_business_small.png Binary files differ
diff --git a/components/browser_ui/settings/android/java/res/drawable-xxhdpi/controlled_setting_mandatory.png b/components/browser_ui/settings/android/java/res/drawable-xxhdpi/ic_business_small.png similarity index 100% rename from components/browser_ui/settings/android/java/res/drawable-xxhdpi/controlled_setting_mandatory.png rename to components/browser_ui/settings/android/java/res/drawable-xxhdpi/ic_business_small.png Binary files differ
diff --git a/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/ManagedPreferencesUtils.java b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/ManagedPreferencesUtils.java index b1d1742..8386b0b6 100644 --- a/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/ManagedPreferencesUtils.java +++ b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/ManagedPreferencesUtils.java
@@ -69,7 +69,7 @@ * @return The resource ID for the Managed By Enterprise icon. */ public static @DrawableRes int getManagedByEnterpriseIconId() { - return R.drawable.controlled_setting_mandatory; + return R.drawable.ic_business_small; } /**
diff --git a/components/browser_ui/styles/android/BUILD.gn b/components/browser_ui/styles/android/BUILD.gn index d2dd1d0..3b99590 100644 --- a/components/browser_ui/styles/android/BUILD.gn +++ b/components/browser_ui/styles/android/BUILD.gn
@@ -99,6 +99,7 @@ "java/res/drawable-xxxhdpi/plus.png", "java/res/drawable-xxxhdpi/settings_all_sites.png", "java/res/drawable-xxxhdpi/top_round.9.png", + "java/res/drawable/ic_business.xml", "java/res/drawable/ic_data_viz_grey.xml", "java/res/drawable/ic_done_blue.xml", "java/res/drawable/ic_eye_crossed.xml",
diff --git a/components/browser_ui/styles/android/java/res/drawable/ic_business.xml b/components/browser_ui/styles/android/java/res/drawable/ic_business.xml new file mode 100644 index 0000000..03a2fb2 --- /dev/null +++ b/components/browser_ui/styles/android/java/res/drawable/ic_business.xml
@@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 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. --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="@color/default_icon_color" + android:pathData="M12,7L12,3L2,3v18h20L22,7L12,7zM6,19L4,19v-2h2v2zM6,15L4,15v-2h2v2zM6,11L4,11L4,9h2v2zM6,7L4,7L4,5h2v2zM10,19L8,19v-2h2v2zM10,15L8,15v-2h2v2zM10,11L8,11L8,9h2v2zM10,7L8,7L8,5h2v2zM20,19h-8v-2h2v-2h-2v-2h2v-2h-2L12,9h8v10zM18,11h-2v2h2v-2zM18,15h-2v2h2v-2z"/> +</vector>
diff --git a/components/content_settings/browser/content_settings_manager_impl.cc b/components/content_settings/browser/content_settings_manager_impl.cc index d513379..066dc48 100644 --- a/components/content_settings/browser/content_settings_manager_impl.cc +++ b/components/content_settings/browser/content_settings_manager_impl.cc
@@ -46,17 +46,11 @@ const GURL& top_origin_url, bool local, bool blocked_by_policy) { - content::RenderFrameHost* frame = - content::RenderFrameHost::FromID(process_id, frame_id); - content::WebContents* web_contents = - content::WebContents::FromRenderFrameHost(frame); - if (!web_contents) - return; - - TabSpecificContentSettings* tab_settings = - TabSpecificContentSettings::FromWebContents(web_contents); - if (tab_settings) - tab_settings->OnDomStorageAccessed(origin_url, local, blocked_by_policy); + TabSpecificContentSettings* settings = + TabSpecificContentSettings::GetForFrame( + content::RenderFrameHost::FromID(process_id, frame_id)); + if (settings) + settings->OnDomStorageAccessed(origin_url, local, blocked_by_policy); } } // namespace @@ -150,17 +144,11 @@ void ContentSettingsManagerImpl::OnContentBlocked(int32_t render_frame_id, ContentSettingsType type) { - content::RenderFrameHost* frame = - content::RenderFrameHost::FromID(render_process_id_, render_frame_id); - content::WebContents* web_contents = - content::WebContents::FromRenderFrameHost(frame); - if (!web_contents) - return; - - TabSpecificContentSettings* tab_settings = - TabSpecificContentSettings::FromWebContents(web_contents); - if (tab_settings) - tab_settings->OnContentBlocked(type); + TabSpecificContentSettings* settings = + TabSpecificContentSettings::GetForFrame(render_process_id_, + render_frame_id); + if (settings) + settings->OnContentBlocked(type); } ContentSettingsManagerImpl::ContentSettingsManagerImpl(
diff --git a/components/content_settings/browser/tab_specific_content_settings.cc b/components/content_settings/browser/tab_specific_content_settings.cc index 9437ad7..2a667d6 100644 --- a/components/content_settings/browser/tab_specific_content_settings.cc +++ b/components/content_settings/browser/tab_specific_content_settings.cc
@@ -384,21 +384,27 @@ int render_process_id, int render_frame_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - - content::RenderFrameHost* frame = - content::RenderFrameHost::FromID(render_process_id, render_frame_id); - if (!frame) - return nullptr; - return TabSpecificContentSettings::GetForCurrentDocument( - frame->GetMainFrame()); + return GetForFrame( + content::RenderFrameHost::FromID(render_process_id, render_frame_id)); } // static -TabSpecificContentSettings* TabSpecificContentSettings::FromWebContents( - content::WebContents* web_contents) { +TabSpecificContentSettings* TabSpecificContentSettings::GetForFrame( + content::RenderFrameHost* rfh) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - return TabSpecificContentSettings::GetForCurrentDocument( - web_contents->GetMainFrame()); + return rfh ? TabSpecificContentSettings::GetForCurrentDocument( + rfh->GetMainFrame()) + : nullptr; +} + +// static +TabSpecificContentSettings::Delegate* +TabSpecificContentSettings::GetDelegateForWebContents( + content::WebContents* web_contents) { + auto* handler = + TabSpecificContentSettings::WebContentsHandler::FromWebContents( + web_contents); + return handler ? handler->delegate() : nullptr; } // static
diff --git a/components/content_settings/browser/tab_specific_content_settings.h b/components/content_settings/browser/tab_specific_content_settings.h index fa48ac5..6c3d78e 100644 --- a/components/content_settings/browser/tab_specific_content_settings.h +++ b/components/content_settings/browser/tab_specific_content_settings.h
@@ -165,12 +165,21 @@ std::unique_ptr<Delegate> delegate); static void DeleteForWebContentsForTest(content::WebContents* web_contents); - // Returns the object given a RenderFrameHost ids. + // Returns the object given a RenderFrameHost ids. Returns nullptr if the + // frame no longer exist or there are no TabSpecificContentSettings attached + // to the document. static TabSpecificContentSettings* GetForFrame(int render_process_id, int render_frame_id); - // TODO(carlscab): Get rid of this and use GetForFrame instead - static TabSpecificContentSettings* FromWebContents( - content::WebContents* contents); + // Returns the object given a RenderFrameHost. Returns nullptr if the frame + // is nullptr or there are no TabSpecificContentSettings attached to the + // document. + static TabSpecificContentSettings* GetForFrame(content::RenderFrameHost* rfh); + + // Returns the Delegate that was associated to |web_contents| in + // CreateForWebContents. Null if CreateForWebContents was not called for + // |web_contents|. + static TabSpecificContentSettings::Delegate* GetDelegateForWebContents( + content::WebContents* web_contents); // Called when a specific Web database in the current page was accessed. If // access was blocked due to the user's content settings, @@ -369,8 +378,6 @@ // since the last navigation. bool HasContentSettingChangedViaPageInfo(ContentSettingsType type) const; - Delegate* delegate() { return delegate_; } - private: friend class content::RenderDocumentHostUserData<TabSpecificContentSettings>; @@ -398,6 +405,8 @@ // Notifies all registered |SiteDataObserver|s. void NotifySiteDataObservers(); + Delegate* delegate() { return delegate_.get(); } + private: friend class content::WebContentsUserData<WebContentsHandler>;
diff --git a/components/content_settings/browser/tab_specific_content_settings_unittest.cc b/components/content_settings/browser/tab_specific_content_settings_unittest.cc index 9477ad9..806028e 100644 --- a/components/content_settings/browser/tab_specific_content_settings_unittest.cc +++ b/components/content_settings/browser/tab_specific_content_settings_unittest.cc
@@ -75,7 +75,7 @@ TEST_F(TabSpecificContentSettingsTest, BlockedContent) { NavigateAndCommit(GURL("http://google.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Check that after initializing, nothing is blocked. #if !defined(OS_ANDROID) @@ -107,7 +107,7 @@ {*cookie1}, false}); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); #if !defined(OS_ANDROID) content_settings->OnContentBlocked(ContentSettingsType::IMAGES); #endif @@ -168,12 +168,12 @@ simulator->GetNavigationHandle(), GURL("http://google.com"), content::AllowServiceWorkerResult::FromPolicy(true, false)); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); EXPECT_FALSE( content_settings->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); simulator->Commit(); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Block a javascript when page starts to start ServiceWorker. GetHandle()->OnServiceWorkerAccessed( @@ -185,7 +185,7 @@ // Reset blocked content settings. NavigateAndCommit(GURL("http://google.com")); content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); #if !defined(OS_ANDROID) EXPECT_FALSE(content_settings->IsContentBlocked(ContentSettingsType::IMAGES)); EXPECT_FALSE( @@ -205,7 +205,7 @@ TEST_F(TabSpecificContentSettingsTest, BlockedFileSystems) { NavigateAndCommit(GURL("http://google.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Access a file system. content_settings->OnFileSystemAccessed(GURL("http://google.com"), false); @@ -220,7 +220,7 @@ TEST_F(TabSpecificContentSettingsTest, AllowedContent) { NavigateAndCommit(GURL("http://google.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Test default settings. ASSERT_FALSE(content_settings->IsContentAllowed(ContentSettingsType::IMAGES)); @@ -265,7 +265,7 @@ TEST_F(TabSpecificContentSettingsTest, EmptyCookieList) { NavigateAndCommit(GURL("http://google.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); ASSERT_FALSE( content_settings->IsContentAllowed(ContentSettingsType::COOKIES)); @@ -284,7 +284,7 @@ TEST_F(TabSpecificContentSettingsTest, SiteDataObserver) { NavigateAndCommit(GURL("http://google.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); MockSiteDataObserver mock_observer(web_contents()); EXPECT_CALL(mock_observer, OnSiteDataAccessed()).Times(6); @@ -325,7 +325,7 @@ TEST_F(TabSpecificContentSettingsTest, LocalSharedObjectsContainer) { NavigateAndCommit(GURL("http://google.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); bool blocked_by_policy = false; auto cookie = net::CanonicalCookie::Create(GURL("http://google.com"), "k=v", base::Time::Now(), @@ -362,7 +362,7 @@ TEST_F(TabSpecificContentSettingsTest, LocalSharedObjectsContainerCookie) { NavigateAndCommit(GURL("http://google.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); bool blocked_by_policy = false; auto cookie1 = net::CanonicalCookie::Create(GURL("http://google.com"), "k1=v", base::Time::Now(), @@ -403,7 +403,7 @@ NavigateAndCommit(GURL("http://google.com")); TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::FromWebContents(web_contents()); + TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // First trigger OnContentBlocked. EXPECT_FALSE(content_settings->IsContentBlocked(
diff --git a/components/error_page/common/BUILD.gn b/components/error_page/common/BUILD.gn index c91f2e6..98936b2 100644 --- a/components/error_page/common/BUILD.gn +++ b/components/error_page/common/BUILD.gn
@@ -6,8 +6,6 @@ sources = [ "error.cc", "error.h", - "error_page_params.cc", - "error_page_params.h", "error_page_switches.cc", "error_page_switches.h", "localized_error.cc",
diff --git a/components/error_page/common/error_page_params.cc b/components/error_page/common/error_page_params.cc deleted file mode 100644 index c60931a..0000000 --- a/components/error_page/common/error_page_params.cc +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/error_page/common/error_page_params.h" - -#include "base/values.h" - -namespace error_page { - -ErrorPageParams::ErrorPageParams() : suggest_reload(false) {} - -ErrorPageParams::~ErrorPageParams() { -} - -} // namespace error_page
diff --git a/components/error_page/common/error_page_params.h b/components/error_page/common/error_page_params.h deleted file mode 100644 index eb7d4abb..0000000 --- a/components/error_page/common/error_page_params.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_NET_ERROR_COMMON_ERROR_PAGE_PARAMS_H_ -#define COMPONENTS_NET_ERROR_COMMON_ERROR_PAGE_PARAMS_H_ - -namespace error_page { - -// Optional parameters that affect the display of an error page. -// -// TODO(mmenke): Now that this is only one value, it should probably be removed. -struct ErrorPageParams { - ErrorPageParams(); - ~ErrorPageParams(); - - // Overrides whether reloading is suggested. - bool suggest_reload; -}; - -} // namespace error_page - -#endif // COMPONENTS_NET_ERROR_COMMON_ERROR_PAGE_PARAMS_H_
diff --git a/components/error_page/common/localized_error.cc b/components/error_page/common/localized_error.cc index 1298449..0114a78 100644 --- a/components/error_page/common/localized_error.cc +++ b/components/error_page/common/localized_error.cc
@@ -23,7 +23,6 @@ #include "base/values.h" #include "build/build_config.h" #include "components/error_page/common/error.h" -#include "components/error_page/common/error_page_params.h" #include "components/error_page/common/error_page_switches.h" #include "components/error_page/common/net_error_info.h" #include "components/offline_pages/core/offline_page_feature.h" @@ -896,8 +895,7 @@ bool offline_content_feature_enabled, bool auto_fetch_feature_enabled, bool is_kiosk_mode, - const std::string& locale, - std::unique_ptr<error_page::ErrorPageParams> params) { + const std::string& locale) { LocalizedError::PageState result; result.is_offline_error = IsOfflineError(error_domain, error_code); @@ -999,20 +997,14 @@ } result.strings.SetString("errorCode", error_string); - // If no parameters were provided, use the defaults. - if (!params) { - params.reset(new error_page::ErrorPageParams()); - params->suggest_reload = !!(options.buttons & SHOW_BUTTON_RELOAD); - } - base::ListValue* suggestions_details = result.strings.SetList( "suggestionsDetails", std::make_unique<base::ListValue>()); base::ListValue* suggestions_summary_list = result.strings.SetList( "suggestionsSummaryList", std::make_unique<base::ListValue>()); - // Add the reload suggestion, if needed for pages that didn't come + // Add the reload suggestion, if needed, for pages that didn't come // from a post. - if (params->suggest_reload && !is_post) { + if ((options.buttons & SHOW_BUTTON_RELOAD) && !is_post) { auto reload_button = std::make_unique<base::DictionaryValue>(); result.reload_button_shown = true; reload_button->SetString(
diff --git a/components/error_page/common/localized_error.h b/components/error_page/common/localized_error.h index 5f35ad74..65f819b2 100644 --- a/components/error_page/common/localized_error.h +++ b/components/error_page/common/localized_error.h
@@ -19,8 +19,6 @@ namespace error_page { -struct ErrorPageParams; - class LocalizedError { public: // Information about elements shown on the error page. @@ -56,8 +54,7 @@ bool auto_fetch_feature_enabled, bool is_kiosk_mode, // whether device is currently in single app (kiosk) // mode - const std::string& locale, - std::unique_ptr<error_page::ErrorPageParams> params); + const std::string& locale); // Returns a description of the encountered error. static base::string16 GetErrorDetails(const std::string& error_domain,
diff --git a/components/federated_learning/floc_id.cc b/components/federated_learning/floc_id.cc index 87ae073..38caf08 100644 --- a/components/federated_learning/floc_id.cc +++ b/components/federated_learning/floc_id.cc
@@ -14,7 +14,8 @@ constexpr char kFlocVersion[] = "1.0.0"; -constexpr size_t kNumberOfBitsInFloc = 16; +// This is only for experimentation and won't be served to websites. +constexpr size_t kNumberOfBitsInFloc = 50; static_assert(kNumberOfBitsInFloc > 0 && kNumberOfBitsInFloc <= std::numeric_limits<uint64_t>::digits, "Number of bits in the floc id must be greater than 0 and no "
diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc index 60441eb..38306ee 100644 --- a/components/page_info/page_info.cc +++ b/components/page_info/page_info.cc
@@ -1133,8 +1133,10 @@ content_settings::TabSpecificContentSettings* PageInfo::GetTabSpecificContentSettings() const { - return content_settings::TabSpecificContentSettings::FromWebContents( - web_contents()); + // TODO(https://crbug.com/1103176): PageInfo should be per page. Why is it + // a WebContentsObserver if it is not observing anything? + return content_settings::TabSpecificContentSettings::GetForFrame( + web_contents()->GetMainFrame()); } bool PageInfo::HasContentSettingChangedViaPageInfo(ContentSettingsType type) {
diff --git a/components/paint_preview/common/paint_preview_tracker.cc b/components/paint_preview/common/paint_preview_tracker.cc index dede9c03..adfbed4 100644 --- a/components/paint_preview/common/paint_preview_tracker.cc +++ b/components/paint_preview/common/paint_preview_tracker.cc
@@ -46,7 +46,51 @@ embedding_token_(embedding_token), is_main_frame_(is_main_frame), scroll_(SkISize::Make(0, 0)) {} -PaintPreviewTracker::~PaintPreviewTracker() = default; + +PaintPreviewTracker::~PaintPreviewTracker() { + DCHECK(states_.empty()); +} + +void PaintPreviewTracker::Save() { + states_.push_back(matrix_); +} + +void PaintPreviewTracker::SetMatrix(const SkMatrix& matrix) { + matrix_ = matrix; +} + +void PaintPreviewTracker::Restore() { + if (states_.size() == 0) { + DLOG(ERROR) << "No state to restore"; + return; + } + matrix_ = states_.back(); + states_.pop_back(); +} + +void PaintPreviewTracker::Concat(const SkMatrix& matrix) { + if (matrix.isIdentity()) + return; + matrix_.preConcat(matrix); +} + +void PaintPreviewTracker::Scale(SkScalar x, SkScalar y) { + if (x != 1 || y != 1) { + matrix_.preScale(x, y); + } +} + +void PaintPreviewTracker::Rotate(SkScalar degrees) { + SkMatrix m; + m.setRotate(degrees); + Concat(m); +} + +void PaintPreviewTracker::Translate(SkScalar x, SkScalar y) { + if (x || y) { + matrix_.preTranslate(x, y); + } +} uint32_t PaintPreviewTracker::CreateContentForRemoteFrame( const gfx::Rect& rect, @@ -95,8 +139,12 @@ } } -void PaintPreviewTracker::AnnotateLink(const GURL& url, const gfx::Rect& rect) { - links_.push_back(mojom::LinkData::New(url, rect)); +void PaintPreviewTracker::AnnotateLink(const GURL& url, const SkRect& rect) { + SkRect out_rect; + matrix_.mapRect(&out_rect, rect); + links_.push_back(mojom::LinkData::New( + url, gfx::Rect(out_rect.x(), out_rect.y(), out_rect.width(), + out_rect.height()))); } void PaintPreviewTracker::CustomDataToSkPictureCallback(SkCanvas* canvas,
diff --git a/components/paint_preview/common/paint_preview_tracker.h b/components/paint_preview/common/paint_preview_tracker.h index 0041603..c7a1151 100644 --- a/components/paint_preview/common/paint_preview_tracker.h +++ b/components/paint_preview/common/paint_preview_tracker.h
@@ -41,6 +41,18 @@ } bool IsMainFrame() const { return is_main_frame_; } + // Transform methods -------------------------------------------------------- + + // Used to transform the position of links when parsing the paint op buffer. + // These are inspired by the methods in SkCanvas. + void Save(); + void Restore(); + void SetMatrix(const SkMatrix& matrix); + void Concat(const SkMatrix& matrix); + void Scale(SkScalar x, SkScalar y); + void Rotate(SkScalar degrees); + void Translate(SkScalar x, SkScalar y); + // Data Collection ---------------------------------------------------------- // Creates a placeholder SkPicture for an OOP subframe located at |rect| @@ -58,7 +70,7 @@ void AddGlyphs(const SkTextBlob* blob); // Adds |link| with bounding box |rect| to the list of links. - void AnnotateLink(const GURL& link, const gfx::Rect& rect); + void AnnotateLink(const GURL& link, const SkRect& rect); // Data Serialization ------------------------------------------------------- // NOTE: once any of these methods are called the PaintPreviewTracker should @@ -87,6 +99,8 @@ const bool is_main_frame_; SkISize scroll_; + SkMatrix matrix_; + std::vector<SkMatrix> states_; std::vector<mojom::LinkDataPtr> links_; PictureSerializationContext content_id_to_embedding_token_;
diff --git a/components/paint_preview/common/paint_preview_tracker_unittest.cc b/components/paint_preview/common/paint_preview_tracker_unittest.cc index 8575ba71..e9e2bd08 100644 --- a/components/paint_preview/common/paint_preview_tracker_unittest.cc +++ b/components/paint_preview/common/paint_preview_tracker_unittest.cc
@@ -114,11 +114,11 @@ PaintPreviewTracker tracker(base::UnguessableToken::Create(), kEmbeddingToken, true); const GURL url_1("https://www.chromium.org"); - const gfx::Rect rect_1(10, 20, 30, 40); + const auto rect_1 = SkRect::MakeXYWH(10, 20, 30, 40); tracker.AnnotateLink(url_1, rect_1); const GURL url_2("https://www.w3.org"); - const gfx::Rect rect_2(15, 25, 35, 45); + const auto rect_2 = SkRect::MakeXYWH(15, 25, 35, 45); tracker.AnnotateLink(url_2, rect_2); ASSERT_EQ(tracker.GetLinks().size(), 2U); @@ -141,11 +141,11 @@ PaintPreviewTracker tracker(base::UnguessableToken::Create(), kEmbeddingToken, true); const GURL url_1("https://www.chromium.org"); - const gfx::Rect rect_1(10, 20, 30, 40); + const auto rect_1 = SkRect::MakeXYWH(10, 20, 30, 40); tracker.AnnotateLink(url_1, rect_1); const GURL url_2("https://www.w3.org"); - const gfx::Rect rect_2(15, 25, 35, 45); + const auto rect_2 = SkRect::MakeXYWH(15, 25, 35, 45); tracker.AnnotateLink(url_2, rect_2); std::vector<mojom::LinkDataPtr> links; @@ -165,4 +165,81 @@ EXPECT_EQ(links[1]->rect.y(), rect_2.y()); } +TEST(PaintPreviewTrackerTest, AnnotateLinksWithTransform) { + const base::UnguessableToken kEmbeddingToken = + base::UnguessableToken::Create(); + PaintPreviewTracker tracker(base::UnguessableToken::Create(), kEmbeddingToken, + true); + + const GURL url("http://www.chromium.org"); + const auto rect = SkRect::MakeXYWH(10, 20, 30, 40); + tracker.AnnotateLink(url, rect); + + std::vector<mojom::LinkDataPtr> links; + tracker.MoveLinks(&links); + ASSERT_EQ(links.size(), 1U); + EXPECT_EQ(links[0]->url, url); + EXPECT_EQ(links[0]->rect.width(), rect.width()); + EXPECT_EQ(links[0]->rect.height(), rect.height()); + EXPECT_EQ(links[0]->rect.x(), rect.x()); + EXPECT_EQ(links[0]->rect.y(), rect.y()); + + tracker.Save(); + tracker.Scale(2, 4); + tracker.AnnotateLink(url, rect); + links.clear(); + tracker.MoveLinks(&links); + EXPECT_EQ(links[0]->url, url); + EXPECT_EQ(links[0]->rect.width(), rect.width() * 2); + EXPECT_EQ(links[0]->rect.height(), rect.height() * 4); + EXPECT_EQ(links[0]->rect.x(), rect.x() * 2); + EXPECT_EQ(links[0]->rect.y(), rect.y() * 4); + + tracker.Translate(10, 20); + tracker.AnnotateLink(url, rect); + links.clear(); + tracker.MoveLinks(&links); + EXPECT_EQ(links[0]->url, url); + EXPECT_EQ(links[0]->rect.width(), rect.width() * 2); + EXPECT_EQ(links[0]->rect.height(), rect.height() * 4); + EXPECT_EQ(links[0]->rect.x(), (10 + rect.x()) * 2); + EXPECT_EQ(links[0]->rect.y(), (20 + rect.y()) * 4); + + tracker.Restore(); + links.clear(); + tracker.AnnotateLink(url, rect); + tracker.MoveLinks(&links); + ASSERT_EQ(links.size(), 1U); + EXPECT_EQ(links[0]->url, url); + EXPECT_EQ(links[0]->rect.width(), rect.width()); + EXPECT_EQ(links[0]->rect.height(), rect.height()); + EXPECT_EQ(links[0]->rect.x(), rect.x()); + EXPECT_EQ(links[0]->rect.y(), rect.y()); + + tracker.Concat(SkMatrix::Translate(30, 100)); + links.clear(); + tracker.AnnotateLink(url, rect); + tracker.MoveLinks(&links); + ASSERT_EQ(links.size(), 1U); + EXPECT_EQ(links[0]->url, url); + EXPECT_EQ(links[0]->rect.width(), rect.width()); + EXPECT_EQ(links[0]->rect.height(), rect.height()); + EXPECT_EQ(links[0]->rect.x(), rect.x() + 30); + EXPECT_EQ(links[0]->rect.y(), rect.y() + 100); + + tracker.Rotate(30); + links.clear(); + tracker.AnnotateLink(url, rect); + tracker.MoveLinks(&links); + ASSERT_EQ(links.size(), 1U); + EXPECT_EQ(links[0]->url, url); + EXPECT_EQ(links[0]->rect.width(), 45); + EXPECT_EQ(links[0]->rect.height(), 49); + EXPECT_EQ(links[0]->rect.x(), 8); + EXPECT_EQ(links[0]->rect.y(), 122); + + // no-op (ensure this doesn't crash). + tracker.Restore(); +} + } // namespace paint_preview
diff --git a/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc b/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc index 3cd4ab3b..cdad89e 100644 --- a/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc +++ b/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc
@@ -9,6 +9,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/test/scoped_feature_list.h" #include "base/threading/thread_restrictions.h" +#include "build/build_config.h" #include "components/paint_preview/common/file_stream.h" #include "components/paint_preview/common/mojom/paint_preview_recorder.mojom.h" #include "content/public/renderer/render_frame.h" @@ -60,6 +61,31 @@ return temp_dir_.GetPath().AppendASCII(filename); } + base::FilePath RunCapture(content::RenderFrame* frame, + mojom::PaintPreviewCaptureResponsePtr* out_response, + bool is_main_frame = true) { + base::FilePath skp_path = MakeTestFilePath("test.skp"); + + mojom::PaintPreviewCaptureParamsPtr params = + mojom::PaintPreviewCaptureParams::New(); + auto token = base::UnguessableToken::Create(); + params->guid = token; + params->clip_rect = gfx::Rect(); + params->is_main_frame = is_main_frame; + params->capture_links = true; + base::File skp_file( + skp_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); + params->file = std::move(skp_file); + + PaintPreviewRecorderImpl paint_preview_recorder(frame); + paint_preview_recorder.CapturePaintPreview( + std::move(params), + base::BindOnce(&OnCaptureFinished, mojom::PaintPreviewStatus::kOk, + out_response)); + content::RunAllTasksUntilIdle(); + return skp_path; + } + private: base::ScopedTempDir temp_dir_; base::test::ScopedFeatureList feature_list_; @@ -67,6 +93,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureMainFrameAndClipping) { LoadHTML( + "<!doctype html>" "<body>" " <div style='width: 600px; height: 80vh; " " background-color: #ff0000'> </div>" @@ -80,28 +107,9 @@ " </div>" "</body>"); - base::FilePath skp_path = MakeTestFilePath("test.skp"); - - mojom::PaintPreviewCaptureParamsPtr params = - mojom::PaintPreviewCaptureParams::New(); - auto token = base::UnguessableToken::Create(); - params->guid = token; - params->clip_rect = gfx::Rect(); - params->is_main_frame = true; - params->capture_links = true; - params->max_capture_size = 0; - base::File skp_file(skp_path, - base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - params->file = std::move(skp_file); - auto out_response = mojom::PaintPreviewCaptureResponse::New(); content::RenderFrame* frame = GetFrame(); - PaintPreviewRecorderImpl paint_preview_recorder(frame); - paint_preview_recorder.CapturePaintPreview( - std::move(params), - base::BindOnce(&OnCaptureFinished, mojom::PaintPreviewStatus::kOk, - base::Unretained(&out_response))); - content::RunAllTasksUntilIdle(); + base::FilePath skp_path = RunCapture(frame, &out_response); EXPECT_TRUE(out_response->embedding_token.has_value()); EXPECT_EQ(frame->GetWebFrame()->GetEmbeddingToken(), @@ -150,6 +158,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureMainFrameWithScroll) { LoadHTML( + "<!doctype html>" "<body>" " <div style='width: 600px; height: 80vh; " " background-color: #ff0000'> </div>" @@ -160,28 +169,10 @@ // Scroll to bottom of page to ensure scroll position has no effect on // capture. ExecuteJavaScriptForTests("window.scrollTo(0,document.body.scrollHeight);"); - base::FilePath skp_path = MakeTestFilePath("test.skp"); - - mojom::PaintPreviewCaptureParamsPtr params = - mojom::PaintPreviewCaptureParams::New(); - auto token = base::UnguessableToken::Create(); - params->guid = token; - params->clip_rect = gfx::Rect(); - params->is_main_frame = true; - params->capture_links = true; - params->max_capture_size = 0; - base::File skp_file(skp_path, - base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - params->file = std::move(skp_file); auto out_response = mojom::PaintPreviewCaptureResponse::New(); content::RenderFrame* frame = GetFrame(); - PaintPreviewRecorderImpl paint_preview_recorder(frame); - paint_preview_recorder.CapturePaintPreview( - std::move(params), - base::BindOnce(&OnCaptureFinished, mojom::PaintPreviewStatus::kOk, - base::Unretained(&out_response))); - content::RunAllTasksUntilIdle(); + base::FilePath skp_path = RunCapture(frame, &out_response); EXPECT_TRUE(out_response->embedding_token.has_value()); EXPECT_EQ(frame->GetWebFrame()->GetEmbeddingToken(), @@ -215,33 +206,16 @@ // Use position absolute position to check that the captured link dimensions // match what is specified. LoadHTML( + "<!doctype html>" "<body style='min-height:1000px;'>" " <a style='position: absolute; left: -15px; top: 0px; width: 40px; " " height: 30px;' href='#fragment'>Foo</a>" " <h1 id='fragment'>I'm a fragment</h1>" "</body>"); - base::FilePath skp_path = MakeTestFilePath("test.skp"); - - mojom::PaintPreviewCaptureParamsPtr params = - mojom::PaintPreviewCaptureParams::New(); - auto token = base::UnguessableToken::Create(); - params->guid = token; - params->clip_rect = gfx::Rect(); - params->is_main_frame = true; - params->capture_links = true; - params->max_capture_size = 0; - base::File skp_file(skp_path, - base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - params->file = std::move(skp_file); - auto out_response = mojom::PaintPreviewCaptureResponse::New(); content::RenderFrame* frame = GetFrame(); - PaintPreviewRecorderImpl paint_preview_recorder(frame); - paint_preview_recorder.CapturePaintPreview( - std::move(params), - base::BindOnce(&OnCaptureFinished, mojom::PaintPreviewStatus::kOk, - &out_response)); - content::RunAllTasksUntilIdle(); + + RunCapture(frame, &out_response); EXPECT_TRUE(out_response->embedding_token.has_value()); EXPECT_EQ(frame->GetWebFrame()->GetEmbeddingToken(), @@ -281,33 +255,16 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureMainFrameAndLocalFrame) { LoadHTML( + "<!doctype html>" "<body style='min-height:1000px;'>" " <iframe style='width: 500px, height: 500px'" " srcdoc=\"<div style='width: 100px; height: 100px;" " background-color: #000000'> </div>\"></iframe>" "</body>"); - base::FilePath skp_path = MakeTestFilePath("test.skp"); - - mojom::PaintPreviewCaptureParamsPtr params = - mojom::PaintPreviewCaptureParams::New(); - auto token = base::UnguessableToken::Create(); - params->guid = token; - params->clip_rect = gfx::Rect(); - params->is_main_frame = true; - params->capture_links = true; - params->max_capture_size = 0; - base::File skp_file(skp_path, - base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - params->file = std::move(skp_file); - auto out_response = mojom::PaintPreviewCaptureResponse::New(); content::RenderFrame* frame = GetFrame(); - PaintPreviewRecorderImpl paint_preview_recorder(frame); - paint_preview_recorder.CapturePaintPreview( - std::move(params), - base::BindOnce(&OnCaptureFinished, mojom::PaintPreviewStatus::kOk, - base::Unretained(&out_response))); - content::RunAllTasksUntilIdle(); + + RunCapture(frame, &out_response); EXPECT_TRUE(out_response->embedding_token.has_value()); EXPECT_EQ(frame->GetWebFrame()->GetEmbeddingToken(), @@ -317,38 +274,242 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureLocalFrame) { LoadHTML( + "<!doctype html>" "<body style='min-height:1000px;'>" " <iframe style='width: 500px, height: 500px'" " srcdoc=\"<div style='width: 100px; height: 100px;" " background-color: #000000'> </div>\"></iframe>" "</body>"); - base::FilePath skp_path = MakeTestFilePath("test.skp"); - - mojom::PaintPreviewCaptureParamsPtr params = - mojom::PaintPreviewCaptureParams::New(); - auto token = base::UnguessableToken::Create(); - params->guid = token; - params->clip_rect = gfx::Rect(); - params->is_main_frame = false; - params->capture_links = true; - params->max_capture_size = 0; - base::File skp_file(skp_path, - base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - params->file = std::move(skp_file); - auto out_response = mojom::PaintPreviewCaptureResponse::New(); auto* child_frame = content::RenderFrame::FromWebFrame( GetFrame()->GetWebFrame()->FirstChild()->ToWebLocalFrame()); ASSERT_TRUE(child_frame); - PaintPreviewRecorderImpl paint_preview_recorder(child_frame); - paint_preview_recorder.CapturePaintPreview( - std::move(params), - base::BindOnce(&OnCaptureFinished, mojom::PaintPreviewStatus::kOk, - base::Unretained(&out_response))); - content::RunAllTasksUntilIdle(); + + RunCapture(child_frame, &out_response, false); EXPECT_TRUE(out_response->embedding_token.has_value()); EXPECT_EQ(out_response->content_id_to_embedding_token.size(), 0U); } +TEST_F(PaintPreviewRecorderRenderViewTest, CaptureWithTranslate) { + // URLs should be annotated correctly when a CSS transform is applied. + LoadHTML( + R"( + <!doctype html> + <body> + <div style="display: inline-block; + padding: 16px; + font-size: 16px;"> + <div style="padding: 16px; + transform: translate(10px, 20px); + margin-bottom: 30px;"> + <div> + <a href="http://www.example.com" style="display: block; + width: 70px; + height: 20px;"> + <div>Example</div> + </a> + </div> + </div> + </div> + </body>)"); + auto out_response = mojom::PaintPreviewCaptureResponse::New(); + content::RenderFrame* frame = GetFrame(); + + RunCapture(frame, &out_response); + + EXPECT_TRUE(out_response->embedding_token.has_value()); + EXPECT_EQ(frame->GetWebFrame()->GetEmbeddingToken(), + out_response->embedding_token.value()); + EXPECT_EQ(out_response->content_id_to_embedding_token.size(), 0U); + + ASSERT_EQ(out_response->links.size(), 1U); + EXPECT_EQ(out_response->links[0]->url, GURL("http://www.example.com")); + EXPECT_NEAR(out_response->links[0]->rect.x(), 50, 3); + EXPECT_NEAR(out_response->links[0]->rect.y(), 60, 3); + EXPECT_NEAR(out_response->links[0]->rect.width(), 70, 3); + EXPECT_NEAR(out_response->links[0]->rect.height(), 20, 3); +} + +TEST_F(PaintPreviewRecorderRenderViewTest, CaptureWithTranslateThenRotate) { + // URLs should be annotated correctly when a CSS transform is applied. + LoadHTML( + R"( + <!doctype html> + <body> + <div style="display: inline-block; + padding: 16px; + font-size: 16px;"> + <div style="padding: 16px; + transform: translate(100px, 0) rotate(45deg); + margin-bottom: 30px;"> + <div> + <a href="http://www.example.com" style="display: block; + width: 70px; + height: 20px;"> + <div>Example</div> + </a> + </div> + </div> + </div> + </body>)"); + auto out_response = mojom::PaintPreviewCaptureResponse::New(); + content::RenderFrame* frame = GetFrame(); + + RunCapture(frame, &out_response); + + EXPECT_TRUE(out_response->embedding_token.has_value()); + EXPECT_EQ(frame->GetWebFrame()->GetEmbeddingToken(), + out_response->embedding_token.value()); + EXPECT_EQ(out_response->content_id_to_embedding_token.size(), 0U); + + ASSERT_EQ(out_response->links.size(), 1U); + EXPECT_EQ(out_response->links[0]->url, GURL("http://www.example.com")); + EXPECT_NEAR(out_response->links[0]->rect.x(), 141, 5); + EXPECT_NEAR(out_response->links[0]->rect.y(), 18, 5); +#if !defined(OS_ANDROID) + EXPECT_NEAR(out_response->links[0]->rect.width(), 58, 10); + EXPECT_NEAR(out_response->links[0]->rect.height(), 58, 10); +#endif +} + +TEST_F(PaintPreviewRecorderRenderViewTest, CaptureWithRotateThenTranslate) { + // URLs should be annotated correctly when a CSS transform is applied. + LoadHTML( + R"( + <!doctype html> + <body> + <div style="display: inline-block; + padding: 16px; + font-size: 16px;"> + <div style="padding: 16px; + transform: rotate(45deg) translate(100px, 0); + margin-bottom: 30px;"> + <div> + <a href="http://www.example.com" style="display: block; + width: 70px; + height: 20px;"> + <div>Example</div> + </a> + </div> + </div> + </div> + </body>)"); + auto out_response = mojom::PaintPreviewCaptureResponse::New(); + content::RenderFrame* frame = GetFrame(); + + RunCapture(frame, &out_response); + + EXPECT_TRUE(out_response->embedding_token.has_value()); + EXPECT_EQ(frame->GetWebFrame()->GetEmbeddingToken(), + out_response->embedding_token.value()); + EXPECT_EQ(out_response->content_id_to_embedding_token.size(), 0U); + + ASSERT_EQ(out_response->links.size(), 1U); + EXPECT_EQ(out_response->links[0]->url, GURL("http://www.example.com")); + EXPECT_NEAR(out_response->links[0]->rect.x(), 111, 5); + EXPECT_NEAR(out_response->links[0]->rect.y(), 88, 5); +#if !defined(OS_ANDROID) + EXPECT_NEAR(out_response->links[0]->rect.width(), 58, 10); + EXPECT_NEAR(out_response->links[0]->rect.height(), 58, 10); +#endif +} + +TEST_F(PaintPreviewRecorderRenderViewTest, CaptureWithScale) { + // URLs should be annotated correctly when a CSS transform is applied. + LoadHTML( + R"( + <!doctype html> + <body> + <div style="display: inline-block; + padding: 16px; + font-size: 16px;"> + <div style="padding: 16px; + transform: scale(2, 1); + margin-bottom: 30px;"> + <div> + <a href="http://www.example.com" style="display: block; + width: 70px; + height: 20px;"> + <div>Example</div> + </a> + </div> + </div> + </div> + </body>)"); + auto out_response = mojom::PaintPreviewCaptureResponse::New(); + content::RenderFrame* frame = GetFrame(); + + RunCapture(frame, &out_response); + + EXPECT_TRUE(out_response->embedding_token.has_value()); + EXPECT_EQ(frame->GetWebFrame()->GetEmbeddingToken(), + out_response->embedding_token.value()); + EXPECT_EQ(out_response->content_id_to_embedding_token.size(), 0U); + + ASSERT_EQ(out_response->links.size(), 1U); + EXPECT_EQ(out_response->links[0]->url, GURL("http://www.example.com")); + EXPECT_NEAR(out_response->links[0]->rect.x(), 5, 3); + EXPECT_NEAR(out_response->links[0]->rect.y(), 40, 3); + EXPECT_NEAR(out_response->links[0]->rect.width(), 140, 3); + EXPECT_NEAR(out_response->links[0]->rect.height(), 20, 3); +} + +TEST_F(PaintPreviewRecorderRenderViewTest, CaptureSaveRestore) { + // URLs should be annotated correctly when a CSS transform is applied. + LoadHTML( + R"( + <!doctype html> + <body> + <div style="display: inline-block; + padding: 16px; + font-size: 16px;"> + <div style="padding: 16px; + transform: translate(20px, 0); + margin-bottom: 30px;"> + <div> + <a href="http://www.example.com" style="display: block; + width: 70px; + height: 20px;"> + <div>Example</div> + </a> + </div> + </div> + <div style="padding: 16px; + transform: none; + margin-bottom: 30px;"> + <div> + <a href="http://www.chromium.org" style="display: block; + width: 80px; + height: 20px;"> + <div>Chromium</div> + </a> + </div> + </div> + </div> + </body>)"); + auto out_response = mojom::PaintPreviewCaptureResponse::New(); + content::RenderFrame* frame = GetFrame(); + + RunCapture(frame, &out_response); + + EXPECT_TRUE(out_response->embedding_token.has_value()); + EXPECT_EQ(frame->GetWebFrame()->GetEmbeddingToken(), + out_response->embedding_token.value()); + EXPECT_EQ(out_response->content_id_to_embedding_token.size(), 0U); + + ASSERT_EQ(out_response->links.size(), 2U); + EXPECT_EQ(out_response->links[0]->url, GURL("http://www.chromium.org")); + EXPECT_NEAR(out_response->links[0]->rect.x(), 40, 3); + EXPECT_NEAR(out_response->links[0]->rect.y(), 122, 3); + EXPECT_NEAR(out_response->links[0]->rect.width(), 80, 3); + EXPECT_NEAR(out_response->links[0]->rect.height(), 20, 3); + + EXPECT_EQ(out_response->links[1]->url, GURL("http://www.example.com")); + EXPECT_NEAR(out_response->links[1]->rect.x(), 60, 3); + EXPECT_NEAR(out_response->links[1]->rect.y(), 40, 3); + EXPECT_NEAR(out_response->links[1]->rect.width(), 70, 3); + EXPECT_NEAR(out_response->links[1]->rect.height(), 20, 3); +} + } // namespace paint_preview
diff --git a/components/paint_preview/renderer/paint_preview_recorder_impl.cc b/components/paint_preview/renderer/paint_preview_recorder_impl.cc index 1a08834..1de00be 100644 --- a/components/paint_preview/renderer/paint_preview_recorder_impl.cc +++ b/components/paint_preview/renderer/paint_preview_recorder_impl.cc
@@ -57,9 +57,9 @@ return out; } - TRACE_EVENT_BEGIN0("paint_preview", "ParseGlyphs"); - ParseGlyphs(recording.get(), tracker.get()); - TRACE_EVENT_END0("paint_preview", "ParseGlyphs"); + TRACE_EVENT_BEGIN0("paint_preview", "ParseGlyphsAndLinks"); + ParseGlyphsAndLinks(recording.get(), tracker.get()); + TRACE_EVENT_END0("paint_preview", "ParseGlyphsAndLinks"); size_t serialized_size = 0; bool success = false;
diff --git a/components/paint_preview/renderer/paint_preview_recorder_utils.cc b/components/paint_preview/renderer/paint_preview_recorder_utils.cc index 28eda0b..d15b478 100644 --- a/components/paint_preview/renderer/paint_preview_recorder_utils.cc +++ b/components/paint_preview/renderer/paint_preview_recorder_utils.cc
@@ -12,20 +12,80 @@ #include "components/paint_preview/common/file_stream.h" #include "components/paint_preview/common/paint_preview_tracker.h" #include "mojo/public/cpp/base/shared_memory_utils.h" +#include "third_party/skia/include/core/SkData.h" +#include "third_party/skia/include/core/SkRefCnt.h" namespace paint_preview { -void ParseGlyphs(const cc::PaintOpBuffer* buffer, - PaintPreviewTracker* tracker) { +void ParseGlyphsAndLinks(const cc::PaintOpBuffer* buffer, + PaintPreviewTracker* tracker) { for (cc::PaintOpBuffer::Iterator it(buffer); it; ++it) { - if (it->GetType() == cc::PaintOpType::DrawTextBlob) { - auto* text_blob_op = static_cast<cc::DrawTextBlobOp*>(*it); - tracker->AddGlyphs(text_blob_op->blob.get()); - } else if (it->GetType() == cc::PaintOpType::DrawRecord) { - // Recurse into nested records if they contain text blobs (equivalent to - // nested SkPictures). - auto* record_op = static_cast<cc::DrawRecordOp*>(*it); - ParseGlyphs(record_op->record.get(), tracker); + switch (it->GetType()) { + case cc::PaintOpType::DrawTextBlob: { + auto* text_blob_op = static_cast<cc::DrawTextBlobOp*>(*it); + tracker->AddGlyphs(text_blob_op->blob.get()); + break; + } + case cc::PaintOpType::DrawRecord: { + // Recurse into nested records if they contain text blobs (equivalent to + // nested SkPictures). + auto* record_op = static_cast<cc::DrawRecordOp*>(*it); + ParseGlyphsAndLinks(record_op->record.get(), tracker); + break; + } + case cc::PaintOpType::Annotate: { + auto* annotate_op = static_cast<cc::AnnotateOp*>(*it); + tracker->AnnotateLink(GURL(std::string(reinterpret_cast<const char*>( + annotate_op->data->data()), + annotate_op->data->size())), + annotate_op->rect); + // Delete the data. We no longer need it. + annotate_op->data.reset(); + return; + } + case cc::PaintOpType::Save: { + tracker->Save(); + break; + } + case cc::PaintOpType::SaveLayer: { + tracker->Save(); + break; + } + case cc::PaintOpType::SaveLayerAlpha: { + tracker->Save(); + break; + } + case cc::PaintOpType::Restore: { + tracker->Restore(); + break; + } + case cc::PaintOpType::SetMatrix: { + auto* matrix_op = static_cast<cc::SetMatrixOp*>(*it); + tracker->SetMatrix(matrix_op->matrix); + break; + } + case cc::PaintOpType::Concat: { + auto* concat_op = static_cast<cc::ConcatOp*>(*it); + tracker->Concat(concat_op->matrix); + break; + } + case cc::PaintOpType::Scale: { + auto* scale_op = static_cast<cc::ScaleOp*>(*it); + tracker->Scale(scale_op->sx, scale_op->sy); + break; + } + case cc::PaintOpType::Rotate: { + auto* rotate_op = static_cast<cc::RotateOp*>(*it); + tracker->Rotate(rotate_op->degrees); + break; + } + case cc::PaintOpType::Translate: { + auto* translate_op = static_cast<cc::TranslateOp*>(*it); + tracker->Translate(translate_op->dx, translate_op->dy); + break; + } + default: + continue; } } }
diff --git a/components/paint_preview/renderer/paint_preview_recorder_utils.h b/components/paint_preview/renderer/paint_preview_recorder_utils.h index 69acb1f..89ca935 100644 --- a/components/paint_preview/renderer/paint_preview_recorder_utils.h +++ b/components/paint_preview/renderer/paint_preview_recorder_utils.h
@@ -21,9 +21,10 @@ class PaintPreviewTracker; -// Walks |buffer| to extract all the glyphs from its text blobs and writes -// them to |tracker|. -void ParseGlyphs(const cc::PaintOpBuffer* buffer, PaintPreviewTracker* tracker); +// Walks |buffer| to extract all the glyphs from its text blobs and links. The +// extracted data is written to to |tracker|. +void ParseGlyphsAndLinks(const cc::PaintOpBuffer* buffer, + PaintPreviewTracker* tracker); // Serializes |record| to |out_stream| as an SkPicture of size |dimensions|. // |tracker| supplies metadata required during serialization.
diff --git a/components/paint_preview/renderer/paint_preview_recorder_utils_unittest.cc b/components/paint_preview/renderer/paint_preview_recorder_utils_unittest.cc index 68858f5..f67984c 100644 --- a/components/paint_preview/renderer/paint_preview_recorder_utils_unittest.cc +++ b/components/paint_preview/renderer/paint_preview_recorder_utils_unittest.cc
@@ -33,6 +33,19 @@ namespace paint_preview { +namespace { + +sk_sp<cc::PaintRecord> AddLink(const std::string& link, const SkRect& rect) { + cc::PaintRecorder link_recorder; + cc::PaintCanvas* link_canvas = link_recorder.beginRecording( + rect.x() + rect.width(), rect.y() + rect.height()); + link_canvas->Annotate(cc::PaintCanvas::AnnotationType::URL, rect, + SkData::MakeWithCString(link.c_str())); + return link_recorder.finishRecordingAsPicture(); +} + +} // namespace + TEST(PaintPreviewRecorderUtilsTest, TestParseGlyphs) { auto typeface = SkTypeface::MakeDefault(); SkFont font(typeface); @@ -53,7 +66,7 @@ PaintPreviewTracker tracker(base::UnguessableToken::Create(), base::UnguessableToken::Create(), true); - ParseGlyphs(record.get(), &tracker); + ParseGlyphsAndLinks(record.get(), &tracker); auto* usage_map = tracker.GetTypefaceUsageMap(); EXPECT_TRUE(usage_map->count(typeface->uniqueID())); EXPECT_TRUE( @@ -70,6 +83,80 @@ (*usage_map)[typeface->uniqueID()]->IsSet(typeface->unicharToGlyph('g'))); } +TEST(PaintPreviewRecorderUtilsTest, TestParseLinks) { + cc::PaintFlags flags; + cc::PaintRecorder outer_recorder; + cc::PaintCanvas* outer_canvas = outer_recorder.beginRecording(500, 500); + + outer_canvas->save(); + outer_canvas->translate(10, 20); + std::string link_1 = "http://www.foo.com/"; + SkRect rect_1 = SkRect::MakeXYWH(10, 20, 30, 40); + outer_canvas->drawPicture(AddLink(link_1, rect_1)); + outer_canvas->restore(); + + outer_canvas->save(); + outer_canvas->concat(SkMatrix::Translate(40, 50)); + outer_canvas->scale(2, 4); + std::string link_2 = "http://www.bar.com/"; + SkRect rect_2 = SkRect::MakeXYWH(1, 2, 3, 4); + outer_canvas->drawPicture(AddLink(link_2, rect_2)); + + cc::PaintRecorder inner_recorder; + cc::PaintCanvas* inner_canvas = inner_recorder.beginRecording(500, 500); + inner_canvas->rotate(20); + std::string link_3 = "http://www.baz.com/"; + SkRect rect_3 = SkRect::MakeXYWH(5, 7, 9, 13); + inner_canvas->drawPicture(AddLink(link_3, rect_3)); + + outer_canvas->drawPicture(inner_recorder.finishRecordingAsPicture()); + outer_canvas->restore(); + + outer_canvas->save(); + outer_canvas->translate(20, 50); + outer_canvas->setMatrix(SkMatrix::Translate(10, 30)); + std::string link_4 = "http://www.example.com/"; + SkRect rect_4 = SkRect::MakeXYWH(10, 30, 40, 50); + outer_canvas->drawPicture(AddLink(link_4, rect_4)); + outer_canvas->restore(); + + outer_canvas->saveLayer(&rect_1, nullptr); + outer_canvas->saveLayerAlpha(&rect_1, 8); + outer_canvas->restoreToCount(1); + auto record = outer_recorder.finishRecordingAsPicture(); + + PaintPreviewTracker tracker(base::UnguessableToken::Create(), + base::UnguessableToken::Create(), true); + ParseGlyphsAndLinks(record.get(), &tracker); + + std::vector<mojom::LinkDataPtr> links; + tracker.MoveLinks(&links); + ASSERT_EQ(links.size(), 4U); + EXPECT_EQ(links[0]->url, link_1); + EXPECT_EQ(links[0]->rect.x(), rect_1.x() + 10); + EXPECT_EQ(links[0]->rect.y(), rect_1.y() + 20); + EXPECT_EQ(links[0]->rect.width(), rect_1.width()); + EXPECT_EQ(links[0]->rect.height(), rect_1.height()); + + EXPECT_EQ(links[1]->url, link_2); + EXPECT_EQ(links[1]->rect.x(), rect_2.x() * 2 + 40); + EXPECT_EQ(links[1]->rect.y(), rect_2.y() * 4 + 50); + EXPECT_EQ(links[1]->rect.width(), rect_2.width() * 2); + EXPECT_EQ(links[1]->rect.height(), rect_2.height() * 4); + + EXPECT_EQ(links[2]->url, link_3); + EXPECT_EQ(links[2]->rect.x(), 35); + EXPECT_EQ(links[2]->rect.y(), 83); + EXPECT_EQ(links[2]->rect.width(), 25); + EXPECT_EQ(links[2]->rect.height(), 61); + + EXPECT_EQ(links[3]->url, link_4); + EXPECT_EQ(links[3]->rect.x(), rect_4.x() + 10); + EXPECT_EQ(links[3]->rect.y(), rect_4.y() + 30); + EXPECT_EQ(links[3]->rect.width(), rect_4.width()); + EXPECT_EQ(links[3]->rect.height(), rect_4.height()); +} + class PaintPreviewRecorderUtilsSerializeAsSkPictureTest : public testing::TestWithParam<mojom::Persistence> { public: @@ -191,8 +278,9 @@ auto token = base::UnguessableToken::Create(); auto embedding_token = base::UnguessableToken::Create(); PaintPreviewTracker tracker(token, embedding_token, true); - tracker.AnnotateLink(GURL("www.google.com"), gfx::Rect(1, 2, 3, 4)); - tracker.AnnotateLink(GURL("www.chromium.org"), gfx::Rect(10, 20, 10, 20)); + tracker.AnnotateLink(GURL("www.google.com"), SkRect::MakeXYWH(1, 2, 3, 4)); + tracker.AnnotateLink(GURL("www.chromium.org"), + SkRect::MakeXYWH(10, 20, 10, 20)); tracker.CreateContentForRemoteFrame(gfx::Rect(1, 1, 1, 1), base::UnguessableToken::Create()); tracker.CreateContentForRemoteFrame(gfx::Rect(1, 2, 4, 8),
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentFeatureList.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentFeatureList.java index 47070c97..79b22ff 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentFeatureList.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentFeatureList.java
@@ -28,6 +28,7 @@ public static final String WEB_PAYMENTS = "WebPayments"; public static final String WEB_PAYMENTS_ALWAYS_ALLOW_JUST_IN_TIME_PAYMENT_APP = "AlwaysAllowJustInTimePaymentApp"; + public static final String WEB_PAYMENTS_APP_STORE_BILLING = "AppStoreBilling"; public static final String WEB_PAYMENTS_APP_STORE_BILLING_DEBUG = "AppStoreBillingDebug"; public static final String WEB_PAYMENTS_EXPERIMENTAL_FEATURES = "WebPaymentsExperimentalFeatures";
diff --git a/components/payments/content/android/payment_feature_list.cc b/components/payments/content/android/payment_feature_list.cc index 03fe29b..3a105c0 100644 --- a/components/payments/content/android/payment_feature_list.cc +++ b/components/payments/content/android/payment_feature_list.cc
@@ -24,6 +24,7 @@ &::features::kWebPayments, &::features::kWebPaymentsMinimalUI, &features::kAlwaysAllowJustInTimePaymentApp, + &features::kAppStoreBilling, &features::kAppStoreBillingDebug, &features::kEnforceFullDelegation, &features::kPaymentRequestSkipToGPay,
diff --git a/components/payments/core/features.cc b/components/payments/core/features.cc index 341ecf7..b129c3e 100644 --- a/components/payments/core/features.cc +++ b/components/payments/core/features.cc
@@ -4,6 +4,8 @@ #include "components/payments/core/features.h" +#include "build/build_config.h" + namespace payments { namespace features { @@ -44,6 +46,15 @@ const base::Feature kWebPaymentsRedactShippingAddress{ "WebPaymentsRedactShippingAddress", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kAppStoreBilling { + "AppStoreBilling", +#if defined(OS_ANDROID) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif // OS_ANDROID +}; + const base::Feature kAppStoreBillingDebug{"AppStoreBillingDebug", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/payments/core/features.h b/components/payments/core/features.h index 2a9e3c1b..60b86bf 100644 --- a/components/payments/core/features.h +++ b/components/payments/core/features.h
@@ -35,6 +35,10 @@ // with a single URL based payment app and no other info requested. extern const base::Feature kWebPaymentsSingleAppUiSkip; +// Used to control whether the invoking TWA can handle payments for app store +// payment method identifiers. +extern const base::Feature kAppStoreBilling; + // Used to control whether to remove the restriction that TWA has to be // installed from specific app stores. extern const base::Feature kAppStoreBillingDebug;
diff --git a/components/performance_manager/BUILD.gn b/components/performance_manager/BUILD.gn index 83ee545..41693801 100644 --- a/components/performance_manager/BUILD.gn +++ b/components/performance_manager/BUILD.gn
@@ -155,10 +155,8 @@ if (!is_android) { sources += [ "decorators/site_data_recorder.cc", - "decorators/site_data_recorder.h", "persistence/site_data/exponential_moving_average.cc", "persistence/site_data/exponential_moving_average.h", - "persistence/site_data/feature_usage.h", "persistence/site_data/leveldb_site_data_store.cc", "persistence/site_data/leveldb_site_data_store.h", "persistence/site_data/non_recording_site_data_cache.cc", @@ -174,11 +172,13 @@ "persistence/site_data/site_data_impl.cc", "persistence/site_data/site_data_impl.h", "persistence/site_data/site_data_reader.cc", - "persistence/site_data/site_data_reader.h", "persistence/site_data/site_data_store.h", "persistence/site_data/site_data_writer.cc", "persistence/site_data/site_data_writer.h", "persistence/site_data/tab_visibility.h", + "public/decorators/site_data_recorder.h", + "public/persistence/site_data/feature_usage.h", + "public/persistence/site_data/site_data_reader.h", ] public_deps += [
diff --git a/components/performance_manager/decorators/site_data_recorder.cc b/components/performance_manager/decorators/site_data_recorder.cc index 6150f1a..07c67086 100644 --- a/components/performance_manager/decorators/site_data_recorder.cc +++ b/components/performance_manager/decorators/site_data_recorder.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/performance_manager/decorators/site_data_recorder.h" +#include "components/performance_manager/public/decorators/site_data_recorder.h" #include "base/time/time.h" #include "components/performance_manager/graph/node_attached_data_impl.h" @@ -10,6 +10,7 @@ #include "components/performance_manager/persistence/site_data/site_data_cache.h" #include "components/performance_manager/persistence/site_data/site_data_cache_factory.h" #include "components/performance_manager/persistence/site_data/site_data_writer.h" +#include "components/performance_manager/public/persistence/site_data/site_data_reader.h" namespace performance_manager { @@ -74,6 +75,11 @@ return writer_.get(); } + SiteDataReader* reader() const override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return reader_.get(); + } + private: // The features tracked by the SiteDataRecorder class. enum class FeatureType { @@ -110,6 +116,7 @@ base::TimeTicks loaded_time_; std::unique_ptr<SiteDataWriter> writer_; + std::unique_ptr<SiteDataReader> reader_; SEQUENCE_CHECKER(sequence_checker_); @@ -131,6 +138,7 @@ return; writer_ = data_cache_->GetWriterForOrigin(origin); + reader_ = data_cache_->GetReaderForOrigin(origin); // The writer is assumed to be in an unloaded state by default, set the proper // loading state if necessary. @@ -193,6 +201,7 @@ loaded_time_ = base::TimeTicks(); } writer_.reset(); + reader_.reset(); } bool SiteDataNodeData::ShouldIgnoreFeatureUsageEvent(FeatureType feature_type) { @@ -338,6 +347,12 @@ SiteDataNodeData::Data::~Data() = default; // static +const SiteDataRecorder::Data* SiteDataRecorder::Data::FromPageNode( + const PageNode* page_node) { + return SiteDataNodeData::Get(PageNodeImpl::FromNode(page_node)); +} + +// static SiteDataRecorder::Data* SiteDataRecorder::Data::GetForTesting( const PageNode* page_node) { return GetSiteDataNodeDataFromPageNode(page_node);
diff --git a/components/performance_manager/decorators/site_data_recorder_unittest.cc b/components/performance_manager/decorators/site_data_recorder_unittest.cc index cb6309d1..bc89aea 100644 --- a/components/performance_manager/decorators/site_data_recorder_unittest.cc +++ b/components/performance_manager/decorators/site_data_recorder_unittest.cc
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/performance_manager/decorators/site_data_recorder.h" +#include "components/performance_manager/public/decorators/site_data_recorder.h" + #include <memory> #include "base/callback_forward.h"
diff --git a/components/performance_manager/performance_manager_lifetime.cc b/components/performance_manager/performance_manager_lifetime.cc index cb08a59..e402b2b3 100644 --- a/components/performance_manager/performance_manager_lifetime.cc +++ b/components/performance_manager/performance_manager_lifetime.cc
@@ -5,6 +5,7 @@ #include "components/performance_manager/embedder/performance_manager_lifetime.h" #include "base/bind.h" +#include "build/build_config.h" #include "components/performance_manager/decorators/page_load_tracker_decorator.h" #include "components/performance_manager/execution_context/execution_context_registry_impl.h" #include "components/performance_manager/graph/frame_node_impl_describer.h" @@ -16,6 +17,10 @@ #include "components/performance_manager/public/decorators/tab_properties_decorator.h" #include "components/performance_manager/public/graph/graph.h" +#if !defined(OS_ANDROID) +#include "components/performance_manager/public/decorators/site_data_recorder.h" +#endif + namespace performance_manager { namespace { @@ -32,6 +37,9 @@ graph->PassToGraph(std::make_unique<ProcessNodeImplDescriber>()); graph->PassToGraph(std::make_unique<TabPropertiesDecorator>()); graph->PassToGraph(std::make_unique<WorkerNodeImplDescriber>()); +#if !defined(OS_ANDROID) + graph->PassToGraph(std::make_unique<SiteDataRecorder>()); +#endif std::move(external_graph_created_callback).Run(graph); }
diff --git a/components/performance_manager/persistence/site_data/non_recording_site_data_cache.cc b/components/performance_manager/persistence/site_data/non_recording_site_data_cache.cc index 63fa384c..b1e627a 100644 --- a/components/performance_manager/persistence/site_data/non_recording_site_data_cache.cc +++ b/components/performance_manager/persistence/site_data/non_recording_site_data_cache.cc
@@ -7,8 +7,8 @@ #include "base/memory/ptr_util.h" #include "components/performance_manager/persistence/site_data/noop_site_data_writer.h" #include "components/performance_manager/persistence/site_data/site_data_cache_factory.h" -#include "components/performance_manager/persistence/site_data/site_data_reader.h" #include "components/performance_manager/persistence/site_data/site_data_writer.h" +#include "components/performance_manager/public/persistence/site_data/site_data_reader.h" namespace performance_manager {
diff --git a/components/performance_manager/persistence/site_data/site_data_cache.h b/components/performance_manager/persistence/site_data/site_data_cache.h index 01753812..61d37fb 100644 --- a/components/performance_manager/persistence/site_data/site_data_cache.h +++ b/components/performance_manager/persistence/site_data/site_data_cache.h
@@ -8,9 +8,9 @@ #include <memory> #include "base/macros.h" -#include "components/performance_manager/persistence/site_data/site_data_reader.h" #include "components/performance_manager/persistence/site_data/site_data_writer.h" #include "components/performance_manager/persistence/site_data/tab_visibility.h" +#include "components/performance_manager/public/persistence/site_data/site_data_reader.h" #include "url/origin.h" namespace performance_manager {
diff --git a/components/performance_manager/persistence/site_data/site_data_cache_impl.cc b/components/performance_manager/persistence/site_data/site_data_cache_impl.cc index 8fe99d9..369eab9d6 100644 --- a/components/performance_manager/persistence/site_data/site_data_cache_impl.cc +++ b/components/performance_manager/persistence/site_data/site_data_cache_impl.cc
@@ -12,8 +12,8 @@ #include "base/stl_util.h" #include "components/performance_manager/persistence/site_data/leveldb_site_data_store.h" #include "components/performance_manager/persistence/site_data/site_data_cache_factory.h" -#include "components/performance_manager/persistence/site_data/site_data_reader.h" #include "components/performance_manager/persistence/site_data/site_data_writer.h" +#include "components/performance_manager/public/persistence/site_data/site_data_reader.h" namespace performance_manager {
diff --git a/components/performance_manager/persistence/site_data/site_data_impl.h b/components/performance_manager/persistence/site_data/site_data_impl.h index eef1eb1..ee090e32 100644 --- a/components/performance_manager/persistence/site_data/site_data_impl.h +++ b/components/performance_manager/persistence/site_data/site_data_impl.h
@@ -16,10 +16,10 @@ #include "base/sequence_checker.h" #include "base/time/time.h" #include "components/performance_manager/persistence/site_data/exponential_moving_average.h" -#include "components/performance_manager/persistence/site_data/feature_usage.h" #include "components/performance_manager/persistence/site_data/site_data.pb.h" #include "components/performance_manager/persistence/site_data/site_data_store.h" #include "components/performance_manager/persistence/site_data/tab_visibility.h" +#include "components/performance_manager/public/persistence/site_data/feature_usage.h" #include "url/origin.h" namespace performance_manager {
diff --git a/components/performance_manager/persistence/site_data/site_data_reader.cc b/components/performance_manager/persistence/site_data/site_data_reader.cc index 197a490..080d6645 100644 --- a/components/performance_manager/persistence/site_data/site_data_reader.cc +++ b/components/performance_manager/persistence/site_data/site_data_reader.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/performance_manager/persistence/site_data/site_data_reader.h" +#include "components/performance_manager/public/persistence/site_data/site_data_reader.h" #include <utility>
diff --git a/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc b/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc index 3f43575..f308f179 100644 --- a/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc +++ b/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/performance_manager/persistence/site_data/site_data_reader.h" +#include "components/performance_manager/public/persistence/site_data/site_data_reader.h" #include <memory> #include <utility>
diff --git a/components/performance_manager/persistence/site_data/site_data_writer_unittest.cc b/components/performance_manager/persistence/site_data/site_data_writer_unittest.cc index 8f0fb427..272089fd 100644 --- a/components/performance_manager/persistence/site_data/site_data_writer_unittest.cc +++ b/components/performance_manager/persistence/site_data/site_data_writer_unittest.cc
@@ -7,9 +7,9 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/time/time.h" -#include "components/performance_manager/persistence/site_data/feature_usage.h" #include "components/performance_manager/persistence/site_data/site_data_impl.h" #include "components/performance_manager/persistence/site_data/unittest_utils.h" +#include "components/performance_manager/public/persistence/site_data/feature_usage.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h"
diff --git a/components/performance_manager/decorators/site_data_recorder.h b/components/performance_manager/public/decorators/site_data_recorder.h similarity index 79% rename from components/performance_manager/decorators/site_data_recorder.h rename to components/performance_manager/public/decorators/site_data_recorder.h index f8e8ddb..5abf5d26 100644 --- a/components/performance_manager/decorators/site_data_recorder.h +++ b/components/performance_manager/public/decorators/site_data_recorder.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_SITE_DATA_RECORDER_H_ -#define COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_SITE_DATA_RECORDER_H_ +#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_SITE_DATA_RECORDER_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_SITE_DATA_RECORDER_H_ #include "base/macros.h" #include "base/sequence_checker.h" @@ -12,11 +12,13 @@ namespace performance_manager { +class SiteDataReader; class SiteDataWriter; class SiteDataCache; // The SiteDataRecorder decorator is responsible for adorning PageNodes with a -// SiteDataWriter and for forwarding the event of interest to this writer. +// SiteDataReader and a SiteDataWriter and for forwarding the event of interest +// to this writer. class SiteDataRecorder : public GraphOwned, public PageNode::ObserverDefaultImpl { public: @@ -54,7 +56,8 @@ SEQUENCE_CHECKER(sequence_checker_); }; -// Allows retrieving the SiteDataWriter associated with a PageNode. +// Allows retrieving the SiteDataWriter and SiteDataReader associated with a +// PageNode. class SiteDataRecorder::Data { public: Data(); @@ -63,11 +66,13 @@ Data& operator=(const Data&) = delete; virtual SiteDataWriter* writer() const = 0; + virtual SiteDataReader* reader() const = 0; + static const Data* FromPageNode(const PageNode* page_node); virtual void SetDataCacheForTesting(SiteDataCache* cache) = 0; static Data* GetForTesting(const PageNode* page_node); }; } // namespace performance_manager -#endif // COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_SITE_DATA_RECORDER_H_ +#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_SITE_DATA_RECORDER_H_
diff --git a/components/performance_manager/persistence/site_data/feature_usage.h b/components/performance_manager/public/persistence/site_data/feature_usage.h similarity index 65% rename from components/performance_manager/persistence/site_data/feature_usage.h rename to components/performance_manager/public/persistence/site_data/feature_usage.h index a8db38f..a30540f 100644 --- a/components/performance_manager/persistence/site_data/feature_usage.h +++ b/components/performance_manager/public/persistence/site_data/feature_usage.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PERFORMANCE_MANAGER_PERSISTENCE_SITE_DATA_FEATURE_USAGE_H_ -#define COMPONENTS_PERFORMANCE_MANAGER_PERSISTENCE_SITE_DATA_FEATURE_USAGE_H_ +#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERSISTENCE_SITE_DATA_FEATURE_USAGE_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERSISTENCE_SITE_DATA_FEATURE_USAGE_H_ namespace performance_manager { @@ -17,4 +17,4 @@ } // namespace performance_manager -#endif // COMPONENTS_PERFORMANCE_MANAGER_PERSISTENCE_SITE_DATA_FEATURE_USAGE_H_ +#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERSISTENCE_SITE_DATA_FEATURE_USAGE_H_
diff --git a/components/performance_manager/persistence/site_data/site_data_reader.h b/components/performance_manager/public/persistence/site_data/site_data_reader.h similarity index 87% rename from components/performance_manager/persistence/site_data/site_data_reader.h rename to components/performance_manager/public/persistence/site_data/site_data_reader.h index 193d02d..3a26cbe 100644 --- a/components/performance_manager/persistence/site_data/site_data_reader.h +++ b/components/performance_manager/public/persistence/site_data/site_data_reader.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PERFORMANCE_MANAGER_PERSISTENCE_SITE_DATA_SITE_DATA_READER_H_ -#define COMPONENTS_PERFORMANCE_MANAGER_PERSISTENCE_SITE_DATA_SITE_DATA_READER_H_ +#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERSISTENCE_SITE_DATA_SITE_DATA_READER_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERSISTENCE_SITE_DATA_SITE_DATA_READER_H_ #include "base/callback_forward.h" #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "components/performance_manager/persistence/site_data/feature_usage.h" +#include "components/performance_manager/public/persistence/site_data/feature_usage.h" namespace performance_manager { @@ -73,4 +73,4 @@ } // namespace performance_manager -#endif // COMPONENTS_PERFORMANCE_MANAGER_PERSISTENCE_SITE_DATA_SITE_DATA_READER_H_ +#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERSISTENCE_SITE_DATA_SITE_DATA_READER_H_
diff --git a/components/performance_manager/test_support/test_harness_helper.h b/components/performance_manager/test_support/test_harness_helper.h index f8e87f05..ee78514 100644 --- a/components/performance_manager/test_support/test_harness_helper.h +++ b/components/performance_manager/test_support/test_harness_helper.h
@@ -50,14 +50,14 @@ const PerformanceManagerTestHarnessHelper&) = delete; PerformanceManagerTestHarnessHelper& operator=( const PerformanceManagerTestHarnessHelper&) = delete; - ~PerformanceManagerTestHarnessHelper(); + virtual ~PerformanceManagerTestHarnessHelper(); // Sets up the PM and registry, etc. - void SetUp(); + virtual void SetUp(); // Tears down the PM and registry, etc. Blocks on the main thread until they // are torn down. - void TearDown(); + virtual void TearDown(); // Attaches tab helpers to the provided |contents|. This should only need to // be called explicitly in components_unittests. In unit_tests, browser_tests
diff --git a/components/performance_manager/worker_watcher.cc b/components/performance_manager/worker_watcher.cc index b5935e1..6e786e4 100644 --- a/components/performance_manager/worker_watcher.cc +++ b/components/performance_manager/worker_watcher.cc
@@ -13,7 +13,7 @@ #include "components/performance_manager/graph/worker_node_impl.h" #include "components/performance_manager/performance_manager_impl.h" #include "components/performance_manager/process_node_source.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" namespace performance_manager {
diff --git a/components/performance_manager/worker_watcher.h b/components/performance_manager/worker_watcher.h index 1e8c566..e1a2d00 100644 --- a/components/performance_manager/worker_watcher.h +++ b/components/performance_manager/worker_watcher.h
@@ -19,7 +19,7 @@ #include "content/public/browser/service_worker_context.h" #include "content/public/browser/service_worker_context_observer.h" #include "content/public/browser/shared_worker_service.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" namespace performance_manager {
diff --git a/components/permissions/contexts/geolocation_permission_context_unittest.cc b/components/permissions/contexts/geolocation_permission_context_unittest.cc index 8aec360..5c4fbd1 100644 --- a/components/permissions/contexts/geolocation_permission_context_unittest.cc +++ b/components/permissions/contexts/geolocation_permission_context_unittest.cc
@@ -253,8 +253,9 @@ const GURL& requesting_frame, ContentSetting expected_content_setting) { auto* content_settings = - content_settings::TabSpecificContentSettings::FromWebContents( - web_contents()); + content_settings::TabSpecificContentSettings::GetForFrame( + web_contents()->GetMainFrame()); + const ContentSettingsUsagesState::StateMap& state_map = content_settings->geolocation_usages_state().state_map(); EXPECT_EQ(1U, state_map.count(requesting_frame.GetOrigin()));
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto index deda32c4..d6dafed 100644 --- a/components/policy/proto/device_management_backend.proto +++ b/components/policy/proto/device_management_backend.proto
@@ -2911,6 +2911,32 @@ COMPLETE = 4; }; + // Current stage of the extension downloading process. See + // ExtensionDownloaderDelegate::Stage for more details. + // ExtensionDownloaderDelegate::Stage is the main enum and this is a copy used + // for reporting purposes. + enum DownloadingStage { + DOWNLOAD_PENDING = 0; + + QUEUED_FOR_MANIFEST = 1; + + DOWNLOADING_MANIFEST = 2; + + DOWNLOADING_MANIFEST_RETRY = 3; + + PARSING_MANIFEST = 4; + + MANIFEST_LOADED = 5; + + QUEUED_FOR_CRX = 6; + + DOWNLOADING_CRX = 7; + + DOWNLOADING_CRX_RETRY = 8; + + FINISHED = 9; + }; + // Timestamp, in microseconds since epoch. Set for all log // events. optional int64 timestamp = 1; @@ -2935,6 +2961,9 @@ // Stage of installation process. optional InstallationStage installation_stage = 8; + + // Stage of downloading process. + optional DownloadingStage downloading_stage = 9; } // A single entry in the push-install log for an app.
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index ac6820bb..0e7c41f 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -15293,43 +15293,56 @@ 'device_only': True, 'type': 'dict', 'schema': { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'chromeos_version': { - 'description': '''Minimum allowed <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version''', - 'type': 'string', - }, - 'warning_period': { - 'description': '''Time in days after which the user will be signed out if <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version is less than the specified <ph name="CHROMEOS_VERSION_PROPERTY_NAME">chromeos_version</ph>''', - 'type': 'integer', - 'minimum': 0, - }, - 'aue_warning_period': { - 'description': '''Time in days after auto update expiration post which the user will be signed out if <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version is less than the specified <ph name="CHROMEOS_VERSION_PROPERTY_NAME">chromeos_version</ph>''', - 'type': 'integer', - 'minimum': 0, + 'type': 'object', + 'properties': { + 'requirements': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'chromeos_version': { + 'description': '''Minimum allowed <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version''', + 'type': 'string', + }, + 'warning_period': { + 'description': '''Time in days after which the user will be signed out if <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version is less than the specified <ph name="CHROMEOS_VERSION_PROPERTY_NAME">chromeos_version</ph>''', + 'type': 'integer', + 'minimum': 0, + }, + 'aue_warning_period': { + 'description': '''Time in days after auto update expiration post which the user will be signed out if <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version is less than the specified <ph name="CHROMEOS_VERSION_PROPERTY_NAME">chromeos_version</ph>''', + 'type': 'integer', + 'minimum': 0, + }, + }, + 'required': ['chromeos_version'], }, }, - 'required': ['chromeos_version'], - }, + 'unmanaged_user_restricted': { + 'description': '''A boolean flag indicating whether unmanaged user sessions should receive notifications and force log out if update is required as per this policy.''', + 'type': 'boolean' + } + } }, 'features': { 'dynamic_refresh': True, 'per_profile': False, }, - 'example_value': [ - { - "chromeos_version" : "12215", - "warning_period" : 0, - "aue_warning_period" : 14 - }, { - "chromeos_version" : "13315.60.12", - "warning_period" : 10, - "aue_warning_period" : 21 - } - ], + 'example_value': { + "requirements": + [ + { + "chromeos_version" : "12215", + "warning_period" : 0, + "aue_warning_period" : 14 + }, { + "chromeos_version" : "13315.60.12", + "warning_period" : 10, + "aue_warning_period" : 21 + } + ], + "unmanaged_user_restricted": True + }, 'id': 670, 'caption': '''Configure minimum allowed Chrome OS version for the device.''', 'tags': [], @@ -15349,10 +15362,13 @@ If the current version becomes obsolete during user session and the device has reached auto update expiration, an on-screen notification is shown to return the device within <ph name="AUE_WARNING_PERIOD_PROPERTY_NAME">aue_warning_period</ph>. If the device is found to have reached auto update expiration at the time of login with expired <ph name="AUE_WARNING_PERIOD_PROPERTY_NAME">aue_warning_period</ph>, the device is blocked for any user to sign in. + Unmanaged user sessions do not receive notifications and force log out if <ph name="UNMANAGED_USER_RESTRICTED_PROPERTY_NAME">unmanaged_user_restricted</ph> is unset or set to False. + If this policy is not set or set to empty, no restrictions are applied, already existing restrictions are revoked and user can sign in regardless of <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version. Here <ph name="CHROMEOS_VERSION_PROPERTY_NAME">chromeos_version</ph> can be either an exact version like '13305.0.0' or a version prefix, like '13305'. - The <ph name="WARNING_PERIOD_PROPERTY_NAME">warning_period</ph> and <ph name="AUE_WARNING_PERIOD_PROPERTY_NAME">aue_warning_period</ph> are optional values specified in number of days. Default value for them is 0 days, which means that there is no warning period.''', + The <ph name="WARNING_PERIOD_PROPERTY_NAME">warning_period</ph> and <ph name="AUE_WARNING_PERIOD_PROPERTY_NAME">aue_warning_period</ph> are optional values specified in number of days. Default value for them is 0 days, which means that there is no warning period. + The <ph name="UNMANAGED_USER_RESTRICTED_PROPERTY_NAME">unmanaged_user_restricted</ph> is an optional property with default value as False.''', }, { 'name': 'DeviceMinimumVersionAueMessage',
diff --git a/components/signin/OWNERS b/components/signin/OWNERS index e4b8e297..837b6f4 100644 --- a/components/signin/OWNERS +++ b/components/signin/OWNERS
@@ -1,5 +1,6 @@ bsazonov@chromium.org droger@chromium.org +msalama@chromium.org msarda@chromium.org sdefresne@chromium.org
diff --git a/components/sync/engine_impl/model_type_worker.cc b/components/sync/engine_impl/model_type_worker.cc index 5162186..13280dbd 100644 --- a/components/sync/engine_impl/model_type_worker.cc +++ b/components/sync/engine_impl/model_type_worker.cc
@@ -446,14 +446,6 @@ model_type_processor_->OnCommitFailed(commit_error); } -void ModelTypeWorker::AbortMigration() { - DCHECK(!model_type_state_.initial_sync_done()); - model_type_state_ = sync_pb::ModelTypeState(); - entries_pending_decryption_.clear(); - pending_updates_.clear(); - nudge_handler_->NudgeForInitialDownload(type_); -} - size_t ModelTypeWorker::EstimateMemoryUsage() const { using base::trace_event::EstimateMemoryUsage; size_t memory_usage = 0;
diff --git a/components/sync/engine_impl/model_type_worker.h b/components/sync/engine_impl/model_type_worker.h index cd557f3a7..3da565b 100644 --- a/components/sync/engine_impl/model_type_worker.h +++ b/components/sync/engine_impl/model_type_worker.h
@@ -123,10 +123,6 @@ // called when a new encryption mechanism is ready. void EncryptionAcceptedMaybeApplyUpdates(); - // If migration the directory encounters an error partway through, we need to - // clear the update data that has been added so far. - void AbortMigration(); - // Public for testing. // Returns true if this type should stop communicating because of outstanding // encryption issues and must wait for keys to be updated.
diff --git a/components/sync/protocol/autofill_specifics.proto b/components/sync/protocol/autofill_specifics.proto index 1eb5886..c79d6dd9 100644 --- a/components/sync/protocol/autofill_specifics.proto +++ b/components/sync/protocol/autofill_specifics.proto
@@ -20,6 +20,28 @@ // An AutofillProfile. message AutofillProfileSpecifics { + // Represents the validation status of value stored in the AutofillProfile. + enum VerificationStatus { + // No verification status assigned. + VERIFICATION_STATUS_UNSPECIFIED = 0; + // The value token was parsed from a parent token. + // For example, the first name was derived by splitting a full name into + // its components. + PARSED = 1; + // Value was built from its subcomponents. + // For example, the full name was built from the first, middle and last + // name. + FORMATTED = 2; + // The value was observed in a form transmission. + // For example, the user filled a form that contained at NAME_FULL field. + // The value of NAME_FULL will be stored as OBSERVED. + OBSERVED = 3; + // The user used the autofill settings to verify and store this token. + // This is currently only applicable to the full name, since users cannot + // edit individual components of their name. + USER_VERIFIED = 4; + } + optional string guid = 15; optional string origin = 16; optional int64 use_count = 22; @@ -29,15 +51,44 @@ // from the Windows epoch. optional int64 use_date = 23; - // Contact info. + // Contact info name fields. + repeated string name_honorific = 26; repeated string name_first = 2; repeated string name_middle = 3; repeated string name_last = 4; + // Sometimes the last name is composed of two names as it is common for + // Hispanic/Latinx names. In the unstructured representation of the last name, + // there may be even a conjunction between the first and the second last + // name. For example, the more-complete version of Pablo Picasso's surname is + // "Ruiz y Picasso" containing a first last name, a conjunction (the y) and a + // second last name. + repeated string name_last_first = 27; + repeated string name_last_conjuction = 28; + repeated string name_last_second = 29; repeated string name_full = 21; + + // Validation status records for name fields. + repeated VerificationStatus name_honorific_status = 30; + repeated VerificationStatus name_first_status = 31; + repeated VerificationStatus name_middle_status = 32; + repeated VerificationStatus name_last_status = 33; + repeated VerificationStatus name_last_first_status = 34; + repeated VerificationStatus name_last_conjuction_status = 35; + repeated VerificationStatus name_last_second_status = 36; + repeated VerificationStatus name_full_status = 37; + + // Contact info additional fields. repeated string email_address = 5; optional string company_name = 6; - // Address. + // Address field. + // The address_home_line1/2 fields are deprecated and + // address_home_street_address should be used instead by + // joining address_home_line1/2 with a newline ("\n"). + // Full deprecation can not be achieved before all sync profiles have been + // updated with a M86+ client. + // TODO(crbug/1111740): Remove usages of address_home_line1/2 and mark field + // as deprecated. optional string address_home_line1 = 7; optional string address_home_line2 = 8; optional string address_home_city = 9; @@ -50,6 +101,27 @@ optional string address_home_sorting_code = 18; optional string address_home_dependent_locality = 19; optional string address_home_language_code = 20; + optional string address_home_thoroughfare_name = 38; + optional string address_home_thoroughfare_number = 39; + optional string address_home_dependent_thoroughfare_name = 40; + optional string address_home_premise_name = 41; + optional string address_home_subpremise_name = 42; + + // Validation status records for address fields. + optional VerificationStatus address_home_city_status = 43; + optional VerificationStatus address_home_state_status = 44; + optional VerificationStatus address_home_zip_status = 45; + optional VerificationStatus address_home_country_status = 46; + optional VerificationStatus address_home_street_address_status = 47; + optional VerificationStatus address_home_sorting_code_status = 48; + optional VerificationStatus address_home_dependent_locality_status = 49; + optional VerificationStatus address_home_language_code_status = 50; + optional VerificationStatus address_home_thoroughfare_name_status = 51; + optional VerificationStatus address_home_thoroughfare_number_status = 52; + optional VerificationStatus address_home_dependent_thoroughfare_name_status = + 53; + optional VerificationStatus address_home_premise_name_status = 54; + optional VerificationStatus address_home_subpremise_name_status = 55; // Phone. repeated string phone_home_whole_number = 13;
diff --git a/components/sync/protocol/proto_enum_conversions.cc b/components/sync/protocol/proto_enum_conversions.cc index a2e1142..bac8aef9e 100644 --- a/components/sync/protocol/proto_enum_conversions.cc +++ b/components/sync/protocol/proto_enum_conversions.cc
@@ -47,6 +47,22 @@ } const char* ProtoEnumToString( + sync_pb::AutofillProfileSpecifics::VerificationStatus status) { + ASSERT_ENUM_BOUNDS(sync_pb::AutofillProfileSpecifics, VerificationStatus, + VERIFICATION_STATUS_UNSPECIFIED, USER_VERIFIED); + switch (status) { + ENUM_CASE(sync_pb::AutofillProfileSpecifics, + VERIFICATION_STATUS_UNSPECIFIED); + ENUM_CASE(sync_pb::AutofillProfileSpecifics, PARSED); + ENUM_CASE(sync_pb::AutofillProfileSpecifics, FORMATTED); + ENUM_CASE(sync_pb::AutofillProfileSpecifics, OBSERVED); + ENUM_CASE(sync_pb::AutofillProfileSpecifics, USER_VERIFIED); + } + NOTREACHED(); + return ""; +} + +const char* ProtoEnumToString( sync_pb::AutofillWalletSpecifics::WalletInfoType wallet_info_type) { ASSERT_ENUM_BOUNDS(sync_pb::AutofillWalletSpecifics, WalletInfoType, UNKNOWN, CREDIT_CARD_CLOUD_TOKEN_DATA);
diff --git a/components/sync/protocol/proto_enum_conversions.h b/components/sync/protocol/proto_enum_conversions.h index 0b030c8..c49e54e 100644 --- a/components/sync/protocol/proto_enum_conversions.h +++ b/components/sync/protocol/proto_enum_conversions.h
@@ -108,6 +108,9 @@ sync_pb::WebAppSpecifics::UserDisplayMode user_display_mode); const char* ProtoEnumToString( + sync_pb::AutofillProfileSpecifics::VerificationStatus status); + +const char* ProtoEnumToString( sync_pb::WifiConfigurationSpecifics::SecurityType security_type); const char* ProtoEnumToString(
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h index a4091986..8e7d13a3 100644 --- a/components/sync/protocol/proto_visitors.h +++ b/components/sync/protocol/proto_visitors.h
@@ -141,12 +141,27 @@ VISIT(origin); VISIT(use_count); VISIT(use_date); + VISIT_REP(name_honorific); VISIT_REP(name_first); VISIT_REP(name_middle); + VISIT_REP(name_last_first); + VISIT_REP(name_last_conjuction); + VISIT_REP(name_last_second); VISIT_REP(name_last); VISIT_REP(name_full); + + VISIT_REP(name_honorific_status); + VISIT_REP(name_first_status); + VISIT_REP(name_middle_status); + VISIT_REP(name_last_first_status); + VISIT_REP(name_last_conjuction_status); + VISIT_REP(name_last_second_status); + VISIT_REP(name_last_status); + VISIT_REP(name_full_status); + VISIT_REP(email_address); VISIT(company_name); + VISIT(address_home_line1); VISIT(address_home_line2); VISIT(address_home_city); @@ -156,6 +171,25 @@ VISIT(address_home_street_address); VISIT(address_home_sorting_code); VISIT(address_home_dependent_locality); + VISIT(address_home_thoroughfare_name); + VISIT(address_home_thoroughfare_number); + VISIT(address_home_dependent_thoroughfare_name); + VISIT(address_home_premise_name); + VISIT(address_home_subpremise_name); + + VISIT_ENUM(address_home_city_status); + VISIT_ENUM(address_home_state_status); + VISIT_ENUM(address_home_zip_status); + VISIT_ENUM(address_home_country_status); + VISIT_ENUM(address_home_street_address_status); + VISIT_ENUM(address_home_sorting_code_status); + VISIT_ENUM(address_home_dependent_locality_status); + VISIT_ENUM(address_home_thoroughfare_name_status); + VISIT_ENUM(address_home_thoroughfare_number_status); + VISIT_ENUM(address_home_dependent_thoroughfare_name_status); + VISIT_ENUM(address_home_premise_name_status); + VISIT_ENUM(address_home_subpremise_name_status); + VISIT(address_home_language_code); VISIT_REP(phone_home_whole_number); VISIT(validity_state_bitfield);
diff --git a/components/url_formatter/url_formatter.cc b/components/url_formatter/url_formatter.cc index fbebb29..4f14b548 100644 --- a/components/url_formatter/url_formatter.cc +++ b/components/url_formatter/url_formatter.cc
@@ -200,6 +200,7 @@ format_types &= ~kFormatUrlOmitHTTPS; format_types &= ~kFormatUrlOmitTrivialSubdomains; format_types &= ~kFormatUrlTrimAfterHost; + format_types &= ~kFormatUrlOmitFileScheme; // Format the underlying URL and record adjustments. const std::string& url_str(url.possibly_invalid_spec());
diff --git a/components/url_formatter/url_formatter_unittest.cc b/components/url_formatter/url_formatter_unittest.cc index 80cf386..739eb62 100644 --- a/components/url_formatter/url_formatter_unittest.cc +++ b/components/url_formatter/url_formatter_unittest.cc
@@ -247,6 +247,19 @@ kFormatUrlOmitTrivialSubdomains | kFormatUrlTrimAfterHost, net::UnescapeRule::NORMAL, L"view-source:https://www.google.com/foo", 20}, +#if defined(OS_WIN) + {"view-source should not omit file on Windows", + "view-source:file:///C:/Users/homedirname/folder/file.pdf/", + kFormatUrlOmitDefaults | kFormatUrlOmitFileScheme, + net::UnescapeRule::NORMAL, + L"view-source:file:///C:/Users/homedirname/folder/file.pdf/", 19}, +#else + {"view-source should not omit file", + "view-source:file:///Users/homedirname/folder/file.pdf/", + kFormatUrlOmitDefaults | kFormatUrlOmitFileScheme, + net::UnescapeRule::NORMAL, + L"view-source:file:///Users/homedirname/folder/file.pdf/", 19}, +#endif // -------- omit https -------- {"omit https", "https://www.google.com/", kFormatUrlOmitHTTPS,
diff --git a/components/viz/host/gpu_host_impl.cc b/components/viz/host/gpu_host_impl.cc index 862abdd9..fbc86206 100644 --- a/components/viz/host/gpu_host_impl.cc +++ b/components/viz/host/gpu_host_impl.cc
@@ -25,8 +25,6 @@ #include "gpu/ipc/host/shader_disk_cache.h" #include "ui/base/ui_base_features.h" #include "ui/gfx/font_render_params.h" -#include "ui/ozone/public/gpu_platform_support_host.h" -#include "ui/ozone/public/ozone_platform.h" #if defined(OS_ANDROID) #include "base/android/build_info.h" @@ -38,6 +36,8 @@ #if defined(USE_OZONE) #include "ui/base/ui_base_features.h" +#include "ui/ozone/public/gpu_platform_support_host.h" +#include "ui/ozone/public/ozone_platform.h" #endif namespace viz {
diff --git a/components/viz/service/display_embedder/output_presenter.cc b/components/viz/service/display_embedder/output_presenter.cc index 035c23c5..6679d806a 100644 --- a/components/viz/service/display_embedder/output_presenter.cc +++ b/components/viz/service/display_embedder/output_presenter.cc
@@ -64,8 +64,10 @@ gpu::SharedImageRepresentation::AllowUnclearedAccess::kYes); DCHECK(scoped_skia_write_access_); if (!begin_semaphores.empty()) { - scoped_skia_write_access_->surface()->wait(begin_semaphores.size(), - begin_semaphores.data()); + scoped_skia_write_access_->surface()->wait( + begin_semaphores.size(), + begin_semaphores.data(), + /*deleteSemaphoresAfterWait=*/false); } }
diff --git a/components/viz/service/display_embedder/skia_output_device_webview.cc b/components/viz/service/display_embedder/skia_output_device_webview.cc index 6e067db..dd59bb7 100644 --- a/components/viz/service/display_embedder/skia_output_device_webview.cc +++ b/components/viz/service/display_embedder/skia_output_device_webview.cc
@@ -36,17 +36,7 @@ DCHECK(context_state_->gr_context()); DCHECK(context_state_->context()); - // Get alpha bits from the default frame buffer. - glBindFramebufferEXT(GL_FRAMEBUFFER, - gl_surface_->GetBackingFramebufferObject()); - context_state_->gr_context()->resetContext(kRenderTarget_GrGLBackendState); - GLint alpha_bits = 0; - glGetIntegerv(GL_ALPHA_BITS, &alpha_bits); - CHECK_GL_ERROR(); - supports_alpha_ = alpha_bits > 0; - - capabilities_.sk_color_type = - supports_alpha_ ? kRGBA_8888_SkColorType : kRGB_888x_SkColorType; + capabilities_.sk_color_type = kRGBA_8888_SkColorType; capabilities_.gr_backend_format = context_state_->gr_context()->defaultBackendFormat( capabilities_.sk_color_type, GrRenderable::kYes); @@ -109,9 +99,8 @@ GrGLFramebufferInfo framebuffer_info; framebuffer_info.fFBOID = fbo; - framebuffer_info.fFormat = supports_alpha_ ? GL_RGBA8 : GL_RGB8_OES; - DCHECK_EQ(capabilities_.gr_backend_format.asGLFormat(), - supports_alpha_ ? GrGLFormat::kRGBA8 : GrGLFormat::kRGB8); + framebuffer_info.fFormat = GL_RGBA8; + DCHECK_EQ(capabilities_.gr_backend_format.asGLFormat(), GrGLFormat::kRGBA8); SkColorType color_type = capabilities_.sk_color_type; GrBackendRenderTarget render_target(size_.width(), size_.height(),
diff --git a/components/viz/service/display_embedder/skia_output_device_webview.h b/components/viz/service/display_embedder/skia_output_device_webview.h index a240e49a..c27516e 100644 --- a/components/viz/service/display_embedder/skia_output_device_webview.h +++ b/components/viz/service/display_embedder/skia_output_device_webview.h
@@ -58,8 +58,6 @@ gfx::ColorSpace color_space_; unsigned int last_frame_buffer_object_ = -1; - bool supports_alpha_ = false; - base::WeakPtrFactory<SkiaOutputDeviceWebView> weak_ptr_factory_{this}; };
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 2d75921..fb553c6 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -543,8 +543,9 @@ promise_image_access_helper_.BeginAccess( std::move(image_contexts), &begin_semaphores, &end_semaphores); if (!begin_semaphores.empty()) { - auto result = output_sk_surface()->wait(begin_semaphores.size(), - begin_semaphores.data()); + auto result = output_sk_surface()->wait( + begin_semaphores.size(), begin_semaphores.data(), + /*deleteSemaphoresAfterWait=*/false); DCHECK(result); } @@ -668,8 +669,9 @@ promise_image_access_helper_.BeginAccess( std::move(image_contexts), &begin_semaphores, &end_semaphores); if (!begin_semaphores.empty()) { - auto result = offscreen.surface()->wait(begin_semaphores.size(), - begin_semaphores.data()); + auto result = offscreen.surface()->wait( + begin_semaphores.size(), begin_semaphores.data(), + /*deleteSemaphoresAfterWait=*/false); DCHECK(result); } offscreen.surface()->draw(ddl);
diff --git a/content/browser/device_sensors/device_sensor_browsertest.cc b/content/browser/device_sensors/device_sensor_browsertest.cc index 2ac11d6d..ae49fb3 100644 --- a/content/browser/device_sensors/device_sensor_browsertest.cc +++ b/content/browser/device_sensors/device_sensor_browsertest.cc
@@ -351,16 +351,15 @@ "https://github.com/WICG/feature-policy/blob/" "master/features.md#sensor-features"; - auto console_delegate = std::make_unique<ConsoleObserverDelegate>( - shell()->web_contents(), kWarningMessage); - shell()->web_contents()->SetDelegate(console_delegate.get()); + WebContentsConsoleObserver console_observer(shell()->web_contents()); + console_observer.SetPattern(kWarningMessage); EXPECT_TRUE(NavigateToURL(shell(), main_frame_url)); EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "cross_origin_iframe", iframe_url)); - console_delegate->Wait(); - EXPECT_EQ(kWarningMessage, console_delegate->message()); + console_observer.Wait(); + EXPECT_EQ(kWarningMessage, console_observer.GetMessageAt(0u)); } } // namespace
diff --git a/content/browser/download/mhtml_generation_browsertest.cc b/content/browser/download/mhtml_generation_browsertest.cc index 2f66591a..35b8123 100644 --- a/content/browser/download/mhtml_generation_browsertest.cc +++ b/content/browser/download/mhtml_generation_browsertest.cc
@@ -359,18 +359,14 @@ return; // Loads the generated file to check if it is well formed. - WebContentsDelegate* old_delegate = shell()->web_contents()->GetDelegate(); - ConsoleObserverDelegate console_delegate(shell()->web_contents(), - "Malformed multipart archive: *"); - shell()->web_contents()->SetDelegate(&console_delegate); + WebContentsConsoleObserver console_observer(shell()->web_contents()); + console_observer.SetPattern("Malformed multipart archive: *"); EXPECT_TRUE( NavigateToURL(shell(), net::FilePathToFileURL(params.file_path))) << "Error navigating to the generated MHTML file"; - EXPECT_EQ(0U, console_delegate.message().length()) + EXPECT_TRUE(console_observer.messages().empty()) << "The generated MHTML file is malformed"; - - shell()->web_contents()->SetDelegate(old_delegate); } void TwoStepSyncTestFor(const TaskOrder order);
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc index 459e00d..0e28250 100644 --- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -7211,6 +7211,10 @@ GURL start_url(embedded_test_server()->GetURL("a.com", "/title1.html")); EXPECT_TRUE(NavigateToURL(shell(), start_url)); + // The test below only makes sense for same-site same-RFH navigations, so we + // need to ensure that we won't trigger a same-site cross-RFH navigation. + DisableProactiveBrowsingInstanceSwapFor(root->current_frame_host()); + GURL same_document_url( embedded_test_server()->GetURL("a.com", "/title1.html#foo")); EXPECT_TRUE(NavigateToURL(shell(), same_document_url)); @@ -7255,6 +7259,10 @@ GURL start_url(embedded_test_server()->GetURL("a.com", "/title1.html")); EXPECT_TRUE(NavigateToURL(shell(), start_url)); + // The test below only makes sense for same-site same-RFH navigations, so we + // need to ensure that we won't trigger a same-site cross-RFH navigation. + DisableProactiveBrowsingInstanceSwapFor(root->current_frame_host()); + GURL same_document_url( embedded_test_server()->GetURL("a.com", "/title1.html#foo")); EXPECT_TRUE(NavigateToURL(shell(), same_document_url)); @@ -7321,6 +7329,10 @@ EXPECT_EQ(0, web_contents->GetController().GetLastCommittedEntryIndex()); } + // The test below only makes sense for same-site same-RFH navigations, so we + // need to ensure that we won't trigger a same-site cross-RFH navigation. + DisableProactiveBrowsingInstanceSwapFor(root->current_frame_host()); + // 2. Perform a same-document navigation forward. { GURL same_document_url(
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 8309fdc..9b0365f 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1028,9 +1028,6 @@ // the dtor has run. (It may also be null in tests.) unload_event_monitor_timeout_.reset(); - for (auto& iter : visual_state_callbacks_) - std::move(iter.second).Run(false); - // Delete this before destroying the widget, to guard against reentrancy // by in-process screen readers such as JAWS. browser_accessibility_manager_.reset(); @@ -1168,6 +1165,12 @@ MaybeEvictFromBackForwardCache(); } +void RenderFrameHostImpl::DisableProactiveBrowsingInstanceSwapForTesting() { + // This should only be called on main frames. + DCHECK(!GetParent()); + is_proactive_browsing_instance_swap_disabled_for_testing_ = true; +} + void RenderFrameHostImpl::OnGrantedMediaStreamAccess() { was_granted_media_access_ = true; MaybeEvictFromBackForwardCache(); @@ -1633,7 +1636,6 @@ IPC_BEGIN_MESSAGE_MAP(RenderFrameHostImpl, msg) IPC_MESSAGE_HANDLER(FrameHostMsg_Unload_ACK, OnUnloadACK) IPC_MESSAGE_HANDLER(FrameHostMsg_ContextMenu, OnContextMenu) - IPC_MESSAGE_HANDLER(FrameHostMsg_VisualStateResponse, OnVisualStateResponse) IPC_MESSAGE_HANDLER(FrameHostMsg_SelectionChanged, OnSelectionChanged) IPC_END_MESSAGE_MAP() @@ -1842,8 +1844,6 @@ smart_clip_callbacks_.Clear(); #endif // defined(OS_ANDROID) - visual_state_callbacks_.clear(); - // Ensure that future remote interface requests are associated with the new // process's channel. remote_associated_interfaces_.reset(); @@ -3112,16 +3112,6 @@ } #endif // defined(OS_ANDROID) -void RenderFrameHostImpl::OnVisualStateResponse(uint64_t id) { - auto it = visual_state_callbacks_.find(id); - if (it != visual_state_callbacks_.end()) { - std::move(it->second).Run(true); - visual_state_callbacks_.erase(it); - } else { - NOTREACHED() << "Received script response for unknown request"; - } -} - void RenderFrameHostImpl::RunModalAlertDialog( const base::string16& alert_message, RunModalAlertDialogCallback response_callback) { @@ -6634,10 +6624,7 @@ void RenderFrameHostImpl::InsertVisualStateCallback( VisualStateCallback callback) { - static uint64_t next_id = 1; - uint64_t key = next_id++; - Send(new FrameMsg_VisualStateRequest(routing_id_, key)); - visual_state_callbacks_.emplace(key, std::move(callback)); + GetRenderWidgetHost()->InsertVisualStateCallback(std::move(callback)); } bool RenderFrameHostImpl::IsRenderFrameCreated() {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 86af7ca..f34a297 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1138,6 +1138,14 @@ return back_forward_cache_disabled_reasons_; } + // Prevents this frame to do a proactive BrowsingInstance swap (for all + // navigations on this frame - cross-site and same-site). + void DisableProactiveBrowsingInstanceSwapForTesting(); + + bool IsProactiveBrowsingInstanceSwapDisabledForTesting() const { + return is_proactive_browsing_instance_swap_disabled_for_testing_; + } + void AddServiceWorkerContainerHost( const std::string& uuid, base::WeakPtr<ServiceWorkerContainerHost> host); @@ -1879,8 +1887,6 @@ // IPC Message handlers. void OnUnloadACK(); void OnContextMenu(const UntrustworthyContextMenuParams& params); - void OnVisualStateResponse(uint64_t id); - void OnForwardResourceTimingToParent( const ResourceTimingInfo& resource_timing); void OnSelectionChanged(const base::string16& text, @@ -2500,8 +2506,6 @@ // The http status code of the last committed navigation. int last_http_status_code_ = 0; - std::map<uint64_t, VisualStateCallback> visual_state_callbacks_; - // Local root subframes directly own their RenderWidgetHost. // Please see comments about the GetLocalRenderWidgetHost() function. // TODO(kenrb): Later this will also be used on the top-level frame, when @@ -2943,6 +2947,12 @@ // breakdown of NotRestoredReason::kDisableForRenderFrameHostCalled. std::set<std::string> back_forward_cache_disabled_reasons_; + // Whether proactive BrowsingInstance swap is disabled for this frame or not. + // Note that even if this is false, proactive BrowsingInstance swap still + // might not happen on navigations on this frame due to other reasons. + // Should only be used for testing purposes. + bool is_proactive_browsing_instance_swap_disabled_for_testing_ = false; + // This used to re-commit when restoring from the BackForwardCache, with the // same params as the original navigation. // Note: If BackForwardCache is not enabled, this field is not set.
diff --git a/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/content/browser/frame_host/render_frame_host_impl_browsertest.cc index 62fd6a9c..1f7f0bd8 100644 --- a/content/browser/frame_host/render_frame_host_impl_browsertest.cc +++ b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
@@ -26,6 +26,7 @@ #include "content/browser/renderer_host/input/timeout_monitor.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/content_navigation_policy.h" #include "content/common/frame_messages.h" #include "content/public/browser/javascript_dialog_manager.h" #include "content/public/browser/render_frame_host.h" @@ -1304,7 +1305,19 @@ GURL url(embedded_test_server()->GetURL("/title1.html")); EXPECT_TRUE(NavigateToURL(shell(), url)); - // Now make a navigation. + // This test only makes sense for navigations that stay in the same + // RenderFrame, otherwise the document.open() will run on the previous + // page's RenderFrame, and the navigation won't get aborted. We need to + // ensure that we won't trigger a same-site cross-RFH navigation. + // TODO(crbug.com/1099193): This should also work on cross-RFH same-site + // navigations. + DisableProactiveBrowsingInstanceSwapFor( + shell()->web_contents()->GetMainFrame()); + + // Now make a navigation. |observer| will make a document.open() call at + // ReadyToCommit time - see + // NavigationHandleGrabber::SendingNavigationCommitted(). The navigation + // should get aborted because of the document.open() in the navigating RFH. NavigationHandleGrabber observer(shell()->web_contents()); const base::string16 title = base::ASCIIToUTF16("done"); EXPECT_TRUE(ExecuteScript(shell()->web_contents(), @@ -1671,6 +1684,7 @@ IN_PROC_BROWSER_TEST_F( RenderFrameHostImplBrowserTest, EarlyInterfaceRequestsFromNewDocumentDispatchedAfterNavigationFinished) { + WebContents* web_contents = shell()->web_contents(); const GURL first_url(embedded_test_server()->GetURL("/title1.html")); const GURL second_url(embedded_test_server()->GetURL("/title2.html")); @@ -1692,7 +1706,7 @@ // Replace the |interface_broker_receiver| argument in the next // DidCommitProvisionalLoad message coming from the renderer with the // rigged |interface_broker_with_pending_requests| from above. - ScopedFakeInterfaceBrokerRequestInjector injector(shell()->web_contents()); + ScopedFakeInterfaceBrokerRequestInjector injector(web_contents); injector.set_fake_receiver_for_next_commit( std::move(interface_broker_receiver_with_pending_receiver)); @@ -1700,23 +1714,29 @@ // dispatched to the RenderFrameHost, WebContentsObserver::DidFinishNavigation // will have already been invoked. bool did_finish_navigation = false; - auto* main_rfh = shell()->web_contents()->GetMainFrame(); + + // Start the same-process navigation. + TestNavigationManager navigation_manager(web_contents, second_url); + shell()->LoadURL(second_url); + EXPECT_TRUE(navigation_manager.WaitForResponse()); + auto* committing_rfh = + navigation_manager.GetNavigationHandle()->GetRenderFrameHost(); + DidFinishNavigationObserver navigation_finish_observer( - main_rfh, base::BindLambdaForTesting([&did_finish_navigation]() { + committing_rfh, base::BindLambdaForTesting([&did_finish_navigation]() { did_finish_navigation = true; })); base::RunLoop wait_until_interface_request_is_dispatched; ScopedInterfaceRequestMonitor monitor( - main_rfh, mojom::FrameHostTestInterface::Name_, + committing_rfh, mojom::FrameHostTestInterface::Name_, base::BindLambdaForTesting([&]() { EXPECT_TRUE(did_finish_navigation); wait_until_interface_request_is_dispatched.Quit(); })); - // Start the same-process navigation. - ASSERT_TRUE(NavigateToURL(shell(), second_url)); - EXPECT_EQ(main_rfh, shell()->web_contents()->GetMainFrame()); + // Finish the navigation. + navigation_manager.WaitForNavigationFinished(); EXPECT_EQ(second_url, injector.url_of_last_commit()); EXPECT_TRUE(injector.original_receiver_of_last_commit().is_valid()); @@ -1759,6 +1779,11 @@ ASSERT_TRUE(injector.original_receiver_of_last_commit().is_valid()); } + // The test below only works for same-RFH navigations, so we need to ensure + // that we won't trigger a same-site cross-RFH navigation. + DisableProactiveBrowsingInstanceSwapFor( + shell()->web_contents()->GetMainFrame()); + // Prepare an interface receiver for FrameHostTestInterface. mojo::Remote<mojom::FrameHostTestInterface> test_interface; auto test_interface_receiver = test_interface.BindNewPipeAndPassReceiver(); @@ -2317,6 +2342,11 @@ ASSERT_TRUE(NavigateToURL(shell(), kUrl1)); } + // The test below only makes sense for same-RFH navigations, so we need to + // ensure that we won't trigger a same-site cross-RFH navigation. + DisableProactiveBrowsingInstanceSwapFor( + shell()->web_contents()->GetMainFrame()); + { ScopedFakeInterfaceBrokerRequestInjector injector(shell()->web_contents()); injector.set_fake_receiver_for_next_commit( @@ -3998,8 +4028,6 @@ GURL url2(embedded_test_server()->GetURL("/document2")); WebContents* web_contents = shell()->web_contents(); - RenderFrameHostImpl* rfhi = - static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame()); base::RunLoop loop_until_onload; DocumentOnLoadObserver onload_observer(web_contents, @@ -4007,7 +4035,8 @@ shell()->LoadURL(url1); loop_until_onload.Run(); - EXPECT_TRUE(rfhi->IsDOMContentLoaded()); + EXPECT_TRUE(static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame()) + ->IsDOMContentLoaded()); EXPECT_TRUE(web_contents->IsDocumentOnLoadCompletedInMainFrame()); // Expect that the loading state will be reset after a navigation. @@ -4021,8 +4050,8 @@ "Content-Type: text/html; charset=utf-8\r\n" "\r\n"); navigation_observer.WaitForNavigationFinished(); - - EXPECT_FALSE(rfhi->IsDOMContentLoaded()); + EXPECT_FALSE(static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame()) + ->IsDOMContentLoaded()); EXPECT_FALSE(web_contents->IsDocumentOnLoadCompletedInMainFrame()); }
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index c13020a2..2feb42e 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -1292,6 +1292,12 @@ const GURL& destination_url, bool is_reload, bool should_replace_current_entry) { + auto* current_rfhi = + static_cast<RenderFrameHostImpl*>(render_frame_host_.get()); + // If we've disabled proactive BrowsingInstance swap for this RenderFrameHost, + // we should not try to do a proactive swap. + if (current_rfhi->IsProactiveBrowsingInstanceSwapDisabledForTesting()) + return ShouldSwapBrowsingInstance::kNo_ProactiveSwapDisabled; // We should only do proactive swap when either the flag is enabled, or if // it's needed for the back-forward cache (and the bfcache flag is enabled). if (!IsProactivelySwapBrowsingInstanceEnabled() && @@ -1355,11 +1361,10 @@ if (is_reload) return ShouldSwapBrowsingInstance::kNo_Reload; - if (IsCurrentlySameSite( - static_cast<RenderFrameHostImpl*>(render_frame_host_.get()), - destination_url)) { - if (IsProactivelySwapBrowsingInstanceOnSameSiteNavigationEnabled()) + if (IsCurrentlySameSite(current_rfhi, destination_url)) { + if (IsProactivelySwapBrowsingInstanceOnSameSiteNavigationEnabled()) { return ShouldSwapBrowsingInstance::kYes_SameSiteProactiveSwap; + } return ShouldSwapBrowsingInstance::kNo_SameSiteNavigation; }
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc index a6acfe0..bafb295 100644 --- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc +++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -3806,7 +3806,14 @@ GURL url_b_with_frame(embedded_test_server()->GetURL( "b.com", "/navigation_controller/page_with_iframe.html")); EXPECT_TRUE(NavigateToURL(shell(), url_b_with_frame)); - EXPECT_EQ(rfh_b, web_contents->GetMainFrame()); + if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) { + // If same-site ProactivelySwapBrowsingInstance or main-frame RenderDocument + // is enabled, the navigation will result in a new RFH. + EXPECT_NE(rfh_b, web_contents->GetMainFrame()); + rfh_b = web_contents->GetMainFrame(); + } else { + EXPECT_EQ(rfh_b, web_contents->GetMainFrame()); + } EXPECT_EQ(url::Origin::Create(url_b), rfh_b->GetLastCommittedOrigin()); FrameTreeNode* child = root->child_at(0); RenderFrameHostImpl* child_rfh_b = root->child_at(0)->current_frame_host(); @@ -4356,8 +4363,16 @@ scoped_refptr<SiteInstance> error_site_instance = shell()->web_contents()->GetMainFrame()->GetSiteInstance(); EXPECT_NE(success_site_instance, error_site_instance); - EXPECT_TRUE(success_site_instance->IsRelatedSiteInstance( - error_site_instance.get())); + if (CanSameSiteMainFrameNavigationsChangeSiteInstances()) { + // When ProactivelySwapBrowsingInstance is enabled on same-site + // navigations, the navigation above will result in a new + // BrowsingInstance. + EXPECT_FALSE(success_site_instance->IsRelatedSiteInstance( + error_site_instance.get())); + } else { + EXPECT_TRUE(success_site_instance->IsRelatedSiteInstance( + error_site_instance.get())); + } EXPECT_NE(success_site_instance->GetProcess()->GetID(), error_site_instance->GetProcess()->GetID()); EXPECT_EQ(GURL(kUnreachableWebDataURL), error_site_instance->GetSiteURL()); @@ -4392,8 +4407,16 @@ scoped_refptr<SiteInstance> error_site_instance = shell()->web_contents()->GetMainFrame()->GetSiteInstance(); EXPECT_NE(success_site_instance, error_site_instance); - EXPECT_TRUE(success_site_instance->IsRelatedSiteInstance( - error_site_instance.get())); + if (CanSameSiteMainFrameNavigationsChangeSiteInstances()) { + // When ProactivelySwapBrowsingInstance is enabled on same-site + // navigations, the navigation above will result in a new + // BrowsingInstance. + EXPECT_FALSE(success_site_instance->IsRelatedSiteInstance( + error_site_instance.get())); + } else { + EXPECT_TRUE(success_site_instance->IsRelatedSiteInstance( + error_site_instance.get())); + } EXPECT_NE(success_site_instance->GetProcess()->GetID(), error_site_instance->GetProcess()->GetID()); EXPECT_EQ(GURL(kUnreachableWebDataURL), error_site_instance->GetSiteURL());
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc index 7e33ceb5..f56ac8e 100644 --- a/content/browser/navigation_browsertest.cc +++ b/content/browser/navigation_browsertest.cc
@@ -334,11 +334,19 @@ EXPECT_FALSE(observer.last_initiator_routing_id()); } - // The RenderFrameHost should not have changed. - EXPECT_EQ(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents()) - ->GetFrameTree() - ->root() - ->current_frame_host()); + RenderFrameHost* second_rfh = + static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root() + ->current_frame_host(); + + if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) { + // If same-site ProactivelySwapBrowsingInstance or main-frame RenderDocument + // is enabled, the navigation will result in a new RFH. + EXPECT_NE(initial_rfh, second_rfh); + } else { + EXPECT_EQ(initial_rfh, second_rfh); + } // Perform a cross-site navigation. { @@ -352,10 +360,10 @@ } // The RenderFrameHost should have changed. - EXPECT_NE(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents()) - ->GetFrameTree() - ->root() - ->current_frame_host()); + EXPECT_NE(second_rfh, static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root() + ->current_frame_host()); } // Ensure that renderer initiated same-site navigations work. @@ -378,6 +386,9 @@ ->root() ->current_frame_host(); + auto initial_rfh_routing_id = GlobalFrameRoutingId( + initial_rfh->GetProcess()->GetID(), initial_rfh->GetRoutingID()); + // Simulate clicking on a same-site link. { TestNavigationObserver observer(shell()->web_contents()); @@ -394,16 +405,34 @@ RenderFrameHost* main_rfh = shell()->web_contents()->GetMainFrame(); EXPECT_EQ(main_rfh->GetLastCommittedOrigin(), observer.last_initiator_origin()); - EXPECT_EQ(GlobalFrameRoutingId(main_rfh->GetProcess()->GetID(), - main_rfh->GetRoutingID()), - observer.last_initiator_routing_id()); + + if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) { + // If same-site ProactivelySwapBrowsingInstance or main-frame + // RenderDocument is enabled, the navigation will result in a new RFH, so + // we need to compare with |initial_rfh|. + EXPECT_NE(main_rfh, initial_rfh); + EXPECT_EQ(initial_rfh_routing_id, observer.last_initiator_routing_id()); + } else { + EXPECT_EQ(main_rfh, initial_rfh); + EXPECT_EQ(GlobalFrameRoutingId(main_rfh->GetProcess()->GetID(), + main_rfh->GetRoutingID()), + observer.last_initiator_routing_id()); + } } - // The RenderFrameHost should not have changed. - EXPECT_EQ(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents()) - ->GetFrameTree() - ->root() - ->current_frame_host()); + RenderFrameHost* second_rfh = + static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root() + ->current_frame_host(); + + if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) { + // If same-site ProactivelySwapBrowsingInstance or main-frame RenderDocument + // is enabled, the navigation will result in a new RFH. + EXPECT_NE(initial_rfh, second_rfh); + } else { + EXPECT_EQ(initial_rfh, second_rfh); + } } // Ensure that renderer initiated cross-site navigations work.
diff --git a/content/browser/push_messaging/push_messaging_manager.cc b/content/browser/push_messaging/push_messaging_manager.cc index 01f5cdc8..8b851d2 100644 --- a/content/browser/push_messaging/push_messaging_manager.cc +++ b/content/browser/push_messaging/push_messaging_manager.cc
@@ -535,7 +535,7 @@ FROM_HERE, ServiceWorkerContext::GetCoreThreadId(), base::BindOnce(&PushMessagingManager::PersistRegistrationOnSW, sw_parent_, std::move(data), push_subscription_id, - endpoint, p256dh, auth, + endpoint, expiration_time, p256dh, auth, subscription_changed ? blink::mojom::PushRegistrationStatus:: SUCCESS_NEW_SUBSCRIPTION_FROM_PUSH_SERVICE @@ -555,6 +555,7 @@ RegisterData data, const std::string& push_subscription_id, const GURL& endpoint, + const base::Optional<base::Time>& expiration_time, const std::vector<uint8_t>& p256dh, const std::vector<uint8_t>& auth, blink::mojom::PushRegistrationStatus status) { @@ -571,12 +572,13 @@ {kPushSenderIdServiceWorkerKey, application_server_key}}, base::BindOnce(&PushMessagingManager::DidPersistRegistrationOnSW, weak_factory_.GetWeakPtr(), std::move(data), endpoint, - p256dh, auth, status)); + expiration_time, p256dh, auth, status)); } void PushMessagingManager::DidPersistRegistrationOnSW( RegisterData data, const GURL& endpoint, + const base::Optional<base::Time>& expiration_time, const std::vector<uint8_t>& p256dh, const std::vector<uint8_t>& auth, blink::mojom::PushRegistrationStatus push_registration_status, @@ -584,7 +586,7 @@ DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); if (service_worker_status == blink::ServiceWorkerStatusCode::kOk) { SendSubscriptionSuccess(std::move(data), push_registration_status, endpoint, - p256dh, auth); + expiration_time, p256dh, auth); } else { // TODO(johnme): Unregister, so PushMessagingServiceImpl can decrease count. SendSubscriptionError(std::move(data), @@ -604,6 +606,7 @@ RegisterData data, blink::mojom::PushRegistrationStatus status, const GURL& endpoint, + const base::Optional<base::Time>& expiration_time, const std::vector<uint8_t>& p256dh, const std::vector<uint8_t>& auth) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); @@ -619,8 +622,8 @@ std::move(data.callback) .Run(status, blink::mojom::PushSubscription::New( - endpoint, base::nullopt /* expiration_time */, - std::move(data.options), p256dh, auth)); + endpoint, expiration_time, std::move(data.options), + p256dh, auth)); RecordRegistrationStatus(status); }
diff --git a/content/browser/push_messaging/push_messaging_manager.h b/content/browser/push_messaging/push_messaging_manager.h index 5d0ca75d..33cac78c 100644 --- a/content/browser/push_messaging/push_messaging_manager.h +++ b/content/browser/push_messaging/push_messaging_manager.h
@@ -78,16 +78,19 @@ blink::ServiceWorkerStatusCode service_worker_status); // Called via PostTask from UI thread. - void PersistRegistrationOnSW(RegisterData data, - const std::string& push_subscription_id, - const GURL& endpoint, - const std::vector<uint8_t>& p256dh, - const std::vector<uint8_t>& auth, - blink::mojom::PushRegistrationStatus status); + void PersistRegistrationOnSW( + RegisterData data, + const std::string& push_subscription_id, + const GURL& endpoint, + const base::Optional<base::Time>& expiration_time, + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth, + blink::mojom::PushRegistrationStatus status); void DidPersistRegistrationOnSW( RegisterData data, const GURL& endpoint, + const base::Optional<base::Time>& expiration_time, const std::vector<uint8_t>& p256dh, const std::vector<uint8_t>& auth, blink::mojom::PushRegistrationStatus push_registration_status, @@ -97,11 +100,13 @@ void SendSubscriptionError(RegisterData data, blink::mojom::PushRegistrationStatus status); // Called both from "SW core" thread, and via PostTask from UI thread. - void SendSubscriptionSuccess(RegisterData data, - blink::mojom::PushRegistrationStatus status, - const GURL& endpoint, - const std::vector<uint8_t>& p256dh, - const std::vector<uint8_t>& auth); + void SendSubscriptionSuccess( + RegisterData data, + blink::mojom::PushRegistrationStatus status, + const GURL& endpoint, + const base::Optional<base::Time>& expiration_time, + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth); void UnsubscribeHavingGottenSenderId( UnsubscribeCallback callback,
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index de4fd2c..4de45c4 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -95,6 +95,7 @@ #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/ipc/common/gpu_messages.h" +#include "mojo/public/cpp/bindings/callback_helpers.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/system/platform_handle.h" #include "net/base/filename_util.h" @@ -632,6 +633,7 @@ blink_frame_widget_host_receiver_.reset(); blink_frame_widget_.reset(); frame_widget_input_handler_.reset(); + widget_compositor_.reset(); return std::make_pair( blink_frame_widget_host_receiver_.BindNewEndpointAndPassRemote(), blink_frame_widget_.BindNewEndpointAndPassReceiver()); @@ -646,6 +648,7 @@ blink_frame_widget_host_receiver_.reset(); blink_frame_widget_.reset(); frame_widget_input_handler_.reset(); + widget_compositor_.reset(); blink_frame_widget_host_receiver_.Bind(std::move(frame_widget_host)); blink_frame_widget_.Bind(std::move(frame_widget)); } @@ -2894,6 +2897,23 @@ return false; } +void RenderWidgetHostImpl::InsertVisualStateCallback( + VisualStateCallback callback) { + if (!blink_frame_widget_) { + std::move(callback).Run(false); + return; + } + + if (!widget_compositor_) { + blink_frame_widget_->BindWidgetCompositor( + widget_compositor_.BindNewPipeAndPassReceiver()); + } + + widget_compositor_->VisualStateRequest(base::BindOnce( + [](VisualStateCallback callback) { std::move(callback).Run(true); }, + mojo::WrapCallbackWithDefaultInvokeIfNotRun(std::move(callback), false))); +} + const mojo::AssociatedRemote<blink::mojom::FrameWidget>& RenderWidgetHostImpl::GetAssociatedFrameWidget() { return blink_frame_widget_;
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 8236256..ec4696ba 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -16,6 +16,7 @@ #include <vector> #include "base/callback.h" +#include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/containers/queue.h" #include "base/gtest_prod_util.h" @@ -785,6 +786,14 @@ // Add/ClearPendingUserActivation() for details. bool RemovePendingUserActivationIfAvailable(); + // Roundtrips through the renderer and compositor pipeline to ensure that any + // changes to the contents resulting from operations executed prior to this + // call are visible on screen. The call completes asynchronously by running + // the supplied |callback| with a value of true upon successful completion and + // false otherwise when the widget is destroyed. + using VisualStateCallback = base::OnceCallback<void(bool)>; + void InsertVisualStateCallback(VisualStateCallback callback); + const mojo::AssociatedRemote<blink::mojom::FrameWidget>& GetAssociatedFrameWidget(); @@ -1326,6 +1335,8 @@ blink_widget_host_receiver_{this}; mojo::AssociatedRemote<blink::mojom::Widget> blink_widget_; + mojo::Remote<blink::mojom::WidgetCompositor> widget_compositor_; + base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostImpl);
diff --git a/content/browser/service_worker/service_worker_container_host_unittest.cc b/content/browser/service_worker/service_worker_container_host_unittest.cc index 9c7ef4e9..55a738a 100644 --- a/content/browser/service_worker/service_worker_container_host_unittest.cc +++ b/content/browser/service_worker/service_worker_container_host_unittest.cc
@@ -39,7 +39,7 @@ #include "mojo/public/cpp/system/functions.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" #include "url/url_util.h"
diff --git a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h index 7d94972..9d4ed77 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h +++ b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h
@@ -17,7 +17,7 @@ #include "content/public/common/child_process_host.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
diff --git a/content/browser/tracing/tracing_controller_browsertest.cc b/content/browser/tracing/tracing_controller_browsertest.cc index 8ea005f..662da43 100644 --- a/content/browser/tracing/tracing_controller_browsertest.cc +++ b/content/browser/tracing/tracing_controller_browsertest.cc
@@ -352,6 +352,7 @@ #define MAYBE_EnableAndStopTracingWithEmptyFile \ DISABLED_EnableAndStopTracingWithEmptyFile #define MAYBE_DoubleStopTracing DISABLED_DoubleStopTracing +#define MAYBE_ProcessesPresentInTrace DISABLED_ProcessesPresentInTrace #else #define MAYBE_EnableAndStopTracing EnableAndStopTracing #define MAYBE_DisableRecordingStoresMetadata DisableRecordingStoresMetadata @@ -362,6 +363,7 @@ #define MAYBE_EnableAndStopTracingWithEmptyFile \ EnableAndStopTracingWithEmptyFile #define MAYBE_DoubleStopTracing DoubleStopTracing +#define MAYBE_ProcessesPresentInTrace ProcessesPresentInTrace #endif IN_PROC_BROWSER_TEST_F(TracingControllerTest, GetCategories) { @@ -501,10 +503,7 @@ EXPECT_TRUE(last_data().find("systemTraceEvents") != std::string::npos); } -// TODO(crbug.com/1107612): Disabled due to flakiness. Also fails consistently -// on Android Asan (crbug.com/1045519). -IN_PROC_BROWSER_TEST_F(TracingControllerTest, - DISABLED_ProcessesPresentInTrace) { +IN_PROC_BROWSER_TEST_F(TracingControllerTest, MAYBE_ProcessesPresentInTrace) { TestStartAndStopTracingString(); EXPECT_TRUE(last_data().find("CrBrowserMain") != std::string::npos); EXPECT_TRUE(last_data().find("CrRendererMain") != std::string::npos);
diff --git a/content/browser/tracing/tracing_ui.cc b/content/browser/tracing/tracing_ui.cc index 1363a25..3ca7b7f 100644 --- a/content/browser/tracing/tracing_ui.cc +++ b/content/browser/tracing/tracing_ui.cc
@@ -80,10 +80,11 @@ g_tracing_session = perfetto::Tracing::NewTrace().release(); g_tracing_session->Setup(tracing::GetDefaultPerfettoConfig(trace_config)); - auto shared_callback(std::make_shared<WebUIDataSource::GotDataCallback>( - std::move(callback))); + auto shared_callback = base::MakeRefCounted< + base::RefCountedData<WebUIDataSource::GotDataCallback>>( + std::move(callback)); g_tracing_session->SetOnStartCallback([shared_callback] { - OnRecordingEnabledAck(std::move(*shared_callback)); + OnRecordingEnabledAck(std::move(shared_callback->data)); }); g_tracing_session->Start(); return true; @@ -104,8 +105,9 @@ if (g_tracing_session) { // |callback| is move-only, so in order to pass it through a copied lambda // we need to temporarily move it on the heap. - auto shared_callback(std::make_shared<WebUIDataSource::GotDataCallback>( - std::move(callback))); + auto shared_callback = base::MakeRefCounted< + base::RefCountedData<WebUIDataSource::GotDataCallback>>( + std::move(callback)); g_tracing_session->GetTraceStats( [shared_callback]( perfetto::TracingSession::GetTraceStatsCallbackArgs args) { @@ -117,7 +119,7 @@ double percent_full = tracing::GetTraceBufferUsage(trace_stats); usage = base::NumberToString(percent_full); } - std::move(*shared_callback) + std::move(shared_callback->data) .Run(base::RefCountedString::TakeString(&usage)); }); return true;
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index cec3daa..4ddeec0d 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -34,6 +34,7 @@ #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/web_contents/web_contents_view.h" +#include "content/common/content_navigation_policy.h" #include "content/common/frame.mojom-test-utils.h" #include "content/common/frame_messages.h" #include "content/common/page_messages.h" @@ -1230,10 +1231,15 @@ EXPECT_CALL(observer, OnPageScaleFactorChanged(::testing::FloatEq(1.5))); observer.WaitForPageScaleUpdate(); - // Navigate to reset the page scale factor. - shell()->LoadURL(embedded_test_server()->GetURL("/title2.html")); - EXPECT_CALL(observer, OnPageScaleFactorChanged(::testing::_)); - observer.WaitForPageScaleUpdate(); + if (!CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) { + // Navigate to reset the page scale factor. We'll only get the + // OnPageScaleFactorChanged if we reuse the same RenderFrameHost, which will + // not happen if ProactivelySwapBrowsingInstance or RenderDocument is + // enabled for same-site main frame navigations. + shell()->LoadURL(embedded_test_server()->GetURL("/title2.html")); + EXPECT_CALL(observer, OnPageScaleFactorChanged(::testing::_)); + observer.WaitForPageScaleUpdate(); + } } // Test that a direct navigation to a view-source URL works.
diff --git a/content/browser/web_contents/web_contents_observer_browsertest.cc b/content/browser/web_contents/web_contents_observer_browsertest.cc index 44078c4..cf382d66 100644 --- a/content/browser/web_contents/web_contents_observer_browsertest.cc +++ b/content/browser/web_contents/web_contents_observer_browsertest.cc
@@ -14,6 +14,7 @@ #include "content/public/common/content_features.h" #include "content/public/test/browser_test.h" #include "content/public/test/content_browser_test.h" +#include "content/public/test/test_utils.h" #include "content/shell/browser/shell.h" #include "content/test/test_content_browser_client.h" #include "net/dns/mock_host_resolver.h" @@ -558,21 +559,25 @@ // 2) Load a page with subresource. Both the page and the resource should get // a cookie. EXPECT_TRUE(NavigateToURL(web_contents(), url2)); - + // If the RFH changes after navigation, the cookie will be attributed to a + // different frame. + int frame_id_index = + CanSameSiteMainFrameNavigationsChangeRenderFrameHosts() ? 1 : 0; cookie_tracker.WaitForCookies(2); - EXPECT_THAT(cookie_tracker.cookie_accesses(), - testing::ElementsAre( - CookieAccess{CookieAccessDetails::Type::kRead, - ContextType::kNavigation, - {}, - cookie_tracker.navigation_id(1), - url2, - first_party_url, - "foo", - "bar"}, - CookieAccess{CookieAccessDetails::Type::kRead, - ContextType::kFrame, cookie_tracker.frame_id(0), - -1, url2_image, first_party_url, "foo", "bar"})); + EXPECT_THAT( + cookie_tracker.cookie_accesses(), + testing::ElementsAre( + CookieAccess{CookieAccessDetails::Type::kRead, + ContextType::kNavigation, + {}, + cookie_tracker.navigation_id(1), + url2, + first_party_url, + "foo", + "bar"}, + CookieAccess{CookieAccessDetails::Type::kRead, ContextType::kFrame, + cookie_tracker.frame_id(frame_id_index), -1, url2_image, + first_party_url, "foo", "bar"})); cookie_tracker.cookie_accesses().clear(); }
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc index 153192c..f7039bd 100644 --- a/content/browser/worker_host/dedicated_worker_host.cc +++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -31,7 +31,7 @@ #include "mojo/public/cpp/system/message_pipe.h" #include "net/base/isolation_info.h" #include "third_party/blink/public/common/features.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom.h" namespace content {
diff --git a/content/browser/worker_host/dedicated_worker_host.h b/content/browser/worker_host/dedicated_worker_host.h index 62031989..fb5e88f 100644 --- a/content/browser/worker_host/dedicated_worker_host.h +++ b/content/browser/worker_host/dedicated_worker_host.h
@@ -19,7 +19,7 @@ #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/network/public/cpp/cross_origin_embedder_policy.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/idle/idle_manager.mojom-forward.h" #include "third_party/blink/public/mojom/loader/content_security_notifier.mojom.h" #include "third_party/blink/public/mojom/sms/sms_receiver.mojom-forward.h"
diff --git a/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc b/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc index 17c8e64..f96f57aa 100644 --- a/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc +++ b/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc
@@ -20,8 +20,8 @@ #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "third_party/blink/public/common/features.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" -#include "third_party/blink/public/common/tokens/worker_tokens_mojom_traits.h" +#include "third_party/blink/public/common/tokens/tokens.h" +#include "third_party/blink/public/common/tokens/tokens_mojom_traits.h" #include "third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom.h" #include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h"
diff --git a/content/browser/worker_host/shared_worker_host.h b/content/browser/worker_host/shared_worker_host.h index d524c95..b7e5464 100644 --- a/content/browser/worker_host/shared_worker_host.h +++ b/content/browser/worker_host/shared_worker_host.h
@@ -29,7 +29,7 @@ #include "mojo/public/cpp/bindings/remote.h" #include "services/metrics/public/cpp/ukm_source_id.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/appcache/appcache.mojom.h" #include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" #include "third_party/blink/public/mojom/payments/payment_app.mojom-forward.h"
diff --git a/content/browser/worker_host/shared_worker_service_impl.h b/content/browser/worker_host/shared_worker_service_impl.h index 634a906..0d517bc 100644 --- a/content/browser/worker_host/shared_worker_service_impl.h +++ b/content/browser/worker_host/shared_worker_service_impl.h
@@ -22,7 +22,7 @@ #include "services/metrics/public/cpp/ukm_source_id.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/network/public/mojom/url_response_head.mojom.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom.h" #include "third_party/blink/public/mojom/worker/shared_worker_connector.mojom.h" #include "third_party/blink/public/mojom/worker/shared_worker_factory.mojom.h"
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.h b/content/browser/worker_host/worker_script_fetch_initiator.h index 5b51a8e..712f2ff 100644 --- a/content/browser/worker_host/worker_script_fetch_initiator.h +++ b/content/browser/worker_host/worker_script_fetch_initiator.h
@@ -18,7 +18,7 @@ #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/network/public/mojom/url_response_head.mojom.h" #include "third_party/blink/public/common/loader/url_loader_throttle.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom.h" #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" #include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
diff --git a/content/browser/worker_host/worker_script_loader.h b/content/browser/worker_host/worker_script_loader.h index 44ff24ea..257d3ba 100644 --- a/content/browser/worker_host/worker_script_loader.h +++ b/content/browser/worker_host/worker_script_loader.h
@@ -22,7 +22,7 @@ #include "net/url_request/url_request.h" #include "services/network/public/cpp/resource_request.h" #include "services/network/public/mojom/url_loader.mojom.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" namespace blink { class ThrottlingURLLoader;
diff --git a/content/browser/worker_host/worker_script_loader_factory.h b/content/browser/worker_host/worker_script_loader_factory.h index 9c4de27..9347730 100644 --- a/content/browser/worker_host/worker_script_loader_factory.h +++ b/content/browser/worker_host/worker_script_loader_factory.h
@@ -11,7 +11,7 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" namespace network { class SharedURLLoaderFactory;
diff --git a/content/browser/worker_host/worker_script_loader_factory_unittest.cc b/content/browser/worker_host/worker_script_loader_factory_unittest.cc index d1e5bd6..0ac1f5a 100644 --- a/content/browser/worker_host/worker_script_loader_factory_unittest.cc +++ b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
@@ -19,7 +19,7 @@ #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_client.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" namespace content {
diff --git a/content/common/frame.mojom b/content/common/frame.mojom index 613f026..b2102804 100644 --- a/content/common/frame.mojom +++ b/content/common/frame.mojom
@@ -42,7 +42,7 @@ import "third_party/blink/public/mojom/loader/referrer.mojom"; import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom"; import "third_party/blink/public/mojom/service_worker/service_worker_container.mojom"; -import "third_party/blink/public/mojom/tokens/portal_token.mojom"; +import "third_party/blink/public/mojom/tokens/tokens.mojom"; import "third_party/blink/public/mojom/widget/visual_properties.mojom"; import "third_party/blink/public/mojom/window_features/window_features.mojom"; import "ui/accessibility/mojom/ax_tree_update.mojom";
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 0973d39..eea8b6a 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -426,10 +426,6 @@ content::CustomContextMenuContext /* custom_context */, unsigned /* action */) -// Requests that the RenderFrame send back a response after waiting for the -// commit, activation and frame swap of the current DOM tree in blink. -IPC_MESSAGE_ROUTED1(FrameMsg_VisualStateRequest, uint64_t /* id */) - #if BUILDFLAG(ENABLE_PLUGINS) // Notifies the renderer of updates to the Plugin Power Saver origin allowlist. IPC_MESSAGE_ROUTED1(FrameMsg_UpdatePluginContentOriginAllowlist, @@ -634,10 +630,6 @@ uint32_t /* the offset of the text in the document */, gfx::Range /* selection range in the document */) -// Sent as a response to FrameMsg_VisualStateRequest. -// The message is delivered using RenderWidget::QueueMessage. -IPC_MESSAGE_ROUTED1(FrameHostMsg_VisualStateResponse, uint64_t /* id */) - // Adding a new message? Stick to the sort order above: first platform // independent FrameMsg, then ifdefs for platform specific FrameMsg, then // platform independent FrameHostMsg, then ifdefs for platform specific
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionProxyView.java b/content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionProxyView.java index aa3f6f9..2c28bdb 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionProxyView.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionProxyView.java
@@ -22,7 +22,7 @@ * This is a fake View that is only exposed to InputMethodManager. */ public class ThreadedInputConnectionProxyView extends View { - private static final String TAG = "Ime"; + private static final String TAG = "ImeProxyView"; private static final boolean DEBUG_LOGS = false; private final Handler mImeThreadHandler; @@ -55,6 +55,7 @@ } public void onOriginalViewWindowFocusChanged(boolean gainFocus) { + if (DEBUG_LOGS) Log.w(TAG, "onOriginalViewWindowFocusChanged: " + gainFocus); mWindowFocused.set(gainFocus); } @@ -100,17 +101,19 @@ @Override public boolean hasWindowFocus() { - if (DEBUG_LOGS) Log.w(TAG, "hasWindowFocus"); - return mWindowFocused.get(); + boolean focused = mWindowFocused.get(); + if (DEBUG_LOGS) Log.w(TAG, "hasWindowFocus: " + focused); + return focused; } @Override public View getRootView() { - if (DEBUG_LOGS) Log.w(TAG, "getRootView"); // Returning a null here matches mCurRootView being null value in InputMethodManager, // which represents that the current focused window is not IME target window. // In this case, you are still able to type. - return mWindowFocused.get() ? mRootView.get() : null; + View rootView = mWindowFocused.get() ? mRootView.get() : null; + if (DEBUG_LOGS) Log.w(TAG, "getRootView: " + rootView); + return rootView; } @Override @@ -122,8 +125,9 @@ @Override public boolean isFocused() { - if (DEBUG_LOGS) Log.w(TAG, "isFocused"); - return mFocused.get(); + boolean focused = mFocused.get(); + if (DEBUG_LOGS) Log.w(TAG, "isFocused: " + focused); + return focused; } @Override
diff --git a/content/public/browser/dedicated_worker_service.h b/content/public/browser/dedicated_worker_service.h index 6bc6a34..de8bec1 100644 --- a/content/public/browser/dedicated_worker_service.h +++ b/content/public/browser/dedicated_worker_service.h
@@ -8,7 +8,7 @@ #include "base/observer_list_types.h" #include "content/common/content_export.h" #include "content/public/browser/global_routing_id.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" class GURL;
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h index f285e96..eb08034 100644 --- a/content/public/browser/render_frame_host.h +++ b/content/public/browser/render_frame_host.h
@@ -305,7 +305,7 @@ // changes to the contents resulting from operations executed prior to this // call are visible on screen. The call completes asynchronously by running // the supplied |callback| with a value of true upon successful completion and - // false otherwise (when the frame is destroyed, detached, etc..). + // false otherwise when the widget is destroyed. using VisualStateCallback = base::OnceCallback<void(bool)>; virtual void InsertVisualStateCallback(VisualStateCallback callback) = 0;
diff --git a/content/public/browser/service_worker_client_info.h b/content/public/browser/service_worker_client_info.h index 5998925..217f2f2d 100644 --- a/content/public/browser/service_worker_client_info.h +++ b/content/public/browser/service_worker_client_info.h
@@ -7,7 +7,7 @@ #include "content/common/content_export.h" #include "content/public/browser/render_frame_host.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h" namespace content {
diff --git a/content/public/browser/shared_worker_service.h b/content/public/browser/shared_worker_service.h index 688e73b..277c156 100644 --- a/content/public/browser/shared_worker_service.h +++ b/content/public/browser/shared_worker_service.h
@@ -10,7 +10,7 @@ #include "base/observer_list_types.h" #include "content/common/content_export.h" #include "content/public/browser/global_routing_id.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" class GURL;
diff --git a/content/public/test/fake_frame_widget.h b/content/public/test/fake_frame_widget.h index c52cc1ac..369d8fac 100644 --- a/content/public/test/fake_frame_widget.h +++ b/content/public/test/fake_frame_widget.h
@@ -63,6 +63,9 @@ void EnableDeviceEmulation( const blink::DeviceEmulationParams& parameters) override {} void DisableDeviceEmulation() override {} + void BindWidgetCompositor( + mojo::PendingReceiver<blink::mojom::WidgetCompositor> receiver) override { + } mojo::AssociatedReceiver<blink::mojom::FrameWidget> receiver_; base::i18n::TextDirection text_direction_ =
diff --git a/content/public/test/test_utils.cc b/content/public/test/test_utils.cc index d0e3f75..9614ae9 100644 --- a/content/public/test/test_utils.cc +++ b/content/public/test/test_utils.cc
@@ -220,6 +220,17 @@ return IsProactivelySwapBrowsingInstanceOnSameSiteNavigationEnabled(); } +void DisableProactiveBrowsingInstanceSwapFor(RenderFrameHost* rfh) { + if (!CanSameSiteMainFrameNavigationsChangeSiteInstances()) + return; + // If the RFH is not a main frame, navigations on it will never result in a + // proactive BrowsingInstance swap, so we shouldn't really call it on main + // frames. + DCHECK(!rfh->GetParent()); + static_cast<RenderFrameHostImpl*>(rfh) + ->DisableProactiveBrowsingInstanceSwapForTesting(); +} + GURL GetWebUIURL(const std::string& host) { return GURL(GetWebUIURLString(host)); }
diff --git a/content/public/test/test_utils.h b/content/public/test/test_utils.h index f92c22d..44f2913 100644 --- a/content/public/test/test_utils.h +++ b/content/public/test/test_utils.h
@@ -112,6 +112,11 @@ // above, this will not be true when RenderDocument for main-frame is enabled. bool CanSameSiteMainFrameNavigationsChangeSiteInstances(); +// Makes sure that navigations that start in |rfh| won't result in a proactive +// BrowsingInstance swap (note they might still result in a normal +// BrowsingInstance swap, e.g. in the case of cross-site navigations). +void DisableProactiveBrowsingInstanceSwapFor(RenderFrameHost* rfh); + // Returns a GURL constructed from the WebUI scheme and the given host. GURL GetWebUIURL(const std::string& host);
diff --git a/content/public/test/web_contents_tester.h b/content/public/test/web_contents_tester.h index 92e9030..ef19451e 100644 --- a/content/public/test/web_contents_tester.h +++ b/content/public/test/web_contents_tester.h
@@ -12,7 +12,7 @@ #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" #include "third_party/blink/public/common/input/web_input_event.h" -#include "third_party/blink/public/common/tokens/portal_token.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom.h" #include "ui/base/page_transition_types.h"
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index cc5f3bb7..6a515a15 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -2236,8 +2236,6 @@ #if BUILDFLAG(ENABLE_PLUGINS) IPC_MESSAGE_HANDLER(FrameMsg_SetPepperVolume, OnSetPepperVolume) #endif - IPC_MESSAGE_HANDLER(FrameMsg_VisualStateRequest, - OnVisualStateRequest) IPC_MESSAGE_HANDLER(FrameMsg_MixedContentFound, OnMixedContentFound) IPC_MESSAGE_HANDLER(UnfreezableFrameMsg_Delete, OnDeleteFrame) IPC_END_MESSAGE_MAP() @@ -2631,11 +2629,6 @@ return base::Value(); } -void RenderFrameImpl::OnVisualStateRequest(uint64_t id) { - GetLocalRootRenderWidget()->QueueMessage( - std::make_unique<FrameHostMsg_VisualStateResponse>(routing_id_, id)); -} - void RenderFrameImpl::OnPortalActivated( const blink::PortalToken& portal_token, mojo::PendingAssociatedRemote<blink::mojom::Portal> portal,
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 8bd0812e..270adb5c 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -1004,7 +1004,6 @@ void OnMoveCaret(const gfx::Point& point); void OnScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect); void OnSelectRange(const gfx::Point& base, const gfx::Point& extent); - void OnVisualStateRequest(uint64_t key); void OnSuppressFurtherDialogs(); void OnMixedContentFound(const FrameMsg_MixedContentFound_Params& params);
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index aa7b701a..31e8817 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -464,21 +464,6 @@ void RenderWidget::UpdateVisualProperties( const blink::VisualProperties& visual_properties) { - // Inform the rendering thread of the color space indicating the presence of - // HDR capabilities. The HDR bit happens to be globally true/false for all - // browser windows (on Windows OS) and thus would be the same for all - // RenderWidgets, so clobbering each other works out since only the HDR bit is - // used. See https://crbug.com/803451 and - // https://chromium-review.googlesource.com/c/chromium/src/+/852912/15#message-68bbd3e25c3b421a79cd028b2533629527d21fee - // - // The RenderThreadImpl can be null in tests. - { - RenderThreadImpl* render_thread = RenderThreadImpl::current(); - if (render_thread) - render_thread->SetRenderingColorSpace( - visual_properties.screen_info.color_space); - } - if (delegate()) { if (size_ != visual_properties.new_size) { // Only hide popups when the size changes. Eg https://crbug.com/761908.
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 47a9dac..c5cf22d0 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -904,6 +904,15 @@ return render_thread->GetGpuFactories(); } +void RendererBlinkPlatformImpl::SetRenderingColorSpace( + const gfx::ColorSpace& color_space) { + auto* render_thread = RenderThreadImpl::current(); + if (!render_thread) + return; + + render_thread->SetRenderingColorSpace(color_space); +} + //------------------------------------------------------------------------------ blink::mojom::CodeCacheHost& RendererBlinkPlatformImpl::GetCodeCacheHost() {
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index f48c402..762195e 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h
@@ -208,6 +208,7 @@ scoped_refptr<network::SharedURLLoaderFactory> factory) override; media::GpuVideoAcceleratorFactories* GetGpuFactories() override; + void SetRenderingColorSpace(const gfx::ColorSpace& color_space) override; // Tells this platform that the renderer is locked to a site (i.e., a scheme // plus eTLD+1, such as https://google.com), or to a more specific origin.
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.cc b/content/renderer/worker/dedicated_worker_host_factory_client.cc index 236fd72f..98506b7 100644 --- a/content/renderer/worker/dedicated_worker_host_factory_client.cc +++ b/content/renderer/worker/dedicated_worker_host_factory_client.cc
@@ -16,13 +16,13 @@ #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/loader/feature_utils.h" #include "third_party/blink/public/common/loader/worker_main_script_load_parameters.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" -#include "third_party/blink/public/common/tokens/worker_tokens_mojom_traits.h" +#include "third_party/blink/public/common/tokens/tokens.h" +#include "third_party/blink/public/common/tokens/tokens_mojom_traits.h" #include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h" #include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom.h" #include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h" -#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h" +#include "third_party/blink/public/mojom/tokens/tokens.mojom.h" #include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h" #include "third_party/blink/public/platform/web_dedicated_worker.h" #include "third_party/blink/public/platform/web_url.h"
diff --git a/content/renderer/worker/embedded_shared_worker_stub.h b/content/renderer/worker/embedded_shared_worker_stub.h index 791c20a1..7ba6c8e 100644 --- a/content/renderer/worker/embedded_shared_worker_stub.h +++ b/content/renderer/worker/embedded_shared_worker_stub.h
@@ -17,7 +17,7 @@ #include "mojo/public/cpp/bindings/remote.h" #include "services/metrics/public/cpp/ukm_source_id.h" #include "services/network/public/mojom/url_loader_factory.mojom-forward.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/common/user_agent/user_agent_metadata.h" #include "third_party/blink/public/mojom/browser_interface_broker.mojom-forward.h" #include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-forward.h"
diff --git a/content/shell/browser/web_test/web_test_push_messaging_service.cc b/content/shell/browser/web_test/web_test_push_messaging_service.cc index 401fb327..ff59a236 100644 --- a/content/shell/browser/web_test/web_test_push_messaging_service.cc +++ b/content/shell/browser/web_test/web_test_push_messaging_service.cc
@@ -40,8 +40,11 @@ static_assert(sizeof(kAuthentication) == 12, "The fake authentication key must be at least 12 bytes in size."); +const int64_t kTestExpirationWindowInDays = 90; + base::Time GetFutureTime() { - return base::Time::Now() + base::TimeDelta::FromDays(100); + return base::Time::Now() + + base::TimeDelta::FromDays(kTestExpirationWindowInDays); } } // anonymous namespace
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 3ce8bc7..079e2b5 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -379,6 +379,10 @@ crbug.com/1010942 [ win amd vulkan passthrough ] conformance/glsl/samplers/glsl-function-texture2dproj.html [ Failure ] crbug.com/angleproject/4286 [ win amd vulkan passthrough ] conformance/rendering/out-of-bounds-array-buffers.html [ Failure ] +# Vulkan / Win10 / Intel / Passthrough +# Flaking since an identified Angle roll. +crbug.com/1111652 [ win10 intel vulkan passthrough ] conformance/context/context-size-change.html [ RetryOnFailure ] + #################### # Mac failures # ####################
diff --git a/docs/README.md b/docs/README.md index 2c89081..90753e4 100644 --- a/docs/README.md +++ b/docs/README.md
@@ -110,6 +110,7 @@ * [Code Reviews](code_reviews.md) - Code review requirements and guidelines * [Respectful Code Reviews](cr_respect.md) - A guide for code reviewers * [Respectful Changes](cl_respect.md) - A guide for code authors +* [Mandatory Code-Review Rollout](code_review_owners.md) - Upcoming policy changes related to code review and OWNERS * [LUCI Migration FAQ](luci_migration_faq.md) - FAQ on Buildbot-to-LUCI builder migration for Chromium * [Tour of Continuous Integration UI](tour_of_luci_ui.md) - A tour of our
diff --git a/docs/code_review_owners.md b/docs/code_review_owners.md new file mode 100644 index 0000000..ed0cf25 --- /dev/null +++ b/docs/code_review_owners.md
@@ -0,0 +1,15 @@ +# Mandatory Code-Review and OWNERS + +Beginning in Q1 2021, committers@ of Chromium will no longer be able +to circumvent code review and OWNERS approval on CLs. + +Currently, these are circumventable by self-code-review and because the +enforcement is done by presumit, although rarely done by external +contributors. In Q1, Gerrit will disallow both bypasses. As part of the +transition, an audit service will automatically file bugs for CLs that +land with only self-approval, launching in Q4 2020. Within Google, where +these bypasses are more common, Googlers can find Google-specific +information in the internal announcements and landing site. + +Periodic updates and FAQs will be sent to chromium-dev@chromium.org +and updated on this page. \ No newline at end of file
diff --git a/docs/code_reviews.md b/docs/code_reviews.md index 0c6df1b..a42add2 100644 --- a/docs/code_reviews.md +++ b/docs/code_reviews.md
@@ -4,7 +4,9 @@ All changes must be reviewed. The general patch, upload, and land process is covered in more detail in the -[contributing code](contributing.md) page. +[contributing code](contributing.md) page. To learn about upcoming code review +and OWNERS policy changes, see +[Mandatory code review and OWNERS](code_review_owners.md). # Code review policies
diff --git a/extensions/browser/updater/extension_downloader_delegate.h b/extensions/browser/updater/extension_downloader_delegate.h index bf0380a8..0f18403 100644 --- a/extensions/browser/updater/extension_downloader_delegate.h +++ b/extensions/browser/updater/extension_downloader_delegate.h
@@ -63,7 +63,10 @@ // DOWNLOADING_CRX_RETRY -> DOWNLOADING_CRX -> FINISHED. // Note: enum used for UMA. Do NOT reorder or remove entries. Don't forget to // update enums.xml (name: ExtensionInstallationDownloadingStage) when adding - // new entries. + // new entries. Don't forget to update device_management_backend.proto (name: + // ExtensionInstallReportLogEvent::DownloadingStage) when adding new entries. + // Don't forget to update ConvertDownloadingStageToProto method in + // ExtensionInstallEventLogCollector. enum class Stage { // Downloader just received extension download request. PENDING = 0,
diff --git a/gpu/command_buffer/service/external_semaphore.cc b/gpu/command_buffer/service/external_semaphore.cc index f691221..8bfe986 100644 --- a/gpu/command_buffer/service/external_semaphore.cc +++ b/gpu/command_buffer/service/external_semaphore.cc
@@ -199,10 +199,4 @@ return semaphore_; } -VkSemaphore ExternalSemaphore::TakeVkSemaphore() { - VkSemaphore semaphore = GetVkSemaphore(); - semaphore_ = VK_NULL_HANDLE; - return semaphore; -} - } // namespace gpu
diff --git a/gpu/command_buffer/service/external_semaphore.h b/gpu/command_buffer/service/external_semaphore.h index df4e6d5..723da3ac 100644 --- a/gpu/command_buffer/service/external_semaphore.h +++ b/gpu/command_buffer/service/external_semaphore.h
@@ -45,10 +45,6 @@ // Get a VkSemaphore. The ownership is not transferred to caller. VkSemaphore GetVkSemaphore(); - // Take the VkSemaphore. The ownership is transferred to caller. The caller is - // responsible for releasing it. - VkSemaphore TakeVkSemaphore(); - bool is_valid() const { return context_provider_ && handle_.is_valid(); } SemaphoreHandle handle() { return handle_.Duplicate(); }
diff --git a/gpu/command_buffer/service/external_vk_image_skia_representation.cc b/gpu/command_buffer/service/external_vk_image_skia_representation.cc index f5df3ca..5a88fd6 100644 --- a/gpu/command_buffer/service/external_vk_image_skia_representation.cc +++ b/gpu/command_buffer/service/external_vk_image_skia_representation.cc
@@ -157,7 +157,7 @@ for (auto& external_semaphore : begin_access_semaphores_) { DCHECK(external_semaphore); - VkSemaphore semaphore = external_semaphore.TakeVkSemaphore(); + VkSemaphore semaphore = external_semaphore.GetVkSemaphore(); DCHECK(semaphore != VK_NULL_HANDLE); // The ownership of semaphore is passed to caller. begin_semaphores->emplace_back();
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc index 934f5ce..6c00779a 100644 --- a/gpu/command_buffer/service/raster_decoder.cc +++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -260,7 +260,8 @@ if (!begin_semaphores.empty()) { bool result = output_surface_->wait(begin_semaphores.size(), - begin_semaphores.data()); + begin_semaphores.data(), + /*deleteSemaphoresAfterWait=*/false); DCHECK(result); } @@ -2299,8 +2300,9 @@ &begin_semaphores, &end_semaphores); if (!begin_semaphores.empty()) { - bool result = dest_scoped_access->surface()->wait(begin_semaphores.size(), - begin_semaphores.data()); + bool result = dest_scoped_access->surface()->wait( + begin_semaphores.size(), begin_semaphores.data(), + /*deleteSemaphoresAfterWait=*/false); DCHECK(result); } @@ -2422,8 +2424,9 @@ } if (!begin_semaphores.empty()) { - bool result = dest_scoped_access->surface()->wait(begin_semaphores.size(), - begin_semaphores.data()); + bool result = dest_scoped_access->surface()->wait( + begin_semaphores.size(), begin_semaphores.data(), + /*deleteSemaphoresAfterWait=*/false); if (!result) { LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glWritePixels", "Unable to obtain write access to dest shared image."); @@ -2529,7 +2532,8 @@ if (!begin_semaphores.empty()) { bool result = shared_context_state_->gr_context()->wait( - begin_semaphores.size(), begin_semaphores.data()); + begin_semaphores.size(), begin_semaphores.data(), + /*deleteSemaphoresAfterWait=*/false); DCHECK(result); } @@ -2694,7 +2698,8 @@ auto* dest_surface = dest_scoped_access->surface(); if (!begin_semaphores.empty()) { bool result = - dest_surface->wait(begin_semaphores.size(), begin_semaphores.data()); + dest_surface->wait(begin_semaphores.size(), begin_semaphores.data(), + /*deleteSemaphoresAfterWait=*/false); DCHECK(result); } @@ -2890,7 +2895,8 @@ if (!begin_semaphores.empty()) { bool result = - sk_surface_->wait(begin_semaphores.size(), begin_semaphores.data()); + sk_surface_->wait(begin_semaphores.size(), begin_semaphores.data(), + /*deleteSemaphoresAfterWait=*/false); DCHECK(result); }
diff --git a/gpu/command_buffer/service/shared_image_representation.h b/gpu/command_buffer/service/shared_image_representation.h index b52622d..c309b90 100644 --- a/gpu/command_buffer/service/shared_image_representation.h +++ b/gpu/command_buffer/service/shared_image_representation.h
@@ -296,7 +296,7 @@ protected: // Begin the write access. The implementations should insert semaphores into // begin_semaphores vector which client will wait on before writing the - // backing. The ownership of begin_semaphores will be passed to client. + // backing. The ownership of begin_semaphores is not passed to client. // The implementations can also optionally insert semaphores into // end_semaphores. If using end_semaphores, the client must submit them with // drawing operations which use the backing. The ownership of end_semaphores @@ -319,7 +319,7 @@ // Begin the read access. The implementations should insert semaphores into // begin_semaphores vector which client will wait on before reading the - // backing. The ownership of begin_semaphores will be passed to client. + // backing. The ownership of begin_semaphores is not passed to client. // The implementations can also optionally insert semaphores into // end_semaphores. If using end_semaphores, the client must submit them with // drawing operations which use the backing. The ownership of end_semaphores
diff --git a/gpu/command_buffer/service/shared_image_representation_skia_vk_android.cc b/gpu/command_buffer/service/shared_image_representation_skia_vk_android.cc index 35d8bc9..0858d324 100644 --- a/gpu/command_buffer/service/shared_image_representation_skia_vk_android.cc +++ b/gpu/command_buffer/service/shared_image_representation_skia_vk_android.cc
@@ -169,13 +169,13 @@ } sync_fd = gl::MergeFDs(std::move(sync_fd), std::move(init_read_fence)); - VkSemaphore begin_access_semaphore = VK_NULL_HANDLE; + DCHECK(begin_access_semaphore_ == VK_NULL_HANDLE); if (sync_fd.is_valid()) { - begin_access_semaphore = vk_implementation()->ImportSemaphoreHandle( + begin_access_semaphore_ = vk_implementation()->ImportSemaphoreHandle( vk_device(), SemaphoreHandle(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, std::move(sync_fd))); - if (begin_access_semaphore == VK_NULL_HANDLE) { + if (begin_access_semaphore_ == VK_NULL_HANDLE) { DLOG(ERROR) << "Failed to import semaphore from sync_fd."; return false; } @@ -187,17 +187,18 @@ if (end_access_semaphore_ == VK_NULL_HANDLE) { DLOG(ERROR) << "Failed to create the external semaphore."; - if (begin_access_semaphore != VK_NULL_HANDLE) { - vkDestroySemaphore(vk_device(), begin_access_semaphore, + if (begin_access_semaphore_ != VK_NULL_HANDLE) { + vkDestroySemaphore(vk_device(), begin_access_semaphore_, nullptr /* pAllocator */); + begin_access_semaphore_ = VK_NULL_HANDLE; } return false; } } - if (begin_access_semaphore != VK_NULL_HANDLE) { + if (begin_access_semaphore_ != VK_NULL_HANDLE) { begin_semaphores->emplace_back(); - begin_semaphores->back().initVulkan(begin_access_semaphore); + begin_semaphores->back().initVulkan(begin_access_semaphore_); } if (end_semaphores) { end_semaphores->emplace_back(); @@ -224,14 +225,24 @@ android_backing()->EndWrite(std::move(sync_fd)); } + std::vector<VkSemaphore> semaphores; + semaphores.reserve(2); + if (begin_access_semaphore_ != VK_NULL_HANDLE) { + semaphores.emplace_back(begin_access_semaphore_); + begin_access_semaphore_ = VK_NULL_HANDLE; + } if (end_access_semaphore_ != VK_NULL_HANDLE) { + semaphores.emplace_back(end_access_semaphore_); + end_access_semaphore_ = VK_NULL_HANDLE; + } + if (!semaphores.empty()) { VulkanFenceHelper* fence_helper = context_state_->vk_context_provider() ->GetDeviceQueue() ->GetFenceHelper(); - fence_helper->EnqueueSemaphoreCleanupForSubmittedWork( - end_access_semaphore_); - end_access_semaphore_ = VK_NULL_HANDLE; + fence_helper->EnqueueSemaphoresCleanupForSubmittedWork( + std::move(semaphores)); } + mode_ = RepresentationAccessMode::kNone; }
diff --git a/gpu/command_buffer/service/shared_image_representation_skia_vk_android.h b/gpu/command_buffer/service/shared_image_representation_skia_vk_android.h index 0c4f35f9..d2f1c64 100644 --- a/gpu/command_buffer/service/shared_image_representation_skia_vk_android.h +++ b/gpu/command_buffer/service/shared_image_representation_skia_vk_android.h
@@ -70,6 +70,7 @@ int surface_msaa_count_ = 0; sk_sp<SkSurface> surface_; scoped_refptr<SharedContextState> context_state_; + VkSemaphore begin_access_semaphore_ = VK_NULL_HANDLE; VkSemaphore end_access_semaphore_ = VK_NULL_HANDLE; };
diff --git a/infra/scripts/build_directory.py b/infra/scripts/build_directory.py index 23847be..e50ec4a0 100644 --- a/infra/scripts/build_directory.py +++ b/infra/scripts/build_directory.py
@@ -52,7 +52,7 @@ assert not cros_board, "'cros_board' not supported on this platform" if sys.platform == 'cygwin' or sys.platform.startswith('win') or ( - sys.platorm == 'darwin'): + sys.platform == 'darwin'): return os.path.join(src_dir, 'out') raise NotImplementedError('Unexpected platform %s' % sys.platform)
diff --git a/ios/chrome/app/app_startup_parameters.h b/ios/chrome/app/app_startup_parameters.h index edbf9505..dc56835 100644 --- a/ios/chrome/app/app_startup_parameters.h +++ b/ios/chrome/app/app_startup_parameters.h
@@ -36,6 +36,10 @@ // |externalURL|. @property(nonatomic, readonly, assign) const GURL& completeURL; +// The list of URLs to open. First URL in the vector is the same +// as |externalURL|. +@property(nonatomic, readonly, assign) const std::vector<GURL>& URLs; + // The URL query string parameters in the case that the app was launched as a // result of Universal Link navigation. The map associates query string // parameters with their corresponding value. @@ -64,6 +68,8 @@ - (instancetype)initWithUniversalLink:(const GURL&)universalLink; +- (instancetype)initWithURLs:(const std::vector<GURL>&)URLs; + @end #endif // IOS_CHROME_APP_APP_STARTUP_PARAMETERS_H_
diff --git a/ios/chrome/app/app_startup_parameters.mm b/ios/chrome/app/app_startup_parameters.mm index 26710b9..7f033e4a 100644 --- a/ios/chrome/app/app_startup_parameters.mm +++ b/ios/chrome/app/app_startup_parameters.mm
@@ -17,6 +17,7 @@ @implementation AppStartupParameters { GURL _externalURL; GURL _completeURL; + std::vector<GURL> _URLs; } @synthesize externalURLParams = _externalURLParams; @@ -44,6 +45,20 @@ return self; } +- (instancetype)initWithURLs:(const std::vector<GURL>&)URLs { + if (URLs.empty()) { + self = [self initWithExternalURL:GURL(kChromeUINewTabURL) + completeURL:GURL(kChromeUINewTabURL)]; + } else { + self = [self initWithExternalURL:URLs.front() completeURL:URLs.front()]; + } + + if (self) { + _URLs = URLs; + } + return self; +} + // TODO(crbug.com/1021752): Remove this stub since |universalLink| is unused. - (instancetype)initWithUniversalLink:(const GURL&)universalLink { // If a new tab with |_externalURL| needs to be opened after the App
diff --git a/ios/chrome/app/application_delegate/metric_kit_subscriber_unittest.mm b/ios/chrome/app/application_delegate/metric_kit_subscriber_unittest.mm index f844b9a..3af38df 100644 --- a/ios/chrome/app/application_delegate/metric_kit_subscriber_unittest.mm +++ b/ios/chrome/app/application_delegate/metric_kit_subscriber_unittest.mm
@@ -114,6 +114,7 @@ tester.ExpectBucketCount("IOS.MetricKit.TimeToFirstDraw", 5, 2); tester.ExpectBucketCount("IOS.MetricKit.TimeToFirstDraw", 15, 4); +#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 if (base::ios::IsRunningOnIOS14OrLater()) { tester.ExpectTotalCount("IOS.MetricKit.BackgroundExitData", 71); tester.ExpectBucketCount("IOS.MetricKit.BackgroundExitData", 2, 1); @@ -135,6 +136,7 @@ tester.ExpectBucketCount("IOS.MetricKit.ForegroundExitData", 8, 18); tester.ExpectBucketCount("IOS.MetricKit.ForegroundExitData", 2, 19); } +#endif } }
diff --git a/ios/chrome/app/application_delegate/mock_tab_opener.h b/ios/chrome/app/application_delegate/mock_tab_opener.h index 85f0173..0a3c152 100644 --- a/ios/chrome/app/application_delegate/mock_tab_opener.h +++ b/ios/chrome/app/application_delegate/mock_tab_opener.h
@@ -13,7 +13,8 @@ // Mocks a class adopting the TabOpening protocol. It saves the arguments of // -dismissModalsAndOpenSelectedTabInMode:withUrlLoadParams:dismissOmnibox: -// completion:. +// completion:. Can also save the arguments of +// -dismissModalsAndOpenMultipleTabsInMode:URLs:dismissOmnibox:completion:. @interface MockTabOpener : NSObject<TabOpening> // Arguments for // -dismissModalsAndOpenSelectedTabInMode:withUrlLoadParams:dismissOmnibox: @@ -21,6 +22,9 @@ @property(nonatomic, readonly) UrlLoadParams urlLoadParams; @property(nonatomic, readonly) ApplicationModeForTabOpening applicationMode; @property(nonatomic, strong, readonly) void (^completionBlock)(void); +// Argument for +// -dismissModalsAndOpenMultipleTabsInMode:URLs:dismissOmnibox:completion:. +@property(nonatomic, readonly) const std::vector<GURL>& URLs; // Clear the URL. - (void)resetURL;
diff --git a/ios/chrome/app/application_delegate/mock_tab_opener.mm b/ios/chrome/app/application_delegate/mock_tab_opener.mm index 0a6e6f96..c8e923fd 100644 --- a/ios/chrome/app/application_delegate/mock_tab_opener.mm +++ b/ios/chrome/app/application_delegate/mock_tab_opener.mm
@@ -7,6 +7,7 @@ #include "base/ios/block_types.h" #include "ios/chrome/app/application_mode.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" +#import "net/base/mac/url_conversions.h" #include "ui/base/page_transition_types.h" #include "url/gurl.h" @@ -14,7 +15,9 @@ #error "This file requires ARC support." #endif -@implementation MockTabOpener +@implementation MockTabOpener { + std::vector<GURL> _URLs; +} - (void)dismissModalsAndOpenSelectedTabInMode: (ApplicationModeForTabOpening)targetMode @@ -25,6 +28,15 @@ _urlLoadParams = urlLoadParams; _applicationMode = targetMode; _completionBlock = [completion copy]; + _URLs.push_back(urlLoadParams.web_params.url); +} + +- (void)dismissModalsAndOpenMultipleTabsInMode: + (ApplicationModeForTabOpening)targetMode + URLs:(const std::vector<GURL>&)URLs + dismissOmnibox:(BOOL)dismissOmnibox + completion:(ProceduralBlock)completion { + _URLs = URLs; } - (void)resetURL {
diff --git a/ios/chrome/app/application_delegate/tab_opening.h b/ios/chrome/app/application_delegate/tab_opening.h index f7b847a4..ca7624ea 100644 --- a/ios/chrome/app/application_delegate/tab_opening.h +++ b/ios/chrome/app/application_delegate/tab_opening.h
@@ -31,6 +31,15 @@ dismissOmnibox:(BOOL)dismissOmnibox completion:(ProceduralBlock)completion; +// Dismisses any modal view, excluding the omnibox if |dismissOmnibox| is NO, +// then opens the list of URLs in |URLs| in either normal or incognito. +// After opening the array of URLs, run completion |handler| if it not nil. +- (void)dismissModalsAndOpenMultipleTabsInMode: + (ApplicationModeForTabOpening)targetMode + URLs:(const std::vector<GURL>&)URLs + dismissOmnibox:(BOOL)dismissOmnibox + completion:(ProceduralBlock)completion; + // Creates a new tab if the launch options are not null. - (void)openTabFromLaunchWithParams:(URLOpenerParams*)params startupInformation:(id<StartupInformation>)startupInformation
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm index 135626e..901efa3 100644 --- a/ios/chrome/app/application_delegate/user_activity_handler.mm +++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -19,6 +19,7 @@ #import "ios/chrome/app/application_delegate/startup_information.h" #import "ios/chrome/app/application_delegate/tab_opening.h" #include "ios/chrome/app/application_mode.h" +#import "ios/chrome/app/intents/OpenInChromeIncognitoIntent.h" #import "ios/chrome/app/intents/OpenInChromeIntent.h" #import "ios/chrome/app/intents/SearchInChromeIntent.h" #import "ios/chrome/app/spotlight/actions_spotlight_manager.h" @@ -55,6 +56,11 @@ NSString* const kShortcutVoiceSearch = @"OpenVoiceSearch"; NSString* const kShortcutQRScanner = @"OpenQRScanner"; +// Constants for Siri shortcut. +NSString* const kSiriShortcutOpenInChrome = @"OpenInChromeIntent"; +NSString* const kSiriShortcutSearchInChrome = @"SearchInChromeIntent"; +NSString* const kSiriShortcutOpenInIncognito = @"OpenInChromeIncognitoIntent"; + } // namespace @interface UserActivityHandler () @@ -143,7 +149,7 @@ return YES; } } else if ([userActivity.activityType - isEqualToString:@"SearchInChromeIntent"]) { + isEqualToString:kSiriShortcutSearchInChrome]) { base::RecordAction(UserMetricsAction("IOSLaunchedBySearchInChromeIntent")); AppStartupParameters* startupParams = [[AppStartupParameters alloc] @@ -166,7 +172,7 @@ webpageURL = [NSURL URLWithString:base::SysUTF8ToNSString(kChromeUINewTabURL)]; } else if ([userActivity.activityType - isEqualToString:@"OpenInChromeIntent"]) { + isEqualToString:kSiriShortcutOpenInChrome]) { base::RecordAction(UserMetricsAction("IOSLaunchedByOpenInChromeIntent")); OpenInChromeIntent* intent = base::mac::ObjCCastStrict<OpenInChromeIntent>( userActivity.interaction.intent); @@ -182,6 +188,28 @@ completeURL:webpageGURL]; [connectionInformation setStartupParameters:startupParams]; webpageURL = intent.url; + } else if ([userActivity.activityType + isEqualToString:kSiriShortcutOpenInIncognito]) { + base::RecordAction(UserMetricsAction("IOSLaunchedByOpenInIncognitoIntent")); + OpenInChromeIncognitoIntent* intent = + base::mac::ObjCCastStrict<OpenInChromeIncognitoIntent>( + userActivity.interaction.intent); + + if (!intent.urls || intent.urls.count == 0) { + return NO; + } + + std::vector<GURL> URLs; + for (NSURL* URL in intent.urls) { + URLs.push_back(net::GURLWithNSURL(URL)); + } + + AppStartupParameters* startupParams = + [[AppStartupParameters alloc] initWithURLs:URLs]; + startupParams.launchInIncognito = YES; + [connectionInformation setStartupParameters:startupParams]; + return YES; + } else { // Do nothing for unknown activity type. return NO; @@ -282,8 +310,39 @@ // Do not load the external URL if the user has not accepted the terms of // service. This corresponds to the case when the user installed Chrome, // has never launched it and attempts to open an external URL in Chrome. - if ([startupInformation isPresentingFirstRunUI]) + if ([startupInformation isPresentingFirstRunUI]) { return; + } + + if (!connectionInformation.startupParameters.URLs.empty()) { + ApplicationModeForTabOpening mode = + connectionInformation.startupParameters.launchInIncognito + ? ApplicationModeForTabOpening::INCOGNITO + : ApplicationModeForTabOpening::NORMAL; + + BOOL dismissOmnibox = [[connectionInformation startupParameters] + postOpeningAction] != FOCUS_OMNIBOX; + + // Using a weak reference to |connectionInformation| to solve a memory leak + // issue. |tabOpener| and |connectionInformation| are the same object in + // some cases (SceneController). This retains the object while the block + // exists. Then this block is passed around and in some cases it ends up + // stored in BrowserViewController. This results in a memory leak that looks + // like this: SceneController -> BrowserViewWrangler -> BrowserCoordinator + // -> BrowserViewController -> SceneController + __weak id<ConnectionInformation> weakConnectionInfo = connectionInformation; + + [tabOpener + dismissModalsAndOpenMultipleTabsInMode:mode + URLs:weakConnectionInfo + .startupParameters.URLs + dismissOmnibox:dismissOmnibox + completion:^{ + weakConnectionInfo.startupParameters = + nil; + }]; + return; + } GURL externalURL = connectionInformation.startupParameters.externalURL; // Check if it's an U2F call. If so, route it to correct tab.
diff --git a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm index 983bd20..ae811ad 100644 --- a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm +++ b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
@@ -20,6 +20,7 @@ #include "ios/chrome/app/application_delegate/startup_information.h" #include "ios/chrome/app/application_delegate/tab_opening.h" #include "ios/chrome/app/application_mode.h" +#import "ios/chrome/app/intents/OpenInChromeIncognitoIntent.h" #import "ios/chrome/app/intents/OpenInChromeIntent.h" #include "ios/chrome/app/main_controller.h" #include "ios/chrome/app/spotlight/actions_spotlight_manager.h" @@ -451,6 +452,64 @@ } } +// Tests that Chrome responds to open in incognito intent in the background +TEST_F(UserActivityHandlerTest, ContinueUserActivityIntentIncognitoBackground) { + NSURL* url1 = [[NSURL alloc] initWithString:@"http://www.google.com"]; + NSURL* url2 = [[NSURL alloc] initWithString:@"http://www.apple.com"]; + NSURL* url3 = [[NSURL alloc] initWithString:@"http://www.espn.com"]; + NSArray<NSURL*>* urls = [NSArray arrayWithObjects:url1, url2, url3, nil]; + + NSUserActivity* userActivity = [[NSUserActivity alloc] + initWithActivityType:@"OpenInChromeIncognitoIntent"]; + + OpenInChromeIncognitoIntent* intent = + [[OpenInChromeIncognitoIntent alloc] init]; + + intent.urls = urls; + + INInteraction* interaction = [[INInteraction alloc] initWithIntent:intent + response:nil]; + + userActivity.interaction = interaction; + + id startupInformationMock = + [OCMockObject niceMockForProtocol:@protocol(StartupInformation)]; + + id connectionInformationMock = + [OCMockObject niceMockForProtocol:@protocol(ConnectionInformation)]; + + [[connectionInformationMock expect] + setStartupParameters:[OCMArg checkWithBlock:^BOOL(id value) { + EXPECT_TRUE([value isKindOfClass:[AppStartupParameters class]] || + value == nil); + + if (value != nil) { + AppStartupParameters* startupParameters = + (AppStartupParameters*)value; + const GURL calledURL = startupParameters.externalURL; + EXPECT_TRUE((int)[intent.urls count] == 3); + return [intent.urls containsObject:(net::NSURLWithGURL(calledURL))]; + } else { + return YES; + } + }]]; + + [[[startupInformationMock stub] andReturnValue:@NO] isPresentingFirstRunUI]; + + MockTabOpener* tabOpener = [[MockTabOpener alloc] init]; + + // Action. + BOOL result = + [UserActivityHandler continueUserActivity:userActivity + applicationIsActive:NO + tabOpener:tabOpener + connectionInformation:connectionInformationMock + startupInformation:startupInformationMock]; + + EXPECT_OCMOCK_VERIFY(startupInformationMock); + EXPECT_TRUE(result); +} + // Tests that Chrome responds to open intents in the background. TEST_F(UserActivityHandlerTest, ContinueUserActivityIntentBackground) { NSUserActivity* userActivity = @@ -491,6 +550,65 @@ EXPECT_TRUE(result); } +// Test that Chrome respond to open in incognito intent in the foreground. +TEST_F(UserActivityHandlerTest, ContinueUserActivityIntentIncognitoForeground) { + NSURL* url1 = [[NSURL alloc] initWithString:@"http://www.google.com"]; + NSURL* url2 = [[NSURL alloc] initWithString:@"http://www.apple.com"]; + NSURL* url3 = [[NSURL alloc] initWithString:@"http://www.espn.com"]; + NSArray<NSURL*>* urls = [NSArray arrayWithObjects:url1, url2, url3, nil]; + + NSUserActivity* userActivity = [[NSUserActivity alloc] + initWithActivityType:@"OpenInChromeIncognitoIntent"]; + + OpenInChromeIncognitoIntent* intent = + [[OpenInChromeIncognitoIntent alloc] init]; + + intent.urls = urls; + + INInteraction* interaction = [[INInteraction alloc] initWithIntent:intent + response:nil]; + + userActivity.interaction = interaction; + + id startupInformationMock = + [OCMockObject niceMockForProtocol:@protocol(StartupInformation)]; + + id connectionInformationMock = + [OCMockObject niceMockForProtocol:@protocol(ConnectionInformation)]; + + [[connectionInformationMock expect] + setStartupParameters:[OCMArg checkWithBlock:^BOOL(id value) { + EXPECT_TRUE([value isKindOfClass:[AppStartupParameters class]] || + value == nil); + + if (value != nil) { + AppStartupParameters* startupParameters = + (AppStartupParameters*)value; + const GURL calledURL = startupParameters.externalURL; + EXPECT_TRUE((int)[intent.urls count] == 3); + return [intent.urls containsObject:(net::NSURLWithGURL(calledURL))]; + } else { + return YES; + } + }]]; + + [[[startupInformationMock stub] andReturnValue:@NO] isPresentingFirstRunUI]; + + MockTabOpener* tabOpener = [[MockTabOpener alloc] init]; + + // Action. + BOOL result = + [UserActivityHandler continueUserActivity:userActivity + applicationIsActive:YES + tabOpener:tabOpener + connectionInformation:connectionInformationMock + startupInformation:startupInformationMock]; + + // Test. + EXPECT_OCMOCK_VERIFY(startupInformationMock); + EXPECT_TRUE(result); +} + // Tests that Chrome responds to open intents in the foreground. TEST_F(UserActivityHandlerTest, ContinueUserActivityIntentForeground) { GURL gurl("http://www.google.com");
diff --git a/ios/chrome/app/intents/BUILD.gn b/ios/chrome/app/intents/BUILD.gn index 8e5bfc6e..7f25c213 100644 --- a/ios/chrome/app/intents/BUILD.gn +++ b/ios/chrome/app/intents/BUILD.gn
@@ -8,6 +8,7 @@ intent_file = "Intents.intentdefinition" intent_names = [ "OpenInChromeIntent", + "OpenInChromeIncognitoIntent", "SearchInChromeIntent", ] }
diff --git a/ios/chrome/app/intents/Intents.intentdefinition b/ios/chrome/app/intents/Intents.intentdefinition index 40b38b05..653f181 100644 --- a/ios/chrome/app/intents/Intents.intentdefinition +++ b/ios/chrome/app/intents/Intents.intentdefinition
@@ -203,6 +203,98 @@ <key>INIntentVerb</key> <string>Open</string> </dict> + <dict> + <key>INIntentCategory</key> + <string>information</string> + <key>INIntentConfigurable</key> + <true/> + <key>INIntentDescriptionID</key> + <string>dYRltF</string> + <key>INIntentEligibleForWidgets</key> + <true/> + <key>INIntentIneligibleForSuggestions</key> + <true/> + <key>INIntentInput</key> + <string>urls</string> + <key>INIntentLastParameterTag</key> + <integer>4</integer> + <key>INIntentManagedParameterCombinations</key> + <dict> + <key>urls</key> + <dict> + <key>INIntentParameterCombinationSupportsBackgroundExecution</key> + <true/> + <key>INIntentParameterCombinationTitle</key> + <string>Open ${urls} in Incognito</string> + <key>INIntentParameterCombinationTitleID</key> + <string>6TwrYB</string> + <key>INIntentParameterCombinationUpdatesLinked</key> + <true/> + </dict> + </dict> + <key>INIntentName</key> + <string>OpenInChromeIncognito</string> + <key>INIntentParameters</key> + <array> + <dict> + <key>INIntentParameterConfigurable</key> + <true/> + <key>INIntentParameterDisplayName</key> + <string>URLs</string> + <key>INIntentParameterDisplayNameID</key> + <string>C8MCpv</string> + <key>INIntentParameterDisplayPriority</key> + <integer>1</integer> + <key>INIntentParameterName</key> + <string>urls</string> + <key>INIntentParameterPromptDialogs</key> + <array> + <dict> + <key>INIntentParameterPromptDialogCustom</key> + <true/> + <key>INIntentParameterPromptDialogFormatString</key> + <string>What URLs?</string> + <key>INIntentParameterPromptDialogFormatStringID</key> + <string>sNz7Cu</string> + <key>INIntentParameterPromptDialogType</key> + <string>Primary</string> + </dict> + </array> + <key>INIntentParameterSupportsMultipleValues</key> + <true/> + <key>INIntentParameterSupportsResolution</key> + <true/> + <key>INIntentParameterTag</key> + <integer>4</integer> + <key>INIntentParameterType</key> + <string>URL</string> + </dict> + </array> + <key>INIntentResponse</key> + <dict> + <key>INIntentResponseCodes</key> + <array> + <dict> + <key>INIntentResponseCodeName</key> + <string>success</string> + <key>INIntentResponseCodeSuccess</key> + <true/> + </dict> + <dict> + <key>INIntentResponseCodeName</key> + <string>failure</string> + </dict> + </array> + </dict> + <key>INIntentTitle</key> + <string>Open URLs In Chrome Incognito</string> + <key>INIntentTitleID</key> + <string>LHJwpy</string> + <key>INIntentType</key> + <string>Custom</string> + <key>INIntentVerb</key> + <string>Open</string> + </dict> </array> <key>INTypes</key> <array/>
diff --git a/ios/chrome/app/resources/Info.plist b/ios/chrome/app/resources/Info.plist index f6d3921..79426e0 100644 --- a/ios/chrome/app/resources/Info.plist +++ b/ios/chrome/app/resources/Info.plist
@@ -95,6 +95,7 @@ <string>${CHROMIUM_HANDOFF_ID}</string> <string>OpenInChromeIntent</string> <string>SearchInChromeIntent</string> + <string>OpenInChromeIncognitoIntent</string> </array> <key>UIBackgroundModes</key> <array>
diff --git a/ios/chrome/app/resources/chrome_localize_strings_config.plist b/ios/chrome/app/resources/chrome_localize_strings_config.plist index ecbdaa2..7de946931 100644 --- a/ios/chrome/app/resources/chrome_localize_strings_config.plist +++ b/ios/chrome/app/resources/chrome_localize_strings_config.plist
@@ -30,6 +30,24 @@ <array> <dict> <key>input</key> + <string>IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_TITLE</string> + <key>output</key> + <string>LHJwpy</string> + </dict> + <dict> + <key>input</key> + <string>IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_DESCRIPTION</string> + <key>output</key> + <string>dYRltF</string> + </dict> + <dict> + <key>input</key> + <string>IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_PARAMETER_COMBINATION_TITLE</string> + <key>output</key> + <string>6TwrYB</string> + </dict> + <dict> + <key>input</key> <string>IDS_IOS_INTENTS_SEARCH_IN_CHROME_DESCRIPTION</string> <key>output</key> <string>4nGj7v</string>
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 9c48f4af..51aec9e 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -713,6 +713,12 @@ <message name="IDS_IOS_DISCOVER_FEED_MENU_MANAGE_INTERESTS_ITEM" desc="The 'Manage Interests' action for the Discover feed header menu."> Manage Interests </message> + <message name="IDS_IOS_DISCOVER_FEED_MENU_TURN_OFF_ITEM" desc="The 'Turn Off' action for the Discover feed header menu."> + Turn Off + </message> + <message name="IDS_IOS_DISCOVER_FEED_MENU_TURN_ON_ITEM" desc="The 'Turn On' action for the Discover feed header menu."> + Turn On + </message> <message name="IDS_IOS_DOWNLOAD_MANAGER_CANNOT_DETERMINE_FILE_SIZE" desc="Message displayed when the size of the file to be downloaded is unknown. [Length: 30em] [iOS only]"> Cannot determine file size. </message> @@ -926,6 +932,15 @@ <message name="IDS_IOS_INTENTS_OPEN_IN_CHROME_PARAMETER_COMBINATION_TITLE" desc="Apple Shortcuts.app format for displaying the URL input [iOS only]."> Open ${url} </message> + <message name="IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_TITLE" desc="Shortcut name to open URL in Chrome in Incognito [iOS only]."> + Open URLs in Chrome in Incognito + </message> + <message name="IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_DESCRIPTION" desc="Shortcut description to open URLs in Chrome in Incognito [iOS only]."> + Opens the inputted URLs in Google Chrome in Incognito. + </message> + <message name="IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_PARAMETER_COMBINATION_TITLE" desc="Apple Shortcuts.app format for displaying the URL input [iOS only]."> + Open ${urls} in Incognito + </message> <message name="IDS_IOS_INTENTS_SEARCH_IN_CHROME_DESCRIPTION" desc="Siri Shortcut for search in chrome description [iOS only]."> Start a search in a new Chrome tab. </message> @@ -1644,9 +1659,9 @@ </message> <message name="IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT" desc="Displays the number of compromised passwords present in the database"> {COUNT, plural, - =0 {No passwords compromised} - =1 {{COUNT} Password compromised} - other {{COUNT} Passwords compromised}} + =0 {No compromised passwords} + =1 {{COUNT} Compromised password} + other {{COUNT} Compromised passwords}} </message> <message name="IDS_IOS_CHECK_PASSWORDS_NOW_BUTTON" desc="Label of a button which starts Password Check [Length: 22em] [iOS only]" meaning="By clicking this button user will start checking all passwords for security issues."> Check Now @@ -1658,7 +1673,7 @@ The following accounts use passwords which were exposed in a third-party data breach or entered on a deceptive website. Change these passwords immediately to keep your accounts safe. </message> <message name="IDS_IOS_CHANGE_COMPROMISED_PASSWORD" desc="Button which is shown on Password Details Screen when password is compromised. [iOS only]" meaning="Telling user to change password on a website since it is compromised."> - Change password on Website + Change Password on Website </message> <message name="IDS_IOS_DELETE_COMPROMISED_PASSWORD_DESCRIPTION" desc="Message on top of the confirmation alert when the user tapped delete password button. [iOS only]" meaning="Explaining to the user that deleting password locally won't delete account on a website."> Deleting this password will not delete your account on <ph name="WEBSITE">$1<ex>twitter.com</ex></ph>. Change your password on <ph name="WEBSITE">$1<ex>twitter.com</ex></ph> to keep it safe from others.
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHANGE_COMPROMISED_PASSWORD.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHANGE_COMPROMISED_PASSWORD.png.sha1 index c217b85..e6320e1 100644 --- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHANGE_COMPROMISED_PASSWORD.png.sha1 +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHANGE_COMPROMISED_PASSWORD.png.sha1
@@ -1 +1 @@ -324e42d485c2b5ff652e154aa3ccac09e7b3aa09 \ No newline at end of file +508a3df5a981a9511135c8f57d2698b559b82f84 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT.png.sha1 index 6627543..30e43b21 100644 --- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT.png.sha1 +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT.png.sha1
@@ -1 +1 @@ -50f9da3214aa8cc48c5c1038753cb1aa27073713 \ No newline at end of file +d1b5c43ab616e32688883221d4bffe29e4e5459f \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_DISCOVER_FEED_MENU_TURN_OFF_ITEM.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_DISCOVER_FEED_MENU_TURN_OFF_ITEM.png.sha1 new file mode 100644 index 0000000..3833ceb4 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_DISCOVER_FEED_MENU_TURN_OFF_ITEM.png.sha1
@@ -0,0 +1 @@ +b446e394ffe02fdf7818bbfb93bcb64a81477e10 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_DISCOVER_FEED_MENU_TURN_ON_ITEM.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_DISCOVER_FEED_MENU_TURN_ON_ITEM.png.sha1 new file mode 100644 index 0000000..cbdcb43 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_DISCOVER_FEED_MENU_TURN_ON_ITEM.png.sha1
@@ -0,0 +1 @@ +3d5ca14ee7f1293bfaf77ca7cb071e452c2f7690 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_DESCRIPTION.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..6eb8cebb --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +8614ba451df59e9955225a99e030b9072e86701e \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_PARAMETER_COMBINATION_TITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_PARAMETER_COMBINATION_TITLE.png.sha1 new file mode 100644 index 0000000..61446bf --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_PARAMETER_COMBINATION_TITLE.png.sha1
@@ -0,0 +1 @@ +6bd0e2112cf7b407cc5ea7adee64a55981d83751 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_TITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_TITLE.png.sha1 new file mode 100644 index 0000000..77374a07 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_TITLE.png.sha1
@@ -0,0 +1 @@ +931014dc4c94334d3c6a37b6ddfb68cfc7ff7f7f \ No newline at end of file
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index c53e865..31521a6 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -680,6 +680,9 @@ flag_descriptions::kEnableFullPageScreenshotName, flag_descriptions::kEnableFullPageScreenshotDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kEnableFullPageScreenshot)}, + {"scroll-to-text-ios", flag_descriptions::kScrollToTextIOSName, + flag_descriptions::kScrollToTextIOSDescription, flags_ui::kOsIos, + FEATURE_VALUE_TYPE(web::features::kScrollToTextIOS)}, }; bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index 4ba8d47..abdc73e 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -421,6 +421,12 @@ const char kSaveCardInfobarMessagesUIDescription[] = "When enabled, Save Card Infobar uses the new Messages UI."; +const char kScrollToTextIOSName[] = "Enable Scroll to Text"; +const char kScrollToTextIOSDescription[] = + "When enabled, opening a URL with a text fragment (e.g., " + "example.com/#:~:text=examples) will cause matching text in the page to be " + "highlighted and scrolled into view."; + const char kSendTabToSelfName[] = "Send tab to self"; const char kSendTabToSelfDescription[] = "Allows users to receive tabs that were pushed from another of their " @@ -438,9 +444,8 @@ const char kSharedHighlightingIOSName[] = "Enable Shared Highlighting features"; const char kSharedHighlightingIOSDescription[] = - "Enables support for Text Fragments (scroll-to-text based on URL " - "directive) and a Link to Text option in the Edit Menu which generates " - "these URLs."; + "Adds a Link to Text option in the Edit Menu which generates URLs with a " + "text fragment. Works best with the #scroll-to-text-ios flag."; const char kShowAutofillTypePredictionsName[] = "Show Autofill predictions"; const char kShowAutofillTypePredictionsDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index fa95ba8..c98e41b 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -366,6 +366,10 @@ extern const char kSaveCardInfobarMessagesUIName[]; extern const char kSaveCardInfobarMessagesUIDescription[]; +// Title and description for the flag to enable the Scroll to Text feature. +extern const char kScrollToTextIOSName[]; +extern const char kScrollToTextIOSDescription[]; + // Title and description for the flag to enable the send tab to self receiving // feature. extern const char kSendTabToSelfName[]; @@ -381,7 +385,7 @@ extern const char kSettingsRefreshDescription[]; // Title and description for the flag to enable Shared Highlighting (Link to -// Text Edit Menu option and Text Fragments web behavior). +// Text Edit Menu option). extern const char kSharedHighlightingIOSName[]; extern const char kSharedHighlightingIOSDescription[];
diff --git a/ios/chrome/browser/metrics/demographics_egtest.mm b/ios/chrome/browser/metrics/demographics_egtest.mm index f06f84f..da2ad7f7 100644 --- a/ios/chrome/browser/metrics/demographics_egtest.mm +++ b/ios/chrome/browser/metrics/demographics_egtest.mm
@@ -7,8 +7,8 @@ #include "components/metrics/demographic_metrics_provider.h" #include "components/ukm/ukm_service.h" #import "ios/chrome/browser/metrics/metrics_app_interface.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_test_case.h" #import "ios/testing/earl_grey/app_launch_configuration.h" @@ -132,7 +132,7 @@ // anonymized data collection is turned on as part of the flow to Sign in to // Chrome and Turn on sync. This matches the main user flow that enables // UKM. - [SigninEarlGreyUI signinWithFakeIdentity:[SigninEarlGreyUtils fakeIdentity1]]; + [SigninEarlGreyUI signinWithFakeIdentity:[SigninEarlGrey fakeIdentity1]]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:syncher::kSyncUKMOperationsTimeout]; }
diff --git a/ios/chrome/browser/metrics/ukm_egtest.mm b/ios/chrome/browser/metrics/ukm_egtest.mm index 712594d..b8045ba4 100644 --- a/ios/chrome/browser/metrics/ukm_egtest.mm +++ b/ios/chrome/browser/metrics/ukm_egtest.mm
@@ -5,9 +5,9 @@ #include "base/ios/ios_util.h" #include "base/macros.h" #import "ios/chrome/browser/metrics/metrics_app_interface.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h" #import "ios/chrome/test/earl_grey/chrome_actions.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" @@ -63,7 +63,7 @@ // Note: URL-keyed anonymized data collection is turned on as part of the // flow to Sign in to Chrome and Turn sync on. This matches the main user // flow that enables UKM. - [SigninEarlGreyUI signinWithFakeIdentity:[SigninEarlGreyUtils fakeIdentity1]]; + [SigninEarlGreyUI signinWithFakeIdentity:[SigninEarlGrey fakeIdentity1]]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:syncher::kSyncUKMOperationsTimeout]; @@ -93,8 +93,8 @@ // Note: URL-keyed anonymized data collection is turned off as part of the // flow to Sign out of Chrome and Turn sync off. This matches the main user // flow that disables UKM. - if (![SigninEarlGreyUtilsAppInterface isSignedOut]) { - [SigninEarlGreyUtilsAppInterface signOut]; + if (![SigninEarlGreyAppInterface isSignedOut]) { + [SigninEarlGreyAppInterface signOut]; } [ChromeEarlGrey waitForSyncInitialized:NO @@ -274,7 +274,7 @@ // Corresponds to ConsentAddedButNoSyncCheck in //chrome/browser/metrics/ // ukm_browsertest.cc. - (void)testConsentAddedButNoSync { - [SigninEarlGreyUtilsAppInterface signOut]; + [SigninEarlGreyAppInterface signOut]; [MetricsAppInterface setMetricsAndCrashReportingForTesting:NO]; GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], @"Failed to assert that UKM was not enabled."); @@ -283,7 +283,7 @@ GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], @"Failed to assert that UKM was not enabled."); - [SigninEarlGreyUI signinWithFakeIdentity:[SigninEarlGreyUtils fakeIdentity1]]; + [SigninEarlGreyUI signinWithFakeIdentity:[SigninEarlGrey fakeIdentity1]]; GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES], @"Failed to assert that UKM was enabled."); } @@ -347,7 +347,7 @@ #endif const uint64_t clientID1 = [MetricsAppInterface UKMClientID]; - [SigninEarlGreyUtilsAppInterface signOut]; + [SigninEarlGreyAppInterface signOut]; GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], @"Failed to assert that UKM was not enabled."); @@ -356,7 +356,7 @@ @"Client ID was not reset."); const uint64_t clientID2 = [MetricsAppInterface UKMClientID]; - [SigninEarlGreyUI signinWithFakeIdentity:[SigninEarlGreyUtils fakeIdentity1]]; + [SigninEarlGreyUI signinWithFakeIdentity:[SigninEarlGrey fakeIdentity1]]; GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES], @"Failed to assert that UKM was enabled.");
diff --git a/ios/chrome/browser/reading_list/offline_page_tab_helper.h b/ios/chrome/browser/reading_list/offline_page_tab_helper.h index 5aeecde..d3b9f52 100644 --- a/ios/chrome/browser/reading_list/offline_page_tab_helper.h +++ b/ios/chrome/browser/reading_list/offline_page_tab_helper.h
@@ -134,6 +134,11 @@ bool navigation_is_renderer_initiated_ = false; WEB_STATE_USER_DATA_KEY_DECL(); + + // Member variables should appear before the WeakPtrFactory, to ensure + // that any WeakPtrs to OfflinePageTabHelper are invalidated before its + // members variable's destructors are executed, rendering them invalid. + base::WeakPtrFactory<OfflinePageTabHelper> weak_factory_{this}; }; #endif // IOS_CHROME_BROWSER_READING_LIST_OFFLINE_PAGE_TAB_HELPER_H_
diff --git a/ios/chrome/browser/reading_list/offline_page_tab_helper.mm b/ios/chrome/browser/reading_list/offline_page_tab_helper.mm index 837dc715..6962a17 100644 --- a/ios/chrome/browser/reading_list/offline_page_tab_helper.mm +++ b/ios/chrome/browser/reading_list/offline_page_tab_helper.mm
@@ -289,9 +289,9 @@ {base::MayBlock(), base::TaskPriority::USER_BLOCKING, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, base::BindOnce(&GetOfflineData, offline_root, offline_path), - base::BindOnce(&OfflinePageTabHelper::LoadData, base::Unretained(this), - last_navigation_started_, entry_url, - offline_path.Extension())); + base::BindOnce(&OfflinePageTabHelper::LoadData, + weak_factory_.GetWeakPtr(), last_navigation_started_, + entry_url, offline_path.Extension())); } bool OfflinePageTabHelper::HasDistilledVersionForOnlineUrl(
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn index a7ff6f6..d9c54b1 100644 --- a/ios/chrome/browser/ui/authentication/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -144,8 +144,8 @@ ] testonly = true sources = [ - "signin_earlgrey_utils_app_interface.h", - "signin_earlgrey_utils_app_interface.mm", + "signin_earl_grey_app_interface.h", + "signin_earl_grey_app_interface.mm", ] deps = [ ":authentication", @@ -177,12 +177,12 @@ ] testonly = true sources = [ + "signin_earl_grey.h", + "signin_earl_grey.mm", + "signin_earl_grey_app_interface.h", + "signin_earl_grey_app_interface_stub.mm", "signin_earl_grey_ui.h", "signin_earl_grey_ui.mm", - "signin_earlgrey_utils.h", - "signin_earlgrey_utils.mm", - "signin_earlgrey_utils_app_interface.h", - "signin_earlgrey_utils_app_interface_stub.mm", ] deps = [ "//base",
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm b/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm index eab5ceed..09e9070 100644 --- a/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm +++ b/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm
@@ -7,8 +7,8 @@ #include "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" #include "base/test/scoped_feature_list.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h" #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_constants.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" @@ -75,10 +75,10 @@ void ChooseImportOrKeepDataSepareteDialog(id<GREYMatcher> choiceButtonMatcher) { // Set up the fake identities. - FakeChromeIdentity* fakeIdentity1 = [SigninEarlGreyUtils fakeIdentity1]; - FakeChromeIdentity* fakeIdentity2 = [SigninEarlGreyUtils fakeIdentity2]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity2]; + FakeChromeIdentity* fakeIdentity1 = [SigninEarlGrey fakeIdentity1]; + FakeChromeIdentity* fakeIdentity2 = [SigninEarlGrey fakeIdentity2]; + [SigninEarlGrey addFakeIdentity:fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity2]; // Sign in to |fakeIdentity1|. [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity1]; @@ -101,7 +101,7 @@ performAction:grey_tap()]; // Check the signed-in user did change. - [SigninEarlGreyUtils checkSignedInWithFakeIdentity:fakeIdentity2]; + [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity2]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; @@ -127,13 +127,13 @@ // correctly when there is already an identity on the device. - (void)testSignInOneUser { // Set up a fake identity. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Check |fakeIdentity| is signed-in. - [SigninEarlGreyUtils checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; } // Tests signing in with one account, switching sync account to a second and @@ -150,8 +150,8 @@ // Tests that signing out from the Settings works correctly. - (void)testSignInDisconnectFromChrome { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; // Sign in to |fakeIdentity|. [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; @@ -164,7 +164,7 @@ // Tests that signing out of a managed account from the Settings works // correctly. - (void)testSignInDisconnectFromChromeManaged { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeManagedIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeManagedIdentity]; // Sign-in with a managed account. [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity isManagedAccount:YES]; @@ -174,15 +174,15 @@ signOutWithSignOutConfirmation:SignOutConfirmationManagedUser]; // Check that there is no signed in user. - [SigninEarlGreyUtils checkSignedOut]; + [SigninEarlGrey checkSignedOut]; } // Tests that signing in, tapping the Settings link on the confirmation screen // and closing the advanced sign-in settings correctly leaves the user signed // in. - (void)testSignInOpenSettings { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [self openSigninFromView:OpenSigninMethodFromSettings tapSettingsLink:YES]; @@ -196,7 +196,7 @@ [[EarlGrey selectElementWithMatcher:settings_matcher] assertWithMatcher:grey_sufficientlyVisible()]; // Test the user is signed in. - [SigninEarlGreyUtils checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; } // Opens the sign in screen and then cancel it by opening a new tab. Ensures @@ -204,8 +204,8 @@ - (void)testSignInCancelIdentityPicker { // Add an identity to avoid arriving on the Add Account screen when opening // sign-in. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [ChromeEarlGreyUI openSettingsMenu]; [ChromeEarlGreyUI tapSettingsMenuButton:SecondarySignInButton()]; @@ -241,10 +241,10 @@ // crbug.com/462202 - (void)testSignInCancelAuthenticationFlow { // Set up the fake identities. - FakeChromeIdentity* fakeIdentity1 = [SigninEarlGreyUtils fakeIdentity1]; - FakeChromeIdentity* fakeIdentity2 = [SigninEarlGreyUtils fakeIdentity2]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity2]; + FakeChromeIdentity* fakeIdentity1 = [SigninEarlGrey fakeIdentity1]; + FakeChromeIdentity* fakeIdentity2 = [SigninEarlGrey fakeIdentity2]; + [SigninEarlGrey addFakeIdentity:fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity2]; // This signs in |fakeIdentity2| first, ensuring that the "Clear Data Before // Syncing" dialog is shown during the second sign-in. This dialog will @@ -290,15 +290,15 @@ performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; - [SigninEarlGreyUtils checkSignedOut]; + [SigninEarlGrey checkSignedOut]; } // Opens the sign in screen from the bookmarks and then cancel it by tapping on // done. Ensures that the sign in screen is correctly dismissed. // Regression test for crbug.com/596029. - (void)testSignInCancelFromBookmarks { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; // Open Bookmarks and tap on Sign In promo button. [ChromeEarlGreyUI openToolsMenu]; @@ -409,8 +409,8 @@ if (!base::ios::IsRunningOnOrLater(13, 0, 0)) { EARL_GREY_TEST_SKIPPED(@"Test disabled on iOS 12 and lower."); } - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [self openSigninFromView:OpenSigninMethodFromSettings tapSettingsLink:YES]; [[EarlGrey selectElementWithMatcher:GoogleServicesSettingsView()] @@ -420,7 +420,7 @@ ButtonWithAccessibilityLabel(GetNSString( IDS_IOS_ADVANCED_SIGNIN_SETTINGS_CANCEL_SYNC_ALERT_CANCEL_SYNC_BUTTON))] performAction:grey_tap()]; - [SigninEarlGreyUtils checkSignedOut]; + [SigninEarlGrey checkSignedOut]; } #pragma mark - Utils @@ -469,8 +469,8 @@ // |tapSettingsLink| if YES, the setting link is tapped before opening the URL. - (void)assertOpenURLWhenSigninFromView:(OpenSigninMethod)openSigninMethod tapSettingsLink:(BOOL)tapSettingsLink { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [self openSigninFromView:openSigninMethod tapSettingsLink:tapSettingsLink]; // Open the URL as if it was opened from another app. [ChromeEarlGrey simulateExternalAppURLOpening]; @@ -482,10 +482,10 @@ if (tapSettingsLink) { // Should be signed in. - [SigninEarlGreyUtils checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; } else { // Should be not signed in. - [SigninEarlGreyUtils checkSignedOut]; + [SigninEarlGrey checkSignedOut]; } } @@ -493,7 +493,7 @@ // onscreen. - (void)assertFakeSSOScreenIsVisible { // Check for the fake SSO screen. - [SigninEarlGreyUtils + [SigninEarlGrey waitForMatcher:grey_accessibilityID(kFakeAddAccountViewIdentifier)]; // Close the SSO view controller. id<GREYMatcher> matcher = @@ -534,17 +534,17 @@ // Tests to remove the last identity in the identity chooser. - (void)testRemoveLastAccount { // Set up a fake identity. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; // Open the identity chooser. [ChromeEarlGreyUI openSettingsMenu]; [ChromeEarlGreyUI tapSettingsMenuButton:SecondarySignInButton()]; - [SigninEarlGreyUtils waitForMatcher:identityChooserButtonMatcherWithEmail( - fakeIdentity.userEmail)]; + [SigninEarlGrey waitForMatcher:identityChooserButtonMatcherWithEmail( + fakeIdentity.userEmail)]; // Remove the fake identity. - [SigninEarlGreyUtils removeFakeIdentity:fakeIdentity]; + [SigninEarlGrey removeFakeIdentity:fakeIdentity]; [ChromeEarlGreyUI waitForAppToIdle]; // Check that the identity has been removed. @@ -558,8 +558,8 @@ - (void)testSignInCancelAddAccount { // Add an identity to avoid arriving on the Add Account screen when opening // sign-in. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [ChromeEarlGreyUI openSettingsMenu]; [ChromeEarlGreyUI tapSettingsMenuButton:SecondarySignInButton()];
diff --git a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h b/ios/chrome/browser/ui/authentication/signin_earl_grey.h similarity index 78% rename from ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h rename to ios/chrome/browser/ui/authentication/signin_earl_grey.h index 2f5e43ec8..df6840d 100644 --- a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h +++ b/ios/chrome/browser/ui/authentication/signin_earl_grey.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARLGREY_UTILS_H_ -#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARLGREY_UTILS_H_ +#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARL_GREY_H_ +#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARL_GREY_H_ #import <Foundation/Foundation.h> @@ -13,12 +13,12 @@ @protocol GREYMatcher; @class FakeChromeIdentity; -#define SigninEarlGreyUtils \ - [SigninEarlGreyUtilsImpl invokedFromFile:@"" __FILE__ lineNumber:__LINE__] +#define SigninEarlGrey \ + [SigninEarlGreyImpl invokedFromFile:@"" __FILE__ lineNumber:__LINE__] // Methods used for the EarlGrey tests. // TODO(crbug.com/974833): Consider moving these into ChromeEarlGrey. -@interface SigninEarlGreyUtilsImpl : BaseEGTestHelperImpl +@interface SigninEarlGreyImpl : BaseEGTestHelperImpl // Returns a fake identity. - (FakeChromeIdentity*)fakeIdentity1; @@ -51,4 +51,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARLGREY_UTILS_H_ +#endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARL_GREY_H_
diff --git a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils.mm b/ios/chrome/browser/ui/authentication/signin_earl_grey.mm similarity index 83% rename from ios/chrome/browser/ui/authentication/signin_earlgrey_utils.mm rename to ios/chrome/browser/ui/authentication/signin_earl_grey.mm index b4ed14a..060b40cc 100644 --- a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils.mm +++ b/ios/chrome/browser/ui/authentication/signin_earl_grey.mm
@@ -2,10 +2,10 @@ // 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/authentication/signin_earlgrey_utils.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" #import "base/test/ios/wait_util.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h" #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h" #import "ios/testing/earl_grey/earl_grey_test.h" @@ -13,7 +13,7 @@ #error "This file requires ARC support." #endif -@implementation SigninEarlGreyUtilsImpl +@implementation SigninEarlGreyImpl - (FakeChromeIdentity*)fakeIdentity1 { return [FakeChromeIdentity identityWithEmail:@"foo1@gmail.com" @@ -34,11 +34,11 @@ } - (void)addFakeIdentity:(FakeChromeIdentity*)fakeIdentity { - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; } - (void)forgetFakeIdentity:(FakeChromeIdentity*)fakeIdentity { - [SigninEarlGreyUtilsAppInterface forgetFakeIdentity:fakeIdentity]; + [SigninEarlGreyAppInterface forgetFakeIdentity:fakeIdentity]; } - (void)checkSignedInWithFakeIdentity:(FakeChromeIdentity*)fakeIdentity { @@ -52,14 +52,14 @@ base::test::ios::kWaitForActionTimeout, ^bool { NSString* primaryAccountGaiaID = - [SigninEarlGreyUtilsAppInterface primaryAccountGaiaID]; + [SigninEarlGreyAppInterface primaryAccountGaiaID]; return primaryAccountGaiaID.length > 0; }), @"Sign in did not complete."); GREYWaitForAppToIdle(@"App failed to idle"); NSString* primaryAccountGaiaID = - [SigninEarlGreyUtilsAppInterface primaryAccountGaiaID]; + [SigninEarlGreyAppInterface primaryAccountGaiaID]; NSString* errorStr = [NSString stringWithFormat:@"Unexpected Gaia ID of the signed in user [expected = " @@ -75,12 +75,12 @@ // the assert. GREYWaitForAppToIdle(@"App failed to idle"); - EG_TEST_HELPER_ASSERT_TRUE([SigninEarlGreyUtilsAppInterface isSignedOut], + EG_TEST_HELPER_ASSERT_TRUE([SigninEarlGreyAppInterface isSignedOut], @"Unexpected signed in user"); } - (void)removeFakeIdentity:(FakeChromeIdentity*)fakeIdentity { - [SigninEarlGreyUtilsAppInterface removeFakeIdentity:fakeIdentity]; + [SigninEarlGreyAppInterface removeFakeIdentity:fakeIdentity]; } - (void)waitForMatcher:(id<GREYMatcher>)matcher {
diff --git a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h b/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h similarity index 77% rename from ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h rename to ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h index 916c6b5..545fcd6 100644 --- a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h +++ b/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h
@@ -2,18 +2,18 @@ // 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_AUTHENTICATION_SIGNIN_EARLGREY_UTILS_APP_INTERFACE_H_ -#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARLGREY_UTILS_APP_INTERFACE_H_ +#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARL_GREY_APP_INTERFACE_H_ +#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARL_GREY_APP_INTERFACE_H_ #import <Foundation/Foundation.h> @class FakeChromeIdentity; @protocol GREYMatcher; -// SigninEarlGreyUtilsAppInterface contains the app-side implementation for +// SigninEarlGreyAppInterface contains the app-side implementation for // helpers that primarily work via direct model access. These helpers are // compiled into the app binary and can be called from either app or test code. -@interface SigninEarlGreyUtilsAppInterface : NSObject +@interface SigninEarlGreyAppInterface : NSObject // Returns a fake identity. + (FakeChromeIdentity*)fakeIdentity1; @@ -48,4 +48,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARLGREY_UTILS_APP_INTERFACE_H_ +#endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARL_GREY_APP_INTERFACE_H_
diff --git a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.mm b/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.mm similarity index 96% rename from ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.mm rename to ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.mm index 9d469a8..0f2416b 100644 --- a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.mm +++ b/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h" #include "base/strings/sys_string_conversions.h" #include "components/bookmarks/browser/bookmark_model.h" @@ -26,7 +26,7 @@ #error "This file requires ARC support." #endif -@implementation SigninEarlGreyUtilsAppInterface +@implementation SigninEarlGreyAppInterface + (FakeChromeIdentity*)fakeIdentity1 { return [FakeChromeIdentity identityWithEmail:@"foo1@gmail.com"
diff --git a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface_stub.mm b/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface_stub.mm similarity index 71% rename from ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface_stub.mm rename to ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface_stub.mm index c87d363..f1c6a193 100644 --- a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface_stub.mm +++ b/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface_stub.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h" #import "ios/third_party/earl_grey2/src/CommonLib/DistantObject/GREYTestApplicationDistantObject.h" @@ -10,4 +10,4 @@ #error "This file requires ARC support." #endif -GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(SigninEarlGreyUtilsAppInterface) +GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(SigninEarlGreyAppInterface)
diff --git a/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm b/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm index e514ec48..648ba391 100644 --- a/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm +++ b/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm
@@ -6,8 +6,8 @@ #include "base/mac/foundation_util.h" #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_constants.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h" #import "ios/chrome/browser/ui/authentication/unified_consent/unified_consent_constants.h" #import "ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller_constants.h" #include "ios/chrome/grit/ios_strings.h" @@ -38,7 +38,7 @@ + (void)signinWithFakeIdentity:(FakeChromeIdentity*)fakeIdentity isManagedAccount:(BOOL)isManagedAccount { - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [ChromeEarlGreyUI openSettingsMenu]; [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SecondarySignInButton()]; @@ -49,13 +49,13 @@ } [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; - [SigninEarlGreyUtils checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; } + (void)selectIdentityWithEmail:(NSString*)userEmail { // Assumes that the identity chooser is visible. [[EarlGrey - selectElementWithMatcher:[SigninEarlGreyUtilsAppInterface + selectElementWithMatcher:[SigninEarlGreyAppInterface identityCellMatcherForEmail:userEmail]] performAction:grey_tap()]; } @@ -74,7 +74,7 @@ ScopedSynchronizationDisabler disabler; id<GREYMatcher> acceptButton = [ChromeMatchersAppInterface buttonWithAccessibilityLabelID:IDS_IOS_MANAGED_SIGNIN_ACCEPT_BUTTON]; - [SigninEarlGreyUtils waitForMatcher:acceptButton]; + [SigninEarlGrey waitForMatcher:acceptButton]; [[EarlGrey selectElementWithMatcher:acceptButton] performAction:grey_tap()]; } @@ -224,7 +224,7 @@ [ChromeEarlGreyUI waitForAppToIdle]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; - [SigninEarlGreyUtils checkSignedOut]; + [SigninEarlGrey checkSignedOut]; } + (void)tapRemoveAccountFromDeviceWithFakeIdentity:
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_promo_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_promo_egtest.mm index ebdebfe..5c5d22b 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_promo_egtest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmarks_promo_egtest.mm
@@ -7,8 +7,8 @@ #include "base/ios/ios_util.h" #import "ios/chrome/browser/ui/authentication/signin/signin_constants.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_ui.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_ui_constants.h" @@ -150,7 +150,7 @@ [BookmarkEarlGreyUI openBookmarks]; // Set up a fake identity. - [SigninEarlGreyUtils addFakeIdentity:[SigninEarlGreyUtils fakeIdentity1]]; + [SigninEarlGrey addFakeIdentity:[SigninEarlGrey fakeIdentity1]]; // Check that promo is visible. [BookmarkEarlGrey verifyPromoAlreadySeen:NO]; @@ -182,8 +182,8 @@ [BookmarkEarlGrey setupStandardBookmarks]; [BookmarkEarlGreyUI openBookmarks]; - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; // Check that sign-in promo view are visible. [BookmarkEarlGrey verifyPromoAlreadySeen:NO];
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index 9eda7d2..37988ac 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -92,6 +92,7 @@ // Redefined as readwrite. @property(nonatomic, strong, readwrite) ContentSuggestionsHeaderViewController* headerController; +@property(nonatomic, strong) PrefBackedBoolean* contentSuggestionsVisible; @end @@ -120,10 +121,11 @@ ->GetPrefs(); bool contentSuggestionsEnabled = prefs->GetBoolean(prefs::kArticlesForYouEnabled); - bool contentSuggestionsVisible = - prefs->GetBoolean(feed::prefs::kArticlesListVisible); + self.contentSuggestionsVisible = [[PrefBackedBoolean alloc] + initWithPrefService:prefs + prefName:feed::prefs::kArticlesListVisible]; if (contentSuggestionsEnabled) { - if (contentSuggestionsVisible) { + if ([self.contentSuggestionsVisible value]) { ntp_home::RecordNTPImpression(ntp_home::REMOTE_SUGGESTIONS); } else { ntp_home::RecordNTPImpression(ntp_home::REMOTE_COLLAPSED); @@ -197,9 +199,7 @@ self.contentSuggestionsMediator.commandHandler = self.NTPMediator; self.contentSuggestionsMediator.headerProvider = self.headerController; self.contentSuggestionsMediator.contentArticlesExpanded = - [[PrefBackedBoolean alloc] - initWithPrefService:prefs - prefName:feed::prefs::kArticlesListVisible]; + self.contentSuggestionsVisible; self.headerController.promoCanShow = [self.contentSuggestionsMediator notificationPromo]->CanShow(); @@ -365,6 +365,9 @@ #pragma mark - DiscoverFeedMenuCommands - (void)openDiscoverFeedMenu:(UIView*)menuButton { + [self.alertCoordinator stop]; + self.alertCoordinator = nil; + self.alertCoordinator = [[ActionSheetCoordinator alloc] initWithBaseViewController:self.suggestionsViewController browser:self.browser @@ -373,6 +376,27 @@ rect:menuButton.frame view:menuButton.superview]; __weak ContentSuggestionsCoordinator* weakSelf = self; + + if ([self.contentSuggestionsVisible value]) { + [self.alertCoordinator + addItemWithTitle:l10n_util::GetNSString( + IDS_IOS_DISCOVER_FEED_MENU_TURN_OFF_ITEM) + action:^{ + [weakSelf.contentSuggestionsVisible setValue:NO]; + [weakSelf.contentSuggestionsMediator reloadAllData]; + } + style:UIAlertActionStyleDestructive]; + } else { + [self.alertCoordinator + addItemWithTitle:l10n_util::GetNSString( + IDS_IOS_DISCOVER_FEED_MENU_TURN_ON_ITEM) + action:^{ + [weakSelf.contentSuggestionsVisible setValue:YES]; + [weakSelf.contentSuggestionsMediator reloadAllData]; + } + style:UIAlertActionStyleDefault]; + } + [self.alertCoordinator addItemWithTitle:l10n_util::GetNSString( IDS_IOS_DISCOVER_FEED_MENU_MANAGE_INTERESTS_ITEM)
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.h index 577e40ea..4358af6 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.h
@@ -78,6 +78,9 @@ // Disconnects the mediator. - (void)disconnect; +// Reloads content suggestions. +- (void)reloadAllData; + // The notification promo owned by this mediator. - (NotificationPromoWhatsNew*)notificationPromo;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm index 2926810b..d8ba703 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm
@@ -199,6 +199,10 @@ _prefObserverBridge.reset(); } +- (void)reloadAllData { + [self.dataSink reloadAllData]; +} + - (void)blockMostVisitedURL:(GURL)URL { _mostVisitedSites->AddOrRemoveBlacklistedUrl(URL, true); [self useFreshMostVisited]; @@ -288,7 +292,9 @@ } else if (sectionInfo == self.learnMoreSectionInfo) { [convertedSuggestions addObject:self.learnMoreItem]; } else if (sectionInfo == self.discoverSectionInfo) { - [convertedSuggestions addObject:self.discoverItem]; + if ([self.contentArticlesExpanded value]) { + [convertedSuggestions addObject:self.discoverItem]; + } } else if (!IsDiscoverFeedEnabled()) { ntp_snippets::Category category = [[self categoryWrapperForSectionInfo:sectionInfo] category]; @@ -481,7 +487,7 @@ dispatch_after( dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [self.dataSink reloadAllData]; + [self reloadAllData]; }); } @@ -745,7 +751,7 @@ - (void)onPreferenceChanged:(const std::string&)preferenceName { if (preferenceName == prefs::kArticlesForYouEnabled) { - [self.dataSink reloadAllData]; + [self reloadAllData]; } }
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 21400a2..cf157bae 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -48,7 +48,7 @@ using CSCollectionViewItem = CollectionViewItem<SuggestedContent>; const CGFloat kMostVisitedBottomMargin = 13; const CGFloat kCardBorderRadius = 11; - +const CGFloat kDiscoverFeedContentWith = 430; } NSString* const kContentSuggestionsMostVisitedAccessibilityIdentifierPrefix = @@ -492,8 +492,7 @@ UIEdgeInsets parentInset = [super collectionView:collectionView layout:collectionViewLayout insetForSectionAtIndex:section]; - if ([self.collectionUpdater isHeaderSection:section] || - [self.collectionUpdater isDiscoverSection:section]) { + if ([self.collectionUpdater isHeaderSection:section]) { parentInset.top = 0; parentInset.left = 0; parentInset.right = 0; @@ -506,6 +505,13 @@ if ([self.collectionUpdater isMostVisitedSection:section]) { parentInset.bottom = kMostVisitedBottomMargin; } + } else if ([self.collectionUpdater isDiscoverSection:section]) { + // TODO(crbug.com/1085419): Get card width from Mulder. + CGFloat feedCardWidth = kDiscoverFeedContentWith; + CGFloat margin = + MAX(0, (collectionView.frame.size.width - feedCardWidth) / 2); + parentInset.left = margin; + parentInset.right = margin; } else if (self.styler.cellStyle == MDCCollectionViewCellStyleCard) { CGFloat collectionWidth = collectionView.bounds.size.width; CGFloat maxCardWidth =
diff --git a/ios/chrome/browser/ui/first_run/first_run_egtest.mm b/ios/chrome/browser/ui/first_run/first_run_egtest.mm index 00895d0..9ef1049 100644 --- a/ios/chrome/browser/ui/first_run/first_run_egtest.mm +++ b/ios/chrome/browser/ui/first_run/first_run_egtest.mm
@@ -5,8 +5,8 @@ #include "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" #import "ios/chrome/browser/ui/authentication/signin/signin_constants.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h" #import "ios/chrome/browser/ui/first_run/first_run_app_interface.h" #import "ios/chrome/browser/ui/first_run/first_run_constants.h" #include "ios/chrome/grit/ios_chromium_strings.h" @@ -122,8 +122,8 @@ // Signs in to an account and then taps the Advanced link to go to settings. - (void)testSignInAndTapSettingsLink { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; // Launch First Run and accept tems of services. [FirstRunAppInterface showFirstRunUI]; @@ -141,7 +141,7 @@ [[EarlGrey selectElementWithMatcher:SyncSettingsConfirmButton()] performAction:grey_tap()]; - [SigninEarlGreyUtils checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; GREYAssertTrue([FirstRunAppInterface isSyncFirstSetupComplete], @"Sync should have finished its original setup");
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm index c2e4c30..d7b121c 100644 --- a/ios/chrome/browser/ui/main/scene_controller.mm +++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -79,6 +79,7 @@ #import "ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h" #include "ios/web/public/thread/web_task_traits.h" #import "ios/web/public/web_state.h" +#import "net/base/mac/url_conversions.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -1353,6 +1354,55 @@ dismissOmnibox:dismissOmnibox]; } +- (void)dismissModalsAndOpenMultipleTabsInMode: + (ApplicationModeForTabOpening)targetMode + URLs:(const std::vector<GURL>&)URLs + dismissOmnibox:(BOOL)dismissOmnibox + completion:(ProceduralBlock)completion { + __weak SceneController* weakSelf = self; + + std::vector<GURL> copyURLs = URLs; + + id<BrowserInterface> targetInterface = + [self extractInterfaceBaseOnMode:targetMode]; + + web::WebState* currentWebState = + targetInterface.browser->GetWebStateList()->GetActiveWebState(); + + if (currentWebState) { + web::NavigationManager* navigation_manager = + currentWebState->GetNavigationManager(); + // Check if the current tab is in the procress of restoration and whether it + // is an NTP. If so, add the tabs-opening action to the + // RestoreCompletionCallback queue so that the tabs are opened only after + // the NTP finishes restoring. This is to avoid an edge where multiple tabs + // are trying to open in the middle of NTP restoration, as this will cause + // all tabs trying to load into the same NTP, causing a race condition that + // results in wrong behavior. + if (navigation_manager->IsRestoreSessionInProgress() && + IsURLNtp(currentWebState->GetVisibleURL())) { + navigation_manager->AddRestoreCompletionCallback(base::BindOnce(^{ + [self + dismissModalDialogsWithCompletion:^{ + [weakSelf openMultipleTabsInMode:targetMode + URLs:copyURLs + completion:completion]; + } + dismissOmnibox:dismissOmnibox]; + })); + return; + } + } + + [self + dismissModalDialogsWithCompletion:^{ + [weakSelf openMultipleTabsInMode:targetMode + URLs:copyURLs + completion:completion]; + } + dismissOmnibox:dismissOmnibox]; +} + - (void)openTabFromLaunchWithParams:(URLOpenerParams*)params startupInformation:(id<StartupInformation>)startupInformation appState:(AppState*)appState { @@ -1508,6 +1558,61 @@ ios::GetChromeBrowserProvider()->LogIfModalViewsArePresented(); } +- (void)openMultipleTabsInMode: + (ApplicationModeForTabOpening)tabOpeningTargetMode + URLs:(const std::vector<GURL>&)URLs + completion:(ProceduralBlock)completion { + [self recursiveOpenURLs:URLs + inMode:tabOpeningTargetMode + currentIndex:0 + totalCount:URLs.size() + completion:completion]; +} + +// Call |dismissModalsAndOpenSelectedTabInMode| recursively to open the list of +// URLs contained in |URLs|. Achieved through chaining +// |dismissModalsAndOpenSelectedTabInMode| in its completion handler. +- (void)recursiveOpenURLs:(const std::vector<GURL>&)URLs + inMode:(ApplicationModeForTabOpening)mode + currentIndex:(size_t)currentIndex + totalCount:(size_t)totalCount + completion:(ProceduralBlock)completion { + if (currentIndex >= totalCount) { + if (completion) { + completion(); + } + return; + } + + GURL webpageGURL = URLs.at(currentIndex); + + __weak SceneController* weakSelf = self; + + if (!webpageGURL.is_valid()) { + [self recursiveOpenURLs:URLs + inMode:mode + currentIndex:(currentIndex + 1) + totalCount:totalCount + completion:completion]; + return; + } + + UrlLoadParams param = UrlLoadParams::InNewTab(webpageGURL, webpageGURL); + std::vector<GURL> copyURLs = URLs; + + [self dismissModalsAndOpenSelectedTabInMode:mode + withUrlLoadParams:param + dismissOmnibox:YES + completion:^{ + [weakSelf + recursiveOpenURLs:copyURLs + inMode:mode + currentIndex:(currentIndex + 1) + totalCount:totalCount + completion:completion]; + }]; +} + // Opens a tab in the target BVC, and switches to it in a way that's appropriate // to the current UI, based on the |dismissModals| flag: // - If a modal dialog is showing and |dismissModals| is NO, the selected tab of @@ -1548,7 +1653,6 @@ // Commands are only allowed on NTP. DCHECK(IsURLNtp(urlLoadParams.web_params.url) || !startupCompletion); - ProceduralBlock tabOpenedCompletion = nil; if (startupCompletion && completion) { tabOpenedCompletion = ^{ @@ -1697,7 +1801,6 @@ ->Load(newTabParams); return; } - // Otherwise, load |urlLoadParams| in the current tab. UrlLoadParams sameTabParams = urlLoadParams; sameTabParams.disposition = WindowOpenDisposition::CURRENT_TAB; @@ -1973,6 +2076,28 @@ } } +- (id<BrowserInterface>)extractInterfaceBaseOnMode: + (ApplicationModeForTabOpening)targetMode { + ApplicationMode applicationMode; + + if (targetMode == ApplicationModeForTabOpening::CURRENT) { + applicationMode = self.interfaceProvider.currentInterface.incognito + ? ApplicationMode::INCOGNITO + : ApplicationMode::NORMAL; + } else if (targetMode == ApplicationModeForTabOpening::NORMAL) { + applicationMode = ApplicationMode::NORMAL; + } else { + applicationMode = ApplicationMode::INCOGNITO; + } + + id<BrowserInterface> targetInterface = + applicationMode == ApplicationMode::NORMAL + ? self.interfaceProvider.mainInterface + : self.interfaceProvider.incognitoInterface; + + return targetInterface; +} + #pragma mark - Handling of destroying the incognito BrowserState // The incognito BrowserState should be closed when the last incognito tab is
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm index a36800ce..63da8ca 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
@@ -771,34 +771,58 @@ // Creates the menu items for the search menu. - (void)createSearchMenuItems { - NSMutableArray* items = [NSMutableArray array]; + self.items = @[ [self searchMenuStaticItems] ]; - // The consumer is expecting an array of arrays of items. Each sub array - // represent a section in the popup menu. Having one sub array means having - // all the items in the same section. - PopupMenuToolsItem* copiedContentItem = nil; ClipboardRecentContent* clipboardRecentContent = ClipboardRecentContent::GetInstance(); - if (search_engines::SupportsSearchByImage(self.templateURLService) && - clipboardRecentContent->HasRecentImageFromClipboard()) { - copiedContentItem = CreateTableViewItem( - IDS_IOS_TOOLS_MENU_SEARCH_COPIED_IMAGE, - PopupMenuActionSearchCopiedImage, @"popup_menu_paste_and_go", - kToolsMenuCopiedImageSearch); - } else if (clipboardRecentContent->GetRecentURLFromClipboard()) { - copiedContentItem = CreateTableViewItem( - IDS_IOS_TOOLS_MENU_VISIT_COPIED_LINK, PopupMenuActionPasteAndGo, - @"popup_menu_paste_and_go", kToolsMenuPasteAndGo); - } else if (clipboardRecentContent->GetRecentTextFromClipboard()) { - copiedContentItem = CreateTableViewItem( - IDS_IOS_TOOLS_MENU_SEARCH_COPIED_TEXT, PopupMenuActionPasteAndGo, - @"popup_menu_paste_and_go", kToolsMenuPasteAndGo); - } - if (copiedContentItem) { - [items addObject:@[ copiedContentItem ]]; - } + std::set<ClipboardContentType> clipboard_types; + clipboard_types.insert(ClipboardContentType::URL); + clipboard_types.insert(ClipboardContentType::Text); + clipboard_types.insert(ClipboardContentType::Image); + clipboardRecentContent->HasRecentContentFromClipboard( + clipboard_types, + base::BindOnce(^(std::set<ClipboardContentType> matched_types) { + __block NSMutableArray* items = [NSMutableArray array]; + // The consumer is expecting an array of arrays of items. Each sub array + // represent a section in the popup menu. Having one sub array means + // having all the items in the same section. + PopupMenuToolsItem* copiedContentItem = nil; + if (search_engines::SupportsSearchByImage(self.templateURLService) && + matched_types.find(ClipboardContentType::Image) != + matched_types.end()) { + copiedContentItem = CreateTableViewItem( + IDS_IOS_TOOLS_MENU_SEARCH_COPIED_IMAGE, + PopupMenuActionSearchCopiedImage, @"popup_menu_paste_and_go", + kToolsMenuCopiedImageSearch); + } else if (matched_types.find(ClipboardContentType::URL) != + matched_types.end()) { + copiedContentItem = CreateTableViewItem( + IDS_IOS_TOOLS_MENU_VISIT_COPIED_LINK, PopupMenuActionPasteAndGo, + @"popup_menu_paste_and_go", kToolsMenuPasteAndGo); + } else if (matched_types.find(ClipboardContentType::Text) != + matched_types.end()) { + copiedContentItem = CreateTableViewItem( + IDS_IOS_TOOLS_MENU_SEARCH_COPIED_TEXT, PopupMenuActionPasteAndGo, + @"popup_menu_paste_and_go", kToolsMenuPasteAndGo); + } + if (copiedContentItem) { + [items addObject:@[ copiedContentItem ]]; + } + + [items addObject:[self searchMenuStaticItems]]; + self.items = items; + + dispatch_async(dispatch_get_main_queue(), ^{ + [self.popupMenu setPopupMenuItems:self.items]; + }); + })); +} + +// Creates and returns the search menu items that are static (i.e. always in +// the search menu). +- (NSArray<TableViewItem<PopupMenuItem>*>*)searchMenuStaticItems { PopupMenuToolsItem* QRCodeSearch = CreateTableViewItem( IDS_IOS_TOOLS_MENU_QR_SCANNER, PopupMenuActionQRCodeSearch, @"popup_menu_qr_scanner", kToolsMenuQRCodeSearch); @@ -812,10 +836,7 @@ IDS_IOS_TOOLS_MENU_NEW_INCOGNITO_SEARCH, PopupMenuActionIncognitoSearch, @"popup_menu_new_incognito_tab", kToolsMenuIncognitoSearch); - [items - addObject:@[ newSearch, newIncognitoSearch, voiceSearch, QRCodeSearch ]]; - - self.items = items; + return @[ newSearch, newIncognitoSearch, voiceSearch, QRCodeSearch ]; } // Creates the menu items for the tools menu.
diff --git a/ios/chrome/browser/ui/popup_menu/public/popup_menu_presenter.mm b/ios/chrome/browser/ui/popup_menu/public/popup_menu_presenter.mm index 49e36dfd..176e9c8 100644 --- a/ios/chrome/browser/ui/popup_menu/public/popup_menu_presenter.mm +++ b/ios/chrome/browser/ui/popup_menu/public/popup_menu_presenter.mm
@@ -33,6 +33,11 @@ @property(nonatomic, strong) NSArray<NSLayoutConstraint*>* initialConstraints; // Constraints used for the positioning of the popup when presented. @property(nonatomic, strong) NSArray<NSLayoutConstraint*>* presentedConstraints; + +@property(nonatomic, strong) + NSLayoutConstraint* presentedViewControllerHeightConstraint; +@property(nonatomic, strong) + NSLayoutConstraint* presentedViewControllerWidthConstraint; @end @implementation PopupMenuPresenter @@ -67,35 +72,30 @@ // itself. [self.presentedViewController.view setNeedsLayout]; [self.presentedViewController.view layoutIfNeeded]; - CGSize fittingSize = [self.presentedViewController.view - sizeThatFits:CGSizeMake(kMaxWidth, kMaxHeight)]; - // Use preferredSize if it is set. - CGSize preferredSize = self.presentedViewController.preferredContentSize; - CGFloat width = fittingSize.width; - CGFloat height = fittingSize.height; - if (!CGSizeEqualToSize(preferredSize, CGSizeZero)) { - width = preferredSize.width; - height = preferredSize.height; - } // Set the sizing constraints, in case the UIViewController is using a // UIScrollView. The priority needs to be non-required to allow downsizing if // needed, and more than UILayoutPriorityDefaultHigh to take precedence on // compression resistance. - NSLayoutConstraint* widthConstraint = + self.presentedViewControllerWidthConstraint = [self.presentedViewController.view.widthAnchor - constraintEqualToConstant:width]; - widthConstraint.priority = UILayoutPriorityDefaultHigh + 1; + constraintEqualToConstant:0]; + self.presentedViewControllerWidthConstraint.priority = + UILayoutPriorityDefaultHigh + 1; - NSLayoutConstraint* heightConstraint = + self.presentedViewControllerHeightConstraint = [self.presentedViewController.view.heightAnchor - constraintEqualToConstant:height]; - heightConstraint.priority = UILayoutPriorityDefaultHigh + 1; + constraintEqualToConstant:0]; + self.presentedViewControllerHeightConstraint.priority = + UILayoutPriorityDefaultHigh + 1; + + // Set the constraint constants to their correct intial values. + [self setPresentedViewControllerConstraintConstants]; UIView* popup = self.popupViewController.contentContainer; [NSLayoutConstraint activateConstraints:@[ - widthConstraint, - heightConstraint, + self.presentedViewControllerWidthConstraint, + self.presentedViewControllerHeightConstraint, [popup.heightAnchor constraintLessThanOrEqualToConstant:kMaxHeight], [popup.widthAnchor constraintLessThanOrEqualToConstant:kMaxWidth], [popup.widthAnchor constraintGreaterThanOrEqualToConstant:kMinWidth], @@ -238,6 +238,23 @@ ]; } +// Updates the constants for the constraints constraining the presented view +// controller's height and width. +- (void)setPresentedViewControllerConstraintConstants { + CGSize fittingSize = [self.presentedViewController.view + sizeThatFits:CGSizeMake(kMaxWidth, kMaxHeight)]; + // Use preferredSize if it is set. + CGSize preferredSize = self.presentedViewController.preferredContentSize; + CGFloat width = fittingSize.width; + CGFloat height = fittingSize.height; + if (!CGSizeEqualToSize(preferredSize, CGSizeZero)) { + width = preferredSize.width; + height = preferredSize.height; + } + self.presentedViewControllerHeightConstraint.constant = height; + self.presentedViewControllerWidthConstraint.constant = width; +} + #pragma mark - PopupMenuViewControllerDelegate - (void)popupMenuViewControllerWillDismiss: @@ -245,4 +262,19 @@ [self.delegate popupMenuPresenterWillDismiss:self]; } +- (void)containedViewControllerContentSizeChangedForPopupMenuViewController: + (PopupMenuViewController*)viewController { + // Set the frame of the table view to the maximum width to have the label + // resizing correctly. + CGRect frame = self.presentedViewController.view.frame; + frame.size.width = kMaxWidth; + self.presentedViewController.view.frame = frame; + // It is necessary to do a first layout pass so the table view can size + // itself. + [self.presentedViewController.view setNeedsLayout]; + [self.presentedViewController.view layoutIfNeeded]; + + [self setPresentedViewControllerConstraintConstants]; +} + @end
diff --git a/ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller.mm b/ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller.mm index 8c360e0..7ccb96ef 100644 --- a/ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller.mm +++ b/ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller.mm
@@ -130,6 +130,7 @@ } } [self.tableView reloadData]; + self.preferredContentSize = [self calculatePreferredContentSize]; } - (void)itemsHaveChanged:(NSArray<TableViewItem<PopupMenuItem>*>*)items { @@ -166,7 +167,13 @@ } } -- (CGSize)preferredContentSize { +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + self.preferredContentSize = [self calculatePreferredContentSize]; +} + +- (CGSize)calculatePreferredContentSize { CGFloat width = 0; CGFloat height = 0; for (NSInteger section = 0; section < [self.tableViewModel numberOfSections];
diff --git a/ios/chrome/browser/ui/popup_menu/public/popup_menu_view_controller.h b/ios/chrome/browser/ui/popup_menu/public/popup_menu_view_controller.h index 3e0a269..2b230999 100644 --- a/ios/chrome/browser/ui/popup_menu/public/popup_menu_view_controller.h +++ b/ios/chrome/browser/ui/popup_menu/public/popup_menu_view_controller.h
@@ -8,7 +8,6 @@ #import <UIKit/UIKit.h> @protocol PopupMenuViewControllerDelegate; -@protocol PopupMenuViewControllerDelegate; // ViewController displaying a popup for a menu. The view of this controller is // a transparent scrim, dismissing the popup if tapped.
diff --git a/ios/chrome/browser/ui/popup_menu/public/popup_menu_view_controller.mm b/ios/chrome/browser/ui/popup_menu/public/popup_menu_view_controller.mm index 165beb7..3d811950 100644 --- a/ios/chrome/browser/ui/popup_menu/public/popup_menu_view_controller.mm +++ b/ios/chrome/browser/ui/popup_menu/public/popup_menu_view_controller.mm
@@ -84,4 +84,10 @@ [self.delegate popupMenuViewControllerWillDismiss:self]; } +- (void)preferredContentSizeDidChangeForChildContentContainer: + (id<UIContentContainer>)container { + [self.delegate + containedViewControllerContentSizeChangedForPopupMenuViewController:self]; +} + @end
diff --git a/ios/chrome/browser/ui/popup_menu/public/popup_menu_view_controller_delegate.h b/ios/chrome/browser/ui/popup_menu/public/popup_menu_view_controller_delegate.h index 61994689..8a3409e 100644 --- a/ios/chrome/browser/ui/popup_menu/public/popup_menu_view_controller_delegate.h +++ b/ios/chrome/browser/ui/popup_menu/public/popup_menu_view_controller_delegate.h
@@ -16,6 +16,9 @@ - (void)popupMenuViewControllerWillDismiss: (PopupMenuViewController*)viewController; +- (void)containedViewControllerContentSizeChangedForPopupMenuViewController: + (PopupMenuViewController*)viewController; + @end #endif // IOS_CHROME_BROWSER_UI_POPUP_MENU_PUBLIC_POPUP_MENU_VIEW_CONTROLLER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm index 1d90351..a06e18bd 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm
@@ -8,8 +8,8 @@ #include "base/ios/ios_util.h" #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_constants.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h" #import "ios/chrome/browser/ui/history/history_ui_constants.h" #import "ios/chrome/browser/ui/list_model/list_model.h" #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_constants.h" @@ -162,13 +162,13 @@ // Sign-in promo should be visible with cold state. [SigninEarlGreyUI checkSigninPromoVisibleWithMode:SigninPromoViewModeColdState closeButton:NO]; - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; // Sign-in promo should be visible with warm state. [SigninEarlGreyUI checkSigninPromoVisibleWithMode:SigninPromoViewModeWarmState closeButton:NO]; [self closeRecentTabs]; - [SigninEarlGreyUtils removeFakeIdentity:fakeIdentity]; + [SigninEarlGrey removeFakeIdentity:fakeIdentity]; } // Tests that the sign-in promo can be reloaded correctly while being hidden. @@ -189,8 +189,8 @@ [SigninEarlGreyUI checkSigninPromoNotVisible]; // Add an account. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; // Tap on "Other Devices", to show the sign-in promo. [[EarlGrey selectElementWithMatcher:otherDevicesMatcher] @@ -198,7 +198,7 @@ [SigninEarlGreyUI checkSigninPromoVisibleWithMode:SigninPromoViewModeWarmState closeButton:NO]; [self closeRecentTabs]; - [SigninEarlGreyUtils removeFakeIdentity:fakeIdentity]; + [SigninEarlGrey removeFakeIdentity:fakeIdentity]; } // Tests that the VC can be dismissed by swiping down. @@ -234,7 +234,7 @@ // Tests that the Recent Tabs can be opened while signed in (prevent regression // for https://crbug.com/1056613). - (void)testOpenWhileSignedIn { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; OpenRecentTabsPanel();
diff --git a/ios/chrome/browser/ui/settings/google_services/accounts_table_egtest.mm b/ios/chrome/browser/ui/settings/google_services/accounts_table_egtest.mm index ce9e3813..d774aea7 100644 --- a/ios/chrome/browser/ui/settings/google_services/accounts_table_egtest.mm +++ b/ios/chrome/browser/ui/settings/google_services/accounts_table_egtest.mm
@@ -5,8 +5,8 @@ #import <UIKit/UIKit.h> #import "base/test/scoped_feature_list.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_ui.h" #import "ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller_constants.h" @@ -76,7 +76,7 @@ // Tests that the Sync and Account Settings screen are correctly popped if the // signed in account is removed. - (void)testSignInPopUpAccountOnSyncSettings { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; // Sign In |identity|, then open the Sync Settings. [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; @@ -85,11 +85,11 @@ // Forget |fakeIdentity|, screens should be popped back to the Main Settings. [ChromeEarlGreyUI waitForAppToIdle]; - [SigninEarlGreyUtils forgetFakeIdentity:fakeIdentity]; + [SigninEarlGrey forgetFakeIdentity:fakeIdentity]; [[EarlGrey selectElementWithMatcher:PrimarySignInButton()] assertWithMatcher:grey_sufficientlyVisible()]; - [SigninEarlGreyUtils checkSignedOut]; + [SigninEarlGrey checkSignedOut]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; @@ -98,8 +98,8 @@ // Tests that the Account Settings screen is correctly popped if the signed in // account is removed while the "Disconnect Account" dialog is up. - (void)testSignInPopUpAccountOnDisconnectAccount { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; // Sign In |fakeIdentity|, then open the Account Settings. [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; @@ -109,11 +109,11 @@ // Forget |fakeIdentity|, screens should be popped back to the Main Settings. [ChromeEarlGreyUI waitForAppToIdle]; - [SigninEarlGreyUtils forgetFakeIdentity:fakeIdentity]; + [SigninEarlGrey forgetFakeIdentity:fakeIdentity]; [[EarlGrey selectElementWithMatcher:PrimarySignInButton()] assertWithMatcher:grey_sufficientlyVisible()]; - [SigninEarlGreyUtils checkSignedOut]; + [SigninEarlGrey checkSignedOut]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; @@ -122,9 +122,9 @@ // Tests that the Account Settings screen is correctly reloaded when one of // the non-primary account is removed. - (void)testSignInReloadOnRemoveAccount { - FakeChromeIdentity* fakeIdentity1 = [SigninEarlGreyUtils fakeIdentity1]; - FakeChromeIdentity* fakeIdentity2 = [SigninEarlGreyUtils fakeIdentity2]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity2]; + FakeChromeIdentity* fakeIdentity1 = [SigninEarlGrey fakeIdentity1]; + FakeChromeIdentity* fakeIdentity2 = [SigninEarlGrey fakeIdentity2]; + [SigninEarlGrey addFakeIdentity:fakeIdentity2]; // Sign In |fakeIdentity|, then open the Account Settings. [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity1]; @@ -148,7 +148,7 @@ fakeIdentity2.userEmail), grey_sufficientlyVisible(), nil)] assertWithMatcher:grey_nil()]; - [SigninEarlGreyUtils checkSignedInWithFakeIdentity:fakeIdentity1]; + [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity1]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; @@ -157,7 +157,7 @@ // Tests that the Account Settings screen is popped and the user signed out // when the account is removed. - (void)testSignOutOnRemoveAccount { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; // Sign In |fakeIdentity|, then open the Account Settings. [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; @@ -177,7 +177,7 @@ // Check that the user is signed out and the Main Settings screen is shown. [[EarlGrey selectElementWithMatcher:PrimarySignInButton()] assertWithMatcher:grey_sufficientlyVisible()]; - [SigninEarlGreyUtils checkSignedOut]; + [SigninEarlGrey checkSignedOut]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; @@ -186,7 +186,7 @@ // Tests that selecting sign-out from a non-managed account keeps the user's // synced data. - (void)testSignOutFromNonManagedAccountKeepsData { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; // Sign In |fakeIdentity|. [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; @@ -212,7 +212,7 @@ // Tests that selecting sign-out and clear data from a non-managed user account // clears the user's synced data. - (void)testSignOutAndClearDataFromNonManagedAccountClearsData { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; // Sign In |fakeIdentity|. [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; @@ -237,7 +237,7 @@ // Tests that signing out from a managed user account clears the user's data. - (void)testsSignOutFromManagedAccount { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeManagedIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeManagedIdentity]; // Sign In |fakeIdentity|. [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity isManagedAccount:YES]; @@ -270,7 +270,7 @@ #define MAYBE_testSignInDisconnectCancelled testSignInDisconnectCancelled #endif - (void)MAYBE_testSignInDisconnectCancelled { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; // Sign In |fakeIdentity|, then open the Account Settings. [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; @@ -290,7 +290,7 @@ [[EarlGrey selectElementWithMatcher:chrome_test_util:: SettingsAccountsCollectionView()] assertWithMatcher:grey_sufficientlyVisible()]; - [SigninEarlGreyUtils checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()];
diff --git a/ios/chrome/browser/ui/settings/google_services/google_services_settings_egtest.mm b/ios/chrome/browser/ui/settings/google_services/google_services_settings_egtest.mm index eba276b..bdf384a80 100644 --- a/ios/chrome/browser/ui/settings/google_services/google_services_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/google_services/google_services_settings_egtest.mm
@@ -5,8 +5,8 @@ #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" #include "components/safe_browsing/core/features.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h" #import "ios/chrome/browser/ui/settings/google_services/google_services_settings_app_interface.h" #import "ios/chrome/browser/ui/settings/google_services/google_services_settings_constants.h" #import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_constants.h" @@ -91,12 +91,12 @@ // Regression test for crbug.com/1033901 - (void)testRemovePrimaryAccount { // Signin. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Open "Google Services" settings. [self openGoogleServicesSettings]; // Remove the primary account. - [SigninEarlGreyUtils forgetFakeIdentity:fakeIdentity]; + [SigninEarlGrey forgetFakeIdentity:fakeIdentity]; // Assert the UI has been reloaded by testing for the signin cell being // visible. id<GREYMatcher> signinCellMatcher = @@ -122,8 +122,8 @@ [GoogleServicesSettingsAppInterface unblockAllNavigationRequestsForCurrentWebState]; }]; - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; // Open "Google Services" settings. [self openGoogleServicesSettings]; // Open sign-in. @@ -163,7 +163,7 @@ // See: crbug.com/1076843 - (void)testOpenSSOAddAccount { // Signin. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Open "Google Services" settings. [self openGoogleServicesSettings]; @@ -234,7 +234,7 @@ forUserPref:password_manager::prefs::kPasswordLeakDetectionEnabled]; // Sign in. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Open "Google Services" settings. [self openGoogleServicesSettings]; @@ -294,7 +294,7 @@ forUserPref:password_manager::prefs::kPasswordLeakDetectionEnabled]; // Sign in. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Open "Google Services" settings. [self openGoogleServicesSettings];
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_unittest.mm index afde54e6..7d91e77 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_unittest.mm
@@ -185,19 +185,15 @@ // Tests that password is shown/hidden. TEST_F(PasswordDetailsViewControllerTest, TestShowHidePassword) { - // TODO(crbug.com/1111183): Investigate why this is failing on iOS14. - if (base::ios::IsRunningOnIOS14OrLater()) { - return; - } SetPassword(); - CheckEditCellText(kMaskedPassword, 0, 2); NSIndexPath* indexOfPassword = [NSIndexPath indexPathForRow:2 inSection:0]; TableViewTextEditCell* textFieldCell = - base::mac::ObjCCastStrict<TableViewTextEditCell>( - [controller().tableView cellForRowAtIndexPath:indexOfPassword]); - ASSERT_TRUE(textFieldCell != nil); + base::mac::ObjCCastStrict<TableViewTextEditCell>([controller() + tableView:controller().tableView + cellForRowAtIndexPath:indexOfPassword]); + EXPECT_TRUE(textFieldCell); [textFieldCell.identifyingIconButton sendActionsForControlEvents:UIControlEventTouchUpInside]; @@ -213,11 +209,6 @@ // Tests that passwords was not shown in case reauth failed. TEST_F(PasswordDetailsViewControllerTest, TestShowPasswordReauthFailed) { - // TODO(crbug.com/1111183): Investigate why this is failing on iOS14. - if (base::ios::IsRunningOnIOS14OrLater()) { - return; - } - SetPassword(); CheckEditCellText(kMaskedPassword, 0, 2); @@ -225,9 +216,10 @@ reauth().expectedResult = ReauthenticationResult::kFailure; NSIndexPath* indexOfPassword = [NSIndexPath indexPathForRow:2 inSection:0]; TableViewTextEditCell* textFieldCell = - base::mac::ObjCCastStrict<TableViewTextEditCell>( - [controller().tableView cellForRowAtIndexPath:indexOfPassword]); - ASSERT_TRUE(textFieldCell != nil); + base::mac::ObjCCastStrict<TableViewTextEditCell>([controller() + tableView:controller().tableView + cellForRowAtIndexPath:indexOfPassword]); + EXPECT_TRUE(textFieldCell); [textFieldCell.identifyingIconButton sendActionsForControlEvents:UIControlEventTouchUpInside];
diff --git a/ios/chrome/browser/ui/settings/password/passwords_mediator.mm b/ios/chrome/browser/ui/settings/password/passwords_mediator.mm index d9e9a04..522aec4 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_mediator.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_mediator.mm
@@ -160,6 +160,11 @@ - (void)compromisedCredentialsDidChange: (password_manager::CompromisedCredentialsManager::CredentialsView) credentials { + // Compromised passwords changes has no effect on UI while check is running. + if (_passwordCheckManager->GetPasswordCheckState() == + PasswordCheckState::kRunning) + return; + DCHECK(self.consumer); [self.consumer setPasswordCheckUIState: [self computePasswordCheckUIStateWith:_currentState]];
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm index 920b9a7..3f9b81d 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
@@ -259,6 +259,9 @@ // The loading spinner background which appears when loading passwords. @property(nonatomic, strong) HomeWaitingView* spinnerView; +// Current state of the Password Check. +@property(nonatomic, assign) PasswordCheckUIState passwordCheckState; + @end @implementation PasswordsTableViewController @@ -439,16 +442,16 @@ password_manager::features::kPasswordCheck)) { // Password check. [model addSectionWithIdentifier:SectionIdentifierPasswordCheck]; - if (!_passwordProblemsItem) { - _passwordProblemsItem = [self passwordProblemsItem]; - } + _passwordProblemsItem = [self passwordProblemsItem]; + [model addItem:_passwordProblemsItem toSectionWithIdentifier:SectionIdentifierPasswordCheck]; - if (!_checkForProblemsItem) { - _checkForProblemsItem = [self checkForProblemsItem]; - } + _checkForProblemsItem = [self checkForProblemsItem]; + [model addItem:_checkForProblemsItem toSectionWithIdentifier:SectionIdentifierPasswordCheck]; + [self updatePasswordCheckButtonWithState:_passwordCheckState]; + [self updatePasswordCheckStatusLabelWithState:_passwordCheckState]; } // Saved passwords. @@ -700,6 +703,7 @@ #pragma mark - PasswordsConsumer - (void)setPasswordCheckUIState:(PasswordCheckUIState)state { + _passwordCheckState = state; [self updatePasswordCheckButtonWithState:state]; [self updatePasswordCheckStatusLabelWithState:state]; }
diff --git a/ios/chrome/browser/ui/settings/signin_settings_egtest.mm b/ios/chrome/browser/ui/settings/signin_settings_egtest.mm index 624ab85..95a46c7 100644 --- a/ios/chrome/browser/ui/settings/signin_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/signin_settings_egtest.mm
@@ -4,8 +4,8 @@ #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_constants.h" #import "ios/chrome/browser/ui/authentication/signin/signin_constants.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h" #import "ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h" #import "ios/chrome/browser/ui/settings/signin_settings_app_interface.h" #include "ios/chrome/grit/ios_strings.h" @@ -55,8 +55,8 @@ // Tests signing in, using the primary button with a warm state. - (void)testSignInPromoWithWarmStateUsingPrimaryButton { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [ChromeEarlGreyUI openSettingsMenu]; [SigninEarlGreyUI @@ -65,7 +65,7 @@ [SigninEarlGreyUI confirmSigninConfirmationDialog]; // User signed in. - [SigninEarlGreyUtils checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; [SigninEarlGreyUI checkSigninPromoNotVisible]; [[EarlGrey selectElementWithMatcher:SettingsAccountButton()] assertWithMatcher:grey_interactable()]; @@ -73,8 +73,8 @@ // Tests signing in, using the secondary button with a warm state. - (void)testSignInPromoWithWarmStateUsingSecondaryButton { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; - [SigninEarlGreyUtils addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [ChromeEarlGreyUI openSettingsMenu]; [SigninEarlGreyUI @@ -84,7 +84,7 @@ [SigninEarlGreyUI confirmSigninConfirmationDialog]; // User signed in. - [SigninEarlGreyUtils checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; [SigninEarlGreyUI checkSigninPromoNotVisible]; [[EarlGrey selectElementWithMatcher:SettingsAccountButton()] assertWithMatcher:grey_interactable()];
diff --git a/ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller_egtest.mm b/ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller_egtest.mm index 0f21000..a320b72 100644 --- a/ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller_egtest.mm +++ b/ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller_egtest.mm
@@ -3,8 +3,8 @@ // found in the LICENSE file. #import <UIKit/UIKit.h> +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h" #import "ios/chrome/grit/ios_strings.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" @@ -28,7 +28,7 @@ - (void)testShowSyncPassphraseAndDismiss { [ChromeEarlGrey addBookmarkWithSyncPassphrase:@"hello"]; // Signin. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyUtils fakeIdentity1]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey openNewTab]; [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId(
diff --git a/ios/chrome/browser/ui/settings/sync/utils/sync_fake_server_egtest.mm b/ios/chrome/browser/ui/settings/sync/utils/sync_fake_server_egtest.mm index 34184c9..7763918 100644 --- a/ios/chrome/browser/ui/settings/sync/utils/sync_fake_server_egtest.mm +++ b/ios/chrome/browser/ui/settings/sync/utils/sync_fake_server_egtest.mm
@@ -4,8 +4,8 @@ #include "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" -#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_matchers.h" @@ -69,9 +69,8 @@ [BookmarkEarlGrey addBookmarkWithTitle:@"foo" URL:@"https://www.foo.com"]; // Sign in to sync, after a bookmark has been added. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Assert that the correct number of bookmarks have been synced. @@ -81,9 +80,8 @@ // Tests that a bookmark added on the client is uploaded to the Sync server. - (void)testSyncUploadBookmark { - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Add a bookmark after sync is initialized. @@ -100,9 +98,8 @@ [ChromeEarlGrey addFakeSyncServerBookmarkWithURL:URL title:"hoo"]; // Sign in to sync, after a bookmark has been injected in the sync server. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; [BookmarkEarlGrey verifyBookmarksWithTitle:@"hoo" expectedCount:1]; @@ -111,9 +108,8 @@ // Tests that the local cache guid does not change when sync is restarted. - (void)testSyncCheckSameCacheGuid_SyncRestarted { // Sign in the fake identity. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; @@ -133,16 +129,15 @@ // signs back in with the same account. - (void)testSyncCheckDifferentCacheGuid_SignOutAndSignIn { // Sign in a fake identity, and store the initial sync guid. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; std::string original_guid = [ChromeEarlGrey syncCacheGUID]; - GREYAssert([SigninEarlGreyUtilsAppInterface isAuthenticated], + GREYAssert([SigninEarlGreyAppInterface isAuthenticated], @"User is not signed in."); - [SigninEarlGreyUtilsAppInterface signOut]; + [SigninEarlGreyAppInterface signOut]; [ChromeEarlGrey waitForSyncInitialized:NO syncTimeout:kSyncOperationTimeout]; // Sign the user back in, and verify the guid has changed. @@ -158,15 +153,14 @@ // Test for http://crbug.com/413611 . - (void)testSyncCheckSameCacheGuid_SyncRestartedAfterSignOutAndSignIn { // Sign in a fake idenitty. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; - GREYAssert([SigninEarlGreyUtilsAppInterface isAuthenticated], + GREYAssert([SigninEarlGreyAppInterface isAuthenticated], @"User is not signed in."); - [SigninEarlGreyUtilsAppInterface signOut]; + [SigninEarlGreyAppInterface signOut]; [ChromeEarlGrey waitForSyncInitialized:NO syncTimeout:kSyncOperationTimeout]; // Sign the user back in. @@ -199,9 +193,8 @@ }]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Verify that the autofill profile has been downloaded. @@ -228,9 +221,8 @@ }]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Verify that the autofill profile has been downloaded. @@ -274,9 +266,8 @@ }]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Verify that the autofill profile has been downloaded @@ -315,9 +306,8 @@ [ChromeEarlGrey loadURL:URL2]; // Sign in to sync, after opening two tabs. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Verify the sessions on the sync server. @@ -343,9 +333,8 @@ [ChromeEarlGrey addHistoryServiceTypedURL:mockURL]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; @@ -371,9 +360,8 @@ [ChromeEarlGrey addFakeSyncServerTypedURL:mockURL]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; @@ -398,9 +386,8 @@ [ChromeEarlGrey addFakeSyncServerTypedURL:mockURL]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; @@ -433,9 +420,8 @@ [ChromeEarlGrey addHistoryServiceTypedURL:mockURL]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; @@ -476,9 +462,8 @@ originator_client_item_id:"1"]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = - [SigninEarlGreyUtilsAppInterface fakeIdentity1]; - [SigninEarlGreyUtilsAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; + [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout];
diff --git a/ios/chrome/browser/ui/ui_feature_flags.h b/ios/chrome/browser/ui/ui_feature_flags.h index 43015dc..0e3a27897 100644 --- a/ios/chrome/browser/ui/ui_feature_flags.h +++ b/ios/chrome/browser/ui/ui_feature_flags.h
@@ -65,8 +65,8 @@ // Feature flag to enable new illustrations and UI on empty states. extern const base::Feature kIllustratedEmptyStates; -// Feature flag to enable Shared Highlighting (Text Fragments/scroll-to-text -// and Link to Text features). +// Feature flag to enable Shared Highlighting (Link to Text). Also enable +// kScrollToTextIOS to successfully open these links. extern const base::Feature kSharedHighlightingIOS; // Feature flag that enables taking fullpage screenshots of a webpage.
diff --git a/ios/chrome/browser/url_loading/scene_url_loading_service.h b/ios/chrome/browser/url_loading/scene_url_loading_service.h index 40e80da..c244b56 100644 --- a/ios/chrome/browser/url_loading/scene_url_loading_service.h +++ b/ios/chrome/browser/url_loading/scene_url_loading_service.h
@@ -37,6 +37,14 @@ withUrlLoadParams:(const UrlLoadParams&)urlLoadParams completion:(ProceduralBlock)completion; +// Open the list of URLs contained in |URLs| in mode specified by +// |tabOpeningTargetMode|. |completion| is executed after all the tabs are +// opened. +- (void)openMultipleTabsInMode: + (ApplicationModeForTabOpening)tabOpeningTargetMode + URLs:(const std::vector<GURL>&)URLs + completion:(ProceduralBlock)completion; + // Opens a new tab as if originating from |originPoint| and |focusOmnibox|. - (void)openNewTabFromOriginPoint:(CGPoint)originPoint focusOmnibox:(BOOL)focusOmnibox;
diff --git a/ios/chrome/browser/web/error_page_util.mm b/ios/chrome/browser/web/error_page_util.mm index ab4bcac..1c2e46d63a 100644 --- a/ios/chrome/browser/web/error_page_util.mm +++ b/ios/chrome/browser/web/error_page_util.mm
@@ -12,7 +12,6 @@ #include "base/strings/sys_string_conversions.h" #include "base/values.h" #include "components/error_page/common/error.h" -#include "components/error_page/common/error_page_params.h" #include "components/error_page/common/localized_error.h" #include "components/grit/components_resources.h" #include "ios/chrome/browser/application_context.h" @@ -57,8 +56,7 @@ /*offline_content_feature_enabled=*/false, /*auto_fetch_feature_enabled=*/false, /*is_kiosk_mode=*/false, - GetApplicationContext()->GetApplicationLocale(), - /*params=*/nullptr); + GetApplicationContext()->GetApplicationLocale()); ui::ScaleFactor scale_factor = ui::ResourceBundle::GetSharedInstance().GetMaxScaleFactor();
diff --git a/ios/chrome/search_widget_extension/copied_content_view.h b/ios/chrome/search_widget_extension/copied_content_view.h index 53cb519..51e0ed0e 100644 --- a/ios/chrome/search_widget_extension/copied_content_view.h +++ b/ios/chrome/search_widget_extension/copied_content_view.h
@@ -30,8 +30,7 @@ - (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; -- (void)setCopiedContentType:(CopiedContentType)type - copiedText:(NSString*)copiedText; +- (void)setCopiedContentType:(CopiedContentType)type; @end
diff --git a/ios/chrome/search_widget_extension/copied_content_view.mm b/ios/chrome/search_widget_extension/copied_content_view.mm index 426a05b6..b2188bd4 100644 --- a/ios/chrome/search_widget_extension/copied_content_view.mm +++ b/ios/chrome/search_widget_extension/copied_content_view.mm
@@ -24,8 +24,6 @@ // The type of the copied content @property(nonatomic) CopiedContentType type; -// The copied text to be displayed if the type supports showing the string. -@property(nonatomic, copy) NSString* copiedText; // The copied URL label containing the URL or a placeholder text. @property(nonatomic, strong) UILabel* copiedContentLabel; // The copied URL title label containing the title of the copied URL button. @@ -38,7 +36,7 @@ @property(nonatomic, strong) UIVisualEffectView* primaryEffectView; @property(nonatomic, strong) UIVisualEffectView* secondaryEffectView; -// Updates the view to show the currently set |type| and |copiedText|. +// Updates the view to show the currently set |type|. - (void)updateUI; @end @@ -173,7 +171,7 @@ [_copiedContentLabel.trailingAnchor constraintEqualToAnchor:_openCopiedContentTitleLabel.trailingAnchor], ]]; - [self setCopiedContentType:CopiedContentTypeNone copiedText:nil]; + [self setCopiedContentType:CopiedContentTypeNone]; self.highlightableViews = @[ _hairlineView, _copiedButtonView, _openCopiedContentTitleLabel, _copiedContentLabel @@ -182,10 +180,8 @@ return self; } -- (void)setCopiedContentType:(CopiedContentType)type - copiedText:(NSString*)copiedText { +- (void)setCopiedContentType:(CopiedContentType)type { self.type = type; - self.copiedText = copiedText; [self updateUI]; } @@ -224,12 +220,10 @@ } case CopiedContentTypeURL: { titleText = NSLocalizedString(@"IDS_IOS_OPEN_COPIED_LINK", nil); - contentText = self.copiedText; break; } case CopiedContentTypeString: { titleText = NSLocalizedString(@"IDS_IOS_OPEN_COPIED_TEXT", nil); - contentText = self.copiedText; break; } case CopiedContentTypeImage: {
diff --git a/ios/chrome/search_widget_extension/search_widget_view.h b/ios/chrome/search_widget_extension/search_widget_view.h index e1b8faf..80f99e1 100644 --- a/ios/chrome/search_widget_extension/search_widget_view.h +++ b/ios/chrome/search_widget_extension/search_widget_view.h
@@ -44,10 +44,8 @@ // Gets the height of the widget. - (CGFloat)widgetHeight; -// Sets the copied content type. |copiedText| should be provided if the content -// type requires textual data, otherwise it should be nil. -- (void)setCopiedContentType:(CopiedContentType)type - copiedText:(NSString*)copiedText; +// Sets the copied content type. +- (void)setCopiedContentType:(CopiedContentType)type; @end
diff --git a/ios/chrome/search_widget_extension/search_widget_view.mm b/ios/chrome/search_widget_extension/search_widget_view.mm index ae61caf..49d9991 100644 --- a/ios/chrome/search_widget_extension/search_widget_view.mm +++ b/ios/chrome/search_widget_extension/search_widget_view.mm
@@ -210,9 +210,8 @@ return [self actionContentHeight] + [self copiedURLSectionHeight]; } -- (void)setCopiedContentType:(CopiedContentType)type - copiedText:(NSString*)copiedText { - [self.copiedURLSection setCopiedContentType:type copiedText:copiedText]; +- (void)setCopiedContentType:(CopiedContentType)type { + [self.copiedURLSection setCopiedContentType:type]; } @end
diff --git a/ios/chrome/search_widget_extension/search_widget_view_controller.mm b/ios/chrome/search_widget_extension/search_widget_view_controller.mm index 3f33f01..cbf9c36 100644 --- a/ios/chrome/search_widget_extension/search_widget_view_controller.mm +++ b/ios/chrome/search_widget_extension/search_widget_view_controller.mm
@@ -23,8 +23,6 @@ @interface SearchWidgetViewController ()<SearchWidgetViewActionTarget> @property(nonatomic, weak) SearchWidgetView* widgetView; -@property(nonatomic, strong, nullable) NSString* copiedText; -@property(nonatomic, strong, nullable) UIImage* copiedImage; @property(nonatomic) CopiedContentType copiedContentType; @property(nonatomic, strong) ClipboardRecentContentImplIOS* clipboardRecentContent; @@ -96,13 +94,26 @@ - (void)widgetPerformUpdateWithCompletionHandler: (void (^)(NCUpdateResult))completionHandler { - completionHandler([self updateWidget] ? NCUpdateResultNewData - : NCUpdateResultNoData); + [self updateWidgetWithCompletionHandler:^(BOOL updates) { + completionHandler(updates ? NCUpdateResultNewData : NCUpdateResultNoData); + }]; } -// Updates the widget with latest data from the clipboard. Returns whether any -// visual updates occurred. -- (BOOL)updateWidget { +- (void)updateWidget { + [self updateWidgetWithCompletionHandler:^(BOOL updates) { + if (updates && self.extensionContext.widgetActiveDisplayMode == + NCWidgetDisplayModeExpanded) { + CGSize maxSize = [self.extensionContext + widgetMaximumSizeForDisplayMode:NCWidgetDisplayModeExpanded]; + self.preferredContentSize = + CGSizeMake(maxSize.width, [self.widgetView widgetHeight]); + } + }]; +} + +// Updates the widget with latest data from the clipboard. Calls completion +// handler with whether any updates occured.. +- (void)updateWidgetWithCompletionHandler:(void (^)(BOOL))completionHandler { NSUserDefaults* sharedDefaults = app_group::GetGroupUserDefaults(); NSString* fieldTrialKey = base::SysUTF8ToNSString(app_group::kChromeExtensionFieldTrialPreference); @@ -113,35 +124,25 @@ self.supportsSearchByImage = [sharedDefaults boolForKey:supportsSearchByImageKey]; - NSString* copiedText; - UIImage* copiedImage; - CopiedContentType type = CopiedContentTypeNone; + NSSet* wantedTypes = [NSSet + setWithArray:@[ ContentTypeURL, ContentTypeText, ContentTypeImage ]]; - if (UIImage* image = [self getCopiedImageFromClipboard]) { - copiedImage = image; - type = CopiedContentTypeImage; - } else if (NSURL* url = - [self.clipboardRecentContent recentURLFromClipboard]) { - copiedText = url.absoluteString; - type = CopiedContentTypeURL; - } else if (NSString* text = - [self.clipboardRecentContent recentTextFromClipboard]) { - copiedText = text; - type = CopiedContentTypeString; - } - - return [self setCopiedContentType:type - copiedText:copiedText - copiedImage:copiedImage]; -} - -// Helper method to encapsulate checking whether the current search engine -// supports search-by-image and getting the copied image. -- (UIImage*)getCopiedImageFromClipboard { - if (!self.supportsSearchByImage) { - return nil; - } - return [self.clipboardRecentContent recentImageFromClipboard]; + [self.clipboardRecentContent + hasContentMatchingTypes:wantedTypes + completionHandler:^(NSSet<ContentType>* matchedTypes) { + CopiedContentType newType = CopiedContentTypeNone; + if (self.supportsSearchByImage && + [matchedTypes containsObject:ContentTypeImage]) { + newType = CopiedContentTypeImage; + } else if ([matchedTypes containsObject:ContentTypeURL]) { + newType = CopiedContentTypeURL; + } else if ([matchedTypes containsObject:ContentTypeText]) { + newType = CopiedContentTypeString; + } + dispatch_async(dispatch_get_main_queue(), ^{ + completionHandler([self updateCopiedContentType:newType]); + }); + }]; } - (void)viewWillTransitionToSize:(CGSize)size @@ -201,25 +202,47 @@ } - (void)openCopiedContent:(id)sender { - DCHECK([self verifyCopiedContentType]); switch (self.copiedContentType) { - case CopiedContentTypeURL: - [self.command prepareToOpenURL:[NSURL URLWithString:self.copiedText]]; + case CopiedContentTypeURL: { + [self.clipboardRecentContent + recentURLFromClipboardAsync:^(NSURL* copiedURL) { + if (!copiedURL) { + return; + } + [self.command prepareToOpenURL:copiedURL]; + [self.command executeInApp]; + }]; break; - case CopiedContentTypeString: - [self.command prepareToSearchText:self.copiedText]; + } + case CopiedContentTypeString: { + [self.clipboardRecentContent + recentTextFromClipboardAsync:^(NSString* copiedText) { + if (!copiedText) { + return; + } + [self.command prepareToSearchText:copiedText]; + [self.command executeInApp]; + }]; break; + } case CopiedContentTypeImage: { - // Resize image before converting to NSData so we can store less data. - UIImage* resizedImage = ResizeImageForSearchByImage(self.copiedImage); - [self.command prepareToSearchImage:resizedImage]; + [self.clipboardRecentContent + recentImageFromClipboardAsync:^(UIImage* copiedImage) { + if (!copiedImage) { + return; + } + // Resize image before converting to NSData so we can store less + // data. + UIImage* resizedImage = ResizeImageForSearchByImage(copiedImage); + [self.command prepareToSearchImage:resizedImage]; + [self.command executeInApp]; + }]; break; } case CopiedContentTypeNone: NOTREACHED(); return; } - [self.command executeInApp]; } #pragma mark - internal @@ -241,38 +264,15 @@ forKey:app_group::kSearchExtensionDisplayCount]; } -// Sets the copied content type. |copiedText| should be provided if the content -// type requires textual data, otherwise it should be nil. Likewise, -// |copiedImage| should be provided if the content type requires image data. -// Also saves the data and returns YES if the screen needs updating and NO -// otherwise. -- (BOOL)setCopiedContentType:(CopiedContentType)type - copiedText:(NSString*)copiedText - copiedImage:(UIImage*)copiedImage { - if (self.copiedContentType == type && - [self.copiedText isEqualToString:copiedText] && - [self.copiedImage isEqual:copiedImage]) { +// Sets the copied content type returns YES if the screen needs updating and NO +// otherwise. This must only be called on the main thread. +- (BOOL)updateCopiedContentType:(CopiedContentType)type { + if (self.copiedContentType == type) { return NO; } self.copiedContentType = type; - self.copiedText = copiedText; - self.copiedImage = copiedImage; - [self.widgetView setCopiedContentType:self.copiedContentType - copiedText:self.copiedText]; + [self.widgetView setCopiedContentType:self.copiedContentType]; return YES; } -// Verifies that the current copied content type has the required data with it. -- (BOOL)verifyCopiedContentType { - switch (self.copiedContentType) { - case CopiedContentTypeString: - case CopiedContentTypeURL: - return self.copiedText; - case CopiedContentTypeImage: - return self.copiedImage; - case CopiedContentTypeNone: - return true; - } -} - @end
diff --git a/ios/web/common/features.h b/ios/web/common/features.h index b3e4360..d7e550d 100644 --- a/ios/web/common/features.h +++ b/ios/web/common/features.h
@@ -57,6 +57,12 @@ // the URL. extern const base::Feature kAddWebContentDropInteraction; +// When enabled, opening a URL with a text fragment (e.g., +// example.com/#:~:text=examples) will cause matching text in the page to be +// highlighted and scrolled into view. +// See also: https://wicg.github.io/scroll-to-text-fragment/ +extern const base::Feature kScrollToTextIOS; + // When true, for each navigation, the default user agent is chosen by the // WebClient GetDefaultUserAgent() method. If it is false, the mobile version // is requested by default.
diff --git a/ios/web/common/features.mm b/ios/web/common/features.mm index 688740c..df6b531 100644 --- a/ios/web/common/features.mm +++ b/ios/web/common/features.mm
@@ -48,6 +48,9 @@ const base::Feature kAddWebContentDropInteraction{ "AddWebContentDropInteraction", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kScrollToTextIOS{"ScrollToTextIOS", + base::FEATURE_DISABLED_BY_DEFAULT}; + bool UseWebClientDefaultUserAgent() { if (@available(iOS 13, *)) { return base::FeatureList::IsEnabled(kUseDefaultUserAgentInWebClient);
diff --git a/ios/web/navigation/session_storage_builder.mm b/ios/web/navigation/session_storage_builder.mm index a78731f..11817a0 100644 --- a/ios/web/navigation/session_storage_builder.mm +++ b/ios/web/navigation/session_storage_builder.mm
@@ -8,6 +8,7 @@ #include "base/check_op.h" #include "base/mac/foundation_util.h" +#include "ios/web/common/features.h" #import "ios/web/navigation/navigation_item_impl.h" #import "ios/web/navigation/navigation_item_storage_builder.h" #include "ios/web/navigation/navigation_manager_impl.h" @@ -113,7 +114,12 @@ web_state->certificate_policy_cache_ = std::move(cert_policy_cache); web::SerializableUserDataManager::FromWebState(web_state) ->AddSerializableUserData(storage.userData); - web_state->SetUserAgent(storage.userAgentType); + UserAgentType user_agent_type = storage.userAgentType; + if (user_agent_type == UserAgentType::AUTOMATIC && + !features::UseWebClientDefaultUserAgent()) { + user_agent_type = UserAgentType::MOBILE; + } + web_state->SetUserAgent(user_agent_type); } } // namespace web
diff --git a/ios/web/session/crw_session_storage.mm b/ios/web/session/crw_session_storage.mm index 18401f6..6891deb1 100644 --- a/ios/web/session/crw_session_storage.mm +++ b/ios/web/session/crw_session_storage.mm
@@ -110,8 +110,13 @@ forKey:kCertificatePolicyCacheStorageKey]; if (_userData) _userData->Encode(coder); + web::UserAgentType userAgentType = _userAgentType; + if (userAgentType == web::UserAgentType::AUTOMATIC && + !web::features::UseWebClientDefaultUserAgent()) { + userAgentType = web::UserAgentType::MOBILE; + } web::nscoder_util::EncodeString( - coder, kUserAgentKey, web::GetUserAgentTypeDescription(_userAgentType)); + coder, kUserAgentKey, web::GetUserAgentTypeDescription(userAgentType)); } @end
diff --git a/mojo/BUILD.gn b/mojo/BUILD.gn index b0d08da..ea1cc00 100644 --- a/mojo/BUILD.gn +++ b/mojo/BUILD.gn
@@ -10,7 +10,7 @@ testonly = true deps = [ ":tests" ] - if (!(is_linux && current_cpu == "x86")) { + if (!((is_linux || is_chromeos) && current_cpu == "x86")) { deps += [ "//mojo/public" ] }
diff --git a/mojo/core/test/BUILD.gn b/mojo/core/test/BUILD.gn index 1abadfc..1eab16f 100644 --- a/mojo/core/test/BUILD.gn +++ b/mojo/core/test/BUILD.gn
@@ -47,7 +47,7 @@ "//testing/gtest", ] - if (is_linux && !is_component_build) { + if ((is_linux || is_chromeos) && !is_component_build) { public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] } } @@ -65,7 +65,7 @@ sources = [ "run_all_perftests.cc" ] - if (is_linux && !is_component_build) { + if ((is_linux || is_chromeos) && !is_component_build) { public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] } }
diff --git a/native_client_sdk/src/BUILD.gn b/native_client_sdk/src/BUILD.gn index ff31576..27b24d1 100644 --- a/native_client_sdk/src/BUILD.gn +++ b/native_client_sdk/src/BUILD.gn
@@ -7,7 +7,7 @@ declare_args() { # Set to true if cross compiling trusted (e.g. building sel_ldr_arm on x86) # binaries is supported. - enable_cross_trusted = is_linux + enable_cross_trusted = is_linux || is_chromeos # Build the nacl SDK untrusted components. This is disabled by default since # not all NaCl untrusted compilers are in goma (e.g arm-nacl-glibc) @@ -28,7 +28,7 @@ "//native_client/src/trusted/service_runtime:sel_ldr", "//native_client/src/trusted/validator/driver:ncval_new", ] - if (is_linux) { + if (is_linux || is_chromeos) { deps += [ "//native_client/src/nonsfi/loader:nonsfi_loader" ] } }
diff --git a/net/BUILD.gn b/net/BUILD.gn index 497313b..45688e85 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -99,7 +99,7 @@ "//build/config/compiler:wexit_time_destructors", ] -if (is_linux) { +if (is_linux || is_chromeos) { net_configs += [ "//build/config/linux:libresolv" ] } @@ -166,6 +166,8 @@ "base/sockaddr_storage.cc", "base/sockaddr_storage.h", "base/sys_addrinfo.h", + "base/transport_info.cc", + "base/transport_info.h", "base/url_util.cc", "base/url_util.h", "cert/asn1_util.cc", @@ -1237,7 +1239,7 @@ ] } - if (is_linux) { + if (is_linux && !is_chromeos) { sources += [ "base/network_change_notifier_linux.cc", "base/network_change_notifier_linux.h", @@ -1246,7 +1248,7 @@ ] } - if (is_linux || is_android) { + if (is_linux || is_chromeos || is_android) { sources += [ "base/address_tracker_linux.cc", "base/address_tracker_linux.h", @@ -1425,7 +1427,7 @@ } # Use getifaddrs() on POSIX platforms, except Linux. - if (is_posix && !is_linux) { + if (is_posix && !is_linux && !is_chromeos) { sources += [ "base/network_interfaces_getifaddrs.cc", "base/network_interfaces_getifaddrs.h", @@ -2455,7 +2457,7 @@ } } -if (is_linux || is_mac) { +if (is_linux || is_chromeos || is_mac) { executable("cachetool") { testonly = true sources = [ "tools/cachetool/cachetool.cc" ] @@ -2482,7 +2484,7 @@ } } -if (is_linux) { +if (is_linux || is_chromeos) { static_library("epoll_server") { sources = [ "tools/epoll_server/platform/impl/epoll_bug_impl.h", @@ -2558,7 +2560,7 @@ } } -if (is_android || is_linux) { +if (is_android || is_linux || is_chromeos) { executable("disk_cache_memory_test") { testonly = true sources = [ "tools/disk_cache_memory_test/disk_cache_memory_test.cc" ] @@ -4472,7 +4474,7 @@ ] } - if (is_linux) { + if (is_linux || is_chromeos) { sources += [ "base/address_tracker_linux_unittest.cc", "base/network_interfaces_linux_unittest.cc", @@ -4583,7 +4585,7 @@ "//testing/buildbot/filters:net_unittests_filters", ] - if (is_linux || is_mac || is_win || is_fuchsia) { + if (is_linux || is_chromeos || is_mac || is_win || is_fuchsia) { deps += [ "//third_party/pywebsocket3/", "//third_party/tlslite/", @@ -4599,7 +4601,7 @@ ] } - if (is_linux) { + if (is_linux || is_chromeos) { sources += [ "quic/platform/impl/quic_epoll_clock_test.cc", "quic/platform/impl/quic_flags_test.cc", @@ -4760,7 +4762,7 @@ } # Use getifaddrs() on POSIX platforms, except Linux and Android. - if (is_posix && !is_linux && !is_android) { + if (is_posix && !is_linux && !is_chromeos && !is_android) { sources += [ "base/network_interfaces_getifaddrs_unittest.cc" ] } @@ -5564,7 +5566,7 @@ dict = "data/fuzzer_dictionaries/net_uri_template_fuzzer.dict" } -if (is_linux) { +if (is_linux || is_chromeos) { fuzzer_test("net_base_address_tracker_linux_fuzzer") { sources = [ "base/address_tracker_linux_fuzzer.cc" ] deps = [
diff --git a/net/base/transport_info.cc b/net/base/transport_info.cc new file mode 100644 index 0000000..3861e83 --- /dev/null +++ b/net/base/transport_info.cc
@@ -0,0 +1,61 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/transport_info.h" + +#include <ostream> +#include <utility> + +#include "base/strings/strcat.h" + +namespace net { + +base::StringPiece TransportTypeToString(TransportType type) { + switch (type) { + case TransportType::kDirect: + return "TransportType::kDirect"; + case TransportType::kProxied: + return "TransportType::kProxied"; + } + + // We define this here instead of as a `default` clause above so as to force + // a compiler error if a new value is added to the enum and this method is + // not updated to reflect it. + return "<invalid transport type>"; +} + +TransportInfo::TransportInfo() = default; + +TransportInfo::TransportInfo(TransportType type_arg, IPEndPoint endpoint_arg) + : type(type_arg), endpoint(std::move(endpoint_arg)) {} + +TransportInfo::~TransportInfo() = default; + +bool TransportInfo::operator==(const TransportInfo& other) const { + return type == other.type && endpoint == other.endpoint; +} + +bool TransportInfo::operator!=(const TransportInfo& other) const { + return !(*this == other); +} + +std::string TransportInfo::ToString() const { + return base::StrCat({ + "TransportInfo{ type = ", + TransportTypeToString(type), + ", endpoint = ", + endpoint.ToString(), + " }", + }); +} + +std::ostream& operator<<(std::ostream& out, TransportType type) { + return out << TransportTypeToString(type); +} + +std::ostream& operator<<(std::ostream& out, const TransportInfo& info) { + return out << info.ToString(); +} + +} // namespace net
diff --git a/net/base/transport_info.h b/net/base/transport_info.h new file mode 100644 index 0000000..6f0dde3 --- /dev/null +++ b/net/base/transport_info.h
@@ -0,0 +1,57 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_TRANSPORT_INFO_H_ +#define NET_BASE_TRANSPORT_INFO_H_ + +#include <iosfwd> +#include <string> + +#include "base/strings/string_piece.h" +#include "net/base/ip_endpoint.h" +#include "net/base/net_export.h" + +namespace net { + +// Specifies the type of a network transport. +enum class TransportType { + // The transport was established directly to a peer. + kDirect, + // The transport was established to a proxy of some kind. + kProxied, +}; + +// Returns a string representation of the given transport type. +// The returned StringPiece is static, has no lifetime restrictions. +NET_EXPORT base::StringPiece TransportTypeToString(TransportType type); + +// Describes a network transport. +struct NET_EXPORT TransportInfo { + TransportInfo(); + TransportInfo(TransportType type_arg, IPEndPoint endpoint_arg); + ~TransportInfo(); + + // Instances of this type are comparable for equality. + bool operator==(const TransportInfo& other) const; + bool operator!=(const TransportInfo& other) const; + + // Returns a string representation of this struct, suitable for debugging. + std::string ToString() const; + + // The type of the transport. + TransportType type = TransportType::kDirect; + + // If |type| is kDirect, then this identifies the peer endpoint. + // If |type| is kProxied, then this identifies the proxy endpoint. + IPEndPoint endpoint; +}; + +// Instances of these types are streamable for easier debugging. +NET_EXPORT std::ostream& operator<<(std::ostream& out, TransportType type); +NET_EXPORT std::ostream& operator<<(std::ostream& out, + const TransportInfo& info); + +} // namespace net + +#endif // NET_BASE_TRANSPORT_INFO_H_
diff --git a/net/cookies/cookie_monster_perftest.cc b/net/cookies/cookie_monster_perftest.cc index 7ca45d7..10c79a1 100644 --- a/net/cookies/cookie_monster_perftest.cc +++ b/net/cookies/cookie_monster_perftest.cc
@@ -28,8 +28,7 @@ namespace { const int kNumCookies = 20000; -const char kCookieLine[] = "A = \"b=;\\\"\" ;secure;;;"; -const char kGoogleURL[] = "http://www.foo.com"; +const char kCookieLine[] = "A = \"b=;\\\"\" ;secure;;; samesite=none"; static constexpr char kMetricPrefixParsedCookie[] = "ParsedCookie."; static constexpr char kMetricPrefixCookieMonster[] = "CookieMonster."; @@ -106,7 +105,8 @@ private: void Run(CookieAccessResult result) { - EXPECT_TRUE(result.status.IsInclude()); + EXPECT_TRUE(result.status.IsInclude()) + << "result.status: " << result.status.GetDebugString(); CookieTestCallback::Run(); } CookieOptions options_; @@ -178,7 +178,7 @@ auto cm = std::make_unique<CookieMonster>(nullptr, nullptr); std::vector<std::string> cookies; for (int i = 0; i < kNumCookies; i++) { - cookies.push_back(base::StringPrintf("a%03d=b", i)); + cookies.push_back(base::StringPrintf("a%03d=b; SameSite=None; Secure", i)); } SetCookieCallback setCookieCallback; @@ -187,9 +187,10 @@ auto reporter = SetUpCookieMonsterReporter("single_host"); base::ElapsedTimer add_timer; + const GURL kGoogleURL = GURL("https://www.foo.com"); for (std::vector<std::string>::const_iterator it = cookies.begin(); it != cookies.end(); ++it) { - setCookieCallback.SetCookie(cm.get(), GURL(kGoogleURL), *it); + setCookieCallback.SetCookie(cm.get(), kGoogleURL, *it); } reporter.AddResult(kMetricAddTimeMs, add_timer.Elapsed().InMillisecondsF()); @@ -198,7 +199,7 @@ base::ElapsedTimer query_timer; for (std::vector<std::string>::const_iterator it = cookies.begin(); it != cookies.end(); ++it) { - getCookieListCallback.GetCookieList(cm.get(), GURL(kGoogleURL)); + getCookieListCallback.GetCookieList(cm.get(), kGoogleURL); } reporter.AddResult(kMetricQueryTimeMs, query_timer.Elapsed().InMillisecondsF()); @@ -250,7 +251,8 @@ auto cm = std::make_unique<CookieMonster>(nullptr, nullptr); GetCookieListCallback getCookieListCallback; SetCookieCallback setCookieCallback; - const char domain_cookie_format_tree[] = "a=b; domain=%s"; + const char domain_cookie_format_tree[] = + "a=b; domain=%s; samesite=none; secure"; const std::string domain_base("top.com"); std::vector<std::string> domain_list; @@ -323,7 +325,8 @@ domain_list.push_back("b.a.b.a.top.com"); EXPECT_EQ(4u, domain_list.size()); - const char domain_cookie_format_line[] = "a%03d=b; domain=%s"; + const char domain_cookie_format_line[] = + "a%03d=b; domain=%s; samesite=none; secure"; for (int i = 0; i < 8; i++) { for (std::vector<std::string>::const_iterator it = domain_list.begin(); it != domain_list.end(); it++) { @@ -445,8 +448,8 @@ test_case.num_cookies, test_case.num_old_cookies, 0, 0, CookieMonster::kSafeFromGlobalPurgeDays * 2); - GURL gurl("http://foo.com"); - std::string cookie_line("z=3"); + GURL gurl("https://foo.com"); + std::string cookie_line("z=3; samesite=none; secure"); // Trigger the Garbage collection we're allowed. setCookieCallback.SetCookie(cm.get(), gurl, cookie_line);
diff --git a/net/features.gni b/net/features.gni index d545845..25729120 100644 --- a/net/features.gni +++ b/net/features.gni
@@ -23,7 +23,7 @@ disable_brotli_filter = false # Multicast DNS. - enable_mdns = is_win || is_linux || is_fuchsia || is_apple + enable_mdns = is_win || is_linux || is_chromeos || is_fuchsia || is_apple # Reporting not used on iOS. enable_reporting = !is_ios
diff --git a/net/http/http_cache_lookup_manager_unittest.cc b/net/http/http_cache_lookup_manager_unittest.cc index 5298584..73e760b 100644 --- a/net/http/http_cache_lookup_manager_unittest.cc +++ b/net/http/http_cache_lookup_manager_unittest.cc
@@ -52,12 +52,25 @@ std::unique_ptr<MockTransaction> CreateMockTransaction(const GURL& url) { MockTransaction mock_trans = { - url.spec().c_str(), "GET", base::Time(), "", LOAD_NORMAL, + url.spec().c_str(), + "GET", + base::Time(), + "", + LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Date: Wed, 28 Nov 2007 09:40:09 GMT\n" "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n", - base::Time(), "<html><body>Google Blah Blah</body></html>", - TEST_MODE_NORMAL, nullptr, nullptr, nullptr, 0, 0, OK}; + base::Time(), + "<html><body>Google Blah Blah</body></html>", + TEST_MODE_NORMAL, + nullptr, + nullptr, + nullptr, + 0, + 0, + OK, + }; return std::make_unique<MockTransaction>(mock_trans); }
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index c410380..c7a7a9b 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc
@@ -35,6 +35,7 @@ #include "net/base/elements_upload_data_stream.h" #include "net/base/features.h" #include "net/base/host_port_pair.h" +#include "net/base/ip_address.h" #include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/base/load_timing_info.h" @@ -75,9 +76,11 @@ using testing::AllOf; using testing::ByRef; using testing::Contains; +using testing::ElementsAre; using testing::Eq; using testing::Field; using testing::Gt; +using testing::IsEmpty; using testing::NotNull; using base::Time; @@ -371,6 +374,7 @@ base::Time(), "", LOAD_VALIDATE_CACHE, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Cache-Control: max-age=10000\n", base::Time(), @@ -381,7 +385,8 @@ nullptr, 0, 0, - OK}; + OK, +}; // This class provides a handler for kRangeGET_TransactionOK so that the range // request can be served on demand. @@ -565,6 +570,7 @@ base::Time(), "Range: bytes = 40-49\r\n" EXTRA_HEADER, LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 206 Partial Content", "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" "ETag: \"foo\"\n" @@ -578,7 +584,8 @@ nullptr, 0, 0, - OK}; + OK, +}; const char kFullRangeData[] = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 " @@ -720,6 +727,13 @@ return !log.GetEntriesWithType(expected).empty(); } +// Returns a TransportInfo distinct from the default for mock transactions. +TransportInfo TestTransportInfo() { + TransportInfo result; + result.endpoint = IPEndPoint(IPAddress(42, 0, 1, 2), 1337); + return result; +} + } // namespace using HttpCacheTest = TestWithTaskEnvironment; @@ -826,7 +840,9 @@ ConnectedHandler connected_handler; - MockHttpRequest request(kSimpleGET_Transaction); + ScopedMockTransaction mock_transaction(kSimpleGET_Transaction); + mock_transaction.transport_info = TestTransportInfo(); + MockHttpRequest request(mock_transaction); std::unique_ptr<HttpTransaction> transaction; EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk()); @@ -840,7 +856,7 @@ IsError(ERR_IO_PENDING)); EXPECT_THAT(callback.WaitForResult(), IsOk()); - EXPECT_EQ(1, connected_handler.call_count()); + EXPECT_THAT(connected_handler.transports(), ElementsAre(TestTransportInfo())); } // This test verifies that when the callback passed to SetConnectedCallback() @@ -904,8 +920,9 @@ EXPECT_EQ(1, cache.network_layer()->transaction_count()); // TODO(crbug.com/986744): Expect 1 call once HttpCache::Transaction is - // modified to call the callback on cache hits. - EXPECT_EQ(0, connected_handler.call_count()); + // modified to call the callback on cache hits, expect that the endpoint is + // the one from which the cached data was downloaded. + EXPECT_THAT(connected_handler.transports(), IsEmpty()); } class HttpCacheTest_SplitCacheFeature @@ -2024,6 +2041,7 @@ ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK); mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER; mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 "; + mock_transaction.transport_info = TestTransportInfo(); MockHttpRequest request(mock_transaction); ConnectedHandler connected_handler; @@ -2041,14 +2059,29 @@ EXPECT_THAT(callback.WaitForResult(), IsOk()); // 1 call for the first range's network transaction. - EXPECT_EQ(1, connected_handler.call_count()); + EXPECT_THAT(connected_handler.transports(), + ElementsAre(TestTransportInfo())); + + // Switch the endpoint for the next network transaction to observe. + // For ease, we just switch the port number. + // + // NOTE: This works because only the mock transaction struct's address is + // registered with the mocking framework - the pointee data is consulted + // each time it is read. + auto new_transport_info = TestTransportInfo(); + new_transport_info.endpoint = + IPEndPoint(new_transport_info.endpoint.address(), 123); + mock_transaction.transport_info = new_transport_info; ReadAndVerifyTransaction(transaction.get(), mock_transaction); // A second call for the last range's network transaction. // TODO(crbug.com/986744): Expect 3 calls once the callback is notified on // cache hits as well as network connections. - EXPECT_EQ(2, connected_handler.call_count()); + // TODO(crbug.com/986744): Test that the cached data is served as coming + // from the endpoint whence it was originally downloaded. + EXPECT_THAT(connected_handler.transports(), + ElementsAre(TestTransportInfo(), new_transport_info)); } } @@ -2095,7 +2128,8 @@ EXPECT_THAT(callback.WaitForResult(), IsOk()); // 1 call for the first range's network transaction. - EXPECT_EQ(1, connected_handler.call_count()); + EXPECT_THAT(connected_handler.transports(), + ElementsAre(DefaultTransportInfo())); // Set the callback to return an error the next time it is called. The exact // error code is irrelevant, what matters is that it is reflected in the @@ -2107,7 +2141,8 @@ IsError(ERR_NOT_IMPLEMENTED)); // A second call that failed. - EXPECT_EQ(2, connected_handler.call_count()); + EXPECT_THAT(connected_handler.transports(), + ElementsAre(DefaultTransportInfo(), DefaultTransportInfo())); } } @@ -9283,8 +9318,7 @@ // Tests basic pickling/unpickling of HttpResponseInfo. TEST_F(HttpCacheTest, PersistHttpResponseInfo) { - const IPEndPoint expected_endpoint = - IPEndPoint(net::IPAddress(1, 2, 3, 4), 80); + const IPEndPoint expected_endpoint = IPEndPoint(IPAddress(1, 2, 3, 4), 80); // Set some fields (add more if needed.) HttpResponseInfo response1; response1.was_cached = false;
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 4aa3c63..69b55e23 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc
@@ -30,6 +30,7 @@ #include "net/base/load_timing_info.h" #include "net/base/net_errors.h" #include "net/base/proxy_server.h" +#include "net/base/transport_info.h" #include "net/base/upload_data_stream.h" #include "net/base/url_util.h" #include "net/cert/cert_status_flags.h" @@ -876,7 +877,11 @@ // Fire off notification that we have successfully connected. if (!connected_callback_.is_null()) { - result = connected_callback_.Run(); + TransportType type = TransportType::kDirect; + if (!proxy_info_.is_direct()) { + type = TransportType::kProxied; + } + result = connected_callback_.Run(TransportInfo(type, remote_endpoint_)); DCHECK_NE(result, ERR_IO_PENDING); }
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 755df4ac..26d16a20 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -43,6 +43,7 @@ #include "net/base/elements_upload_data_stream.h" #include "net/base/features.h" #include "net/base/host_port_pair.h" +#include "net/base/ip_address.h" #include "net/base/ip_endpoint.h" #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" @@ -141,6 +142,8 @@ using base::ASCIIToUTF16; using testing::AnyOf; +using testing::ElementsAre; +using testing::IsEmpty; //----------------------------------------------------------------------------- @@ -356,15 +359,23 @@ } }; +// A default minimal HttpRequestInfo for use in tests, targeting HTTP. HttpRequestInfo DefaultRequestInfo() { HttpRequestInfo info; info.method = "GET"; - info.url = GURL("http://www.example.org"); + info.url = GURL("http://foo.test"); info.traffic_annotation = net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); return info; } +// The default info for transports to the embedded HTTP server. +TransportInfo EmbeddedHttpServerTransportInfo() { + TransportInfo info; + info.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 80); + return info; +} + } // namespace class HttpNetworkTransactionTest : public PlatformTest, @@ -885,12 +896,15 @@ // remote endpoint, the ConnectedCallback is never called. TEST_F(HttpNetworkTransactionTest, ConnectedCallbackNeverCalled) { auto resolver = std::make_unique<MockHostResolver>(); - resolver->rules()->AddSimulatedTimeoutFailure("www.example.org"); + resolver->rules()->AddSimulatedTimeoutFailure("bar.test"); session_deps_.host_resolver = std::move(resolver); ConnectedHandler connected_handler; std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_); + auto request = DefaultRequestInfo(); + request.url = GURL("http://bar.test"); + HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get()); transaction.SetConnectedCallback(connected_handler.Callback()); @@ -898,7 +912,7 @@ transaction.Start(&request, callback.callback(), NetLogWithSource()); callback.WaitForResult(); - EXPECT_EQ(connected_handler.call_count(), 0); + EXPECT_THAT(connected_handler.transports(), IsEmpty()); } // This test verifies that if the ConnectedCallback returns an error, the @@ -924,7 +938,8 @@ IsError(ERR_IO_PENDING)); EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NOT_IMPLEMENTED)); - EXPECT_EQ(connected_handler.call_count(), 1); + EXPECT_THAT(connected_handler.transports(), + ElementsAre(EmbeddedHttpServerTransportInfo())); } // This test verifies that the ConnectedCallback is called once in the case of @@ -949,7 +964,8 @@ IsError(ERR_IO_PENDING)); EXPECT_THAT(callback.WaitForResult(), IsOk()); - EXPECT_EQ(connected_handler.call_count(), 1); + EXPECT_THAT(connected_handler.transports(), + ElementsAre(EmbeddedHttpServerTransportInfo())); } // This test verifies that the ConnectedCallback is called once more per @@ -985,7 +1001,8 @@ IsError(ERR_IO_PENDING)); EXPECT_THAT(callback1.WaitForResult(), IsOk()); - EXPECT_EQ(connected_handler.call_count(), 1); + EXPECT_THAT(connected_handler.transports(), + ElementsAre(EmbeddedHttpServerTransportInfo())); // Second request, connects again. TestCompletionCallback callback2; @@ -994,7 +1011,9 @@ IsError(ERR_IO_PENDING)); EXPECT_THAT(callback2.WaitForResult(), IsOk()); - EXPECT_EQ(connected_handler.call_count(), 2); + EXPECT_THAT(connected_handler.transports(), + ElementsAre(EmbeddedHttpServerTransportInfo(), + EmbeddedHttpServerTransportInfo())); } // This test verifies that the ConnectedCallback is called once more per retry. @@ -1026,7 +1045,9 @@ IsError(ERR_IO_PENDING)); EXPECT_THAT(callback1.WaitForResult(), IsOk()); - EXPECT_EQ(connected_handler.call_count(), 2); + EXPECT_THAT(connected_handler.transports(), + ElementsAre(EmbeddedHttpServerTransportInfo(), + EmbeddedHttpServerTransportInfo())); } // Allow up to 4 bytes of junk to precede status line. @@ -1379,7 +1400,8 @@ EXPECT_EQ(1234, response->headers->GetContentLength()); EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine()); EXPECT_TRUE(response->proxy_server.is_direct()); - EXPECT_EQ(connected_handler.call_count(), 1); + EXPECT_THAT(connected_handler.transports(), + ElementsAre(EmbeddedHttpServerTransportInfo())); std::string server_header; size_t iter = 0; @@ -3445,10 +3467,13 @@ session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); TestCompletionCallback callback1; + ConnectedHandler connected_handler; auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get()); + trans->SetConnectedCallback(connected_handler.Callback()); + int rv = trans->Start(&request, callback1.callback(), log.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); @@ -3463,6 +3488,12 @@ NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, NetLogEventPhase::NONE); + // TODO(crbug.com/986744): Fix handling of OnConnected() when proxy + // authentication is required. We should notify the callback that a connection + // was established, even though the stream might not be ready for us to send + // data through it. + EXPECT_THAT(connected_handler.transports(), IsEmpty()); + const HttpResponseInfo* response = trans->GetResponseInfo(); ASSERT_TRUE(response); EXPECT_FALSE(response->headers->IsKeepAlive()); @@ -3493,6 +3524,11 @@ EXPECT_EQ(5, response->headers->GetContentLength()); EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); + TransportInfo expected_transport; + expected_transport.type = TransportType::kProxied; + expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70); + EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport)); + // Check that credentials were successfully cached, with the right target. HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup( GURL("http://myproxy:70"), HttpAuth::AUTH_PROXY, "MyRealm1", @@ -3576,11 +3612,14 @@ SSLSocketDataProvider ssl(ASYNC, OK); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + ConnectedHandler connected_handler; TestCompletionCallback callback1; auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get()); + trans->SetConnectedCallback(connected_handler.Callback()); + int rv = trans->Start(&request, callback1.callback(), log.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); @@ -3603,6 +3642,12 @@ EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge)); + // TODO(crbug.com/986744): Fix handling of OnConnected() when proxy + // authentication is required. We should notify the callback that a connection + // was established, even though the stream might not be ready for us to send + // data through it. + EXPECT_THAT(connected_handler.transports(), IsEmpty()); + LoadTimingInfo load_timing_info; // CONNECT requests and responses are handled at the connect job level, so // the transaction does not yet have a connection. @@ -3625,6 +3670,11 @@ EXPECT_EQ(5, response->headers->GetContentLength()); EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); + TransportInfo expected_transport; + expected_transport.type = TransportType::kProxied; + expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70); + EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport)); + // The password prompt info should not be set. EXPECT_FALSE(response->auth_challenge.has_value()); @@ -5672,10 +5722,14 @@ SameProxyWithDifferentSchemesProxyResolver() {} ~SameProxyWithDifferentSchemesProxyResolver() override {} - static std::string ProxyHostPortPairAsString() { return "proxy.test:10000"; } + static constexpr uint16_t kProxyPort = 10000; static HostPortPair ProxyHostPortPair() { - return HostPortPair::FromString(ProxyHostPortPairAsString()); + return HostPortPair("proxy.test", kProxyPort); + } + + static std::string ProxyHostPortPairAsString() { + return ProxyHostPortPair().ToString(); } // ProxyResolver implementation. @@ -5870,29 +5924,44 @@ }; for (const auto& test_case : kTestCases) { + SCOPED_TRACE(test_case.url); + HttpRequestInfo request; request.method = "GET"; request.url = test_case.url; request.traffic_annotation = net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - std::unique_ptr<HttpNetworkTransaction> trans = - std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, - session.get()); + ConnectedHandler connected_handler; + + auto transaction = std::make_unique<HttpNetworkTransaction>( + DEFAULT_PRIORITY, session.get()); + + transaction->SetConnectedCallback(connected_handler.Callback()); + TestCompletionCallback callback; - int rv = trans->Start(&request, callback.callback(), NetLogWithSource()); + int rv = + transaction->Start(&request, callback.callback(), NetLogWithSource()); EXPECT_THAT(callback.GetResult(rv), IsOk()); - const HttpResponseInfo* response = trans->GetResponseInfo(); + const HttpResponseInfo* response = transaction->GetResponseInfo(); ASSERT_TRUE(response); ASSERT_TRUE(response->headers); EXPECT_EQ(200, response->headers->response_code()); std::string response_data; - EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk()); + EXPECT_THAT(ReadTransaction(transaction.get(), &response_data), IsOk()); EXPECT_EQ(test_case.expected_response, response_data); + TransportInfo expected_transport; + expected_transport.type = TransportType::kProxied; + expected_transport.endpoint = + IPEndPoint(IPAddress::IPv4Localhost(), + SameProxyWithDifferentSchemesProxyResolver::kProxyPort); + EXPECT_THAT(connected_handler.transports(), + ElementsAre(expected_transport)); + // Return the socket to the socket pool, so can make sure it's not used for // the next requests. - trans.reset(); + transaction.reset(); base::RunLoop().RunUntilIdle(); // Check the number of idle sockets in the pool, to make sure that used @@ -6256,10 +6325,13 @@ SSLSocketDataProvider ssl(ASYNC, OK); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + ConnectedHandler connected_handler; TestCompletionCallback callback1; HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); + trans.SetConnectedCallback(connected_handler.Callback()); + int rv = trans.Start(&request, callback1.callback(), log.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); @@ -6280,6 +6352,11 @@ EXPECT_EQ(100, response->headers->GetContentLength()); EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); + TransportInfo expected_transport; + expected_transport.type = TransportType::kProxied; + expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70); + EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport)); + // The password prompt info should not be set. EXPECT_FALSE(response->auth_challenge.has_value()); } @@ -6319,10 +6396,13 @@ ssl.next_proto = kProtoHTTP2; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + ConnectedHandler connected_handler; TestCompletionCallback callback1; HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); + trans.SetConnectedCallback(connected_handler.Callback()); + int rv = trans.Start(&request, callback1.callback(), log.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); @@ -6340,6 +6420,11 @@ ASSERT_TRUE(response->headers); EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); + TransportInfo expected_transport; + expected_transport.type = TransportType::kProxied; + expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70); + EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport)); + std::string response_data; ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk()); EXPECT_EQ(kUploadData, response_data); @@ -16015,9 +16100,13 @@ EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair::FromString("myproxy:70")), response->proxy_server); - EXPECT_EQ(1, connected_handler.call_count()); EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); + TransportInfo expected_transport; + expected_transport.type = TransportType::kProxied; + expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70); + EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport)); + LoadTimingInfo load_timing_info; EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info)); TestLoadTimingNotReusedWithPac(load_timing_info, @@ -16095,7 +16184,11 @@ EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair::FromString("myproxy:70")), response->proxy_server); - EXPECT_EQ(1, connected_handler.call_count()); + + TransportInfo expected_transport; + expected_transport.type = TransportType::kProxied; + expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70); + EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport)); LoadTimingInfo load_timing_info; EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc index f1adaf1..65daba7 100644 --- a/net/http/http_response_info.cc +++ b/net/http/http_response_info.cc
@@ -164,6 +164,7 @@ case CONNECTION_INFO_QUIC_DRAFT_27: case CONNECTION_INFO_QUIC_DRAFT_28: case CONNECTION_INFO_QUIC_DRAFT_29: + case CONNECTION_INFO_QUIC_T051: return CONNECTION_INFO_COARSE_QUIC; case CONNECTION_INFO_UNKNOWN: @@ -501,6 +502,7 @@ case CONNECTION_INFO_QUIC_DRAFT_27: case CONNECTION_INFO_QUIC_DRAFT_28: case CONNECTION_INFO_QUIC_DRAFT_29: + case CONNECTION_INFO_QUIC_T051: return true; case NUM_OF_CONNECTION_INFOS: NOTREACHED(); @@ -595,6 +597,8 @@ return "http/1.0"; case CONNECTION_INFO_QUIC_999: return "http2+quic/999"; + case CONNECTION_INFO_QUIC_T051: + return "h3-T051"; case NUM_OF_CONNECTION_INFOS: break; }
diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h index f878369a..e47c31f 100644 --- a/net/http/http_response_info.h +++ b/net/http/http_response_info.h
@@ -75,6 +75,7 @@ CONNECTION_INFO_QUIC_DRAFT_27 = 36, CONNECTION_INFO_QUIC_DRAFT_28 = 37, CONNECTION_INFO_QUIC_DRAFT_29 = 38, + CONNECTION_INFO_QUIC_T051 = 39, NUM_OF_CONNECTION_INFOS, };
diff --git a/net/http/http_transaction.h b/net/http/http_transaction.h index 4e26bdb..19e4d4d 100644 --- a/net/http/http_transaction.h +++ b/net/http/http_transaction.h
@@ -24,6 +24,7 @@ struct HttpRequestInfo; class HttpResponseInfo; class IOBuffer; +struct TransportInfo; struct LoadTimingInfo; class NetLogWithSource; class QuicServerInfo; @@ -37,24 +38,29 @@ public: // If |*defer| is set to true, the transaction will wait until // ResumeNetworkStart is called before establishing a connection. - typedef base::OnceCallback<void(bool* defer)> BeforeNetworkStartCallback; + using BeforeNetworkStartCallback = base::OnceCallback<void(bool* defer)>; // Called each time a connection is obtained, before any data is sent. // + // |info| describes the newly-obtained connection. + // // This can be called multiple times for a single transaction, in the case of // retries, auth challenges, and split range requests. // - // The callee can call GetRemoteEndpoint() on the caller transaction to - // determine where the latest connection terminates. - // // If this callback returns an error, the transaction fails with that error. // Otherwise the transaction continues unimpeded. // Must not return ERR_IO_PENDING. // + // TODO(crbug.com/986744): Fix handling of OnConnected() when proxy + // authentication is required. We should notify this callback that a + // connection was established, even though the stream might not be ready for + // us to send data through it. + // // TODO(crbug.com/591068): Allow ERR_IO_PENDING, add a new state machine state // to wait on a callback (either passed to this callback or a new explicit // method like ResumeNetworkStart()) to be called before continuing. - typedef base::RepeatingCallback<int()> ConnectedCallback; + using ConnectedCallback = + base::RepeatingCallback<int(const TransportInfo& info)>; // Stops any pending IO and destroys the transaction object. virtual ~HttpTransaction() {}
diff --git a/net/http/http_transaction_test_util.cc b/net/http/http_transaction_test_util.cc index 580a358..90235d2 100644 --- a/net/http/http_transaction_test_util.cc +++ b/net/http/http_transaction_test_util.cc
@@ -17,6 +17,8 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/clock.h" #include "base/time/time.h" +#include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/base/load_timing_info.h" #include "net/base/net_errors.h" @@ -40,6 +42,11 @@ static MockTransactionMap mock_transactions; } // namespace +TransportInfo DefaultTransportInfo() { + return TransportInfo(TransportType::kDirect, + IPEndPoint(IPAddress::IPv4Localhost(), 80)); +} + //----------------------------------------------------------------------------- // mock transaction data @@ -49,6 +56,7 @@ base::Time(), "", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Cache-Control: max-age=10000\n", base::Time(), @@ -60,7 +68,8 @@ 0, 0, OK, - OK}; + OK, +}; const MockTransaction kSimplePOST_Transaction = { "http://bugdatabase.com/edit", @@ -68,6 +77,7 @@ base::Time(), "", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "", base::Time(), @@ -79,7 +89,8 @@ 0, 0, OK, - OK}; + OK, +}; const MockTransaction kTypicalGET_Transaction = { "http://www.example.com/~foo/bar.html", @@ -87,6 +98,7 @@ base::Time(), "", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Date: Wed, 28 Nov 2007 09:40:09 GMT\n" "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n", @@ -99,7 +111,8 @@ 0, 0, OK, - OK}; + OK, +}; const MockTransaction kETagGET_Transaction = { "http://www.google.com/foopy", @@ -107,6 +120,7 @@ base::Time(), "", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Cache-Control: max-age=10000\n" "Etag: \"foopy\"\n", @@ -119,7 +133,8 @@ 0, 0, OK, - OK}; + OK, +}; const MockTransaction kRangeGET_Transaction = { "http://www.google.com/", @@ -127,6 +142,7 @@ base::Time(), "Range: 0-100\r\n", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Cache-Control: max-age=10000\n", base::Time(), @@ -138,7 +154,8 @@ 0, 0, OK, - OK}; + OK, +}; static const MockTransaction* const kBuiltinMockTransactions[] = { &kSimpleGET_Transaction, @@ -525,7 +542,7 @@ int result = OK; if (!connected_callback_.is_null()) { - result = connected_callback_.Run(); + result = connected_callback_.Run(t->transport_info); } CallbackLater(std::move(callback), result); @@ -646,4 +663,21 @@ return OK; } +//----------------------------------------------------------------------------- +// connected callback handler + +ConnectedHandler::ConnectedHandler() = default; +ConnectedHandler::~ConnectedHandler() = default; + +ConnectedHandler::ConnectedHandler(const ConnectedHandler&) = default; +ConnectedHandler& ConnectedHandler::operator=(const ConnectedHandler&) = + default; +ConnectedHandler::ConnectedHandler(ConnectedHandler&&) = default; +ConnectedHandler& ConnectedHandler::operator=(ConnectedHandler&&) = default; + +int ConnectedHandler::OnConnected(const TransportInfo& info) { + transports_.push_back(info); + return result_; +} + } // namespace net
diff --git a/net/http/http_transaction_test_util.h b/net/http/http_transaction_test_util.h index 8f7df63..89a5826 100644 --- a/net/http/http_transaction_test_util.h +++ b/net/http/http_transaction_test_util.h
@@ -10,6 +10,7 @@ #include <stdint.h> #include <string> +#include <vector> #include "base/callback.h" #include "base/compiler_specific.h" @@ -22,6 +23,7 @@ #include "net/base/net_errors.h" #include "net/base/request_priority.h" #include "net/base/test_completion_callback.h" +#include "net/base/transport_info.h" #include "net/disk_cache/disk_cache.h" #include "net/http/http_cache.h" #include "net/http/http_request_info.h" @@ -63,6 +65,10 @@ std::string* response_headers, std::string* response_data); +// Default TransportInfo suitable for most MockTransactions. +// Describes a direct connection to (127.0.0.1, 80). +TransportInfo DefaultTransportInfo(); + struct MockTransaction { const char* url; const char* method; @@ -70,6 +76,8 @@ base::Time request_time; const char* request_headers; int load_flags; + // Connection info passed to ConnectedCallback(), if any. + TransportInfo transport_info = DefaultTransportInfo(); const char* status; const char* response_headers; // If |response_time| is unspecified, the current time will be used. @@ -367,12 +375,15 @@ // Used for injecting ConnectedCallback instances in HttpTransaction. class ConnectedHandler { public: - ConnectedHandler() = default; + ConnectedHandler(); + ~ConnectedHandler(); - ConnectedHandler(const ConnectedHandler&) = default; - ConnectedHandler& operator=(const ConnectedHandler&) = default; - ConnectedHandler(ConnectedHandler&&) = default; - ConnectedHandler& operator=(ConnectedHandler&&) = default; + // Instances of this class are copyable and efficiently movable. + // WARNING: Do not move an instance to which a callback is bound. + ConnectedHandler(const ConnectedHandler&); + ConnectedHandler& operator=(const ConnectedHandler&); + ConnectedHandler(ConnectedHandler&&); + ConnectedHandler& operator=(ConnectedHandler&&); // Returns a callback bound to this->OnConnected(). // The returned callback must not outlive this instance. @@ -382,19 +393,18 @@ } // Compatible with HttpTransaction::ConnectedCallback. - int OnConnected() { - call_count_++; - return result_; - } + // Returns the last value passed to set_result(), if any, OK otherwise. + int OnConnected(const TransportInfo& info); - // Returns the number of times OnConnected() was called. - int call_count() const { return call_count_; } + // Returns the list of arguments with which OnConnected() was called. + // The arguments are listed in the same order as the calls were received. + const std::vector<TransportInfo>& transports() const { return transports_; } // Sets the value to be returned by subsequent calls to OnConnected(). void set_result(int result) { result_ = result; } private: - int call_count_ = 0; + std::vector<TransportInfo> transports_; int result_ = OK; };
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index 3834c10c..398b0e5 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -447,3 +447,6 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_overshooting_detection, false) + +// If true, enable QUIC version h3-T051. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_t051, true)
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc index 1b03ac6..6318e43 100644 --- a/net/quic/quic_http_stream.cc +++ b/net/quic/quic_http_stream.cc
@@ -108,6 +108,8 @@ return HttpResponseInfo::CONNECTION_INFO_QUIC_DRAFT_29; case quic::QUIC_VERSION_RESERVED_FOR_NEGOTIATION: return HttpResponseInfo::CONNECTION_INFO_QUIC_999; + case quic::QUIC_VERSION_51: + return HttpResponseInfo::CONNECTION_INFO_QUIC_T051; } NOTREACHED(); return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION;
diff --git a/net/third_party/quiche/BUILD.gn b/net/third_party/quiche/BUILD.gn index a715ea8..836245d 100644 --- a/net/third_party/quiche/BUILD.gn +++ b/net/third_party/quiche/BUILD.gn
@@ -652,7 +652,7 @@ extra_configs = [ "//build/config/compiler:wexit_time_destructors" ] } -if (is_linux) { +if (is_linux || is_chromeos) { source_set("epoll_server_core") { sources = [ "src/epoll_server/platform/api/epoll_bug.h", @@ -984,7 +984,7 @@ "//third_party/quic_trace:quic_trace_proto", ] - if (is_linux) { + if (is_linux || is_chromeos) { sources += [ "src/epoll_server/fake_simple_epoll_server.cc", "src/epoll_server/fake_simple_epoll_server.h", @@ -1450,7 +1450,7 @@ if (is_desktop_linux) { public_deps += [ "//net:epoll_quic_tools" ] } - if (is_linux) { + if (is_linux || is_chromeos) { sources += [ "src/epoll_server/simple_epoll_server_test.cc", "src/quic/core/chlo_extractor_test.cc",
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index bc4646f..d96b342 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -124,7 +124,8 @@ /////////////////////////////////////////////////////////////////////////////// // URLRequest::Delegate -int URLRequest::Delegate::OnConnected(URLRequest* request) { +int URLRequest::Delegate::OnConnected(URLRequest* request, + const TransportInfo& info) { return OK; } @@ -773,8 +774,8 @@ return (status_ != OK && status_ != ERR_IO_PENDING); } -int URLRequest::NotifyConnected() { - return delegate_->OnConnected(this); +int URLRequest::NotifyConnected(const TransportInfo& info) { + return delegate_->OnConnected(this, info); } void URLRequest::NotifyReceivedRedirect(const RedirectInfo& redirect_info,
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index 765ecc2..b139941 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h
@@ -60,6 +60,7 @@ class SSLCertRequestInfo; class SSLInfo; class SSLPrivateKey; +struct TransportInfo; class UploadDataStream; class URLRequestContext; class URLRequestJob; @@ -116,21 +117,22 @@ public: // Called each time a connection is obtained, before any data is sent. // + // |request| is never nullptr. Caller retains ownership. + // + // |info| describes the newly-obtained connection. + // // This may be called several times if the request creates multiple HTTP // transactions, e.g. if the request is redirected. It may also be called // several times per transaction, e.g. if the connection is retried, after // each HTTP auth challenge, or for split HTTP range requests. // - // The delegate may call request->GetTransactionRemoteEndpoint() to - // determine where the latest connection terminates. - // // If this returns an error, the request fails with the given error. // Otherwise the request continues unimpeded. // Must not return ERR_IO_PENDING. // // TODO(crbug.com/591068): Allow ERR_IO_PENDING for a potentially-slow // CORS-RFC1918 preflight check. - virtual int OnConnected(URLRequest* request); + virtual int OnConnected(URLRequest* request, const TransportInfo& info); // Called upon receiving a redirect. The delegate may call the request's // Cancel method to prevent the redirect from being followed. Since there @@ -789,7 +791,7 @@ // These functions delegate to |delegate_|. See URLRequest::Delegate for the // meaning of these functions. - int NotifyConnected(); + int NotifyConnected(const TransportInfo& info); void NotifyAuthRequired(std::unique_ptr<AuthChallengeInfo> auth_info); void NotifyCertificateRequested(SSLCertRequestInfo* cert_request_info); void NotifySSLCertificateError(int net_error,
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index c69bc7c9..0f66b6e 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -362,8 +362,8 @@ out->clear(); } -int URLRequestHttpJob::NotifyConnectedCallback() { - return URLRequestJob::NotifyConnected(); +int URLRequestHttpJob::NotifyConnectedCallback(const TransportInfo& info) { + return URLRequestJob::NotifyConnected(info); } void URLRequestHttpJob::NotifyHeadersComplete() {
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h index 8ddb724..ef89c70 100644 --- a/net/url_request/url_request_http_job.h +++ b/net/url_request/url_request_http_job.h
@@ -36,6 +36,7 @@ class HttpTransaction; class HttpUserAgentSettings; class SSLPrivateKey; +struct TransportInfo; class UploadDataStream; // A URLRequestJob subclass that is built on top of HttpTransaction. It @@ -122,7 +123,7 @@ // This just forwards the call to URLRequestJob::NotifyConnected(). // We need it because that method is protected and cannot be bound in a // callback in this class. - int NotifyConnectedCallback(); + int NotifyConnectedCallback(const TransportInfo& info); void RestartTransactionWithAuth(const AuthCredentials& credentials);
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index e1e4d408..88d9a007 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc
@@ -385,8 +385,8 @@ return GURL(); } -int URLRequestJob::NotifyConnected() { - return request_->NotifyConnected(); +int URLRequestJob::NotifyConnected(const TransportInfo& info) { + return request_->NotifyConnected(info); } void URLRequestJob::NotifyCertificateRequested(
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h index 7e34fff..b3f9216 100644 --- a/net/url_request/url_request_job.h +++ b/net/url_request/url_request_job.h
@@ -45,6 +45,7 @@ class SSLCertRequestInfo; class SSLInfo; class SSLPrivateKey; +struct TransportInfo; class UploadDataStream; class X509Certificate; @@ -257,7 +258,7 @@ protected: // Notifies the job that we are connected. - int NotifyConnected(); + int NotifyConnected(const TransportInfo& info); // Notifies the job that a certificate is requested. void NotifyCertificateRequested(SSLCertRequestInfo* cert_request_info);
diff --git a/net/url_request/url_request_job_unittest.cc b/net/url_request/url_request_job_unittest.cc index 7db8a73..d4b985c 100644 --- a/net/url_request/url_request_job_unittest.cc +++ b/net/url_request/url_request_job_unittest.cc
@@ -107,6 +107,7 @@ base::Time(), "", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Cache-Control: max-age=10000\n" "Content-Length: 30\n", // Intentionally wrong. @@ -127,6 +128,7 @@ base::Time(), "", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Cache-Control: max-age=10000\n" "Content-Length: +30\n", // Invalid @@ -147,6 +149,7 @@ base::Time(), "", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Cache-Control: max-age=10000\n" "Content-Encoding: gzip\n" @@ -169,6 +172,7 @@ base::Time(), "", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Cache-Control: max-age=10000\n" "Content-Encoding: gzip\n", @@ -190,6 +194,7 @@ base::Time(), "", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 302 Found", "Cache-Control: max-age=10000\n" "Location: http://www.google.com/destination\n" @@ -212,6 +217,7 @@ base::Time(), "", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Content-Encoding: gzip\n", base::Time(), @@ -232,6 +238,7 @@ base::Time(), "", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Content-Encoding: gzip\n" "Content-Length: 21\n", @@ -253,6 +260,7 @@ base::Time(), "", LOAD_NORMAL, + DefaultTransportInfo(), "HTTP/1.1 200 OK", "Cache-Control: max-age=10000\n" "Content-Encoding: br\n"
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index 5b2da3c..beaf7acc 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc
@@ -247,8 +247,8 @@ run_loop.Run(); } -int TestDelegate::OnConnected(URLRequest* request) { - connected_count_++; +int TestDelegate::OnConnected(URLRequest* request, const TransportInfo& info) { + transports_.push_back(info); return on_connected_result_; }
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h index 932b3e0f..2b4d68fe 100644 --- a/net/url_request/url_request_test_util.h +++ b/net/url_request/url_request_test_util.h
@@ -12,6 +12,7 @@ #include <memory> #include <string> #include <utility> +#include <vector> #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" @@ -27,6 +28,7 @@ #include "net/base/net_errors.h" #include "net/base/network_delegate_impl.h" #include "net/base/request_priority.h" +#include "net/base/transport_info.h" #include "net/cert/cert_verifier.h" #include "net/cert/ct_policy_enforcer.h" #include "net/cookies/cookie_monster.h" @@ -167,7 +169,9 @@ on_complete_ = std::move(on_complete); } + // Sets the result returned by subsequent calls to OnConnected(). void set_on_connected_result(int result) { on_connected_result_ = result; } + void set_cancel_in_received_redirect(bool val) { cancel_in_rr_ = val; } void set_cancel_in_response_started(bool val) { cancel_in_rs_ = val; } void set_cancel_in_received_data(bool val) { cancel_in_rd_ = val; } @@ -182,8 +186,11 @@ credentials_ = credentials; } + // Returns the list of arguments with which OnConnected() was called. + // The arguments are listed in the same order as the calls were received. + const std::vector<TransportInfo>& transports() const { return transports_; } + // query state - int connected_count() const { return connected_count_; } const std::string& data_received() const { return data_received_; } int bytes_received() const { return static_cast<int>(data_received_.size()); } int response_started_count() const { return response_started_count_; } @@ -204,7 +211,7 @@ int request_status() const { return request_status_; } // URLRequest::Delegate: - int OnConnected(URLRequest*) override; + int OnConnected(URLRequest* request, const TransportInfo& info) override; void OnReceivedRedirect(URLRequest* request, const RedirectInfo& redirect_info, bool* defer_redirect) override; @@ -244,7 +251,7 @@ base::OnceClosure on_auth_required_; // tracks status of callbacks - int connected_count_ = 0; + std::vector<TransportInfo> transports_; int response_started_count_ = 0; int received_bytes_count_ = 0; int received_redirect_count_ = 0;
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index e7426b40..0e83d22d 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -57,6 +57,8 @@ #include "net/base/escape.h" #include "net/base/features.h" #include "net/base/hash_value.h" +#include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" #include "net/base/isolation_info.h" #include "net/base/load_flags.h" #include "net/base/load_timing_info.h" @@ -66,6 +68,7 @@ #include "net/base/proxy_server.h" #include "net/base/request_priority.h" #include "net/base/test_completion_callback.h" +#include "net/base/transport_info.h" #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" @@ -166,6 +169,8 @@ using net::test::IsOk; using net::test_server::RegisterDefaultHandlers; using testing::AnyOf; +using testing::ElementsAre; +using testing::IsEmpty; using base::ASCIIToUTF16; using base::Time; @@ -1485,7 +1490,7 @@ request->Start(); delegate.RunUntilComplete(); - EXPECT_EQ(delegate.connected_count(), 0); + EXPECT_THAT(delegate.transports(), IsEmpty()); } // This test verifies that URLRequest::Delegate's OnConnected() callback @@ -1503,7 +1508,10 @@ request->Start(); delegate.RunUntilComplete(); - EXPECT_EQ(delegate.connected_count(), 1); + TransportInfo expected_transport; + expected_transport.endpoint = + IPEndPoint(IPAddress::IPv4Localhost(), test_server.port()); + EXPECT_THAT(delegate.transports(), ElementsAre(expected_transport)); } // This test verifies that URLRequest::Delegate's OnConnected() callback is @@ -1523,13 +1531,17 @@ request->Start(); delegate.RunUntilRedirect(); - EXPECT_EQ(delegate.connected_count(), 1); + TransportInfo expected_transport; + expected_transport.endpoint = + IPEndPoint(IPAddress::IPv4Localhost(), test_server.port()); + EXPECT_THAT(delegate.transports(), ElementsAre(expected_transport)); request->FollowDeferredRedirect(/*removed_headers=*/{}, /*modified_headers=*/{}); delegate.RunUntilComplete(); - EXPECT_EQ(delegate.connected_count(), 2); + EXPECT_THAT(delegate.transports(), + ElementsAre(expected_transport, expected_transport)); } // This test verifies that when the URLRequest Delegate returns an error from @@ -1548,7 +1560,11 @@ request->Start(); delegate.RunUntilComplete(); - EXPECT_EQ(delegate.connected_count(), 1); + TransportInfo expected_transport; + expected_transport.endpoint = + IPEndPoint(IPAddress::IPv4Localhost(), test_server.port()); + EXPECT_THAT(delegate.transports(), ElementsAre(expected_transport)); + EXPECT_TRUE(delegate.request_failed()); EXPECT_THAT(delegate.request_status(), IsError(ERR_NOT_IMPLEMENTED)); }
diff --git a/pdf/BUILD.gn b/pdf/BUILD.gn index abbe76a..04fffbb 100644 --- a/pdf/BUILD.gn +++ b/pdf/BUILD.gn
@@ -149,7 +149,7 @@ "//ui/gfx/range", ] - if (is_linux) { + if (is_linux || is_chromeos) { sources += [ "pdfium/pdfium_font_linux.cc", "pdfium/pdfium_font_linux.h",
diff --git a/ppapi/BUILD.gn b/ppapi/BUILD.gn index ad1525f1..8d0cac67 100644 --- a/ppapi/BUILD.gn +++ b/ppapi/BUILD.gn
@@ -457,7 +457,7 @@ [ ":ppapi_nacl_tests(//build/toolchain/nacl:glibc_${target_cpu})" ] } - if (is_linux && enable_nacl_nonsfi) { + if ((is_linux || is_chromeos) && enable_nacl_nonsfi) { data_deps += [ ":ppapi_nacl_tests(//build/toolchain/nacl:newlib_pnacl_nonsfi)" ] }
diff --git a/ppapi/tests/extensions/BUILD.gn b/ppapi/tests/extensions/BUILD.gn index 2a6342f1..1abf250 100644 --- a/ppapi/tests/extensions/BUILD.gn +++ b/ppapi/tests/extensions/BUILD.gn
@@ -19,7 +19,7 @@ ":ppapi_tests_extensions_popup($newlib)", ":ppapi_tests_extensions_socket_permissions($newlib)", ] - if ((target_cpu == "x86" || target_cpu == "x64") && is_linux && + if ((target_cpu == "x86" || target_cpu == "x64") && (is_linux || is_chromeos) && enable_nacl_nonsfi) { nonsfi = "//build/toolchain/nacl:newlib_pnacl_nonsfi" data_deps += [ ":ppapi_tests_extensions_packaged_app($nonsfi)" ]
diff --git a/printing/BUILD.gn b/printing/BUILD.gn index 446773a..766501a 100644 --- a/printing/BUILD.gn +++ b/printing/BUILD.gn
@@ -206,7 +206,7 @@ if (use_cups) { configs += [ ":cups" ] - if (is_linux) { + if (is_linux || is_chromeos) { # CUPS 1.6 deprecated the PPD APIs, but we will stay with this API # for now as the suitability of the replacement is unclear. # More info: crbug.com/226176 @@ -312,7 +312,7 @@ if (is_fuchsia) { sources += [ "image_fuchsia.cc" ] } - if (is_linux) { + if (is_linux || is_chromeos) { sources += [ "image_linux.cc" ] } if (is_mac) {
diff --git a/printing/buildflags/buildflags.gni b/printing/buildflags/buildflags.gni index ed471184..bb9dabfc 100644 --- a/printing/buildflags/buildflags.gni +++ b/printing/buildflags/buildflags.gni
@@ -20,7 +20,7 @@ # Enable exporting to tagged PDF. enable_tagged_pdf = !is_android && !is_chromecast && !is_ios && !is_fuchsia - if (use_fuzzing_engine && is_linux) { + if (use_fuzzing_engine && (is_linux || is_chromeos)) { # For fuzzing, just restrict to chromeos and linux. use_cups = true } else {
diff --git a/remoting/client/display/BUILD.gn b/remoting/client/display/BUILD.gn index 0897284..a0c8de3 100644 --- a/remoting/client/display/BUILD.gn +++ b/remoting/client/display/BUILD.gn
@@ -43,7 +43,7 @@ libs = [ "GLESv2" ] } - if (is_linux) { + if (is_linux || is_chromeos) { libs = [ "GL" ] }
diff --git a/remoting/codec/BUILD.gn b/remoting/codec/BUILD.gn index f6ff1ab..b1a76d5 100644 --- a/remoting/codec/BUILD.gn +++ b/remoting/codec/BUILD.gn
@@ -41,7 +41,7 @@ # Currently, building WebrtcVideoEncoderGpu is only supported on Windows and # Linux, and encoding with WebrtcVideoEncoderGpu is only supported on Windows. - if (is_win || is_linux) { + if (is_win || is_linux || is_chromeos) { public_configs = [ "//skia:skia_config" ] sources += [ "webrtc_video_encoder_gpu.cc",
diff --git a/remoting/protocol/BUILD.gn b/remoting/protocol/BUILD.gn index 5fd981cc..fdd9be64 100644 --- a/remoting/protocol/BUILD.gn +++ b/remoting/protocol/BUILD.gn
@@ -237,7 +237,7 @@ defines = [] # Must match condition in //remoting/codec/BUILD.gn - if (is_win || is_linux) { + if (is_win || is_linux || is_chromeos) { defines += [ "USE_H264_ENCODER" ] deps += [ "//media",
diff --git a/remoting/remoting_options.gni b/remoting/remoting_options.gni index 7cd564c..b7e9fa6 100644 --- a/remoting/remoting_options.gni +++ b/remoting/remoting_options.gni
@@ -6,7 +6,7 @@ import("//build/config/ui.gni") enable_remoting_host = - is_win || (is_linux && (is_chromeos || use_x11)) || is_mac + is_win || (is_chromeos || (is_linux && use_x11)) || is_mac enable_me2me_host = is_win || (is_linux && !is_chromeos && use_x11) || is_mac # Enable the multi-process host on Windows by default.
diff --git a/services/tracing/perfetto/perfetto_integration_unittest.cc b/services/tracing/perfetto/perfetto_integration_unittest.cc index a6e6518b..c5b00b31 100644 --- a/services/tracing/perfetto/perfetto_integration_unittest.cc +++ b/services/tracing/perfetto/perfetto_integration_unittest.cc
@@ -42,9 +42,21 @@ return base::StrCat({mojom::kPerfettoProducerNamePrefix, "123"}); } +RebindableTaskRunner* GetPerfettoTaskRunner() { + static base::NoDestructor<RebindableTaskRunner> task_runner; + return task_runner.get(); +} + class PerfettoIntegrationTest : public testing::Test { public: void SetUp() override { + auto* perfetto_task_runner = GetPerfettoTaskRunner(); + auto* perfetto_platform = + PerfettoTracedProcess::Get()->perfetto_platform_for_testing(); + if (!perfetto_platform->did_start_task_runner()) + perfetto_platform->StartTaskRunner(perfetto_task_runner); + perfetto_task_runner->set_task_runner(base::ThreadTaskRunnerHandle::Get()); + PerfettoTracedProcess::ResetTaskRunnerForTesting(); PerfettoTracedProcess::Get()->ClearDataSourcesForTesting(); data_source_ = TestDataSource::CreateAndRegisterDataSource(
diff --git a/services/tracing/perfetto/test_utils.cc b/services/tracing/perfetto/test_utils.cc index a8366d5..074b557d 100644 --- a/services/tracing/perfetto/test_utils.cc +++ b/services/tracing/perfetto/test_utils.cc
@@ -410,6 +410,9 @@ MockProducer::~MockProducer() = default; +RebindableTaskRunner::RebindableTaskRunner() = default; +RebindableTaskRunner::~RebindableTaskRunner() = default; + void MockProducer::WritePacketBigly(base::OnceClosure on_write_complete) { PerfettoTracedProcess::Get() ->GetTaskRunner() @@ -420,4 +423,22 @@ std::move(on_write_complete)); } +bool RebindableTaskRunner::PostDelayedTask(const base::Location& from_here, + base::OnceClosure task, + base::TimeDelta delay) { + return task_runner_->PostDelayedTask(from_here, std::move(task), delay); +} + +bool RebindableTaskRunner::PostNonNestableDelayedTask( + const base::Location& from_here, + base::OnceClosure task, + base::TimeDelta delay) { + return task_runner_->PostNonNestableDelayedTask(from_here, std::move(task), + delay); +} + +bool RebindableTaskRunner::RunsTasksInCurrentSequence() const { + return task_runner_->RunsTasksInCurrentSequence(); +} + } // namespace tracing
diff --git a/services/tracing/perfetto/test_utils.h b/services/tracing/perfetto/test_utils.h index c33d41c7..7963a76 100644 --- a/services/tracing/perfetto/test_utils.h +++ b/services/tracing/perfetto/test_utils.h
@@ -226,6 +226,31 @@ std::unique_ptr<MockProducerHost> producer_host_; }; +// A proxy task runner which can be dynamically pointed to route tasks into a +// different task runner. +class RebindableTaskRunner : public base::SequencedTaskRunner { + public: + RebindableTaskRunner(); + + void set_task_runner(scoped_refptr<base::SequencedTaskRunner> task_runner) { + task_runner_ = task_runner; + } + + // base::SequecedTaskRunner implementation. + bool PostDelayedTask(const base::Location& from_here, + base::OnceClosure task, + base::TimeDelta delay) override; + bool PostNonNestableDelayedTask(const base::Location& from_here, + base::OnceClosure task, + base::TimeDelta delay) override; + bool RunsTasksInCurrentSequence() const override; + + private: + ~RebindableTaskRunner() override; + + scoped_refptr<base::SequencedTaskRunner> task_runner_; +}; + } // namespace tracing #endif // SERVICES_TRACING_PERFETTO_TEST_UTILS_H_
diff --git a/services/tracing/tracing_service_unittest.cc b/services/tracing/tracing_service_unittest.cc index 07f7729..6e5cb97 100644 --- a/services/tracing/tracing_service_unittest.cc +++ b/services/tracing/tracing_service_unittest.cc
@@ -41,40 +41,8 @@ namespace tracing { namespace { -// A task runner which can be dynamically redirected to a different task runner. -class ProxyTaskRunner : public base::SequencedTaskRunner { - public: - ProxyTaskRunner() = default; - - void set_task_runner(scoped_refptr<base::SequencedTaskRunner> task_runner) { - task_runner_ = task_runner; - } - - bool PostDelayedTask(const base::Location& from_here, - base::OnceClosure task, - base::TimeDelta delay) override { - return task_runner_->PostDelayedTask(from_here, std::move(task), delay); - } - - bool PostNonNestableDelayedTask(const base::Location& from_here, - base::OnceClosure task, - base::TimeDelta delay) override { - return task_runner_->PostNonNestableDelayedTask(from_here, std::move(task), - delay); - } - - bool RunsTasksInCurrentSequence() const override { - return task_runner_->RunsTasksInCurrentSequence(); - } - - private: - ~ProxyTaskRunner() override = default; - - scoped_refptr<base::SequencedTaskRunner> task_runner_; -}; - -ProxyTaskRunner* GetProxyTaskRunner() { - static base::NoDestructor<ProxyTaskRunner> task_runner; +RebindableTaskRunner* GetPerfettoTaskRunner() { + static base::NoDestructor<RebindableTaskRunner> task_runner; return task_runner.get(); } @@ -86,12 +54,12 @@ // Since Perfetto's platform backend can only be initialized once in a // process, we give it a task runner that can outlive the per-test task // environment. - auto* proxy_task_runner = GetProxyTaskRunner(); + auto* perfetto_task_runner = GetPerfettoTaskRunner(); auto* perfetto_platform = PerfettoTracedProcess::Get()->perfetto_platform_for_testing(); if (!perfetto_platform->did_start_task_runner()) - perfetto_platform->StartTaskRunner(proxy_task_runner); - proxy_task_runner->set_task_runner(base::ThreadTaskRunnerHandle::Get()); + perfetto_platform->StartTaskRunner(perfetto_task_runner); + perfetto_task_runner->set_task_runner(base::ThreadTaskRunnerHandle::Get()); // Also tell PerfettoTracedProcess to use the current task environment. PerfettoTracedProcess::ResetTaskRunnerForTesting(
diff --git a/styleguide/c++/c++11.html b/styleguide/c++/c++11.html index 6a91c4f..633c649 100644 --- a/styleguide/c++/c++11.html +++ b/styleguide/c++/c++11.html
@@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!DOCTYPE html> <!-- Copyright 2014 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be @@ -51,7 +51,7 @@ <li><b>C++14:</b> <i>Default allowed; see banned features below</i></li> <li><b>C++17:</b> <i>Not yet supported in Chromium, unlikely before mid-2021; <a href="http://crbug.com/752720">tracking bug</a></i></li> <li><b>C++20:</b> <i>Not yet standardized</i></li> -<li><b>Abseil:</b> Initially supported July 27, 2020; see allowed/banned/TBD features below</li> +<li><b>Abseil:</b> Initially supported July 31, 2020; see allowed/banned/TBD features below</li> </ul></p> @@ -290,7 +290,11 @@ </tr> <tr> -<td colspan="5" style="text-align:center">TBD</td> +<td>Variant</td> +<td><code>absl::variant</code></td> +<td>Early adaptation of C++17 std::variant.</td> +<td><a href="https://en.cppreference.com/w/cpp/utility/variant">std::variant</a></td> +<td><a href="https://groups.google.com/a/chromium.org/g/cxx/c/DqvG-TpvMyU">Discussion thread</a></td> </tr> </tbody> @@ -469,14 +473,6 @@ <td>Overlaps with <code>Time</code> APIs in <code>base/</code>.</td> </tr> -<tr> -<td>Variant</td> -<td><code>absl::variant</code></td> -<td>Early adaptation of C++17 std::variant.</td> -<td><a href="https://en.cppreference.com/w/cpp/utility/variant">std::variant</a></td> -<td></td> -</tr> - </tbody> </table>
diff --git a/testing/scripts/representative_perf_test_data/representatives_frame_times_upper_limit.json b/testing/scripts/representative_perf_test_data/representatives_frame_times_upper_limit.json index 3f09038..91466a0 100644 --- a/testing/scripts/representative_perf_test_data/representatives_frame_times_upper_limit.json +++ b/testing/scripts/representative_perf_test_data/representatives_frame_times_upper_limit.json
@@ -7,10 +7,8 @@ }, "filter_terrain_svg": { "ci_095": 0.574, - "_comment": "crbug.com/1053614", "avg": 33.202, - "cpu_wall_time_ratio": 0.368, - "experimental": true + "cpu_wall_time_ratio": 0.368 }, "web_animation_value_type_transform_complex": { "ci_095": 1.704, @@ -70,10 +68,8 @@ }, "css_value_type_shadow": { "ci_095": 1.482, - "_comment": "crbug.com/1093313", "avg": 56.704, - "cpu_wall_time_ratio": 0.414, - "experimental": true + "cpu_wall_time_ratio": 0.414 }, "nvidia_vertex_buffer_object": { "ci_095": 3.605, @@ -109,10 +105,8 @@ }, "css_value_type_shadow": { "ci_095": 18.3, - "_comment": "crbug.com/1093313", "avg": 65.502, - "cpu_wall_time_ratio": 0.585, - "experimental": true + "cpu_wall_time_ratio": 0.585 }, "animometer_webgl_attrib_arrays": { "ci_095": 0.44,
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 8a26f83..e21867f 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1225,6 +1225,46 @@ ] } ], + "BrowserVerifiedUserActivationKeyboardTrigger": [ + { + "platforms": [ + "windows", + "mac", + "chromeos", + "linux", + "android", + "android_weblayer" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "BrowserVerifiedUserActivationKeyboard" + ] + } + ] + } + ], + "BrowserVerifiedUserActivationMouseTrigger": [ + { + "platforms": [ + "windows", + "mac", + "chromeos", + "linux", + "android", + "android_weblayer" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "BrowserVerifiedUserActivationMouse" + ] + } + ] + } + ], "CSSMatchedPropertiesCacheDependencies": [ { "platforms": [ @@ -1389,6 +1429,21 @@ ] } ], + "CertVerifierBuiltin": [ + { + "platforms": [ + "mac" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "CertVerifierBuiltin" + ] + } + ] + } + ], "ChromeCleanupDistribution": [ { "platforms": [
diff --git a/third_party/abseil-cpp/BUILD.gn b/third_party/abseil-cpp/BUILD.gn index 0373bff..dffe05f3 100644 --- a/third_party/abseil-cpp/BUILD.gn +++ b/third_party/abseil-cpp/BUILD.gn
@@ -53,14 +53,6 @@ } } } - - # Usage of Abseil in Chromium is guarded by an explicit opt-in list, before - # adding projects to this list please reach out to cxx@chromium.org and CC: - # - https://cs.chromium.org/chromium/src/third_party/abseil-cpp/OWNERS - # - # More information can be found at: - # https://docs.google.com/document/d/1DgS1-A3rzboTLjpf4m1sqkJgWjnY_Ru2dokk1X1vBDU - visibility = absl_visibility } group("absl_component_deps") { @@ -69,8 +61,8 @@ "//third_party/abseil-cpp/absl/base", "//third_party/abseil-cpp/absl/base:config", "//third_party/abseil-cpp/absl/base:core_headers", - "//third_party/abseil-cpp/absl/container:flat_hash_map", "//third_party/abseil-cpp/absl/container:fixed_array", + "//third_party/abseil-cpp/absl/container:flat_hash_map", "//third_party/abseil-cpp/absl/container:flat_hash_set", "//third_party/abseil-cpp/absl/container:inlined_vector", "//third_party/abseil-cpp/absl/debugging:failure_signal_handler", @@ -181,12 +173,8 @@ "absl/strings:match_test", "absl/strings:str_replace_test", "absl/strings:string_view_test", - - # TODO(mbonadei): On iOS, gtest doesn't support death tests. Fix upstream - # Abseil to use EXPECT_DEATH_IF_SUPPORTED instead of EXPECT_DEATH. - # "absl/types:optional_test", - # "absl/types:variant_test", - + "absl/types:optional_test", + "absl/types:variant_test", "//third_party/googletest:gtest_main", ] } @@ -203,6 +191,7 @@ "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/types:optional", "//third_party/abseil-cpp/absl/types:span", + "//third_party/abseil-cpp/absl/types:variant", "//third_party/googletest:gtest", ] }
diff --git a/third_party/abseil-cpp/README.chromium b/third_party/abseil-cpp/README.chromium index 37dbe88..cb4beff 100644 --- a/third_party/abseil-cpp/README.chromium +++ b/third_party/abseil-cpp/README.chromium
@@ -9,8 +9,10 @@ Description: This directory contains the source code of Abseil for C++. This can be used by -Chromium's dependencies, but shouldn't be used by Chromium itself. -See: https://goo.gl/TgnJb8. +Chromium, subject to the guidance at https://chromium-cpp.appspot.com/; it can +be used without restriction by Chromium's dependencies, except that objects +compiled into Chromium itself cannot use anything relying on +absl::base_internal::FastTypeId (see https://crbug.com/1096380). How to update Abseil:
diff --git a/third_party/abseil-cpp/absl.gni b/third_party/abseil-cpp/absl.gni index 88ce3aa..dc87e2a6 100644 --- a/third_party/abseil-cpp/absl.gni +++ b/third_party/abseil-cpp/absl.gni
@@ -7,9 +7,6 @@ # This template will correctly set "configs" and "public_configs" in order # to correctly compile abseil in Chromium. # -# Targets that set visibility should set it to something more restrictive than -# `absl_visibility` (defined below). -# # Usage: # Most of the times its usage will be similar to the example below but all # the arguments avilable in source_set are also available for absl_source_set. @@ -22,35 +19,6 @@ import("//build_overrides/build.gni") -# Usage of Abseil in Chromium is guarded by an explicit opt-in list, before -# adding projects to this list please reach out to cxx@chromium.org and CC: -# - https://cs.chromium.org/chromium/src/third_party/abseil-cpp/OWNERS -# -# More information can be found at: -# https://docs.google.com/document/d/1DgS1-A3rzboTLjpf4m1sqkJgWjnY_Ru2dokk1X1vBDU -declare_args() { - # Additional targets that can depend on absl. - additional_absl_clients = [] -} - -_chromium_absl_clients = [ - "//chrome/services/sharing/nearby/platform_v2/*", - "//third_party/blink/renderer/modules/peerconnection", - "//third_party/blink/renderer/platform", - "//third_party/googletest:gtest", - "//third_party/openscreen/src/third_party/abseil/*", - "//third_party/private_membership/*", - "//third_party/shell-encryption/*", - "//third_party/webrtc/*", - "//third_party/nearby/*", -] - -# When adding a new package to `absl_visibility`, please check that all the -# Abseil dependencies that are required are listed in the dependencies of -# //third_party/abseil-cpp:absl. If not, please add them and run: -# //third_party/abseil-cpp/generate_def_file.py. -absl_visibility = _chromium_absl_clients + additional_absl_clients - template("absl_source_set") { source_set(target_name) { forward_variables_from(invoker, "*") @@ -75,8 +43,14 @@ public_configs += [ "//third_party/abseil-cpp:absl_include_config" ] if (!defined(visibility)) { + # Within Chromium builds, restrict direct visibility of Abseil sources, so + # users must depend on //third_party/abseil-cpp:absl. This prevents use of + # banned targets like absl/types:any. A few targets require exceptions. + # TODO(crbug.com/1096380): Consider replacing build_with_chromium with + # is_component_build for a narrower, more accurate condition. if (build_with_chromium) { visibility = [ + # Abseil itself. "//third_party/abseil-cpp/*", # WebRTC binary to run PSNR and SSIM video quality analysis. It @@ -85,7 +59,7 @@ # component because it uses absl/flags. "//third_party/webrtc/rtc_tools:frame_analyzer", - # WebRTC binaries used by //:chromium_builder_asan, they both + # WebRTC binaries used by //:chromium_builder_asan. They both # statically link absl (because they depend on absl/flags) and are # used by Chromium only when is_component_build=false. "//third_party/webrtc/rtc_tools:rtp_generator",
diff --git a/third_party/abseil-cpp/absl/types/BUILD.gn b/third_party/abseil-cpp/absl/types/BUILD.gn index 40b9d9e6..f9f1515c 100644 --- a/third_party/abseil-cpp/absl/types/BUILD.gn +++ b/third_party/abseil-cpp/absl/types/BUILD.gn
@@ -98,36 +98,34 @@ "//third_party/abseil-cpp/absl/meta:type_traits", ] } -# TODO(mbonadei): On iOS, gtest doesn't support death tests. Fix upstream -# Abseil to use EXPECT_DEATH_IF_SUPPORTED instead of EXPECT_DEATH. -# absl_source_set("optional_test") { -# testonly = true -# sources = [ "optional_test.cc" ] -# deps = [ -# ":optional", -# "//third_party/abseil-cpp/absl/base:config", -# "//third_party/abseil-cpp/absl/base:raw_logging_internal", -# "//third_party/abseil-cpp/absl/meta:type_traits", -# "//third_party/abseil-cpp/absl/strings", -# "//third_party/googletest:gtest", -# ] -# visibility = [ "*" ] -# } -# -# absl_source_set("variant_test") { -# testonly = true -# sources = [ "variant_test.cc" ] -# if (is_clang) { -# cflags_cc = [ "-Wno-unused-function" ] -# } -# deps = [ -# ":variant", -# "//third_party/abseil-cpp/absl/base:config", -# "//third_party/abseil-cpp/absl/base:core_headers", -# "//third_party/abseil-cpp/absl/memory", -# "//third_party/abseil-cpp/absl/meta:type_traits", -# "//third_party/abseil-cpp/absl/strings", -# "//third_party/googletest:gtest", -# "//third_party/googletest:gmock", -# ] -# } + +absl_source_set("optional_test") { + testonly = true + sources = [ "optional_test.cc" ] + deps = [ + ":optional", + "//third_party/abseil-cpp/absl/base:config", + "//third_party/abseil-cpp/absl/base:raw_logging_internal", + "//third_party/abseil-cpp/absl/meta:type_traits", + "//third_party/abseil-cpp/absl/strings", + "//third_party/googletest:gtest", + ] +} + +absl_source_set("variant_test") { + testonly = true + sources = [ "variant_test.cc" ] + if (is_clang) { + cflags_cc = [ "-Wno-unused-function" ] + } + deps = [ + ":variant", + "//third_party/abseil-cpp/absl/base:config", + "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/meta:type_traits", + "//third_party/abseil-cpp/absl/strings", + "//third_party/googletest:gtest", + "//third_party/googletest:gmock", + ] +}
diff --git a/third_party/abseil-cpp/absl_hardening_test.cc b/third_party/abseil-cpp/absl_hardening_test.cc index 4b280986..cbe8532 100644 --- a/third_party/abseil-cpp/absl_hardening_test.cc +++ b/third_party/abseil-cpp/absl_hardening_test.cc
@@ -12,6 +12,7 @@ #include "third_party/abseil-cpp/absl/strings/string_view.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/abseil-cpp/absl/types/span.h" +#include "third_party/abseil-cpp/absl/types/variant.h" namespace { @@ -70,4 +71,10 @@ EXPECT_DEATH_IF_SUPPORTED(absl::MakeConstSpan(&v1[2], &v[0]), ""); } +TEST(AbslHardeningTest, Variant) { + absl::variant<int, std::string> variant = 5; + EXPECT_DEATH_IF_SUPPORTED(absl::get<std::string>(variant), ""); + EXPECT_DEATH_IF_SUPPORTED(absl::get<1>(variant), ""); +} + } // namespace
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 0f3f1bf..7f0ea90 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -228,6 +228,10 @@ const base::Feature kIntensiveWakeUpThrottling{ "IntensiveWakeUpThrottling", base::FEATURE_DISABLED_BY_DEFAULT}; +// When enabled, timers with timeout=0 are not throttled. +const base::Feature kOptOutZeroTimeoutTimersFromThrottling{ + "OptOutZeroTimeoutTimersFromThrottling", base::FEATURE_DISABLED_BY_DEFAULT}; + // When enabled, no throttling is applied to a page when it uses WebRTC. // // This allows a page to use a timer to do video processing on frames. An
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn index cd0090d..9401ecb 100644 --- a/third_party/blink/public/common/BUILD.gn +++ b/third_party/blink/public/common/BUILD.gn
@@ -168,13 +168,9 @@ "sms/sms_receiver_destroyed_reason.h", "sms/sms_receiver_outcome.h", "switches.h", - "tokens/frame_token.h", - "tokens/frame_token_mojom_traits.h", - "tokens/portal_token.h", - "tokens/portal_token_mojom_traits.h", "tokens/token_mojom_traits_helper.h", - "tokens/worker_tokens.h", - "tokens/worker_tokens_mojom_traits.h", + "tokens/tokens.h", + "tokens/tokens_mojom_traits.h", "user_agent/user_agent_metadata.h", "web_cache/web_cache_resource_type_stats.h", "web_package/signed_exchange_consts.h",
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 0e033c8..1e2fc23 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -61,6 +61,8 @@ BLINK_COMMON_EXPORT extern const char kIntensiveWakeUpThrottling_GracePeriodSeconds_Name[]; +BLINK_COMMON_EXPORT extern const base::Feature + kOptOutZeroTimeoutTimersFromThrottling; BLINK_COMMON_EXPORT extern const base::Feature kOptOutWebRTCFromAllThrottling; #if BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
diff --git a/third_party/blink/public/common/tokens/README.md b/third_party/blink/public/common/tokens/README.md index b847885..c8bd024 100644 --- a/third_party/blink/public/common/tokens/README.md +++ b/third_party/blink/public/common/tokens/README.md
@@ -12,22 +12,18 @@ ## Adding a new token -Suppose you want to add a new token type, `FooToken`. You would do the following: +Suppose you want to add a new token type. You would do the following: - - Create a new `foo_token.h` header in [`/third_party/blink/public/common/tokens`](/third_party/blink/public/common/tokens) - and define the token using [`util::TokenType<...>`](/base/util/type_safety/token_type.h). - See [`/third_party/blink/public/common/tokens/worker_tokens.h`](/third_party/blink/public/common/tokens/worker_tokens.h) - for an example. - - Create a new `foo_token.mojom` defining a Mojo struct for the token type in - [`/third_party/blink/public/mojom/tokens`](/third_party/blink/public/mojom/tokens). - Be sure to follow the convention that the struct contain a single - `base.mojom.UnguessableToken` member named `value`. See - [`worker_tokens.mojom`](/third_party/blink/public/mojom/tokens/worker_tokens.mojom) for an example. - - Create a new `foo_token_mojom_traits.h` header in [`/third_party/blink/public/common/tokens`](/third_party/blink/public/common/tokens) - that implements `mojo::StructTraits` serialization. Use the templated - [`TokenMojomTraitsHelper<...>`](/third_party/blink/public/common/token_mojom_traits_helper.h) - helper class. See [`worker_tokens_mojom_traits.h`](/third_party/blink/public/common/tokens/worker_tokens_mojom_traits.h) for an example. + - Add a new C++ token type to + [`/third_party/blink/public/common/tokens/tokens.h`](/third_party/blink/public/common/tokens/tokens.h). + - Add an equivalent Mojom token type to + [`/third_party/blink/public/mojom/tokens/tokens.mojom`](/third_party/blink/public/mojom/tokens/tokens.mojom). + Be sure to follow the convention that the struct contains a single + `base.mojom.UnguessableToken` member named `value`. + - Create a new Mojom traits declaration to + [`/third_party/blink/public/common/tokens/tokens_mojom_traits.h`](/third_party/blink/public/common/tokens/tokens_mojom_traits.h). + Use the templated [`TokenMojomTraitsHelper<...>`](/third_party/blink/public/common/token_mojom_traits_helper.h) helper class. - Update [`mojom/tokens/BUILD.gn`](third_party/blink/public/mojom/tokens/BUILD.gn) and add a new typemap definition for the token to the `shared_cpp_typemaps` section. - If your token needs to be sent via legacy IPC as well, add the appropriate - definition to [`/content/common/content_param_traits.h`](/content/common/content_param_traits.h). \ No newline at end of file + definition to [`/content/common/content_param_traits.h`](/content/common/content_param_traits.h).
diff --git a/third_party/blink/public/common/tokens/frame_token.h b/third_party/blink/public/common/tokens/frame_token.h deleted file mode 100644 index 70f3023..0000000 --- a/third_party/blink/public/common/tokens/frame_token.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_FRAME_TOKEN_H_ -#define THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_FRAME_TOKEN_H_ - -#include "base/util/type_safety/token_type.h" - -namespace blink { - -// Frame token type. Note that this token is type-mapped to its mojom equivalent -// (defined in third_party/blink/public/mojom/tokens/frame_token.mojom). See -// frame_token_mojom_traits.h for the StructTraits. -using FrameToken = util::TokenType<class FrameTokenTypeMarker>; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_FRAME_TOKEN_H_
diff --git a/third_party/blink/public/common/tokens/frame_token_mojom_traits.h b/third_party/blink/public/common/tokens/frame_token_mojom_traits.h deleted file mode 100644 index a9974a8..0000000 --- a/third_party/blink/public/common/tokens/frame_token_mojom_traits.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_FRAME_TOKEN_MOJOM_TRAITS_H_ -#define THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_FRAME_TOKEN_MOJOM_TRAITS_H_ - -#include "third_party/blink/public/common/tokens/frame_token.h" -#include "third_party/blink/public/common/tokens/token_mojom_traits_helper.h" -#include "third_party/blink/public/mojom/tokens/frame_token.mojom-shared.h" - -namespace mojo { - -template <> -struct StructTraits<blink::mojom::FrameTokenDataView, blink::FrameToken> - : public blink::TokenMojomTraitsHelper<blink::mojom::FrameTokenDataView, - blink::FrameToken> {}; - -} // namespace mojo - -#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_FRAME_TOKEN_MOJOM_TRAITS_H_
diff --git a/third_party/blink/public/common/tokens/portal_token.h b/third_party/blink/public/common/tokens/portal_token.h deleted file mode 100644 index 53ccda2..0000000 --- a/third_party/blink/public/common/tokens/portal_token.h +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_PORTAL_TOKEN_H_ -#define THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_PORTAL_TOKEN_H_ - -#include "base/util/type_safety/token_type.h" - -namespace blink { - -// Typemapped to blink::mojom::PortalToken (see portal_token_mojom_traits.h). -using PortalToken = util::TokenType<class PortalTokenTypeMarker>; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_PORTAL_TOKEN_H_
diff --git a/third_party/blink/public/common/tokens/portal_token_mojom_traits.h b/third_party/blink/public/common/tokens/portal_token_mojom_traits.h deleted file mode 100644 index c97fc59..0000000 --- a/third_party/blink/public/common/tokens/portal_token_mojom_traits.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_PORTAL_TOKEN_MOJOM_TRAITS_H_ -#define THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_PORTAL_TOKEN_MOJOM_TRAITS_H_ - -#include "third_party/blink/public/common/tokens/portal_token.h" -#include "third_party/blink/public/common/tokens/token_mojom_traits_helper.h" -#include "third_party/blink/public/mojom/tokens/portal_token.mojom-shared.h" - -namespace mojo { - -template <> -struct StructTraits<blink::mojom::PortalTokenDataView, blink::PortalToken> - : public blink::TokenMojomTraitsHelper<blink::mojom::PortalTokenDataView, - blink::PortalToken> {}; - -} // namespace mojo - -#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_PORTAL_TOKEN_MOJOM_TRAITS_H_
diff --git a/third_party/blink/public/common/tokens/tokens.h b/third_party/blink/public/common/tokens/tokens.h new file mode 100644 index 0000000..988f326 --- /dev/null +++ b/third_party/blink/public/common/tokens/tokens.h
@@ -0,0 +1,68 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_H_ +#define THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_H_ + +#include "base/util/type_safety/token_type.h" + +namespace blink { + +// Various token types. These are used as cross-layer and cross-process +// identifiers for objects that exist in blink, but which have representations +// in the browser process. They should not be used to identify objects in +// browser-to-renderer control messages; rather, such messages should exist as +// methods on the interface bound to the object itself. They are fine to use +// for informational messages that cross over other interfaces, in both +// directions. +// +// See README.md for more details. + +//////////////////////////////////////////////////////////////////////////////// +// FRAME TOKENS + +// Uniquely identifies a blink::LocalFrame / blink::WebLocalFrame / +// content::RenderFrame in a renderer process, and its content::RenderFrameHost +// counterpart in the browser. +using LocalFrameToken = util::TokenType<class LocalFrameTokenTypeMarker>; + +// Uniquely identifies an blink::RemoteFrame / blink::WebRemoteFrame / +// content::RenderFrameProxy in a renderer process, and its +// ontent::RenderFrameProxyHost counterpart in the browser. There can be +// multiple RemoteFrames corresponding to a single LocalFrame, and each token +// will be distinct. +using RemoteFrameToken = util::TokenType<class RemoteFrameTokenTypeMarker>; + +//////////////////////////////////////////////////////////////////////////////// +// WORKER TOKENS + +// Identifies a blink::DedicatedWorkerGlobalScope in the renderer and a +// content::DedicatedWorkerHost in the browser. +using DedicatedWorkerToken = + util::TokenType<class DedicatedWorkerTokenTypeMarker>; + +// Identifies a blink::SharedWorkerGlobalScope in the renderer and a +// content::SharedWorkerHost in the browser. +using SharedWorkerToken = util::TokenType<class SharedWorkerTokenTypeMarker>; + +// Identifies a blink::ServiceWorkerGlobalScope in the renderer and a +// content::ServiceWorkerVersion in the browser. +using ServiceWorkerToken = util::TokenType<class ServiceWorkerTokenTypeMarker>; + +//////////////////////////////////////////////////////////////////////////////// +// OTHER TOKENS +// +// Keep this section last. +// +// If you have multiple tokens that make a thematic group, please lift them to +// their own section, in alphabetical order. If adding a new token here, please +// keep the following list in alphabetic order. + +// Identifies a blink::PortalContents / blink::HTMLPortalElement in the +// renderer process, and a content::Portal in the browser process. +using PortalToken = util::TokenType<class PortalTokenTypeMarker>; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_H_
diff --git a/third_party/blink/public/common/tokens/tokens_mojom_traits.h b/third_party/blink/public/common/tokens/tokens_mojom_traits.h new file mode 100644 index 0000000..af23712 --- /dev/null +++ b/third_party/blink/public/common/tokens/tokens_mojom_traits.h
@@ -0,0 +1,74 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_MOJOM_TRAITS_H_ +#define THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_MOJOM_TRAITS_H_ + +#include "third_party/blink/public/common/tokens/token_mojom_traits_helper.h" +#include "third_party/blink/public/common/tokens/tokens.h" +#include "third_party/blink/public/mojom/tokens/tokens.mojom-shared.h" + +namespace mojo { + +// Mojom traits for the various token types. +// See third_party/blink/public/common/tokens/tokens.h for more details. + +//////////////////////////////////////////////////////////////////////////////// +// FRAME TOKENS + +template <> +struct StructTraits<blink::mojom::LocalFrameTokenDataView, + blink::LocalFrameToken> + : public blink::TokenMojomTraitsHelper< + blink::mojom::LocalFrameTokenDataView, + blink::LocalFrameToken> {}; + +template <> +struct StructTraits<blink::mojom::RemoteFrameTokenDataView, + blink::RemoteFrameToken> + : public blink::TokenMojomTraitsHelper< + blink::mojom::RemoteFrameTokenDataView, + blink::RemoteFrameToken> {}; + +//////////////////////////////////////////////////////////////////////////////// +// WORKER TOKENS + +template <> +struct StructTraits<blink::mojom::DedicatedWorkerTokenDataView, + blink::DedicatedWorkerToken> + : public blink::TokenMojomTraitsHelper< + blink::mojom::DedicatedWorkerTokenDataView, + blink::DedicatedWorkerToken> {}; + +template <> +struct StructTraits<blink::mojom::ServiceWorkerTokenDataView, + blink::ServiceWorkerToken> + : public blink::TokenMojomTraitsHelper< + blink::mojom::ServiceWorkerTokenDataView, + blink::ServiceWorkerToken> {}; + +template <> +struct StructTraits<blink::mojom::SharedWorkerTokenDataView, + blink::SharedWorkerToken> + : public blink::TokenMojomTraitsHelper< + blink::mojom::SharedWorkerTokenDataView, + blink::SharedWorkerToken> {}; + +//////////////////////////////////////////////////////////////////////////////// +// OTHER TOKENS +// +// Keep this section last. +// +// If you have multiple tokens that make a thematic group, please lift them to +// their own section, in alphabetical order. If adding a new token here, please +// keep the following list in alphabetic order. + +template <> +struct StructTraits<blink::mojom::PortalTokenDataView, blink::PortalToken> + : public blink::TokenMojomTraitsHelper<blink::mojom::PortalTokenDataView, + blink::PortalToken> {}; + +} // namespace mojo + +#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_MOJOM_TRAITS_H_
diff --git a/third_party/blink/public/common/tokens/worker_tokens.h b/third_party/blink/public/common/tokens/worker_tokens.h deleted file mode 100644 index 42d9ca1..0000000 --- a/third_party/blink/public/common/tokens/worker_tokens.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2020 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. - -// Definitions of all Blink token types. Each is of these has distinct mojo -// type maps for both Blink and non-Blink variants. See the various -// *_mojom_traits.h files in this directory. - -#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_WORKER_TOKENS_H_ -#define THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_WORKER_TOKENS_H_ - -#include "base/util/type_safety/token_type.h" - -namespace blink { - -// Worker token types. Note that these token types are type-mapped to their -// mojom equivalents (defined in mojom/worker_tokens.mojom). See -// worker_tokens_mojom_traits for the StructTraits. -using DedicatedWorkerToken = - util::TokenType<class DedicatedWorkerTokenTypeMarker>; -using SharedWorkerToken = util::TokenType<class SharedWorkerTokenTypeMarker>; -using ServiceWorkerToken = util::TokenType<class ServiceWorkerTokenTypeMarker>; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_WORKER_TOKENS_H_
diff --git a/third_party/blink/public/common/tokens/worker_tokens_mojom_traits.h b/third_party/blink/public/common/tokens/worker_tokens_mojom_traits.h deleted file mode 100644 index 6cfbcba..0000000 --- a/third_party/blink/public/common/tokens/worker_tokens_mojom_traits.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_WORKER_TOKENS_MOJOM_TRAITS_H_ -#define THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_WORKER_TOKENS_MOJOM_TRAITS_H_ - -#include "third_party/blink/public/common/tokens/token_mojom_traits_helper.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" -#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom-shared.h" - -namespace mojo { - -template <> -struct StructTraits<blink::mojom::DedicatedWorkerTokenDataView, - blink::DedicatedWorkerToken> - : public blink::TokenMojomTraitsHelper< - blink::mojom::DedicatedWorkerTokenDataView, - blink::DedicatedWorkerToken> {}; - -template <> -struct StructTraits<blink::mojom::ServiceWorkerTokenDataView, - blink::ServiceWorkerToken> - : public blink::TokenMojomTraitsHelper< - blink::mojom::ServiceWorkerTokenDataView, - blink::ServiceWorkerToken> {}; - -template <> -struct StructTraits<blink::mojom::SharedWorkerTokenDataView, - blink::SharedWorkerToken> - : public blink::TokenMojomTraitsHelper< - blink::mojom::SharedWorkerTokenDataView, - blink::SharedWorkerToken> {}; - -} // namespace mojo - -#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_WORKER_TOKENS_MOJOM_TRAITS_H_
diff --git a/third_party/blink/public/mojom/page/widget.mojom b/third_party/blink/public/mojom/page/widget.mojom index 2010444..5a68c0c8 100644 --- a/third_party/blink/public/mojom/page/widget.mojom +++ b/third_party/blink/public/mojom/page/widget.mojom
@@ -91,6 +91,9 @@ // Disables device emulator. DisableDeviceEmulation(); + + // Binds an WidgetCompositor interface. + BindWidgetCompositor(pending_receiver<WidgetCompositor> host); }; // Implemented in Browser, this interface defines frame-widget-specific methods that @@ -186,3 +189,10 @@ mojo_base.mojom.TextDirection focus_dir, bool is_anchor_first); }; + +// This interface is bound on the compositor thread. +interface WidgetCompositor { + // Requests that the RenderWidget sends back a response after the next main + // frame is generated and presented in the display compositor. + VisualStateRequest() => (); +};
diff --git a/third_party/blink/public/mojom/tokens/BUILD.gn b/third_party/blink/public/mojom/tokens/BUILD.gn index 4b2c60c..d71335db 100644 --- a/third_party/blink/public/mojom/tokens/BUILD.gn +++ b/third_party/blink/public/mojom/tokens/BUILD.gn
@@ -9,24 +9,27 @@ output_prefix = "tokens_mojom" macro_prefix = "TOKENS_MOJOM" - sources = [ - "frame_token.mojom", - "portal_token.mojom", - "worker_tokens.mojom", - ] + sources = [ "tokens.mojom" ] shared_cpp_typemaps = [ { types = [ + # FRAME TOKENS + { + mojom = "blink.mojom.LocalFrameToken" + cpp = "::blink::LocalFrameToken" + }, + { + mojom = "blink.mojom.RemoteFrameToken" + cpp = "::blink::RemoteFrameToken" + }, + + # WORKER TOKENS { mojom = "blink.mojom.DedicatedWorkerToken" cpp = "::blink::DedicatedWorkerToken" }, { - mojom = "blink.mojom.PortalToken" - cpp = "::blink::PortalToken" - }, - { mojom = "blink.mojom.ServiceWorkerToken" cpp = "::blink::ServiceWorkerToken" }, @@ -34,22 +37,21 @@ mojom = "blink.mojom.SharedWorkerToken" cpp = "::blink::SharedWorkerToken" }, - ] - traits_headers = [ - "//third_party/blink/public/common/tokens/portal_token_mojom_traits.h", - "//third_party/blink/public/common/tokens/worker_tokens_mojom_traits.h", - ] - }, - { - types = [ + + # OTHER TOKENS + # + # Keep this section last. + # + # If you have multiple tokens that make a thematic group, please lift + # them to their own section, in alphabetical order. If adding a new + # token here, please keep the following list in alphabetic order. { - mojom = "blink.mojom.FrameToken" - cpp = "::blink::FrameToken" + mojom = "blink.mojom.PortalToken" + cpp = "::blink::PortalToken" }, ] - traits_headers = [ - "//third_party/blink/public/common/tokens/frame_token_mojom_traits.h", - ] + traits_headers = + [ "//third_party/blink/public/common/tokens/tokens_mojom_traits.h" ] }, ]
diff --git a/third_party/blink/public/mojom/tokens/frame_token.mojom b/third_party/blink/public/mojom/tokens/frame_token.mojom deleted file mode 100644 index 36d5e52..0000000 --- a/third_party/blink/public/mojom/tokens/frame_token.mojom +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2020 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 blink.mojom; - -import "mojo/public/mojom/base/unguessable_token.mojom"; - -// This identifier represents the stable identifier between a -// blink::LocalFrame <--> content::RenderFrameHostImpl or a -// blink::RemoteFrame <--> content::RenderFrameProxyHost in the browser process. -// Note that this identifier is unique per render process and -// browser relationship. ie. If this is a LocalFrame, RemoteFrames that -// represent this frame node in other processes will *not* have the same -// identifier. Similarly, if this is a RemoteFrame, the LocalFrame and -// other RemoteFrames that represent this frame node in other processes -// will *not* have the same identifier. This is different than the -// |devtools_frame_token_| in which all representations of this frame node -// have the same value in all processes. This is intended to be transferred -// between browser and renderer processes to uniquely identify a frame in the -// context of that browser/renderer relationship. -// See third_party/blink/public/common/tokens for helper classes. -struct FrameToken { - mojo_base.mojom.UnguessableToken value; -}; \ No newline at end of file
diff --git a/third_party/blink/public/mojom/tokens/portal_token.mojom b/third_party/blink/public/mojom/tokens/portal_token.mojom deleted file mode 100644 index 6a218e7..0000000 --- a/third_party/blink/public/mojom/tokens/portal_token.mojom +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2020 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 blink.mojom; - -import "mojo/public/mojom/base/unguessable_token.mojom"; - -// Identifier sent from the browser process to renderer processes, that is used -// by the renderer to uniquely identify and refer to a portal object created in -// the browser process. -struct PortalToken { - mojo_base.mojom.UnguessableToken value; -};
diff --git a/third_party/blink/public/mojom/tokens/tokens.mojom b/third_party/blink/public/mojom/tokens/tokens.mojom new file mode 100644 index 0000000..75a7d685 --- /dev/null +++ b/third_party/blink/public/mojom/tokens/tokens.mojom
@@ -0,0 +1,56 @@ +// Copyright 2020 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 blink.mojom; + +import "mojo/public/mojom/base/unguessable_token.mojom"; + +// Various token types. These are used as cross-layer and cross-process +// identifiers for objects that exist in blink, but which have representations +// in the browser process. They should not be used to identify objects in +// browser-to-renderer control messages; rather, such messages should exist as +// methods on the interface bound to the object itself. They are fine to use +// for informational messages that cross over other interfaces, in both +// directions. +// +// See third_party/blink/public/common/tokens/tokens.h for more details. + +//////////////////////////////////////////////////////////////////////////////// +// FRAME TOKENS + +struct LocalFrameToken { + mojo_base.mojom.UnguessableToken value; +}; + +struct RemoteFrameToken { + mojo_base.mojom.UnguessableToken value; +}; + +//////////////////////////////////////////////////////////////////////////////// +// WORKER TOKENS + +struct DedicatedWorkerToken { + mojo_base.mojom.UnguessableToken value; +}; + +struct SharedWorkerToken { + mojo_base.mojom.UnguessableToken value; +}; + +struct ServiceWorkerToken { + mojo_base.mojom.UnguessableToken value; +}; + +//////////////////////////////////////////////////////////////////////////////// +// OTHER TOKENS +// +// Keep this section last. +// +// If you have multiple tokens that make a thematic group, please lift them to +// their own section, in alphabetical order. If adding a new token here, please +// keep the following list in alphabetic order. + +struct PortalToken { + mojo_base.mojom.UnguessableToken value; +};
diff --git a/third_party/blink/public/mojom/tokens/worker_tokens.mojom b/third_party/blink/public/mojom/tokens/worker_tokens.mojom deleted file mode 100644 index fd79521..0000000 --- a/third_party/blink/public/mojom/tokens/worker_tokens.mojom +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2020 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 blink.mojom; - -import "mojo/public/mojom/base/unguessable_token.mojom"; - -// These identifiers uniquely represent workers (dedicated/shared/service) -// across the content and blink layers. It is only intended to be transferred -// between the browser process and the renderer process hosting the worker. -// This is a simple wrapper that provides type safety. - -struct DedicatedWorkerToken { - mojo_base.mojom.UnguessableToken value; -}; - -struct SharedWorkerToken { - mojo_base.mojom.UnguessableToken value; -}; - -struct ServiceWorkerToken { - mojo_base.mojom.UnguessableToken value; -};
diff --git a/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom b/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom index 3d20f54..b5fe48e 100644 --- a/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom +++ b/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom
@@ -14,7 +14,7 @@ import "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom"; import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom"; import "third_party/blink/public/mojom/service_worker/service_worker_container.mojom"; -import "third_party/blink/public/mojom/tokens/worker_tokens.mojom"; +import "third_party/blink/public/mojom/tokens/tokens.mojom"; import "url/mojom/url.mojom"; // The name of the InterfaceProviderSpec in service manifests used by the
diff --git a/third_party/blink/public/mojom/worker/shared_worker_factory.mojom b/third_party/blink/public/mojom/worker/shared_worker_factory.mojom index 123a42f..dcf0850 100644 --- a/third_party/blink/public/mojom/worker/shared_worker_factory.mojom +++ b/third_party/blink/public/mojom/worker/shared_worker_factory.mojom
@@ -12,7 +12,7 @@ import "third_party/blink/public/mojom/renderer_preferences.mojom"; import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom"; import "third_party/blink/public/mojom/service_worker/service_worker_container.mojom"; -import "third_party/blink/public/mojom/tokens/worker_tokens.mojom"; +import "third_party/blink/public/mojom/tokens/tokens.mojom"; import "third_party/blink/public/mojom/worker/shared_worker.mojom"; import "third_party/blink/public/mojom/worker/shared_worker_host.mojom"; import "third_party/blink/public/mojom/worker/shared_worker_info.mojom";
diff --git a/third_party/blink/public/platform/TaskTypes.md b/third_party/blink/public/platform/TaskTypes.md index 76c519a..3a3d28c4 100644 --- a/third_party/blink/public/platform/TaskTypes.md +++ b/third_party/blink/public/platform/TaskTypes.md
@@ -19,7 +19,8 @@ | MediaElementEvent | No | No | Yes | Yes | Yes | | CanvasBlobSerialization | No | Yes | Yes | Yes | Yes | | Microtask | No | Yes | Yes | Yes | Yes | -| JavascriptTimer | Yes | Yes | Yes | Yes | Yes | +| JavascriptTimerDelayed | Yes | Yes | Yes | Yes | Yes | +| JavascriptTimerImmediate [1] | No | Yes | Yes | Yes | Yes | | RemoteEvent | No | Yes | Yes | Yes | Yes | | WebSocket | No | Yes | Yes | Yes | Yes | | PostedMessage | No | No | Yes | Yes | Yes | @@ -56,3 +57,5 @@ | InternalContinueScriptLoadin | No | No | Yes | Yes | Yes | Internal Translation queue supports concept of it running only in the foreground. It is disabled if the page that owns it goes in background. + +[1] Assuming that the "OptOutZeroTimeoutTimersFromThrottling" feature is enabled.
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h index 688088b..abfcd20b 100644 --- a/third_party/blink/public/platform/platform.h +++ b/third_party/blink/public/platform/platform.h
@@ -72,6 +72,10 @@ class SingleThreadTaskRunner; } +namespace gfx { +class ColorSpace; +} + namespace gpu { class GpuMemoryBufferManager; } @@ -679,6 +683,8 @@ return nullptr; } + virtual void SetRenderingColorSpace(const gfx::ColorSpace& color_space) {} + // Renderer Memory Metrics ---------------------------------------------- virtual void RecordMetricsForBackgroundedRendererPurge() {}
diff --git a/third_party/blink/public/platform/task_type.h b/third_party/blink/public/platform/task_type.h index 35d9d12..9d2ac8d7 100644 --- a/third_party/blink/public/platform/task_type.h +++ b/third_party/blink/public/platform/task_type.h
@@ -73,9 +73,14 @@ kMicrotask = 9, // https://html.spec.whatwg.org/multipage/webappapis.html#timers - // This task source is used to queue tasks queued by setInterval() and similar - // APIs. - kJavascriptTimer = 10, + // For tasks queued by setInterval() and similar APIs. A different type is + // used depending on whether the timeout is zero or non-zero. Tasks with + // a zero timeout and a nesting level <= 5 will be associated with task + // queues that are not throttlable. This complies with the spec since it + // does not reduce the timeout to less than zero or bypass the timeout + // extension triggered on nesting level >= 5. + kJavascriptTimerDelayed = 10, + kJavascriptTimerImmediate = 72, // https://html.spec.whatwg.org/multipage/comms.html#sse-processing-model // This task source is used for any tasks that are queued by EventSource @@ -264,7 +269,7 @@ kWorkerThreadTaskQueueV8 = 47, kWorkerThreadTaskQueueCompositor = 48, - kCount = 72, + kCount = 73, }; } // namespace blink
diff --git a/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h b/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h index 4a2eed0..d0230c9 100644 --- a/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h +++ b/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h
@@ -10,7 +10,7 @@ #include "mojo/public/cpp/system/message_pipe.h" #include "services/network/public/mojom/fetch_api.mojom-shared.h" #include "services/network/public/mojom/referrer_policy.mojom-shared.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/blob/blob_url_store.mojom-shared.h" #include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h" #include "third_party/blink/public/platform/cross_variant_mojo_util.h"
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h index 2f369cc2..699eb37 100644 --- a/third_party/blink/public/web/web_local_frame.h +++ b/third_party/blink/public/web/web_local_frame.h
@@ -18,7 +18,7 @@ #include "third_party/blink/public/common/feature_policy/feature_policy_features.h" #include "third_party/blink/public/common/frame/user_activation_update_source.h" #include "third_party/blink/public/common/messaging/transferable_message.h" -#include "third_party/blink/public/common/tokens/portal_token.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-shared.h" #include "third_party/blink/public/mojom/blob/blob_url_store.mojom-shared.h" #include "third_party/blink/public/mojom/commit_result/commit_result.mojom-shared.h"
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h index 7a54209..cc7c11d6 100644 --- a/third_party/blink/public/web/web_local_frame_client.h +++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -43,7 +43,7 @@ #include "third_party/blink/public/common/loader/loading_behavior_flag.h" #include "third_party/blink/public/common/loader/url_loader_factory_bundle.h" #include "third_party/blink/public/common/navigation/triggering_event_info.h" -#include "third_party/blink/public/common/tokens/portal_token.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/common/user_agent/user_agent_metadata.h" #include "third_party/blink/public/mojom/frame/blocked_navigation_types.mojom-shared.h" #include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-shared.h"
diff --git a/third_party/blink/public/web/web_shared_worker.h b/third_party/blink/public/web/web_shared_worker.h index 4360fea..d744c1bb 100644 --- a/third_party/blink/public/web/web_shared_worker.h +++ b/third_party/blink/public/web/web_shared_worker.h
@@ -38,7 +38,7 @@ #include "services/network/public/mojom/content_security_policy.mojom-shared.h" #include "services/network/public/mojom/fetch_api.mojom-shared.h" #include "services/network/public/mojom/ip_address_space.mojom-shared.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/common/user_agent/user_agent_metadata.h" #include "third_party/blink/public/mojom/browser_interface_broker.mojom-shared.h" #include "third_party/blink/public/mojom/script/script_type.mojom-shared.h"
diff --git a/third_party/blink/renderer/controller/BUILD.gn b/third_party/blink/renderer/controller/BUILD.gn index 7791766..fbfd5591 100644 --- a/third_party/blink/renderer/controller/BUILD.gn +++ b/third_party/blink/renderer/controller/BUILD.gn
@@ -45,7 +45,7 @@ "memory_usage_monitor.h", ] - if (is_linux) { + if (is_linux || is_chromeos) { sources += [ "memory_usage_monitor_posix.cc", "memory_usage_monitor_posix.h", @@ -81,7 +81,7 @@ # HighestPmfReporter depends on MemoryUsageMonitor and MemoryUsageMonitor # depends on platform specific code. Explicitly specify supported platforms. - if (is_linux || is_win || is_android || is_mac) { + if (is_linux || is_chromeos || is_win || is_android || is_mac) { sources += [ "highest_pmf_reporter.cc", "highest_pmf_reporter.h", @@ -165,7 +165,7 @@ sources = [ "tests/run_all_tests.cc" ] sources += bindings_unittest_files - if (is_linux) { + if (is_linux || is_chromeos) { sources += [ "memory_usage_monitor_posix_test.cc" ] } if (is_android) { @@ -176,7 +176,7 @@ ] } - if (is_linux || is_android || is_mac || is_win) { + if (is_linux || is_chromeos || is_android || is_mac || is_win) { sources += [ "highest_pmf_reporter_test.cc", "memory_usage_monitor_test.cc",
diff --git a/third_party/blink/renderer/core/frame/dom_timer.cc b/third_party/blink/renderer/core/frame/dom_timer.cc index 30dfd23..a287ba4 100644 --- a/third_party/blink/renderer/core/frame/dom_timer.cc +++ b/third_party/blink/renderer/core/frame/dom_timer.cc
@@ -27,6 +27,7 @@ #include "third_party/blink/renderer/core/frame/dom_timer.h" #include "base/single_thread_task_runner.h" +#include "base/time/time.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/core/v8/scheduled_action.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" @@ -36,15 +37,32 @@ namespace blink { -static const int kMaxTimerNestingLevel = 5; -// Chromium uses a minimum timer interval of 4ms. We'd like to go -// lower; however, there are poorly coded websites out there which do -// create CPU-spinning loops. Using 4ms prevents the CPU from -// spinning too busily and provides a balance between CPU spinning and -// the smallest possible interval timer. -static constexpr base::TimeDelta kMinimumInterval = +namespace { + +// Step 11 of the algorithm at +// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html requires +// that a timeout less than 4ms is increased to 4ms when the nesting level is +// greater than 5. +constexpr int kMaxTimerNestingLevel = 5; +constexpr base::TimeDelta kMinimumInterval = base::TimeDelta::FromMilliseconds(4); +// Computes the timeout of a timer according to the algorithm at +// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html. +base::TimeDelta ComputeTimeout(base::TimeDelta timeout, int nesting_level) { + // Step 10: + if (timeout < base::TimeDelta()) + timeout = base::TimeDelta(); + + // Step 11 (the implementation is not spec-compliant crbug.com/1108877): + if (nesting_level + 1 >= kMaxTimerNestingLevel && timeout < kMinimumInterval) + timeout = kMinimumInterval; + + return timeout; +} + +} // namespace + int DOMTimer::Install(ExecutionContext* context, ScheduledAction* action, base::TimeDelta timeout, @@ -63,33 +81,39 @@ if (timer) timer->SetExecutionContext(nullptr); } - DOMTimer::DOMTimer(ExecutionContext* context, ScheduledAction* action, - base::TimeDelta interval, + base::TimeDelta timeout, bool single_shot, int timeout_id) : ExecutionContextLifecycleObserver(context), - TimerBase(context->GetTaskRunner(TaskType::kJavascriptTimer)), + TimerBase(context->GetTaskRunner( + ComputeTimeout(timeout, context->Timers()->TimerNestingLevel()) + .is_zero() + ? TaskType::kJavascriptTimerImmediate + : TaskType::kJavascriptTimerDelayed)), timeout_id_(timeout_id), - nesting_level_(context->Timers()->TimerNestingLevel() + 1), + nesting_level_(context->Timers()->TimerNestingLevel()), action_(action) { DCHECK_GT(timeout_id, 0); - base::TimeDelta interval_milliseconds = - std::max(base::TimeDelta::FromMilliseconds(1), interval); - if (interval_milliseconds < kMinimumInterval && - nesting_level_ >= kMaxTimerNestingLevel) - interval_milliseconds = kMinimumInterval; + // Steps 10 and 11, and rounding up to 1 ms for historical reasons + // crbug.com/402694. + timeout = std::max(base::TimeDelta::FromMilliseconds(1), + ComputeTimeout(timeout, nesting_level_)); + + // Step 12 and 13: + ++nesting_level_; + if (single_shot) - StartOneShot(interval_milliseconds, FROM_HERE); + StartOneShot(timeout, FROM_HERE); else - StartRepeating(interval_milliseconds, FROM_HERE); + StartRepeating(timeout, FROM_HERE); TRACE_EVENT_INSTANT1("devtools.timeline", "TimerInstall", TRACE_EVENT_SCOPE_THREAD, "data", inspector_timer_install_event::Data( - context, timeout_id, interval, single_shot)); + context, timeout_id, timeout, single_shot)); probe::AsyncTaskScheduledBreakable( context, single_shot ? "setTimeout" : "setInterval", &async_task_id_); } @@ -142,8 +166,11 @@ if (IsActive()) { if (is_interval && RepeatInterval() < kMinimumInterval) { nesting_level_++; - if (nesting_level_ >= kMaxTimerNestingLevel) + if (nesting_level_ >= kMaxTimerNestingLevel) { + MoveToNewTaskRunner( + context->GetTaskRunner(TaskType::kJavascriptTimerDelayed)); AugmentRepeatInterval(kMinimumInterval - RepeatInterval()); + } } // No access to member variables after this point, it can delete the timer.
diff --git a/third_party/blink/renderer/core/frame/dom_timer.h b/third_party/blink/renderer/core/frame/dom_timer.h index 669db99..460577a 100644 --- a/third_party/blink/renderer/core/frame/dom_timer.h +++ b/third_party/blink/renderer/core/frame/dom_timer.h
@@ -57,7 +57,7 @@ DOMTimer(ExecutionContext*, ScheduledAction*, - base::TimeDelta interval, + base::TimeDelta timeout, bool single_shot, int timeout_id); ~DOMTimer() override;
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h index f31cae1..96bf50bf 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client.h +++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -42,7 +42,7 @@ #include "third_party/blink/public/common/feature_policy/feature_policy.h" #include "third_party/blink/public/common/loader/loading_behavior_flag.h" #include "third_party/blink/public/common/navigation/triggering_event_info.h" -#include "third_party/blink/public/common/tokens/portal_token.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/common/user_agent/user_agent_metadata.h" #include "third_party/blink/public/mojom/frame/navigation_initiator.mojom-blink-forward.h" #include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h"
diff --git a/third_party/blink/renderer/core/frame/pausable_script_executor.cc b/third_party/blink/renderer/core/frame/pausable_script_executor.cc index 4ad3f53..bc8a98e 100644 --- a/third_party/blink/renderer/core/frame/pausable_script_executor.cc +++ b/third_party/blink/renderer/core/frame/pausable_script_executor.cc
@@ -209,10 +209,7 @@ ExecuteAndDestroySelf(); return; } - task_handle_ = PostCancellableTask( - *context->GetTaskRunner(TaskType::kJavascriptTimer), FROM_HERE, - WTF::Bind(&PausableScriptExecutor::ExecuteAndDestroySelf, - WrapPersistent(this))); + PostExecuteAndDestroySelf(context); } void PausableScriptExecutor::RunAsync(BlockingOption blocking) { @@ -222,8 +219,13 @@ if (blocking_option_ == kOnloadBlocking) To<LocalDOMWindow>(context)->document()->IncrementLoadEventDelayCount(); + PostExecuteAndDestroySelf(context); +} + +void PausableScriptExecutor::PostExecuteAndDestroySelf( + ExecutionContext* context) { task_handle_ = PostCancellableTask( - *context->GetTaskRunner(TaskType::kJavascriptTimer), FROM_HERE, + *context->GetTaskRunner(TaskType::kJavascriptTimerImmediate), FROM_HERE, WTF::Bind(&PausableScriptExecutor::ExecuteAndDestroySelf, WrapPersistent(this))); }
diff --git a/third_party/blink/renderer/core/frame/pausable_script_executor.h b/third_party/blink/renderer/core/frame/pausable_script_executor.h index 99f2a8d..8eb168e7 100644 --- a/third_party/blink/renderer/core/frame/pausable_script_executor.h +++ b/third_party/blink/renderer/core/frame/pausable_script_executor.h
@@ -63,7 +63,7 @@ void Trace(Visitor*) const override; private: - + void PostExecuteAndDestroySelf(ExecutionContext* context); void ExecuteAndDestroySelf(); void Dispose();
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc index a3b74a6..4387d2f2 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
@@ -353,6 +353,11 @@ } #endif +void WebFrameWidgetBase::BindWidgetCompositor( + mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) { + widget_base_->BindWidgetCompositor(std::move(receiver)); +} + void WebFrameWidgetBase::CancelDrag() { // It's possible for this to be called while we're not doing a drag if // it's from a previous page that got unloaded.
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.h b/third_party/blink/renderer/core/frame/web_frame_widget_base.h index d2f9f984c..944a5a8 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_base.h +++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
@@ -385,6 +385,9 @@ base::Optional<gfx::Point> GetAndResetContextMenuLocation(); + void BindWidgetCompositor( + mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) override; + // Called when the FrameView for this Widget's local root is created. virtual void DidCreateLocalRootView() {}
diff --git a/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js b/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js index 6380d46..ab4faac 100644 --- a/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js +++ b/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js
@@ -3479,6 +3479,26 @@ }; /** + * @param {!Day} day + * @param {!Day} minDay + * @param {!Day} maxDay + * @return {boolean} + */ +function isDayOutsideOfRange(day, minDay, maxDay) { + return day < minDay || maxDay < day; +} + +/** + * @param {!Week} week + * @param {!Week} minWeek + * @param {!Week} maxWeek + * @return {boolean} + */ +function isWeekOutsideOfRange(week, minWeek, maxWeek) { + return week < minWeek || maxWeek < week; +} + +/** * @constructor * @extends View * @param {!CalendarPicker} calendarPicker @@ -3532,10 +3552,15 @@ this.onNavigationButtonClick); this._todayButton.element.classList.add( CalendarHeaderView.GetClassNameTodayButton()); - var monthContainingToday = Month.createFromToday(); - this._todayButton.setDisabled( - monthContainingToday < this.calendarPicker.minimumMonth || - monthContainingToday > this.calendarPicker.maximumMonth); + if (this.calendarPicker.type === 'week') { + this._todayButton.setDisabled(isWeekOutsideOfRange( + Week.createFromToday(), this.calendarPicker.config.minimum, + this.calendarPicker.config.maximum)); + } else { + this._todayButton.setDisabled(isDayOutsideOfRange( + Day.createFromToday(), this.calendarPicker.config.minimum, + this.calendarPicker.config.maximum)); + } this._todayButton.element.setAttribute( 'aria-label', global.params.todayLabel); } @@ -3660,11 +3685,17 @@ this.disabled || this.calendarPicker.currentMonth() >= this.calendarPicker.maximumMonth); if (this._todayButton) { - var monthContainingToday = Month.createFromToday(); - this._todayButton.setDisabled( - this.disabled || - monthContainingToday < this.calendarPicker.minimumMonth || - monthContainingToday > this.calendarPicker.maximumMonth); + if (this.disabled) { + this._todayButton.setDisabled(true); + } else if (this.calendarPicker.type === 'week') { + this._todayButton.setDisabled(isWeekOutsideOfRange( + Week.createFromToday(), this.calendarPicker.config.minimum, + this.calendarPicker.config.maximum)); + } else { + this._todayButton.setDisabled(isDayOutsideOfRange( + Day.createFromToday(), this.calendarPicker.config.minimum, + this.calendarPicker.config.maximum)); + } } }; @@ -4041,10 +4072,15 @@ todayButton.element.textContent = global.params.todayLabel; todayButton.element.classList.add( CalendarHeaderView.GetClassNameTodayButton()); - var monthContainingToday = Month.createFromToday(); - todayButton.setDisabled( - monthContainingToday < this.calendarPicker.minimumMonth || - monthContainingToday > this.calendarPicker.maximumMonth); + if (this.calendarPicker.type === 'week') { + todayButton.setDisabled(isWeekOutsideOfRange( + Week.createFromToday(), this.calendarPicker.config.minimum, + this.calendarPicker.config.maximum)); + } else { + todayButton.setDisabled(isDayOutsideOfRange( + Day.createFromToday(), this.calendarPicker.config.minimum, + this.calendarPicker.config.maximum)); + } todayButton.element.setAttribute('aria-label', global.params.todayLabel); }
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.h b/third_party/blink/renderer/core/html/portal/html_portal_element.h index 4d4244d..9311cc7 100644 --- a/third_party/blink/renderer/core/html/portal/html_portal_element.h +++ b/third_party/blink/renderer/core/html/portal/html_portal_element.h
@@ -9,7 +9,7 @@ #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" -#include "third_party/blink/public/common/tokens/portal_token.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/core/core_export.h"
diff --git a/third_party/blink/renderer/core/html/portal/portal_activate_event.h b/third_party/blink/renderer/core/html/portal/portal_activate_event.h index 8d18425a..c0576bc 100644 --- a/third_party/blink/renderer/core/html/portal/portal_activate_event.h +++ b/third_party/blink/renderer/core/html/portal/portal_activate_event.h
@@ -9,7 +9,7 @@ #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/pending_associated_remote.h" -#include "third_party/blink/public/common/tokens/portal_token.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/unpacked_serialized_script_value.h"
diff --git a/third_party/blink/renderer/core/html/portal/portal_contents.h b/third_party/blink/renderer/core/html/portal/portal_contents.h index b97903a..a33b60f8 100644 --- a/third_party/blink/renderer/core/html/portal/portal_contents.h +++ b/third_party/blink/renderer/core/html/portal/portal_contents.h
@@ -12,7 +12,7 @@ #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/pending_associated_remote.h" #include "services/network/public/mojom/referrer_policy.mojom-shared.h" -#include "third_party/blink/public/common/tokens/portal_token.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/portal/portal.mojom-blink.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.cc b/third_party/blink/renderer/core/inspector/inspector_highlight.cc index e93ec7ccf..657543a 100644 --- a/third_party/blink/renderer/core/inspector/inspector_highlight.cc +++ b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -486,7 +486,6 @@ size_t first_explicit_index = layout_grid->ExplicitGridStartForDirection(direction); - LayoutUnit first_offset = track_positions.front(); // Go line by line, calculating the offset to fall in the middle of gaps // if needed. for (size_t i = first_explicit_index; i < track_positions.size(); ++i) { @@ -496,8 +495,8 @@ if (grid_gap == 0 || i == 0 || i == track_positions.size() - 1) { gapOffset = LayoutUnit(); } - PhysicalOffset number_position( - track_positions.at(i) - gapOffset - first_offset, alt_axis_pos); + PhysicalOffset number_position(track_positions.at(i) - gapOffset, + alt_axis_pos); if (direction == kForRows) number_position = Transpose(number_position); number_positions->pushValue(BuildPosition( @@ -545,8 +544,8 @@ i == trackPositions.size() - 1)) { gapOffset = LayoutUnit(); } - PhysicalOffset number_position( - trackPositions.at(i) - gapOffset - first_offset, alt_axis_pos); + PhysicalOffset number_position(trackPositions.at(i) - gapOffset, + alt_axis_pos); if (direction == kForRows) number_position = Transpose(number_position); number_positions->pushValue(BuildPosition( @@ -699,7 +698,7 @@ LayoutUnit gap_offset = index > 0 && index < tracks.size() - 1 ? gap / 2 : LayoutUnit(); - LayoutUnit main_axis_pos = track - gap_offset - first_offset; + LayoutUnit main_axis_pos = track - gap_offset; PhysicalOffset line_name_pos(main_axis_pos, alt_axis_pos); if (direction == kForRows) @@ -711,8 +710,8 @@ line->setString("name", name); // TODO (alexrudenko): offset should be removed once the frontend starts // using absolute positions. - line->setValue("offset", - protocol::FundamentalValue::create(main_axis_pos * scale)); + line->setValue("offset", protocol::FundamentalValue::create( + (main_axis_pos - first_offset) * scale)); lines->pushValue(std::move(line)); }
diff --git a/third_party/blink/renderer/core/layout/BUILD.gn b/third_party/blink/renderer/core/layout/BUILD.gn index 1b9e856..74381bb 100644 --- a/third_party/blink/renderer/core/layout/BUILD.gn +++ b/third_party/blink/renderer/core/layout/BUILD.gn
@@ -627,7 +627,7 @@ sources += [ "layout_theme_font_provider_default.cc" ] } - if (is_linux) { + if (is_linux || is_chromeos) { sources += [ "layout_theme_linux.cc", "layout_theme_linux.h",
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc index 8757357..8433a3fe 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -73,12 +73,17 @@ if (!containing_block_fragment) containing_block_fragment = fragment; + LogicalOffset containing_block_offset = + descendant.containing_block_offset.ConvertToLogical( + GetWritingMode(), Direction(), child.Size(), PhysicalSize()); + containing_block_offset += child_offset; + NGLogicalStaticPosition static_position = descendant.static_position.ConvertToLogical( GetWritingMode(), Direction(), PhysicalSize()); oof_positioned_fragmentainer_descendants_.emplace_back( descendant.node, static_position, descendant.inline_container, - /* needs_block_offset_adjustment */ false, + /* needs_block_offset_adjustment */ false, containing_block_offset, containing_block_fragment); } }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h index 6b332b1..7d4a2509 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h
@@ -37,17 +37,20 @@ NGPhysicalStaticPosition static_position; // Continuation root of the optional inline container. const LayoutInline* inline_container; + PhysicalOffset containing_block_offset; scoped_refptr<const NGPhysicalContainerFragment> containing_block_fragment; NGPhysicalOutOfFlowPositionedNode( NGBlockNode node, NGPhysicalStaticPosition static_position, const LayoutInline* inline_container = nullptr, + PhysicalOffset containing_block_offset = PhysicalOffset(), scoped_refptr<const NGPhysicalContainerFragment> containing_block_fragment = nullptr) : node(node), static_position(static_position), inline_container(inline_container), + containing_block_offset(containing_block_offset), containing_block_fragment(std::move(containing_block_fragment)) { DCHECK(!inline_container || inline_container == inline_container->ContinuationRoot()); @@ -66,6 +69,7 @@ // Continuation root of the optional inline container. const LayoutInline* inline_container; bool needs_block_offset_adjustment; + LogicalOffset containing_block_offset; scoped_refptr<const NGPhysicalContainerFragment> containing_block_fragment; NGLogicalOutOfFlowPositionedNode( @@ -73,12 +77,14 @@ NGLogicalStaticPosition static_position, const LayoutInline* inline_container = nullptr, bool needs_block_offset_adjustment = false, + LogicalOffset containing_block_offset = LogicalOffset(), scoped_refptr<const NGPhysicalContainerFragment> containing_block_fragment = nullptr) : node(node), static_position(static_position), inline_container(inline_container), needs_block_offset_adjustment(needs_block_offset_adjustment), + containing_block_offset(containing_block_offset), containing_block_fragment(std::move(containing_block_fragment)) { DCHECK(!inline_container || inline_container == inline_container->ContinuationRoot());
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc index 61b61767..2cfed6f 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -163,7 +163,13 @@ descendant.node, descendant.static_position.ConvertToPhysical( builder->Style().GetWritingMode(), builder->Direction(), size), - descendant.inline_container, descendant.containing_block_fragment); + descendant.inline_container, + descendant.containing_block_offset.ConvertToPhysical( + builder->Style().GetWritingDirection(), size, + descendant.containing_block_fragment + ? descendant.containing_block_fragment->Size() + : PhysicalSize()), + descendant.containing_block_fragment); } }
diff --git a/third_party/blink/renderer/core/layout/scroll_anchor.cc b/third_party/blink/renderer/core/layout/scroll_anchor.cc index 117a16a..ad15ffa 100644 --- a/third_party/blink/renderer/core/layout/scroll_anchor.cc +++ b/third_party/blink/renderer/core/layout/scroll_anchor.cc
@@ -597,9 +597,13 @@ // and attempt to re-find the anchor. The user-visible effect should end up // roughly the same. ScrollOffset current_offset = scroller_->GetScrollOffset(); - FloatPoint desired_point = - anchor_object->AbsoluteBoundingBoxFloatRect().Location() + - current_offset; + FloatRect bounding_box = anchor_object->AbsoluteBoundingBoxFloatRect(); + FloatPoint location_point = + anchor_object->Style()->IsFlippedBlocksWritingMode() + ? bounding_box.MaxXMinYCorner() + : bounding_box.Location(); + FloatPoint desired_point = location_point + current_offset; + ScrollOffset desired_offset = ScrollOffset(desired_point.X(), desired_point.Y()); ScrollOffset delta = @@ -647,6 +651,7 @@ SerializedAnchor new_anchor( ComputeUniqueSelector(anchor_object_->GetNode()), ComputeRelativeOffset(anchor_object_, scroller_, corner_)); + if (new_anchor.IsValid()) { saved_selector_ = new_anchor.selector; }
diff --git a/third_party/blink/renderer/core/layout/scroll_anchor_test.cc b/third_party/blink/renderer/core/layout/scroll_anchor_test.cc index df6bb25..e53134f 100644 --- a/third_party/blink/renderer/core/layout/scroll_anchor_test.cc +++ b/third_party/blink/renderer/core/layout/scroll_anchor_test.cc
@@ -751,6 +751,30 @@ ValidateSerializedAnchor("html>body>.barbaz", LayoutPoint(-50, 0)); } +TEST_P(ScrollAnchorTest, RestoreAnchorVerticalRlWritingMode) { + SetBodyInnerHTML(R"HTML( + <style> + body { + height: 100px; + margin: 0; + writing-mode: + vertical-rl; + } + div.big { width: 800px; } + div { width: 100px; height: 100px; } + </style> + <div class='big'></div> + <div id='last'></div> + )HTML"); + + SerializedAnchor serialized_anchor("#last", LayoutPoint(0, 0)); + + EXPECT_TRUE( + GetScrollAnchor(LayoutViewport()).RestoreAnchor(serialized_anchor)); + EXPECT_EQ(LayoutViewport()->ScrollOffsetInt().Width(), 0); + EXPECT_EQ(LayoutViewport()->ScrollOffsetInt().Height(), 0); +} + TEST_P(ScrollAnchorTest, SerializeAnchorQualifiedTagName) { SetBodyInnerHTML(R"HTML( <style>
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc index bc7e917..43b17aa 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc
@@ -19,6 +19,24 @@ namespace blink { +namespace { + +void ExtractLinks(const cc::PaintOpBuffer* buffer, std::vector<GURL>* links) { + for (cc::PaintOpBuffer::Iterator it(buffer); it; ++it) { + if (it->GetType() == cc::PaintOpType::Annotate) { + auto* annotate_op = static_cast<cc::AnnotateOp*>(*it); + links->push_back(GURL( + std::string(reinterpret_cast<const char*>(annotate_op->data->data()), + annotate_op->data->size()))); + } else if (it->GetType() == cc::PaintOpType::DrawRecord) { + auto* record_op = static_cast<cc::DrawRecordOp*>(*it); + ExtractLinks(record_op->record.get(), links); + } + } +} + +} // namespace + class NGBoxFragmentPainterTest : public PaintControllerPaintTest, private ScopedLayoutNGForTest { public: @@ -126,10 +144,12 @@ kGlobalPaintFlattenCompositingLayers, CullRect::Infinite()); - builder.EndRecording(); - ASSERT_EQ(tracker.GetLinks().size(), 2U); - EXPECT_EQ(tracker.GetLinks()[0]->url, "https://www.chromium.org/"); - EXPECT_EQ(tracker.GetLinks()[1]->url, "https://www.wikipedia.org/"); + auto record = builder.EndRecording(); + std::vector<GURL> links; + ExtractLinks(record.get(), &links); + ASSERT_EQ(links.size(), 2U); + EXPECT_EQ(links[0].spec(), "https://www.chromium.org/"); + EXPECT_EQ(links[1].spec(), "https://www.wikipedia.org/"); } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/video_painter.cc b/third_party/blink/renderer/core/paint/video_painter.cc index 89ee4c2..e892ef5d 100644 --- a/third_party/blink/renderer/core/paint/video_painter.cc +++ b/third_party/blink/renderer/core/paint/video_painter.cc
@@ -51,6 +51,9 @@ content_box_rect.Move(paint_offset); if (context.IsPaintingPreview()) { + // Create a canvas and draw a URL rect to it for the paint preview. + BoxDrawingRecorder recorder(context, layout_video_, paint_info.phase, + paint_offset); context.SetURLForRect(layout_video_.GetDocument().Url(), snapped_replaced_rect); }
diff --git a/third_party/blink/renderer/core/paint/video_painter_test.cc b/third_party/blink/renderer/core/paint/video_painter_test.cc index a9c0aae8..b9d3264c 100644 --- a/third_party/blink/renderer/core/paint/video_painter_test.cc +++ b/third_party/blink/renderer/core/paint/video_painter_test.cc
@@ -22,6 +22,23 @@ namespace blink { namespace { +void ExtractLinks(const cc::PaintOpBuffer* buffer, + std::vector<std::pair<GURL, SkRect>>* links) { + for (cc::PaintOpBuffer::Iterator it(buffer); it; ++it) { + if (it->GetType() == cc::PaintOpType::Annotate) { + auto* annotate_op = static_cast<cc::AnnotateOp*>(*it); + links->push_back(std::make_pair( + GURL(std::string( + reinterpret_cast<const char*>(annotate_op->data->data()), + annotate_op->data->size())), + annotate_op->rect)); + } else if (it->GetType() == cc::PaintOpType::DrawRecord) { + auto* record_op = static_cast<cc::DrawRecordOp*>(*it); + ExtractLinks(record_op->record.get(), links); + } + } +} + class StubWebMediaPlayer : public EmptyWebMediaPlayer { public: StubWebMediaPlayer(WebMediaPlayerClient* client) : client_(client) {} @@ -164,13 +181,15 @@ recorder.beginRecording(bounds().width(), bounds().height()); canvas->SetPaintPreviewTracker(&tracker); - EXPECT_EQ(0lu, tracker.GetLinks().size()); GetLocalMainFrame().CapturePaintPreview(WebRect(bounds()), canvas, /*include_linked_destinations=*/true); + auto record = recorder.finishRecordingAsPicture(); + std::vector<std::pair<GURL, SkRect>> links; + ExtractLinks(record.get(), &links); - ASSERT_EQ(1lu, tracker.GetLinks().size()); - EXPECT_EQ("http://test.com/", tracker.GetLinks()[0]->url); - EXPECT_EQ(gfx::Rect(300, 300), tracker.GetLinks()[0]->rect); + ASSERT_EQ(1lu, links.size()); + EXPECT_EQ("http://test.com/", links[0].first); + EXPECT_EQ(SkRect::MakeWH(300, 300), links[0].second); } } // namespace
diff --git a/third_party/blink/renderer/core/scheduler_integration_tests/throttling_test.cc b/third_party/blink/renderer/core/scheduler_integration_tests/throttling_test.cc index 3bff32d..5079751 100644 --- a/third_party/blink/renderer/core/scheduler_integration_tests/throttling_test.cc +++ b/third_party/blink/renderer/core/scheduler_integration_tests/throttling_test.cc
@@ -27,13 +27,29 @@ constexpr auto kDefaultThrottledWakeUpInterval = base::TimeDelta::FromSeconds(1); +// A SimTest with mock time. +class ThrottlingTestBase : public SimTest { + public: + ThrottlingTestBase() { + platform_->SetAutoAdvanceNowToPendingTasks(false); + + // Align the time on a 1-minute interval, to simplify expectations. + platform_->AdvanceClock( + platform_->NowTicks().SnappedToNextTick( + base::TimeTicks(), base::TimeDelta::FromMinutes(1)) - + platform_->NowTicks()); + } + + ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> + platform_; +}; + class DisableBackgroundThrottlingIsRespectedTest - : public SimTest, + : public ThrottlingTestBase, private ScopedTimerThrottlingForBackgroundTabsForTest { public: DisableBackgroundThrottlingIsRespectedTest() : ScopedTimerThrottlingForBackgroundTabsForTest(false) {} - void SetUp() override { SimTest::SetUp(); } }; TEST_F(DisableBackgroundThrottlingIsRespectedTest, @@ -56,15 +72,15 @@ // Run delayed tasks for 1 second. All tasks should be completed // with throttling disabled. - test::RunDelayedTasks(base::TimeDelta::FromSeconds(1)); + platform_->RunForPeriod(base::TimeDelta::FromSeconds(1)); EXPECT_THAT(ConsoleMessages(), ElementsAre("called f", "called f", "called f", "called f", "called f")); } -class BackgroundPageThrottlingTest : public SimTest {}; +class BackgroundPageThrottlingTest : public ThrottlingTestBase {}; -TEST_F(BackgroundPageThrottlingTest, BackgroundPagesAreThrottled) { +TEST_F(BackgroundPageThrottlingTest, TimersThrottledInBackgroundPage) { SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); @@ -82,28 +98,155 @@ GetDocument().GetPage()->GetPageScheduler()->SetPageVisible(false); // Make sure that we run no more than one task a second. - test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(3000)); - EXPECT_THAT( - ConsoleMessages(), - AnyOf(ElementsAre("called f", "called f", "called f"), - ElementsAre("called f", "called f", "called f", "called f"))); + platform_->RunForPeriod(base::TimeDelta::FromSeconds(3)); + EXPECT_THAT(ConsoleMessages(), + ElementsAre("called f", "called f", "called f")); } -class IntensiveWakeUpThrottlingTest : public SimTest { +// Same test as above, but using timeout=0. +TEST_F(BackgroundPageThrottlingTest, + ZeroTimeoutTimersThrottledInBackgroundPage) { + SimRequest main_resource("https://example.com/", "text/html"); + + LoadURL("https://example.com/"); + + main_resource.Complete( + "(<script>" + " function f(repetitions) {" + " if (repetitions == 0) return;" + " console.log('called f');" + " setTimeout(f, 0, repetitions - 1);" + " }" + " setTimeout(f, 0, 50);" + "</script>)"); + + GetDocument().GetPage()->GetPageScheduler()->SetPageVisible(false); + + // 0ms timeouts are rounded up to 1ms (https://crbug.com/402694). When the + // nesting level is 5, they are rounded up to 4 ms. The duration of a + // throttled wake up is 3ms. Therefore, at the 2 first wake ups, the timer + // runs twice. At the third wake up, it runs once. + platform_->RunForPeriod(base::TimeDelta::FromSeconds(3)); + EXPECT_THAT(ConsoleMessages(), ElementsAre("called f", "called f", "called f", + "called f", "called f")); +} + +namespace { + +class OptOutZeroTimeoutFromThrottlingTest : public ThrottlingTestBase { + public: + OptOutZeroTimeoutFromThrottlingTest() { + scoped_feature_list_.InitAndEnableFeature( + features::kOptOutZeroTimeoutTimersFromThrottling); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +} // namespace + +// Verify that in a hidden page, when the kOptOutZeroTimeoutTimersFromThrottling +// feature is enabled: +// - setTimeout(..., 0) and setTimeout(..., -1) schedule their callback after +// 1ms. The 1 ms delay exists for historical reasons crbug.com/402694. +// - setTimeout(..., 5) schedules its callback at the next aligned time +TEST_F(OptOutZeroTimeoutFromThrottlingTest, WithoutNesting) { + SimRequest main_resource("https://example.com/", "text/html"); + LoadURL("https://example.com/"); + main_resource.Complete( + "<script>" + " setTimeout(function() {" + " setTimeout(function() { console.log('setTimeout 0'); }, 0);" + " setTimeout(function() { console.log('setTimeout -1'); }, -1);" + " setTimeout(function() { console.log('setTimeout 5'); }, 5);" + " }, 1000);" + "</script>"); + GetDocument().GetPage()->GetPageScheduler()->SetPageVisible(false); + + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(1001)); + EXPECT_THAT(ConsoleMessages(), ElementsAre("setTimeout 0", "setTimeout -1")); + + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(998)); + EXPECT_THAT(ConsoleMessages(), ElementsAre("setTimeout 0", "setTimeout -1")); + + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); + EXPECT_THAT(ConsoleMessages(), + ElementsAre("setTimeout 0", "setTimeout -1", "setTimeout 5")); +} + +// Verify that in a hidden page, when the kOptOutZeroTimeoutTimersFromThrottling +// feature is enabled, a timer created with setTimeout(..., 0) is throttled +// after 5 nesting levels. +TEST_F(OptOutZeroTimeoutFromThrottlingTest, SetTimeoutNesting) { + SimRequest main_resource("https://example.com/", "text/html"); + LoadURL("https://example.com/"); + main_resource.Complete( + "<script>" + " function f(repetitions) {" + " if (repetitions == 0) return;" + " console.log('called f');" + " setTimeout(f, 0, repetitions - 1);" + " }" + " setTimeout(f, 0, 50);" + "</script>"); + GetDocument().GetPage()->GetPageScheduler()->SetPageVisible(false); + + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); + EXPECT_THAT(ConsoleMessages(), Vector<String>(1, "called f")); + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); + EXPECT_THAT(ConsoleMessages(), Vector<String>(2, "called f")); + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); + EXPECT_THAT(ConsoleMessages(), Vector<String>(3, "called f")); + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); + EXPECT_THAT(ConsoleMessages(), Vector<String>(4, "called f")); + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(995)); + EXPECT_THAT(ConsoleMessages(), Vector<String>(4, "called f")); + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); + EXPECT_THAT(ConsoleMessages(), Vector<String>(5, "called f")); +} + +// Verify that in a hidden page, when the kOptOutZeroTimeoutTimersFromThrottling +// feature is enabled, a timer created with setInterval(..., 0) is throttled +// after 5 nesting levels. +TEST_F(OptOutZeroTimeoutFromThrottlingTest, SetIntervalNesting) { + SimRequest main_resource("https://example.com/", "text/html"); + LoadURL("https://example.com/"); + main_resource.Complete( + "<script>" + " function f() {" + " if (repetitions == 0) clearInterval(interval_id);" + " console.log('called f');" + " repetitions = repetitions - 1;" + " }" + " var repetitions = 50;" + " var interval_id = setInterval(f, 0);" + "</script>"); + GetDocument().GetPage()->GetPageScheduler()->SetPageVisible(false); + + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); + EXPECT_THAT(ConsoleMessages(), Vector<String>(1, "called f")); + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); + EXPECT_THAT(ConsoleMessages(), Vector<String>(2, "called f")); + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); + EXPECT_THAT(ConsoleMessages(), Vector<String>(3, "called f")); + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); + EXPECT_THAT(ConsoleMessages(), Vector<String>(4, "called f")); + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(995)); + EXPECT_THAT(ConsoleMessages(), Vector<String>(4, "called f")); + platform_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); + EXPECT_THAT(ConsoleMessages(), Vector<String>(5, "called f")); +} + +namespace { + +class IntensiveWakeUpThrottlingTest : public ThrottlingTestBase { public: IntensiveWakeUpThrottlingTest() { scoped_feature_list_.InitWithFeatures( {features::kIntensiveWakeUpThrottling}, // Disable freezing because it hides the effect of intensive throttling. {features::kStopInBackground}); - - platform_->SetAutoAdvanceNowToPendingTasks(false); - - // Align the time on a 1-minute interval, to simplify expectations. - platform_->AdvanceClock( - platform_->NowTicks().SnappedToNextTick( - base::TimeTicks(), base::TimeDelta::FromMinutes(1)) - - platform_->NowTicks()); } void TestNoIntensiveThrotlingOnTitleOrFaviconUpdate() { @@ -133,20 +276,15 @@ EXPECT_THAT(ConsoleMessages(), expected_ouput); } - ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> - platform_; - private: base::test::ScopedFeatureList scoped_feature_list_; }; -namespace { - // Use to install a function that does not actually communicate with the user. constexpr char kCommunicationNop[] = "<script>" - " function maybeCommunicateInBackground() { " - " return; " + " function maybeCommunicateInBackground() {" + " return;" " }" "</script>"; @@ -154,7 +292,7 @@ // update. constexpr char kCommunicateThroughTitleScript[] = "<script>" - " function maybeCommunicateInBackground() { " + " function maybeCommunicateInBackground() {" " document.title += \"A\";" " }" "</script>"; @@ -163,7 +301,7 @@ // update. constexpr char kCommunicateThroughFavisonScript[] = "<script>" - " function maybeCommunicateInBackground() { " + " function maybeCommunicateInBackground() {" " document.querySelector(\"link[rel*='icon']\").href = \"favicon.ico\";" " }" "</script>";
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.h b/third_party/blink/renderer/core/workers/dedicated_worker.h index c5f64f7..f310727 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker.h
@@ -10,7 +10,7 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "services/network/public/mojom/url_loader_factory.mojom-blink.h" #include "third_party/blink/public/common/loader/worker_main_script_load_parameters.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/browser_interface_broker.mojom-blink-forward.h" #include "third_party/blink/public/platform/web_dedicated_worker.h" #include "third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h"
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h index 258ff1ff..50ea000 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
@@ -32,7 +32,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_DEDICATED_WORKER_GLOBAL_SCOPE_H_ #include <memory> -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/messaging/message_port.h"
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h index a73e37a7..cfc9757 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h
@@ -10,7 +10,7 @@ #include "base/memory/scoped_refptr.h" #include "base/optional.h" #include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/messaging/transferable_message.mojom-blink-forward.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/messaging/message_port.h"
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h b/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h index 08206d0..f8b0b92a 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h
@@ -34,7 +34,7 @@ #include <memory> #include "base/macros.h" #include "base/memory/scoped_refptr.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/messaging/message_port.h" #include "third_party/blink/renderer/core/workers/threaded_object_proxy_base.h"
diff --git a/third_party/blink/renderer/core/workers/shared_worker_global_scope.h b/third_party/blink/renderer/core/workers/shared_worker_global_scope.h index 9f729d9..d6ae45c 100644 --- a/third_party/blink/renderer/core/workers/shared_worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/shared_worker_global_scope.h
@@ -34,7 +34,7 @@ #include <memory> #include "services/metrics/public/cpp/ukm_source_id.h" #include "third_party/blink/public/common/messaging/message_port_channel.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/workers/global_scope_creation_params.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h"
diff --git a/third_party/blink/renderer/core/workers/shared_worker_thread.h b/third_party/blink/renderer/core/workers/shared_worker_thread.h index ac16212..a400165 100644 --- a/third_party/blink/renderer/core/workers/shared_worker_thread.h +++ b/third_party/blink/renderer/core/workers/shared_worker_thread.h
@@ -32,7 +32,7 @@ #include <memory> #include "services/metrics/public/cpp/ukm_source_id.h" -#include "third_party/blink/public/common/tokens/worker_tokens.h" +#include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/workers/worker_thread.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc b/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc index 76d204b..9c5145c 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc
@@ -123,7 +123,9 @@ IDBObjectStore* object_store = EffectiveObjectStore(); return object_store->DoPut(script_state, mojom::IDBPutMode::CursorUpdate, IDBRequest::Source::FromIDBCursor(this), value, - IdbPrimaryKey(), exception_state); + IdbPrimaryKey(), exception_state, + /*optional_custom_callback=*/nullptr, + /*blob_handles_out=*/nullptr); } void IDBCursor::advance(unsigned count, ExceptionState& exception_state) {
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc index 231d68c..ac684b1c 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
@@ -47,6 +47,7 @@ #include "third_party/blink/renderer/modules/indexeddb/idb_key_path.h" #include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h" #include "third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h" +#include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" @@ -353,7 +354,9 @@ IDB_TRACE1("IDBObjectStore::addRequestSetup", "store_name", metadata_->name.Utf8()); return DoPut(script_state, mojom::IDBPutMode::AddOnly, value, key, - exception_state); + exception_state, + /*optional_custom_callback=*/nullptr, + /*blob_handles_out=*/nullptr); } IDBRequest* IDBObjectStore::put(ScriptState* script_state, @@ -364,20 +367,171 @@ exception_state); } -HeapVector<Member<IDBRequest>> IDBObjectStore::putAll( - ScriptState* script_state, - const HeapVector<ScriptValue>& values, - ExceptionState& exception_state) { +namespace { + +class PutAllWebCallbacksAccumulationImpl + : public base::RefCounted<PutAllWebCallbacksAccumulationImpl> { + public: + PutAllWebCallbacksAccumulationImpl( + int num_custom_callbacks, + std::unique_ptr<WebIDBCallbacks> request_callbacks) + : request_callbacks_(std::move(request_callbacks)), + num_custom_callbacks_(num_custom_callbacks) {} + + void HandleCustomCallbackSuccess() { + DCHECK_GT(num_custom_callbacks_, 0); + num_custom_callbacks_--; + if (num_custom_callbacks_ == 0) + CallRequestCallbacks(); + } + + void HandleCustomCallbackError(mojom::blink::IDBException code, + const String& message) { + DCHECK_GT(num_custom_callbacks_, 0); + num_custom_callbacks_--; + received_error_ = true; + latest_error_code = code; + latest_error_message = message; + if (num_custom_callbacks_ == 0) + CallRequestCallbacks(); + } + + void CallRequestCallbacks() { + if (!received_error_) { + request_callbacks_->Success(); + } else { + request_callbacks_->Error(latest_error_code, latest_error_message); + } + } + + private: + friend class base::RefCounted<PutAllWebCallbacksAccumulationImpl>; + ~PutAllWebCallbacksAccumulationImpl() = default; + + std::unique_ptr<WebIDBCallbacks> request_callbacks_; + int num_custom_callbacks_; + bool received_error_ = false; + mojom::blink::IDBException latest_error_code; + String latest_error_message; +}; + +class PutAllWebCallbacksImpl : public WebIDBCallbacks { + public: + explicit PutAllWebCallbacksImpl( + scoped_refptr<PutAllWebCallbacksAccumulationImpl> callback_accumulator) + : callback_accumulator_(callback_accumulator) {} + + void Success() override { NOTREACHED(); } + + void Error(mojom::blink::IDBException code, const String& message) override { + callback_accumulator_->HandleCustomCallbackError(code, message); + } + + void SetState(base::WeakPtr<WebIDBCursorImpl> cursor, + int64_t transaction_id) override {} + + void SuccessNamesAndVersionsList( + Vector<mojom::blink::IDBNameAndVersionPtr> names_and_versions) override { + NOTREACHED(); + } + + void SuccessStringList(const Vector<String>&) override { NOTREACHED(); } + + void SuccessCursor( + mojo::PendingAssociatedRemote<mojom::blink::IDBCursor> cursor_info, + std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primary_key, + base::Optional<std::unique_ptr<IDBValue>> optional_value) override { + NOTREACHED(); + } + + void SuccessCursorPrefetch( + Vector<std::unique_ptr<IDBKey>> keys, + Vector<std::unique_ptr<IDBKey>> primary_keys, + Vector<std::unique_ptr<IDBValue>> values) override { + NOTREACHED(); + } + + void SuccessDatabase( + mojo::PendingAssociatedRemote<mojom::blink::IDBDatabase> pending_backend, + const IDBDatabaseMetadata& metadata) override { + NOTREACHED(); + } + + void SuccessKey(std::unique_ptr<IDBKey> key) override { + callback_accumulator_->HandleCustomCallbackSuccess(); + } + + void SuccessValue(mojom::blink::IDBReturnValuePtr return_value) override { + NOTREACHED(); + } + + void SuccessArray(Vector<mojom::blink::IDBReturnValuePtr> values) override { + NOTREACHED(); + } + + void SuccessInteger(int64_t value) override { NOTREACHED(); } + + void SuccessCursorContinue( + std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primary_key, + base::Optional<std::unique_ptr<IDBValue>> value) override { + NOTREACHED(); + } + + void Blocked(int64_t old_version) override { NOTREACHED(); } + + void UpgradeNeeded( + mojo::PendingAssociatedRemote<mojom::blink::IDBDatabase> pending_database, + int64_t old_version, + mojom::IDBDataLoss data_loss, + const String& data_loss_message, + const IDBDatabaseMetadata& metadata) override { + NOTREACHED(); + } + + void DetachRequestFromCallback() override { NOTREACHED(); } + + void ReceiveGetAllResults( + bool key_only, + mojo::PendingReceiver<mojom::blink::IDBDatabaseGetAllResultSink> receiver) + override { + NOTREACHED(); + } + + private: + scoped_refptr<PutAllWebCallbacksAccumulationImpl> callback_accumulator_; +}; + +} // namespace + +IDBRequest* IDBObjectStore::putAll(ScriptState* script_state, + const HeapVector<ScriptValue>& values, + ExceptionState& exception_state) { v8::Isolate* isolate = script_state->GetIsolate(); const ScriptValue& v8_undefined = ScriptValue(isolate, v8::Undefined(isolate)); - HeapVector<Member<IDBRequest>> requests; + IDBRequest::AsyncTraceState metrics("IDBObjectStore::putAll"); + IDBRequest* request = IDBRequest::Create( + script_state, this, transaction_.Get(), std::move(metrics)); + std::unique_ptr<WebIDBCallbacks> request_callbacks = + request->CreateWebCallbacks(); + scoped_refptr<PutAllWebCallbacksAccumulationImpl> callback_accumulator = + base::MakeRefCounted<PutAllWebCallbacksAccumulationImpl>( + values.size(), std::move(request_callbacks)); for (const auto& value : values) { + std::unique_ptr<WebIDBCallbacks> custom_callback = + std::make_unique<PutAllWebCallbacksImpl>(callback_accumulator); + Vector<scoped_refptr<BlobDataHandle>> blob_handles_out; IDBRequest* result = - put(script_state, value, v8_undefined, exception_state); - requests.push_back(*result); + DoPut(script_state, mojom::IDBPutMode::AddOrUpdate, value, v8_undefined, + exception_state, std::move(custom_callback), &blob_handles_out); + for (const auto& blob_handle : blob_handles_out) { + request->transit_blob_handles().push_back(blob_handle); + } + DCHECK(result == nullptr); } - return requests; + return request; } IDBRequest* IDBObjectStore::put(ScriptState* script_state, @@ -387,14 +541,19 @@ IDB_TRACE1("IDBObjectStore::putRequestSetup", "store_name", metadata_->name.Utf8()); return DoPut(script_state, mojom::IDBPutMode::AddOrUpdate, value, key, - exception_state); + exception_state, + /*optional_custom_callback=*/nullptr, + /*blob_handles_out=*/nullptr); } -IDBRequest* IDBObjectStore::DoPut(ScriptState* script_state, - mojom::IDBPutMode put_mode, - const ScriptValue& value, - const ScriptValue& key_value, - ExceptionState& exception_state) { +IDBRequest* IDBObjectStore::DoPut( + ScriptState* script_state, + mojom::IDBPutMode put_mode, + const ScriptValue& value, + const ScriptValue& key_value, + ExceptionState& exception_state, + std::unique_ptr<WebIDBCallbacks> optional_custom_callback, + Vector<scoped_refptr<BlobDataHandle>>* blob_handles_out) { std::unique_ptr<IDBKey> key = key_value.IsUndefined() ? nullptr @@ -402,17 +561,22 @@ script_state->GetIsolate(), key_value, exception_state); if (exception_state.HadException()) return nullptr; + return DoPut(script_state, put_mode, IDBRequest::Source::FromIDBObjectStore(this), value, key.get(), - exception_state); + exception_state, std::move(optional_custom_callback), + blob_handles_out); } -IDBRequest* IDBObjectStore::DoPut(ScriptState* script_state, - mojom::IDBPutMode put_mode, - const IDBRequest::Source& source, - const ScriptValue& value, - const IDBKey* key, - ExceptionState& exception_state) { +IDBRequest* IDBObjectStore::DoPut( + ScriptState* script_state, + mojom::IDBPutMode put_mode, + const IDBRequest::Source& source, + const ScriptValue& value, + const IDBKey* key, + ExceptionState& exception_state, + std::unique_ptr<WebIDBCallbacks> optional_custom_callback, + Vector<scoped_refptr<BlobDataHandle>>* blob_handles_out) { const char* tracing_name = nullptr; switch (put_mode) { case mojom::IDBPutMode::AddOrUpdate: @@ -596,8 +760,11 @@ base::saturated_cast<base::HistogramBase::Sample>( value_wrapper.DataLengthBeforeWrapInBytes() / 1024)); - IDBRequest* request = IDBRequest::Create( - script_state, source, transaction_.Get(), std::move(metrics)); + IDBRequest* request = nullptr; + if (!optional_custom_callback) { + request = IDBRequest::Create(script_state, source, transaction_.Get(), + std::move(metrics)); + } value_wrapper.DoneCloning(); @@ -607,11 +774,18 @@ value_wrapper.TakeWireBytes(), value_wrapper.TakeBlobInfo(), value_wrapper.TakeNativeFileSystemTransferTokens()); - request->transit_blob_handles() = value_wrapper.TakeBlobDataHandles(); + std::unique_ptr<WebIDBCallbacks> callbacks; + if (optional_custom_callback) { + *blob_handles_out = value_wrapper.TakeBlobDataHandles(); + callbacks = std::move(optional_custom_callback); + } else { + request->transit_blob_handles() = value_wrapper.TakeBlobDataHandles(); + callbacks = request->CreateWebCallbacks(); + } + transaction_->transaction_backend()->Put( Id(), std::move(idb_value), IDBKey::Clone(key), put_mode, - base::WrapUnique(request->CreateWebCallbacks().release()), - std::move(index_keys)); + std::move(callbacks), std::move(index_keys)); return request; }
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.h b/third_party/blink/renderer/modules/indexeddb/idb_object_store.h index 58353ab..ca85f63 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.h
@@ -102,9 +102,9 @@ const ScriptValue& key, ExceptionState&); IDBRequest* put(ScriptState*, const ScriptValue& value, ExceptionState&); - HeapVector<Member<IDBRequest>> putAll(ScriptState*, - const HeapVector<ScriptValue>& values, - ExceptionState&); + IDBRequest* putAll(ScriptState*, + const HeapVector<ScriptValue>& values, + ExceptionState&); IDBRequest* put(ScriptState*, const ScriptValue& value, const ScriptValue& key, @@ -131,7 +131,9 @@ const IDBRequest::Source&, const ScriptValue&, const IDBKey*, - ExceptionState&); + ExceptionState&, + std::unique_ptr<WebIDBCallbacks> optional_custom_callback, + Vector<scoped_refptr<BlobDataHandle>>* blob_handles_out); // Used internally and by InspectorIndexedDBAgent: IDBRequest* openCursor( @@ -207,7 +209,9 @@ mojom::IDBPutMode, const ScriptValue&, const ScriptValue& key_value, - ExceptionState&); + ExceptionState&, + std::unique_ptr<WebIDBCallbacks> optional_custom_callback, + Vector<scoped_refptr<BlobDataHandle>>* blob_handles_out); int64_t FindIndexId(const String& name) const;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.idl b/third_party/blink/renderer/modules/indexeddb/idb_object_store.idl index 275241c..844774e 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.idl +++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.idl
@@ -42,7 +42,7 @@ MeasureAs=IndexedDBWrite, RaisesException, RuntimeEnabled=IDBPutAll - ] sequence<IDBRequest> putAll(sequence<any> values); + ] IDBRequest putAll(sequence<any> values); [CallWith=ScriptState, MeasureAs=IndexedDBWrite, NewObject, RaisesException] IDBRequest add(any value, optional any key);
diff --git a/third_party/blink/renderer/modules/plugins/navigator_plugins.cc b/third_party/blink/renderer/modules/plugins/navigator_plugins.cc index 58a61076..6ea9da60 100644 --- a/third_party/blink/renderer/modules/plugins/navigator_plugins.cc +++ b/third_party/blink/renderer/modules/plugins/navigator_plugins.cc
@@ -11,6 +11,7 @@ #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/modules/plugins/dom_mime_type_array.h" #include "third_party/blink/renderer/modules/plugins/dom_plugin_array.h" +#include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h" namespace blink { @@ -65,14 +66,14 @@ IdentifiableTokenBuilder builder; for (unsigned i = 0; i < result->length(); i++) { DOMPlugin* plugin = result->item(i); - builder.AddAtomic(StringToBytesSafe(plugin->name())) - .AddAtomic(StringToBytesSafe(plugin->description())) - .AddAtomic(StringToBytesSafe(plugin->filename())); + builder.AddToken(IdentifiabilityBenignStringToken(plugin->name())) + .AddToken(IdentifiabilityBenignStringToken(plugin->description())) + .AddToken(IdentifiabilityBenignStringToken(plugin->filename())); for (unsigned j = 0; j < plugin->length(); j++) { DOMMimeType* mimeType = plugin->item(j); - builder.AddAtomic(StringToBytesSafe(mimeType->type())) - .AddAtomic(StringToBytesSafe(mimeType->description())) - .AddAtomic(StringToBytesSafe(mimeType->suffixes())); + builder.AddToken(IdentifiabilityBenignStringToken(mimeType->type())) + .AddToken(IdentifiabilityBenignStringToken(mimeType->description())) + .AddToken(IdentifiabilityBenignStringToken(mimeType->suffixes())); } } // ...and report to UKM. @@ -83,10 +84,6 @@ return result; } -base::span<const uint8_t> NavigatorPlugins::StringToBytesSafe(String str) const { - return str.Is8Bit() ? str.Span8() : as_bytes(str.Span16()); -} - DOMMimeTypeArray* NavigatorPlugins::mimeTypes(LocalFrame* frame) const { if (!mime_types_) mime_types_ = MakeGarbageCollected<DOMMimeTypeArray>(frame);
diff --git a/third_party/blink/renderer/modules/plugins/navigator_plugins.h b/third_party/blink/renderer/modules/plugins/navigator_plugins.h index 15b4b5d9..7f424a4 100644 --- a/third_party/blink/renderer/modules/plugins/navigator_plugins.h +++ b/third_party/blink/renderer/modules/plugins/navigator_plugins.h
@@ -37,8 +37,6 @@ mutable Member<DOMPluginArray> plugins_; mutable Member<DOMMimeTypeArray> mime_types_; - - base::span<const uint8_t> StringToBytesSafe(String str) const; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 2bfd450..ccdfd97 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1469,6 +1469,12 @@ "widget/compositing/layer_tree_view.cc", "widget/compositing/layer_tree_view.h", "widget/compositing/layer_tree_view_delegate.h", + "widget/compositing/queue_report_time_swap_promise.cc", + "widget/compositing/queue_report_time_swap_promise.h", + "widget/compositing/widget_compositor.cc", + "widget/compositing/widget_compositor.h", + "widget/compositing/widget_swap_queue.cc", + "widget/compositing/widget_swap_queue.h", "widget/frame_widget.cc", "widget/frame_widget.h", "widget/input/compositor_thread_event_queue.cc", @@ -2030,6 +2036,7 @@ "widget/compositing/layer_tree_settings_unittest.cc", "widget/compositing/layer_tree_view_unittest.cc", "widget/compositing/test/stub_layer_tree_view_delegate.h", + "widget/compositing/widget_compositor_unittest.cc", "widget/input/elastic_overscroll_controller_bezier_unittest.cc", "widget/input/elastic_overscroll_controller_exponential_unittest.cc", "widget/input/input_event_prediction_unittest.cc", @@ -2223,7 +2230,7 @@ sources = [ "testing/run_all_tests.cc" ] - if (is_linux) { + if (is_linux || is_chromeos) { deps += [ "//third_party/blink/renderer/platform/scheduler:scheduler_fuzzer_tests", ]
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc index 13ad534..e16fcda 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -32,6 +32,42 @@ #include "third_party/skia/include/gpu/GrDirectContext.h" namespace blink { + +class FlushForImageListener { + // With deferred rendering it's possible for a drawImage operation on a canvas + // to trigger a copy-on-write if another canvas has a read reference to it. + // This can cause serious regressions due to extra allocations: + // crbug.com/1030108. FlushForImageListener keeps a list of all active 2d + // contexts on a thread and notifies them when one is attempting copy-on + // write. If the notified context has a read reference to the canvas + // attempting a copy-on-write it then flushes so as to make the copy-on-write + // unnecessary. + public: + static FlushForImageListener* GetFlushForImageListener(); + void AddObserver(CanvasResourceProvider* observer) { + observers_.AddObserver(observer); + } + + void RemoveObserver(CanvasResourceProvider* observer) { + observers_.RemoveObserver(observer); + } + + void NotifyFlushForImage(cc::PaintImage::ContentId content_id) { + for (CanvasResourceProvider& obs : observers_) + obs.OnFlushForImage(content_id); + } + + private: + friend class WTF::ThreadSpecific<FlushForImageListener>; + base::ObserverList<CanvasResourceProvider> observers_; +}; + +static FlushForImageListener* GetFlushForImageListener() { + DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<FlushForImageListener>, + flush_for_image_listener, ()); + return flush_for_image_listener; +} + namespace { bool IsGMBAllowed(IntSize size, @@ -206,11 +242,15 @@ ->GetCapabilities() .supports_oop_raster) { resource_ = NewOrRecycledResource(); + GetFlushForImageListener()->AddObserver(this); + if (resource_) EnsureWriteAccess(); } - ~CanvasResourceProviderSharedImage() override {} + ~CanvasResourceProviderSharedImage() override { + GetFlushForImageListener()->RemoveObserver(this); + } bool IsAccelerated() const final { return is_accelerated_; } bool SupportsDirectCompositing() const override { return true; } @@ -354,6 +394,16 @@ if (IsGpuContextLost()) return; + // Because the cached snapshot is about to be cleared we'll record its + // content_id to be used by the FlushForImageListener. + // ShouldReplaceTargetBuffer needs this ID in order to let other contexts + // know to flush to avoid unnecessary copy-on-writes. + PaintImage::ContentId content_id = PaintImage::kInvalidContentId; + if (cached_snapshot_) { + content_id = + cached_snapshot_->PaintImageForCurrentFrame().GetContentIdForFrame( + 0u); + } // Since the resource will be updated, the cached snapshot is no longer // valid. Note that it is important to release this reference here to not // trigger copy-on-write below from the resource ref in the snapshot. @@ -365,7 +415,7 @@ // We don't need to do copy-on-write for the resource here since writes to // the GMB are deferred until it needs to be dispatched to the display // compositor via ProduceCanvasResource. - if (is_accelerated_ && ShouldReplaceTargetBuffer()) { + if (is_accelerated_ && ShouldReplaceTargetBuffer(content_id)) { DCHECK(!current_resource_has_write_access_) << "Write access must be released before sharing the resource"; @@ -454,7 +504,8 @@ ri->EndRasterCHROMIUM(); } - bool ShouldReplaceTargetBuffer() { + bool ShouldReplaceTargetBuffer( + PaintImage::ContentId content_id = PaintImage::kInvalidContentId) { // If the canvas is single buffered, concurrent read/writes to the resource // are allowed. Note that we ignore the resource lost case as well since // that only indicates that we did not get a sync token for read/write @@ -474,8 +525,12 @@ // Its possible to have deferred work in skia which uses this resource. Try // flushing once to see if that releases the read refs. We can avoid a copy // by queuing this work before writing to this resource. - if (is_accelerated_) + if (is_accelerated_) { + // Another context may have a read reference to this resource. Flush the + // deferred queue in that context so that we don't need to copy. + GetFlushForImageListener()->NotifyFlushForImage(content_id); surface_->flushAndSubmit(); + } return !resource_->HasOneRef(); } @@ -1090,6 +1145,15 @@ } } +void CanvasResourceProvider::OnFlushForImage(PaintImage::ContentId content_id) { + if (Canvas()) { + MemoryManagedPaintCanvas* canvas = + static_cast<MemoryManagedPaintCanvas*>(Canvas()); + if (canvas->IsCachingImage(content_id)) + this->FlushCanvas(); + } +} + void CanvasResourceProvider::ReleaseLockedImages() { if (canvas_image_provider_) canvas_image_provider_->ReleaseLockedImages();
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h index b8ed7f9..6cd6cf6d 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
@@ -11,8 +11,10 @@ #include "third_party/blink/renderer/platform/graphics/canvas_resource.h" #include "third_party/blink/renderer/platform/graphics/identifiability_paint_op_digest.h" #include "third_party/blink/renderer/platform/graphics/image_orientation.h" +#include "third_party/blink/renderer/platform/graphics/memory_managed_paint_recorder.h" #include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h" #include "third_party/blink/renderer/platform/instrumentation/canvas_memory_dump_provider.h" +#include "third_party/blink/renderer/platform/wtf/thread_specific.h" #include "third_party/skia/include/core/SkSurface.h" class GrDirectContext; @@ -58,6 +60,7 @@ class PLATFORM_EXPORT CanvasResourceProvider : public WebGraphicsContext3DProviderWrapper::DestructionObserver, + public base::CheckedObserver, public CanvasMemoryDumpClient { public: // These values are persisted to logs. Entries should not be renumbered and @@ -255,6 +258,8 @@ SkSurface::ContentChangeMode mode_ = SkSurface::kRetain_ContentChangeMode; private: + friend class FlushForImageListener; + void OnFlushForImage(cc::PaintImage::ContentId content_id); virtual sk_sp<SkSurface> CreateSkSurface() const = 0; virtual scoped_refptr<CanvasResource> CreateResource(); virtual bool UseOopRasterization() { return false; } @@ -282,7 +287,7 @@ const bool is_origin_top_left_; std::unique_ptr<CanvasImageProvider> canvas_image_provider_; std::unique_ptr<cc::SkiaPaintCanvas> skia_canvas_; - std::unique_ptr<PaintRecorder> recorder_; + std::unique_ptr<MemoryManagedPaintRecorder> recorder_; bool needs_flush_ = false;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc index 114cd18..41058175f 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
@@ -524,4 +524,52 @@ kColorParams.GetOpacityMode()); } +TEST_F(CanvasResourceProviderTest, FlushForImage) { + const IntSize kSize(10, 10); + const CanvasColorParams kColorParams( + CanvasColorSpace::kSRGB, CanvasColorParams::GetNativeCanvasPixelFormat(), + kNonOpaque); + + auto src_provider = CanvasResourceProvider::CreateSharedImageProvider( + kSize, context_provider_wrapper_, kMedium_SkFilterQuality, kColorParams, + true /* is_origin_top_left */, RasterMode::kGPU, 0u); + + auto dst_provider = CanvasResourceProvider::CreateSharedImageProvider( + kSize, context_provider_wrapper_, kMedium_SkFilterQuality, kColorParams, + true /* is_origin_top_left */, RasterMode::kGPU, 0u); + + MemoryManagedPaintCanvas* dst_canvas = + static_cast<MemoryManagedPaintCanvas*>(dst_provider->Canvas()); + + PaintImage paint_image = + src_provider->Snapshot()->PaintImageForCurrentFrame(); + PaintImage::ContentId src_content_id = paint_image.GetContentIdForFrame(0u); + + EXPECT_FALSE(dst_canvas->IsCachingImage(src_content_id)); + + cc::PaintFlags flags; + dst_canvas->drawImage(paint_image, 0, 0, &flags); + + EXPECT_TRUE(dst_canvas->IsCachingImage(src_content_id)); + + src_provider->Canvas()->clear( + SK_ColorWHITE); // Modify the canvas to trigger OnFlushForImage + src_provider + ->ProduceCanvasResource(); // So that all the cached draws are executed + + // The paint canvas may have moved + dst_canvas = static_cast<MemoryManagedPaintCanvas*>(dst_provider->Canvas()); + + // TODO(aaronhk): The resource on the src_provider should be the same before + // and after the draw. Something about the program flow within + // this testing framework (but not in layout tests) makes a reference to + // the src_resource stick around throughout the FlushForImage call so the + // src_resource changes in this test. Things work as expected for actual + // browser code like canvas_to_canvas_draw.html. + + // OnFlushForImage should detect the modification of the source resource and + // clear the cache of the destination canvas to avoid a copy-on-write. + EXPECT_FALSE(dst_canvas->IsCachingImage(src_content_id)); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.cc b/third_party/blink/renderer/platform/graphics/graphics_context.cc index ec7473c..90ea268 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -355,8 +355,7 @@ } // namespace -int GraphicsContext::FocusRingOutsetExtent(int offset, - int width) { +int GraphicsContext::FocusRingOutsetExtent(int offset, int width) { // Unlike normal outlines (whole width is outside of the offset), focus // rings can be drawn with the center of the path aligned with the offset, so // only half of the width is outside of the offset. @@ -1268,13 +1267,7 @@ void GraphicsContext::SetURLForRect(const KURL& link, const IntRect& dest_rect) { - DCHECK(canvas_ || tracker_); - - // Intercept URL rects when painting previews. - if (IsPaintingPreview() && tracker_) { - tracker_->AnnotateLink(GURL(link), dest_rect); - return; - } + DCHECK(canvas_); sk_sp<SkData> url(SkData::MakeWithCString(link.GetString().Utf8().c_str())); canvas_->Annotate(cc::PaintCanvas::AnnotationType::URL, dest_rect, @@ -1283,13 +1276,7 @@ void GraphicsContext::SetURLFragmentForRect(const String& dest_name, const IntRect& rect) { - DCHECK(canvas_ || tracker_); - - // Intercept URL rects when painting previews. - if (IsPaintingPreview() && tracker_) { - tracker_->AnnotateLink(GURL(dest_name.Utf8()), rect); - return; - } + DCHECK(canvas_); sk_sp<SkData> sk_dest_name(SkData::MakeWithCString(dest_name.Utf8().c_str())); canvas_->Annotate(cc::PaintCanvas::AnnotationType::LINK_TO_DESTINATION, rect, @@ -1300,6 +1287,10 @@ const IntPoint& location) { DCHECK(canvas_); + // Paint previews don't make use of linked destinations. + if (tracker_) + return; + SkRect rect = SkRect::MakeXYWH(location.X(), location.Y(), 0, 0); sk_sp<SkData> sk_name(SkData::MakeWithCString(name.Utf8().c_str())); canvas_->Annotate(cc::PaintCanvas::AnnotationType::NAMED_DESTINATION, rect,
diff --git a/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.cc b/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.cc index 527bbf2..7c11403f 100644 --- a/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.cc +++ b/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.cc
@@ -46,4 +46,9 @@ set_needs_flush_callback_.Run(); } +bool MemoryManagedPaintCanvas::IsCachingImage( + const cc::PaintImage::ContentId content_id) const { + return cached_image_ids_.Contains(content_id); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.h b/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.h index 1a7c000..2d2d17a 100644 --- a/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.h +++ b/third_party/blink/renderer/platform/graphics/memory_managed_paint_canvas.h
@@ -7,8 +7,10 @@ #include <memory> +#include "cc/paint/paint_canvas.h" #include "cc/paint/record_paint_canvas.h" #include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" namespace blink { @@ -36,10 +38,14 @@ const cc::PaintFlags* flags, SkCanvas::SrcRectConstraint constraint) override; + bool IsCachingImage(const cc::PaintImage::ContentId content_id) const; + private: void UpdateMemoryUsage(const cc::PaintImage& image); - HashSet<int, DefaultHash<int>::Hash, WTF::UnsignedWithZeroKeyHashTraits<int>> + HashSet<cc::PaintImage::ContentId, + DefaultHash<cc::PaintImage::ContentId>::Hash, + WTF::UnsignedWithZeroKeyHashTraits<cc::PaintImage::ContentId>> cached_image_ids_; uint64_t total_stored_image_memory_ = 0;
diff --git a/third_party/blink/renderer/platform/scheduler/BUILD.gn b/third_party/blink/renderer/platform/scheduler/BUILD.gn index 22550984..3a2eb4a 100644 --- a/third_party/blink/renderer/platform/scheduler/BUILD.gn +++ b/third_party/blink/renderer/platform/scheduler/BUILD.gn
@@ -262,7 +262,7 @@ "//third_party/blink/renderer/platform/scheduler:test_support", ] - if (is_linux) { + if (is_linux || is_chromeos) { sources += [ "test/fuzzer/sequence_manager_fuzzer_processor.cc", "test/fuzzer/sequence_manager_fuzzer_processor.h",
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc index c1beca5..f3af71aa2 100644 --- a/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc +++ b/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc
@@ -23,7 +23,6 @@ : BudgetPool(name, budget_pool_controller), current_budget_level_(base::TimeDelta(), "RendererScheduler.BackgroundBudgetMs", - budget_pool_controller, tracing_controller, TimeDeltaToMilliseconds), last_checkpoint_(now),
diff --git a/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h b/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h index d82b092..34639cb 100644 --- a/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h +++ b/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h
@@ -93,14 +93,13 @@ DISALLOW_NEW(); public: - StateTracer(const char* name, const void* object) - : name_(name), object_(object), slice_is_open_(false) { + explicit StateTracer(const char* name) : name_(name), slice_is_open_(false) { internal::ValidateTracingCategory(category); } ~StateTracer() { if (slice_is_open_) - TRACE_EVENT_NESTABLE_ASYNC_END0(category, name_, TRACE_ID_LOCAL(object_)); + TRACE_EVENT_NESTABLE_ASYNC_END0(category, name_, TRACE_ID_LOCAL(this)); } // String will be copied before leaving this function. @@ -122,25 +121,23 @@ private: void TraceImpl(const char* state, bool need_copy) { if (slice_is_open_) { - TRACE_EVENT_NESTABLE_ASYNC_END0(category, name_, TRACE_ID_LOCAL(object_)); + TRACE_EVENT_NESTABLE_ASYNC_END0(category, name_, TRACE_ID_LOCAL(this)); slice_is_open_ = false; } if (!state || !is_enabled()) return; if (need_copy) { - TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(category, name_, - TRACE_ID_LOCAL(object_), "state", - TRACE_STR_COPY(state)); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(category, name_, TRACE_ID_LOCAL(this), + "state", TRACE_STR_COPY(state)); } else { - TRACE_EVENT_NESTABLE_ASYNC_BEGIN1( - category, name_, TRACE_ID_LOCAL(object_), "state", state); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(category, name_, TRACE_ID_LOCAL(this), + "state", state); } slice_is_open_ = true; } const char* const name_; // Not owned. - const void* const object_; // Not owned. // We have to track whether slice is open to avoid confusion since assignment, // "absent" state and OnTraceLogEnabled can happen anytime. @@ -160,11 +157,10 @@ TraceableState(T initial_state, const char* name, - const void* object, TraceableVariableController* controller, ConverterFuncPtr converter) : TraceableVariable(controller), - StateTracer<category>(name, object), + StateTracer<category>(name), converter_(converter), state_(initial_state) { Trace(); @@ -227,12 +223,10 @@ TraceableCounter(T initial_value, const char* name, - const void* object, TraceableVariableController* controller, ConverterFuncPtr converter) : TraceableVariable(controller), name_(name), - object_(object), converter_(converter), value_(initial_value) { internal::ValidateTracingCategory(category); @@ -241,16 +235,10 @@ TraceableCounter(T initial_value, const char* name, - const void* object, TraceableVariableController* controller) - : TraceableVariable(controller), - name_(name), - object_(object), - converter_([](const T& value) { return static_cast<double>(value); }), - value_(initial_value) { - internal::ValidateTracingCategory(category); - Trace(); - } + : TraceableCounter(initial_value, name, controller, [](const T& value) { + return static_cast<double>(value); + }) {} TraceableCounter& operator=(const T& value) { value_ = value; @@ -281,12 +269,11 @@ void OnTraceLogEnabled() final { Trace(); } void Trace() const { - TRACE_COUNTER_ID1(category, name_, object_, converter_(value_)); + TRACE_COUNTER_ID1(category, name_, this, converter_(value_)); } private: const char* const name_; // Not owned. - const void* const object_; // Not owned. const ConverterFuncPtr converter_; T value_;
diff --git a/third_party/blink/renderer/platform/scheduler/common/tracing_helper_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/tracing_helper_unittest.cc index bae7678f..fceebdef 100644 --- a/third_party/blink/renderer/platform/scheduler/common/tracing_helper_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/common/tracing_helper_unittest.cc
@@ -36,7 +36,7 @@ : public TraceableState<int, TracingCategoryName::kDefault> { public: TraceableStateForTest(TraceableVariableController* controller) - : TraceableState(0, "State", controller, controller, SignOfInt) { + : TraceableState(0, "State", controller, SignOfInt) { // We shouldn't expect trace in constructor here because mock isn't set yet. mock_trace_for_test_ = &MockTrace; } @@ -73,9 +73,9 @@ TEST(TracingHelperTest, TraceableStateOperators) { TraceableVariableController controller; TraceableState<int, TracingCategoryName::kDebug> x(-1, "X", &controller, - &controller, SignOfInt); + SignOfInt); TraceableState<int, TracingCategoryName::kDebug> y(1, "Y", &controller, - &controller, SignOfInt); + SignOfInt); EXPECT_EQ(0, x + y); EXPECT_FALSE(x == y); EXPECT_TRUE(x != y);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc index 159492c..537aebf 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -123,62 +123,52 @@ throttling_state_(SchedulingLifecycleState::kNotThrottled), frame_visible_(true, "FrameScheduler.FrameVisible", - this, &tracing_controller_, VisibilityStateToString), frame_paused_(false, "FrameScheduler.FramePaused", - this, &tracing_controller_, PausedStateToString), frame_origin_type_(frame_type == FrameType::kMainFrame ? FrameOriginType::kMainFrame : FrameOriginType::kSameOriginToMainFrame, "FrameScheduler.Origin", - this, &tracing_controller_, FrameOriginTypeToString), subresource_loading_paused_(false, "FrameScheduler.SubResourceLoadingPaused", - this, &tracing_controller_, PausedStateToString), - url_tracer_("FrameScheduler.URL", this), + url_tracer_("FrameScheduler.URL"), task_queues_throttled_(false, "FrameScheduler.TaskQueuesThrottled", - this, &tracing_controller_, YesNoStateToString), preempted_for_cooperative_scheduling_( false, "FrameScheduler.PreemptedForCooperativeScheduling", - this, &tracing_controller_, YesNoStateToString), all_throttling_opt_out_count_(0), aggressive_throttling_opt_out_count_(0), opted_out_from_all_throttling_(false, "FrameScheduler.AllThrottlingDisabled", - this, &tracing_controller_, YesNoStateToString), opted_out_from_aggressive_throttling_( false, "FrameScheduler.AggressiveThrottlingDisabled", - this, &tracing_controller_, YesNoStateToString), subresource_loading_pause_count_(0u), opted_out_from_back_forward_cache_( false, "FrameScheduler.OptedOutFromBackForwardCache", - this, &tracing_controller_, YesNoStateToString), page_frozen_for_tracing_( parent_page_scheduler_ ? parent_page_scheduler_->IsFrozen() : true, "FrameScheduler.PageFrozen", - this, &tracing_controller_, FrozenStateToString), page_visibility_for_tracing_( @@ -186,23 +176,19 @@ ? PageVisibilityState::kVisible : PageVisibilityState::kHidden, "FrameScheduler.PageVisibility", - this, &tracing_controller_, PageVisibilityStateToString), page_keep_active_for_tracing_( parent_page_scheduler_ ? parent_page_scheduler_->KeepActive() : false, "FrameScheduler.KeepActive", - this, &tracing_controller_, KeepActiveStateToString), waiting_for_contentful_paint_(true, "FrameScheduler.WaitingForContentfulPaint", - this, &tracing_controller_, YesNoStateToString), waiting_for_meaningful_paint_(true, "FrameScheduler.WaitingForMeaningfulPaint", - this, &tracing_controller_, YesNoStateToString) { frame_task_queue_controller_.reset( @@ -386,9 +372,16 @@ case TaskType::kInternalContentCapture: return ThrottleableTaskQueueTraits().SetPrioritisationType( QueueTraits::PrioritisationType::kBestEffort); - case TaskType::kJavascriptTimer: + case TaskType::kJavascriptTimerDelayed: return ThrottleableTaskQueueTraits().SetPrioritisationType( QueueTraits::PrioritisationType::kJavaScriptTimer); + case TaskType::kJavascriptTimerImmediate: { + return DeferrableTaskQueueTraits() + .SetPrioritisationType( + QueueTraits::PrioritisationType::kJavaScriptTimer) + .SetCanBeThrottled(!base::FeatureList::IsEnabled( + features::kOptOutZeroTimeoutTimersFromThrottling)); + } case TaskType::kInternalLoading: case TaskType::kNetworking: case TaskType::kNetworkingWithURLLoaderAnnotation:
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc index 3f60fb9c..12b1cbb 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
@@ -90,7 +90,8 @@ // FrameSchedulerImpl::CreateQueueTraitsForTaskType(). constexpr TaskType kAllFrameTaskTypes[] = { TaskType::kInternalContentCapture, - TaskType::kJavascriptTimer, + TaskType::kJavascriptTimerDelayed, + TaskType::kJavascriptTimerImmediate, TaskType::kInternalLoading, TaskType::kNetworking, TaskType::kNetworkingWithURLLoaderAnnotation, @@ -138,7 +139,7 @@ TaskType::kInternalHighPriorityLocalFrame}; static_assert( - static_cast<int>(TaskType::kCount) == 72, + static_cast<int>(TaskType::kCount) == 73, "When adding a TaskType, make sure that kAllFrameTaskTypes is updated."); void AppendToVectorTestTask(Vector<String>* vector, String value) { @@ -324,6 +325,12 @@ PrioritisationType::kJavaScriptTimer)); } + scoped_refptr<TaskQueue> JavaScriptTimerNonThrottleableTaskQueue() { + return GetTaskQueue( + FrameSchedulerImpl::DeferrableTaskQueueTraits().SetPrioritisationType( + PrioritisationType::kJavaScriptTimer)); + } + scoped_refptr<TaskQueue> LoadingTaskQueue() { return GetTaskQueue(FrameSchedulerImpl::LoadingTaskQueueTraits()); } @@ -729,7 +736,7 @@ 2 / kTaskPeriod; // This TaskRunner is throttled. const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer); + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed); // Hide the page. This enables wake up throttling. EXPECT_TRUE(page_scheduler_->IsPageVisible()); @@ -757,14 +764,14 @@ constexpr int kNumTasks = 3; // |task_runner| is throttled. const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer); + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed); // |other_task_runner| is throttled. It belongs to a different frame on the // same page. const auto other_frame_scheduler = CreateFrameScheduler( page_scheduler_.get(), frame_scheduler_delegate_.get(), nullptr, FrameScheduler::FrameType::kSubframe); const scoped_refptr<base::SingleThreadTaskRunner> other_task_runner = - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer); + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed); // Fast-forward the time to a multiple of |kDefaultThrottledWakeUpInterval|. // Otherwise, the time at which tasks run will vary. @@ -2180,8 +2187,18 @@ // Make sure the queue lookup and task type to queue traits map works as // expected. This test will fail if these task types are moved to different // default queues. - EXPECT_EQ(GetTaskQueue(TaskType::kJavascriptTimer), + EXPECT_EQ(GetTaskQueue(TaskType::kJavascriptTimerDelayed), JavaScriptTimerTaskQueue()); + EXPECT_EQ(GetTaskQueue(TaskType::kJavascriptTimerImmediate), + JavaScriptTimerTaskQueue()); + { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + features::kOptOutZeroTimeoutTimersFromThrottling); + EXPECT_EQ(GetTaskQueue(TaskType::kJavascriptTimerImmediate), + JavaScriptTimerNonThrottleableTaskQueue()); + } + EXPECT_EQ(GetTaskQueue(TaskType::kWebSocket), DeferrableTaskQueue()); EXPECT_EQ(GetTaskQueue(TaskType::kDatabaseAccess), PausableTaskQueue()); EXPECT_EQ(GetTaskQueue(TaskType::kPostedMessage), PausableTaskQueue()); @@ -2193,9 +2210,10 @@ ForegroundOnlyTaskQueue()); } -// Verify that kJavascriptTimer is the only non-internal TaskType that can be -// throttled. This ensures that the Javascript timer throttling experiment only -// affects wake ups from Javascript timers https://crbug.com/1075553 +// Verify that kJavascriptTimerDelayed is the only non-internal TaskType that +// can be throttled. This ensures that the Javascript timer throttling +// experiment only affects wake ups from Javascript timers +// https://crbug.com/1075553 TEST_F(FrameSchedulerImplTest, ThrottledTaskTypes) { page_scheduler_->SetPageVisible(false); @@ -2205,7 +2223,8 @@ << TaskTypeNames::TaskTypeToString(task_type)); switch (task_type) { case TaskType::kInternalContentCapture: - case TaskType::kJavascriptTimer: + case TaskType::kJavascriptTimerDelayed: + case TaskType::kJavascriptTimerImmediate: case TaskType::kInternalTranslation: EXPECT_TRUE(IsTaskTypeThrottled(task_type)); break; @@ -2275,7 +2294,7 @@ } TEST_F(FrameSchedulerImplTest, ComputePriorityForDetachedFrame) { - auto task_queue = GetTaskQueue(TaskType::kJavascriptTimer); + auto task_queue = GetTaskQueue(TaskType::kJavascriptTimerDelayed); // Just check that it does not crash. page_scheduler_.reset(); frame_scheduler_->ComputePriority(task_queue.get()); @@ -2415,7 +2434,7 @@ TEST_F(FrameSchedulerImplTest, FeatureUpload) { ResetFrameScheduler(FrameScheduler::FrameType::kMainFrame); - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer) + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed) ->PostTask( FROM_HERE, base::BindOnce( @@ -2454,7 +2473,7 @@ FeatureHandle feature_handle; - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer) + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed) ->PostTask( FROM_HERE, base::BindOnce( @@ -2474,7 +2493,7 @@ }, frame_scheduler_.get(), frame_scheduler_delegate_.get(), &feature_handle)); - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer) + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed) ->PostTask(FROM_HERE, base::BindOnce( [](FrameSchedulerImpl* frame_scheduler, @@ -2584,8 +2603,8 @@ testing::ElementsAre("V1", "V2", "B1", "B2", "U1", "U2")); } -// Verify that tasks posted with TaskType::kJavascriptTimer run at the expected -// time when throttled. +// Verify that tasks posted with TaskType::kJavascriptTimerDelayed run at the +// expected time when throttled. TEST_F(FrameSchedulerImplTest, ThrottledJSTimerTasksRunTime) { // Snap the time to a multiple of 1 second. Otherwise, the exact run time // of throttled tasks after hiding the page will vary. @@ -2596,7 +2615,7 @@ page_scheduler_->SetPageVisible(false); const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer); + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed); std::vector<base::TimeTicks> run_times; // Post tasks. @@ -2694,7 +2713,7 @@ // Throttled TaskRunner to which tasks are posted in this test. const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer); + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed); // Snap the time to a multiple of // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, the time at which @@ -2850,7 +2869,7 @@ // Throttled TaskRunner to which tasks are posted in this test. const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer); + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed); // Snap the time to a multiple of // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, the time at which @@ -3000,7 +3019,7 @@ ManySameFrameOriginFrames) { ASSERT_FALSE(frame_scheduler_->IsCrossOriginToMainFrame()); const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer); + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed); // Create a FrameScheduler that is same-origin with the main frame, and an // associated throttled TaskRunner. @@ -3010,7 +3029,7 @@ FrameScheduler::FrameType::kSubframe); ASSERT_FALSE(other_frame_scheduler->IsCrossOriginToMainFrame()); const scoped_refptr<base::SingleThreadTaskRunner> other_task_runner = - other_frame_scheduler->GetTaskRunner(TaskType::kJavascriptTimer); + other_frame_scheduler->GetTaskRunner(TaskType::kJavascriptTimerDelayed); // Snap the time to a multiple of // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, the time at which @@ -3059,14 +3078,14 @@ constexpr int kNumTasks = 3; // |task_runner| is throttled. const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer); + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed); // |other_task_runner| is throttled. It belongs to a different frame on the // same page. const auto other_frame_scheduler = CreateFrameScheduler( page_scheduler_.get(), frame_scheduler_delegate_.get(), nullptr, FrameScheduler::FrameType::kSubframe); const scoped_refptr<base::SingleThreadTaskRunner> other_task_runner = - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer); + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed); // Fast-forward the time to a multiple of // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, @@ -3183,14 +3202,14 @@ constexpr int kNumTasks = 3; // |task_runner| is throttled. const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer); + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed); // |other_task_runner| is throttled. It belongs to a different frame on the // same page. const auto other_frame_scheduler = CreateFrameScheduler( page_scheduler_.get(), frame_scheduler_delegate_.get(), nullptr, FrameScheduler::FrameType::kSubframe); const scoped_refptr<base::SingleThreadTaskRunner> other_task_runner = - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer); + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed); // Fast-forward the time to a multiple of // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, @@ -3312,7 +3331,7 @@ FrameChangesOriginType) { EXPECT_FALSE(frame_scheduler_->IsCrossOriginToMainFrame()); const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer); + frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed); // Create a new FrameScheduler that remains cross-origin with the main frame // throughout the test. @@ -3322,7 +3341,8 @@ FrameScheduler::FrameType::kSubframe); cross_origin_frame_scheduler->SetCrossOriginToMainFrame(true); const scoped_refptr<base::SingleThreadTaskRunner> cross_origin_task_runner = - cross_origin_frame_scheduler->GetTaskRunner(TaskType::kJavascriptTimer); + cross_origin_frame_scheduler->GetTaskRunner( + TaskType::kJavascriptTimerDelayed); // Snap the time to a multiple of // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, the time at which
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc index 1b9223c..c3cb873 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -348,94 +348,77 @@ kShortIdlePeriodDurationPercentile), current_use_case(UseCase::kNone, "Scheduler.UseCase", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, UseCaseToString), longest_jank_free_task_duration( base::TimeDelta(), "Scheduler.LongestJankFreeTaskDuration", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, TimeDeltaToMilliseconds), renderer_pause_count(0, "Scheduler.PauseCount", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_), rail_mode_for_tracing(current_policy.rail_mode(), "Scheduler.RAILMode", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, RAILModeToString), renderer_hidden(false, "RendererVisibility", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, HiddenStateToString), renderer_backgrounded(kLaunchingProcessIsBackgrounded, "RendererPriority", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, BackgroundStateToString), keep_active_fetch_or_worker( false, "Scheduler.KeepRendererActive", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), blocking_input_expected_soon( false, "Scheduler.BlockingInputExpectedSoon", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), have_reported_blocking_intervention_in_current_policy( false, "Scheduler.HasReportedBlockingInterventionInCurrentPolicy", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), have_reported_blocking_intervention_since_navigation( false, "Scheduler.HasReportedBlockingInterventionSinceNavigation", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), has_visible_render_widget_with_touch_handler( false, "Scheduler.HasVisibleRenderWidgetWithTouchHandler", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), in_idle_period_for_testing( false, "Scheduler.InIdlePeriod", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), use_virtual_time(false, "Scheduler.UseVirtualTime", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), is_audio_playing(false, "RendererAudioState", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, AudioPlayingStateToString), compositor_will_send_main_frame_not_expected( false, "Scheduler.CompositorWillSendMainFrameNotExpected", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), has_navigated(false, "Scheduler.HasNavigated", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), pause_timers_for_webview(false, "Scheduler.PauseTimersForWebview", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), background_status_changed_at(now), @@ -446,19 +429,16 @@ renderer_backgrounded), process_type(WebRendererProcessType::kRenderer, "RendererProcessType", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, RendererProcessTypeToString), task_description_for_tracing( base::nullopt, "Scheduler.MainThreadTask", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, OptionalTaskDescriptionToString), task_priority_for_tracing( base::nullopt, "Scheduler.TaskPriority", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, OptionalTaskPriorityToString), virtual_time_policy(VirtualTimePolicy::kAdvance), @@ -469,7 +449,6 @@ prioritize_compositing_after_input( false, "Scheduler.PrioritizeCompositingAfterInput", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), compositor_priority_experiments(main_thread_scheduler_impl), @@ -482,60 +461,50 @@ : awaiting_touch_start_response( false, "Scheduler.AwaitingTouchstartResponse", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), in_idle_period(false, "Scheduler.InIdlePeriod", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), begin_main_frame_on_critical_path( false, "Scheduler.BeginMainFrameOnCriticalPath", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), last_gesture_was_compositor_driven( false, "Scheduler.LastGestureWasCompositorDriven", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), default_gesture_prevented( true, "Scheduler.DefaultGesturePrevented", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), have_seen_a_blocking_gesture( false, "Scheduler.HaveSeenBlockingGesture", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), waiting_for_any_main_frame_contentful_paint( false, "Scheduler.WaitingForMainFrameContentfulPaint", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), waiting_for_any_main_frame_meaningful_paint( false, "Scheduler.WaitingForMeaningfulPaint", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), have_seen_input_since_navigation( false, "Scheduler.HaveSeenInputSinceNavigation", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), begin_main_frame_scheduled_count( 0, "Scheduler.BeginMainFrameScheduledCount", - main_thread_scheduler_impl, &main_thread_scheduler_impl->tracing_controller_) {} MainThreadSchedulerImpl::SchedulingSettings::SchedulingSettings() {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc index e4b7a31..6ee6e345 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
@@ -3869,8 +3869,8 @@ CreateFrameScheduler(page_scheduler.get(), &frame_delegate, nullptr, FrameScheduler::FrameType::kSubframe); - scoped_refptr<TaskQueue> timer_tq = - QueueForTaskType(frame_scheduler.get(), TaskType::kJavascriptTimer); + scoped_refptr<TaskQueue> timer_tq = QueueForTaskType( + frame_scheduler.get(), TaskType::kJavascriptTimerDelayed); ForceUpdatePolicyAndGetCurrentUseCase(); EXPECT_FALSE(timer_tq->IsQueueEnabled()); @@ -3892,8 +3892,8 @@ CreateFrameScheduler(page_scheduler.get(), &frame_delegate, nullptr, FrameScheduler::FrameType::kSubframe); - scoped_refptr<TaskQueue> timer_tq = - QueueForTaskType(frame_scheduler.get(), TaskType::kJavascriptTimer); + scoped_refptr<TaskQueue> timer_tq = QueueForTaskType( + frame_scheduler.get(), TaskType::kJavascriptTimerDelayed); FakeInputEvent mouse_move_event{WebInputEvent::Type::kMouseMove, blink::WebInputEvent::kLeftButtonDown};
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc index 07d10cf1..f462aab 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
@@ -35,8 +35,10 @@ return "CanvasBlobSerialization"; case TaskType::kMicrotask: return "Microtask"; - case TaskType::kJavascriptTimer: - return "JavascriptTimer"; + case TaskType::kJavascriptTimerDelayed: + return "JavascriptTimerDelayed"; + case TaskType::kJavascriptTimerImmediate: + return "JavascriptTimerImmediate"; case TaskType::kRemoteEvent: return "RemoteEvent"; case TaskType::kWebSocket:
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc index 5d2f6746..04fa08a 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
@@ -133,7 +133,8 @@ scoped_refptr<base::SingleThreadTaskRunner> WorkerScheduler::GetTaskRunner( TaskType type) const { switch (type) { - case TaskType::kJavascriptTimer: + case TaskType::kJavascriptTimerDelayed: + case TaskType::kJavascriptTimerImmediate: case TaskType::kPostedMessage: case TaskType::kWorkerAnimation: return throttleable_task_queue_->CreateTaskRunner(type);
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc index e979188..a6552d0 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc
@@ -286,7 +286,7 @@ // Tests interlacing pausable, throttable and unpausable tasks and // ensures that the pausable & throttable tasks don't run when paused. // Throttable - PostTestTask(&run_order, "T1", TaskType::kJavascriptTimer); + PostTestTask(&run_order, "T1", TaskType::kJavascriptTimerDelayed); // Pausable PostTestTask(&run_order, "T2", TaskType::kNetworking); // Unpausable @@ -304,7 +304,7 @@ auto pause_handle = worker_scheduler_->Pause(); { auto pause_handle2 = worker_scheduler_->Pause(); - PostTestTask(&run_order, "T1", TaskType::kJavascriptTimer); + PostTestTask(&run_order, "T1", TaskType::kJavascriptTimerDelayed); PostTestTask(&run_order, "T2", TaskType::kNetworking); } RunUntilIdle();
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc index 76cce482..4ddb680 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
@@ -539,7 +539,7 @@ scheduler_->SetUkmRecorderForTest(std::move(owned_ukm_recorder)); base::sequence_manager::FakeTask task( - static_cast<int>(TaskType::kJavascriptTimer)); + static_cast<int>(TaskType::kJavascriptTimerDelayed)); base::sequence_manager::FakeTaskTiming task_timing( base::TimeTicks() + base::TimeDelta::FromMilliseconds(200), base::TimeTicks() + base::TimeDelta::FromMilliseconds(700), @@ -557,7 +557,8 @@ ukm::TestUkmRecorder::ExpectEntryMetric(entries[0], "RendererBackgrounded", true); ukm::TestUkmRecorder::ExpectEntryMetric( - entries[0], "TaskType", static_cast<int>(TaskType::kJavascriptTimer)); + entries[0], "TaskType", + static_cast<int>(TaskType::kJavascriptTimerDelayed)); ukm::TestUkmRecorder::ExpectEntryMetric( entries[0], "FrameStatus", static_cast<int>(FrameStatus::kCrossOriginBackground));
diff --git a/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.cc b/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.cc new file mode 100644 index 0000000..8a6c899e --- /dev/null +++ b/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.cc
@@ -0,0 +1,69 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.h" + +#if defined(OS_ANDROID) +#include "third_party/blink/public/platform/platform.h" +#endif + +namespace blink { + +QueueReportTimeSwapPromise::QueueReportTimeSwapPromise( + int source_frame_number, + DrainCallback drain_callback, + base::OnceClosure swap_callback, + scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner) + : source_frame_number_(source_frame_number), + drain_callback_(std::move(drain_callback)), + swap_callback_(std::move(swap_callback)), +#if defined(OS_ANDROID) + call_swap_on_activate_( + Platform::Current()->IsSynchronousCompositingEnabled()), +#endif + compositor_task_runner_(std::move(compositor_task_runner)) { +} + +QueueReportTimeSwapPromise::~QueueReportTimeSwapPromise() { + if (compositor_task_runner_ && (drain_callback_ || swap_callback_)) { + DCHECK(!compositor_task_runner_->BelongsToCurrentThread()); + compositor_task_runner_->PostTask( + FROM_HERE, + base::BindOnce([](DrainCallback, base::OnceClosure) {}, + std::move(drain_callback_), std::move(swap_callback_))); + } +} + +void QueueReportTimeSwapPromise::WillSwap( + viz::CompositorFrameMetadata* metadata) { + DCHECK_GT(metadata->frame_token, 0u); +} + +void QueueReportTimeSwapPromise::DidSwap() { + if (swap_callback_) + std::move(swap_callback_).Run(); +} + +cc::SwapPromise::DidNotSwapAction QueueReportTimeSwapPromise::DidNotSwap( + DidNotSwapReason reason) { + if (reason == cc::SwapPromise::SWAP_FAILS || + reason == cc::SwapPromise::COMMIT_NO_UPDATE) { + if (drain_callback_) + std::move(drain_callback_).Run(source_frame_number_); + if (swap_callback_) + std::move(swap_callback_).Run(); + } + return DidNotSwapAction::BREAK_PROMISE; +} + +void QueueReportTimeSwapPromise::DidActivate() { + if (drain_callback_) + std::move(drain_callback_).Run(source_frame_number_); +#if defined(OS_ANDROID) + if (call_swap_on_activate_ && swap_callback_) + std::move(swap_callback_).Run(); +#endif +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.h b/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.h new file mode 100644 index 0000000..a1de1aaf --- /dev/null +++ b/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.h
@@ -0,0 +1,52 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_COMPOSITING_QUEUE_REPORT_TIME_SWAP_PROMISE_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_COMPOSITING_QUEUE_REPORT_TIME_SWAP_PROMISE_H_ + +#include "base/memory/scoped_refptr.h" +#include "base/single_thread_task_runner.h" +#include "build/build_config.h" +#include "cc/trees/swap_promise.h" + +namespace blink { + +// This class invokes DrainCallback to drain queued callbacks for frame numbers +// lower or equal to |source_frame_number| when the commit results in a +// successful activation of the pending layer tree in swap promise. +// +// This class doesn't have the reporting callback of the swap time. +class QueueReportTimeSwapPromise : public cc::SwapPromise { + public: + using DrainCallback = base::OnceCallback<void(int)>; + QueueReportTimeSwapPromise( + int source_frame_number, + DrainCallback drain_callback, + base::OnceClosure swap_callback, + scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner); + ~QueueReportTimeSwapPromise() override; + QueueReportTimeSwapPromise(const QueueReportTimeSwapPromise&) = delete; + QueueReportTimeSwapPromise& operator=(const QueueReportTimeSwapPromise&) = + delete; + + void WillSwap(viz::CompositorFrameMetadata* metadata) override; + void DidSwap() override; + cc::SwapPromise::DidNotSwapAction DidNotSwap( + DidNotSwapReason reason) override; + void DidActivate() override; + int64_t TraceId() const override { return 0; } + + private: + int source_frame_number_; + DrainCallback drain_callback_; + base::OnceClosure swap_callback_; +#if defined(OS_ANDROID) + const bool call_swap_on_activate_; +#endif + scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_COMPOSITING_QUEUE_REPORT_TIME_SWAP_PROMISE_H_
diff --git a/third_party/blink/renderer/platform/widget/compositing/widget_compositor.cc b/third_party/blink/renderer/platform/widget/compositing/widget_compositor.cc new file mode 100644 index 0000000..88d33c7 --- /dev/null +++ b/third_party/blink/renderer/platform/widget/compositing/widget_compositor.cc
@@ -0,0 +1,126 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/widget/compositing/widget_compositor.h" + +#include "cc/trees/layer_tree_host.h" +#include "third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.h" +#include "third_party/blink/renderer/platform/widget/widget_base.h" + +namespace blink { + +WidgetCompositor::WidgetCompositor( + base::WeakPtr<WidgetBase> widget_base, + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, + mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) + : widget_base_(widget_base), + main_task_runner_(std::move(main_task_runner)), + compositor_task_runner_(std::move(compositor_task_runner)), + swap_queue_(std::make_unique<WidgetSwapQueue>()) { + if (!compositor_task_runner_) { + BindOnThread(std::move(receiver)); + } else { + compositor_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&WidgetCompositor::BindOnThread, + base::Unretained(this), std::move(receiver))); + } +} + +void WidgetCompositor::Shutdown() { + if (!compositor_task_runner_) { + ResetOnThread(); + } else { + compositor_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&WidgetCompositor::ResetOnThread, + scoped_refptr<WidgetCompositor>(this))); + } +} + +void WidgetCompositor::BindOnThread( + mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) { + DCHECK(CalledOnValidCompositorThread()); + receiver_.Bind(std::move(receiver), compositor_task_runner_); +} + +void WidgetCompositor::ResetOnThread() { + DCHECK(CalledOnValidCompositorThread()); + receiver_.reset(); +} + +void WidgetCompositor::VisualStateRequest(VisualStateRequestCallback callback) { + DCHECK(CalledOnValidCompositorThread()); + + auto drain_callback = + WTF::Bind(&WidgetCompositor::DrainQueue, base::RetainedRef(this)); + auto swap_callback = WTF::Bind(&WidgetCompositor::VisualStateResponse, + base::RetainedRef(this)); + if (!compositor_task_runner_) { + CreateQueueSwapPromise(std::move(drain_callback), std::move(swap_callback), + std::move(callback)); + } else { + main_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&WidgetCompositor::CreateQueueSwapPromise, + base::RetainedRef(this), std::move(drain_callback), + std::move(swap_callback), std::move(callback))); + } +} + +cc::LayerTreeHost* WidgetCompositor::LayerTreeHost() const { + return widget_base_->LayerTreeHost(); +} + +void WidgetCompositor::CreateQueueSwapPromise( + base::OnceCallback<void(int)> drain_callback, + base::OnceClosure swap_callback, + VisualStateRequestCallback callback) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + + if (!widget_base_) + return; + + bool first_message_for_frame = false; + int source_frame_number = LayerTreeHost()->SourceFrameNumber(); + swap_queue_->Queue(source_frame_number, std::move(callback), + &first_message_for_frame); + if (first_message_for_frame) { + LayerTreeHost()->QueueSwapPromise( + std::make_unique<QueueReportTimeSwapPromise>( + source_frame_number, std::move(drain_callback), + std::move(swap_callback), compositor_task_runner_)); + // Request a main frame if one is not already in progress. This might either + // A) request a commit ahead of time or B) request a commit which is not + // needed because there are not pending updates. If B) then the frame will + // be aborted early and the swap promises will be broken (see + // EarlyOut_NoUpdates). + LayerTreeHost()->SetNeedsAnimateIfNotInsideMainFrame(); + } else if (compositor_task_runner_) { + // Delete callbacks on the compositor thread. + compositor_task_runner_->PostTask( + FROM_HERE, + base::BindOnce([](base::OnceCallback<void(int)>, base::OnceClosure) {}, + std::move(drain_callback), std::move(swap_callback))); + } +} + +void WidgetCompositor::VisualStateResponse() { + DCHECK(CalledOnValidCompositorThread()); + Vector<VisualStateRequestCallback> callbacks; + swap_queue_->GetCallbacks(&callbacks); + for (auto& callback : callbacks) + std::move(callback).Run(); +} + +void WidgetCompositor::DrainQueue(int source_frame_number) { + DCHECK(CalledOnValidCompositorThread()); + swap_queue_->Drain(source_frame_number); +} + +bool WidgetCompositor::CalledOnValidCompositorThread() { + return !compositor_task_runner_ || + compositor_task_runner_->BelongsToCurrentThread(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/widget/compositing/widget_compositor.h b/third_party/blink/renderer/platform/widget/compositing/widget_compositor.h new file mode 100644 index 0000000..dd8832f --- /dev/null +++ b/third_party/blink/renderer/platform/widget/compositing/widget_compositor.h
@@ -0,0 +1,63 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_COMPOSITING_WIDGET_COMPOSITOR_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_COMPOSITING_WIDGET_COMPOSITOR_H_ + +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "third_party/blink/public/mojom/page/widget.mojom-blink.h" +#include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/widget/compositing/widget_swap_queue.h" + +namespace cc { +class LayerTreeHost; +} + +namespace blink { + +class WidgetBase; + +class PLATFORM_EXPORT WidgetCompositor + : public base::RefCountedThreadSafe<WidgetCompositor>, + public mojom::blink::WidgetCompositor { + public: + WidgetCompositor( + base::WeakPtr<WidgetBase> widget_base, + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, + mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver); + ~WidgetCompositor() override = default; + WidgetCompositor(const WidgetCompositor&) = delete; + WidgetCompositor& operator=(const WidgetCompositor&) = delete; + + void Shutdown(); + + // mojom::WidgetCompositor: + void VisualStateRequest(VisualStateRequestCallback callback) override; + + virtual cc::LayerTreeHost* LayerTreeHost() const; + + private: + void BindOnThread( + mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver); + void ResetOnThread(); + void CreateQueueSwapPromise(base::OnceCallback<void(int)> drain_callback, + base::OnceClosure swap_callback, + VisualStateRequestCallback callback); + void VisualStateResponse(); + void DrainQueue(int source_frame_number); + bool CalledOnValidCompositorThread(); + + // Note that |widget_base_| is safe to be accessed on the main thread. + base::WeakPtr<WidgetBase> widget_base_; + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; + mojo::Receiver<mojom::blink::WidgetCompositor> receiver_{this}; + std::unique_ptr<WidgetSwapQueue> swap_queue_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_COMPOSITING_WIDGET_COMPOSITOR_H_
diff --git a/third_party/blink/renderer/platform/widget/compositing/widget_compositor_unittest.cc b/third_party/blink/renderer/platform/widget/compositing/widget_compositor_unittest.cc new file mode 100644 index 0000000..0658962 --- /dev/null +++ b/third_party/blink/renderer/platform/widget/compositing/widget_compositor_unittest.cc
@@ -0,0 +1,103 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/widget/compositing/widget_compositor.h" + +#include "base/test/task_environment.h" +#include "cc/test/layer_tree_test.h" +#include "cc/trees/layer_tree_host.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "third_party/blink/renderer/platform/widget/widget_base.h" +#include "third_party/blink/renderer/platform/widget/widget_base_client.h" + +namespace blink { + +class StubWidgetBaseClient : public WidgetBaseClient { + public: + void BeginMainFrame(base::TimeTicks) override {} + void RecordTimeToFirstActivePaint(base::TimeDelta) override {} + void UpdateLifecycle(WebLifecycleUpdate, DocumentUpdateReason) override {} + void RequestNewLayerTreeFrameSink(LayerTreeFrameSinkCallback) override {} + WebInputEventResult DispatchBufferedTouchEvents() override { + return WebInputEventResult::kNotHandled; + } + WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override { + return WebInputEventResult::kNotHandled; + } + bool SupportsBufferedTouchEvents() override { return false; } + bool WillHandleGestureEvent(const WebGestureEvent&) override { return false; } + bool WillHandleMouseEvent(const WebMouseEvent&) override { return false; } + void ObserveGestureEventAndResult(const WebGestureEvent&, + const gfx::Vector2dF&, + const cc::OverscrollBehavior&, + bool) override {} + void FocusChanged(bool) override {} + void UpdateVisualProperties( + const VisualProperties& visual_properties) override {} + void UpdateScreenRects(const gfx::Rect& widget_screen_rect, + const gfx::Rect& window_screen_rect) override {} +}; + +class FakeWidgetCompositor : public WidgetCompositor { + public: + FakeWidgetCompositor( + cc::LayerTreeHost* layer_tree_host, + base::WeakPtr<WidgetBase> widget_base, + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, + mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) + : WidgetCompositor(widget_base, + std::move(main_task_runner), + std::move(compositor_task_runner), + std::move(receiver)), + layer_tree_host_(layer_tree_host) {} + + cc::LayerTreeHost* LayerTreeHost() const override { return layer_tree_host_; } + + cc::LayerTreeHost* layer_tree_host_; +}; + +class WidgetCompositorTest : public cc::LayerTreeTest { + public: + using CompositorMode = cc::CompositorMode; + + void BeginTest() override { + widget_base_ = std::make_unique<WidgetBase>( + &client_, + blink::CrossVariantMojoAssociatedRemote< + blink::mojom::WidgetHostInterfaceBase>(), + blink::CrossVariantMojoAssociatedReceiver< + blink::mojom::WidgetInterfaceBase>()); + + widget_compositor_ = base::MakeRefCounted<FakeWidgetCompositor>( + layer_tree_host(), widget_base_->GetWeakPtr(), + layer_tree_host()->GetTaskRunnerProvider()->MainThreadTaskRunner(), + layer_tree_host()->GetTaskRunnerProvider()->ImplThreadTaskRunner(), + remote_.BindNewPipeAndPassReceiver()); + + remote_->VisualStateRequest(base::BindOnce( + &WidgetCompositorTest::VisualStateResponse, base::Unretained(this))); + PostSetNeedsCommitToMainThread(); + } + + void VisualStateResponse() { + is_callback_run_ = true; + widget_compositor_->Shutdown(); + widget_compositor_ = nullptr; + EndTest(); + } + + void AfterTest() override { EXPECT_TRUE(is_callback_run_); } + + mojo::Remote<mojom::blink::WidgetCompositor> remote_; + StubWidgetBaseClient client_; + std::unique_ptr<WidgetBase> widget_base_; + scoped_refptr<FakeWidgetCompositor> widget_compositor_; + bool is_callback_run_ = false; + base::test::SingleThreadTaskEnvironment task_environment_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(WidgetCompositorTest); + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/widget/compositing/widget_swap_queue.cc b/third_party/blink/renderer/platform/widget/compositing/widget_swap_queue.cc new file mode 100644 index 0000000..bcb37940 --- /dev/null +++ b/third_party/blink/renderer/platform/widget/compositing/widget_swap_queue.cc
@@ -0,0 +1,37 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/widget/compositing/widget_swap_queue.h" + +namespace blink { + +void WidgetSwapQueue::Queue(int source_frame_number, + VisualStateRequestCallback callback, + bool* is_first) { + base::AutoLock lock(lock_); + if (is_first) + *is_first = (queue_.count(source_frame_number) == 0); + + queue_[source_frame_number].push_back(std::move(callback)); +} + +void WidgetSwapQueue::Drain(int source_frame_number) { + base::AutoLock lock(lock_); + auto end = queue_.upper_bound(source_frame_number); + for (auto i = queue_.begin(); i != end; i++) { + DCHECK(i->first <= source_frame_number); + std::move(i->second.begin(), i->second.end(), + std::back_inserter(next_callbacks_)); + } + queue_.erase(queue_.begin(), end); +} + +void WidgetSwapQueue::GetCallbacks( + Vector<VisualStateRequestCallback>* callbacks) { + std::move(next_callbacks_.begin(), next_callbacks_.end(), + std::back_inserter(*callbacks)); + next_callbacks_.clear(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/widget/compositing/widget_swap_queue.h b/third_party/blink/renderer/platform/widget/compositing/widget_swap_queue.h new file mode 100644 index 0000000..8f73484a --- /dev/null +++ b/third_party/blink/renderer/platform/widget/compositing/widget_swap_queue.h
@@ -0,0 +1,61 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_COMPOSITING_WIDGET_SWAP_QUEUE_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_COMPOSITING_WIDGET_SWAP_QUEUE_H_ + +#include <map> +#include "base/synchronization/lock.h" +#include "third_party/blink/public/mojom/page/widget.mojom-blink.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" + +namespace blink { + +// Queue used to keep track of which VisualStateRequestCallback should be +// invoked after a particular compositor frame swap. The callbacks are +// guaranteed to be processed after the frame is processed, but there is no +// guarantee that nothing else happens between processing the frame and +// processing the callback. +class WidgetSwapQueue { + public: + using VisualStateRequestCallback = + mojom::blink::WidgetCompositor::VisualStateRequestCallback; + WidgetSwapQueue() = default; + ~WidgetSwapQueue() = default; + WidgetSwapQueue(const WidgetSwapQueue&) = delete; + WidgetSwapQueue& operator=(const WidgetSwapQueue&) = delete; + + // Returns true if there are no callback in the queue. + bool Empty() const { return queue_.empty(); } + + // Queues the callback to be returned on a matching Drain call. + // + // |source_frame_number| - frame number to queue |callback| for. + // |callback| - callback to queue. The method takes ownership of |callback|. + // |is_first| - output parameter. Set to true if this was the first message + // enqueued for the given source_frame_number. + void Queue(int source_frame_number, + VisualStateRequestCallback callback, + bool* is_first); + + // The method will append cllbacks queued for frame numbers lower or equal to + // |source_frame_number| + // + // |source_frame_number| - swapped frame number. + void Drain(int source_frame_number); + + // The method will clear |next_callbacks_| after copying to |callbacks|. + // + // |callbacks| - vector to store callbacks. + void GetCallbacks(Vector<VisualStateRequestCallback>* callbacks); + + private: + base::Lock lock_; + std::map<int, Vector<VisualStateRequestCallback>> queue_; + Vector<VisualStateRequestCallback> next_callbacks_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_COMPOSITING_WIDGET_SWAP_QUEUE_H_
diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc index e82d3049..7ac1a8f 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.cc +++ b/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -24,6 +24,7 @@ #include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.h" #include "third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h" +#include "third_party/blink/renderer/platform/widget/compositing/widget_compositor.h" #include "third_party/blink/renderer/platform/widget/frame_widget.h" #include "third_party/blink/renderer/platform/widget/input/ime_event_guard.h" #include "third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h" @@ -189,6 +190,11 @@ FROM_HERE, base::BindOnce([](scoped_refptr<WidgetInputHandlerManager> manager) {}, std::move(widget_input_handler_manager_))); + + if (widget_compositor_) { + widget_compositor_->Shutdown(); + widget_compositor_ = nullptr; + } } cc::LayerTreeHost* WidgetBase::LayerTreeHost() const { @@ -289,6 +295,15 @@ visual_properties.screen_info.device_scale_factor)); } + // Inform the rendering thread of the color space indicating the presence of + // HDR capabilities. The HDR bit happens to be globally true/false for all + // browser windows (on Windows OS) and thus would be the same for all + // RenderWidgets, so clobbering each other works out since only the HDR bit is + // used. See https://crbug.com/803451 and + // https://chromium-review.googlesource.com/c/chromium/src/+/852912/15#message-68bbd3e25c3b421a79cd028b2533629527d21fee + Platform::Current()->SetRenderingColorSpace( + visual_properties.screen_info.color_space); + LayerTreeHost()->SetBrowserControlsParams( visual_properties.browser_controls_params); @@ -654,6 +669,18 @@ client_->FocusChanged(enable); } +void WidgetBase::BindWidgetCompositor( + mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) { + if (widget_compositor_) + widget_compositor_->Shutdown(); + + widget_compositor_ = base::MakeRefCounted<WidgetCompositor>( + weak_ptr_factory_.GetWeakPtr(), + LayerTreeHost()->GetTaskRunnerProvider()->MainThreadTaskRunner(), + LayerTreeHost()->GetTaskRunnerProvider()->ImplThreadTaskRunner(), + std::move(receiver)); +} + void WidgetBase::UpdateCompositionInfo(bool immediate_request) { if (!monitor_composition_info_ && !immediate_request) return; // Do not calculate composition info if not requested.
diff --git a/third_party/blink/renderer/platform/widget/widget_base.h b/third_party/blink/renderer/platform/widget/widget_base.h index 2d9e2e8..f2820ec 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.h +++ b/third_party/blink/renderer/platform/widget/widget_base.h
@@ -39,6 +39,7 @@ class LayerTreeView; class WidgetBaseClient; class WidgetInputHandlerManager; +class WidgetCompositor; namespace scheduler { class WebRenderWidgetSchedulingState; @@ -215,6 +216,13 @@ CrossVariantMojoRemote< mojom::blink::PointerLockContextInterfaceBase>)> callback); + void BindWidgetCompositor( + mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver); + + base::WeakPtr<WidgetBase> GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); + } + private: bool CanComposeInline(); void UpdateTextInputStateInternal(bool show_virtual_keyboard, @@ -242,6 +250,7 @@ base::TimeTicks was_shown_time_ = base::TimeTicks::Now(); bool has_focus_ = false; WidgetBaseInputHandler input_handler_{this}; + scoped_refptr<WidgetCompositor> widget_compositor_; // Stores the current selection bounds. gfx::Rect selection_focus_rect_;
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 483b66c..8f48075 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -740,6 +740,96 @@ crbug.com/1003506 external/wpt/css/css-flexbox/percentage-heights-007.html [ Failure ] crbug.com/1081802 external/wpt/css/css-flexbox/overflow-area-001.html [ Failure ] crbug.com/1081802 external/wpt/css/css-flexbox/overflow-area-002.html [ Failure ] +crbug.com/807497 external/wpt/css/css-flexbox/anonymous-flex-item-005.html [ Failure ] +crbug.com/1111708 external/wpt/css/css-flexbox/flexbox_justifycontent-center-overflow.html [ Failure ] +crbug.com/1111710 external/wpt/css/css-flexbox/getcomputedstyle/flexbox_computedstyle_flex-basis-0percent.html [ Failure ] +crbug.com/1111710 external/wpt/css/css-flexbox/getcomputedstyle/flexbox_computedstyle_flex-shorthand-number.html [ Failure ] + +# These testcases are incorrect, mark them as failing until they're fixed in the testsuite. +# https://lists.w3.org/Archives/Public/www-style/2016Jan/0275.html +# https://lists.w3.org/Archives/Public/www-style/2016Jan/0276.html +crbug.com/249112 external/wpt/css/css-flexbox/flex-minimum-height-flex-items-005.xht [ Failure ] +crbug.com/249112 external/wpt/css/css-flexbox/flex-minimum-height-flex-items-007.xht [ Failure ] +crbug.com/249112 external/wpt/css/css-flexbox/flex-minimum-width-flex-items-005.xht [ Failure ] +crbug.com/249112 external/wpt/css/css-flexbox/flex-minimum-width-flex-items-007.xht [ Failure ] + +# Not implemented yet +crbug.com/336604 external/wpt/css/css-flexbox/flexbox_visibility-collapse-line-wrapping.html [ Failure ] +crbug.com/336604 external/wpt/css/css-flexbox/flexbox_visibility-collapse.html [ Failure ] + +# These require justify-content:right and align-content:end +crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-horiz-001a.xhtml [ Failure ] +crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-horiz-001b.xhtml [ Failure ] +crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-001a.xhtml [ Failure ] +crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-001b.xhtml [ Failure ] +crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-002.xhtml [ Failure ] +crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-horiz-002.xhtml [ Failure ] +crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-001a.xhtml [ Failure ] +crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-001b.xhtml [ Failure ] +crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-003.xhtml [ Failure ] +crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-005.xhtml [ Failure ] +crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-006.xhtml [ Failure ] + +# We don't support requesting flex line breaks and it is not clear that we should. +# See https://lists.w3.org/Archives/Public/www-style/2015May/0065.html +crbug.com/473481 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-horiz-001a.html [ Failure ] +crbug.com/473481 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-horiz-001b.html [ Failure ] +crbug.com/473481 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-vert-001a.html [ Failure ] +crbug.com/473481 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-vert-001b.html [ Failure ] + +# We don't currently support visibility: collapse in flexbox +crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-baseline-001.html [ Failure ] +crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-001.html [ Failure ] +crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-002.html [ Failure ] +crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-003.html [ Failure ] + +# We don't correctly implement aspect ratios for images in Flexbox +crbug.com/531199 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001.html [ Failure ] +crbug.com/531199 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002.html [ Failure ] +crbug.com/531199 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005.html [ Failure ] +crbug.com/531199 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006.html [ Failure ] +crbug.com/1111128 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002b.html [ Failure ] + +# These tests are incorrect, as Firefox has a bug in this area. https://bugzilla.mozilla.org/show_bug.cgi?id=1136312 +crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002a.html [ Failure ] +crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002c.html [ Failure ] +crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-width-auto-002a.html [ Failure ] +crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-width-auto-002c.html [ Failure ] + +# We paint in an incorrect order when layers are present. Blocked on composite-after-paint. +crbug.com/370604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-paint-ordering-002.xhtml [ Failure ] + +# Untriaged flex failures +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-wmvert-001.xhtml [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-001a.xhtml [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-001b.xhtml [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-006.xhtml [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-007.xhtml [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-008.xhtml [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-vert-002.xhtml [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-vert-rtl-005.xhtml [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-align-self-baseline-vert-001.html [ Failure Pass ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-vert-001a.html [ Failure Pass ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001a.html [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001b.html [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-002a.html [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-002b.html [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-003a.html [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-004a.html [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001v.html [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002v.html [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005v.html [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006v.html [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007.html [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007v.html [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-vert-006.xhtml [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-wmvert-001.xhtml [ Failure ] +crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-safe-overflow-position-001.html [ Failure ] +crbug.com/715718 [ Win ] external/wpt/css/css-flexbox/align-items-004.htm [ Failure Pass ] +crbug.com/715718 [ Win ] external/wpt/css/css-flexbox/flex-minimum-width-flex-items-001.xht [ Failure Pass ] +crbug.com/715718 [ Win ] external/wpt/css/css-flexbox/flex-minimum-width-flex-items-003.xht [ Failure Pass ] +crbug.com/715718 [ Win ] external/wpt/css/css-flexbox/flexbox_flex-natural-mixed-basis-auto.html [ Failure Pass ] +crbug.com/898186 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003v.html [ Pass Failure ] # [css-lists] crbug.com/1066577 external/wpt/css/css-lists/li-value-reversed-005.html [ Failure ] @@ -1969,71 +2059,11 @@ # Chrome touch-action computation ignores div transforms. crbug.com/715148 external/wpt/pointerevents/pointerevent_touch-action-rotated-divs_touch-manual.html [ Skip ] -# These testcases are incorrect, mark them as failing until they're fixed in the testsuite. -# https://lists.w3.org/Archives/Public/www-style/2016Jan/0275.html -# https://lists.w3.org/Archives/Public/www-style/2016Jan/0276.html -crbug.com/249112 external/wpt/css/css-flexbox/flex-minimum-height-flex-items-005.xht [ Failure ] -crbug.com/249112 external/wpt/css/css-flexbox/flex-minimum-height-flex-items-007.xht [ Failure ] -crbug.com/249112 external/wpt/css/css-flexbox/flex-minimum-width-flex-items-005.xht [ Failure ] -crbug.com/249112 external/wpt/css/css-flexbox/flex-minimum-width-flex-items-007.xht [ Failure ] - -# Not implemented yet -crbug.com/336604 external/wpt/css/css-flexbox/flexbox_visibility-collapse-line-wrapping.html [ Failure ] -crbug.com/336604 external/wpt/css/css-flexbox/flexbox_visibility-collapse.html [ Failure ] - -crbug.com/807497 external/wpt/css/css-flexbox/anonymous-flex-item-005.html [ Failure ] -crbug.com/467127 external/wpt/css/css-flexbox/flexbox_justifycontent-center-overflow.html [ Failure ] -crbug.com/467127 external/wpt/css/css-flexbox/getcomputedstyle/flexbox_computedstyle_flex-basis-0percent.html [ Failure ] -crbug.com/467127 external/wpt/css/css-flexbox/getcomputedstyle/flexbox_computedstyle_flex-shorthand-number.html [ Failure ] - -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-horiz-001a.xhtml [ Failure ] -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-horiz-001b.xhtml [ Failure ] -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-001a.xhtml [ Failure ] -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-001b.xhtml [ Failure ] -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-001a.xhtml [ Failure ] -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-001b.xhtml [ Failure ] -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-003.xhtml [ Failure ] -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-005.xhtml [ Failure ] -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-010.html [ Failure Pass ] -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-012.html [ Failure Pass ] -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-013.html [ Failure Pass ] -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-014.html [ Failure Pass ] -crbug.com/467127 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-015.html [ Failure Pass ] - crbug.com/654999 [ Win ] fast/forms/color/color-suggestion-picker-appearance-zoom200.html [ Pass Failure ] crbug.com/654999 [ Linux ] fast/forms/color/color-suggestion-picker-appearance-zoom200.html [ Pass Failure ] crbug.com/658304 [ Win ] fast/forms/select/input-select-after-resize.html [ Crash Timeout Pass Failure ] -# We don't support requesting flex line breaks and it is not clear that we should. -# See https://lists.w3.org/Archives/Public/www-style/2015May/0065.html -crbug.com/473481 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-horiz-001a.html [ Failure ] -crbug.com/473481 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-horiz-001b.html [ Failure ] -crbug.com/473481 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-vert-001a.html [ Failure ] -crbug.com/473481 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-vert-001b.html [ Failure ] - -# We don't currently support visibility: collapse in flexbox -crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-baseline-001.html [ Failure ] -crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-001.html [ Failure ] -crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-002.html [ Failure ] -crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-003.html [ Failure ] - -# We don't correctly implement aspect ratios for images in Flexbox -crbug.com/531199 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001.html [ Failure ] -crbug.com/531199 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002.html [ Failure ] -crbug.com/531199 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005.html [ Failure ] -crbug.com/531199 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006.html [ Failure ] -crbug.com/531199 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002b.html [ Failure ] - -# These tests are incorrect, as Firefox has a bug in this area. https://bugzilla.mozilla.org/show_bug.cgi?id=1136312 -crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002a.html [ Failure ] -crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002c.html [ Failure ] -crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-width-auto-002a.html [ Failure ] -crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-width-auto-002c.html [ Failure ] - -# We paint in an incorrect order when layers are present -crbug.com/370604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-paint-ordering-002.xhtml [ Failure ] - crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-break-inside-001a.html [ Failure ] crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-001.html [ Failure ] crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-002.html [ Failure ] @@ -2190,11 +2220,6 @@ crbug.com/713587 external/wpt/css/css-ui/caret-color-006.html [ Skip ] -# Automatically-added expectations for CSS tests which are temporarily -# commented-out while the test directory is disabled (see top of file). -#crbug.com/626703 [ Win ] external/wpt/css/css-flexbox/flex-minimum-width-flex-items-001.xht [ Failure ] -#crbug.com/626703 [ Win ] external/wpt/css/css-flexbox/flex-minimum-width-flex-items-003.xht [ Failure ] -#crbug.com/626703 [ Win ] external/wpt/css/css-flexbox/flexbox_flex-natural-mixed-basis-auto.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-013.xht [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/sizing-orthog-vlr-in-htb-008.xht [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/sizing-orthog-vlr-in-htb-020.xht [ Failure ] @@ -2657,6 +2682,9 @@ crbug.com/27659 external/wpt/css/css-ruby/ruby-whitespace-001.html [ Failure ] crbug.com/27659 external/wpt/css/css-ruby/ruby-whitespace-002.html [ Failure ] +# WebRTC: Perfect Negotiation is flaky in Unified Plan. +# This will be fixed when crbug.com/1060083 is fixed. +crbug.com/1060083 external/wpt/webrtc/RTCPeerConnection-perfect-negotiation.https.html [ Pass Failure Timeout ] # WebRTC: Perfect Negotiation times out in Plan B. This is expected. crbug.com/980872 virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-perfect-negotiation.https.html [ Timeout ] @@ -2954,9 +2982,6 @@ crbug.com/626703 external/wpt/webaudio/the-audio-api/processing-model/feedback-delay-time.html [ Failure ] crbug.com/626703 external/wpt/webaudio/the-audio-api/processing-model/delay-time-clamping.html [ Failure ] crbug.com/626703 external/wpt/webaudio/the-audio-api/processing-model/cycle-without-delay.html [ Failure ] -crbug.com/626703 [ Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-008.xhtml [ Failure ] -crbug.com/626703 [ Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-008.xhtml [ Failure ] -crbug.com/626703 [ Win ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-008.xhtml [ Failure ] crbug.com/626703 [ Win7 ] external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch.html [ Timeout ] crbug.com/626703 [ Win7 ] external/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch.html [ Timeout ] crbug.com/626703 [ Win ] external/wpt/css/css-text/word-break/word-break-keep-all-008.html [ Failure ] @@ -3127,11 +3152,9 @@ crbug.com/626703 external/wpt/html/semantics/forms/the-fieldset-element/accessibility/legend-display-none-manual.html [ Skip ] crbug.com/626703 external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html [ Timeout ] crbug.com/626703 external/wpt/webrtc/RTCPeerConnection-remote-track-mute.https.html [ Timeout ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007v.html [ Failure ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-cyclic-invalid.html [ Pass Failure Timeout ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-alphabetic-invalid.html [ Pass Failure Timeout ] crbug.com/626703 [ Mac10.11 ] external/wpt/mimesniff/mime-types/parsing.any.html [ Timeout ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007.html [ Failure ] crbug.com/626703 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/navigation.sub.html?encoding=windows-1252 [ Timeout ] crbug.com/626703 external/wpt/css/css-values/ch-unit-011.html [ Failure ] crbug.com/626703 [ Mac ] external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-width-height.html [ Crash Timeout ] @@ -3262,15 +3285,7 @@ crbug.com/626703 external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/tasks.window.html [ Timeout ] crbug.com/875411 external/wpt/svg/text/reftests/text-complex-002.svg [ Failure ] crbug.com/875411 external/wpt/svg/text/reftests/text-shape-inside-001.svg [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-vert-002.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-wmvert-001.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-vert-006.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-vert-rtl-005.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-wmvert-001.xhtml [ Failure ] crbug.com/875411 external/wpt/svg/text/reftests/text-complex-001.svg [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-002.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-006.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-horiz-002.xhtml [ Failure ] crbug.com/875411 external/wpt/svg/text/reftests/text-shape-inside-002.svg [ Failure ] crbug.com/626703 external/wpt/speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html [ Failure ] crbug.com/366553 external/wpt/svg/text/reftests/text-inline-size-007.svg [ Failure ] @@ -3294,7 +3309,6 @@ crbug.com/626703 external/wpt/css/css-lists/content-property/marker-text-matches-square.html [ Failure ] crbug.com/626703 external/wpt/svg/linking/reftests/use-descendant-combinator-003.html [ Failure ] crbug.com/626703 external/wpt/css/css-lists/content-property/marker-text-matches-circle.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-safe-overflow-position-001.html [ Failure ] crbug.com/626703 external/wpt/content-security-policy/securitypolicyviolation/inside-service-worker.https.html [ Timeout ] crbug.com/626703 external/wpt/content-security-policy/securitypolicyviolation/inside-shared-worker.html [ Timeout ] crbug.com/626703 external/wpt/content-security-policy/securitypolicyviolation/inside-dedicated-worker.html [ Timeout ] @@ -3390,17 +3404,11 @@ crbug.com/626703 [ IOS ] external/wpt/websockets/Create-Secure-extensions-empty.any.html [ Timeout ] crbug.com/626703 [ IOS ] external/wpt/websockets/Create-Secure-extensions-empty.any.worker.html [ Timeout ] crbug.com/626703 external/wpt/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html [ Timeout ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-003a.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-004a.html [ Failure ] crbug.com/626703 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-008.html [ Failure ] crbug.com/626703 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-006.html [ Failure ] crbug.com/626703 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-005.html [ Failure ] crbug.com/626703 external/wpt/css/css-fonts/font-variant-descriptor-01.html [ Failure ] crbug.com/626703 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-007.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001a.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-002a.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-002b.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001b.html [ Failure ] crbug.com/626703 [ Win7 ] external/wpt/css/css-fonts/variations/font-opentype-collections.html [ Timeout ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-numeric.html [ Failure ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/descriptor-suffix-invalid.html [ Failure ] @@ -3429,14 +3437,10 @@ crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/descriptor-symbols.html [ Failure ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-extends-invalid.html [ Failure ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/redefine-builtin.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006v.html [ Failure ] crbug.com/626703 external/wpt/css/css-fonts/font-feature-resolution-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-fonts/font-feature-resolution-002.html [ Failure ] crbug.com/626703 external/wpt/css/css-fonts/font-variant-05.xht [ Failure ] crbug.com/626703 external/wpt/css/css-fonts/font-variant-06.xht [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001v.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002v.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005v.html [ Failure ] crbug.com/626703 external/wpt/css/mediaqueries/viewport-script-dynamic.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/available-size-014.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/available-size-013.html [ Failure ] @@ -3519,12 +3523,6 @@ crbug.com/626703 external/wpt/css/css-fonts/font-variant-position.html [ Failure ] crbug.com/626703 external/wpt/css/css-tables/floats/floats-wrap-bfc-006b.xht [ Failure ] crbug.com/626703 external/wpt/css/css-tables/floats/floats-wrap-bfc-006c.xht [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-001a.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-001b.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-006.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-007.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-align-self-baseline-vert-001.html [ Failure Pass ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-vert-001a.html [ Failure Pass ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/logical-physical-mapping-001.html [ Failure ] crbug.com/626703 external/wpt/encoding/eof-utf-8-three.html [ Failure ] crbug.com/626703 external/wpt/encoding/eof-utf-8-two.html [ Failure ] @@ -4871,10 +4869,6 @@ crbug.com/875003 [ Win ] editing/caret/caret-is-hidden-when-no-focus.html [ Pass Failure ] crbug.com/715718 external/wpt/media-source/mediasource-remove.html [ Failure Pass ] -crbug.com/715718 [ Win ] external/wpt/css/css-flexbox/align-items-004.htm [ Failure Pass ] -crbug.com/715718 [ Win ] external/wpt/css/css-flexbox/flex-minimum-width-flex-items-001.xht [ Failure Pass ] -crbug.com/715718 [ Win ] external/wpt/css/css-flexbox/flex-minimum-width-flex-items-003.xht [ Failure Pass ] -crbug.com/715718 [ Win ] external/wpt/css/css-flexbox/flexbox_flex-natural-mixed-basis-auto.html [ Failure Pass ] # New failure when importing css-variables: crbug.com/791529 external/wpt/css/css-variables/variable-transitions-from-no-value.html [ Skip ] @@ -5466,8 +5460,6 @@ crbug.com/874162 [ Mac ] fast/events/middleClickAutoscroll-nested-divs.html [ Skip ] crbug.com/874162 [ Mac ] fast/events/selection-autoscroll-borderbelt.html [ Skip ] -crbug.com/898186 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003v.html [ Pass Failure ] - # Sheriff 2018-09-10 crbug.com/881207 fast/js/regress/splice-to-remove.html [ Timeout Pass ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 6e34349b..f726331f 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -79300,6 +79300,32 @@ {} ] ], + "position-relative-006.html": [ + "545edc990b9ff89ddcb5bbf09dc0b8c8d8238888", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "position-relative-007.html": [ + "2425514f308afebd3ce32ae6e04c57077428c05e", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "position-relative-table-tbody-left-absolute-child.html": [ "98e759a8c0a83817b3d691503e807ed5ed549936", [ @@ -354300,6 +354326,13 @@ {} ] ], + "intersection-ratio-ib-split.html": [ + "905ea436fd6a85fff228f5676742b89ab001a3b7", + [ + null, + {} + ] + ], "isIntersecting-change-events.html": [ "99bc65bd60afee82f2ddd6b5380437d94811e30d", [
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_putall.tentative.any.js b/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_putall.tentative.any.js index 8bdc765..a312d71 100644 --- a/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_putall.tentative.any.js +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_putall.tentative.any.js
@@ -3,23 +3,24 @@ promise_test(async testCase => { const db = await createDatabase(testCase, db => { const store = createBooksStore(testCase, db); - let values = [ - {isbn: 'one', title: 'title1'}, - {isbn: 'two', title: 'title2'}, - {isbn: 'three', title: 'title3'} - ]; - const putAllRequests = store.putAll(values); - putAllRequests.forEach(async request => { - await promiseForRequest(testCase, request); - }); }); - - const txn = db.transaction(['books'], 'readonly'); + const txn = db.transaction(['books'], 'readwrite'); const objectStore = txn.objectStore('books'); - const getRequest1 = objectStore.get('one'); - const getRequest2 = objectStore.get('two'); - const getRequest3 = objectStore.get('three'); + let values = [ + {isbn: 'one', title: 'title1'}, + {isbn: 'two', title: 'title2'}, + {isbn: 'three', title: 'title3'} + ]; + let putAllRequest = objectStore.putAll(values); + await promiseForRequest(testCase, putAllRequest); await promiseForTransaction(testCase, txn); + + const txn2 = db.transaction(['books'], 'readonly'); + const objectStore2 = txn2.objectStore('books'); + const getRequest1 = objectStore2.get('one'); + const getRequest2 = objectStore2.get('two'); + const getRequest3 = objectStore2.get('three'); + await promiseForTransaction(testCase, txn2); assert_array_equals( [getRequest1.result.title, getRequest2.result.title, @@ -27,4 +28,4 @@ ['title1', 'title2', 'title3'], 'All three retrieved titles should match those that were put.'); db.close(); -}, 'Data can be successfully inputted into an object store using putAll.'); \ No newline at end of file +}, 'Data can be successfully inputted into an object store using putAll.');
diff --git a/third_party/blink/web_tests/external/wpt/intersection-observer/intersection-ratio-ib-split.html b/third_party/blink/web_tests/external/wpt/intersection-observer/intersection-ratio-ib-split.html new file mode 100644 index 0000000..905ea436 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/intersection-observer/intersection-ratio-ib-split.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<meta name="viewport" content="width=device-width,initial-scale=1"> +<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<link rel="help" href="https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-intersectionratio"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1581876"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + block { + display: block; + width: 50vw; + height: 50vh; + background: green; + } +</style> +<inline> + <block></block> +</inline> +<script> +promise_test(async function() { + for (let element of document.querySelectorAll("inline, block")) { + let entries = await new Promise(resolve => { + new IntersectionObserver(resolve).observe(element); + }); + assert_equals(entries.length, 1, element.nodeName + ": Should get an entry"); + assert_true(entries[0].isIntersecting, element.nodeName + ": Should be intersecting"); + assert_equals(entries[0].intersectionRatio, 1, element.nodeName + ": Should be fully intersecting"); + } +}, "IntersectionObserver on an IB split gets the right intersection ratio"); +</script>
diff --git a/third_party/blink/web_tests/fast/forms/calendar-picker/calendar-picker-isDayOutsideOfRange.html b/third_party/blink/web_tests/fast/forms/calendar-picker/calendar-picker-isDayOutsideOfRange.html new file mode 100644 index 0000000..c1f9445 --- /dev/null +++ b/third_party/blink/web_tests/fast/forms/calendar-picker/calendar-picker-isDayOutsideOfRange.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../forms/resources/picker-common.js"></script> + +<input type=date id=dateElement> + +<script> +promise_test(async () => { + await openPickerWithPromise(dateElement); + const {Month, Day, isDayOutsideOfRange} = popupWindow; + + assert_true(isDayOutsideOfRange( + /*day=*/new Day(1, 1, 1), + /*minDay=*/new Day(2, 1, 1), + /*maxDay=*/new Day(3, 1, 1)), + 'day.year < min < max: day is outside of range'); + assert_false(isDayOutsideOfRange( + /*day=*/new Day(2, 9, 9), + /*minDay=*/new Day(1, 1, 1), + /*maxDay=*/new Day(3, 1, 1)), + 'min < day.year < max: day is within range'); + assert_true(isDayOutsideOfRange( + /*day=*/new Day(3, 1, 1), + /*minDay=*/new Day(1, 1, 1), + /*maxDay=*/new Day(2, 1, 1)), + 'min < max < day.year: day is outside of range'); + + assert_true(isDayOutsideOfRange( + /*day=*/new Day(1, 1, 1), + /*minDay=*/new Day(1, 2, 1), + /*maxDay=*/new Day(1, 3, 1)), + 'day.month < min < max: day is outside of range'); + assert_false(isDayOutsideOfRange( + /*day=*/new Day(1, 2, 9), + /*minDay=*/new Day(1, 1, 1), + /*maxDay=*/new Day(1, 3, 1)), + 'min < day.month < max: day is within range'); + assert_true(isDayOutsideOfRange( + /*day=*/new Day(1, 3, 1), + /*minDay=*/new Day(1, 1, 1), + /*maxDay=*/new Day(1, 2, 1)), + 'min < max < day.month: day is outside of range'); + + assert_true(isDayOutsideOfRange( + /*day=*/new Day(1, 1, 1), + /*minDay=*/new Day(1, 1, 2), + /*maxDay=*/new Day(1, 1, 3)), + 'day.date < min < max: day is outside of range'); + assert_false(isDayOutsideOfRange( + /*day=*/new Day(1, 1, 2), + /*minDay=*/new Day(1, 1, 1), + /*maxDay=*/new Day(1, 1, 3)), + 'min < day.date < max: day is within range'); + assert_true(isDayOutsideOfRange( + /*day=*/new Day(1, 1, 3), + /*minDay=*/new Day(1, 1, 1), + /*maxDay=*/new Day(1, 1, 2)), + 'min < max < day.date: day is outside of range'); + +}, `Tests behavior of the date picker's internal function isTodayOutsideOfRange.`); +</script>
diff --git a/third_party/blink/web_tests/fast/forms/calendar-picker/calendar-picker-isWeekOutsideOfRange.html b/third_party/blink/web_tests/fast/forms/calendar-picker/calendar-picker-isWeekOutsideOfRange.html new file mode 100644 index 0000000..b3b25b7e --- /dev/null +++ b/third_party/blink/web_tests/fast/forms/calendar-picker/calendar-picker-isWeekOutsideOfRange.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../forms/resources/picker-common.js"></script> + +<input type=date id=dateElement> + +<script> +promise_test(async () => { + await openPickerWithPromise(dateElement); + const {Month, Day, Week, isWeekOutsideOfRange} = popupWindow; + + assert_true(isWeekOutsideOfRange( + /*week=*/new Week(1, 1), + /*minWeek=*/new Week(2, 1), + /*maxWeek=*/new Week(3, 1)), + 'week.year < min < max: week is outside of range'); + assert_false(isWeekOutsideOfRange( + /*week=*/new Week(2, 9), + /*minWeek=*/new Week(1, 1), + /*maxWeek=*/new Week(3, 1)), + 'min < week.year < max: week is within range'); + assert_true(isWeekOutsideOfRange( + /*week=*/new Week(3, 1), + /*minWeek=*/new Week(1, 1), + /*maxWeek=*/new Week(2, 1)), + 'min < max < week.year: week is outside of range'); + + assert_true(isWeekOutsideOfRange( + /*week=*/new Week(1, 1), + /*minWeek=*/new Week(1, 2), + /*maxWeek=*/new Week(1, 3)), + 'week.week < min < max: week is outside of range'); + assert_false(isWeekOutsideOfRange( + /*week=*/new Week(1, 2), + /*minWeek=*/new Week(1, 1), + /*maxWeek=*/new Week(1, 3)), + 'min < week.week < max: week is within range'); + assert_true(isWeekOutsideOfRange( + /*week=*/new Week(1, 3), + /*minWeek=*/new Week(1, 1), + /*maxWeek=*/new Week(1, 2)), + 'min < max < week.week: week is outside of range'); + +}, `Tests behavior of the date picker's internal function isTodayOutsideOfRange.`); +</script>
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-grid-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-grid-expected.txt index 4b4fddf..3e4f72ac 100644 --- a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-grid-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-grid-expected.txt
@@ -219,30 +219,30 @@ ], "positiveRowLineNumberPositions": [ { - "x": 118, + "x": 173, "y": 408 }, { - "x": 150.5, + "x": 205.5, "y": 408 }, { - "x": 183, + "x": 238, "y": 408 } ], "positiveColumnLineNumberPositions": [ { "x": 173, - "y": 1198 + "y": 408 }, { "x": 173, - "y": 1135.5 + "y": 345.5 }, { "x": 173, - "y": 923 + "y": 133 } ], "negativeRowLineNumberOffsets": [ @@ -266,11 +266,11 @@ }, { "x": 238, - "y": 1135.5 + "y": 345.5 }, { "x": 238, - "y": 923 + "y": 133 } ], "areaNames": {},
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-multiple-css-grid-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-multiple-css-grid-expected.txt index 5add83b..50fc05a 100644 --- a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-multiple-css-grid-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-multiple-css-grid-expected.txt
@@ -124,30 +124,30 @@ ], "positiveRowLineNumberPositions": [ { - "x": 118, + "x": 173, "y": 408 }, { - "x": 150.5, + "x": 205.5, "y": 408 }, { - "x": 183, + "x": 238, "y": 408 } ], "positiveColumnLineNumberPositions": [ { "x": 173, - "y": 1198 + "y": 408 }, { "x": 173, - "y": 1135.5 + "y": 345.5 }, { "x": 173, - "y": 923 + "y": 133 } ], "negativeRowLineNumberOffsets": [ @@ -171,11 +171,11 @@ }, { "x": 238, - "y": 1135.5 + "y": 345.5 }, { "x": 238, - "y": 923 + "y": 133 } ], "areaNames": {},
diff --git a/third_party/blink/web_tests/http/tests/push_messaging/push-subscription-stringification.html b/third_party/blink/web_tests/http/tests/push_messaging/push-subscription-stringification.html index 32828ffc..a8ba724 100644 --- a/third_party/blink/web_tests/http/tests/push_messaging/push-subscription-stringification.html +++ b/third_party/blink/web_tests/http/tests/push_messaging/push-subscription-stringification.html
@@ -3,6 +3,7 @@ <head> <title>Stringifying a PushSubscription object includes all object members</title> <link rel="manifest" href="resources/push_manifest.json"> +<script src="resources/push-constants.js"></script> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="../serviceworker/resources/test-helpers.js"></script> @@ -36,9 +37,12 @@ assert_own_property(reflectedObject, 'endpoint'); assert_equals(reflectedObject.endpoint, pushSubscription.endpoint); + // Expiration time should be in the expected window assert_own_property(reflectedObject, 'expirationTime'); - assert_equals(reflectedObject.expirationTime, null); - + assert_true(typeof pushSubscription.expirationTime === 'number'); + assert_approx_equals(pushSubscription.expirationTime, Date.now() + + EXPIRATION_WINDOW, EXPIRATION_TIME_TOLERANCE, + `Expiration time should be in expected window: ${EXPIRATION_TIME_TOLERANCE} ms`); assert_own_property(reflectedObject, 'keys'); assert_own_property(reflectedObject.keys, 'p256dh'); assert_own_property(reflectedObject.keys, 'auth');
diff --git a/third_party/blink/web_tests/http/tests/push_messaging/resources/push-constants.js b/third_party/blink/web_tests/http/tests/push_messaging/resources/push-constants.js index 7db1d186..33ddb4e 100644 --- a/third_party/blink/web_tests/http/tests/push_messaging/resources/push-constants.js +++ b/third_party/blink/web_tests/http/tests/push_messaging/resources/push-constants.js
@@ -17,4 +17,8 @@ const INVALID_BASE64URL_ENCODED_KEY = "BJEOX8aRBRLJ1SitNXbDH9Lc5CCIsTE33YwGakcXvoQ5K7KZq13-jxB2vhMTcX9c4-tC0h6CIFifzJhH6cNS!!!" -const INVALID_BASE64_ENCODED_KEY = "BJEOX8aRBRLJ1SitNXbDH9Lc5CCIsTE33YwGakcXvoQ5K7KZq13+jxB2vhMTcX9c4+tC0h6CIFifzJhH6cNS/wQ=" \ No newline at end of file +const INVALID_BASE64_ENCODED_KEY = "BJEOX8aRBRLJ1SitNXbDH9Lc5CCIsTE33YwGakcXvoQ5K7KZq13+jxB2vhMTcX9c4+tC0h6CIFifzJhH6cNS/wQ=" + +const EXPIRATION_WINDOW = 90 * 24 * 60 * 60 * 1000; + +const EXPIRATION_TIME_TOLERANCE = 24 * 60 * 60 * 1000;
diff --git a/third_party/blink/web_tests/http/tests/push_messaging/subscribe-success-in-document.html b/third_party/blink/web_tests/http/tests/push_messaging/subscribe-success-in-document.html index 0924a195..5fccd681 100644 --- a/third_party/blink/web_tests/http/tests/push_messaging/subscribe-success-in-document.html +++ b/third_party/blink/web_tests/http/tests/push_messaging/subscribe-success-in-document.html
@@ -3,6 +3,7 @@ <head> <title>subscribe() succeeds when permission is granted and resolves with a valid subscription</title> <link rel="manifest" href="resources/push_manifest.json"> +<script src="resources/push-constants.js"></script> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="../serviceworker/resources/test-helpers.js"></script> @@ -31,11 +32,12 @@ assert_idl_attribute(pushSubscription, 'endpoint'); assert_equals(typeof pushSubscription.endpoint, 'string'); + // Expiration time should be in the expected window assert_idl_attribute(pushSubscription, 'expirationTime'); - // TODO(viviy): check for not null after passing expiration time in - // PushMessagingManager - assert_equals(pushSubscription.expirationTime, null); - + assert_true(typeof pushSubscription.expirationTime === 'number'); + assert_approx_equals(pushSubscription.expirationTime, Date.now() + + EXPIRATION_WINDOW, EXPIRATION_TIME_TOLERANCE, + `Expiration time should be in expected window: ${EXPIRATION_TIME_TOLERANCE} ms`); try { var endpointUrl = new URL(pushSubscription.endpoint); } catch(e) {
diff --git a/third_party/boringssl/BUILD.gn b/third_party/boringssl/BUILD.gn index b435499..fab8905 100644 --- a/third_party/boringssl/BUILD.gn +++ b/third_party/boringssl/BUILD.gn
@@ -72,7 +72,7 @@ } else if (current_cpu == "x64") { if (is_mac) { sources += crypto_sources_mac_x86_64 - } else if (is_linux || is_android) { + } else if (is_linux || is_chromeos || is_android) { sources += crypto_sources_linux_x86_64 } else { public_configs = [ ":no_asm_config" ] @@ -80,13 +80,13 @@ } else if (current_cpu == "x86") { if (is_mac) { sources += crypto_sources_mac_x86 - } else if (is_linux || is_android) { + } else if (is_linux || is_chromeos || is_android) { sources += crypto_sources_linux_x86 } else { public_configs = [ ":no_asm_config" ] } } else if (current_cpu == "arm") { - if (is_linux || is_android) { + if (is_linux || is_chromeos || is_android) { sources += crypto_sources_linux_arm } else if (is_ios) { sources += crypto_sources_ios_arm @@ -94,7 +94,7 @@ public_configs = [ ":no_asm_config" ] } } else if (current_cpu == "arm64") { - if (is_linux || is_android) { + if (is_linux || is_chromeos || is_android) { sources += crypto_sources_linux_aarch64 } else if (is_ios) { sources += crypto_sources_ios_aarch64
diff --git a/third_party/breakpad/BUILD.gn b/third_party/breakpad/BUILD.gn index 9867688..cd2a60b 100644 --- a/third_party/breakpad/BUILD.gn +++ b/third_party/breakpad/BUILD.gn
@@ -471,7 +471,7 @@ } } -if (is_linux || is_android) { +if (is_linux || is_chromeos || is_android) { if (current_toolchain == host_toolchain) { executable("symupload") { sources = [
diff --git a/third_party/crashpad/crashpad/build/crashpad_buildconfig.gni b/third_party/crashpad/crashpad/build/crashpad_buildconfig.gni index d919a8b..a8bf6cf8 100644 --- a/third_party/crashpad/crashpad/build/crashpad_buildconfig.gni +++ b/third_party/crashpad/crashpad/build/crashpad_buildconfig.gni
@@ -38,7 +38,7 @@ crashpad_is_mac = is_mac crashpad_is_ios = is_ios crashpad_is_win = is_win - crashpad_is_linux = is_linux + crashpad_is_linux = is_linux || is_chromeos crashpad_is_android = is_android crashpad_is_fuchsia = is_fuchsia
diff --git a/third_party/dav1d/BUILD.gn b/third_party/dav1d/BUILD.gn index 33b855f9d..327cdcc 100644 --- a/third_party/dav1d/BUILD.gn +++ b/third_party/dav1d/BUILD.gn
@@ -113,7 +113,7 @@ if (is_mac) { dav1d_copts += [ "-D_DARWIN_C_SOURCE" ] } - if (is_linux || is_android || current_os == "aix") { + if (is_linux || is_chromeos || is_android || current_os == "aix") { if (!is_clang) { dav1d_copts += [ "-D_GNU_SOURCE" ] }
diff --git a/third_party/expat/BUILD.gn b/third_party/expat/BUILD.gn index 1bddfcb0..2dc7964 100644 --- a/third_party/expat/BUILD.gn +++ b/third_party/expat/BUILD.gn
@@ -9,7 +9,7 @@ # let's not pull it in twice. # Chromecast doesn't ship expat as a system library. # Libfuzzer and AFL need to build library from sources. -if (is_linux && !is_chromecast && !use_fuzzing_engine) { +if ((is_linux || is_chromeos) && !is_chromecast && !use_fuzzing_engine) { config("expat_config") { libs = [ "expat" ] }
diff --git a/third_party/fontconfig/BUILD.gn b/third_party/fontconfig/BUILD.gn index 2f93387..1bee7acb 100644 --- a/third_party/fontconfig/BUILD.gn +++ b/third_party/fontconfig/BUILD.gn
@@ -5,7 +5,7 @@ import("//build/config/sanitizers/sanitizers.gni") import("//third_party/fontconfig/fontconfig.gni") -assert(is_linux) +assert(is_linux || is_chromeos) if (use_bundled_fontconfig) { config("fontconfig_config") {
diff --git a/third_party/fontconfig/fontconfig.gni b/third_party/fontconfig/fontconfig.gni index 2baef3b5..50d9f1fa 100644 --- a/third_party/fontconfig/fontconfig.gni +++ b/third_party/fontconfig/fontconfig.gni
@@ -5,8 +5,8 @@ import("//build/config/chromeos/args.gni") import("//build/config/features.gni") -assert(is_linux) +assert(is_linux || is_chromeos) declare_args() { - use_bundled_fontconfig = is_linux && !is_chromeos_device + use_bundled_fontconfig = (is_linux || is_chromeos) && !is_chromeos_device }
diff --git a/third_party/freetype/BUILD.gn b/third_party/freetype/BUILD.gn index d8599ae..b84a743 100644 --- a/third_party/freetype/BUILD.gn +++ b/third_party/freetype/BUILD.gn
@@ -131,13 +131,13 @@ ] } - if (is_linux || is_chromecast) { + if (is_linux || is_chromeos || is_chromecast) { # Needed for content_shell on Linux and Chromecast, since fontconfig # requires FT_Get_BDF_Property. sources += [ "src/src/base/ftbdf.c" ] } - if (is_linux || is_chromecast) { + if (is_linux || is_chromeos || is_chromecast) { # Needed on Fedora whose libfreetype builds ftsynth.c containing # FT_GlyphSlot_Embolden, which we need to replace in content_shell if # we are linking against our own FreeType.
diff --git a/third_party/ijar/BUILD.gn b/third_party/ijar/BUILD.gn index 127fb96..9ad722f 100644 --- a/third_party/ijar/BUILD.gn +++ b/third_party/ijar/BUILD.gn
@@ -4,7 +4,7 @@ # A tool that removes all non-interface-specific parts from a .jar file. -if (is_linux) { +if (is_linux || is_chromeos) { executable("ijar") { sources = [ "classfile.cc",
diff --git a/third_party/libdrm/BUILD.gn b/third_party/libdrm/BUILD.gn index b870f33..1da5e188 100644 --- a/third_party/libdrm/BUILD.gn +++ b/third_party/libdrm/BUILD.gn
@@ -1,7 +1,7 @@ # 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. -assert(is_linux) +assert(is_linux || is_chromeos) config("libdrm_config") { # TODO(thomasanderson): Remove this hack once
diff --git a/third_party/libusb/BUILD.gn b/third_party/libusb/BUILD.gn index 2159671f..fe8c6649 100644 --- a/third_party/libusb/BUILD.gn +++ b/third_party/libusb/BUILD.gn
@@ -28,7 +28,7 @@ if (is_clang) { # guid_eq in windows_usb.c is unused. cflags = [ "-Wno-unused-function" ] - if (is_linux && !use_udev) { + if ((is_linux || is_chromeos) && !use_udev) { cflags += [ "-Wno-pointer-sign" ] } } @@ -115,7 +115,7 @@ ] } - if (is_linux) { + if (is_linux || is_chromeos) { sources += [ "src/libusb/os/linux_usbfs.c", "src/libusb/os/linux_usbfs.h", @@ -139,7 +139,7 @@ deps += [ "//build/linux/libudev" ] } - if (is_linux && !use_udev) { + if ((is_linux || is_chromeos) && !use_udev) { sources += [ "src/libusb/os/linux_netlink.c" ] defines += [ "HAVE_LINUX_NETLINK_H" ] }
diff --git a/third_party/libxml/BUILD.gn b/third_party/libxml/BUILD.gn index 653a076ef..a155534 100644 --- a/third_party/libxml/BUILD.gn +++ b/third_party/libxml/BUILD.gn
@@ -4,7 +4,7 @@ # Define an "os_include" variable that points at the OS-specific generated # headers. These were generated by running the configure script offline. -if (is_linux || is_android || is_nacl || is_fuchsia) { +if (is_linux || is_chromeos || is_android || is_nacl || is_fuchsia) { os_include = "linux" } else if (is_apple) { os_include = "mac" @@ -66,7 +66,7 @@ # TODO(hans): See if we can fix upstream (http://crbug.com/763944). "-Wno-enum-compare", ] - } else if (is_linux) { + } else if (is_linux || is_chromeos) { cflags = [ # gcc spits out a bunch of warnings about passing too many arguments to # __xmlSimpleError.
diff --git a/third_party/libxslt/BUILD.gn b/third_party/libxslt/BUILD.gn index 4aa6502..2cc220dc 100644 --- a/third_party/libxslt/BUILD.gn +++ b/third_party/libxslt/BUILD.gn
@@ -81,7 +81,7 @@ public_configs = [ ":libxslt_config" ] cflags = [] - if (is_linux || is_android || is_fuchsia) { + if (is_linux || is_chromeos || is_android || is_fuchsia) { include_dirs = [ "linux" ] } else if (is_win) { include_dirs = [ "win32" ]
diff --git a/third_party/minigbm/BUILD.gn b/third_party/minigbm/BUILD.gn index 8cc5f9d..79ebcab 100644 --- a/third_party/minigbm/BUILD.gn +++ b/third_party/minigbm/BUILD.gn
@@ -5,7 +5,7 @@ import("//build/config/chromecast_build.gni") import("//build/config/linux/pkg_config.gni") -assert(is_linux) +assert(is_linux || is_chromeos) declare_args() { # Controls whether the build should use the version of minigbm library shipped
diff --git a/third_party/openh264/BUILD.gn b/third_party/openh264/BUILD.gn index 581ad6e..ef4937a 100644 --- a/third_party/openh264/BUILD.gn +++ b/third_party/openh264/BUILD.gn
@@ -45,7 +45,7 @@ # is believed to work. # MSAN builds are flaky with assembler. crbug.com/685168 -use_assembler = (is_win || is_linux) && +use_assembler = (is_win || is_linux || is_chromeos) && (current_cpu == "x86" || current_cpu == "x64") && !is_msan # This IF statement will make the targets visible only on specific builds, @@ -55,7 +55,7 @@ if (!is_component_build) { if (is_apple) { asm_defines += [ "WELS_PRIVATE_EXTERN=private_extern" ] - } else if (is_linux || is_android || is_fuchsia) { + } else if (is_linux || is_chromeos || is_android || is_fuchsia) { asm_defines += [ "WELS_PRIVATE_EXTERN=hidden" ] } } @@ -74,7 +74,7 @@ ] } else if (is_win) { defines += [ "WIN64" ] - } else if (is_linux) { + } else if (is_linux || is_chromeos) { defines += [ "UNIX64" ] } } @@ -95,7 +95,7 @@ ] } else if (is_win) { defines += [ "WIN64" ] - } else if (is_linux) { + } else if (is_linux || is_chromeos) { defines += [ "UNIX64" ] } } @@ -116,12 +116,12 @@ ] } else if (is_win) { defines += [ "WIN64" ] - } else if (is_linux) { + } else if (is_linux || is_chromeos) { defines += [ "UNIX64" ] } } } -} # if (is_win || is_linux) +} # if (is_win || is_linux || is_chromeos) source_set("common") { sources = openh264_common_sources
diff --git a/third_party/opus/BUILD.gn b/third_party/opus/BUILD.gn index a6f4000..413a0e9 100644 --- a/third_party/opus/BUILD.gn +++ b/third_party/opus/BUILD.gn
@@ -21,7 +21,7 @@ # If OPUS Run Time CPU Detections (RTCD) shall be used. # Based on the conditions in celt/arm/armcpu.c: # defined(_MSC_VER) || defined(__linux__). -use_opus_arm_rtcd = current_cpu == "arm" && (is_win || is_android || is_linux) +use_opus_arm_rtcd = current_cpu == "arm" && (is_win || is_android || is_linux || is_chromeos) config("opus_config") { include_dirs = [ "src/include" ] @@ -612,7 +612,7 @@ # Compilation fails on windows due to wstring/string mistmatch. # This is not worth looking at it since the benchmark is tailored for android. # It is ok to run it on linux though, for experimentation purpose. -if (is_android || is_linux) { +if (is_android || is_linux || is_chromeos) { test("opus_tests") { sources = [ "tests/opus_benchmark.cc" ]
diff --git a/third_party/sqlite/BUILD.gn b/third_party/sqlite/BUILD.gn index 772114f..6994028 100644 --- a/third_party/sqlite/BUILD.gn +++ b/third_party/sqlite/BUILD.gn
@@ -138,7 +138,7 @@ ] } } - if (is_linux) { + if (is_linux || is_chromeos) { cflags += [ # SQLite doesn't believe in compiler warnings, preferring testing. # http://www.sqlite.org/faq.html#q17 @@ -191,7 +191,7 @@ } } - if (is_linux || is_android) { + if (is_linux || is_chromeos || is_android) { defines += [ # Linux provides fdatasync(), a faster equivalent of fsync(). "fdatasync=fdatasync", @@ -270,7 +270,7 @@ } } - if (is_linux || is_android) { + if (is_linux || is_chromeos || is_android) { defines += [ # Linux provides fdatasync(), a faster equivalent of fsync(). "fdatasync=fdatasync", @@ -344,7 +344,7 @@ ] } -if (is_win || is_mac || is_linux) { +if (is_win || is_mac || is_linux || is_chromeos) { executable("sqlite_shell") { include_dirs = [ # SQLite's shell.c contains an '#include "sqlite3.h", which we want to be
diff --git a/third_party/usrsctp/BUILD.gn b/third_party/usrsctp/BUILD.gn index caf61a64..00ed6acb 100644 --- a/third_party/usrsctp/BUILD.gn +++ b/third_party/usrsctp/BUILD.gn
@@ -121,7 +121,7 @@ "-UINET6", ] - if (is_linux || is_android) { + if (is_linux || is_chromeos || is_android) { defines += [ "__Userspace_os_Linux", "_GNU_SOURCE",
diff --git a/third_party/widevine/cdm/BUILD.gn b/third_party/widevine/cdm/BUILD.gn index 1919784f..6225a61 100644 --- a/third_party/widevine/cdm/BUILD.gn +++ b/third_party/widevine/cdm/BUILD.gn
@@ -135,7 +135,7 @@ # This target exists for tests to depend on that pulls in a runtime dependency # on the license server. group("widevine_test_license_server") { - if (bundle_widevine_cdm && is_linux) { + if (bundle_widevine_cdm && (is_linux || is_chromeos)) { data = [ "//third_party/widevine/test/license_server/" ] } }
diff --git a/tools/android/avd/proto/creation/generic_android23.textpb b/tools/android/avd/proto/creation/generic_android23.textpb index cd0054b..f5e0d93 100644 --- a/tools/android/avd/proto/creation/generic_android23.textpb +++ b/tools/android/avd/proto/creation/generic_android23.textpb
@@ -6,13 +6,13 @@ emulator_package { package_name: "chromium/third_party/android_sdk/public/emulator" - version: "A4EvXZUIuQho0QRDJopMUpgyp6NA3aiDQjGKPUKbowMC" + version: "xhyuoquVvBTcJelgRjMKZeoBVSQRjB7pLVJPt5C9saIC" dest_path: ".emulator_sdk" } system_image_package { package_name: "chromium/third_party/android_sdk/public/system-images/android-23/google_apis/x86" - version: "j_921Gw3fAlW8WYL9A6BeEFLQ8CSC9LMhPZKAq8DCxkC" + version: "npuCAATVbhmywZwGhI3tMoECTrBBzzyJLpjAPXqtmYYC" dest_path: ".emulator_sdk" } system_image_name: "system-images;android-23;google_apis;x86" @@ -34,4 +34,7 @@ key: "GLDMA" value: "off" } + # Tests can run into low memory issue with the default ram size 1024MB + # Incease to 2048MB, which is the same as that on Nexus 5X + ram_size: 2048 }
diff --git a/tools/android/avd/proto/creation/generic_android23_tablet.textpb b/tools/android/avd/proto/creation/generic_android23_tablet.textpb index a0bfaa2..3ba60e6 100644 --- a/tools/android/avd/proto/creation/generic_android23_tablet.textpb +++ b/tools/android/avd/proto/creation/generic_android23_tablet.textpb
@@ -6,13 +6,13 @@ emulator_package { package_name: "chromium/third_party/android_sdk/public/emulator" - version: "A4EvXZUIuQho0QRDJopMUpgyp6NA3aiDQjGKPUKbowMC" + version: "xhyuoquVvBTcJelgRjMKZeoBVSQRjB7pLVJPt5C9saIC" dest_path: ".emulator_sdk" } system_image_package { package_name: "chromium/third_party/android_sdk/public/system-images/android-23/google_apis/x86" - version: "j_921Gw3fAlW8WYL9A6BeEFLQ8CSC9LMhPZKAq8DCxkC" + version: "npuCAATVbhmywZwGhI3tMoECTrBBzzyJLpjAPXqtmYYC" dest_path: ".emulator_sdk" } system_image_name: "system-images;android-23;google_apis;x86" @@ -37,4 +37,7 @@ key: "GLDMA" value: "off" } + # Tests can run into low memory issue with the default ram size 1024MB + # Incease to 2048MB, which is the same as that on Nexus 5X + ram_size: 2048 }
diff --git a/tools/android/avd/proto/creation/generic_android28.textpb b/tools/android/avd/proto/creation/generic_android28.textpb index 367fe1d1..d77326f2 100644 --- a/tools/android/avd/proto/creation/generic_android28.textpb +++ b/tools/android/avd/proto/creation/generic_android28.textpb
@@ -6,13 +6,13 @@ emulator_package { package_name: "chromium/third_party/android_sdk/public/emulator" - version: "A4EvXZUIuQho0QRDJopMUpgyp6NA3aiDQjGKPUKbowMC" + version: "xhyuoquVvBTcJelgRjMKZeoBVSQRjB7pLVJPt5C9saIC" dest_path: ".emulator_sdk" } system_image_package { package_name: "chromium/third_party/android_sdk/public/system-images/android-28/google_apis/x86" - version: "FqzSrAzROgfIjXE0eJ8hmf--GqFjwf9aIDzBVdvPIbwC" + version: "LDa0XkTjgGYx7Amzg5qjIRgCfc4F_pq7rKMJVdACYx8C" dest_path: ".emulator_sdk" } system_image_name: "system-images;android-28;google_apis;x86"
diff --git a/tools/android/avd/proto/creation/generic_playstore_android28.textpb b/tools/android/avd/proto/creation/generic_playstore_android28.textpb index 854807ee..4196b6e 100644 --- a/tools/android/avd/proto/creation/generic_playstore_android28.textpb +++ b/tools/android/avd/proto/creation/generic_playstore_android28.textpb
@@ -6,7 +6,7 @@ emulator_package { package_name: "chromium/third_party/android_sdk/public/emulator" - version: "A4EvXZUIuQho0QRDJopMUpgyp6NA3aiDQjGKPUKbowMC" + version: "lnt2Oz8NS73mAJL389R1QwgbM2qDSKNIRWTUOdmywukC" dest_path: ".emulator_sdk" }
diff --git a/tools/binary_size/libsupersize/caspian/wasmbuild.patch b/tools/binary_size/libsupersize/caspian/wasmbuild.patch index c1866163..65d45ded 100644 --- a/tools/binary_size/libsupersize/caspian/wasmbuild.patch +++ b/tools/binary_size/libsupersize/caspian/wasmbuild.patch
@@ -1,24 +1,25 @@ diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn -index 4cc6bfc45e64..02fb53d01d0a 100644 +index 59dace167eef..ebbe3f37d101 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn -@@ -291,9 +291,10 @@ is_ios = current_os == "ios" +@@ -291,10 +291,11 @@ is_ios = current_os == "ios" is_linux = current_os == "chromeos" || current_os == "linux" is_mac = current_os == "mac" is_nacl = current_os == "nacl" +is_wasm = current_os == "wasm" is_win = current_os == "win" || current_os == "winuwp" + is_apple = is_ios || is_mac -is_posix = !is_win && !is_fuchsia +is_posix = !is_win && !is_fuchsia && !is_wasm # ============================================================================= # SOURCES FILTERS diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn -index d483562f6b0b..6b00d5d2ab2b 100644 +index f4ba837449b5..0fe4f8247c68 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn -@@ -575,6 +575,19 @@ config("compiler") { +@@ -578,6 +578,19 @@ config("compiler") { ldflags += [ "-stdlib=libc++" ] } @@ -38,7 +39,7 @@ # Add flags for link-time optimization. These flags enable # optimizations/transformations that require whole-program visibility at link # time, so they need to be applied to all translation units, and we may end up -@@ -1492,7 +1505,8 @@ config("default_warnings") { +@@ -1495,7 +1508,8 @@ config("default_warnings") { cflags += [ "-Wno-nonportable-include-path" ] } @@ -48,7 +49,7 @@ # Flags NaCl (Clang 3.7) and Xcode 9.2 (Clang clang-900.0.39.2) do not # recognize. cflags += [ -@@ -2248,6 +2262,9 @@ config("symbols") { +@@ -2257,6 +2271,9 @@ config("symbols") { "-debug-info-kind=constructor", ] } @@ -59,10 +60,10 @@ cflags = [] if (is_mac && enable_dsyms) { diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni -index 80c2e7b5e4a2..1976fab7b86e 100644 +index d556b0e0927e..f4597ab04037 100644 --- a/build/toolchain/toolchain.gni +++ b/build/toolchain/toolchain.gni -@@ -59,6 +59,9 @@ if (is_mac || is_ios) { +@@ -59,6 +59,9 @@ if (is_apple) { shlib_extension = ".so" } else if (is_win) { shlib_extension = ".dll"
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index a37068b..ce36e9f 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -9033,6 +9033,15 @@ <description>User opened a URL in Chrome via Apple Shortcuts.</description> </action> +<action name="IOSLaunchedByOpenInIncognitoIntent"> + <owner>gujen@chromium.org</owner> + <owner>rohitrao@chromium.org</owner> + <description> + User opened a URL/a list of URLs in Chrome in Incognito mode via Apple + Shortcuts. + </description> +</action> + <action name="IOSLaunchedBySearchInChromeIntent"> <owner>justincohen@chromium.org</owner> <description> @@ -20691,12 +20700,31 @@ </action> <action name="SharingQRCode.DialogLaunched"> + <owner>skare@chromium.org</owner> <owner>src/components/send_tab_to_self/OWNERS</owner> <description> User launched the QR Generator dialog (desktop platforms). </description> </action> +<action name="SharingQRCode.DialogLaunched.ContextMenuImage"> + <owner>skare@chromium.org</owner> + <owner>src/components/send_tab_to_self/OWNERS</owner> + <description> + User launched the QR Generator dialog for an image via the context menu on + desktop. + </description> +</action> + +<action name="SharingQRCode.DialogLaunched.ContextMenuPage"> + <owner>skare@chromium.org</owner> + <owner>src/components/send_tab_to_self/OWNERS</owner> + <description> + User launched the QR Generator dialog for a page via the context menu on + desktop. + </description> +</action> + <action name="SharingQRCode.DownloadQRCode"> <owner>tgupta@chromium.org</owner> <owner>src/components/send_tab_to_self/OWNERS</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b8e52628..0dcc0ef 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -60221,7 +60221,7 @@ <int value="7" label="MediaElementEvent"/> <int value="8" label="CanvasBlobSerialization"/> <int value="9" label="Microtask"/> - <int value="10" label="JavascriptTimer"/> + <int value="10" label="JavascriptTimerDelayed"/> <int value="11" label="RemoteEvent"/> <int value="12" label="WebSocket"/> <int value="13" label="PostedMessage"/> @@ -60283,6 +60283,7 @@ <int value="69" label="MainThreadTaskQueueNonWaking"/> <int value="70" label="InternalFindInPage"/> <int value="71" label="InternalHighPriorityLocalFrame"/> + <int value="72" label="JavascriptTimerImmediate"/> </enum> <enum name="RendererSchedulerTaskUseCase">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index e4624bc..14ca58e8 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -9608,6 +9608,18 @@ </summary> </histogram> +<histogram base="true" name="Ash.Assistant.AnimationSmoothness" units="%" + expires_after="2021-07-20"> +<!-- Name completed by histogram_suffixes name="AshAssistantAnimationSmoothness" --> + + <owner>cowmoo@chromium.org</owner> + <owner>xiaohuic@chromium.org</owner> + <summary> + Relative smoothness of assistant related animations. 100% represents ideally + smooth 60 frames per second. + </summary> +</histogram> + <histogram name="Ash.BackGesture.EndScenarioType" enum="BackGestureEndScenarioType" expires_after="2020-12-23"> <owner>minch@chromium.org</owner> @@ -145175,6 +145187,9 @@ <histogram name="ResourceCoordinator.LocalDB.DatabaseInit" enum="LocalSiteCharacteristicsDBInitStatus" expires_after="M77"> + <obsolete> + Removed July 2020. + </obsolete> <owner>sebmarchand@chromium.org</owner> <summary> The result of opening the Local Site Characteristics database. @@ -145183,6 +145198,9 @@ <histogram name="ResourceCoordinator.LocalDB.DatabaseInitAfterDelete" enum="LocalSiteCharacteristicsDBInitStatus" expires_after="M77"> + <obsolete> + Removed July 2020. + </obsolete> <owner>sebmarchand@chromium.org</owner> <summary> The result of opening the Local Site Characteristics database after deleting @@ -145192,6 +145210,9 @@ <histogram name="ResourceCoordinator.LocalDB.DatabaseInitAfterRepair" enum="LocalSiteCharacteristicsDBInitStatus" expires_after="M77"> + <obsolete> + Removed July 2020. + </obsolete> <owner>sebmarchand@chromium.org</owner> <summary> The result of opening the Local Site Characteristics database after a repair @@ -145201,6 +145222,9 @@ <histogram name="ResourceCoordinator.LocalDB.DatabaseRepair" enum="BooleanSuccess" expires_after="M77"> + <obsolete> + Removed July 2020. + </obsolete> <owner>sebmarchand@chromium.org</owner> <summary> The result of trying to repair the Local Site Characteristics database after @@ -145210,6 +145234,9 @@ <histogram name="ResourceCoordinator.LocalDB.ObservationTimeBeforeFirstUse" units="ms" expires_after="M85"> + <obsolete> + Removed July 2020. + </obsolete> <!-- Name completed by histogram_suffixes name="LocalSiteCharacteristicsFeatures" --> <owner>sebmarchand@chromium.org</owner> @@ -145221,6 +145248,9 @@ <histogram name="ResourceCoordinator.LocalDB.OnDiskSize" units="KB" expires_after="M85"> + <obsolete> + Removed July 2020. + </obsolete> <owner>sebmarchand@chromium.org</owner> <summary> The size of the Local Site Characteristics database on disk. Recorded at @@ -145230,6 +145260,9 @@ <histogram name="ResourceCoordinator.LocalDB.ReadHasCompletedBeforeQuery" enum="Boolean" expires_after="M77"> + <obsolete> + Removed July 2020. + </obsolete> <owner>sebmarchand@chromium.org</owner> <summary> Boolean indicating if the read operation from the Local Site Characteristics @@ -198543,6 +198576,18 @@ <affected-histogram name="ArcAuth.MainAccountResolutionStatus"/> </histogram_suffixes> +<histogram_suffixes name="AshAssistantAnimationSmoothness" separator="."> + <suffix name="CardElement" + label="Animation for showing and hiding card responses"/> + <suffix name="ResizeAssistantPageView" + label="Expand assistant from launcher"/> + <suffix name="SuggestionChip" + label="Animation for showing and hiding suggestion chips"/> + <suffix name="TextElement" + label="Animation for showing and hiding text response"/> + <affected-histogram name="Ash.Assistant.AnimationSmoothness"/> +</histogram_suffixes> + <histogram_suffixes name="AssistantProactiveSuggestionsShowAttemptByCategory" separator="." ordering="prefix,3"> <suffix name="AbortedByDuplicateSuppression" @@ -205840,6 +205885,9 @@ </histogram_suffixes> <histogram_suffixes name="LocalSiteCharacteristicsFeatures" separator="."> + <obsolete> + Removed July 2020. + </obsolete> <suffix name="AudioUsageInBackground" label="A tab played some audio while it was in background."/> <suffix name="FaviconUpdateInBackground"
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index ae35bf456..0ae6f1f0 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -9,8 +9,8 @@ "remote_path": "perfetto_binaries/trace_processor_shell/mac/f6c424bb59238a75fbb10d4d802b5ad31107a3a3/trace_processor_shell" }, "linux": { - "hash": "d2519e9005a8c9ad14abc39f10566856720e9068", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/f6c424bb59238a75fbb10d4d802b5ad31107a3a3/trace_processor_shell" + "hash": "6272ed239cb17d8d5de1880b69d56c41e9d57f09", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/4766bd88cf78535fd52edab11fa99374581b2bee/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/android/java/res/values-night/colors.xml b/ui/android/java/res/values-night/colors.xml index 31d9e3e..a211303 100644 --- a/ui/android/java/res/values-night/colors.xml +++ b/ui/android/java/res/values-night/colors.xml
@@ -40,6 +40,7 @@ <color name="ripple_color_blue">@color/ripple_color_blue_light</color> <!-- Colors used for Widgets (checkboxes, switches, buttons, etc)--> + <color name="default_control_color_normal">@color/default_control_color_normal_dark</color> <color name="default_control_color_active">@color/default_control_color_active_dark</color> <!-- Chip colors -->
diff --git a/ui/android/java/res/values/semantic_colors_adaptive.xml b/ui/android/java/res/values/semantic_colors_adaptive.xml index f52e4807..d143c80 100644 --- a/ui/android/java/res/values/semantic_colors_adaptive.xml +++ b/ui/android/java/res/values/semantic_colors_adaptive.xml
@@ -74,6 +74,7 @@ <color name="ripple_color_blue">@color/ripple_color_blue_dark</color> <!-- Colors used for Widgets (checkboxes, switches, buttons, etc)--> + <color name="default_control_color_normal" tools:ignore="UnusedResources">@color/default_control_color_normal_light</color> <color name="default_control_color_active" tools:ignore="UnusedResources">@color/default_control_color_active_light</color> <!-- Chip colors -->
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 94c6f10..7768cec5 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -428,6 +428,7 @@ ":ui_data_pack", "//base", "//skia", + "//third_party/abseil-cpp:absl", "//ui/gfx", "//ui/gfx/geometry", ]
diff --git a/ui/base/models/image_model.cc b/ui/base/models/image_model.cc index ce409c3..acecd35 100644 --- a/ui/base/models/image_model.cc +++ b/ui/base/models/image_model.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <tuple> + #include "ui/base/models/image_model.h" namespace ui { @@ -11,7 +13,7 @@ VectorIconModel::VectorIconModel(const gfx::VectorIcon& vector_icon, int color_id, int icon_size) - : vector_icon_(&vector_icon), icon_size_(icon_size), color_id_(color_id) {} + : vector_icon_(&vector_icon), icon_size_(icon_size), color_(color_id) {} VectorIconModel::VectorIconModel(const gfx::VectorIcon& vector_icon, SkColor color, @@ -29,8 +31,8 @@ VectorIconModel& VectorIconModel::operator=(VectorIconModel&&) = default; bool VectorIconModel::operator==(const VectorIconModel& other) const { - return vector_icon_ == other.vector_icon_ && icon_size_ == other.icon_size_ && - color_ == other.color_ && color_id_ == other.color_id_; + return std::tie(vector_icon_, icon_size_, color_) == + std::tie(other.vector_icon_, other.icon_size_, other.color_); } bool VectorIconModel::operator!=(const VectorIconModel& other) const { @@ -40,9 +42,9 @@ ImageModel::ImageModel() = default; ImageModel::ImageModel(const VectorIconModel& vector_icon_model) - : vector_icon_model_(vector_icon_model) {} + : icon_(vector_icon_model) {} -ImageModel::ImageModel(const gfx::Image& image) : image_(image) {} +ImageModel::ImageModel(const gfx::Image& image) : icon_(image) {} ImageModel::ImageModel(const gfx::ImageSkia& image_skia) : ImageModel(gfx::Image(image_skia)) {} @@ -86,11 +88,13 @@ } bool ImageModel::IsVectorIcon() const { - return vector_icon_model_ && !vector_icon_model_.value().is_empty(); + return absl::holds_alternative<VectorIconModel>(icon_) && + !absl::get<VectorIconModel>(icon_).is_empty(); } bool ImageModel::IsImage() const { - return image_ && !image_.value().IsEmpty(); + return absl::holds_alternative<gfx::Image>(icon_) && + !absl::get<gfx::Image>(icon_).IsEmpty(); } gfx::Size ImageModel::Size() const { @@ -101,33 +105,18 @@ return IsImage() ? GetImage().Size() : gfx::Size(); } -const VectorIconModel ImageModel::GetVectorIcon() const { +VectorIconModel ImageModel::GetVectorIcon() const { DCHECK(IsVectorIcon()); - return vector_icon_model_.value(); + return absl::get<VectorIconModel>(icon_); } -const gfx::Image ImageModel::GetImage() const { +gfx::Image ImageModel::GetImage() const { DCHECK(IsImage()); - return image_.value(); + return absl::get<gfx::Image>(icon_); } bool ImageModel::operator==(const ImageModel& other) const { - if (IsEmpty() != other.IsEmpty()) - return false; - - if (IsEmpty()) - return true; - - if (IsVectorIcon() != other.IsVectorIcon()) - return false; - - if (IsImage()) { - return GetImage().AsImageSkia().BackedBySameObjectAs( - other.GetImage().AsImageSkia()); - } - - DCHECK(IsVectorIcon()); - return GetVectorIcon() == other.GetVectorIcon(); + return icon_ == other.icon_; } bool ImageModel::operator!=(const ImageModel& other) const {
diff --git a/ui/base/models/image_model.h b/ui/base/models/image_model.h index 408a7c2..7c9fb9b 100644 --- a/ui/base/models/image_model.h +++ b/ui/base/models/image_model.h
@@ -7,8 +7,9 @@ #include "base/callback.h" #include "base/component_export.h" -#include "base/optional.h" +#include "third_party/abseil-cpp/absl/types/variant.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/color_palette.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" @@ -57,17 +58,13 @@ const gfx::VectorIcon* vector_icon() const { return vector_icon_; } int icon_size() const { return icon_size_; } - int color_id() const { return color_id_.value(); } - SkColor color() const { return color_.value(); } - bool has_color() const { return color_.has_value(); } + int color_id() const { return absl::get<int>(color_); } + SkColor color() const { return absl::get<SkColor>(color_); } + bool has_color() const { return absl::holds_alternative<SkColor>(color_); } const gfx::VectorIcon* vector_icon_ = nullptr; int icon_size_ = 0; - // Only one of the following will ever be assigned. - // TODO: Update to use std::variant or base:Variant once one of them is - // available to use. - base::Optional<int> color_id_; - base::Optional<SkColor> color_; + absl::variant<int, SkColor> color_ = gfx::kPlaceholderColor; }; // ImageModel encapsulates either a gfx::Image or a VectorIconModel. Only one @@ -97,8 +94,8 @@ bool IsImage() const; gfx::Size Size() const; // Only valid if IsVectorIcon() or IsImage() return true, respectively. - const VectorIconModel GetVectorIcon() const; - const gfx::Image GetImage() const; + VectorIconModel GetVectorIcon() const; + gfx::Image GetImage() const; // Checks if both model yield equal images. bool operator==(const ImageModel& other) const; @@ -109,11 +106,7 @@ ImageModel(const gfx::ImageSkia& image_skia); ImageModel(const VectorIconModel& vector_icon_model); - // Only one of the following will ever be assigned. - // TODO: Update to use std::variant or base:Variant once one of them is - // available to use. - base::Optional<VectorIconModel> vector_icon_model_; - base::Optional<gfx::Image> image_; + absl::variant<VectorIconModel, gfx::Image> icon_; }; } // namespace ui
diff --git a/ui/compositor/animation_metrics_reporter.h b/ui/compositor/animation_metrics_reporter.h index 1b12fb5..d06fe232 100644 --- a/ui/compositor/animation_metrics_reporter.h +++ b/ui/compositor/animation_metrics_reporter.h
@@ -5,7 +5,6 @@ #ifndef UI_COMPOSITOR_ANIMATION_METRICS_REPORTER_H_ #define UI_COMPOSITOR_ANIMATION_METRICS_REPORTER_H_ -#include "base/metrics/histogram_macros.h" #include "ui/compositor/compositor_export.h" namespace ui { @@ -23,25 +22,6 @@ virtual void Report(int value) = 0; }; -// A subclass of AnimationMetricsReporter that writes into a percentage -// histogram when Report() is called. -template <const char* histogram_name> -class COMPOSITOR_EXPORT HistogramPercentageMetricsReporter - : public AnimationMetricsReporter { - public: - HistogramPercentageMetricsReporter() = default; - HistogramPercentageMetricsReporter( - const HistogramPercentageMetricsReporter&) = delete; - HistogramPercentageMetricsReporter& operator=( - const HistogramPercentageMetricsReporter&) = delete; - ~HistogramPercentageMetricsReporter() override = default; - - // AnimationMetricsReporter: - void Report(int value) override { - UMA_HISTOGRAM_PERCENTAGE(histogram_name, value); - } -}; - } // namespace ui #endif // UI_COMPOSITOR_ANIMATION_METRICS_REPORTER_H_
diff --git a/ui/gfx/image/image.cc b/ui/gfx/image/image.cc index 1a3c9ca2..bfc36b6 100644 --- a/ui/gfx/image/image.cc +++ b/ui/gfx/image/image.cc
@@ -371,6 +371,10 @@ Image::~Image() {} +bool Image::operator==(const Image& other) const { + return storage_ == other.storage_; +} + // static Image Image::CreateFrom1xBitmap(const SkBitmap& bitmap) { return Image(ImageSkia::CreateFrom1xBitmap(bitmap));
diff --git a/ui/gfx/image/image.h b/ui/gfx/image/image.h index 57596d2a..466b7bf 100644 --- a/ui/gfx/image/image.h +++ b/ui/gfx/image/image.h
@@ -93,6 +93,9 @@ // representations. ~Image(); + // True iff both images are backed by the same storage. + bool operator==(const Image& other) const; + // Creates an image from the passed in 1x bitmap. // WARNING: The resulting image will be pixelated when painted on a high // density display.
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn index 187c455..4df6e85 100644 --- a/ui/message_center/BUILD.gn +++ b/ui/message_center/BUILD.gn
@@ -138,6 +138,8 @@ sources = [ "fake_message_center.cc", "fake_message_center.h", + "lock_screen/fake_lock_screen_controller.cc", + "lock_screen/fake_lock_screen_controller.h", ] deps = [ @@ -160,8 +162,6 @@ } sources = [ - "lock_screen/fake_lock_screen_controller.cc", - "lock_screen/fake_lock_screen_controller.h", "message_center_impl_unittest.cc", "notification_list_unittest.cc", "public/cpp/notification_delegate_unittest.cc",
diff --git a/url/android/java/src/org/chromium/url/GURL.java b/url/android/java/src/org/chromium/url/GURL.java index b9d0788..5361fdd3 100644 --- a/url/android/java/src/org/chromium/url/GURL.java +++ b/url/android/java/src/org/chromium/url/GURL.java
@@ -84,9 +84,6 @@ /** * Enables debug stack trace gathering for GURL. - * - * TODO(https://crbug.com/783819): Remove this when the the fraction of users hitting this - * drops. */ public static void setReportDebugThrowableCallback(ReportDebugThrowableCallback callback) { sReportCallback = callback; @@ -107,7 +104,8 @@ RecordHistogram.recordTimesHistogram("Startup.Android.GURLEnsureMainDexInitialized", SystemClock.elapsedRealtime() - time); if (sReportCallback != null && new Random().nextInt(100) < DEBUG_REPORT_PERCENTAGE) { - final Throwable throwable = new Throwable("This is not a crash, please ignore."); + final Throwable throwable = + new Throwable("This is not a crash, please ignore. See crbug.com/1065377."); // This isn't an assert, because by design this is possible, but we would prefer // this path does not get hit more than necessary and getting stack traces from the // wild will help find issues.
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/DownloadCallbackTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/DownloadCallbackTest.java index d768ef3..bb59addd 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/DownloadCallbackTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/DownloadCallbackTest.java
@@ -27,6 +27,7 @@ import org.chromium.weblayer.DownloadError; import org.chromium.weblayer.DownloadState; import org.chromium.weblayer.Profile; +import org.chromium.weblayer.WebLayer; import org.chromium.weblayer.shell.InstrumentationActivity; import java.io.File; @@ -42,6 +43,8 @@ public InstrumentationActivityTestRule mActivityTestRule = new InstrumentationActivityTestRule(); + private static boolean sIsFileNameSupported; + private InstrumentationActivity mActivity; private Callback mCallback; @@ -51,6 +54,7 @@ public String mContentDisposition; public String mMimetype; public String mLocation; + public String mFileName; public @DownloadState int mState; public @DownloadError int mError; public long mContentLength; @@ -86,6 +90,9 @@ public void onDownloadCompleted(Download download) { mSeenCompleted = true; mLocation = download.getLocation().toString(); + if (sIsFileNameSupported) { + mFileName = download.getFileNameToReportToUser().toString(); + } mState = download.getState(); mError = download.getError(); mMimetype = download.getMimeType(); @@ -131,6 +138,9 @@ Profile profile = mActivity.getBrowser().getProfile(); profile.setDownloadCallback(mCallback); profile.setDownloadDirectory(new File(tempDownloadDirectory)); + + sIsFileNameSupported = + WebLayer.getSupportedMajorVersion(mActivity.getApplicationContext()) >= 86; }); } @@ -196,6 +206,9 @@ Assert.assertTrue(mCallback.mLocation.contains( "org.chromium.weblayer.shell/cache/weblayer/Downloads/")); + if (sIsFileNameSupported) { + Assert.assertTrue(mCallback.mFileName.contains("test")); + } Assert.assertEquals(DownloadState.COMPLETE, mCallback.mState); Assert.assertEquals(DownloadError.NO_ERROR, mCallback.mError); Assert.assertEquals("text/html", mCallback.mMimetype);
diff --git a/weblayer/browser/download_impl.cc b/weblayer/browser/download_impl.cc index 0e8440e..1daa690 100644 --- a/weblayer/browser/download_impl.cc +++ b/weblayer/browser/download_impl.cc
@@ -54,6 +54,13 @@ base::android::ConvertUTF8ToJavaString(env, GetLocation().value())); } +base::android::ScopedJavaLocalRef<jstring> +DownloadImpl::GetFileNameToReportToUser(JNIEnv* env) { + return base::android::ScopedJavaLocalRef<jstring>( + base::android::ConvertUTF8ToJavaString( + env, GetFileNameToReportToUser().value())); +} + base::android::ScopedJavaLocalRef<jstring> DownloadImpl::GetMimeTypeImpl( JNIEnv* env) { return base::android::ScopedJavaLocalRef<jstring>( @@ -117,6 +124,10 @@ return item_->GetTargetFilePath(); } +base::FilePath DownloadImpl::GetFileNameToReportToUser() { + return item_->GetFileNameToReportUser(); +} + std::string DownloadImpl::GetMimeType() { return item_->GetMimeType(); }
diff --git a/weblayer/browser/download_impl.h b/weblayer/browser/download_impl.h index 3319120..d00bc2a 100644 --- a/weblayer/browser/download_impl.h +++ b/weblayer/browser/download_impl.h
@@ -41,6 +41,8 @@ void Resume(JNIEnv* env) { Resume(); } void Cancel(JNIEnv* env) { Cancel(); } base::android::ScopedJavaLocalRef<jstring> GetLocation(JNIEnv* env); + base::android::ScopedJavaLocalRef<jstring> GetFileNameToReportToUser( + JNIEnv* env); // Add Impl suffix to avoid compiler clash with the C++ interface method. base::android::ScopedJavaLocalRef<jstring> GetMimeTypeImpl(JNIEnv* env); int GetError(JNIEnv* env) { return static_cast<int>(GetError()); } @@ -58,6 +60,7 @@ void Resume() override; void Cancel() override; base::FilePath GetLocation() override; + base::FilePath GetFileNameToReportToUser() override; std::string GetMimeType() override; DownloadError GetError() override;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java index 6dd5292d..cdb14cc 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java
@@ -8,6 +8,7 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.net.Uri; import android.os.RemoteException; import android.text.TextUtils; @@ -91,10 +92,9 @@ Intent openIntent = new Intent(Intent.ACTION_VIEW); if (TextUtils.isEmpty(mimeType)) { - openIntent.setData(ContentUriUtils.getContentUriFromFile(new File(location))); + openIntent.setData(getDownloadUri(location)); } else { - openIntent.setDataAndType( - ContentUriUtils.getContentUriFromFile(new File(location)), mimeType); + openIntent.setDataAndType(getDownloadUri(location), mimeType); } openIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); openIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); @@ -256,6 +256,13 @@ } @Override + public String getFileNameToReportToUser() { + StrictModeWorkaround.apply(); + throwIfNativeDestroyed(); + return DownloadImplJni.get().getFileNameToReportToUser(mNativeDownloadImpl); + } + + @Override public String getMimeType() { StrictModeWorkaround.apply(); throwIfNativeDestroyed(); @@ -347,9 +354,9 @@ .setPriorityBeforeO(NotificationCompat.PRIORITY_DEFAULT); // The filename might not have been available initially. - String location = getLocation(); - if (!TextUtils.isEmpty((location))) { - builder.setContentTitle((new File(location)).getName()); + String name = getFileNameToReportToUser(); + if (!TextUtils.isEmpty(name)) { + builder.setContentTitle(name); } if (state == DownloadState.CANCELLED) { @@ -453,6 +460,11 @@ return new NotificationManagerProxyImpl(ContextUtils.getApplicationContext()); } + private static Uri getDownloadUri(String location) { + if (ContentUriUtils.isContentUri(location)) return Uri.parse(location); + return ContentUriUtils.getContentUriFromFile(new File(location)); + } + @CalledByNative private void onNativeDestroyed() { mNativeDownloadImpl = 0; @@ -470,6 +482,7 @@ void resume(long nativeDownloadImpl); void cancel(long nativeDownloadImpl); String getLocation(long nativeDownloadImpl); + String getFileNameToReportToUser(long nativeDownloadImpl); String getMimeTypeImpl(long nativeDownloadImpl); int getError(long nativeDownloadImpl); }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IDownload.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IDownload.aidl index 4cd8eb6..8f686ec 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IDownload.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IDownload.aidl
@@ -18,4 +18,5 @@ int getError() = 7; String getMimeType() = 8; void disableNotification() = 9; + String getFileNameToReportToUser() = 10; }
diff --git a/weblayer/public/download.h b/weblayer/public/download.h index 46fc8c3..5f1122f 100644 --- a/weblayer/public/download.h +++ b/weblayer/public/download.h
@@ -79,6 +79,10 @@ // available until the download completes successfully. virtual base::FilePath GetLocation() = 0; + // Returns the file name for the download that should be displayed to the + // user. + virtual base::FilePath GetFileNameToReportToUser() = 0; + // Returns the effective MIME type of downloaded content. virtual std::string GetMimeType() = 0;
diff --git a/weblayer/public/java/org/chromium/weblayer/Download.java b/weblayer/public/java/org/chromium/weblayer/Download.java index 48e64f1..4c80639 100644 --- a/weblayer/public/java/org/chromium/weblayer/Download.java +++ b/weblayer/public/java/org/chromium/weblayer/Download.java
@@ -129,6 +129,24 @@ } /** + * Returns the file name for the download that should be displayed to the user. + * + * @since 86 + */ + @NonNull + public File getFileNameToReportToUser() { + ThreadCheck.ensureOnUiThread(); + if (WebLayer.getSupportedMajorVersionInternal() < 86) { + throw new UnsupportedOperationException(); + } + try { + return new File(mDownloadImpl.getFileNameToReportToUser()); + } catch (RemoteException e) { + throw new APICallException(e); + } + } + + /** * Returns the effective MIME type of downloaded content. */ @NonNull