diff --git a/DEPS b/DEPS index c584445..9018480b 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # 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': 'b5464754e7d1884519d170fa994c64693a3f9112', + 'v8_revision': '2783d5390f40a85a6588da2e2f2784fd9349ad86', # 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. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'ada8f7cc7d7aa2d0a7d18016c6510c1d5892bd17', + 'catapult_revision': '643994eea8e5d5421441168190e8499c9cbf7ae8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java index d9aefd6b..fbadb25 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.infobar.translate.TranslateMenuHelper; import org.chromium.chrome.browser.infobar.translate.TranslateTabLayout; import org.chromium.chrome.browser.snackbar.Snackbar; +import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController; import org.chromium.chrome.browser.widget.TintedImageButton; import org.chromium.ui.widget.Toast; @@ -42,6 +43,26 @@ private TintedImageButton mMenuButton; + /** The controller for translate UI snackbars. */ + class TranslateSnackbarController implements SnackbarController { + private final int mMenuItemId; + + public TranslateSnackbarController(int menuItemId) { + mMenuItemId = menuItemId; + } + + @Override + public void onDismissNoAction(Object actionData) { + handleTranslateOptionPostSnackbar(mMenuItemId); + } + + @Override + public void onAction(Object actionData) { + // TODO(ramyasharma): Add logging metric to track cancel actions. + // Do nothing. + } + }; + @CalledByNative private static InfoBar create(int initialStep, String sourceLanguageCode, String targetLanguageCode, boolean alwaysTranslate, boolean triggeredFromMenu, @@ -178,24 +199,26 @@ mLanguageMenuHelper.show(TranslateMenu.MENU_TARGET_LANGUAGE); return; case TranslateMenu.ID_OVERFLOW_ALWAYS_TRANSLATE: - mOptions.toggleAlwaysTranslateLanguageState( - !mOptions.alwaysTranslateLanguageState()); - nativeApplyBoolTranslateOption(mNativeTranslateInfoBarPtr, - TranslateOption.ALWAYS_TRANSLATE, mOptions.alwaysTranslateLanguageState()); // Only show snackbar when "Always Translate" is enabled. - if (mOptions.alwaysTranslateLanguageState()) { - showSnackbar(TranslateSnackbarType.ALWAYS_TRANSLATE); + if (!mOptions.alwaysTranslateLanguageState()) { + createAndShowSnackbar( + getContext().getString(R.string.translate_snackbar_always_translate, + mOptions.sourceLanguageName(), mOptions.targetLanguageName()), + Snackbar.UMA_TRANSLATE_ALWAYS, itemId); + } else { + handleTranslateOptionPostSnackbar(itemId); } return; case TranslateMenu.ID_OVERFLOW_NEVER_LANGUAGE: - nativeApplyBoolTranslateOption( - mNativeTranslateInfoBarPtr, TranslateOption.NEVER_TRANSLATE, true); - showSnackbar(TranslateSnackbarType.NEVER_TRANSLATE); + createAndShowSnackbar( + getContext().getString(R.string.translate_snackbar_language_never, + mOptions.sourceLanguageName()), + Snackbar.UMA_TRANSLATE_NEVER, itemId); return; case TranslateMenu.ID_OVERFLOW_NEVER_SITE: - nativeApplyBoolTranslateOption( - mNativeTranslateInfoBarPtr, TranslateOption.NEVER_TRANSLATE_SITE, true); - showSnackbar(TranslateSnackbarType.NEVER_TRANSLATE_SITE); + createAndShowSnackbar( + getContext().getString(R.string.translate_snackbar_site_never), + Snackbar.UMA_TRANSLATE_NEVER_SITE, itemId); return; case TranslateMenu.ID_OVERFLOW_NOT_THIS_LANGUAGE: initMenuHelper(TranslateMenu.MENU_SOURCE_LANGUAGE); @@ -230,29 +253,37 @@ } } - private void showSnackbar(int snackbarType) { - if (snackbarType == TranslateSnackbarType.NEVER_TRANSLATE) { - createAndShowSnackbar(getContext().getString(R.string.translate_snackbar_language_never, - mOptions.sourceLanguageName()), - Snackbar.UMA_TRANSLATE_NEVER); - } else if (snackbarType == TranslateSnackbarType.ALWAYS_TRANSLATE) { - createAndShowSnackbar( - getContext().getString(R.string.translate_snackbar_always_translate, - mOptions.sourceLanguageName(), mOptions.targetLanguageName()), - Snackbar.UMA_TRANSLATE_ALWAYS); - } else if (snackbarType == TranslateSnackbarType.NEVER_TRANSLATE_SITE) { - createAndShowSnackbar(getContext().getString(R.string.translate_snackbar_site_never), - Snackbar.UMA_TRANSLATE_NEVER_SITE); - } - } - - private void createAndShowSnackbar(String title, int type) { + private void createAndShowSnackbar(String title, int umaType, int itemId) { if (getSnackbarManager() == null) { + // Directly apply menu option, if snackbar system is not working. + handleTranslateOptionPostSnackbar(itemId); return; } - getSnackbarManager().showSnackbar(Snackbar.make(title, new TranslateSnackbarController(), - Snackbar.TYPE_NOTIFICATION, type) - .setSingleLine(false)); + getSnackbarManager().showSnackbar( + Snackbar.make(title, new TranslateSnackbarController(itemId), + Snackbar.TYPE_NOTIFICATION, umaType) + .setSingleLine(false) + .setAction( + getContext().getString(R.string.translate_snackbar_cancel), null)); + } + + private void handleTranslateOptionPostSnackbar(int itemId) { + switch (itemId) { + case TranslateMenu.ID_OVERFLOW_ALWAYS_TRANSLATE: + mOptions.toggleAlwaysTranslateLanguageState( + !mOptions.alwaysTranslateLanguageState()); + nativeApplyBoolTranslateOption(mNativeTranslateInfoBarPtr, + TranslateOption.ALWAYS_TRANSLATE, mOptions.alwaysTranslateLanguageState()); + return; + case TranslateMenu.ID_OVERFLOW_NEVER_LANGUAGE: + nativeApplyBoolTranslateOption( + mNativeTranslateInfoBarPtr, TranslateOption.NEVER_TRANSLATE, true); + return; + case TranslateMenu.ID_OVERFLOW_NEVER_SITE: + nativeApplyBoolTranslateOption( + mNativeTranslateInfoBarPtr, TranslateOption.NEVER_TRANSLATE_SITE, true); + return; + } } private native void nativeApplyStringTranslateOption(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateSnackbarController.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateSnackbarController.java deleted file mode 100644 index 21db1ae..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateSnackbarController.java +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.infobar; - -import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController; - -/** - * The controller for translate UI snackbars. - */ -class TranslateSnackbarController implements SnackbarController { - @Override - public void onDismissNoAction(Object actionData) { - // No action. - } - - @Override - public void onAction(Object actionData) { - nativeToggleTranslateOption(((Long) actionData).longValue()); - } - - private native void nativeToggleTranslateOption(long nativeTranslateSnackbar); -};
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index e9b2afd1..261d895 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -474,7 +474,6 @@ "java/src/org/chromium/chrome/browser/infobar/TranslateNeverPanel.java", "java/src/org/chromium/chrome/browser/infobar/TranslateOptions.java", "java/src/org/chromium/chrome/browser/infobar/TranslateSubPanel.java", - "java/src/org/chromium/chrome/browser/infobar/TranslateSnackbarController.java", "java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java", "java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenu.java", "java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenuHelper.java",
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 28a0089..9092afd 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4150,7 +4150,6 @@ "../android/java/src/org/chromium/chrome/browser/infobar/SubresourceFilterInfoBar.java", "../android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java", "../android/java/src/org/chromium/chrome/browser/infobar/TranslateInfoBar.java", - "../android/java/src/org/chromium/chrome/browser/infobar/TranslateSnackbarController.java", "../android/java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java", "../android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsSettings.java", "../android/java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 6b4eb07..16a1c17 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1210,6 +1210,9 @@ {"top-chrome-md", flag_descriptions::kTopChromeMd, flag_descriptions::kTopChromeMdDescription, kOsDesktop, MULTI_VALUE_TYPE(kTopChromeMaterialDesignChoices)}, + {"enable-site-details", flag_descriptions::kSiteDetails, + flag_descriptions::kSiteDetailsDescription, kOsDesktop, + FEATURE_VALUE_TYPE(features::kSiteDetails)}, {"enable-site-settings", flag_descriptions::kSiteSettings, flag_descriptions::kSiteSettingsDescription, kOsDesktop, SINGLE_VALUE_TYPE(switches::kEnableSiteSettings)},
diff --git a/chrome/browser/chromeos/arc/arc_util.cc b/chrome/browser/chromeos/arc/arc_util.cc index 09a17372..70194d7 100644 --- a/chrome/browser/chromeos/arc/arc_util.cc +++ b/chrome/browser/chromeos/arc/arc_util.cc
@@ -246,7 +246,11 @@ DCHECK(!callback.is_null()); // If ARC is not available, skip the check. - if (!IsArcAvailable()) { + // This shortcut is just for merginally improving the log-in performance on + // old devices without ARC. We can always safely remove the following 4 lines + // without changing any functionality when, say, the code clarity becomes + // more important in the future. + if (!IsArcAvailable() && !IsArcKioskAvailable()) { callback.Run(); return; }
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 71e11e2d..71c0017a 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -243,6 +243,12 @@ const char kTopChromeMdMaterialHybrid[] = "Touch"; +const char kSiteDetails[] = "Site Details"; + +const char kSiteDetailsDescription[] = + "Adds UI in MD Settings to view all content settings for a specific " + "origin."; + const char kSiteSettings[] = "Site settings with All sites and Site details"; const char kSiteSettingsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 42d0adf..437edc3 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -252,6 +252,13 @@ // Top Chrome material hybrid design option (for touchscreens). extern const char kTopChromeMdMaterialHybrid[]; +// Title of the flag which enables site details in MD settings. +extern const char kSiteDetails[]; + +// Description of the flag which enables or disables site details in MD +// settings. +extern const char kSiteDetailsDescription[]; + // Title of the flag which enables the site settings all sites list and site // details. extern const char kSiteSettings[];
diff --git a/chrome/browser/resources/md_bookmarks/app.html b/chrome/browser/resources/md_bookmarks/app.html index 4d997e4..e35f026 100644 --- a/chrome/browser/resources/md_bookmarks/app.html +++ b/chrome/browser/resources/md_bookmarks/app.html
@@ -31,8 +31,17 @@ } #splitter { + box-sizing: border-box; cursor: e-resize; flex: 0 0 var(--splitter-width); + opacity: 0; + } + + #splitter:hover, + #splitter.splitter-active { + -webkit-border-start: 1px solid rgba(0, 0, 0, 0.1); + opacity: 1; + transition: opacity 100ms ease-out; } :host-context([dir='rtl']) #splitter {
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc index 9a465f5..5b84fda 100644 --- a/chrome/browser/search/instant_service.cc +++ b/chrome/browser/search/instant_service.cc
@@ -59,7 +59,7 @@ namespace { const base::Feature kNtpTilesFeature{"NTPTilesInInstantService", - base::FEATURE_ENABLED_BY_DEFAULT}; + base::FEATURE_DISABLED_BY_DEFAULT}; } // namespace
diff --git a/chrome/browser/ui/android/snackbars/translate_snackbar.cc b/chrome/browser/ui/android/snackbars/translate_snackbar.cc deleted file mode 100644 index fd7c8b1..0000000 --- a/chrome/browser/ui/android/snackbars/translate_snackbar.cc +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/android/snackbars/translate_snackbar.h" - -#include "base/memory/ptr_util.h" -#include "jni/TranslateSnackbarController_jni.h" - -TranslateSnackbar::TranslateSnackbar(int snackbar_type) { - type_ = snackbar_type; -} - -void TranslateSnackbar::ToggleTranslateOption( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj) { - // TODO(ramyasharma): Implement. -} - -// Native JNI methods ------------------------------------------------------- - -// static -bool RegisterTranslateSnackbar(JNIEnv* env) { - return RegisterNativesImpl(env); -}
diff --git a/chrome/browser/ui/android/snackbars/translate_snackbar.h b/chrome/browser/ui/android/snackbars/translate_snackbar.h deleted file mode 100644 index dce84997..0000000 --- a/chrome/browser/ui/android/snackbars/translate_snackbar.h +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_ANDROID_SNACKBARS_TRANSLATE_SNACKBAR_H_ -#define CHROME_BROWSER_UI_ANDROID_SNACKBARS_TRANSLATE_SNACKBAR_H_ - -#include <stddef.h> - -#include "base/android/jni_android.h" -#include "base/android/scoped_java_ref.h" -#include "base/macros.h" - -class TranslateSnackbar { - public: - explicit TranslateSnackbar(int snackbar_type); - - void ToggleTranslateOption(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj); - - private: - int type_; - - DISALLOW_COPY_AND_ASSIGN(TranslateSnackbar); -}; - -// Registers the native methods through JNI. -bool RegisterTranslateSnackbar(JNIEnv* env); - -#endif // CHROME_BROWSER_UI_ANDROID_SNACKBARS_TRANSLATE_SNACKBAR_H_
diff --git a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h index f05035b..76520037 100644 --- a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h +++ b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h
@@ -80,6 +80,7 @@ gfx::Rect GetClientAreaBoundsInScreen() const override; bool IsImmersiveModeEnabled() override; gfx::Rect GetTopContainerBoundsInScreen() override; + void DestroyAnyExclusiveAccessBubble() override; private: BrowserWindow* GetBrowserWindow() const;
diff --git a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm index cbe83eba..f60f66d5 100644 --- a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm +++ b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm
@@ -193,6 +193,11 @@ return gfx::Rect(); } +void ExclusiveAccessController::DestroyAnyExclusiveAccessBubble() { + Destroy(); + new_back_shortcut_bubble_.reset(); +} + BrowserWindow* ExclusiveAccessController::GetBrowserWindow() const { return [controller_ browserWindow]; }
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc index 55e44ee9..784d16d 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc
@@ -88,3 +88,10 @@ void FullscreenControllerTest::SetPrivilegedFullscreen(bool is_privileged) { GetFullscreenController()->SetPrivilegedFullscreenForTesting(is_privileged); } + +void FullscreenControllerTest::EnterActiveTabFullscreen() { + WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); + FullscreenNotificationObserver fullscreen_observer; + browser()->EnterFullscreenModeForTab(tab, GURL()); + fullscreen_observer.Wait(); +}
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h index ccf86e7b..daab667 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h
@@ -51,6 +51,8 @@ void GoBack(); void Reload(); void SetPrivilegedFullscreen(bool is_privileged); + void EnterActiveTabFullscreen(); + static const char kFullscreenMouseLockHTML[]; FullscreenController* GetFullscreenController(); ExclusiveAccessManager* GetExclusiveAccessManager();
diff --git a/chrome/browser/ui/views/collected_cookies_views.cc b/chrome/browser/ui/views/collected_cookies_views.cc index 0148bf2..6ba1064 100644 --- a/chrome/browser/ui/views/collected_cookies_views.cc +++ b/chrome/browser/ui/views/collected_cookies_views.cc
@@ -75,7 +75,7 @@ const int button_padding = provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL); const int button_size_limit = - provider->GetDistanceMetric(DISTANCE_BUTTON_MAX_LINKABLE_WIDTH); + provider->GetDistanceMetric(views::DISTANCE_BUTTON_MAX_LINKABLE_WIDTH); views::ColumnSet* column_set = layout->AddColumnSet(column_layout_id); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 0,
diff --git a/chrome/browser/ui/views/exclusive_access_bubble_views.cc b/chrome/browser/ui/views/exclusive_access_bubble_views.cc index b556c88..7040d6b 100644 --- a/chrome/browser/ui/views/exclusive_access_bubble_views.cc +++ b/chrome/browser/ui/views/exclusive_access_bubble_views.cc
@@ -282,6 +282,23 @@ UpdateMouseWatcher(); } +void ExclusiveAccessBubbleViews::OnWidgetDestroyed(views::Widget* widget) { + // Although SubtleNotificationView uses WIDGET_OWNS_NATIVE_WIDGET, a close can + // originate from the OS or some Chrome shutdown codepaths that bypass the + // destructor. + views::Widget* popup_on_stack = popup_; + DCHECK(popup_on_stack->HasObserver(this)); + + // Get ourselves destroyed. Calling ExitExclusiveAccess() won't work because + // the parent window might be destroyed as well, so asking it to exit + // fullscreen would be a bad idea. + bubble_view_context_->DestroyAnyExclusiveAccessBubble(); + + // Note: |this| is destroyed on the line above. Check that the destructor was + // invoked. This is safe to do since |popup_| is deleted via a posted task. + DCHECK(!popup_on_stack->HasObserver(this)); +} + void ExclusiveAccessBubbleViews::OnWidgetVisibilityChanged( views::Widget* widget, bool visible) {
diff --git a/chrome/browser/ui/views/exclusive_access_bubble_views.h b/chrome/browser/ui/views/exclusive_access_bubble_views.h index 46d06a7..fb93a95 100644 --- a/chrome/browser/ui/views/exclusive_access_bubble_views.h +++ b/chrome/browser/ui/views/exclusive_access_bubble_views.h
@@ -61,7 +61,7 @@ // Returns the root view containing |browser_view_|. views::View* GetBrowserRootView() const; - // ExclusiveAccessBubble overrides: + // ExclusiveAccessBubble: void AnimationProgressed(const gfx::Animation* animation) override; void AnimationEnded(const gfx::Animation* animation) override; gfx::Rect GetPopupRect(bool ignore_animation_state) const override; @@ -73,12 +73,13 @@ bool IsAnimating() override; bool CanMouseTriggerSlideIn() const override; - // content::NotificationObserver override: + // content::NotificationObserver: void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) override; - // views::WidgetObserver override: + // views::WidgetObserver: + void OnWidgetDestroyed(views::Widget* widget) override; void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override; // views::LinkListener override:
diff --git a/chrome/browser/ui/views/exclusive_access_bubble_views_context.h b/chrome/browser/ui/views/exclusive_access_bubble_views_context.h index d2300ea..e5da3b36 100644 --- a/chrome/browser/ui/views/exclusive_access_bubble_views_context.h +++ b/chrome/browser/ui/views/exclusive_access_bubble_views_context.h
@@ -47,6 +47,11 @@ // Returns the bounds of the top level View in screen coordinate system. virtual gfx::Rect GetTopContainerBoundsInScreen() = 0; + + // Destroy any exclusive access bubble. This allows the bubble to ask its + // owner to clean up when the bubble observes its native widget being + // destroyed before the owner requested it. + virtual void DestroyAnyExclusiveAccessBubble() = 0; }; #endif // CHROME_BROWSER_UI_VIEWS_EXCLUSIVE_ACCESS_BUBBLE_VIEWS_CONTEXT_H_
diff --git a/chrome/browser/ui/views/exclusive_access_bubble_views_interactive_uitest.cc b/chrome/browser/ui/views/exclusive_access_bubble_views_interactive_uitest.cc new file mode 100644 index 0000000..71f3942d --- /dev/null +++ b/chrome/browser/ui/views/exclusive_access_bubble_views_interactive_uitest.cc
@@ -0,0 +1,61 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/exclusive_access/fullscreen_controller_test.h" +#include "chrome/browser/ui/views/exclusive_access_bubble_views.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_observer.h" + +class ExclusiveAccessBubbleViewsTest : public FullscreenControllerTest, + public views::WidgetObserver { + public: + ExclusiveAccessBubbleViewsTest() {} + + ExclusiveAccessBubbleViews* bubble() { + BrowserView* browser_view = + BrowserView::GetBrowserViewForBrowser(browser()); + return browser_view->exclusive_access_bubble(); + } + + // WidgetObserver: + void OnWidgetDestroying(views::Widget* widget) override { + was_observing_in_destroying_ = widget->HasObserver(bubble()); + was_destroying_ = true; + widget->RemoveObserver(this); + } + + protected: + bool was_destroying_ = false; + bool was_observing_in_destroying_ = false; + + private: + DISALLOW_COPY_AND_ASSIGN(ExclusiveAccessBubbleViewsTest); +}; + +// Simulate obscure codepaths resulting in the bubble Widget being closed before +// the ExclusiveAccessBubbleViews destructor asks for it. If a close bypasses +// the destructor, animations could still be running that attempt to manipulate +// a destroyed Widget and crash. +IN_PROC_BROWSER_TEST_F(ExclusiveAccessBubbleViewsTest, NativeClose) { + EXPECT_FALSE(bubble()); + EnterActiveTabFullscreen(); + EXPECT_TRUE(bubble()); + + bubble()->GetView()->GetWidget()->AddObserver(this); + + // Simulate the bubble being closed out from under its controller, which seems + // to happen in some odd corner cases, like system log-off while the bubble is + // showing. + bubble()->GetView()->GetWidget()->CloseNow(); + EXPECT_FALSE(bubble()); + + // Verify that teardown is really happening via OnWidgetDestroyed() rather + // than the usual path via the ExclusiveAccessBubbleViews destructor. Since + // the destructor always first removes ExclusiveAccessBubbleViews as an + // observer before starting the close, checking in OnWidgetDestroyed that it's + // still observing achieves this. + EXPECT_TRUE(was_observing_in_destroying_); + EXPECT_TRUE(was_destroying_); +}
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 66f94a6..cd473a1 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -2694,6 +2694,11 @@ return top_container_->GetBoundsInScreen(); } +void BrowserView::DestroyAnyExclusiveAccessBubble() { + exclusive_access_bubble_.reset(); + new_back_shortcut_bubble_.reset(); +} + extensions::ActiveTabPermissionGranter* BrowserView::GetActiveTabPermissionGranter() { content::WebContents* web_contents = GetActiveWebContents();
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index c1a2b41..c79b85cb 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -465,6 +465,7 @@ gfx::Rect GetClientAreaBoundsInScreen() const override; bool IsImmersiveModeEnabled() override; gfx::Rect GetTopContainerBoundsInScreen() override; + void DestroyAnyExclusiveAccessBubble() override; // extension::ExtensionKeybindingRegistry::Delegate overrides extensions::ActiveTabPermissionGranter* GetActiveTabPermissionGranter()
diff --git a/chrome/browser/ui/views/harmony/chrome_layout_provider.cc b/chrome/browser/ui/views/harmony/chrome_layout_provider.cc index dd6b727b..6bb3edf 100644 --- a/chrome/browser/ui/views/harmony/chrome_layout_provider.cc +++ b/chrome/browser/ui/views/harmony/chrome_layout_provider.cc
@@ -26,8 +26,6 @@ int ChromeLayoutProvider::GetDistanceMetric(int metric) const { switch (metric) { - case DISTANCE_BUTTON_MAX_LINKABLE_WIDTH: - return 0; case DISTANCE_BUTTON_MINIMUM_WIDTH: return views::kMinimumButtonWidth; case DISTANCE_CONTROL_LIST_VERTICAL:
diff --git a/chrome/browser/ui/views/harmony/chrome_layout_provider.h b/chrome/browser/ui/views/harmony/chrome_layout_provider.h index b78c155..18be5ff 100644 --- a/chrome/browser/ui/views/harmony/chrome_layout_provider.h +++ b/chrome/browser/ui/views/harmony/chrome_layout_provider.h
@@ -13,12 +13,8 @@ #include "ui/views/layout/layout_provider.h" enum ChromeDistanceMetric { - // The maximum width a button can have and still influence the sizes of - // other linked buttons. This allows short buttons to have linked widths - // without long buttons making things overly wide. - DISTANCE_BUTTON_MAX_LINKABLE_WIDTH = views::VIEWS_DISTANCE_END, // Default minimum width of a button. - DISTANCE_BUTTON_MINIMUM_WIDTH, + DISTANCE_BUTTON_MINIMUM_WIDTH = views::VIEWS_DISTANCE_END, // Vertical spacing between a list of multiple controls in one column. DISTANCE_CONTROL_LIST_VERTICAL, // Margin between the edge of a dialog and the left, right, or bottom of a
diff --git a/chrome/browser/ui/views/harmony/harmony_layout_provider.cc b/chrome/browser/ui/views/harmony/harmony_layout_provider.cc index d9dbd4df..d11ef463 100644 --- a/chrome/browser/ui/views/harmony/harmony_layout_provider.cc +++ b/chrome/browser/ui/views/harmony/harmony_layout_provider.cc
@@ -57,8 +57,8 @@ 2 * GetDistanceMetric(views::DISTANCE_BUTTON_HORIZONTAL_PADDING); case views::DISTANCE_BUTTON_HORIZONTAL_PADDING: return kHarmonyLayoutUnit; - case DISTANCE_BUTTON_MAX_LINKABLE_WIDTH: - return kHarmonyLayoutUnit * 8; + case views::DISTANCE_BUTTON_MAX_LINKABLE_WIDTH: + return kHarmonyLayoutUnit * 7; case DISTANCE_RELATED_LABEL_HORIZONTAL: return kHarmonyLayoutUnit; case DISTANCE_SUBSECTION_HORIZONTAL_INDENT:
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc index b5eb4956..73b462d 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -217,6 +217,7 @@ // views::BubbleDialogDelegateView: void OnWidgetDestroying(views::Widget* widget) override; int GetDialogButtons() const override; + bool ShouldSnapFrameWidth() const override; private: friend class PageInfoBubbleView; @@ -378,6 +379,10 @@ return ui::DIALOG_BUTTON_NONE; } +bool InternalPageInfoBubbleView::ShouldSnapFrameWidth() const { + return false; +} + //////////////////////////////////////////////////////////////////////////////// // PageInfoBubbleView ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index ecd94eb1..7cd2d31c 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -300,6 +300,11 @@ const base::Feature kSimplifiedFullscreenUI{"ViewsSimplifiedFullscreenUI", base::FEATURE_ENABLED_BY_DEFAULT}; +// Enables or disables UI in MD Settings to view content settings grouped by +// origin. +const base::Feature kSiteDetails{"SiteDetails", + base::FEATURE_DISABLED_BY_DEFAULT}; + #if defined(SYZYASAN) // Enable the deferred free mechanism in the syzyasan module, which helps the // performance by deferring some work on the critical path to a background
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index d6ecedc8..4aae3c88 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -164,6 +164,8 @@ extern const base::Feature kSimplifiedFullscreenUI; +extern const base::Feature kSiteDetails; + #if defined(SYZYASAN) extern const base::Feature kSyzyasanDeferredFree; #endif
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index b2916324..129e8c84 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -542,6 +542,7 @@ "../browser/ui/views/bookmarks/bookmark_bar_view_test_helper.h", "../browser/ui/views/certificate_selector_browsertest.cc", "../browser/ui/views/constrained_window_views_browsertest.cc", + "../browser/ui/views/exclusive_access_bubble_views_interactive_uitest.cc", "../browser/ui/views/extensions/extension_dialog_interactive_uitest.cc", "../browser/ui/views/find_bar_views_interactive_uitest.cc", "../browser/ui/views/frame/browser_view_focus_uitest.cc",
diff --git a/components/content_settings/core/browser/BUILD.gn b/components/content_settings/core/browser/BUILD.gn index 3e4fa66..44e44e3 100644 --- a/components/content_settings/core/browser/BUILD.gn +++ b/components/content_settings/core/browser/BUILD.gn
@@ -54,6 +54,7 @@ "//components/url_formatter", "//extensions/features", "//net", + "//services/preferences/public/cpp", "//url", ]
diff --git a/components/content_settings/core/browser/DEPS b/components/content_settings/core/browser/DEPS index eddae7b..01dbe2a 100644 --- a/components/content_settings/core/browser/DEPS +++ b/components/content_settings/core/browser/DEPS
@@ -8,4 +8,5 @@ "+extensions/features", "+net/base", "+net/cookies", + "+services/preferences/public", ]
diff --git a/components/content_settings/core/browser/content_settings_pref.cc b/components/content_settings/core/browser/content_settings_pref.cc index d1bf46e..d26b155 100644 --- a/components/content_settings/core/browser/content_settings_pref.cc +++ b/components/content_settings/core/browser/content_settings_pref.cc
@@ -8,6 +8,7 @@ #include "base/auto_reset.h" #include "base/bind.h" +#include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" @@ -20,6 +21,8 @@ #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/pref_names.h" #include "components/prefs/scoped_user_pref_update.h" +#include "services/preferences/public/cpp/dictionary_value_update.h" +#include "services/preferences/public/cpp/scoped_pref_update.h" #include "url/gurl.h" namespace { @@ -179,9 +182,8 @@ { base::AutoReset<bool> auto_reset(&updating_preferences_, true); - DictionaryPrefUpdate update(prefs_, pref_name_); - base::DictionaryValue* pattern_pairs_settings = update.Get(); - pattern_pairs_settings->Clear(); + prefs::ScopedDictionaryPrefUpdate update(prefs_, pref_name_); + update->Clear(); } } @@ -214,13 +216,13 @@ } void ContentSettingsPref::ReadContentSettingsFromPref() { - // |DictionaryPrefUpdate| sends out notifications when destructed. This + // |ScopedDictionaryPrefUpdate| sends out notifications when destructed. This // construction order ensures |AutoLock| gets destroyed first and |lock_| is // not held when the notifications are sent. Also, |auto_reset| must be still // valid when the notifications are sent, so that |Observe| skips the // notification. base::AutoReset<bool> auto_reset(&updating_preferences_, true); - DictionaryPrefUpdate update(prefs_, pref_name_); + prefs::ScopedDictionaryPrefUpdate update(prefs_, pref_name_); base::AutoLock auto_lock(lock_); const base::DictionaryValue* all_settings_dictionary = @@ -233,23 +235,26 @@ if (!all_settings_dictionary) return; - base::DictionaryValue* mutable_settings; - std::unique_ptr<base::DictionaryValue> mutable_settings_scope; + const base::DictionaryValue* settings; if (!is_incognito_) { - mutable_settings = update.Get(); + // Convert all Unicode patterns into punycode form, then read. + auto mutable_settings = update.Get(); + CanonicalizeContentSettingsExceptions(mutable_settings.get()); + settings = mutable_settings->AsConstDictionary(); } else { - // Create copy as we do not want to persist anything in incognito prefs. - mutable_settings = all_settings_dictionary->DeepCopy(); - mutable_settings_scope.reset(mutable_settings); + // Canonicalization is unnecessary when |is_incognito_|. Both incognito and + // non-incognito read from the same pref and non-incognito reads occur + // before incognito reads. Thus, by the time the incognito call to + // ReadContentSettingsFromPref() occurs, the non-incognito call will have + // canonicalized the stored pref data. + settings = all_settings_dictionary; } - // Convert all Unicode patterns into punycode form, then read. - CanonicalizeContentSettingsExceptions(mutable_settings); size_t cookies_block_exception_count = 0; size_t cookies_allow_exception_count = 0; size_t cookies_session_only_exception_count = 0; - for (base::DictionaryValue::Iterator i(*mutable_settings); !i.IsAtEnd(); + for (base::DictionaryValue::Iterator i(*settings); !i.IsAtEnd(); i.Advance()) { const std::string& pattern_str(i.key()); std::pair<ContentSettingsPattern, ContentSettingsPattern> pattern_pair = @@ -349,39 +354,41 @@ const base::Time last_modified, const base::Value* value) { // Ensure that |lock_| is not held by this thread, since this function will - // send out notifications (by |~DictionaryPrefUpdate|). + // send out notifications (by |~ScopedDictionaryPrefUpdate|). AssertLockNotHeld(); base::AutoReset<bool> auto_reset(&updating_preferences_, true); { - DictionaryPrefUpdate update(prefs_, pref_name_); - base::DictionaryValue* pattern_pairs_settings = update.Get(); + prefs::ScopedDictionaryPrefUpdate update(prefs_, pref_name_); + std::unique_ptr<prefs::DictionaryValueUpdate> pattern_pairs_settings = + update.Get(); // Get settings dictionary for the given patterns. std::string pattern_str(CreatePatternString(primary_pattern, secondary_pattern)); - base::DictionaryValue* settings_dictionary = nullptr; + std::unique_ptr<prefs::DictionaryValueUpdate> settings_dictionary; bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( pattern_str, &settings_dictionary); if (!found && value) { - settings_dictionary = new base::DictionaryValue; - pattern_pairs_settings->SetWithoutPathExpansion( - pattern_str, settings_dictionary); + settings_dictionary = + pattern_pairs_settings->SetDictionaryWithoutPathExpansion( + pattern_str, base::MakeUnique<base::DictionaryValue>()); } if (settings_dictionary) { if (SupportsResourceIdentifiers(content_type_) && !resource_identifier.empty()) { - base::DictionaryValue* resource_dictionary = nullptr; + std::unique_ptr<prefs::DictionaryValueUpdate> resource_dictionary; found = settings_dictionary->GetDictionary( kPerResourceIdentifierPrefName, &resource_dictionary); if (!found) { if (value == nullptr) return; // Nothing to remove. Exit early. - resource_dictionary = new base::DictionaryValue; - settings_dictionary->Set( - kPerResourceIdentifierPrefName, resource_dictionary); + resource_dictionary = + settings_dictionary->SetDictionaryWithoutPathExpansion( + kPerResourceIdentifierPrefName, + base::MakeUnique<base::DictionaryValue>()); } // Update resource dictionary. if (value == nullptr) { @@ -394,8 +401,8 @@ nullptr); } } else { - resource_dictionary->SetWithoutPathExpansion( - resource_identifier, value->DeepCopy()); + resource_dictionary->SetWithoutPathExpansion(resource_identifier, + value->CreateDeepCopy()); // Update timestamp for whole resource dictionary. settings_dictionary->SetStringWithoutPathExpansion( kLastModifiedPath, @@ -409,8 +416,8 @@ settings_dictionary->RemoveWithoutPathExpansion(kLastModifiedPath, nullptr); } else { - settings_dictionary->SetWithoutPathExpansion( - kSettingPath, value->DeepCopy()); + settings_dictionary->SetWithoutPathExpansion(kSettingPath, + value->CreateDeepCopy()); settings_dictionary->SetStringWithoutPathExpansion( kLastModifiedPath, base::Int64ToString(last_modified.ToInternalValue())); @@ -427,14 +434,14 @@ // static void ContentSettingsPref::CanonicalizeContentSettingsExceptions( - base::DictionaryValue* all_settings_dictionary) { + prefs::DictionaryValueUpdate* all_settings_dictionary) { DCHECK(all_settings_dictionary); std::vector<std::string> remove_items; base::StringPairs move_items; - for (base::DictionaryValue::Iterator i(*all_settings_dictionary); - !i.IsAtEnd(); - i.Advance()) { + for (base::DictionaryValue::Iterator i( + *all_settings_dictionary->AsConstDictionary()); + !i.IsAtEnd(); i.Advance()) { const std::string& pattern_str(i.key()); std::pair<ContentSettingsPattern, ContentSettingsPattern> pattern_pair = ParsePatternString(pattern_str); @@ -478,7 +485,7 @@ all_settings_dictionary->RemoveWithoutPathExpansion( move_items[i].first, &pattern_settings_dictionary); all_settings_dictionary->SetWithoutPathExpansion( - move_items[i].second, pattern_settings_dictionary.release()); + move_items[i].second, std::move(pattern_settings_dictionary)); } }
diff --git a/components/content_settings/core/browser/content_settings_pref.h b/components/content_settings/core/browser/content_settings_pref.h index 356176c6..697425d4 100644 --- a/components/content_settings/core/browser/content_settings_pref.h +++ b/components/content_settings/core/browser/content_settings_pref.h
@@ -23,8 +23,8 @@ class PrefService; class PrefChangeRegistrar; -namespace base { -class DictionaryValue; +namespace prefs { +class DictionaryValueUpdate; } namespace content_settings { @@ -92,7 +92,7 @@ const base::Value* value); static void CanonicalizeContentSettingsExceptions( - base::DictionaryValue* all_settings_dictionary); + prefs::DictionaryValueUpdate* all_settings_dictionary); // In the debug mode, asserts that |lock_| is not held by this thread. It's // ok if some other thread holds |lock_|, as long as it will eventually
diff --git a/components/content_settings/core/browser/content_settings_pref_provider.cc b/components/content_settings/core/browser/content_settings_pref_provider.cc index 98ab6245d..e7ac35f3c 100644 --- a/components/content_settings/core/browser/content_settings_pref_provider.cc +++ b/components/content_settings/core/browser/content_settings_pref_provider.cc
@@ -28,6 +28,8 @@ #include "components/prefs/pref_registry.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" +#include "services/preferences/public/cpp/dictionary_value_update.h" +#include "services/preferences/public/cpp/scoped_pref_update.h" namespace content_settings { @@ -252,11 +254,11 @@ if (!prefs_->GetDictionary(info->pref_name())) continue; - DictionaryPrefUpdate update(prefs_, info->pref_name()); - base::DictionaryValue* all_settings = update.Get(); + prefs::ScopedDictionaryPrefUpdate update(prefs_, info->pref_name()); + auto all_settings = update.Get(); std::vector<std::string> values_to_clean; - for (base::DictionaryValue::Iterator i(*all_settings); !i.IsAtEnd(); - i.Advance()) { + for (base::DictionaryValue::Iterator i(*all_settings->AsConstDictionary()); + !i.IsAtEnd(); i.Advance()) { const base::DictionaryValue* pattern_settings = nullptr; bool is_dictionary = i.value().GetAsDictionary(&pattern_settings); DCHECK(is_dictionary); @@ -265,7 +267,7 @@ } for (const std::string& key : values_to_clean) { - base::DictionaryValue* pattern_settings = nullptr; + std::unique_ptr<prefs::DictionaryValueUpdate> pattern_settings; all_settings->GetDictionaryWithoutPathExpansion(key, &pattern_settings); pattern_settings->RemoveWithoutPathExpansion(kObsoleteLastUsed, nullptr); if (pattern_settings->empty())
diff --git a/components/subresource_filter/core/common/url_pattern_index_unittest.cc b/components/subresource_filter/core/common/url_pattern_index_unittest.cc index 1052d5ba..fcdb9da 100644 --- a/components/subresource_filter/core/common/url_pattern_index_unittest.cc +++ b/components/subresource_filter/core/common/url_pattern_index_unittest.cc
@@ -4,6 +4,7 @@ #include "components/subresource_filter/core/common/url_pattern_index.h" +#include <algorithm> #include <memory> #include <string> #include <vector> @@ -54,6 +55,14 @@ IsThirdParty(url, document_origin), disable_generic_rules); } + bool IsOutOfRange(const flat::UrlRule* rule) const { + if (!rule) + return false; + const auto* data = reinterpret_cast<const uint8_t*>(rule); + return data < flat_builder_->GetBufferPointer() || + data >= flat_builder_->GetBufferPointer() + flat_builder_->GetSize(); + } + void Reset() { index_matcher_.reset(); index_builder_.reset(); @@ -665,4 +674,34 @@ FindMatch("http://example.com", nullptr, kNoElement, kGenericBlock)); } +TEST_F(UrlPatternIndexTest, FindMatchReturnsCorrectRules) { + constexpr size_t kNumOfPatterns = 1024; + + std::vector<std::string> url_patterns(kNumOfPatterns); + for (size_t i = 0; i < kNumOfPatterns; ++i) { + url_patterns[i] = "http://example." + std::to_string(i) + ".com"; + ASSERT_TRUE( + AddUrlRule(MakeUrlRule(UrlPattern(url_patterns[i], kSubstring)))) + << "Rule #" << i; + } + Finish(); + + std::reverse(url_patterns.begin() + kNumOfPatterns / 2, url_patterns.end()); + for (const std::string& url_pattern : url_patterns) { + SCOPED_TRACE(::testing::Message() << "UrlPattern: " << url_pattern); + + const flat::UrlRule* rule = FindMatch(url_pattern); + ASSERT_TRUE(rule); + ASSERT_FALSE(IsOutOfRange(rule)); + + const flatbuffers::String* rule_pattern = rule->url_pattern(); + ASSERT_TRUE(rule_pattern); + EXPECT_EQ(url_pattern, + base::StringPiece(rule_pattern->data(), rule_pattern->size())); + } + + EXPECT_FALSE( + FindMatch("http://example." + std::to_string(kNumOfPatterns) + ".com")); +} + } // namespace subresource_filter
diff --git a/components/suggestions/suggestions_service_impl.cc b/components/suggestions/suggestions_service_impl.cc index 6e41445d..5a013c8 100644 --- a/components/suggestions/suggestions_service_impl.cc +++ b/components/suggestions/suggestions_service_impl.cc
@@ -46,37 +46,6 @@ namespace { -// Establishes the different sync states that matter to SuggestionsService. -// There are three different concepts in the sync service: initialized, sync -// enabled and history sync enabled. -enum SyncState { - // State: Sync service is not initialized, yet not disabled. History sync - // state is unknown (since not initialized). - // Behavior: Does not issue a server request, but serves from cache if - // available. - NOT_INITIALIZED_ENABLED, - - // State: Sync service is initialized, sync is enabled and history sync is - // enabled. - // Behavior: Update suggestions from the server. Serve from cache on timeout. - INITIALIZED_ENABLED_HISTORY, - - // State: Sync service is disabled or history sync is disabled. - // Behavior: Do not issue a server request. Clear the cache. Serve empty - // suggestions. - SYNC_OR_HISTORY_SYNC_DISABLED, -}; - -SyncState GetSyncState(syncer::SyncService* sync) { - if (!sync || !sync->CanSyncStart() || sync->IsLocalSyncEnabled()) - return SYNC_OR_HISTORY_SYNC_DISABLED; - if (!sync->IsSyncActive() || !sync->ConfigurationDone()) - return NOT_INITIALIZED_ENABLED; - return sync->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES) - ? INITIALIZED_ENABLED_HISTORY - : SYNC_OR_HISTORY_SYNC_DISABLED; -} - // Used to UMA log the state of the last response from the server. enum SuggestionsResponseState { RESPONSE_EMPTY, @@ -150,6 +119,7 @@ token_service_(token_service), sync_service_(sync_service), sync_service_observer_(this), + sync_state_(INITIALIZED_ENABLED_HISTORY), url_request_context_(url_request_context), suggestions_store_(std::move(suggestions_store)), thumbnail_manager_(std::move(thumbnail_manager)), @@ -157,8 +127,9 @@ scheduling_delay_(TimeDelta::FromSeconds(kDefaultSchedulingDelaySec)), weak_ptr_factory_(this) { // |sync_service_| is null if switches::kDisableSync is set (tests use that). - if (sync_service_) + if (sync_service_) { sync_service_observer_.Add(sync_service_); + } // Immediately get the current sync state, so we'll flush the cache if // necessary. OnStateChanged(sync_service_); @@ -169,8 +140,9 @@ bool SuggestionsServiceImpl::FetchSuggestionsData() { DCHECK(thread_checker_.CalledOnValidThread()); // If sync state allows, issue a network request to refresh the suggestions. - if (GetSyncState(sync_service_) != INITIALIZED_ENABLED_HISTORY) + if (sync_state_ != INITIALIZED_ENABLED_HISTORY) { return false; + } IssueRequestIfNoneOngoing(BuildSuggestionsURL()); return true; } @@ -300,8 +272,38 @@ kDeviceType)); } +SuggestionsServiceImpl::SyncState SuggestionsServiceImpl::ComputeSyncState() + const { + if (!sync_service_ || !sync_service_->CanSyncStart() || + sync_service_->IsLocalSyncEnabled()) { + return SYNC_OR_HISTORY_SYNC_DISABLED; + } + if (!sync_service_->IsSyncActive() || !sync_service_->ConfigurationDone()) { + return NOT_INITIALIZED_ENABLED; + } + return sync_service_->GetActiveDataTypes().Has( + syncer::HISTORY_DELETE_DIRECTIVES) + ? INITIALIZED_ENABLED_HISTORY + : SYNC_OR_HISTORY_SYNC_DISABLED; +} + +bool SuggestionsServiceImpl::RefreshSyncState() { + SyncState new_sync_state = ComputeSyncState(); + if (sync_state_ == new_sync_state) { + return false; + } + sync_state_ = new_sync_state; + return true; +} + void SuggestionsServiceImpl::OnStateChanged(syncer::SyncService* sync) { - switch (GetSyncState(sync_service_)) { + DCHECK(sync_service_ == sync); + + if (!RefreshSyncState()) { + return; + } + + switch (sync_state_) { case SYNC_OR_HISTORY_SYNC_DISABLED: // Cancel any ongoing request, to stop interacting with the server. pending_request_.reset(nullptr);
diff --git a/components/suggestions/suggestions_service_impl.h b/components/suggestions/suggestions_service_impl.h index dac972d..ee0b2fd 100644 --- a/components/suggestions/suggestions_service_impl.h +++ b/components/suggestions/suggestions_service_impl.h
@@ -87,6 +87,11 @@ private: friend class SuggestionsServiceTest; FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, FetchSuggestionsData); + FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, IgnoresNoopSyncChange); + FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, + IgnoresUninterestingSyncChange); + FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, + FetchSuggestionsDataSyncNotInitializedEnabled); FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, FetchSuggestionsDataSyncDisabled); FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, @@ -104,6 +109,25 @@ FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, UpdateBlacklistDelay); FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, CheckDefaultTimeStamps); + // Establishes the different sync states that matter to SuggestionsService. + enum SyncState { + // State: Sync service is not initialized, yet not disabled. History sync + // state is unknown (since not initialized). + // Behavior: Do not issue server requests, but serve from cache if + // available. + NOT_INITIALIZED_ENABLED, + + // State: Sync service is initialized, sync is enabled and history sync is + // enabled. + // Behavior: Update suggestions from the server on FetchSuggestionsData(). + INITIALIZED_ENABLED_HISTORY, + + // State: Sync service is disabled or history sync is disabled. + // Behavior: Do not issue server requests. Clear the cache. Serve empty + // suggestions. + SYNC_OR_HISTORY_SYNC_DISABLED, + }; + // Helpers to build the various suggestions URLs. These are static members // rather than local functions in the .cc file to make them accessible to // tests. @@ -112,6 +136,13 @@ static GURL BuildSuggestionsBlacklistURL(const GURL& candidate_url); static GURL BuildSuggestionsBlacklistClearURL(); + // Computes the appropriate SyncState from |sync_service_|. + SyncState ComputeSyncState() const; + + // Re-computes |sync_state_| from the sync service. Returns whether + // |sync_state_| was changed. + bool RefreshSyncState(); + // syncer::SyncServiceObserver implementation. void OnStateChanged(syncer::SyncService* sync) override; @@ -173,6 +204,8 @@ ScopedObserver<syncer::SyncService, syncer::SyncServiceObserver> sync_service_observer_; + SyncState sync_state_; + net::URLRequestContextGetter* url_request_context_; // The cache for the suggestions.
diff --git a/components/suggestions/suggestions_service_impl_unittest.cc b/components/suggestions/suggestions_service_impl_unittest.cc index 217303e..2a9ab77 100644 --- a/components/suggestions/suggestions_service_impl_unittest.cc +++ b/components/suggestions/suggestions_service_impl_unittest.cc
@@ -339,11 +339,59 @@ EXPECT_EQ(kTestFaviconUrl, suggestions_profile.suggestions(0).favicon_url()); } +TEST_F(SuggestionsServiceTest, IgnoresNoopSyncChange) { + std::unique_ptr<SuggestionsServiceImpl> suggestions_service( + CreateSuggestionsServiceWithMocks()); + auto subscription = suggestions_service->AddCallback(base::Bind( + &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); + + SuggestionsProfile suggestions_profile = CreateSuggestionsProfile(); + factory_.SetFakeResponse(SuggestionsServiceImpl::BuildSuggestionsURL(), + suggestions_profile.SerializeAsString(), + net::HTTP_OK, net::URLRequestStatus::SUCCESS); + + // An no-op change should not result in a suggestions refresh. + suggestions_service->OnStateChanged(mock_sync_service_.get()); + + // Let any network request run (there shouldn't be one). + base::RunLoop().RunUntilIdle(); + + // Ensure that we weren't called back. + EXPECT_EQ(0, suggestions_data_callback_count_); +} + +TEST_F(SuggestionsServiceTest, IgnoresUninterestingSyncChange) { + std::unique_ptr<SuggestionsServiceImpl> suggestions_service( + CreateSuggestionsServiceWithMocks()); + auto subscription = suggestions_service->AddCallback(base::Bind( + &SuggestionsServiceTest::CheckCallback, base::Unretained(this))); + + SuggestionsProfile suggestions_profile = CreateSuggestionsProfile(); + factory_.SetFakeResponse(SuggestionsServiceImpl::BuildSuggestionsURL(), + suggestions_profile.SerializeAsString(), + net::HTTP_OK, net::URLRequestStatus::SUCCESS); + + // An uninteresting change should not result in a network request (the + // SyncState is INITIALIZED_ENABLED_HISTORY before and after). + EXPECT_CALL(*mock_sync_service_, GetActiveDataTypes()) + .Times(AnyNumber()) + .WillRepeatedly(Return(syncer::ModelTypeSet( + syncer::HISTORY_DELETE_DIRECTIVES, syncer::BOOKMARKS))); + suggestions_service->OnStateChanged(mock_sync_service_.get()); + + // Let any network request run (there shouldn't be one). + base::RunLoop().RunUntilIdle(); + + // Ensure that we weren't called back. + EXPECT_EQ(0, suggestions_data_callback_count_); +} + TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncNotInitializedEnabled) { - std::unique_ptr<SuggestionsService> suggestions_service( + std::unique_ptr<SuggestionsServiceImpl> suggestions_service( CreateSuggestionsServiceWithMocks()); EXPECT_CALL(*mock_sync_service_, IsSyncActive()) .WillRepeatedly(Return(false)); + suggestions_service->OnStateChanged(mock_sync_service_.get()); auto subscription = suggestions_service->AddCallback(base::Bind( &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 3c7f850..78376e1 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -556,6 +556,7 @@ // The background color of the web content. This color will be drawn when the // web content is not able to draw in time. SkColor background_color_ = SK_ColorTRANSPARENT; + SkColor last_frame_root_background_color_ = SK_ColorTRANSPARENT; // Factory used to safely scope delayed calls to ShutdownHost(). base::WeakPtrFactory<RenderWidgetHostViewMac> weak_factory_;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 1e60855..e9ff56d 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -426,6 +426,12 @@ } void RenderWidgetHostViewMac::AcceleratedWidgetSwapCompleted() { + // Set the background color for the root layer from the frame that just + // swapped. See RenderWidgetHostViewAura for more details. Note that this is + // done only after the swap has completed, so that the background is not set + // before the frame is up. + UpdateBackgroundColorFromRenderer(last_frame_root_background_color_); + if (display_link_) display_link_->NotifyCurrentTime(base::TimeTicks::Now()); } @@ -1423,10 +1429,7 @@ cc::CompositorFrame frame) { TRACE_EVENT0("browser", "RenderWidgetHostViewMac::OnSwapCompositorFrame"); - // Override the compositor background color. See RenderWidgetHostViewAura - // for more details. - UpdateBackgroundColorFromRenderer(frame.metadata.root_background_color); - + last_frame_root_background_color_ = frame.metadata.root_background_color; last_scroll_offset_ = frame.metadata.root_scroll_offset; page_at_minimum_scale_ =
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn index 334aee2..a3c8d33 100644 --- a/ios/web_view/BUILD.gn +++ b/ios/web_view/BUILD.gn
@@ -24,6 +24,8 @@ "public/cwv_html_element.h", "public/cwv_navigation_action.h", "public/cwv_navigation_delegate.h", + "public/cwv_scroll_view.h", + "public/cwv_scroll_view_delegate.h", "public/cwv_translate_delegate.h", "public/cwv_translate_manager.h", "public/cwv_ui_delegate.h", @@ -38,6 +40,8 @@ "internal/cwv_html_element_internal.h", "internal/cwv_navigation_action.mm", "internal/cwv_navigation_action_internal.h", + "internal/cwv_scroll_view.mm", + "internal/cwv_scroll_view_internal.h", "internal/cwv_user_content_controller.mm", "internal/cwv_user_content_controller_internal.h", "internal/cwv_user_script.mm",
diff --git a/ios/web_view/internal/cwv_scroll_view.mm b/ios/web_view/internal/cwv_scroll_view.mm new file mode 100644 index 0000000..53dc5d8c --- /dev/null +++ b/ios/web_view/internal/cwv_scroll_view.mm
@@ -0,0 +1,116 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web_view/public/cwv_scroll_view.h" + +#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h" +#import "ios/web_view/internal/cwv_scroll_view_internal.h" +#import "ios/web_view/public/cwv_scroll_view_delegate.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface CWVScrollView ()<CRWWebViewScrollViewProxyObserver> + +// For KVO compliance, redefines the property as readwrite and calls its setter +// when the value changes, instead of defining a getter which directly calls +// _proxy.contentSize. +@property(nonatomic, readwrite) CGSize contentSize; + +@end + +@implementation CWVScrollView + +@synthesize contentSize = _contentSize; +@synthesize delegate = _delegate; +@synthesize proxy = _proxy; + +- (void)setProxy:(nullable CRWWebViewScrollViewProxy*)proxy { + [_proxy removeObserver:self]; + _proxy = proxy; + self.contentSize = _proxy.contentSize; + [_proxy addObserver:self]; +} + +- (CGPoint)contentOffset { + return _proxy.contentOffset; +} + +- (void)setContentOffset:(CGPoint)contentOffset { + _proxy.contentOffset = contentOffset; +} + +- (CGRect)bounds { + return {_proxy.contentOffset, _proxy.frame.size}; +} + +- (BOOL)isDragging { + return _proxy.dragging; +} + +- (UIEdgeInsets)contentInset { + return _proxy.contentInset; +} + +- (void)setContentInset:(UIEdgeInsets)contentInset { + _proxy.contentInset = contentInset; +} + +- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer { + [_proxy addGestureRecognizer:gestureRecognizer]; +} + +#pragma mark - NSObject + +- (void)dealloc { + // Removes |self| from |_proxy|'s observers. Otherwise |_proxy| will keep a + // dangling pointer to |self| and cause SEGV later. + [_proxy removeObserver:self]; +} + +#pragma mark - CRWWebViewScrollViewObserver + +- (void)webViewScrollViewWillBeginDragging: + (CRWWebViewScrollViewProxy*)webViewScrollViewProxy { + SEL selector = @selector(webViewScrollViewWillBeginDragging:); + if ([_delegate respondsToSelector:selector]) { + [_delegate scrollViewWillBeginDragging:self]; + } +} +- (void)webViewScrollViewWillEndDragging: + (CRWWebViewScrollViewProxy*)webViewScrollViewProxy + withVelocity:(CGPoint)velocity + targetContentOffset:(inout CGPoint*)targetContentOffset { + SEL selector = @selector + (webViewScrollViewWillEndDragging:withVelocity:targetContentOffset:); + if ([_delegate respondsToSelector:selector]) { + [_delegate scrollViewWillEndDragging:self + withVelocity:velocity + targetContentOffset:targetContentOffset]; + } +} + +- (void)webViewScrollViewDidScroll: + (CRWWebViewScrollViewProxy*)webViewScrollViewProxy { + SEL selector = @selector(scrollViewDidScroll:); + if ([_delegate respondsToSelector:selector]) { + [_delegate scrollViewDidScroll:self]; + } +} + +- (void)webViewScrollViewDidEndDecelerating: + (CRWWebViewScrollViewProxy*)webViewScrollViewProxy { + SEL selector = @selector(webViewScrollViewDidEndDecelerating:); + if ([_delegate respondsToSelector:selector]) { + [_delegate scrollViewDidEndDecelerating:self]; + } +} + +- (void)webViewScrollViewDidResetContentSize: + (CRWWebViewScrollViewProxy*)webViewScrollViewProxy { + self.contentSize = _proxy.contentSize; +} + +@end
diff --git a/ios/web_view/internal/cwv_scroll_view_internal.h b/ios/web_view/internal/cwv_scroll_view_internal.h new file mode 100644 index 0000000..5328719 --- /dev/null +++ b/ios/web_view/internal/cwv_scroll_view_internal.h
@@ -0,0 +1,22 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_VIEW_INTERNAL_CWV_SCROLL_VIEW_INTERNAL_H_ +#define IOS_WEB_VIEW_INTERNAL_CWV_SCROLL_VIEW_INTERNAL_H_ + +#import <ChromeWebView/cwv_export.h> +#import <Foundation/Foundation.h> + +#import "ios/web_view/public/cwv_scroll_view.h" + +@class CRWWebViewScrollViewProxy; + +@interface CWVScrollView () + +// Operations to this scroll view are delegated to this proxy. +@property(nonatomic, weak, readwrite) CRWWebViewScrollViewProxy* proxy; + +@end + +#endif // IOS_WEB_VIEW_INTERNAL_CWV_SCROLL_VIEW_INTERNAL_H_
diff --git a/ios/web_view/internal/cwv_web_view.mm b/ios/web_view/internal/cwv_web_view.mm index 503cadd..544a327 100644 --- a/ios/web_view/internal/cwv_web_view.mm +++ b/ios/web_view/internal/cwv_web_view.mm
@@ -17,11 +17,14 @@ #import "ios/web/public/web_state/context_menu_params.h" #import "ios/web/public/web_state/js/crw_js_injection_receiver.h" #import "ios/web/public/web_state/ui/crw_web_delegate.h" +#import "ios/web/public/web_state/ui/crw_web_view_proxy.h" +#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h" #import "ios/web/public/web_state/web_state.h" #import "ios/web/public/web_state/web_state_delegate_bridge.h" #import "ios/web/public/web_state/web_state_observer_bridge.h" #import "ios/web_view/internal/cwv_html_element_internal.h" #import "ios/web_view/internal/cwv_navigation_action_internal.h" +#import "ios/web_view/internal/cwv_scroll_view_internal.h" #import "ios/web_view/internal/cwv_web_view_configuration_internal.h" #import "ios/web_view/internal/translate/web_view_translate_client.h" #include "ios/web_view/internal/web_view_browser_state.h" @@ -85,6 +88,7 @@ @synthesize translationDelegate = _translationDelegate; @synthesize estimatedProgress = _estimatedProgress; @synthesize UIDelegate = _UIDelegate; +@synthesize scrollView = _scrollView; + (NSString*)userAgentProduct { return gUserAgentProduct; @@ -114,6 +118,7 @@ self = [super initWithFrame:frame]; if (self) { _configuration = [configuration copy]; + _scrollView = [[CWVScrollView alloc] init]; [self resetWebStateWithSessionStorage:nil]; } return self; @@ -341,6 +346,8 @@ base::MakeUnique<ios_web_view::WebViewJavaScriptDialogPresenter>(self, nullptr); + _scrollView.proxy = _webState.get()->GetWebViewProxy().scrollViewProxy; + // Initialize Translate. ios_web_view::WebViewTranslateClient::CreateForWebState(_webState.get());
diff --git a/ios/web_view/public/ChromeWebView.h b/ios/web_view/public/ChromeWebView.h index 9dc9408..4b2a1358 100644 --- a/ios/web_view/public/ChromeWebView.h +++ b/ios/web_view/public/ChromeWebView.h
@@ -9,6 +9,8 @@ #import <ChromeWebView/cwv_html_element.h> #import <ChromeWebView/cwv_navigation_action.h> #import <ChromeWebView/cwv_navigation_delegate.h> +#import <ChromeWebView/cwv_scroll_view.h> +#import <ChromeWebView/cwv_scroll_view_delegate.h> #import <ChromeWebView/cwv_translate_delegate.h> #import <ChromeWebView/cwv_translate_manager.h> #import <ChromeWebView/cwv_ui_delegate.h>
diff --git a/ios/web_view/public/cwv_scroll_view.h b/ios/web_view/public/cwv_scroll_view.h new file mode 100644 index 0000000..4b5c268f --- /dev/null +++ b/ios/web_view/public/cwv_scroll_view.h
@@ -0,0 +1,47 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_VIEW_PUBLIC_CWV_SCROLL_VIEW_H_ +#define IOS_WEB_VIEW_PUBLIC_CWV_SCROLL_VIEW_H_ + +#import <ChromeWebView/cwv_export.h> +#import <CoreGraphics/CoreGraphics.h> +#import <Foundation/Foundation.h> +#import <UIKit/UIKit.h> + +@protocol CWVScrollViewDelegate; + +// Scroll view inside the web view. This is not a subclass of UIScrollView +// because the underlying //ios/web API only exposes a proxy object of the +// scroll view, not the raw UIScrollView. +// +// These methods are forwarded to the internal UIScrollView. Please see the +// <UIKit/UIScrollView.h> documentation for details about the following methods. +// +// TODO(crbug.com/719323): Add nullability annotations. +CWV_EXPORT +@interface CWVScrollView : NSObject + +@property(nonatomic, readonly) CGRect bounds; +@property(nonatomic) CGPoint contentOffset; +@property(nonatomic, weak) id<CWVScrollViewDelegate> delegate; +@property(nonatomic, readonly, getter=isDragging) BOOL dragging; + +// KVO compliant. +@property(nonatomic, readonly) CGSize contentSize; + +// Be careful when using this property. There's a bug with the +// underlying WKWebView where the web view does not respect contentInsets +// properly when laying out content and calculating innerHeight for Javascript. +// Content is laid out based on the entire height of the web view rather than +// the height between the top and bottom insets. +// https://bugs.webkit.org/show_bug.cgi?id=134230 +// rdar://23584409 (not available on Open Radar) +@property(nonatomic) UIEdgeInsets contentInset; + +- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer; + +@end + +#endif // IOS_WEB_VIEW_PUBLIC_CWV_SCROLL_VIEW_H_
diff --git a/ios/web_view/public/cwv_scroll_view_delegate.h b/ios/web_view/public/cwv_scroll_view_delegate.h new file mode 100644 index 0000000..d5eee58 --- /dev/null +++ b/ios/web_view/public/cwv_scroll_view_delegate.h
@@ -0,0 +1,28 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_VIEW_PUBLIC_CWV_SCROLL_VIEW_DELEGATE_H_ +#define IOS_WEB_VIEW_PUBLIC_CWV_SCROLL_VIEW_DELEGATE_H_ + +#import <CoreGraphics/CoreGraphics.h> + +@class CWVScrollView; + +// Delegete for CWVScrollView. +// +// These methods are forwarded from the internal UIScrollViewDelegate. Please +// see the <UIKit/UIScrollViewDelegate.h> documentation for details about the +// following methods. +CWV_EXPORT +@protocol CWVScrollViewDelegate<NSObject> +@optional +- (void)scrollViewWillBeginDragging:(CWVScrollView*)scrollView; +- (void)scrollViewWillEndDragging:(CWVScrollView*)scrollView + withVelocity:(CGPoint)velocity + targetContentOffset:(inout CGPoint*)targetContentOffset; +- (void)scrollViewDidScroll:(CWVScrollView*)scrollView; +- (void)scrollViewDidEndDecelerating:(CWVScrollView*)scrollView; +@end + +#endif // IOS_WEB_VIEW_PUBLIC_CWV_SCROLL_VIEW_DELEGATE_H_
diff --git a/ios/web_view/public/cwv_web_view.h b/ios/web_view/public/cwv_web_view.h index 639a85c..3bf3ee6 100644 --- a/ios/web_view/public/cwv_web_view.h +++ b/ios/web_view/public/cwv_web_view.h
@@ -7,6 +7,7 @@ #import <ChromeWebView/cwv_export.h> #import <UIKit/UIKit.h> +@class CWVScrollView; @class CWVWebViewConfiguration; @protocol CWVUIDelegate; @protocol CWVTranslateDelegate; @@ -57,6 +58,9 @@ // is reset to 0.0. @property(nonatomic, readonly) double estimatedProgress; +// The scroll view associated with the web view. +@property(nonatomic, readonly) CWVScrollView* scrollView; + // The User Agent product string used to build the full User Agent. + (NSString*)userAgentProduct;
diff --git a/ios/web_view/shell/shell_view_controller.m b/ios/web_view/shell/shell_view_controller.m index c7b1b2a..da1433f 100644 --- a/ios/web_view/shell/shell_view_controller.m +++ b/ios/web_view/shell/shell_view_controller.m
@@ -203,6 +203,17 @@ [_webView reload]; }]]; + // Removes the web view from the view hierarchy and deallocates it. For + // testing deallocation behavior, because there have been multiple crash bugs + // on deallocation of CWVWebView. + [alertController + addAction:[UIAlertAction actionWithTitle:@"Deallocate web view" + style:UIAlertActionStyleDefault + handler:^(UIAlertAction* action) { + [_webView removeFromSuperview]; + _webView = nil; + }]]; + [self presentViewController:alertController animated:YES completion:nil]; }
diff --git a/services/catalog/catalog.cc b/services/catalog/catalog.cc index 0110b7b..beb8d177 100644 --- a/services/catalog/catalog.cc +++ b/services/catalog/catalog.cc
@@ -102,7 +102,7 @@ auto entry = Entry::Deserialize(*manifest); if (entry) { if (!executable_path.empty()) - entry->set_path(executable_path); + entry->set_path(std::move(executable_path)); bool added = cache->AddRootEntry(std::move(entry)); DCHECK(added); } else {
diff --git a/services/catalog/entry.cc b/services/catalog/entry.cc index 2e2836bd..90f61531 100644 --- a/services/catalog/entry.cc +++ b/services/catalog/entry.cc
@@ -29,7 +29,7 @@ LOG(ERROR) << "Entry::Deserialize: list member must be a string"; return false; } - string_set->insert(value); + string_set->insert(std::move(value)); } return true; } @@ -44,14 +44,23 @@ return ReadStringSet(*list_value, string_set); } +// If |key| refers to a dictionary value within |value|, |*out| is set to that +// DictionaryValue. Returns true if either |key| is not present or the +// corresponding value is a dictionary. +bool GetDictionaryValue(const base::DictionaryValue& value, + base::StringPiece key, + const base::DictionaryValue** out) { + const base::Value* entry_value = nullptr; + return !value.Get(key, &entry_value) || entry_value->GetAsDictionary(out); +} + bool BuildInterfaceProviderSpec( const base::DictionaryValue& value, service_manager::InterfaceProviderSpec* interface_provider_specs) { DCHECK(interface_provider_specs); const base::DictionaryValue* provides_value = nullptr; - if (value.HasKey(Store::kInterfaceProviderSpecs_ProvidesKey) && - !value.GetDictionary(Store::kInterfaceProviderSpecs_ProvidesKey, - &provides_value)) { + if (!GetDictionaryValue(value, Store::kInterfaceProviderSpecs_ProvidesKey, + &provides_value)) { LOG(ERROR) << "Entry::Deserialize: " << Store::kInterfaceProviderSpecs_ProvidesKey << " must be a dictionary."; @@ -66,14 +75,13 @@ << " capabilities dictionary"; return false; } - interface_provider_specs->provides[it.key()] = interfaces; + interface_provider_specs->provides[it.key()] = std::move(interfaces); } } const base::DictionaryValue* requires_value = nullptr; - if (value.HasKey(Store::kInterfaceProviderSpecs_RequiresKey) && - !value.GetDictionary(Store::kInterfaceProviderSpecs_RequiresKey, - &requires_value)) { + if (!GetDictionaryValue(value, Store::kInterfaceProviderSpecs_RequiresKey, + &requires_value)) { LOG(ERROR) << "Entry::Deserialize: " << Store::kInterfaceProviderSpecs_RequiresKey << " must be a dictionary."; @@ -96,7 +104,7 @@ return false; } - interface_provider_specs->requires[it.key()] = capabilities; + interface_provider_specs->requires[it.key()] = std::move(capabilities); } } return true; @@ -130,14 +138,15 @@ LOG(ERROR) << "Entry::Deserialize: empty service name."; return nullptr; } - entry->set_name(name); + entry->set_name(std::move(name)); // By default we assume a standalone service executable. The catalog may // override this layer based on configuration external to the service's own // manifest. base::FilePath module_path; base::PathService::Get(base::DIR_MODULE, &module_path); - entry->set_path(module_path.AppendASCII(name + kServiceExecutableExtension)); + entry->set_path( + module_path.AppendASCII(entry->name() + kServiceExecutableExtension)); // Human-readable name. std::string display_name; @@ -146,7 +155,7 @@ << Store::kDisplayNameKey << " key"; return nullptr; } - entry->set_display_name(display_name); + entry->set_display_name(std::move(display_name)); // InterfaceProvider specs. const base::DictionaryValue* interface_provider_specs = nullptr; @@ -172,20 +181,19 @@ << "spec for key: " << it.key(); return nullptr; } - entry->AddInterfaceProviderSpec(it.key(), spec); + entry->AddInterfaceProviderSpec(it.key(), std::move(spec)); } // Required files. base::Optional<RequiredFileMap> required_files = catalog::RetrieveRequiredFiles(value); DCHECK(required_files); - for (const auto& iter : *required_files) { - entry->AddRequiredFilePath(iter.first, iter.second); + for (auto& iter : *required_files) { + entry->AddRequiredFilePath(iter.first, std::move(iter.second)); } - if (value.HasKey(Store::kServicesKey)) { - const base::ListValue* services = nullptr; - value.GetList(Store::kServicesKey, &services); + const base::ListValue* services = nullptr; + if (value.GetList(Store::kServicesKey, &services)) { for (size_t i = 0; i < services->GetSize(); ++i) { const base::DictionaryValue* service = nullptr; services->GetDictionary(i, &service); @@ -206,7 +214,7 @@ if (it == interface_provider_specs_.end()) return false; - auto connection_spec = it->second; + const auto& connection_spec = it->second; return connection_spec.provides.find(capability) != connection_spec.provides.end(); } @@ -219,13 +227,12 @@ void Entry::AddInterfaceProviderSpec( const std::string& name, - const service_manager::InterfaceProviderSpec& spec) { - interface_provider_specs_[name] = spec; + service_manager::InterfaceProviderSpec spec) { + interface_provider_specs_[name] = std::move(spec); } -void Entry::AddRequiredFilePath(const std::string& name, - const base::FilePath& path) { - required_file_paths_[name] = path; +void Entry::AddRequiredFilePath(const std::string& name, base::FilePath path) { + required_file_paths_[name] = std::move(path); } } // catalog
diff --git a/services/catalog/entry.h b/services/catalog/entry.h index f7332d8..21ba2d3 100644 --- a/services/catalog/entry.h +++ b/services/catalog/entry.h
@@ -35,14 +35,14 @@ bool operator==(const Entry& other) const; const std::string& name() const { return name_; } - void set_name(const std::string& name) { name_ = name; } + void set_name(std::string name) { name_ = std::move(name); } const base::FilePath& path() const { return path_; } - void set_path(const base::FilePath& path) { path_ = path; } + void set_path(base::FilePath path) { path_ = std::move(path); } const std::string& display_name() const { return display_name_; } - void set_display_name(const std::string& display_name) { - display_name_ = display_name; + void set_display_name(std::string display_name) { + display_name_ = std::move(display_name); } const Entry* parent() const { return parent_; } @@ -52,19 +52,18 @@ return children_; } std::vector<std::unique_ptr<Entry>>& children() { return children_; } - void set_children(std::vector<std::unique_ptr<Entry>>&& children) { + void set_children(std::vector<std::unique_ptr<Entry>> children) { children_ = std::move(children); } - void AddInterfaceProviderSpec( - const std::string& name, - const service_manager::InterfaceProviderSpec& spec); + void AddInterfaceProviderSpec(const std::string& name, + service_manager::InterfaceProviderSpec spec); const service_manager::InterfaceProviderSpecMap& interface_provider_specs() const { return interface_provider_specs_; } - void AddRequiredFilePath(const std::string& name, const base::FilePath& path); + void AddRequiredFilePath(const std::string& name, base::FilePath path); const std::map<std::string, base::FilePath>& required_file_paths() const { return required_file_paths_; }
diff --git a/services/service_manager/public/cpp/interface_provider_spec.cc b/services/service_manager/public/cpp/interface_provider_spec.cc index e9b6a8c5..06078b6c 100644 --- a/services/service_manager/public/cpp/interface_provider_spec.cc +++ b/services/service_manager/public/cpp/interface_provider_spec.cc
@@ -13,8 +13,15 @@ InterfaceProviderSpec::InterfaceProviderSpec() {} InterfaceProviderSpec::InterfaceProviderSpec( const InterfaceProviderSpec& other) = default; +InterfaceProviderSpec::InterfaceProviderSpec(InterfaceProviderSpec&& other) = + default; InterfaceProviderSpec::~InterfaceProviderSpec() {} +InterfaceProviderSpec& InterfaceProviderSpec::operator=( + const InterfaceProviderSpec& other) = default; +InterfaceProviderSpec& InterfaceProviderSpec::operator=( + InterfaceProviderSpec&& other) = default; + bool InterfaceProviderSpec::operator==( const InterfaceProviderSpec& other) const { return other.provides == provides && other.requires == requires;
diff --git a/services/service_manager/public/cpp/interface_provider_spec.h b/services/service_manager/public/cpp/interface_provider_spec.h index 4d6e45b..7864cba 100644 --- a/services/service_manager/public/cpp/interface_provider_spec.h +++ b/services/service_manager/public/cpp/interface_provider_spec.h
@@ -24,7 +24,10 @@ struct InterfaceProviderSpec { InterfaceProviderSpec(); InterfaceProviderSpec(const InterfaceProviderSpec& other); + InterfaceProviderSpec(InterfaceProviderSpec&& other); ~InterfaceProviderSpec(); + InterfaceProviderSpec& operator=(const InterfaceProviderSpec& other); + InterfaceProviderSpec& operator=(InterfaceProviderSpec&& other); bool operator==(const InterfaceProviderSpec& other) const; bool operator<(const InterfaceProviderSpec& other) const; std::map<Capability, InterfaceSet> provides;
diff --git a/services/service_manager/service_manager.cc b/services/service_manager/service_manager.cc index 5cecb4a2..f013fc3 100644 --- a/services/service_manager/service_manager.cc +++ b/services/service_manager/service_manager.cc
@@ -94,21 +94,26 @@ return exposed_interfaces; } -} // namespace - -Identity CreateServiceManagerIdentity() { - return Identity(service_manager::mojom::kServiceName, mojom::kRootUserID); -} - Identity CreateCatalogIdentity() { return Identity(catalog::mojom::kServiceName, mojom::kRootUserID); } -InterfaceProviderSpec GetPermissiveInterfaceProviderSpec() { +InterfaceProviderSpec CreatePermissiveInterfaceProviderSpec() { InterfaceProviderSpec spec; InterfaceSet interfaces; interfaces.insert("*"); - spec.requires["*"] = interfaces; + spec.requires["*"] = std::move(interfaces); + return spec; +} + +const InterfaceProviderSpec& GetPermissiveInterfaceProviderSpec() { + CR_DEFINE_STATIC_LOCAL(InterfaceProviderSpec, spec, + (CreatePermissiveInterfaceProviderSpec())); + return spec; +} + +const InterfaceProviderSpec& GetEmptyInterfaceProviderSpec() { + CR_DEFINE_STATIC_LOCAL(InterfaceProviderSpec, spec, ()); return spec; } @@ -139,6 +144,12 @@ return allowed; } +} // namespace + +Identity CreateServiceManagerIdentity() { + return Identity(service_manager::mojom::kServiceName, mojom::kRootUserID); +} + // Encapsulates a connection to an instance of a service, tracked by the // Service Manager. class ServiceManager::Instance @@ -150,11 +161,11 @@ public: Instance(service_manager::ServiceManager* service_manager, const Identity& identity, - const InterfaceProviderSpecMap& interface_provider_specs) + InterfaceProviderSpecMap interface_provider_specs) : service_manager_(service_manager), id_(GenerateUniqueID()), identity_(identity), - interface_provider_specs_(interface_provider_specs), + interface_provider_specs_(std::move(interface_provider_specs)), allow_any_application_(GetConnectionSpec().requires.count("*") == 1), pid_receiver_binding_(this), control_binding_(this), @@ -198,14 +209,10 @@ } std::unique_ptr<ConnectParams> params(std::move(*in_params)); - InterfaceProviderSpecMap source_specs; - InterfaceProviderSpec source_connection_spec; Instance* source = service_manager_->GetExistingInstance(params->source()); - if (source) { - source_specs = source->interface_provider_specs_; - source_connection_spec = source->GetConnectionSpec(); - } + const InterfaceProviderSpec& source_connection_spec = + source ? source->GetConnectionSpec() : GetEmptyInterfaceProviderSpec(); if (!AllowsInterface(params->source(), source_connection_spec, identity_, GetConnectionSpec(), params->interface_name())) { @@ -276,7 +283,9 @@ } const InterfaceProviderSpec& GetSpec(const std::string& spec) const { auto it = interface_provider_specs_.find(spec); - return it != interface_provider_specs_.end() ? it->second : empty_spec_; + return it != interface_provider_specs_.end() + ? it->second + : GetEmptyInterfaceProviderSpec(); } const Identity& identity() const { return identity_; } @@ -517,7 +526,7 @@ } mojom::ConnectResult ValidateConnectionSpec(const Identity& target) { - InterfaceProviderSpec connection_spec = GetConnectionSpec(); + const InterfaceProviderSpec& connection_spec = GetConnectionSpec(); // TODO(beng): Need to do the following additional policy validation of // whether this instance is allowed to connect using: // - non-null client process info. @@ -614,7 +623,6 @@ const uint32_t id_; Identity identity_; const InterfaceProviderSpecMap interface_provider_specs_; - const InterfaceProviderSpec empty_spec_; const bool allow_any_application_; std::unique_ptr<ServiceProcessLauncher> runner_; mojom::ServicePtr service_; @@ -702,10 +710,10 @@ spec.requires[catalog::mojom::kServiceName].insert( "service_manager:resolver"); InterfaceProviderSpecMap specs; - specs[mojom::kServiceManager_ConnectorSpec] = spec; + specs[mojom::kServiceManager_ConnectorSpec] = std::move(spec); - service_manager_instance_ = - CreateInstance(Identity(), CreateServiceManagerIdentity(), specs); + service_manager_instance_ = CreateInstance( + Identity(), CreateServiceManagerIdentity(), std::move(specs)); service_manager_instance_->StartWithService(std::move(service)); singletons_.insert(service_manager::mojom::kServiceName); service_context_.reset(new ServiceContext( @@ -743,7 +751,7 @@ void ServiceManager::SetInstanceQuitCallback( base::Callback<void(const Identity&)> callback) { - instance_quit_callback_ = callback; + instance_quit_callback_ = std::move(callback); } void ServiceManager::Connect(std::unique_ptr<ConnectParams> params) { @@ -794,10 +802,11 @@ "service_manager::mojom::Resolver"); spec.provides["control"].insert("catalog::mojom::CatalogControl"); InterfaceProviderSpecMap specs; - specs[mojom::kServiceManager_ConnectorSpec] = spec; + specs[mojom::kServiceManager_ConnectorSpec] = std::move(spec); - Instance* instance = CreateInstance( - CreateServiceManagerIdentity(), CreateCatalogIdentity(), specs); + Instance* instance = + CreateInstance(CreateServiceManagerIdentity(), CreateCatalogIdentity(), + std::move(specs)); singletons_.insert(catalog::mojom::kServiceName); instance->StartWithService(std::move(catalog)); } @@ -941,10 +950,10 @@ ServiceManager::Instance* ServiceManager::CreateInstance( const Identity& source, const Identity& target, - const InterfaceProviderSpecMap& specs) { + InterfaceProviderSpecMap specs) { CHECK(target.user_id() != mojom::kInheritUserID); - auto instance = base::MakeUnique<Instance>(this, target, specs); + auto instance = base::MakeUnique<Instance>(this, target, std::move(specs)); Instance* raw_instance = instance.get(); instances_.insert(std::make_pair(raw_instance, std::move(instance))); @@ -1025,14 +1034,15 @@ return; } - std::string instance_name = params->target().instance(); + const std::string& instance_name = params->target().instance(); // |result->interface_provider_specs| can be empty when there is no manifest. - InterfaceProviderSpec connection_spec = GetPermissiveInterfaceProviderSpec(); auto it = result->interface_provider_specs.find( mojom::kServiceManager_ConnectorSpec); - if (it != result->interface_provider_specs.end()) - connection_spec = it->second; + const InterfaceProviderSpec& connection_spec = + it != result->interface_provider_specs.end() + ? it->second + : GetPermissiveInterfaceProviderSpec(); const Identity original_target(params->target()); const std::string user_id = @@ -1047,8 +1057,6 @@ if (ConnectToExistingInstance(¶ms)) return; - Identity source = params->source(); - // Services that request "all_users" class from the Service Manager are // allowed to field connection requests from any user. They also run with a // synthetic user id generated here. The user id provided via Connect() is @@ -1063,8 +1071,11 @@ source_identity_for_creation = params->source(); } - Instance* instance = CreateInstance(source_identity_for_creation, - target, result->interface_provider_specs); + bool result_interface_provider_specs_empty = + result->interface_provider_specs.empty(); + Instance* instance = + CreateInstance(source_identity_for_creation, target, + std::move(result->interface_provider_specs)); // Below are various paths through which a new Instance can be bound to a // Service proxy. @@ -1084,7 +1095,7 @@ // anything more. // TODO(beng): There may be some cases where it's valid to have an empty // spec, so we should probably include a return value in |result|. - if (result->interface_provider_specs.empty()) { + if (result_interface_provider_specs_empty) { LOG(ERROR) << "Error: The catalog was unable to read a manifest for service \"" << result->name << "\"."; @@ -1095,7 +1106,7 @@ if (parent) { // This service is provided by another service via a ServiceFactory. - std::string target_user_id = target.user_id(); + const std::string* target_user_id = &target.user_id(); std::string factory_instance_name = instance_name; auto spec_iter = parent->interface_provider_specs.find( @@ -1108,20 +1119,20 @@ } else { // Use the original user ID so the existing embedder factory can // be found and used to create the new service. - target_user_id = original_target.user_id(); + target_user_id = &original_target.user_id(); Identity packaged_service_target(target); packaged_service_target.set_user_id(original_target.user_id()); instance->set_identity(packaged_service_target); } instance->StartWithService(std::move(service)); - Identity factory(parent->name, target_user_id, factory_instance_name); + Identity factory(parent->name, *target_user_id, factory_instance_name); CreateServiceWithFactory(factory, target.name(), std::move(request)); } else { base::FilePath package_path; if (!service_overrides_ || !service_overrides_->GetExecutablePathOverride( target.name(), &package_path)) { - package_path = result->package_path; + package_path = std::move(result->package_path); } DCHECK(!package_path.empty());
diff --git a/services/service_manager/service_manager.h b/services/service_manager/service_manager.h index 0fc8d5d..51969321 100644 --- a/services/service_manager/service_manager.h +++ b/services/service_manager/service_manager.h
@@ -135,7 +135,7 @@ Instance* CreateInstance(const Identity& source, const Identity& target, - const InterfaceProviderSpecMap& specs); + InterfaceProviderSpecMap specs); // Called from the instance implementing mojom::ServiceManager. void AddListener(mojom::ServiceManagerListenerPtr listener);
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index ee24cc7..b39df83a 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1606,6 +1606,24 @@ ] } ], + "NTPTilesInInstantService": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "win" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "NTPTilesInInstantService" + ] + } + ] + } + ], "NetDelayableH2AndQuicRequests": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-invalidation-logging.js b/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-invalidation-logging.js index f1398344..06110c9 100644 --- a/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-invalidation-logging.js +++ b/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-invalidation-logging.js
@@ -32,7 +32,7 @@ } `; - paintWorklet.addModule(URL.createObjectURL(new Blob([workletCode]))).then(function() { + paintWorklet.addModule(URL.createObjectURL(new Blob([workletCode], {type: 'text/javascript'}))).then(function() { for (let i = 0; i < tests.length; i++) { tests[i].paintName = 'paint-' + i; registerTest(imageType, tests[i]);
diff --git a/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-paint-worklet.js b/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-paint-worklet.js index bb1dfef..2813491 100644 --- a/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-paint-worklet.js +++ b/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-paint-worklet.js
@@ -9,7 +9,7 @@ testRunner.waitUntilDone(); } - var blob = new Blob([code]); + var blob = new Blob([code], {type: 'text/javascript'}); paintWorklet.addModule(URL.createObjectURL(blob)).then(function() { runAfterLayoutAndPaint(function() { if (window.testRunner) {
diff --git a/third_party/WebKit/LayoutTests/csspaint/valid-image-after-load.html b/third_party/WebKit/LayoutTests/csspaint/valid-image-after-load.html index 7bb5bcd..ed9f0cc 100644 --- a/third_party/WebKit/LayoutTests/csspaint/valid-image-after-load.html +++ b/third_party/WebKit/LayoutTests/csspaint/valid-image-after-load.html
@@ -27,7 +27,8 @@ testRunner.waitUntilDone(); } -var blob = new Blob([document.getElementById('code').textContent]); +var blob = new Blob([document.getElementById('code').textContent], + {type: 'text/javascript'}); paintWorklet.addModule(URL.createObjectURL(blob)).then(function() { var el = document.getElementById('output'); el.style.backgroundImage = 'paint(green)';
diff --git a/third_party/WebKit/LayoutTests/csspaint/valid-image-before-load.html b/third_party/WebKit/LayoutTests/csspaint/valid-image-before-load.html index 3a6eacf..3e6f37b2 100644 --- a/third_party/WebKit/LayoutTests/csspaint/valid-image-before-load.html +++ b/third_party/WebKit/LayoutTests/csspaint/valid-image-before-load.html
@@ -30,7 +30,8 @@ var el = document.getElementById('output'); el.style.backgroundImage = 'paint(green)'; -var blob = new Blob([document.getElementById('code').textContent]); +var blob = new Blob([document.getElementById('code').textContent], + {type: 'text/javascript'}); paintWorklet.addModule(URL.createObjectURL(blob)).then(function() { runAfterLayoutAndPaint(function() { if (window.testRunner) {
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/worklet-import-blocked-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/worklet-import-blocked-expected.txt index 74af2b2..76df14a4 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/worklet-import-blocked-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/worklet-import-blocked-expected.txt
@@ -1,4 +1,4 @@ -CONSOLE ERROR: line 13: Refused to load the script 'http://127.0.0.1:8000/resources/worklet.js' because it violates the following Content Security Policy directive: "script-src 'unsafe-inline'". +CONSOLE ERROR: Refused to load the script 'http://127.0.0.1:8000/resources/worklet.js' because it violates the following Content Security Policy directive: "script-src 'unsafe-inline'". This is a testharness.js-based test. PASS Importing a script rejects the given promise with NetworkError because it violated the same origin CSP policy.
diff --git a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl index 5956fd1..7076913 100644 --- a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl +++ b/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl
@@ -33,6 +33,11 @@ namespace blink { +{% for subgroup in computed_style.subgroups %} +{{define_field_group_class(subgroup)|indent(2)}} + +{% endfor %} + // The generated portion of ComputedStyle. For more info, see the header comment // in ComputedStyle.h. class CORE_EXPORT ComputedStyleBase { @@ -104,11 +109,6 @@ {{field_templates[field.field_template].decl_public_methods(field)|indent(2)}} {% endfor %} - private: - {% for subgroup in computed_style.subgroups %} - {{define_field_group_class(subgroup)|indent(2)}} - - {% endfor %} protected: // Constructor and destructor are protected so that only the parent class ComputedStyle
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5 index 6d3486c..e16dbde3 100644 --- a/third_party/WebKit/Source/core/css/CSSProperties.json5 +++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -545,6 +545,10 @@ custom_all: true, is_descriptor: true, priority: "High", + field_template: "storage_only", + type_name: "float", + default_value: "1.0", + field_group: "visual", }, { @@ -892,6 +896,10 @@ converter: "ConvertClip", custom_all: true, interpolable: true, + field_template: "storage_only", + field_type_path: "platform/LengthBox", + default_value: "LengthBox()", + field_group: "visual", }, { name: "clip-path",
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleExtraFields.json5 b/third_party/WebKit/Source/core/css/ComputedStyleExtraFields.json5 index 68e408a..5e7fae35 100644 --- a/third_party/WebKit/Source/core/css/ComputedStyleExtraFields.json5 +++ b/third_party/WebKit/Source/core/css/ComputedStyleExtraFields.json5
@@ -183,5 +183,21 @@ default_value: "Color::kTransparent", field_group: "background", }, + { + name: "TextDecoration", + field_template: "storage_only", + type_name: "TextDecoration", + field_size: 4, + default_value: "kTextDecorationNone", + field_group: "visual", + }, + { + name: "HasAutoClip", + field_template: "storage_only", + type_name: "bool", + field_size: 1, + default_value: "true", + field_group: "visual", + }, ], }
diff --git a/third_party/WebKit/Source/core/dom/Modulator.cpp b/third_party/WebKit/Source/core/dom/Modulator.cpp index e0b2ed2..83a1157 100644 --- a/third_party/WebKit/Source/core/dom/Modulator.cpp +++ b/third_party/WebKit/Source/core/dom/Modulator.cpp
@@ -29,7 +29,7 @@ static_cast<Modulator*>(per_context_data->GetData(kPerContextDataKey)); if (!modulator) { if (Document* document = ToDocument(ExecutionContext::From(script_state))) { - modulator = ModulatorImpl::Create(script_state, *document); + modulator = ModulatorImpl::Create(script_state, document->Fetcher()); Modulator::SetModulator(script_state, modulator); } }
diff --git a/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp b/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp index e5e4f35d..16081ff 100644 --- a/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp +++ b/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp
@@ -4,7 +4,6 @@ #include "core/dom/ModulatorImpl.h" -#include "core/dom/Document.h" #include "core/dom/ExecutionContext.h" #include "core/dom/ModuleMap.h" #include "core/dom/ModuleScript.h" @@ -19,18 +18,15 @@ namespace blink { ModulatorImpl* ModulatorImpl::Create(RefPtr<ScriptState> script_state, - Document& document) { - return new ModulatorImpl( - std::move(script_state), - TaskRunnerHelper::Get(TaskType::kNetworking, &document), - document.Fetcher()); + ResourceFetcher* resource_fetcher) { + return new ModulatorImpl(std::move(script_state), resource_fetcher); } ModulatorImpl::ModulatorImpl(RefPtr<ScriptState> script_state, - RefPtr<WebTaskRunner> task_runner, ResourceFetcher* fetcher) : script_state_(std::move(script_state)), - task_runner_(std::move(task_runner)), + task_runner_( + TaskRunnerHelper::Get(TaskType::kNetworking, script_state_.Get())), fetcher_(fetcher), map_(this, ModuleMap::Create(this)), loader_registry_(ModuleScriptLoaderRegistry::Create()),
diff --git a/third_party/WebKit/Source/core/dom/ModulatorImpl.h b/third_party/WebKit/Source/core/dom/ModulatorImpl.h index b4f2afd..c971e76 100644 --- a/third_party/WebKit/Source/core/dom/ModulatorImpl.h +++ b/third_party/WebKit/Source/core/dom/ModulatorImpl.h
@@ -14,7 +14,6 @@ namespace blink { -class Document; class ExecutionContext; class ModuleMap; class ModuleScriptLoaderRegistry; @@ -29,7 +28,7 @@ // components together. class ModulatorImpl final : public Modulator { public: - static ModulatorImpl* Create(RefPtr<ScriptState>, Document&); + static ModulatorImpl* Create(RefPtr<ScriptState>, ResourceFetcher*); virtual ~ModulatorImpl(); DECLARE_TRACE(); @@ -67,7 +66,7 @@ Vector<String> ModuleRequestsFromScriptModule(ScriptModule) override; void ExecuteModule(const ModuleScript*) override; - ModulatorImpl(RefPtr<ScriptState>, RefPtr<WebTaskRunner>, ResourceFetcher*); + ModulatorImpl(RefPtr<ScriptState>, ResourceFetcher*); ExecutionContext* GetExecutionContext() const;
diff --git a/third_party/WebKit/Source/core/editing/DOMSelection.cpp b/third_party/WebKit/Source/core/editing/DOMSelection.cpp index 6e31518b..dedd3cb0 100644 --- a/third_party/WebKit/Source/core/editing/DOMSelection.cpp +++ b/third_party/WebKit/Source/core/editing/DOMSelection.cpp
@@ -369,12 +369,6 @@ ClearCachedRangeIfSelectionOfDocument(); - // TODO(editing-dev): Once SVG USE element doesn't modify DOM tree, we - // should get rid of this update layout call. - // See http://crbug.com/566281 - // See "svg/text/textpath-reference-crash.html" - GetFrame()->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); - Position base_position(base_node, base_offset); Position extent_position(extent_node, extent_offset); Range* new_range = Range::Create(base_node->GetDocument());
diff --git a/third_party/WebKit/Source/core/frame/BUILD.gn b/third_party/WebKit/Source/core/frame/BUILD.gn index e6f88fcc..de8783f 100644 --- a/third_party/WebKit/Source/core/frame/BUILD.gn +++ b/third_party/WebKit/Source/core/frame/BUILD.gn
@@ -117,6 +117,7 @@ "UseCounter.h", "VisualViewport.cpp", "VisualViewport.h", + "WebLocalFrameBase.cpp", "WebLocalFrameBase.h", "csp/CSPDirective.h", "csp/CSPDirectiveList.cpp",
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameBase.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameBase.cpp new file mode 100644 index 0000000..3707f52 --- /dev/null +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameBase.cpp
@@ -0,0 +1,23 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/frame/WebLocalFrameBase.h" + +#include "core/page/ChromeClient.h" +#include "core/page/Page.h" + +namespace blink { + +WebLocalFrameBase* WebLocalFrameBase::FromFrame(LocalFrame* frame) { + if (frame && frame->GetPage()) { + return frame->GetPage()->GetChromeClient().GetWebLocalFrameBase(frame); + } + return nullptr; +} + +WebLocalFrameBase* WebLocalFrameBase::FromFrame(LocalFrame& frame) { + return WebLocalFrameBase::FromFrame(&frame); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameBase.h b/third_party/WebKit/Source/core/frame/WebLocalFrameBase.h index 4c41212..3e05917 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameBase.h +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameBase.h
@@ -5,10 +5,13 @@ #ifndef WebLocalFrameBase_h #define WebLocalFrameBase_h +#include "core/CoreExport.h" #include "public/web/WebLocalFrame.h" namespace blink { +class LocalFrame; + // WebLocalFrameBase is a temporary class the provides a layer of abstraction // for WebLocalFrameImpl. Mehtods that are declared public in WebLocalFrameImpl // that are not overrides from WebLocalFrame will be declared pure virtual in @@ -18,6 +21,10 @@ // modules. // TODO(slangley): Remove this class once WebLocalFrameImpl is in core/. class WebLocalFrameBase : public WebLocalFrame { + public: + CORE_EXPORT static WebLocalFrameBase* FromFrame(LocalFrame*); + CORE_EXPORT static WebLocalFrameBase* FromFrame(LocalFrame&); + protected: explicit WebLocalFrameBase(WebTreeScopeType scope) : WebLocalFrame(scope) {} };
diff --git a/third_party/WebKit/Source/core/layout/LayoutText.cpp b/third_party/WebKit/Source/core/layout/LayoutText.cpp index c7b873fe..6e007fd6 100644 --- a/third_party/WebKit/Source/core/layout/LayoutText.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutText.cpp
@@ -343,21 +343,18 @@ static FloatRect LocalQuadForTextBox(InlineTextBox* box, unsigned start, - unsigned end, - bool use_selection_height) { + unsigned end) { unsigned real_end = std::min(box->end() + 1, end); LayoutRect r = box->LocalSelectionRect(start, real_end); if (r.Height()) { - if (!use_selection_height) { - // Change the height and y position (or width and x for vertical text) - // because selectionRect uses selection-specific values. - if (box->IsHorizontal()) { - r.SetHeight(box->Height()); - r.SetY(box->Y()); - } else { - r.SetWidth(box->Width()); - r.SetX(box->X()); - } + // Change the height and y position (or width and x for vertical text) + // because selectionRect uses selection-specific values. + if (box->IsHorizontal()) { + r.SetHeight(box->Height()); + r.SetY(box->Y()); + } else { + r.SetWidth(box->Width()); + r.SetX(box->X()); } return FloatRect(r); } @@ -366,8 +363,7 @@ void LayoutText::AbsoluteRectsForRange(Vector<IntRect>& rects, unsigned start, - unsigned end, - bool use_selection_height) const { + unsigned end) const { // Work around signed/unsigned issues. This function takes unsigneds, and is // often passed UINT_MAX to mean "all the way to the end". InlineTextBox // coordinates are unsigneds, so changing this function to take ints causes @@ -388,16 +384,6 @@ // past it if (start <= box->Start() && box->end() < end) { FloatRect r(box->FrameRect()); - if (use_selection_height) { - LayoutRect selection_rect = box->LocalSelectionRect(start, end); - if (box->IsHorizontal()) { - r.SetHeight(selection_rect.Height().ToFloat()); - r.SetY(selection_rect.Y().ToFloat()); - } else { - r.SetWidth(selection_rect.Width().ToFloat()); - r.SetX(selection_rect.X().ToFloat()); - } - } if (!has_checked_box_in_range) { has_checked_box_in_range = true; rects.clear(); @@ -405,8 +391,7 @@ rects.push_back(LocalToAbsoluteQuad(r).EnclosingBoundingBox()); } else if ((box->Start() <= start && start <= box->end()) || (box->Start() < end && end <= box->end())) { - FloatRect rect = - LocalQuadForTextBox(box, start, end, use_selection_height); + FloatRect rect = LocalQuadForTextBox(box, start, end); if (!rect.IsZero()) { if (!has_checked_box_in_range) { has_checked_box_in_range = true; @@ -417,8 +402,7 @@ } else if (!has_checked_box_in_range) { // FIXME: This code is wrong. It's converting local to absolute twice. // http://webkit.org/b/65722 - FloatRect rect = - LocalQuadForTextBox(box, start, end, use_selection_height); + FloatRect rect = LocalQuadForTextBox(box, start, end); if (!rect.IsZero()) rects.push_back(LocalToAbsoluteQuad(rect).EnclosingBoundingBox()); } @@ -523,7 +507,7 @@ quads.push_back(LocalToAbsoluteQuad(FloatRect(r))); } else if ((box->Start() <= start && start <= box->end()) || (box->Start() < end && end <= box->end())) { - FloatRect rect = LocalQuadForTextBox(box, start, end, false); + FloatRect rect = LocalQuadForTextBox(box, start, end); if (!rect.IsZero()) { if (!has_checked_box_in_range) { has_checked_box_in_range = true; @@ -534,7 +518,7 @@ } else if (!has_checked_box_in_range) { // consider when the offset of range is area of leading or trailing // whitespace - FloatRect rect = LocalQuadForTextBox(box, start, end, false); + FloatRect rect = LocalQuadForTextBox(box, start, end); if (!rect.IsZero()) quads.push_back(LocalToAbsoluteQuad(rect).EnclosingBoundingBox()); }
diff --git a/third_party/WebKit/Source/core/layout/LayoutText.h b/third_party/WebKit/Source/core/layout/LayoutText.h index c675d282..6462cadf 100644 --- a/third_party/WebKit/Source/core/layout/LayoutText.h +++ b/third_party/WebKit/Source/core/layout/LayoutText.h
@@ -101,8 +101,7 @@ const LayoutPoint& accumulated_offset) const final; void AbsoluteRectsForRange(Vector<IntRect>&, unsigned start_offset = 0, - unsigned end_offset = INT_MAX, - bool use_selection_height = false) const; + unsigned end_offset = INT_MAX) const; void AbsoluteQuads(Vector<FloatQuad>&, MapCoordinatesFlags mode = 0) const final;
diff --git a/third_party/WebKit/Source/core/page/ChromeClient.h b/third_party/WebKit/Source/core/page/ChromeClient.h index 343eb97..48e803a2 100644 --- a/third_party/WebKit/Source/core/page/ChromeClient.h +++ b/third_party/WebKit/Source/core/page/ChromeClient.h
@@ -77,6 +77,7 @@ class WebImage; class WebLayer; class WebLayerTreeView; +class WebLocalFrameBase; struct CompositedSelection; struct DateTimeChooserParameters; @@ -352,6 +353,10 @@ virtual WebLayerTreeView* GetWebLayerTreeView(LocalFrame*) { return nullptr; } + virtual WebLocalFrameBase* GetWebLocalFrameBase(LocalFrame*) { + return nullptr; + } + DECLARE_TRACE(); protected:
diff --git a/third_party/WebKit/Source/core/style/BUILD.gn b/third_party/WebKit/Source/core/style/BUILD.gn index 2c449ce..1458f9a 100644 --- a/third_party/WebKit/Source/core/style/BUILD.gn +++ b/third_party/WebKit/Source/core/style/BUILD.gn
@@ -103,8 +103,6 @@ "StyleSelfAlignmentData.h", "StyleTransformData.cpp", "StyleTransformData.h", - "StyleVisualData.cpp", - "StyleVisualData.h", "StyleWillChangeData.cpp", "StyleWillChangeData.h", "TextSizeAdjust.h",
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp index f4ddbc2..522a8a5 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp +++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -115,7 +115,6 @@ ALWAYS_INLINE ComputedStyle::ComputedStyle() : ComputedStyleBase(), RefCounted<ComputedStyle>() { box_data_.Init(); - visual_data_.Init(); rare_non_inherited_data_.Init(); rare_non_inherited_data_.Access()->deprecated_flexible_box_.Init(); rare_non_inherited_data_.Access()->flexible_box_.Init(); @@ -136,7 +135,6 @@ : ComputedStyleBase(o), RefCounted<ComputedStyle>(), box_data_(o.box_data_), - visual_data_(o.visual_data_), rare_non_inherited_data_(o.rare_non_inherited_data_), rare_inherited_data_(o.rare_inherited_data_), inherited_data_(o.inherited_data_), @@ -330,7 +328,6 @@ void ComputedStyle::CopyNonInheritedFromCached(const ComputedStyle& other) { ComputedStyleBase::CopyNonInheritedFromCached(other); box_data_ = other.box_data_; - visual_data_ = other.visual_data_; rare_non_inherited_data_ = other.rare_non_inherited_data_; // The flags are copied one-by-one because they contain @@ -471,7 +468,6 @@ // compare everything except the pseudoStyle pointer return ComputedStyleBase::NonInheritedEqual(other) && box_data_ == other.box_data_ && - visual_data_ == other.visual_data_ && rare_non_inherited_data_ == other.rare_non_inherited_data_ && svg_style_->NonInheritedEqual(*other.svg_style_); } @@ -1057,7 +1053,8 @@ inherited_data_->visited_link_color_ != other.inherited_data_->visited_link_color_ || HasSimpleUnderlineInternal() != other.HasSimpleUnderlineInternal() || - visual_data_->text_decoration != other.visual_data_->text_decoration) { + visual_data_->text_decoration_ != + other.visual_data_->text_decoration_) { diff.SetTextDecorationOrColorChanged(); } else { if (rare_non_inherited_data_.Get() != @@ -1102,11 +1099,11 @@ } } - bool has_clip = HasOutOfFlowPosition() && !visual_data_->has_auto_clip; + bool has_clip = HasOutOfFlowPosition() && !visual_data_->has_auto_clip_; bool other_has_clip = - other.HasOutOfFlowPosition() && !other.visual_data_->has_auto_clip; + other.HasOutOfFlowPosition() && !other.visual_data_->has_auto_clip_; if (has_clip != other_has_clip || - (has_clip && visual_data_->clip != other.visual_data_->clip)) + (has_clip && visual_data_->clip_ != other.visual_data_->clip_)) diff.SetCSSClipChanged(); }
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h index 9034275..d0b5313f 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.h +++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -53,7 +53,6 @@ #include "core/style/StyleReflection.h" #include "core/style/StyleSelfAlignmentData.h" #include "core/style/StyleTransformData.h" -#include "core/style/StyleVisualData.h" #include "core/style/StyleWillChangeData.h" #include "core/style/TransformOrigin.h" #include "platform/Length.h" @@ -184,7 +183,6 @@ protected: // non-inherited attributes DataRef<StyleBoxData> box_data_; - DataRef<StyleVisualData> visual_data_; DataRef<StyleRareNonInheritedData> rare_non_inherited_data_; // inherited attributes @@ -576,15 +574,15 @@ // clip static LengthBox InitialClip() { return LengthBox(); } - const LengthBox& Clip() const { return visual_data_->clip; } + const LengthBox& Clip() const { return visual_data_->clip_; } void SetClip(const LengthBox& box) { - SET_VAR(visual_data_, has_auto_clip, false); - SET_VAR(visual_data_, clip, box); + SET_VAR(visual_data_, has_auto_clip_, false); + SET_VAR(visual_data_, clip_, box); } - bool HasAutoClip() const { return visual_data_->has_auto_clip; } + bool HasAutoClip() const { return visual_data_->has_auto_clip_; } void SetHasAutoClip() { - SET_VAR(visual_data_, has_auto_clip, true); - SET_VAR(visual_data_, clip, ComputedStyle::InitialClip()); + SET_VAR(visual_data_, has_auto_clip_, true); + SET_VAR(visual_data_, clip_, ComputedStyle::InitialClip()); } // Column properties. @@ -1454,10 +1452,10 @@ // text-decoration-line static TextDecoration InitialTextDecoration() { return kTextDecorationNone; } TextDecoration GetTextDecoration() const { - return static_cast<TextDecoration>(visual_data_->text_decoration); + return static_cast<TextDecoration>(visual_data_->text_decoration_); } void SetTextDecoration(TextDecoration v) { - SET_VAR(visual_data_, text_decoration, v); + SET_VAR(visual_data_, text_decoration_, v); } // text-decoration-color @@ -2971,10 +2969,10 @@ } // Clip utility functions. - const Length& ClipLeft() const { return visual_data_->clip.Left(); } - const Length& ClipRight() const { return visual_data_->clip.Right(); } - const Length& ClipTop() const { return visual_data_->clip.Top(); } - const Length& ClipBottom() const { return visual_data_->clip.Bottom(); } + const Length& ClipLeft() const { return visual_data_->clip_.Left(); } + const Length& ClipRight() const { return visual_data_->clip_.Right(); } + const Length& ClipTop() const { return visual_data_->clip_.Top(); } + const Length& ClipBottom() const { return visual_data_->clip_.Bottom(); } // Offset utility functions. // Accessors for positioned object edges that take into account writing mode.
diff --git a/third_party/WebKit/Source/core/style/StyleVisualData.cpp b/third_party/WebKit/Source/core/style/StyleVisualData.cpp deleted file mode 100644 index 89541881..0000000 --- a/third_party/WebKit/Source/core/style/StyleVisualData.cpp +++ /dev/null
@@ -1,42 +0,0 @@ -/* - * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "core/style/StyleVisualData.h" - -#include "core/style/ComputedStyle.h" - -namespace blink { - -StyleVisualData::StyleVisualData() - : has_auto_clip(true), - text_decoration(ComputedStyle::InitialTextDecoration()), - zoom_(ComputedStyle::InitialZoom()) {} - -StyleVisualData::~StyleVisualData() {} - -StyleVisualData::StyleVisualData(const StyleVisualData& o) - : RefCounted<StyleVisualData>(), - clip(o.clip), - has_auto_clip(o.has_auto_clip), - text_decoration(o.text_decoration), - zoom_(o.zoom_) {} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/style/StyleVisualData.h b/third_party/WebKit/Source/core/style/StyleVisualData.h deleted file mode 100644 index 39b6ea6..0000000 --- a/third_party/WebKit/Source/core/style/StyleVisualData.h +++ /dev/null
@@ -1,69 +0,0 @@ -/* - * Copyright (C) 2000 Lars Knoll (knoll@kde.org) - * (C) 2000 Antti Koivisto (koivisto@kde.org) - * (C) 2000 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef StyleVisualData_h -#define StyleVisualData_h - -#include "core/CoreExport.h" -#include "core/style/ComputedStyleConstants.h" -#include "platform/LengthBox.h" -#include "platform/wtf/PassRefPtr.h" -#include "platform/wtf/RefCounted.h" - -namespace blink { - -// TODO(sashab): Move this into a private class on ComputedStyle, and remove -// all methods on it, merging them into copy/creation methods on ComputedStyle -// instead. Keep the allocation logic, only allocating a new object if needed. -class CORE_EXPORT StyleVisualData : public RefCounted<StyleVisualData> { - public: - static PassRefPtr<StyleVisualData> Create() { - return AdoptRef(new StyleVisualData); - } - PassRefPtr<StyleVisualData> Copy() const { - return AdoptRef(new StyleVisualData(*this)); - } - ~StyleVisualData(); - - bool operator==(const StyleVisualData& o) const { - return clip == o.clip && has_auto_clip == o.has_auto_clip && - text_decoration == o.text_decoration && zoom_ == o.zoom_; - } - bool operator!=(const StyleVisualData& o) const { return !(*this == o); } - - LengthBox clip; - bool has_auto_clip : 1; - unsigned text_decoration : kTextDecorationBits; // Text decorations defined - // *only* by this element. - - float zoom_; - - private: - StyleVisualData(); - StyleVisualData(const StyleVisualData&); -}; - -} // namespace blink - -#endif // StyleVisualData_h
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp b/third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp index 4d2c6f1..2c24ab8 100644 --- a/third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp +++ b/third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp
@@ -4,11 +4,13 @@ #include "core/workers/MainThreadWorklet.h" +#include "bindings/core/v8/ScriptPromiseResolver.h" #include "bindings/core/v8/ScriptSourceCode.h" #include "bindings/core/v8/V8BindingForCore.h" #include "core/dom/DOMException.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" +#include "core/dom/TaskRunnerHelper.h" #include "core/frame/LocalFrame.h" #include "core/workers/WorkletGlobalScopeProxy.h" #include "core/workers/WorkletPendingTasks.h" @@ -18,7 +20,8 @@ MainThreadWorklet::MainThreadWorklet(LocalFrame* frame) : Worklet(frame) {} -// Implementation of the "addModule(moduleURL, options)" algorithm: +// Implementation of the first half of the "addModule(moduleURL, options)" +// algorithm: // https://drafts.css-houdini.org/worklets/#dom-worklet-addmodule ScriptPromise MainThreadWorklet::addModule(ScriptState* script_state, const String& module_url) { @@ -50,7 +53,24 @@ // Step 5: "Return promise, and then continue running this algorithm in // parallel." - // TODO(nhiroki): Make the following sequence async. + // |kUnspecedLoading| is used here because this is a part of script module + // loading. + TaskRunnerHelper::Get(TaskType::kUnspecedLoading, script_state) + ->PostTask(BLINK_FROM_HERE, + WTF::Bind(&MainThreadWorklet::FetchAndInvokeScript, + WrapPersistent(this), module_url_record, + WrapPersistent(resolver))); + return promise; +} + +// Implementation of the second half of the "addModule(moduleURL, options)" +// algorithm: +// https://drafts.css-houdini.org/worklets/#dom-worklet-addmodule +void MainThreadWorklet::FetchAndInvokeScript(const KURL& module_url_record, + ScriptPromiseResolver* resolver) { + DCHECK(IsMainThread()); + if (!GetExecutionContext()) + return; // Step 6: "Let credentialOptions be the credentials member of options." // TODO(nhiroki): Implement credentialOptions (https://crbug.com/710837). @@ -93,7 +113,6 @@ // TODO(nhiroki): Queue a task instead of executing this here. GetWorkletGlobalScopeProxy()->FetchAndInvokeScript(module_url_record, pending_tasks); - return promise; } void MainThreadWorklet::ContextDestroyed(ExecutionContext* execution_context) {
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorklet.h b/third_party/WebKit/Source/core/workers/MainThreadWorklet.h index de5853b..e6b5c85 100644 --- a/third_party/WebKit/Source/core/workers/MainThreadWorklet.h +++ b/third_party/WebKit/Source/core/workers/MainThreadWorklet.h
@@ -7,13 +7,14 @@ #include "core/workers/Worklet.h" -#include "bindings/core/v8/ScriptPromiseResolver.h" +#include "bindings/core/v8/ScriptPromise.h" #include "core/CoreExport.h" #include "platform/heap/Handle.h" namespace blink { class LocalFrame; +class ScriptPromiseResolver; // A MainThreadWorklet is a worklet that runs only on the main thread. // TODO(nhiroki): This is a temporary class to support module loading for main @@ -36,6 +37,10 @@ protected: explicit MainThreadWorklet(LocalFrame*); + + private: + void FetchAndInvokeScript(const KURL& module_url_record, + ScriptPromiseResolver*); }; } // namespace blink
diff --git a/third_party/WebKit/Source/web/ChromeClientImpl.cpp b/third_party/WebKit/Source/web/ChromeClientImpl.cpp index 6ec80ab..34e37bb1 100644 --- a/third_party/WebKit/Source/web/ChromeClientImpl.cpp +++ b/third_party/WebKit/Source/web/ChromeClientImpl.cpp
@@ -950,6 +950,10 @@ return web_frame->LocalRoot()->FrameWidget()->GetLayerTreeView(); } +WebLocalFrameBase* ChromeClientImpl::GetWebLocalFrameBase(LocalFrame* frame) { + return WebLocalFrameImpl::FromFrame(frame); +} + void ChromeClientImpl::SetEventListenerProperties( LocalFrame* frame, WebEventListenerClass event_class,
diff --git a/third_party/WebKit/Source/web/ChromeClientImpl.h b/third_party/WebKit/Source/web/ChromeClientImpl.h index 0b2722a..cf0cecf 100644 --- a/third_party/WebKit/Source/web/ChromeClientImpl.h +++ b/third_party/WebKit/Source/web/ChromeClientImpl.h
@@ -235,6 +235,8 @@ WebLayerTreeView* GetWebLayerTreeView(LocalFrame*) override; + WebLocalFrameBase* GetWebLocalFrameBase(LocalFrame*) override; + private: explicit ChromeClientImpl(WebViewBase*);
diff --git a/third_party/WebKit/Source/web/ContextMenuClientImpl.cpp b/third_party/WebKit/Source/web/ContextMenuClientImpl.cpp index 6321465..c1e00ad 100644 --- a/third_party/WebKit/Source/web/ContextMenuClientImpl.cpp +++ b/third_party/WebKit/Source/web/ContextMenuClientImpl.cpp
@@ -107,7 +107,7 @@ static String SelectMisspellingAsync(LocalFrame* selected_frame, String& description) { VisibleSelection selection = - selected_frame->Selection().ComputeVisibleSelectionInDOMTreeDeprecated(); + selected_frame->Selection().ComputeVisibleSelectionInDOMTree(); if (selection.IsNone()) return String();
diff --git a/third_party/WebKit/Source/web/WebDocument.cpp b/third_party/WebKit/Source/web/WebDocument.cpp index cd6040c..110117f 100644 --- a/third_party/WebKit/Source/web/WebDocument.cpp +++ b/third_party/WebKit/Source/web/WebDocument.cpp
@@ -41,6 +41,7 @@ #include "core/dom/Element.h" #include "core/dom/StyleEngine.h" #include "core/events/Event.h" +#include "core/frame/WebLocalFrameBase.h" #include "core/html/HTMLAllCollection.h" #include "core/html/HTMLBodyElement.h" #include "core/html/HTMLCollection.h" @@ -65,7 +66,6 @@ #include "public/web/WebElementCollection.h" #include "public/web/WebFormElement.h" #include "v8/include/v8.h" -#include "web/WebLocalFrameImpl.h" namespace blink { @@ -106,7 +106,7 @@ } WebLocalFrame* WebDocument::GetFrame() const { - return WebLocalFrameImpl::FromFrame(ConstUnwrap<Document>()->GetFrame()); + return WebLocalFrameBase::FromFrame(ConstUnwrap<Document>()->GetFrame()); } bool WebDocument::IsHTMLDocument() const {
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer.py index 067d358..98ab9ee 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer.py
@@ -36,7 +36,6 @@ class BaselineOptimizer(object): - ROOT_LAYOUT_TESTS_DIRECTORY = 'LayoutTests' def __init__(self, host, port, port_names): self._filesystem = host.filesystem @@ -45,8 +44,10 @@ for port_name in port_names: self._ports[port_name] = host.port_factory.get(port_name) - self._webkit_base = port.webkit_base() self._layout_tests_dir = port.layout_tests_dir() + self._parent_of_tests = self._filesystem.dirname(self._layout_tests_dir) + self._layout_tests_dir_name = self._filesystem.relpath( + self._layout_tests_dir, self._parent_of_tests) # Only used by unit tests. self.new_results_by_directory = [] @@ -158,10 +159,10 @@ _log.debug(' (Nothing to add)') def _platform(self, filename): - platform_dir = self.ROOT_LAYOUT_TESTS_DIRECTORY + self._filesystem.sep + 'platform' + self._filesystem.sep + platform_dir = self._layout_tests_dir_name + self._filesystem.sep + 'platform' + self._filesystem.sep if filename.startswith(platform_dir): return filename.replace(platform_dir, '').split(self._filesystem.sep)[0] - platform_dir = self._filesystem.join(self._webkit_base, platform_dir) + platform_dir = self._filesystem.join(self._parent_of_tests, platform_dir) if filename.startswith(platform_dir): return filename.replace(platform_dir, '').split(self._filesystem.sep)[0] return '(generic)' @@ -190,8 +191,8 @@ def _baseline_root(self, baseline_name): virtual_suite = self._virtual_suite(baseline_name) if virtual_suite: - return self._filesystem.join(self.ROOT_LAYOUT_TESTS_DIRECTORY, virtual_suite.name) - return self.ROOT_LAYOUT_TESTS_DIRECTORY + return self._filesystem.join(self._layout_tests_dir_name, virtual_suite.name) + return self._layout_tests_dir_name def _baseline_search_path(self, port, baseline_name): virtual_suite = self._virtual_suite(baseline_name) @@ -209,7 +210,7 @@ """Returns a list of paths to check for baselines in order.""" baseline_search_path = self._baseline_search_path(port, baseline_name) baseline_root = self._baseline_root(baseline_name) - relative_paths = [self._filesystem.relpath(path, self._webkit_base) for path in baseline_search_path] + relative_paths = [self._filesystem.relpath(path, self._parent_of_tests) for path in baseline_search_path] return relative_paths + [baseline_root] def _join_directory(self, directory, baseline_name): @@ -226,7 +227,7 @@ baseline_name_without_virtual = baseline_name[len(virtual_suite.name) + 1:] else: baseline_name_without_virtual = baseline_name - return self._filesystem.join(self._webkit_base, directory, baseline_name_without_virtual) + return self._filesystem.join(self._parent_of_tests, directory, baseline_name_without_virtual) def _results_by_port_name(self, results_by_directory, baseline_name): results_by_port_name = {} @@ -241,7 +242,7 @@ def _directories_immediately_preceding_root(self, baseline_name): directories = set() for port in self._ports.values(): - directory = self._filesystem.relpath(self._baseline_search_path(port, baseline_name)[-1], self._webkit_base) + directory = self._filesystem.relpath(self._baseline_search_path(port, baseline_name)[-1], self._parent_of_tests) directories.add(directory) return directories
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer_unittest.py index 7514e04..f7f142ba 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer_unittest.py
@@ -38,20 +38,20 @@ def _assert_optimization(self, results_by_directory, directory_to_new_results, baseline_dirname='', host=None): host = host or MockHost() fs = host.filesystem - webkit_base = WebKitFinder(fs).webkit_base() + layout_tests_dir = WebKitFinder(fs).layout_tests_dir() baseline_name = 'mock-baseline-expected.txt' fs.write_text_file( - fs.join(webkit_base, 'LayoutTests', 'VirtualTestSuites'), + fs.join(layout_tests_dir, 'VirtualTestSuites'), '[{"prefix": "gpu", "base": "fast/canvas", "args": ["--foo"]}]') for dirname, contents in results_by_directory.items(): - fs.write_binary_file(fs.join(webkit_base, 'LayoutTests', dirname, baseline_name), contents) + fs.write_binary_file(fs.join(layout_tests_dir, dirname, baseline_name), contents) baseline_optimizer = BaselineOptimizer(host, host.port_factory.get(), host.port_factory.all_port_names()) self.assertTrue(baseline_optimizer.optimize(fs.join(baseline_dirname, baseline_name))) for dirname, contents in directory_to_new_results.items(): - path = fs.join(webkit_base, 'LayoutTests', dirname, baseline_name) + path = fs.join(layout_tests_dir, dirname, baseline_name) if contents is not None: self.assertEqual(fs.read_binary_file(path), contents)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_manifest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_manifest.py index d87b6474..e5863a0 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_manifest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_manifest.py
@@ -117,7 +117,7 @@ cmd = ['python', manifest_exec_path, '--work', '--tests-root', dest_path] _log.debug('Running command: %s', ' '.join(cmd)) - proc = executive.popen(cmd, stdout=executive.PIPE, stderr=executive.PIPE, stdin=executive.PIPE, cwd=finder.webkit_base()) + proc = executive.popen(cmd, stdout=executive.PIPE, stderr=executive.PIPE, stdin=executive.PIPE) out, err = proc.communicate('') if proc.returncode: _log.info('# ret> %d', proc.returncode)
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b796bbcd..6968841 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -16980,9 +16980,10 @@ </enum> <enum name="GeolocationSettingsDialogBackOff" type="int"> - <int value="0" label="One week"/> - <int value="1" label="One month"/> - <int value="2" label="Three months"/> + <int value="0" label="No backoff"/> + <int value="1" label="One week"/> + <int value="2" label="One month"/> + <int value="3" label="Three months"/> </enum> <enum name="GeopositionErrorCode" type="int"> @@ -21398,6 +21399,7 @@ <int value="-864205629" label="enable-offline-load-stale-cache"/> <int value="-861678473" label="disable-offer-upload-credit-cards"/> <int value="-861343291" label="ChromeHome:disabled"/> + <int value="-860534647" label="SiteDetails:enabled"/> <int value="-856915246" label="enable-new-audio-rendering-mixing-strategy"/> <int value="-856016114" label="NTPOfflinePages:disabled"/> <int value="-855130893" label="enable-touch-calibration-setting"/> @@ -21738,6 +21740,7 @@ <int value="546710806" label="disable-easy-signin"/> <int value="550378029" label="reset-app-list-install-state"/> <int value="550387510" label="NTPAssetDownloadSuggestions:disabled"/> + <int value="558873715" label="SiteDetails:disabled"/> <int value="562979188" label="DesktopIOSPromotion:enabled"/> <int value="567368307" label="enable-experimental-canvas-features"/> <int value="575394365" label="AndroidPaymentApps:disabled"/>
diff --git a/ui/arc/notification/arc_custom_notification_view.cc b/ui/arc/notification/arc_custom_notification_view.cc index 7c72f3a..d28a6dd7 100644 --- a/ui/arc/notification/arc_custom_notification_view.cc +++ b/ui/arc/notification/arc_custom_notification_view.cc
@@ -197,12 +197,6 @@ owner_->UpdateControlButtonsVisibility(); } - bool IsPinned() const override { - if (!owner_->item_) - return false; - return owner_->item_->pinned(); - } - void UpdateControlButtonsVisibility() override { owner_->UpdateControlButtonsVisibility(); }
diff --git a/ui/message_center/views/custom_notification_content_view_delegate.h b/ui/message_center/views/custom_notification_content_view_delegate.h index c61e8b9b..3d84d00 100644 --- a/ui/message_center/views/custom_notification_content_view_delegate.h +++ b/ui/message_center/views/custom_notification_content_view_delegate.h
@@ -21,7 +21,6 @@ public: virtual bool IsCloseButtonFocused() const = 0; virtual void RequestFocusOnCloseButton() = 0; - virtual bool IsPinned() const = 0; virtual void UpdateControlButtonsVisibility() = 0; };
diff --git a/ui/message_center/views/custom_notification_view.cc b/ui/message_center/views/custom_notification_view.cc index 324db5d..c20104b 100644 --- a/ui/message_center/views/custom_notification_view.cc +++ b/ui/message_center/views/custom_notification_view.cc
@@ -75,12 +75,6 @@ contents_view_delegate_->RequestFocusOnCloseButton(); } -bool CustomNotificationView::IsPinned() const { - if (!contents_view_delegate_) - return false; - return contents_view_delegate_->IsPinned(); -} - const char* CustomNotificationView::GetClassName() const { return kViewClassName; }
diff --git a/ui/message_center/views/custom_notification_view.h b/ui/message_center/views/custom_notification_view.h index 31b7a0d..6cd7f83a 100644 --- a/ui/message_center/views/custom_notification_view.h +++ b/ui/message_center/views/custom_notification_view.h
@@ -38,7 +38,6 @@ void SetDrawBackgroundAsActive(bool active) override; bool IsCloseButtonFocused() const override; void RequestFocusOnCloseButton() override; - bool IsPinned() const override; void UpdateControlButtonsVisibility() override; // Overridden from views::View:
diff --git a/ui/message_center/views/custom_notification_view_unittest.cc b/ui/message_center/views/custom_notification_view_unittest.cc index 3f1a3670..158e010 100644 --- a/ui/message_center/views/custom_notification_view_unittest.cc +++ b/ui/message_center/views/custom_notification_view_unittest.cc
@@ -76,7 +76,6 @@ public: bool IsCloseButtonFocused() const override { return false; } void RequestFocusOnCloseButton() override {} - bool IsPinned() const override { return false; } void UpdateControlButtonsVisibility() override {} };
diff --git a/ui/message_center/views/message_center_view.cc b/ui/message_center/views/message_center_view.cc index defba47..903f8b03 100644 --- a/ui/message_center/views/message_center_view.cc +++ b/ui/message_center/views/message_center_view.cc
@@ -643,7 +643,7 @@ if (mode_ == Mode::NOTIFICATIONS) { bool no_closable_views = true; for (const auto& view : notification_views_) { - if (!view.second->IsPinned()) { + if (!view.second->pinned()) { no_closable_views = false; break; } @@ -676,11 +676,11 @@ if ((*iter)->id() == id) { int old_width = view->width(); int old_height = view->height(); - bool old_pinned = view->IsPinned(); + bool old_pinned = view->pinned(); message_list_view_->UpdateNotification(view, **iter); if (view->GetHeightForWidth(old_width) != old_height) { Update(true /* animate */); - } else if (view->IsPinned() != old_pinned) { + } else if (view->pinned() != old_pinned) { // Animate flag is false, since the pinned flag transition doesn't need // animation. Update(false /* animate */);
diff --git a/ui/message_center/views/message_list_view.cc b/ui/message_center/views/message_list_view.cc index 06cce39..28cb247 100644 --- a/ui/message_center/views/message_list_view.cc +++ b/ui/message_center/views/message_list_view.cc
@@ -261,7 +261,7 @@ continue; if (gfx::IntersectRects(child->bounds(), visible_scroll_rect).IsEmpty()) continue; - if (child->IsPinned()) + if (child->pinned()) continue; if (deleting_views_.find(child) != deleting_views_.end() || deleted_when_done_.find(child) != deleted_when_done_.end()) { @@ -349,15 +349,17 @@ return; } - int new_height = GetHeightForWidth(child_area.width() + GetInsets().width()); - SetSize(gfx::Size(child_area.width() + GetInsets().width(), new_height)); - if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableMessageCenterAlwaysScrollUpUponNotificationRemoval)) AnimateNotificationsBelowTarget(); else AnimateNotifications(); + // Should calculate and set new size after calling AnimateNotifications() + // because fixed_height_ may be updated in it. + int new_height = GetHeightForWidth(child_area.width() + GetInsets().width()); + SetSize(gfx::Size(child_area.width() + GetInsets().width(), new_height)); + adding_views_.clear(); deleting_views_.clear();
diff --git a/ui/message_center/views/message_list_view_unittest.cc b/ui/message_center/views/message_list_view_unittest.cc index d6054ef..8d139a8 100644 --- a/ui/message_center/views/message_list_view_unittest.cc +++ b/ui/message_center/views/message_list_view_unittest.cc
@@ -24,6 +24,7 @@ namespace message_center { static const char* kNotificationId1 = "notification id 1"; +static const char* kNotificationId2 = "notification id 2"; namespace { @@ -131,6 +132,8 @@ int& fixed_height() { return message_list_view_->fixed_height_; } + views::BoundsAnimator& animator() { return message_list_view_->animator_; } + std::vector<int> ComputeRepositionOffsets(const std::vector<int>& heights, const std::vector<bool>& deleting, int target_index, @@ -144,6 +147,11 @@ return new MockNotificationView(this, notification, this); } + void RunPendingAnimations() { + while (animator().IsAnimating()) + RunPendingMessages(); + } + private: // MockNotificationView::Test override void RegisterCall(CallType type) override {} @@ -375,4 +383,73 @@ EXPECT_EQ(5 + top + 2, reposition_top()); } +TEST_F(MessageListViewTest, RemoveNotification) { + message_list_view()->SetBounds(0, 0, 800, 600); + + // Create dummy notifications. + auto* notification_view = CreateNotificationView( + Notification(NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1), + base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message1"), + gfx::Image(), base::UTF8ToUTF16("display source"), GURL(), + NotifierId(NotifierId::APPLICATION, "extension_id"), + message_center::RichNotificationData(), nullptr)); + + message_list_view()->AddNotificationAt(notification_view, 0); + EXPECT_EQ(1, message_list_view()->child_count()); + EXPECT_TRUE(message_list_view()->Contains(notification_view)); + + RunPendingAnimations(); + + message_list_view()->RemoveNotification(notification_view); + + RunPendingAnimations(); + + EXPECT_EQ(0, message_list_view()->child_count()); +} + +TEST_F(MessageListViewTest, ClearAllClosableNotifications) { + message_list_view()->SetBounds(0, 0, 800, 600); + + // Create dummy notifications. + auto* notification_view1 = CreateNotificationView( + Notification(NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1), + base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message1"), + gfx::Image(), base::UTF8ToUTF16("display source"), GURL(), + NotifierId(NotifierId::APPLICATION, "extension_id"), + message_center::RichNotificationData(), nullptr)); + auto* notification_view2 = CreateNotificationView( + Notification(NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2), + base::UTF8ToUTF16("title 2"), base::UTF8ToUTF16("message2"), + gfx::Image(), base::UTF8ToUTF16("display source"), GURL(), + NotifierId(NotifierId::APPLICATION, "extension_id"), + message_center::RichNotificationData(), nullptr)); + + message_list_view()->AddNotificationAt(notification_view1, 0); + EXPECT_EQ(1, message_list_view()->child_count()); + EXPECT_TRUE(notification_view1->visible()); + + RunPendingAnimations(); + + message_list_view()->AddNotificationAt(notification_view2, 1); + EXPECT_EQ(2, message_list_view()->child_count()); + EXPECT_TRUE(notification_view2->visible()); + + RunPendingAnimations(); + + message_list_view()->ClearAllClosableNotifications( + message_list_view()->bounds()); + + RunPendingAnimations(); + + // TODO(yhanada): notification_view1 and notification_view2 should be deleted + // here. Uncomment the below test. + EXPECT_TRUE(gfx::IntersectRects(notification_view1->bounds(), + message_list_view()->bounds()) + .IsEmpty()); + EXPECT_TRUE(gfx::IntersectRects(notification_view2->bounds(), + message_list_view()->bounds()) + .IsEmpty()); + // EXPECT_EQ(0, message_list_view()->child_count()); +} + } // namespace
diff --git a/ui/message_center/views/message_view.cc b/ui/message_center/views/message_view.cc index a1fa32c3..6d5aca2 100644 --- a/ui/message_center/views/message_view.cc +++ b/ui/message_center/views/message_view.cc
@@ -86,6 +86,7 @@ void MessageView::UpdateWithNotification(const Notification& notification) { display_source_ = notification.display_source(); + pinned_ = notification.pinned(); accessible_name_ = CreateAccessibleName(notification); slide_out_controller_.set_enabled(!notification.pinned()); }
diff --git a/ui/message_center/views/message_view.h b/ui/message_center/views/message_view.h index c35d5394..5942e777 100644 --- a/ui/message_center/views/message_view.h +++ b/ui/message_center/views/message_view.h
@@ -55,7 +55,6 @@ virtual bool IsCloseButtonFocused() const = 0; virtual void RequestFocusOnCloseButton() = 0; - virtual bool IsPinned() const = 0; virtual void UpdateControlButtonsVisibility() = 0; void OnCloseButtonPressed(); @@ -79,6 +78,7 @@ std::string notification_id() { return notification_id_; } NotifierId notifier_id() { return notifier_id_; } const base::string16& display_source() const { return display_source_; } + bool pinned() const { return pinned_; } void set_controller(MessageCenterController* controller) { controller_ = controller; @@ -108,6 +108,7 @@ base::string16 accessible_name_; base::string16 display_source_; + bool pinned_ = false; std::unique_ptr<views::Painter> focus_painter_;
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc index b12da67..1258273 100644 --- a/ui/message_center/views/notification_view.cc +++ b/ui/message_center/views/notification_view.cc
@@ -408,10 +408,6 @@ close_button_->RequestFocus(); } -bool NotificationView::IsPinned() const { - return !close_button_; -} - void NotificationView::CreateOrUpdateTitleView( const Notification& notification) { if (notification.title().empty()) {
diff --git a/ui/message_center/views/notification_view.h b/ui/message_center/views/notification_view.h index 127b5a9..0724bfd2 100644 --- a/ui/message_center/views/notification_view.h +++ b/ui/message_center/views/notification_view.h
@@ -54,7 +54,6 @@ void ButtonPressed(views::Button* sender, const ui::Event& event) override; bool IsCloseButtonFocused() const override; void RequestFocusOnCloseButton() override; - bool IsPinned() const override; void UpdateControlButtonsVisibility() override; protected:
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index cb53de4..3d050476 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -711,6 +711,8 @@ "test/slider_test_api.h", "test/test_layout_manager.cc", "test/test_layout_manager.h", + "test/test_layout_provider.cc", + "test/test_layout_provider.h", "test/test_platform_native_widget.h", "test/test_views.cc", "test/test_views.h",
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc index 2a15779b..c97fcf3e 100644 --- a/ui/views/bubble/bubble_frame_view.cc +++ b/ui/views/bubble/bubble_frame_view.cc
@@ -533,7 +533,9 @@ if (footnote_container_) size.Enlarge(0, footnote_container_->GetHeightForWidth(size.width())); - if (GetWidget()->widget_delegate()->AsDialogDelegate()) + DialogDelegate* dialog_delegate = + GetWidget()->widget_delegate()->AsDialogDelegate(); + if (dialog_delegate && dialog_delegate->ShouldSnapFrameWidth()) size.set_width(LayoutProvider::Get()->GetSnappedDialogWidth(size.width())); return size;
diff --git a/ui/views/bubble/bubble_frame_view_unittest.cc b/ui/views/bubble/bubble_frame_view_unittest.cc index 705e1774..bcd120b6 100644 --- a/ui/views/bubble/bubble_frame_view_unittest.cc +++ b/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -14,6 +14,7 @@ #include "ui/views/bubble/bubble_border.h" #include "ui/views/bubble/bubble_dialog_delegate.h" #include "ui/views/controls/button/label_button.h" +#include "ui/views/test/test_layout_provider.h" #include "ui/views/test/test_views.h" #include "ui/views/test/views_test_base.h" #include "ui/views/widget/widget.h" @@ -502,44 +503,32 @@ using BubbleDialogDelegateView::SetAnchorView; + void set_override_snap(bool value) { override_snap_ = value; } + // BubbleDialogDelegateView: void DeleteDelegate() override { // This delegate is owned by the test case itself, so it should not delete // itself here. } - int GetDialogButtons() const override { return ui::DIALOG_BUTTON_NONE; } - + bool ShouldSnapFrameWidth() const override { + return override_snap_.value_or( + BubbleDialogDelegateView::ShouldSnapFrameWidth()); + } gfx::Size GetPreferredSize() const override { return gfx::Size(200, 200); } private: + base::Optional<bool> override_snap_; + DISALLOW_COPY_AND_ASSIGN(TestBubbleDialogDelegateView); }; -class TestLayoutProvider : public LayoutProvider { - public: - TestLayoutProvider() : LayoutProvider() {} - ~TestLayoutProvider() override {} - - // LayoutProvider: - int GetSnappedDialogWidth(int min_width) const override { - return snap_to_ ? snap_to_ : min_width; - } - - void set_snap_to(int width) { snap_to_ = width; } - - private: - int snap_to_ = 0; - - DISALLOW_COPY_AND_ASSIGN(TestLayoutProvider); -}; - } // namespace // This test ensures that if the installed LayoutProvider snaps dialog widths, // BubbleFrameView correctly sizes itself to that width. TEST_F(BubbleFrameViewTest, WidthSnaps) { - TestLayoutProvider provider; + test::TestLayoutProvider provider; TestBubbleDialogDelegateView delegate; Widget anchor; @@ -558,7 +547,7 @@ w0->CloseNow(); constexpr int kTestWidth = 300; - provider.set_snap_to(kTestWidth); + provider.SetSnappedDialogWidth(kTestWidth); // The Widget's snapped width should exactly match the width returned by the // LayoutProvider. @@ -566,6 +555,14 @@ w1->Show(); EXPECT_EQ(kTestWidth, w1->GetWindowBoundsInScreen().width()); w1->CloseNow(); + + // If the DialogDelegate asks not to snap, it should not snap. + delegate.set_override_snap(false); + Widget* w2 = BubbleDialogDelegateView::CreateBubble(&delegate); + w2->Show(); + EXPECT_EQ(delegate.GetPreferredSize().width(), + w2->GetWindowBoundsInScreen().width()); + w2->CloseNow(); } } // namespace views
diff --git a/ui/views/layout/layout_provider.cc b/ui/views/layout/layout_provider.cc index 3cb034c..5d2f86b 100644 --- a/ui/views/layout/layout_provider.cc +++ b/ui/views/layout/layout_provider.cc
@@ -56,6 +56,10 @@ int LayoutProvider::GetDistanceMetric(int metric) const { DCHECK_GE(metric, VIEWS_INSETS_MAX); switch (metric) { + case DistanceMetric::DISTANCE_BUTTON_HORIZONTAL_PADDING: + return kButtonHorizontalPadding; + case DistanceMetric::DISTANCE_BUTTON_MAX_LINKABLE_WIDTH: + return 0; case DistanceMetric::DISTANCE_CLOSE_BUTTON_MARGIN: return kCloseButtonMargin; case DistanceMetric::DISTANCE_RELATED_BUTTON_HORIZONTAL: @@ -66,8 +70,6 @@ return kRelatedControlVerticalSpacing; case DistanceMetric::DISTANCE_DIALOG_BUTTON_MINIMUM_WIDTH: return kDialogMinimumButtonWidth; - case DistanceMetric::DISTANCE_BUTTON_HORIZONTAL_PADDING: - return kButtonHorizontalPadding; } NOTREACHED(); return 0;
diff --git a/ui/views/layout/layout_provider.h b/ui/views/layout/layout_provider.h index f6b9640..71c8f7ee 100644 --- a/ui/views/layout/layout_provider.h +++ b/ui/views/layout/layout_provider.h
@@ -48,6 +48,10 @@ // The default padding to add on each side of a button's label. DISTANCE_BUTTON_HORIZONTAL_PADDING = VIEWS_DISTANCE_START, + // The maximum width a button can have and still influence the sizes of + // other linked buttons. This allows short buttons to have linked widths + // without long buttons making things overly wide. + DISTANCE_BUTTON_MAX_LINKABLE_WIDTH, // The distance between a dialog's edge and the close button in the upper // trailing corner. DISTANCE_CLOSE_BUTTON_MARGIN,
diff --git a/ui/views/test/test_layout_provider.cc b/ui/views/test/test_layout_provider.cc new file mode 100644 index 0000000..a2f3fda --- /dev/null +++ b/ui/views/test/test_layout_provider.cc
@@ -0,0 +1,31 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/views/test/test_layout_provider.h" + +namespace views { +namespace test { + +TestLayoutProvider::TestLayoutProvider() {} +TestLayoutProvider::~TestLayoutProvider() {} + +void TestLayoutProvider::SetDistanceMetric(int metric, int value) { + distance_metrics_[metric] = value; +} +void TestLayoutProvider::SetSnappedDialogWidth(int width) { + snapped_dialog_width_ = width; +} + +int TestLayoutProvider::GetDistanceMetric(int metric) const { + if (distance_metrics_.count(metric)) + return distance_metrics_.find(metric)->second; + return LayoutProvider::GetDistanceMetric(metric); +} + +int TestLayoutProvider::GetSnappedDialogWidth(int min_width) const { + return snapped_dialog_width_ ? snapped_dialog_width_ : min_width; +} + +} // namespace test +} // namespace views
diff --git a/ui/views/test/test_layout_provider.h b/ui/views/test/test_layout_provider.h new file mode 100644 index 0000000..ede0b65c --- /dev/null +++ b/ui/views/test/test_layout_provider.h
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_VIEWS_TEST_TEST_LAYOUT_PROVIDER_H_ +#define UI_VIEWS_TEST_TEST_LAYOUT_PROVIDER_H_ + +#include <map> + +#include "base/macros.h" +#include "ui/views/layout/layout_provider.h" + +namespace views { +namespace test { + +// Helper to test LayoutProvider overrides. +class TestLayoutProvider : public LayoutProvider { + public: + TestLayoutProvider(); + ~TestLayoutProvider() override; + + // Override requests for the |metric| DistanceMetric to return |value| rather + // than the default. + void SetDistanceMetric(int metric, int value); + + // Override the return value of GetSnappedDialogWidth(). + void SetSnappedDialogWidth(int width); + + // LayoutProvider: + int GetDistanceMetric(int metric) const override; + int GetSnappedDialogWidth(int min_width) const override; + + private: + std::map<int, int> distance_metrics_; + int snapped_dialog_width_ = 0; + + DISALLOW_COPY_AND_ASSIGN(TestLayoutProvider); +}; + +} // namespace test +} // namespace views + +#endif // UI_VIEWS_TEST_TEST_LAYOUT_PROVIDER_H_
diff --git a/ui/views/window/dialog_client_view.cc b/ui/views/window/dialog_client_view.cc index 3de458f..775f54d9 100644 --- a/ui/views/window/dialog_client_view.cc +++ b/ui/views/window/dialog_client_view.cc
@@ -338,12 +338,13 @@ return; gfx::Insets insets = button_row_insets_; + LayoutProvider* const layout_provider = LayoutProvider::Get(); // Support dialogs that clear |button_row_insets_| to do their own layout. // They expect GetDialogRelatedControlVerticalSpacing() in this case. // TODO(tapted): Remove this under Harmony. if (insets.top() == 0) { - const int top = LayoutProvider::Get()->GetDistanceMetric( - views::DISTANCE_RELATED_CONTROL_VERTICAL); + const int top = + layout_provider->GetDistanceMetric(DISTANCE_RELATED_CONTROL_VERTICAL); insets.Set(top, insets.left(), insets.bottom(), insets.right()); } @@ -355,11 +356,10 @@ // Button row is [ extra <pad+stretchy> second <pad> third ]. Ensure the <pad> // column is zero width if there isn't a button on either side. // GetExtraViewSpacing() handles <pad+stretchy>. - const int button_spacing = - (ok_button_ && cancel_button_) - ? LayoutProvider::Get()->GetDistanceMetric( - views::DISTANCE_RELATED_BUTTON_HORIZONTAL) - : 0; + const int button_spacing = (ok_button_ && cancel_button_) + ? layout_provider->GetDistanceMetric( + DISTANCE_RELATED_BUTTON_HORIZONTAL) + : 0; constexpr int kButtonRowId = 0; ColumnSet* column_set = layout->AddColumnSet(kButtonRowId); @@ -392,18 +392,20 @@ } } - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { - // If |views[0]| is non-null, it is a visible |extra_view_| and its column - // will be in |link[0]|. Skip that if it is not a button, or if it is a - // Checkbox (which extends LabelButton). Otherwise, link everything. - bool skip_first_link = - views[0] && (!CustomButton::AsCustomButton(views[0]) || - views[0]->GetClassName() == Checkbox::kViewClassName); - if (skip_first_link) - column_set->LinkColumnSizes(link[1], link[2], -1); - else - column_set->LinkColumnSizes(link[0], link[1], link[2], -1); - } + column_set->set_linked_column_size_limit( + layout_provider->GetDistanceMetric(DISTANCE_BUTTON_MAX_LINKABLE_WIDTH)); + + // If |views[0]| is non-null, it is a visible |extra_view_| and its column + // will be in |link[0]|. Skip that if it is not a button, or if it is a + // Checkbox (which extends LabelButton). Otherwise, link everything. + bool skip_first_link = + views[0] && (!CustomButton::AsCustomButton(views[0]) || + views[0]->GetClassName() == Checkbox::kViewClassName); + if (skip_first_link) + column_set->LinkColumnSizes(link[1], link[2], -1); + else + column_set->LinkColumnSizes(link[0], link[1], link[2], -1); + layout->AddPaddingRow(kFixed, insets.bottom()); }
diff --git a/ui/views/window/dialog_client_view_unittest.cc b/ui/views/window/dialog_client_view_unittest.cc index 26ef3e30..877cdb8 100644 --- a/ui/views/window/dialog_client_view_unittest.cc +++ b/ui/views/window/dialog_client_view_unittest.cc
@@ -4,14 +4,16 @@ #include "ui/views/window/dialog_client_view.h" +#include <map> + #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "ui/base/test/material_design_controller_test_api.h" #include "ui/base/ui_base_types.h" #include "ui/views/controls/button/checkbox.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/style/platform_style.h" +#include "ui/views/test/test_layout_provider.h" #include "ui/views/test/test_views.h" #include "ui/views/test/widget_test.h" #include "ui/views/widget/widget.h" @@ -131,7 +133,8 @@ } // Set a longer than normal Cancel label so that the minimum button width is - // exceeded. + // exceeded. The resulting width is around 160 pixels, but depends on system + // fonts. void SetLongCancelLabel() { cancel_label_ = base::ASCIIToUTF16("Cancel Cancel Cancel"); } @@ -360,9 +363,8 @@ // Ensure button widths are linked under MD. TEST_F(DialogClientViewTest, LinkedWidths) { - ui::test::MaterialDesignControllerTestAPI md_test_api( - ui::MaterialDesignController::MATERIAL_NORMAL); - md_test_api.SetSecondaryUiMaterial(true); + test::TestLayoutProvider layout_provider; + layout_provider.SetDistanceMetric(DISTANCE_BUTTON_MAX_LINKABLE_WIDTH, 200); SetLongCancelLabel(); SetDialogButtons(ui::DIALOG_BUTTON_OK); @@ -372,6 +374,7 @@ SetDialogButtons(ui::DIALOG_BUTTON_CANCEL); CheckContentsIsSetToPreferredSize(); const int cancel_button_width = client_view()->cancel_button()->width(); + EXPECT_LT(cancel_button_width, 200); // Ensure the single buttons have different preferred widths when alone, and // that the Cancel button is bigger (so that it dominates the size). @@ -383,12 +386,14 @@ // OK button should now match the bigger, cancel button. EXPECT_EQ(cancel_button_width, client_view()->ok_button()->width()); - // But not under non-MD. - md_test_api.SetSecondaryUiMaterial(false); + // But not when the size of the cancel button exceeds the max linkable width. + layout_provider.SetDistanceMetric(DISTANCE_BUTTON_MAX_LINKABLE_WIDTH, 100); + EXPECT_GT(cancel_button_width, 100); + client_view()->UpdateDialogButtons(); CheckContentsIsSetToPreferredSize(); EXPECT_EQ(ok_button_only_width, client_view()->ok_button()->width()); - md_test_api.SetSecondaryUiMaterial(true); + layout_provider.SetDistanceMetric(DISTANCE_BUTTON_MAX_LINKABLE_WIDTH, 200); // The extra view should also match, if it's a matching button type. LabelButton* extra_button = new LabelButton(nullptr, base::string16());
diff --git a/ui/views/window/dialog_delegate.cc b/ui/views/window/dialog_delegate.cc index 6af25ee..d354353 100644 --- a/ui/views/window/dialog_delegate.cc +++ b/ui/views/window/dialog_delegate.cc
@@ -132,6 +132,10 @@ button->SetIsDefault(is_default); } +bool DialogDelegate::ShouldSnapFrameWidth() const { + return true; +} + int DialogDelegate::GetDialogButtons() const { return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL; }
diff --git a/ui/views/window/dialog_delegate.h b/ui/views/window/dialog_delegate.h index 6a11e65..9f19c73 100644 --- a/ui/views/window/dialog_delegate.h +++ b/ui/views/window/dialog_delegate.h
@@ -88,6 +88,10 @@ // the typical. virtual void UpdateButton(LabelButton* button, ui::DialogButton type); + // Returns true if this dialog should snap the frame width based on the + // LayoutProvider's snapping. + virtual bool ShouldSnapFrameWidth() const; + // Overridden from ui::DialogModel: int GetDialogButtons() const override; int GetDefaultDialogButton() const override;
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html index a14fe6d..0b6fa0f 100644 --- a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html +++ b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
@@ -128,8 +128,8 @@ -webkit-margin-start: var(--cr-control-spacing); } </style> - <template is="dom-if" if="[[isSpinnerShown_]]"> - <paper-spinner-lite active> + <template is="dom-if" id="spinnerTemplate"> + <paper-spinner-lite active="[[isSpinnerShown_]]"> </paper-spinner-lite> </template> <paper-icon-button id="icon" icon="cr:search" title="[[label]]"
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js index 432c828..0f4f1a5 100644 --- a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js +++ b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js
@@ -94,7 +94,10 @@ * @private */ computeIsSpinnerShown_: function() { - return this.spinnerActive && this.showingSearch; + var showSpinner = this.spinnerActive && this.showingSearch; + if (showSpinner) + this.$.spinnerTemplate.if = true; + return showSpinner; }, /** @private */
diff --git a/ui/webui/resources/js/cr/ui/splitter.js b/ui/webui/resources/js/cr/ui/splitter.js index b4260e1..b655f5b 100644 --- a/ui/webui/resources/js/cr/ui/splitter.js +++ b/ui/webui/resources/js/cr/ui/splitter.js
@@ -233,11 +233,15 @@ */ handleSplitterDragStart: function() { // Use the computed width style as the base so that we can ignore what - // box sizing the element has. + // box sizing the element has. Add the difference between offset and + // client widths to account for any scrollbars. var targetElement = this.getResizeTarget_(); var doc = targetElement.ownerDocument; this.startWidth_ = - parseFloat(doc.defaultView.getComputedStyle(targetElement).width); + parseFloat(doc.defaultView.getComputedStyle(targetElement).width) + + targetElement.offsetWidth - targetElement.clientWidth; + + this.classList.add('splitter-active'); }, /** @@ -265,6 +269,8 @@ parseFloat(doc.defaultView.getComputedStyle(targetElement).width); if (this.startWidth_ != computedWidth) cr.dispatchSimpleEvent(this, 'resize'); + + this.classList.remove('splitter-active'); }, };