diff --git a/DEPS b/DEPS index 0eabb67..693a8341 100644 --- a/DEPS +++ b/DEPS
@@ -36,7 +36,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '52d1be5ca7b1ba8cc450be7dd6377ea5bb73386a', + 'skia_revision': 'a2b9fdfe0b2dd3408064b7cfd1bf8677eaf06491', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -88,7 +88,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': 'b4a21633262e2062c6daca42dce7a3316f2bf922', + 'catapult_revision': 'c1a1d1b3ed6c100bc0ae7ff7812be4d9a193de9d', # 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/VERSION b/chrome/VERSION index 339717c..8d50071b 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=54 MINOR=0 -BUILD=2818 +BUILD=2819 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java index 5480867..7b918df 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java
@@ -90,6 +90,25 @@ /** The number of possible actions. */ private static final int NUM_SNIPPETS_ACTIONS = 7; + /** Possible ways to follow the link provided by a snippet. + * Do not remove or change existing values other than NUM_OPEN_SNIPPET_METHODS. */ + @IntDef({OPEN_SNIPPET_METHODS_PLAIN_CLICK, OPEN_SNIPPET_METHODS_NEW_WINDOW, + OPEN_SNIPPET_METHODS_NEW_TAB, OPEN_SNIPPET_METHODS_INCOGNITO, + OPEN_SNIPPET_METHODS_SAVE_FOR_OFFLINE, NUM_OPEN_SNIPPET_METHODS}) + @Retention(RetentionPolicy.SOURCE) + public @interface OpenSnippetMethod {} + /** The article was opened taking over the tab. */ + public static final int OPEN_SNIPPET_METHODS_PLAIN_CLICK = 0; + /** The article was opened in a new window. */ + public static final int OPEN_SNIPPET_METHODS_NEW_WINDOW = 1; + /** The article was opened in a new tab, */ + public static final int OPEN_SNIPPET_METHODS_NEW_TAB = 2; + /** The article was opened in an incognito tab. */ + public static final int OPEN_SNIPPET_METHODS_INCOGNITO = 3; + /** The article was saved to be viewed offline. */ + public static final int OPEN_SNIPPET_METHODS_SAVE_FOR_OFFLINE = 4; + /** The number of ways an article can be viewed. */ + public static final int NUM_OPEN_SNIPPET_METHODS = 5; /** * Records an action taken by the user on the NTP. * @param action One of the ACTION_* values defined in this class. @@ -163,6 +182,15 @@ } /** + * Records how the article linked from a snippet was viewed. + * @param method method key, one of {@link OpenSnippetMethod}'s values. + */ + public static void recordOpenSnippetMethod(@OpenSnippetMethod int method) { + RecordHistogram.recordEnumeratedHistogram( + "NewTabPage.Snippets.OpenMethod", method, NUM_OPEN_SNIPPET_METHODS); + } + + /** * Record a NTP impression (even potential ones to make informed product decisions). * @param impressionType Type of the impression from NewTabPageUma.java */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java index 86ebfd4..10b98b9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -680,12 +680,18 @@ if (mDisableUrlFocusChangeAnimations) return; float percent = mSearchProviderHasLogo ? mUrlFocusChangePercent : 0; - // Only apply the scrolling offset when not using the cards UI, as there we will either snap - // to the top of the page (with scrolling offset 0), or snap to below the fold, where Most - // Likely items are not visible anymore, so they will stay out of sight. - int scrollOffset = mUseCardsUi ? 0 : mScrollView.getScrollY(); - mNewTabPageLayout.setTranslationY(percent * (-mMostVisitedLayout.getTop() + scrollOffset - + mNewTabPageLayout.getPaddingTop())); + + int basePosition = getVerticalScroll() + mNewTabPageLayout.getPaddingTop(); + int target; + if (mUseCardsUi) { + // Cards UI: translate so that the search box is at the top, but only upwards. + target = Math.max(basePosition, + mSearchBoxView.getBottom() - mSearchBoxView.getPaddingBottom()); + } else { + // Otherwise: translate so that Most Visited is right below the omnibox. + target = mMostVisitedLayout.getTop(); + } + mNewTabPageLayout.setTranslationY(percent * (basePosition - target)); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleListItem.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleListItem.java index 59cb780..00e6715 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleListItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleListItem.java
@@ -6,7 +6,6 @@ import android.graphics.Bitmap; import org.chromium.base.metrics.RecordHistogram; -import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.browser.ntp.NewTabPageUma; import org.chromium.chrome.browser.ntp.cards.NewTabPageListItem; @@ -88,10 +87,17 @@ /** Tracks click on this NTP snippet in UMA. */ public void trackClick() { - RecordUserAction.record("MobileNTP.Snippets.Click"); + // To compare against NewTabPage.Snippets.CardShown for each position. RecordHistogram.recordSparseSlowlyHistogram("NewTabPage.Snippets.CardClicked", mPosition); + // To compare against all snippets actions. NewTabPageUma.recordSnippetAction(NewTabPageUma.SNIPPETS_ACTION_CLICKED); + // To compare how the user views the article linked to from a snippet (eg. as opposed to + // opening in a new tab). + NewTabPageUma.recordOpenSnippetMethod(NewTabPageUma.OPEN_SNIPPET_METHODS_PLAIN_CLICK); + // To see how users left the NTP. NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_SNIPPET); + // To see whether users click on more recent snippets and whether our suggestion algorithm + // is accurate. recordAgeAndScore("NewTabPage.Snippets.CardClicked"); } @@ -110,7 +116,7 @@ return mImpressionTracked; } - private void recordAgeAndScore(String histogramPrefix) { + public void recordAgeAndScore(String histogramPrefix) { // Track how the (approx.) position relates to age / score of the snippet that is clicked. int ageInMinutes = (int) ((System.currentTimeMillis() - mPublishTimestampMilliseconds) / 60000L);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java index 5a32a565..e0980f6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
@@ -24,11 +24,13 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; import org.chromium.chrome.browser.favicon.FaviconHelper.FaviconImageCallback; import org.chromium.chrome.browser.favicon.FaviconHelper.IconAvailabilityCallback; import org.chromium.chrome.browser.ntp.DisplayStyleObserver; import org.chromium.chrome.browser.ntp.NewTabPage; +import org.chromium.chrome.browser.ntp.NewTabPageUma; import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager; import org.chromium.chrome.browser.ntp.UiConfig; import org.chromium.chrome.browser.ntp.cards.CardViewHolder; @@ -148,6 +150,10 @@ @Override protected void createContextMenu(ContextMenu menu) { + RecordHistogram.recordSparseSlowlyHistogram( + "NewTabPage.Snippets.CardLongPressed", mArticle.mPosition); + mArticle.recordAgeAndScore("NewTabPage.Snippets.CardLongPressed"); + // Create a context menu akin to the one shown for MostVisitedItems. if (mNewTabPageManager.isOpenInNewWindowEnabled()) { addContextMenuItem(menu, ID_OPEN_IN_NEW_WINDOW, R.string.contextmenu_open_in_new_tab); @@ -172,18 +178,26 @@ @Override public boolean onMenuItemClick(MenuItem item) { + // The UMA is used to compare how the user views the article linked from a snippet. switch (item.getItemId()) { case ID_OPEN_IN_NEW_WINDOW: + NewTabPageUma.recordOpenSnippetMethod( + NewTabPageUma.OPEN_SNIPPET_METHODS_NEW_WINDOW); mNewTabPageManager.openUrlInNewWindow(mArticle.mUrl); return true; case ID_OPEN_IN_NEW_TAB: + NewTabPageUma.recordOpenSnippetMethod( + NewTabPageUma.OPEN_SNIPPET_METHODS_NEW_TAB); mNewTabPageManager.openUrlInNewTab(mArticle.mUrl, false); return true; case ID_OPEN_IN_INCOGNITO_TAB: + NewTabPageUma.recordOpenSnippetMethod( + NewTabPageUma.OPEN_SNIPPET_METHODS_INCOGNITO); mNewTabPageManager.openUrlInNewTab(mArticle.mUrl, true); return true; case ID_REMOVE: assert isDismissable() : "Context menu should not be shown for peeking card."; + // UMA is recorded during dismissal. dismiss(); return true; default:
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java index c9efca6..49a8e4f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -50,7 +50,7 @@ private static final String[] FAKE_MOST_VISITED_TITLES = new String[] { "Simple" }; private static final String[] FAKE_MOST_VISITED_WHITELIST_ICON_PATHS = new String[] { "" }; - private static final int[] FAKE_MOST_VISITED_SOURCES = new int[] {MostVisitedSource.TOP_SITES}; + private static final int[] FAKE_MOST_VISITED_SOURCES = new int[] {NTPTileSource.TOP_SITES}; private Tab mTab; private NewTabPage mNtp;
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 995efd84..54438e4 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -488,7 +488,7 @@ &Edit </message> <if expr="is_macosx"> - <message name="IDS_ACCNAME_TAB" desc="A generic description of a tab button's role"> + <message name="IDS_ACCNAME_TAB" desc="A generic description of a tab button's role" meaning="UI element"> Tab </message> </if>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index e06278f..5ce5565 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -22,13 +22,6 @@ import("//build/config/linux/pkg_config.gni") } -declare_args() { - # 'Ok Google' hotwording is disabled by default. Set to true to enable. (This - # will download a closed-source NaCl module at startup.) Chrome-branded - # ChromeOS builds have this enabled by default. - enable_hotwording = is_chrome_branded && is_chromeos -} - additional_modules_list_file = "$root_gen_dir/chrome/browser/internal/additional_modules_list.txt"
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.cc b/chrome/browser/android/ntp/most_visited_sites_bridge.cc index d91cc89..7951f94 100644 --- a/chrome/browser/android/ntp/most_visited_sites_bridge.cc +++ b/chrome/browser/android/ntp/most_visited_sites_bridge.cc
@@ -97,8 +97,7 @@ public: JavaObserver(JNIEnv* env, const JavaParamRef<jobject>& obj); - void OnMostVisitedURLsAvailable( - const MostVisitedSites::SuggestionsVector& suggestions) override; + void OnMostVisitedURLsAvailable(const NTPTilesVector& tiles) override; void OnPopularURLsAvailable( const MostVisitedSites::PopularSitesVector& sites) override; @@ -115,22 +114,22 @@ : observer_(env, obj) {} void MostVisitedSitesBridge::JavaObserver::OnMostVisitedURLsAvailable( - const MostVisitedSites::SuggestionsVector& suggestions) { + const NTPTilesVector& tiles) { JNIEnv* env = AttachCurrentThread(); std::vector<base::string16> titles; std::vector<std::string> urls; std::vector<std::string> whitelist_icon_paths; std::vector<int> sources; - titles.reserve(suggestions.size()); - urls.reserve(suggestions.size()); - whitelist_icon_paths.reserve(suggestions.size()); - sources.reserve(suggestions.size()); - for (const auto& suggestion : suggestions) { - titles.emplace_back(suggestion.title); - urls.emplace_back(suggestion.url.spec()); - whitelist_icon_paths.emplace_back(suggestion.whitelist_icon_path.value()); - sources.emplace_back(suggestion.source); + titles.reserve(tiles.size()); + urls.reserve(tiles.size()); + whitelist_icon_paths.reserve(tiles.size()); + sources.reserve(tiles.size()); + for (const auto& tile : tiles) { + titles.emplace_back(tile.title); + urls.emplace_back(tile.url.spec()); + whitelist_icon_paths.emplace_back(tile.whitelist_icon_path.value()); + sources.emplace_back(static_cast<int>(tile.source)); } Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable( env, observer_.obj(), ToJavaArrayOfStrings(env, titles).obj(),
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.h b/chrome/browser/android/ntp/most_visited_sites_bridge.h index d039373..915f557 100644 --- a/chrome/browser/android/ntp/most_visited_sites_bridge.h +++ b/chrome/browser/android/ntp/most_visited_sites_bridge.h
@@ -18,6 +18,8 @@ #include "chrome/browser/supervised_user/supervised_user_service_observer.h" #include "components/ntp_tiles/most_visited_sites.h" +using ntp_tiles::NTPTilesVector; + class Profile; // Provides the list of most visited sites and their thumbnails to Java.
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 0000525..4ec2b76 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -4,6 +4,7 @@ import("//build/config/features.gni") import("//build/config/ui.gni") +import("//chrome/common/features.gni") assert(enable_extensions) @@ -108,13 +109,6 @@ "//url", ] - if (enable_task_manager) { - sources += rebase_path( - gypi_values.chrome_browser_extensions_task_manager_enabled_sources, - ".", - "//chrome") - } - if (is_chromeos) { sources += rebase_path(gypi_values.chrome_browser_extensions_chromeos_sources, @@ -128,6 +122,7 @@ "//components/chrome_apps", "//remoting/host/it2me:common", "//third_party/protobuf:protobuf_lite", + "//ui/file_manager:resources", ] } else { sources += [ @@ -140,31 +135,19 @@ "//chrome") } - if (enable_service_discovery) { - sources += rebase_path( - gypi_values.chrome_browser_extensions_service_discovery_sources, - ".", - "//chrome") - } - - if (use_ash) { - sources += [ - "api/tabs/ash_panel_contents.cc", - "api/tabs/ash_panel_contents.h", - ] - deps += [ "//ash" ] - } - - if (use_aura) { - deps += [ - "//ui/keyboard", - "//ui/keyboard:keyboard_with_content", - "//ui/keyboard:resources", + # chromeos uses its own global_shortcut_listener, _x11 is not necessary. + if (is_chromeos || !use_x11) { + sources -= [ + "global_shortcut_listener_x11.cc", + "global_shortcut_listener_x11.h", ] } - if (toolkit_views) { - deps += [ "//ui/views" ] + if (is_chromeos && use_ozone) { + sources -= [ "global_shortcut_listener_chromeos.cc" ] + } + if (!use_ozone) { + sources -= [ "global_shortcut_listener_ozone.cc" ] } if (is_linux) { @@ -190,30 +173,6 @@ } } - if (enable_webrtc) { - sources += [ "api/webrtc_logging_private/webrtc_logging_private_api.cc" ] - } else { - sources += - [ "api/webrtc_logging_private/webrtc_logging_private_api_stub.cc" ] - } - - if (use_brlapi) { - deps += [ "//build/linux/libbrlapi" ] - sources += rebase_path(gypi_values.chrome_browser_extensions_brlapi_sources, - ".", - "//chrome") - } else { - sources += [ "api/braille_display_private/braille_controller_stub.cc" ] - } - - # chromeos uses its own global_shortcut_listener, _x11 is not necessary. - if (is_chromeos || !use_x11) { - sources -= [ - "global_shortcut_listener_x11.cc", - "global_shortcut_listener_x11.h", - ] - } - if (is_win || is_mac) { deps += [ "//components/wifi" ] sources += rebase_path( @@ -245,10 +204,57 @@ "//chrome") } - if (is_chromeos && use_ozone) { - sources -= [ "global_shortcut_listener_chromeos.cc" ] + if (enable_hotwording) { + defines += [ "ENABLE_HOTWORDING" ] } - if (!use_ozone) { - sources -= [ "global_shortcut_listener_ozone.cc" ] + + if (enable_service_discovery) { + sources += rebase_path( + gypi_values.chrome_browser_extensions_service_discovery_sources, + ".", + "//chrome") + } + + if (enable_task_manager) { + sources += rebase_path( + gypi_values.chrome_browser_extensions_task_manager_enabled_sources, + ".", + "//chrome") + } + + if (enable_webrtc) { + sources += [ "api/webrtc_logging_private/webrtc_logging_private_api.cc" ] + } else { + sources += + [ "api/webrtc_logging_private/webrtc_logging_private_api_stub.cc" ] + } + + if (toolkit_views) { + deps += [ "//ui/views" ] + } + + if (use_ash) { + sources += [ + "api/tabs/ash_panel_contents.cc", + "api/tabs/ash_panel_contents.h", + ] + deps += [ "//ash" ] + } + + if (use_aura) { + deps += [ + "//ui/keyboard", + "//ui/keyboard:keyboard_with_content", + "//ui/keyboard:resources", + ] + } + + if (use_brlapi) { + deps += [ "//build/linux/libbrlapi" ] + sources += rebase_path(gypi_values.chrome_browser_extensions_brlapi_sources, + ".", + "//chrome") + } else { + sources += [ "api/braille_display_private/braille_controller_stub.cc" ] } }
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd index ab5c70f..31afaa5 100644 --- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd +++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -1107,7 +1107,7 @@ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'status' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_STATUS_BRL"> sts </message> - <message desc="Describes an element with the ARIA role tab." name="IDS_CHROMEVOX_ROLE_TAB"> + <message desc="Describes an element with the ARIA role tab." name="IDS_CHROMEVOX_ROLE_TAB" meaning="UI element"> Tab </message> <message desc="This is an ARIA widget role name shown on a braille display. If the translation is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TAB_BRL">
diff --git a/chrome/browser/resources/md_history/history_item.html b/chrome/browser/resources/md_history/history_item.html index 0c0a971..44bb6c6 100644 --- a/chrome/browser/resources/md_history/history_item.html +++ b/chrome/browser/resources/md_history/history_item.html
@@ -22,7 +22,6 @@ :host(:not([embedded])) #main-container { background: #fff; border-color: var(--card-border-color); - border-radius: 2px; border-style: solid; border-width: 0 1px; } @@ -36,14 +35,20 @@ } :host([is-card-start]) #main-container { + border-radius: 2px 2px 0 0; border-top-width: 1px; } :host([is-card-end]) #main-container { border-bottom-width: 2px; + border-radius: 0 0 2px 2px; margin-bottom: var(--card-padding-between); } + :host([is-card-start][is-card-end]) #main-container { + border-radius: 2px; + } + #date-accessed { display: none; } @@ -97,24 +102,15 @@ #menu-button { -webkit-margin-end: 12px; - -webkit-margin-start: 2px; - color: var(--secondary-text-color); - height: 36px; - width: 36px; - } - - #menu-button iron-icon { - height: 20px; - width: 20px; } #bookmark-star { - -webkit-margin-end: 10px; - -webkit-margin-start: 20px; + -webkit-margin-end: 4px; + -webkit-margin-start: 12px; color: rgb(68, 136, 255); - height: 20px; + height: 32px; visibility: hidden; - width: 20px; + width: 32px; } #bookmark-star iron-icon { @@ -156,7 +152,8 @@ <iron-icon icon="cr:star"></iron-icon> </button> <button is="paper-icon-button-light" id="menu-button" - on-tap="onMenuButtonTap_" title="$i18n{moreActionsButton}"> + class="icon-button" title="$i18n{moreActionsButton}" + on-tap="onMenuButtonTap_"> <iron-icon icon="cr:more-vert"></iron-icon> </button> </div>
diff --git a/chrome/browser/resources/md_history/shared_style.html b/chrome/browser/resources/md_history/shared_style.html index 26c7ed2..1e3d1a4 100644 --- a/chrome/browser/resources/md_history/shared_style.html +++ b/chrome/browser/resources/md_history/shared_style.html
@@ -66,6 +66,17 @@ text-overflow: ellipsis; white-space: nowrap; } + + button.icon-button { + height: 36px; + width: 36px; + } + + button.icon-button iron-icon { + color: var(--secondary-text-color); + height: 20px; + width: 20px; + } </style> </template> </dom-module>
diff --git a/chrome/browser/resources/md_history/synced_device_card.html b/chrome/browser/resources/md_history/synced_device_card.html index 570ad91..5aaf1f9 100644 --- a/chrome/browser/resources/md_history/synced_device_card.html +++ b/chrome/browser/resources/md_history/synced_device_card.html
@@ -1,9 +1,9 @@ <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/html/icon.html"> <link rel="import" href="chrome://history/browser_service.html"> <link rel="import" href="chrome://history/constants.html"> @@ -42,11 +42,8 @@ color: var(--secondary-text-color); } - #dropdown-indicator { - -webkit-margin-end: 12px; - color: var(--secondary-text-color); - height: 20px; - width: 20px; + .card-title .icon-button { + -webkit-margin-end: 4px; } #collapse { @@ -80,7 +77,11 @@ [[device]] <span id="last-update-time">[[lastUpdateTime]]</span> </div> - <iron-icon icon="cr:expand-less" id="dropdown-indicator"></iron-icon> + <button is="paper-icon-button-light" class="icon-button" + title$="[[getCollapseTitle_(cardOpen_)]]"> + <iron-icon icon="cr:expand-less" id="dropdown-indicator"> + </iron-icon> + </button> </div> <iron-collapse opened="{{cardOpen_}}" id="collapse">
diff --git a/chrome/browser/resources/md_history/synced_device_card.js b/chrome/browser/resources/md_history/synced_device_card.js index 89d9878d..4e80778 100644 --- a/chrome/browser/resources/md_history/synced_device_card.js +++ b/chrome/browser/resources/md_history/synced_device_card.js
@@ -87,5 +87,14 @@ /** @private */ isWindowSeparatorIndex_: function(index, separatorIndexes) { return this.separatorIndexes.indexOf(index) != -1; - } + }, + + /** + * @param {boolean} cardOpen + * @return {string} + */ + getCollapseTitle_: function(cardOpen) { + return cardOpen ? loadTimeData.getString('collapseSessionButton') : + loadTimeData.getString('expandSessionButton'); + }, });
diff --git a/chrome/browser/resources/net_internals/quic_view.html b/chrome/browser/resources/net_internals/quic_view.html index 9ee0590..e5cf4bd 100644 --- a/chrome/browser/resources/net_internals/quic_view.html +++ b/chrome/browser/resources/net_internals/quic_view.html
@@ -15,6 +15,7 @@ <li>Idle Connection Timeout In Seconds: <span jscontent="$this.idle_connection_timeout_seconds"></span></li> <li>Disable PreConnect If 0RTT: <span jscontent="$this.disable_preconnect_if_0rtt"></span></li> <li>Disable QUIC On Timeout With Open Streams: <span jscontent="$this.disable_quic_on_timeout_with_open_streams"></span></li> + <li>Race Cert Verification: <span jscontent="!!race_cert_verification"></span></li> <li jsdisplay="$this.disabled_reason && disabled_reason.length > 0">QUIC dynamically disabled: <span jscontent="disabled_reason"></span></li> </ul>
diff --git a/chrome/browser/resources/settings/settings_page/main_page_behavior.js b/chrome/browser/resources/settings/settings_page/main_page_behavior.js index a9a3d1e8..e17f8809 100644 --- a/chrome/browser/resources/settings/settings_page/main_page_behavior.js +++ b/chrome/browser/resources/settings/settings_page/main_page_behavior.js
@@ -55,9 +55,9 @@ */ toggleOtherSectionsHidden_: function(sectionName, hidden) { var sections = Polymer.dom(this.root).querySelectorAll( - this.sectionSelector + ':not([section=' + sectionName + '])'); + this.sectionSelector); for (var section of sections) - section.hidden = hidden; + section.hidden = hidden && (section.section != sectionName); }, /**
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc index 28b8005..aeb5e1a7 100644 --- a/chrome/browser/search/search.cc +++ b/chrome/browser/search/search.cc
@@ -52,9 +52,6 @@ namespace { -const char kPrerenderInstantUrlOnOmniboxFocus[] = - "prerender_instant_url_on_omnibox_focus"; - // Controls whether to use the alternate Instant search base URL. This allows // experimentation of Instant search. const char kUseAltInstantURL[] = "use_alternate_instant_url"; @@ -517,15 +514,6 @@ return ShouldPrefetchSearchResults() ? GetInstantURL(profile, true) : GURL(); } -bool ShouldPrerenderInstantUrlOnOmniboxFocus() { - if (!ShouldPrefetchSearchResults()) - return false; - - FieldTrialFlags flags; - return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault( - kPrerenderInstantUrlOnOmniboxFocus, false, flags); -} - GURL GetEffectiveURLForInstant(const GURL& url, Profile* profile) { CHECK(ShouldAssignURLToInstantRenderer(url, profile)) << "Error granting Instant access.";
diff --git a/chrome/browser/search/search.h b/chrome/browser/search/search.h index f6215a26..bd8a27549 100644 --- a/chrome/browser/search/search.h +++ b/chrome/browser/search/search.h
@@ -119,10 +119,6 @@ // trials. GURL GetSearchResultPrefetchBaseURL(Profile* profile); -// Returns true if 'prerender_instant_url_on_omnibox_focus' flag is enabled in -// field trials to prerender Instant search base page when the omnibox is -// focused. -bool ShouldPrerenderInstantUrlOnOmniboxFocus(); // Transforms the input |url| into its "effective URL". |url| must be an // Instant URL, i.e. ShouldAssignURLToInstantRenderer must return true. The
diff --git a/chrome/browser/search/search_unittest.cc b/chrome/browser/search/search_unittest.cc index 72b12f4a..0085720 100644 --- a/chrome/browser/search/search_unittest.cc +++ b/chrome/browser/search/search_unittest.cc
@@ -577,24 +577,6 @@ EXPECT_TRUE(ShouldUseSearchPathForInstant()); } -TEST_F(SearchTest, - ShouldPrerenderInstantUrlOnOmniboxFocus_DisabledViaFieldTrial) { - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - "EmbeddedSearch", - "Group1 espv:89 prerender_instant_url_on_omnibox_focus:0")); - EXPECT_FALSE(ShouldPrerenderInstantUrlOnOmniboxFocus()); - EXPECT_EQ(89ul, EmbeddedSearchPageVersion()); -} - -TEST_F(SearchTest, - ShouldPrerenderInstantUrlOnOmniboxFocus_EnabledViaFieldTrial) { - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - "EmbeddedSearch", - "Group1 espv:80 prerender_instant_url_on_omnibox_focus:1")); - EXPECT_TRUE(ShouldPrerenderInstantUrlOnOmniboxFocus()); - EXPECT_EQ(80ul, EmbeddedSearchPageVersion()); -} - TEST_F(SearchTest, IsNTPURL) { GURL invalid_url;
diff --git a/chrome/browser/ssl/chrome_security_state_model_client.cc b/chrome/browser/ssl/chrome_security_state_model_client.cc index 6f242a4..3e1834b 100644 --- a/chrome/browser/ssl/chrome_security_state_model_client.cc +++ b/chrome/browser/ssl/chrome_security_state_model_client.cc
@@ -242,14 +242,9 @@ state->security_bits = ssl.security_bits; state->pkp_bypassed = ssl.pkp_bypassed; state->sct_verify_statuses.clear(); - state->sct_verify_statuses.insert(state->sct_verify_statuses.end(), - ssl.num_unknown_scts, - net::ct::SCT_STATUS_LOG_UNKNOWN); - state->sct_verify_statuses.insert(state->sct_verify_statuses.end(), - ssl.num_invalid_scts, - net::ct::SCT_STATUS_INVALID); - state->sct_verify_statuses.insert(state->sct_verify_statuses.end(), - ssl.num_valid_scts, net::ct::SCT_STATUS_OK); + state->sct_verify_statuses.insert(state->sct_verify_statuses.begin(), + ssl.sct_statuses.begin(), + ssl.sct_statuses.end()); state->displayed_mixed_content = (ssl.content_status & content::SSLStatus::DISPLAYED_INSECURE_CONTENT) ? true
diff --git a/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc b/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc index b9d7d0aa..80c7d441 100644 --- a/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc +++ b/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc
@@ -38,8 +38,11 @@ #include "net/cert/cert_status_flags.h" #include "net/cert/cert_verify_result.h" #include "net/cert/mock_cert_verifier.h" +#include "net/cert/sct_status_flags.h" +#include "net/cert/signed_certificate_timestamp.h" #include "net/cert/x509_certificate.h" #include "net/dns/mock_host_resolver.h" +#include "net/ssl/signed_certificate_timestamp_and_status.h" #include "net/ssl/ssl_cipher_suite_names.h" #include "net/ssl/ssl_connection_status_flags.h" #include "net/test/cert_test_util.h" @@ -1115,4 +1118,141 @@ } } +// After AddSCTUrlHandler() is called, requests to this hostname +// will be served with Signed Certificate Timestamps. +const char kMockHostnameWithSCTs[] = "example-scts.test"; + +// URLRequestJobWithSCTs mocks a connection that includes a set of dummy +// SCTs with these statuses. +const std::vector<net::ct::SCTVerifyStatus> kTestSCTStatuses{ + net::ct::SCT_STATUS_OK, net::ct::SCT_STATUS_LOG_UNKNOWN, + net::ct::SCT_STATUS_OK}; + +// A URLRequestMockHTTPJob that mocks a TLS connection with SCTs +// attached to it. The SCTs will have verification statuses +// |kTestSCTStatuses|. +class URLRequestJobWithSCTs : public net::URLRequestMockHTTPJob { + public: + URLRequestJobWithSCTs(net::URLRequest* request, + net::NetworkDelegate* network_delegate, + const base::FilePath& file_path, + scoped_refptr<net::X509Certificate> cert, + scoped_refptr<base::TaskRunner> task_runner) + : net::URLRequestMockHTTPJob(request, + network_delegate, + file_path, + task_runner), + cert_(std::move(cert)) {} + + void GetResponseInfo(net::HttpResponseInfo* info) override { + net::URLRequestMockHTTPJob::GetResponseInfo(info); + for (const auto& status : kTestSCTStatuses) { + scoped_refptr<net::ct::SignedCertificateTimestamp> dummy_sct = + new net::ct::SignedCertificateTimestamp(); + info->ssl_info.signed_certificate_timestamps.push_back( + net::SignedCertificateTimestampAndStatus(dummy_sct, status)); + } + info->ssl_info.cert = cert_; + } + + protected: + ~URLRequestJobWithSCTs() override {} + + private: + const scoped_refptr<net::X509Certificate> cert_; + + DISALLOW_COPY_AND_ASSIGN(URLRequestJobWithSCTs); +}; + +// A URLRequestInterceptor that handles requests with +// URLRequestJobWithSCTs jobs. +class URLRequestWithSCTsInterceptor : public net::URLRequestInterceptor { + public: + URLRequestWithSCTsInterceptor( + const base::FilePath& base_path, + scoped_refptr<base::SequencedWorkerPool> worker_pool, + scoped_refptr<net::X509Certificate> cert) + : base_path_(base_path), + worker_pool_(std::move(worker_pool)), + cert_(std::move(cert)) {} + + ~URLRequestWithSCTsInterceptor() override {} + + // net::URLRequestInterceptor: + net::URLRequestJob* MaybeInterceptRequest( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) const override { + return new URLRequestJobWithSCTs( + request, network_delegate, base_path_, cert_, + worker_pool_->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); + } + + private: + const base::FilePath base_path_; + const scoped_refptr<base::SequencedWorkerPool> worker_pool_; + const scoped_refptr<net::X509Certificate> cert_; + + DISALLOW_COPY_AND_ASSIGN(URLRequestWithSCTsInterceptor); +}; + +// Installs a handler to serve HTTPS requests to |kMockHostnameWithSCTs| +// with connections that have SCTs. +void AddSCTUrlHandler(const base::FilePath& base_path, + scoped_refptr<net::X509Certificate> cert, + scoped_refptr<base::SequencedWorkerPool> worker_pool) { + net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); + filter->AddHostnameInterceptor( + "https", kMockHostnameWithSCTs, + std::unique_ptr<net::URLRequestInterceptor>( + new URLRequestWithSCTsInterceptor(base_path, worker_pool, cert))); +} + +class BrowserTestURLRequestWithSCTs : public InProcessBrowserTest { + public: + BrowserTestURLRequestWithSCTs() : InProcessBrowserTest(), cert_(nullptr) {} + + void SetUpInProcessBrowserTestFixture() override { + cert_ = + net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); + ASSERT_TRUE(cert_); + } + + void SetUpOnMainThread() override { + base::FilePath serve_file; + PathService::Get(chrome::DIR_TEST_DATA, &serve_file); + serve_file = serve_file.Append(FILE_PATH_LITERAL("title1.html")); + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind( + &AddSCTUrlHandler, serve_file, cert_, + make_scoped_refptr(content::BrowserThread::GetBlockingPool()))); + } + + private: + scoped_refptr<net::X509Certificate> cert_; + + DISALLOW_COPY_AND_ASSIGN(BrowserTestURLRequestWithSCTs); +}; + +// Tests that, when Signed Certificate Timestamps (SCTs) are served on a +// connection, the SCTs verification statuses are exposed on the +// SecurityInfo. +IN_PROC_BROWSER_TEST_F(BrowserTestURLRequestWithSCTs, + SecurityInfoWithSCTsAttached) { + ui_test_utils::NavigateToURL( + browser(), GURL(std::string("https://") + kMockHostnameWithSCTs)); + + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(web_contents); + ChromeSecurityStateModelClient* model_client = + ChromeSecurityStateModelClient::FromWebContents(web_contents); + ASSERT_TRUE(model_client); + const SecurityStateModel::SecurityInfo& security_info = + model_client->GetSecurityInfo(); + EXPECT_EQ(SecurityStateModel::SECURE, security_info.security_level); + EXPECT_EQ(kTestSCTStatuses, security_info.sct_verify_statuses); +} + } // namespace
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm index f09e8fc..0ddbeff 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
@@ -1971,10 +1971,12 @@ [BookmarkButtonCell buttonCellWithText:text image:image menuController:contextMenuController_]; - if (ui::MaterialDesignController::IsModeMaterial()) + if (ui::MaterialDesignController::IsModeMaterial()) { [cell setTag:kMaterialStandardButtonTypeWithLimitedClickFeedback]; - else + [cell setHighlightsBy:NSNoCellMask]; + } else { [cell setTag:kStandardButtonTypeWithLimitedClickFeedback]; + } // Note: a quirk of setting a cell's text color is that it won't work // until the cell is associated with a button, so we can't theme the cell yet.
diff --git a/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm index 80419d5..e368440 100644 --- a/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm
@@ -145,8 +145,10 @@ TEST_F(AccountChooserViewControllerTest, ConfiguresFederatedCredential) { const char federation[] = "https://google.com/idp"; const char name[] = "Peter the Great"; + const char username[] = "pete"; + PasswordDialogController::FormsVector local_forms; - local_forms.push_back(Credential("pizza")); + local_forms.push_back(Credential(username)); local_forms.back()->federation_origin = url::Origin(GURL(federation)); local_forms.back()->display_name = base::ASCIIToUTF16(name); SetUpAccountChooser(&local_forms); @@ -158,6 +160,7 @@ base::SysNSStringToUTF8([base::mac::ObjCCastStrict<CredentialItemButton>( [buttons objectAtIndex:0]) title]); EXPECT_THAT(title, testing::HasSubstr(name)); + EXPECT_THAT(title, testing::HasSubstr(username)); EXPECT_THAT(title, testing::HasSubstr(GURL(federation).host())); }
diff --git a/chrome/browser/ui/cocoa/translate/translate_bubble_controller.h b/chrome/browser/ui/cocoa/translate/translate_bubble_controller.h index 0aeb9631..ee2ae19 100644 --- a/chrome/browser/ui/cocoa/translate/translate_bubble_controller.h +++ b/chrome/browser/ui/cocoa/translate/translate_bubble_controller.h
@@ -44,9 +44,6 @@ // This is nil when the current WebContents is in an incognito window. NSButton* alwaysTranslateCheckbox_; - // The 'Try again' button on the error panel. - NSButton* tryAgainButton_; - // The combobox model which is used to deny translation at the view before // translate. std::unique_ptr<TranslateDenialComboboxModel> translateDenialComboboxModel_;
diff --git a/chrome/browser/ui/cocoa/translate/translate_bubble_controller.mm b/chrome/browser/ui/cocoa/translate/translate_bubble_controller.mm index cc2b6d2..1a751bb0 100644 --- a/chrome/browser/ui/cocoa/translate/translate_bubble_controller.mm +++ b/chrome/browser/ui/cocoa/translate/translate_bubble_controller.mm
@@ -105,7 +105,6 @@ - (void)handleDoneButtonPressed; - (void)handleCancelButtonPressed; - (void)handleShowOriginalButtonPressed; -- (void)handleTryAgainButtonPressed; - (void)handleAdvancedLinkButtonPressed; - (void)handleLanguageSettingsLinkButtonPressed; - (void)handleDenialPopUpButtonNopeSelected; @@ -199,8 +198,7 @@ } - (void)switchToErrorView:(translate::TranslateErrors::Type)errorType { - [self switchView:TranslateBubbleModel::VIEW_STATE_ERROR]; - model_->ShowError(errorType); + // FIXME: Implement this. } - (void)performLayout { @@ -389,35 +387,7 @@ 0); NSView* view = [[NSView alloc] initWithFrame:contentFrame]; - NSString* message = - l10n_util::GetNSString(IDS_TRANSLATE_BUBBLE_COULD_NOT_TRANSLATE); - NSTextField* textLabel = [self addText:message toView:view]; - message = l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_ADVANCED); - NSButton* advancedLinkButton = - [self addLinkButtonWithText:message - action:@selector(handleAdvancedLinkButtonPressed) - toView:view]; - NSString* title = - l10n_util::GetNSString(IDS_TRANSLATE_BUBBLE_TRY_AGAIN); - tryAgainButton_ = [self addButton:title - action:@selector(handleTryAgainButtonPressed) - toView:view]; - - // Layout - CGFloat yPos = 0; - - [tryAgainButton_ - setFrameOrigin:NSMakePoint( - kContentWidth - NSWidth([tryAgainButton_ frame]), - yPos)]; - - yPos += NSHeight([tryAgainButton_ frame]) + kUnrelatedControlVerticalSpacing; - - [textLabel setFrameOrigin:NSMakePoint(0, yPos)]; - [advancedLinkButton - setFrameOrigin:NSMakePoint(NSMaxX([textLabel frame]), yPos)]; - - [view setFrameSize:NSMakeSize(kContentWidth, NSMaxY([textLabel frame]))]; + // TODO(hajimehoshi): Implement this. return view; } @@ -694,11 +664,6 @@ [self close]; } -- (void)handleTryAgainButtonPressed { - model_->Translate(); - translate::ReportUiAction(translate::TRY_AGAIN_BUTTON_CLICKED); -} - - (void)handleAdvancedLinkButtonPressed { translate::ReportUiAction(translate::ADVANCED_LINK_CLICKED); [self switchView:TranslateBubbleModel::VIEW_STATE_ADVANCED];
diff --git a/chrome/browser/ui/cocoa/translate/translate_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/translate/translate_bubble_controller_unittest.mm index deb807a..f72588b 100644 --- a/chrome/browser/ui/cocoa/translate/translate_bubble_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/translate/translate_bubble_controller_unittest.mm
@@ -12,7 +12,6 @@ #import "chrome/browser/ui/cocoa/cocoa_profile_test.h" #import "chrome/browser/ui/cocoa/info_bubble_window.h" #include "chrome/browser/ui/cocoa/run_loop_testing.h" -#include "chrome/browser/ui/translate/translate_bubble_model.h" #include "chrome/common/url_constants.h" #include "content/public/browser/site_instance.h" @@ -24,18 +23,6 @@ @end -@implementation TranslateBubbleController (ForTesting) - -- (NSView*)errorView { - NSNumber* key = @(TranslateBubbleModel::VIEW_STATE_ERROR); - return [views_ objectForKey:key]; -} -- (NSButton*)tryAgainButton { - return tryAgainButton_; -} - -@end - class TranslateBubbleControllerTest : public CocoaProfileTest { public: void SetUp() override { @@ -57,7 +44,6 @@ } BrowserWindowController* bwc() { return bwc_; } - TranslateBubbleController* bubble() { return [bwc() translateBubbleController]; } @@ -75,14 +61,6 @@ [window setAllowedAnimations:info_bubble::kAnimateNone]; } - void SwitchToErrorView() { - translate::TranslateStep step = translate::TRANSLATE_STEP_TRANSLATE_ERROR; - [bwc_ - showTranslateBubbleForWebContents:web_contents_ - step:step - errorType:translate::TranslateErrors::NETWORK]; - } - void CloseBubble() { [bubble() close]; chrome::testing::NSRunLoopRunAllPending(); @@ -104,29 +82,6 @@ EXPECT_FALSE(bubble()); } -TEST_F(TranslateBubbleControllerTest, SwitchToErrorView) { - EXPECT_FALSE(bubble()); - ShowBubble(); - const TranslateBubbleModel* model = [bubble() model]; - - EXPECT_TRUE(bubble()); - EXPECT_EQ(TranslateBubbleModel::ViewState::VIEW_STATE_BEFORE_TRANSLATE, - model->GetViewState()); - - SwitchToErrorView(); - - NSView* errorView = [bubble() errorView]; - // We should have 3 subview inside the error view: - // A NSTextField and two NSButton. - EXPECT_EQ(3UL, [[errorView subviews] count]); - - // one of the subview should be "Try again" button. - EXPECT_TRUE([[errorView subviews] containsObject:[bubble() tryAgainButton]]); - EXPECT_EQ(TranslateBubbleModel::ViewState::VIEW_STATE_ERROR, - model->GetViewState()); - EXPECT_TRUE(bubble()); -} - TEST_F(TranslateBubbleControllerTest, CloseRegistersDecline) { const char kDeclineTranslateDismissUI[] = "Translate.DeclineTranslateDismissUI";
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc index 0444a0a..25dbccf 100644 --- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc +++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
@@ -457,17 +457,10 @@ void ChromeOmniboxClient::SetSuggestionToPrefetch( const InstantSuggestion& suggestion) { DCHECK(search::IsInstantExtendedAPIEnabled()); - content::WebContents* web_contents = controller_->GetWebContents(); - // TODO(treib): This check should probably be removed - IsSearchResultsPage - // will always return false here, because it'll only be true for pages - // rendered in the Instant process. crbug.com/627747 - if (!web_contents || - !SearchTabHelper::FromWebContents(web_contents)->IsSearchResultsPage()) { - InstantSearchPrerenderer* prerenderer = - InstantSearchPrerenderer::GetForProfile(profile_); - if (prerenderer) - prerenderer->Prerender(suggestion); - } + InstantSearchPrerenderer* prerenderer = + InstantSearchPrerenderer::GetForProfile(profile_); + if (prerenderer) + prerenderer->Prerender(suggestion); } void ChromeOmniboxClient::OnBitmapFetched(const BitmapFetchedCallback& callback,
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.h b/chrome/browser/ui/omnibox/chrome_omnibox_client.h index 6796327fc..3c23dfb4 100644 --- a/chrome/browser/ui/omnibox/chrome_omnibox_client.h +++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.h
@@ -16,10 +16,6 @@ class OmniboxEditController; class Profile; -namespace content { -class NavigationController; -} - class ChromeOmniboxClient : public OmniboxClient { public: ChromeOmniboxClient(OmniboxEditController* controller, Profile* profile);
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc index c30c6c8..f6f51a2 100644 --- a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc +++ b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc
@@ -55,18 +55,23 @@ std::pair<base::string16, base::string16> GetCredentialLabelsForAccountChooser( const autofill::PasswordForm& form) { - const base::string16& upper_string = - form.display_name.empty() ? form.username_value : form.display_name; - base::string16 lower_string; - if (form.federation_origin.unique()) { - if (!form.display_name.empty()) - lower_string = form.username_value; - } else { - lower_string = l10n_util::GetStringFUTF16( + base::string16 federation; + if (!form.federation_origin.unique()) { + federation = l10n_util::GetStringFUTF16( IDS_PASSWORDS_VIA_FEDERATION, base::UTF8ToUTF16(form.federation_origin.host())); } - return std::make_pair(upper_string, lower_string); + + if (form.display_name.empty()) + return std::make_pair(form.username_value, std::move(federation)); + + // Display name isn't empty. + if (federation.empty()) + return std::make_pair(form.display_name, form.username_value); + + return std::make_pair( + form.display_name, + form.username_value + base::ASCIIToUTF16("\n") + federation); } void GetSavePasswordDialogTitleTextAndLinkRange(
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils.h b/chrome/browser/ui/passwords/manage_passwords_view_utils.h index 5a47cfc..abc193b 100644 --- a/chrome/browser/ui/passwords/manage_passwords_view_utils.h +++ b/chrome/browser/ui/passwords/manage_passwords_view_utils.h
@@ -33,7 +33,7 @@ gfx::ImageSkia ScaleImageForAccountAvatar(gfx::ImageSkia image_skia); // Returns the upper and lower label to be displayed in the account chooser UI -// for |form|. +// for |form|. The lower label can be multiline. std::pair<base::string16, base::string16> GetCredentialLabelsForAccountChooser( const autofill::PasswordForm& form);
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc index a361016..0f467f2 100644 --- a/chrome/browser/ui/search/search_tab_helper.cc +++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -7,10 +7,8 @@ #include <memory> #include <set> -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram.h" -#include "base/strings/string16.h" #include "base/strings/string_util.h" #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" @@ -23,7 +21,6 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/location_bar/location_bar.h" #include "chrome/browser/ui/omnibox/clipboard_utils.h" -#include "chrome/browser/ui/search/instant_search_prerenderer.h" #include "chrome/browser/ui/search/instant_tab.h" #include "chrome/browser/ui/search/search_ipc_router_policy_impl.h" #include "chrome/browser/ui/search/search_tab_helper_delegate.h" @@ -42,7 +39,6 @@ #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_details.h" #include "content/public/browser/navigation_entry.h" -#include "content/public/browser/navigation_type.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/render_frame_host.h" @@ -138,10 +134,6 @@ sync->GetPreferredDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES); } -bool OmniboxHasFocus(OmniboxView* omnibox) { - return omnibox && omnibox->model()->has_focus(); -} - } // namespace SearchTabHelper::SearchTabHelper(content::WebContents* web_contents) @@ -153,8 +145,7 @@ this, base::WrapUnique(new SearchIPCRouterPolicyImpl(web_contents))), instant_service_(NULL), - delegate_(NULL), - omnibox_has_focus_fn_(&OmniboxHasFocus) { + delegate_(NULL) { if (!is_search_enabled_) return; @@ -189,25 +180,8 @@ // Don't send oninputstart/oninputend updates in response to focus changes // if there's a navigation in progress. This prevents Chrome from sending // a spurious oninputend when the user accepts a match in the omnibox. - if (web_contents_->GetController().GetPendingEntry() == NULL) { + if (web_contents_->GetController().GetPendingEntry() == NULL) ipc_router_.SetInputInProgress(IsInputInProgress()); - - InstantSearchPrerenderer* prerenderer = - InstantSearchPrerenderer::GetForProfile(profile()); - if (!prerenderer || !search::ShouldPrerenderInstantUrlOnOmniboxFocus()) - return; - - if (state == OMNIBOX_FOCUS_NONE) { - prerenderer->Cancel(); - return; - } - - if (!IsSearchResultsPage()) { - prerenderer->Init( - web_contents_->GetController().GetDefaultSessionStorageNamespace(), - web_contents_->GetContainerBounds().size()); - } - } } void SearchTabHelper::NavigationEntryUpdated() { @@ -241,18 +215,6 @@ // it won't correctly detect this case. NTPUserDataLogger::GetOrCreateFromWebContents(web_contents_); } - - OmniboxView* omnibox_view = GetOmniboxView(); - if (search::ShouldPrerenderInstantUrlOnOmniboxFocus() && - omnibox_has_focus_fn_(omnibox_view)) { - InstantSearchPrerenderer* prerenderer = - InstantSearchPrerenderer::GetForProfile(profile()); - if (prerenderer && !IsSearchResultsPage()) { - prerenderer->Init( - web_contents_->GetController().GetDefaultSessionStorageNamespace(), - web_contents_->GetContainerBounds().size()); - } - } } void SearchTabHelper::OnTabDeactivated() {
diff --git a/chrome/browser/ui/search/search_tab_helper.h b/chrome/browser/ui/search/search_tab_helper.h index e20a3ec..8f908350 100644 --- a/chrome/browser/ui/search/search_tab_helper.h +++ b/chrome/browser/ui/search/search_tab_helper.h
@@ -10,6 +10,7 @@ #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" #include "base/macros.h" +#include "base/strings/string16.h" #include "base/time/time.h" #include "chrome/browser/search/instant_service_observer.h" #include "chrome/browser/ui/search/search_ipc_router.h" @@ -110,19 +111,11 @@ OnChromeIdentityCheckMatchSlightlyDifferentGmail2); FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest, OnChromeIdentityCheckMismatch); FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest, - OnChromeIdentityCheckSignedOutMatch); - FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest, OnChromeIdentityCheckSignedOutMismatch); FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest, - OnHistorySyncCheckSyncInactive); - FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest, OnHistorySyncCheckSyncing); FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest, OnHistorySyncCheckNotSyncing); - FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest, - OnMostVisitedItemsChangedFromServer); - FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest, - OnMostVisitedItemsChangedFromClient); FRIEND_TEST_ALL_PREFIXES(SearchIPCRouterTest, IgnoreMessageIfThePageIsNotActive); FRIEND_TEST_ALL_PREFIXES(SearchIPCRouterTest, HandleTabChangedEvents); @@ -193,12 +186,6 @@ // Returns the OmniboxView for |web_contents_| or NULL if not available. OmniboxView* GetOmniboxView() const; - typedef bool (*OmniboxHasFocusFn)(OmniboxView*); - - void set_omnibox_has_focus_fn(OmniboxHasFocusFn fn) { - omnibox_has_focus_fn_ = fn; - } - const bool is_search_enabled_; // Model object for UI that cares about search state. @@ -215,10 +202,6 @@ // NULL on iOS and Android because they don't use the Instant framework. SearchTabHelperDelegate* delegate_; - // Function to check if the omnibox has focus. Tests use this to modify the - // default behavior. - OmniboxHasFocusFn omnibox_has_focus_fn_; - DISALLOW_COPY_AND_ASSIGN(SearchTabHelper); };
diff --git a/chrome/browser/ui/search/search_tab_helper_unittest.cc b/chrome/browser/ui/search/search_tab_helper_unittest.cc index 357c77eb..e6ad88af 100644 --- a/chrome/browser/ui/search/search_tab_helper_unittest.cc +++ b/chrome/browser/ui/search/search_tab_helper_unittest.cc
@@ -10,25 +10,15 @@ #include <string> #include <tuple> -#include "base/command_line.h" -#include "base/metrics/field_trial.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" -#include "chrome/browser/prerender/prerender_manager.h" -#include "chrome/browser/prerender/prerender_manager_factory.h" -#include "chrome/browser/search/instant_unittest_base.h" -#include "chrome/browser/search/search.h" -#include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/signin/fake_signin_manager_builder.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/profile_sync_test_util.h" #include "chrome/browser/ui/search/search_ipc_router.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/webui/ntp/ntp_user_data_logger.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/render_messages.h" -#include "chrome/common/search/ntp_logging_events.h" #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" #include "chrome/test/base/browser_with_test_window_test.h" @@ -36,7 +26,6 @@ #include "chrome/test/base/testing_profile.h" #include "components/browser_sync/browser/profile_sync_service.h" #include "components/omnibox/common/omnibox_focus_state.h" -#include "components/search_engines/template_url_service.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" @@ -355,68 +344,3 @@ EXPECT_EQ(title, title_observer.title_on_commit()); EXPECT_EQ(title, web_contents()->GetTitle()); } - -class SearchTabHelperPrerenderTest : public InstantUnitTestBase { - public: - ~SearchTabHelperPrerenderTest() override {} - - protected: - void SetUp() override { - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - "EmbeddedSearch", - "Group1 espv:89 prefetch_results:1 " - "prerender_instant_url_on_omnibox_focus:1")); - InstantUnitTestBase::SetUp(); - - AddTab(browser(), GURL(chrome::kChromeUINewTabURL)); - SearchTabHelper::FromWebContents(web_contents())->set_omnibox_has_focus_fn( - omnibox_has_focus); - SearchTabHelperPrerenderTest::omnibox_has_focus_ = true; - } - - content::WebContents* web_contents() { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - - bool IsInstantURLMarkedForPrerendering() { - GURL instant_url(search::GetSearchResultPrefetchBaseURL(profile())); - prerender::PrerenderManager* prerender_manager = - prerender::PrerenderManagerFactory::GetForProfile(profile()); - return prerender_manager->HasPrerenderedUrl(instant_url, web_contents()); - } - - static bool omnibox_has_focus(OmniboxView* omnibox) { - return omnibox_has_focus_; - } - - static bool omnibox_has_focus_; -}; - -bool SearchTabHelperPrerenderTest::omnibox_has_focus_ = true; - -TEST_F(SearchTabHelperPrerenderTest, OnOmniboxFocusPrerenderInstantURL) { - SearchTabHelper* search_tab_helper = - SearchTabHelper::FromWebContents(web_contents()); - search_tab_helper->OmniboxFocusChanged(OMNIBOX_FOCUS_VISIBLE, - OMNIBOX_FOCUS_CHANGE_EXPLICIT); - ASSERT_TRUE(IsInstantURLMarkedForPrerendering()); - search_tab_helper->OmniboxFocusChanged(OMNIBOX_FOCUS_NONE, - OMNIBOX_FOCUS_CHANGE_EXPLICIT); - ASSERT_FALSE(IsInstantURLMarkedForPrerendering()); -} - -TEST_F(SearchTabHelperPrerenderTest, OnTabActivatedPrerenderInstantURL) { - SearchTabHelper* search_tab_helper = - SearchTabHelper::FromWebContents(web_contents()); - search_tab_helper->OnTabActivated(); - ASSERT_TRUE(IsInstantURLMarkedForPrerendering()); -} - -TEST_F(SearchTabHelperPrerenderTest, - OnTabActivatedNoPrerenderIfOmniboxBlurred) { - SearchTabHelperPrerenderTest::omnibox_has_focus_ = false; - SearchTabHelper* search_tab_helper = - SearchTabHelper::FromWebContents(web_contents()); - search_tab_helper->OnTabActivated(); - ASSERT_FALSE(IsInstantURLMarkedForPrerendering()); -}
diff --git a/chrome/browser/ui/startup/bad_flags_prompt.cc b/chrome/browser/ui/startup/bad_flags_prompt.cc index 0d61837..284e328 100644 --- a/chrome/browser/ui/startup/bad_flags_prompt.cc +++ b/chrome/browser/ui/startup/bad_flags_prompt.cc
@@ -86,12 +86,6 @@ // if they are not. switches::kUnsafelyTreatInsecureOriginAsSecure, - // This flag enables Web Bluetooth. Since the UI for Web Bluetooth is - // not yet implemented, websites could take control over paired devices - // without the users knowledge, so we need to show a warning for when - // the flag is enabled. - switches::kEnableWebBluetooth, - // This flag disables WebUSB's CORS-like checks for origin to device // communication, allowing any origin to ask the user for permission to // connect to a device. It is intended for manufacturers testing their
diff --git a/chrome/browser/ui/views/passwords/credentials_item_view.cc b/chrome/browser/ui/views/passwords/credentials_item_view.cc index 2049416..7996b3d 100644 --- a/chrome/browser/ui/views/passwords/credentials_item_view.cc +++ b/chrome/browser/ui/views/passwords/credentials_item_view.cc
@@ -102,9 +102,15 @@ lower_label_ = new views::Label( lower_text, rb->GetFontList(ui::ResourceBundle::SmallFont)); lower_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); + lower_label_->SetMultiLine(true); AddChildView(lower_label_); } + if (!upper_text.empty() && !lower_text.empty()) + SetAccessibleName(upper_text + base::ASCIIToUTF16("\n") + lower_text); + else + SetAccessibleName(upper_text + lower_text); + SetFocusBehavior(FocusBehavior::ALWAYS); }
diff --git a/chrome/browser/ui/webui/md_history_ui.cc b/chrome/browser/ui/webui/md_history_ui.cc index 3c24e89..0894853 100644 --- a/chrome/browser/ui/webui/md_history_ui.cc +++ b/chrome/browser/ui/webui/md_history_ui.cc
@@ -44,11 +44,15 @@ source->AddLocalizedString("clearBrowsingData", IDS_CLEAR_BROWSING_DATA_TITLE); source->AddLocalizedString("clearSearch", IDS_MD_HISTORY_CLEAR_SEARCH); + source->AddLocalizedString("collapseSessionButton", + IDS_HISTORY_OTHER_SESSIONS_COLLAPSE_SESSION); source->AddLocalizedString("delete", IDS_MD_HISTORY_DELETE); source->AddLocalizedString("deleteConfirm", IDS_HISTORY_DELETE_PRIOR_VISITS_CONFIRM_BUTTON); source->AddLocalizedString( "deleteWarning", IDS_HISTORY_DELETE_PRIOR_VISITS_WARNING_NO_INCOGNITO); + source->AddLocalizedString("expandSessionButton", + IDS_HISTORY_OTHER_SESSIONS_EXPAND_SESSION); source->AddLocalizedString("foundSearchResults", IDS_HISTORY_FOUND_SEARCH_RESULTS); source->AddLocalizedString("historyInterval", IDS_HISTORY_INTERVAL);
diff --git a/chrome/browser/web_dev_style/js_checker.py b/chrome/browser/web_dev_style/js_checker.py index a328217..d3306a94 100644 --- a/chrome/browser/web_dev_style/js_checker.py +++ b/chrome/browser/web_dev_style/js_checker.py
@@ -55,6 +55,11 @@ return self.RegexCheck(i, line, r"\* (@inheritDoc)", "@inheritDoc is deprecated, use @override instead") + def PolymerLocalIdCheck(self, i, line): + """Checks for use of element.$.localId.""" + return self.RegexCheck(i, line, r"(?<!this)(\.\$)[\[\.]", + "Please only use this.$.localId, not element.$.localId") + def WrapperTypeCheck(self, i, line): """Check for wrappers (new String()) instead of builtins (string).""" return self.RegexCheck(i, line, @@ -228,6 +233,7 @@ self.EndJsDocCommentCheck(i, line), self.ExtraDotInGenericCheck(i, line), self.InheritDocCheck(i, line), + self.PolymerLocalIdCheck(i, line), self.WrapperTypeCheck(i, line), self.VarNameCheck(i, line), ])
diff --git a/chrome/browser/web_dev_style/js_checker_test.py b/chrome/browser/web_dev_style/js_checker_test.py index a8f6336..185ed05 100755 --- a/chrome/browser/web_dev_style/js_checker_test.py +++ b/chrome/browser/web_dev_style/js_checker_test.py
@@ -240,6 +240,38 @@ for line in lines: self.ShouldPassInheritDocCheck(line) + def ShouldFailPolymerLocalIdCheck(self, line): + """Checks that element.$.localId check marks |line| as a style error.""" + error = self.checker.PolymerLocalIdCheck(1, line) + self.assertNotEqual('', error, + msg='Should be flagged as a style error: ' + line) + self.assertTrue('.$' in test_util.GetHighlight(line, error)) + + def ShouldPassPolymerLocalIdCheck(self, line): + """Checks that element.$.localId check doesn't mark |line| as a style + error.""" + self.assertEqual('', self.checker.PolymerLocalIdCheck(1, line), + msg='Should not be flagged as a style error: ' + line) + + def testPolymerLocalIdFails(self): + lines = [ + "cat.$.dog", + "thing1.$.thing2", + "element.$.localId", + "element.$['fancy-hyphenated-id']", + ] + for line in lines: + self.ShouldFailPolymerLocalIdCheck(line) + + def testPolymerLocalIdPasses(self): + lines = [ + "this.$.id", + "this.$.localId", + "this.$['fancy-id']", + ] + for line in lines: + self.ShouldPassPolymerLocalIdCheck(line) + def ShouldFailWrapperTypeCheck(self, line): """Checks that the use of wrapper types (i.e. new Number(), @type {Number}) is a style error.
diff --git a/chrome/common/features.gni b/chrome/common/features.gni index a74efab..8bb1fbe 100644 --- a/chrome/common/features.gni +++ b/chrome/common/features.gni
@@ -5,39 +5,47 @@ # This is the GN version of //chrome/chrome_features.gypi. # Please keep in sync! +import("//build/config/chrome_build.gni") import("//build/config/chromecast_build.gni") +# Please keep features in alphabetical order. declare_args() { - # Google Now is disabled to prepare for its removal. - # http://crbug.com/539674 - enable_google_now = false - # Whether the Java UI is being used (Java infobars and popups, Java native # settings and first run experience, sign-in etc.). # Default to true if compiling for android, but allow this being overriden # through the environment. android_java_ui = is_android - # Use vulcanized HTML/CSS/JS resources to speed up WebUI (chrome://) - # pages. https://github.com/polymer/vulcanize - use_vulcanize = true - # Enables support for background apps. enable_background = !is_ios && !is_android && !is_chromecast enable_one_click_signin = is_win || is_mac || (is_linux && !is_chromeos && !is_chromecast) + # Google Now is disabled to prepare for its removal. + # http://crbug.com/539674 + enable_google_now = false + + # 'Ok Google' hotwording is disabled by default. Set to true to enable. (This + # will download a closed-source NaCl module at startup.) Chrome-branded + # ChromeOS builds have this enabled by default. + enable_hotwording = is_chrome_branded && is_chromeos + # Set to true to bundle all the mash related mojo services into chrome. # Specify --mash to chrome to have chrome start the mash environment. enable_package_mash_services = is_chromeos # Enables vr shell. enable_vr_shell = false + + # Use vulcanized HTML/CSS/JS resources to speed up WebUI (chrome://) + # pages. https://github.com/polymer/vulcanize + use_vulcanize = true } chrome_grit_defines = [ "enable_background=$enable_background", "enable_google_now=$enable_google_now", + "enable_hotwording=$enable_hotwording", "use_vulcanize=$use_vulcanize", ]
diff --git a/chrome/renderer/translate/translate_script_browsertest.cc b/chrome/renderer/translate/translate_script_browsertest.cc index 6fbe684a..1462be0 100644 --- a/chrome/renderer/translate/translate_script_browsertest.cc +++ b/chrome/renderer/translate/translate_script_browsertest.cc
@@ -38,6 +38,7 @@ // JavaScript code to mimic element.js provided by a translate server. const char kElementJs[] = + "serverParams = '';" "translateApiKey = '';" "google = {};" "google.translate = {};"
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h index b32e130..bc9ff63d 100644 --- a/components/autofill/core/browser/personal_data_manager.h +++ b/components/autofill/core/browser/personal_data_manager.h
@@ -31,11 +31,6 @@ class RemoveAutofillTester; class SigninManagerBase; -#if defined(OS_IOS) -// TODO(crbug.com/513344): Remove this once Chrome on iOS is unforked. -class PersonalDataManagerFactory; -#endif - namespace sync_driver { class SyncService; } @@ -293,10 +288,6 @@ friend class autofill::AutofillTest; friend class autofill::PersonalDataManagerFactory; friend class PersonalDataManagerTest; -#if defined(OS_IOS) - // TODO(crbug.com/513344): Remove this once Chrome on iOS is unforked. - friend class ::PersonalDataManagerFactory; -#endif friend class ProfileSyncServiceAutofillTest; friend class ::RemoveAutofillTester; friend std::default_delete<PersonalDataManager>;
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java index 6cd0d23d..09811e8c 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java
@@ -51,7 +51,8 @@ .put("idle_connection_timeout_seconds", 300) .put("close_sessions_on_ip_change", false) .put("migrate_sessions_on_network_change", true) - .put("migrate_sessions_early", true); + .put("migrate_sessions_early", true) + .put("race_cert_verification", true); JSONObject experimentalOptions = new JSONObject().put("QUIC", quicParams); mBuilder.setExperimentalOptions(experimentalOptions.toString()); mBuilder.setMockCertVerifierForTesting(QuicTestServer.createMockCertVerifier());
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc index 1fa0ea0..6a492e5 100644 --- a/components/cronet/url_request_context_config.cc +++ b/components/cronet/url_request_context_config.cc
@@ -53,6 +53,7 @@ const char kQuicMigrateSessionsEarly[] = "migrate_sessions_early"; const char kQuicDisableBidirectionalStreams[] = "quic_disable_bidirectional_streams"; +const char kQuicRaceCertVerification[] = "race_cert_verification"; // AsyncDNS experiment dictionary name. const char kAsyncDnsFieldTrialName[] = "AsyncDNS"; @@ -187,6 +188,13 @@ context_builder->set_quic_disable_bidirectional_streams( quic_disable_bidirectional_streams); } + + bool quic_race_cert_verification = false; + if (quic_args->GetBoolean(kQuicRaceCertVerification, + &quic_race_cert_verification)) { + context_builder->set_quic_race_cert_verification( + quic_race_cert_verification); + } } const base::DictionaryValue* async_dns_args = nullptr;
diff --git a/components/cronet/url_request_context_config_unittest.cc b/components/cronet/url_request_context_config_unittest.cc index a0cef2a..d06522291 100644 --- a/components/cronet/url_request_context_config_unittest.cc +++ b/components/cronet/url_request_context_config_unittest.cc
@@ -46,6 +46,7 @@ "\"packet_loss_threshold\":0.5," "\"idle_connection_timeout_seconds\":300," "\"close_sessions_on_ip_change\":true," + "\"race_cert_verification\":true," "\"connection_options\":\"TIME,TBBR,REJ\"}," "\"AsyncDNS\":{\"enable\":true}}", // Data reduction proxy key. @@ -103,6 +104,9 @@ EXPECT_TRUE(params->quic_close_sessions_on_ip_change); EXPECT_FALSE(params->quic_migrate_sessions_on_network_change); + // Check race_cert_verification. + EXPECT_TRUE(params->quic_race_cert_verification); + // Check AsyncDNS resolver is enabled. EXPECT_TRUE(context->host_resolver()->GetDnsConfigAsValue()); }
diff --git a/components/ntp_tiles/BUILD.gn b/components/ntp_tiles/BUILD.gn index cdd6be5..09ab80c 100644 --- a/components/ntp_tiles/BUILD.gn +++ b/components/ntp_tiles/BUILD.gn
@@ -13,6 +13,8 @@ "constants.h", "most_visited_sites.cc", "most_visited_sites.h", + "ntp_tile.cc", + "ntp_tile.h", "popular_sites.cc", "popular_sites.h", "pref_names.cc", @@ -56,6 +58,7 @@ java_cpp_enum("ntp_tiles_enums_java") { sources = [ "most_visited_sites.h", + "ntp_tile.h", ] } }
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc index 894d83f..02b6776 100644 --- a/components/ntp_tiles/most_visited_sites.cc +++ b/components/ntp_tiles/most_visited_sites.cc
@@ -93,28 +93,28 @@ base::CompareCase::INSENSITIVE_ASCII); } -// Determine whether we need any popular suggestions to fill up a grid of +// Determine whether we need any tiles from PopularSites to fill up a grid of // |num_tiles| tiles. bool NeedPopularSites(const PrefService* prefs, int num_tiles) { - if (num_tiles <= prefs->GetInteger(prefs::kNumPersonalSuggestions)) + if (num_tiles <= prefs->GetInteger(prefs::kNumPersonalTiles)) return false; // TODO(treib): Remove after M55. const base::ListValue* source_list = - prefs->GetList(prefs::kDeprecatedNTPSuggestionsIsPersonal); - // If there aren't enough previous suggestions to fill the grid, we need - // popular suggestions. + prefs->GetList(prefs::kDeprecatedNTPTilesIsPersonal); + // If there aren't enough previous tiles to fill the grid, we need tiles from + // PopularSites. if (static_cast<int>(source_list->GetSize()) < num_tiles) return true; - // Otherwise, if any of the previous suggestions is not personal, then also - // get popular suggestions. + // Otherwise, if any of the previous tiles are not personal, then also + // get tiles from PopularSites. for (int i = 0; i < num_tiles; ++i) { bool is_personal = false; if (source_list->GetBoolean(i, &is_personal) && !is_personal) return true; } - // The whole grid is already filled with personal suggestions, no point in - // bothering with popular ones. + // The whole grid is already filled with personal tiles, no point in bothering + // with popular ones. return false; } @@ -124,13 +124,13 @@ std::string GetSourceHistogramName(int source) { switch (source) { - case MostVisitedSites::TOP_SITES: + case static_cast<int>(NTPTileSource::TOP_SITES): return kHistogramClientName; - case MostVisitedSites::POPULAR: + case static_cast<int>(NTPTileSource::POPULAR): return kHistogramPopularName; - case MostVisitedSites::WHITELIST: + case static_cast<int>(NTPTileSource::WHITELIST): return kHistogramWhitelistName; - case MostVisitedSites::SUGGESTIONS_SERVICE: + case static_cast<int>(NTPTileSource::SUGGESTIONS_SERVICE): return kHistogramServerName; } NOTREACHED(); @@ -139,20 +139,11 @@ } // namespace -MostVisitedSites::Suggestion::Suggestion() : source(TOP_SITES) {} - -MostVisitedSites::Suggestion::~Suggestion() {} - -MostVisitedSites::Suggestion::Suggestion(Suggestion&&) = default; -MostVisitedSites::Suggestion& -MostVisitedSites::Suggestion::operator=(Suggestion&&) = default; - -MostVisitedSites::MostVisitedSites( - PrefService* prefs, - scoped_refptr<history::TopSites> top_sites, - SuggestionsService* suggestions, - PopularSites* popular_sites, - MostVisitedSitesSupervisor* supervisor) +MostVisitedSites::MostVisitedSites(PrefService* prefs, + scoped_refptr<history::TopSites> top_sites, + SuggestionsService* suggestions, + PopularSites* popular_sites, + MostVisitedSitesSupervisor* supervisor) : prefs_(prefs), top_sites_(top_sites), suggestions_service_(suggestions), @@ -164,7 +155,7 @@ waiting_for_popular_sites_(true), recorded_uma_(false), top_sites_observer_(this), - mv_source_(SUGGESTIONS_SERVICE), + mv_source_(NTPTileSource::SUGGESTIONS_SERVICE), weak_ptr_factory_(this) { DCHECK(suggestions_service_); supervisor_->SetObserver(this); @@ -203,9 +194,9 @@ base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable, base::Unretained(this))); - // Immediately build the current suggestions, getting personal suggestions - // from the SuggestionsService's cache or, if that is empty, from TopSites. - BuildCurrentSuggestions(); + // Immediately build the current set of tiles, getting suggestions from the + // SuggestionsService's cache or, if that is empty, sites from TopSites. + BuildCurrentTiles(); // Also start a request for fresh suggestions. suggestions_service_->FetchSuggestionsData(); } @@ -221,7 +212,7 @@ } // Only blacklist in the server-side suggestions service if it's active. - if (mv_source_ == SUGGESTIONS_SERVICE) { + if (mv_source_ == NTPTileSource::SUGGESTIONS_SERVICE) { if (add_url) suggestions_service_->BlacklistURL(url); else @@ -271,19 +262,19 @@ } void MostVisitedSites::OnBlockedSitesChanged() { - BuildCurrentSuggestions(); + BuildCurrentTiles(); } // static void MostVisitedSites::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref(prefs::kNumPersonalSuggestions, 0); + registry->RegisterIntegerPref(prefs::kNumPersonalTiles, 0); // TODO(treib): Remove after M55. - registry->RegisterListPref(prefs::kDeprecatedNTPSuggestionsURL); - registry->RegisterListPref(prefs::kDeprecatedNTPSuggestionsIsPersonal); + registry->RegisterListPref(prefs::kDeprecatedNTPTilesURL); + registry->RegisterListPref(prefs::kDeprecatedNTPTilesIsPersonal); } -void MostVisitedSites::BuildCurrentSuggestions() { +void MostVisitedSites::BuildCurrentTiles() { // Get the current suggestions from cache. If the cache is empty, this will // fall back to TopSites. OnSuggestionsProfileAvailable( @@ -309,7 +300,7 @@ void MostVisitedSites::OnMostVisitedURLsAvailable( const history::MostVisitedURLList& visited_list) { - SuggestionsVector suggestions; + NTPTilesVector tiles; size_t num_tiles = std::min(visited_list.size(), static_cast<size_t>(num_sites_)); for (size_t i = 0; i < num_tiles; ++i) { @@ -321,18 +312,18 @@ if (supervisor_->IsBlocked(visited.url)) continue; - Suggestion suggestion; - suggestion.title = visited.title; - suggestion.url = visited.url; - suggestion.source = TOP_SITES; - suggestion.whitelist_icon_path = GetWhitelistLargeIconPath(visited.url); + NTPTile tile; + tile.title = visited.title; + tile.url = visited.url; + tile.source = NTPTileSource::TOP_SITES; + tile.whitelist_icon_path = GetWhitelistLargeIconPath(visited.url); - suggestions.push_back(std::move(suggestion)); + tiles.push_back(std::move(tile)); } waiting_for_most_visited_sites_ = false; - mv_source_ = TOP_SITES; - SaveNewSuggestions(std::move(suggestions)); + mv_source_ = NTPTileSource::TOP_SITES; + SaveNewTiles(std::move(tiles)); NotifyMostVisitedURLsObserver(); } @@ -348,47 +339,46 @@ if (num_sites_ < num_tiles) num_tiles = num_sites_; - SuggestionsVector suggestions; + NTPTilesVector tiles; for (int i = 0; i < num_tiles; ++i) { const ChromeSuggestion& suggestion_pb = suggestions_profile.suggestions(i); GURL url(suggestion_pb.url()); if (supervisor_->IsBlocked(url)) continue; - Suggestion suggestion; - suggestion.title = base::UTF8ToUTF16(suggestion_pb.title()); - suggestion.url = url; - suggestion.source = SUGGESTIONS_SERVICE; - suggestion.whitelist_icon_path = GetWhitelistLargeIconPath(url); + NTPTile tile; + tile.title = base::UTF8ToUTF16(suggestion_pb.title()); + tile.url = url; + tile.source = NTPTileSource::SUGGESTIONS_SERVICE; + tile.whitelist_icon_path = GetWhitelistLargeIconPath(url); - suggestions.push_back(std::move(suggestion)); + tiles.push_back(std::move(tile)); } waiting_for_most_visited_sites_ = false; - mv_source_ = SUGGESTIONS_SERVICE; - SaveNewSuggestions(std::move(suggestions)); + mv_source_ = NTPTileSource::SUGGESTIONS_SERVICE; + SaveNewTiles(std::move(tiles)); NotifyMostVisitedURLsObserver(); } -MostVisitedSites::SuggestionsVector -MostVisitedSites::CreateWhitelistEntryPointSuggestions( - const SuggestionsVector& personal_suggestions) { - size_t num_personal_suggestions = personal_suggestions.size(); - DCHECK_LE(num_personal_suggestions, static_cast<size_t>(num_sites_)); +NTPTilesVector MostVisitedSites::CreateWhitelistEntryPointTiles( + const NTPTilesVector& personal_tiles) { + size_t num_personal_tiles = personal_tiles.size(); + DCHECK_LE(num_personal_tiles, static_cast<size_t>(num_sites_)); - size_t num_whitelist_suggestions = num_sites_ - num_personal_suggestions; - SuggestionsVector whitelist_suggestions; + size_t num_whitelist_tiles = num_sites_ - num_personal_tiles; + NTPTilesVector whitelist_tiles; std::set<std::string> personal_hosts; - for (const auto& suggestion : personal_suggestions) - personal_hosts.insert(suggestion.url.host()); + for (const auto& tile : personal_tiles) + personal_hosts.insert(tile.url.host()); for (const auto& whitelist : supervisor_->whitelists()) { // Skip blacklisted sites. if (top_sites_ && top_sites_->IsBlacklisted(whitelist.entry_point)) continue; - // Skip suggestions already present. + // Skip tiles already present. if (personal_hosts.find(whitelist.entry_point.host()) != personal_hosts.end()) continue; @@ -397,107 +387,101 @@ if (supervisor_->IsBlocked(whitelist.entry_point)) continue; - Suggestion suggestion; - suggestion.title = whitelist.title; - suggestion.url = whitelist.entry_point; - suggestion.source = WHITELIST; - suggestion.whitelist_icon_path = whitelist.large_icon_path; + NTPTile tile; + tile.title = whitelist.title; + tile.url = whitelist.entry_point; + tile.source = NTPTileSource::WHITELIST; + tile.whitelist_icon_path = whitelist.large_icon_path; - whitelist_suggestions.push_back(std::move(suggestion)); - if (whitelist_suggestions.size() >= num_whitelist_suggestions) + whitelist_tiles.push_back(std::move(tile)); + if (whitelist_tiles.size() >= num_whitelist_tiles) break; } - return whitelist_suggestions; + return whitelist_tiles; } -MostVisitedSites::SuggestionsVector -MostVisitedSites::CreatePopularSitesSuggestions( - const SuggestionsVector& personal_suggestions, - const SuggestionsVector& whitelist_suggestions) { - // For child accounts popular sites suggestions will not be added. +NTPTilesVector MostVisitedSites::CreatePopularSitesTiles( + const NTPTilesVector& personal_tiles, + const NTPTilesVector& whitelist_tiles) { + // For child accounts popular sites tiles will not be added. if (supervisor_->IsChildProfile()) - return SuggestionsVector(); + return NTPTilesVector(); - size_t num_suggestions = - personal_suggestions.size() + whitelist_suggestions.size(); - DCHECK_LE(num_suggestions, static_cast<size_t>(num_sites_)); + size_t num_tiles = personal_tiles.size() + whitelist_tiles.size(); + DCHECK_LE(num_tiles, static_cast<size_t>(num_sites_)); // Collect non-blacklisted popular suggestions, skipping those already present // in the personal suggestions. - size_t num_popular_sites_suggestions = num_sites_ - num_suggestions; - SuggestionsVector popular_sites_suggestions; + size_t num_popular_sites_tiles = num_sites_ - num_tiles; + NTPTilesVector popular_sites_tiles; - if (num_popular_sites_suggestions > 0 && popular_sites_) { + if (num_popular_sites_tiles > 0 && popular_sites_) { std::set<std::string> hosts; - for (const auto& suggestion : personal_suggestions) - hosts.insert(suggestion.url.host()); - for (const auto& suggestion : whitelist_suggestions) - hosts.insert(suggestion.url.host()); + for (const auto& tile : personal_tiles) + hosts.insert(tile.url.host()); + for (const auto& tile : whitelist_tiles) + hosts.insert(tile.url.host()); for (const PopularSites::Site& popular_site : popular_sites_->sites()) { // Skip blacklisted sites. if (top_sites_ && top_sites_->IsBlacklisted(popular_site.url)) continue; std::string host = popular_site.url.host(); - // Skip suggestions already present in personal or whitelists. + // Skip tiles already present in personal or whitelists. if (hosts.find(host) != hosts.end()) continue; - Suggestion suggestion; - suggestion.title = popular_site.title; - suggestion.url = GURL(popular_site.url); - suggestion.source = POPULAR; + NTPTile tile; + tile.title = popular_site.title; + tile.url = GURL(popular_site.url); + tile.source = NTPTileSource::POPULAR; - popular_sites_suggestions.push_back(std::move(suggestion)); - if (popular_sites_suggestions.size() >= num_popular_sites_suggestions) + popular_sites_tiles.push_back(std::move(tile)); + if (popular_sites_tiles.size() >= num_popular_sites_tiles) break; } } - return popular_sites_suggestions; + return popular_sites_tiles; } -void MostVisitedSites::SaveNewSuggestions( - SuggestionsVector personal_suggestions) { - SuggestionsVector whitelist_suggestions = - CreateWhitelistEntryPointSuggestions(personal_suggestions); - SuggestionsVector popular_sites_suggestions = - CreatePopularSitesSuggestions(personal_suggestions, - whitelist_suggestions); +void MostVisitedSites::SaveNewTiles(NTPTilesVector personal_tiles) { + NTPTilesVector whitelist_tiles = + CreateWhitelistEntryPointTiles(personal_tiles); + NTPTilesVector popular_sites_tiles = + CreatePopularSitesTiles(personal_tiles, whitelist_tiles); - size_t num_actual_tiles = personal_suggestions.size() + - whitelist_suggestions.size() + - popular_sites_suggestions.size(); + size_t num_actual_tiles = personal_tiles.size() + whitelist_tiles.size() + + popular_sites_tiles.size(); DCHECK_LE(num_actual_tiles, static_cast<size_t>(num_sites_)); - current_suggestions_ = MergeSuggestions(std::move(personal_suggestions), - std::move(whitelist_suggestions), - std::move(popular_sites_suggestions)); - DCHECK_EQ(num_actual_tiles, current_suggestions_.size()); + current_tiles_ = + MergeTiles(std::move(personal_tiles), std::move(whitelist_tiles), + std::move(popular_sites_tiles)); + DCHECK_EQ(num_actual_tiles, current_tiles_.size()); - int num_personal_suggestions = 0; - for (const auto& suggestion : current_suggestions_) { - if (suggestion.source != POPULAR) - num_personal_suggestions++; + int num_personal_tiles = 0; + for (const auto& tile : current_tiles_) { + if (tile.source != NTPTileSource::POPULAR) + num_personal_tiles++; } - prefs_->SetInteger(prefs::kNumPersonalSuggestions, num_personal_suggestions); + prefs_->SetInteger(prefs::kNumPersonalTiles, num_personal_tiles); // TODO(treib): Remove after M55. - prefs_->ClearPref(prefs::kDeprecatedNTPSuggestionsIsPersonal); - prefs_->ClearPref(prefs::kDeprecatedNTPSuggestionsURL); + prefs_->ClearPref(prefs::kDeprecatedNTPTilesIsPersonal); + prefs_->ClearPref(prefs::kDeprecatedNTPTilesURL); } // static -MostVisitedSites::SuggestionsVector MostVisitedSites::MergeSuggestions( - SuggestionsVector personal_suggestions, - SuggestionsVector whitelist_suggestions, - SuggestionsVector popular_suggestions) { - SuggestionsVector merged_suggestions; - std::move(personal_suggestions.begin(), personal_suggestions.end(), - std::back_inserter(merged_suggestions)); - std::move(whitelist_suggestions.begin(), whitelist_suggestions.end(), - std::back_inserter(merged_suggestions)); - std::move(popular_suggestions.begin(), popular_suggestions.end(), - std::back_inserter(merged_suggestions)); - return merged_suggestions; +NTPTilesVector MostVisitedSites::MergeTiles(NTPTilesVector personal_tiles, + NTPTilesVector whitelist_tiles, + NTPTilesVector popular_tiles) { + NTPTilesVector merged_tiles; + std::move(personal_tiles.begin(), personal_tiles.end(), + std::back_inserter(merged_tiles)); + std::move(whitelist_tiles.begin(), whitelist_tiles.end(), + std::back_inserter(merged_tiles)); + std::move(popular_tiles.begin(), popular_tiles.end(), + std::back_inserter(merged_tiles)); + return merged_tiles; } void MostVisitedSites::NotifyMostVisitedURLsObserver() { @@ -510,7 +494,7 @@ if (!observer_) return; - observer_->OnMostVisitedURLsAvailable(current_suggestions_); + observer_->OnMostVisitedURLsAvailable(current_tiles_); } void MostVisitedSites::OnPopularSitesAvailable(bool success) { @@ -525,21 +509,22 @@ // missing icons, but will *not* cause it to display the popular sites. observer_->OnPopularURLsAvailable(popular_sites_->sites()); - // Re-build the suggestions list. Once done, this will notify the observer. - BuildCurrentSuggestions(); + // Re-build the tile list. Once done, this will notify the observer. + BuildCurrentTiles(); } void MostVisitedSites::RecordImpressionUMAMetrics() { UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfTiles", - current_suggestions_.size()); + current_tiles_.size()); - for (size_t i = 0; i < current_suggestions_.size(); i++) { + for (size_t i = 0; i < current_tiles_.size(); i++) { UMA_HISTOGRAM_ENUMERATION( "NewTabPage.SuggestionsImpression", static_cast<int>(i), num_sites_); std::string histogram = base::StringPrintf( "NewTabPage.SuggestionsImpression.%s", - GetSourceHistogramName(current_suggestions_[i].source).c_str()); + GetSourceHistogramName(static_cast<int>(current_tiles_[i].source)) + .c_str()); LogHistogramEvent(histogram, static_cast<int>(i), num_sites_); } } @@ -548,8 +533,8 @@ void MostVisitedSites::TopSitesChanged(TopSites* top_sites, ChangeReason change_reason) { - if (mv_source_ == TOP_SITES) { - // The displayed suggestions are invalidated. + if (mv_source_ == NTPTileSource::TOP_SITES) { + // The displayed tiles are invalidated. InitiateTopSitesQuery(); } }
diff --git a/components/ntp_tiles/most_visited_sites.h b/components/ntp_tiles/most_visited_sites.h index b2f96c2..9d2fed9 100644 --- a/components/ntp_tiles/most_visited_sites.h +++ b/components/ntp_tiles/most_visited_sites.h
@@ -18,6 +18,7 @@ #include "base/strings/string16.h" #include "components/history/core/browser/history_types.h" #include "components/history/core/browser/top_sites_observer.h" +#include "components/ntp_tiles/ntp_tile.h" #include "components/ntp_tiles/popular_sites.h" #include "components/suggestions/proto/suggestions.pb.h" #include "components/suggestions/suggestions_service.h" @@ -59,7 +60,7 @@ // If true, |url| should not be shown on the NTP. virtual bool IsBlocked(const GURL& url) = 0; - // Explicit suggestions for sites to show on NTP. + // Explicitly-specified sites to show on NTP. virtual std::vector<Whitelist> whitelists() = 0; // If true, be conservative about suggesting sites from outside sources. @@ -79,8 +80,6 @@ class MostVisitedSites : public history::TopSitesObserver, public MostVisitedSitesSupervisor::Observer { public: - struct Suggestion; - using SuggestionsVector = std::vector<Suggestion>; using PopularSitesVector = std::vector<PopularSites::Site>; // The visual type of a most visited tile. @@ -102,49 +101,16 @@ NUM_TILE_TYPES, }; - // The source of the Most Visited sites. - // A Java counterpart will be generated for this enum. - // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp - enum MostVisitedSource { - // Item comes from the personal top sites list. - TOP_SITES, - // Item comes from the suggestions service. - SUGGESTIONS_SERVICE, - // Item is regionally popular. - POPULAR, - // Item is on an custodian-managed whitelist. - WHITELIST - }; - // The observer to be notified when the list of most visited sites changes. class Observer { public: - virtual void OnMostVisitedURLsAvailable( - const SuggestionsVector& suggestions) = 0; + virtual void OnMostVisitedURLsAvailable(const NTPTilesVector& tiles) = 0; virtual void OnPopularURLsAvailable(const PopularSitesVector& sites) = 0; protected: virtual ~Observer() {} }; - struct Suggestion { - base::string16 title; - GURL url; - MostVisitedSource source; - - // Only valid for source == WHITELIST (empty otherwise). - base::FilePath whitelist_icon_path; - - Suggestion(); - ~Suggestion(); - - Suggestion(Suggestion&&); - Suggestion& operator=(Suggestion&&); - - private: - DISALLOW_COPY_AND_ASSIGN(Suggestion); - }; - MostVisitedSites(PrefService* prefs, scoped_refptr<history::TopSites> top_sites, suggestions::SuggestionsService* suggestions, @@ -170,7 +136,7 @@ private: friend class MostVisitedSitesTest; - void BuildCurrentSuggestions(); + void BuildCurrentTiles(); // Initialize the query to Top Sites. Called if the SuggestionsService // returned no data. @@ -189,27 +155,25 @@ // Takes the personal suggestions and creates whitelist entry point // suggestions if necessary. - SuggestionsVector CreateWhitelistEntryPointSuggestions( - const SuggestionsVector& personal_suggestions); + NTPTilesVector CreateWhitelistEntryPointTiles( + const NTPTilesVector& personal_tiles); - // Takes the personal and whitelist suggestions and creates popular - // suggestions if necessary. - SuggestionsVector CreatePopularSitesSuggestions( - const SuggestionsVector& personal_suggestions, - const SuggestionsVector& whitelist_suggestions); + // Takes the personal and whitelist tiles and creates popular tiles if + // necessary. + NTPTilesVector CreatePopularSitesTiles(const NTPTilesVector& personal_tiles, + const NTPTilesVector& whitelist_tiles); - // Takes the personal suggestions, creates and merges in whitelist and popular - // suggestions if appropriate, and saves the new suggestions. - void SaveNewSuggestions(SuggestionsVector personal_suggestions); + // Takes the personal tiles, creates and merges in whitelist and popular tiles + // if appropriate, and saves the new tiles. + void SaveNewTiles(NTPTilesVector personal_tiles); - // Workhorse for SaveNewSuggestions above. Implemented as a separate static - // method for ease of testing. - static SuggestionsVector MergeSuggestions( - SuggestionsVector personal_suggestions, - SuggestionsVector whitelist_suggestions, - SuggestionsVector popular_suggestions); + // Workhorse for SaveNewTiles above. Implemented as a separate static method + // for ease of testing. + static NTPTilesVector MergeTiles(NTPTilesVector personal_tiles, + NTPTilesVector whitelist_tiles, + NTPTilesVector popular_tiles); - // Notifies the observer about the availability of suggestions. + // Notifies the observer about the availability of tiles. // Also records impressions UMA if not done already. void NotifyMostVisitedURLsObserver(); @@ -253,11 +217,10 @@ ScopedObserver<history::TopSites, history::TopSitesObserver> top_sites_observer_; - // The main source of personal suggestions - either TOP_SITES or - // SUGGESTIONS_SEVICE. - MostVisitedSource mv_source_; + // The main source of personal tiles - either TOP_SITES or SUGGESTIONS_SEVICE. + NTPTileSource mv_source_; - SuggestionsVector current_suggestions_; + NTPTilesVector current_tiles_; // For callbacks may be run after destruction. base::WeakPtrFactory<MostVisitedSites> weak_ptr_factory_;
diff --git a/components/ntp_tiles/most_visited_sites_unittest.cc b/components/ntp_tiles/most_visited_sites_unittest.cc index e88f518..6fbc9dc 100644 --- a/components/ntp_tiles/most_visited_sites_unittest.cc +++ b/components/ntp_tiles/most_visited_sites_unittest.cc
@@ -36,13 +36,13 @@ } // namespace -// This a test for MostVisitedSites::MergeSuggestions(...) method, and thus has -// the same scope as the method itself. This tests merging popular suggestions -// with personal suggestions. +// This a test for MostVisitedSites::MergeTiles(...) method, and thus has the +// same scope as the method itself. This tests merging popular sites with +// personal tiles. // More important things out of the scope of testing presently: -// - Removing blacklisted suggestions. +// - Removing blacklisted tiles. // - Correct host extraction from the URL. -// - Ensuring personal suggestions are not duplicated in popular suggestions. +// - Ensuring personal tiles are not duplicated in popular tiles. class MostVisitedSitesTest : public testing::Test { protected: void Check(const std::vector<TitleURL>& popular_sites, @@ -50,42 +50,39 @@ const std::vector<TitleURL>& personal_sites, const std::vector<bool>& expected_sites_is_personal, const std::vector<TitleURL>& expected_sites) { - MostVisitedSites::SuggestionsVector personal_suggestions; + NTPTilesVector personal_tiles; for (const TitleURL& site : personal_sites) - personal_suggestions.push_back(MakeSuggestionFrom(site, true, false)); - MostVisitedSites::SuggestionsVector whitelist_suggestions; + personal_tiles.push_back(MakeTileFrom(site, true, false)); + NTPTilesVector whitelist_tiles; for (const TitleURL& site : whitelist_entry_points) - whitelist_suggestions.push_back(MakeSuggestionFrom(site, false, true)); - MostVisitedSites::SuggestionsVector popular_suggestions; + whitelist_tiles.push_back(MakeTileFrom(site, false, true)); + NTPTilesVector popular_tiles; for (const TitleURL& site : popular_sites) - popular_suggestions.push_back(MakeSuggestionFrom(site, false, false)); - MostVisitedSites::SuggestionsVector result_suggestions = - MostVisitedSites::MergeSuggestions(std::move(personal_suggestions), - std::move(whitelist_suggestions), - std::move(popular_suggestions)); + popular_tiles.push_back(MakeTileFrom(site, false, false)); + NTPTilesVector result_tiles = MostVisitedSites::MergeTiles( + std::move(personal_tiles), std::move(whitelist_tiles), + std::move(popular_tiles)); std::vector<TitleURL> result_sites; std::vector<bool> result_is_personal; - result_sites.reserve(result_suggestions.size()); - result_is_personal.reserve(result_suggestions.size()); - for (const auto& suggestion : result_suggestions) { - result_sites.push_back(TitleURL(suggestion.title, suggestion.url.spec())); - result_is_personal.push_back(suggestion.source != - MostVisitedSites::POPULAR); + result_sites.reserve(result_tiles.size()); + result_is_personal.reserve(result_tiles.size()); + for (const auto& tile : result_tiles) { + result_sites.push_back(TitleURL(tile.title, tile.url.spec())); + result_is_personal.push_back(tile.source != NTPTileSource::POPULAR); } EXPECT_EQ(expected_sites_is_personal, result_is_personal); EXPECT_EQ(expected_sites, result_sites); } - static MostVisitedSites::Suggestion MakeSuggestionFrom( - const TitleURL& title_url, - bool is_personal, - bool whitelist) { - MostVisitedSites::Suggestion suggestion; - suggestion.title = title_url.title; - suggestion.url = GURL(title_url.url); - suggestion.source = whitelist ? MostVisitedSites::WHITELIST - : (is_personal ? MostVisitedSites::TOP_SITES - : MostVisitedSites::POPULAR); - return suggestion; + static NTPTile MakeTileFrom(const TitleURL& title_url, + bool is_personal, + bool whitelist) { + NTPTile tile; + tile.title = title_url.title; + tile.url = GURL(title_url.url); + tile.source = whitelist ? NTPTileSource::WHITELIST + : (is_personal ? NTPTileSource::TOP_SITES + : NTPTileSource::POPULAR); + return tile; } }; @@ -96,8 +93,8 @@ TitleURL("Site 3", "https://www.site3.com/"), TitleURL("Site 4", "https://www.site4.com/"), }; - // Without any popular suggestions, the result after merge should be the - // personal suggestions. + // Without any popular tiles, the result after merge should be the personal + // tiles. std::vector<bool> expected_sites_source(kNumSites, true /*personal source*/); Check(std::vector<TitleURL>(), std::vector<TitleURL>(), personal_sites, expected_sites_source, personal_sites); @@ -110,8 +107,8 @@ TitleURL("Site 3", "https://www.site3.com/"), TitleURL("Site 4", "https://www.site4.com/"), }; - // Without any personal suggestions, the result after merge should be the - // popular suggestions. + // Without any personal tiles, the result after merge should be the popular + // tiles. std::vector<bool> expected_sites_source(kNumSites, false /*popular source*/); Check(popular_sites, std::vector<TitleURL>(), std::vector<TitleURL>(), expected_sites_source, popular_sites); @@ -126,7 +123,7 @@ TitleURL("Site 3", "https://www.site3.com/"), TitleURL("Site 4", "https://www.site4.com/"), }; - // Personal suggestions should precede popular suggestions. + // Personal tiles should precede popular tiles. std::vector<TitleURL> expected_sites{ TitleURL("Site 3", "https://www.site3.com/"), TitleURL("Site 4", "https://www.site4.com/"),
diff --git a/components/ntp_tiles/ntp_tile.cc b/components/ntp_tiles/ntp_tile.cc new file mode 100644 index 0000000..82d16ce --- /dev/null +++ b/components/ntp_tiles/ntp_tile.cc
@@ -0,0 +1,17 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/ntp_tiles/ntp_tile.h" + +namespace ntp_tiles { + +NTPTile::NTPTile() : source(NTPTileSource::TOP_SITES) {} + +NTPTile::~NTPTile() {} + +NTPTile::NTPTile(NTPTile&&) = default; + +NTPTile& NTPTile::operator=(NTPTile&&) = default; + +} // namespace ntp_tiles
diff --git a/components/ntp_tiles/ntp_tile.h b/components/ntp_tiles/ntp_tile.h new file mode 100644 index 0000000..e82cd4db --- /dev/null +++ b/components/ntp_tiles/ntp_tile.h
@@ -0,0 +1,54 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_NTP_TILES_NTP_TILE_H_ +#define COMPONENTS_NTP_TILES_NTP_TILE_H_ + +#include <vector> + +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/strings/string16.h" +#include "url/gurl.h" + +namespace ntp_tiles { + +// The source of an NTP tile. +// A Java counterpart will be generated for this enum. +// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp +enum class NTPTileSource { + // Tile comes from the personal top sites list, based on local history. + TOP_SITES, + // Tile comes from the suggestions service, based on synced history. + SUGGESTIONS_SERVICE, + // Tile is regionally popular. + POPULAR, + // Tile is on an custodian-managed whitelist. + WHITELIST +}; + +// A suggested site shown on the New Tab Page. +struct NTPTile { + base::string16 title; + GURL url; + NTPTileSource source; + + // Only valid for source == WHITELIST (empty otherwise). + base::FilePath whitelist_icon_path; + + NTPTile(); + ~NTPTile(); + + NTPTile(NTPTile&&); + NTPTile& operator=(NTPTile&&); + + private: + DISALLOW_COPY_AND_ASSIGN(NTPTile); +}; + +using NTPTilesVector = std::vector<NTPTile>; + +} // namespace ntp_tiles + +#endif // COMPONENTS_NTP_TILES_NTP_TILE_H_
diff --git a/components/ntp_tiles/popular_sites.h b/components/ntp_tiles/popular_sites.h index 537c7d9..639aedf4 100644 --- a/components/ntp_tiles/popular_sites.h +++ b/components/ntp_tiles/popular_sites.h
@@ -44,8 +44,8 @@ const base::Callback<void(const std::string&)>& error_callback)>; // Downloads and provides a list of suggested popular sites, for display on -// the NTP when there are not enough personalized suggestions. Caches the -// downloaded file on disk to avoid re-downloading on every startup. +// the NTP when there are not enough personalized tiles. Caches the downloaded +// file on disk to avoid re-downloading on every startup. class PopularSites : public net::URLFetcherDelegate { public: struct Site { @@ -79,7 +79,7 @@ // invokes |callback| before returning control to the caller, even if the // result is immediately known. // - // Set |force_download| to enforce re-downloading the suggestions file, even + // Set |force_download| to enforce re-downloading the popular sites file, even // if it already exists on disk. // // Must be called at most once on a given PopularSites object.
diff --git a/components/ntp_tiles/pref_names.cc b/components/ntp_tiles/pref_names.cc index 77c47d05..1ec52196 100644 --- a/components/ntp_tiles/pref_names.cc +++ b/components/ntp_tiles/pref_names.cc
@@ -7,13 +7,12 @@ namespace ntp_tiles { namespace prefs { -const char kDeprecatedNTPSuggestionsURL[] = "ntp.suggestions_url"; -const char kDeprecatedNTPSuggestionsIsPersonal[] = - "ntp.suggestions_is_personal"; +const char kDeprecatedNTPTilesURL[] = "ntp.suggestions_url"; +const char kDeprecatedNTPTilesIsPersonal[] = "ntp.suggestions_is_personal"; -// The number of personal suggestions we had previously. Used to figure out +// The number of personal tiles we had previously. Used to figure out // whether we need popular sites. -const char kNumPersonalSuggestions[] = "ntp.num_personal_suggestions"; +const char kNumPersonalTiles[] = "ntp.num_personal_suggestions"; // If set, overrides the URL for popular sites, including the individual // overrides for country and version below.
diff --git a/components/ntp_tiles/pref_names.h b/components/ntp_tiles/pref_names.h index 81f62f1..243a5fa 100644 --- a/components/ntp_tiles/pref_names.h +++ b/components/ntp_tiles/pref_names.h
@@ -9,10 +9,10 @@ namespace prefs { // TODO(treib): Remove after M55. -extern const char kDeprecatedNTPSuggestionsURL[]; -extern const char kDeprecatedNTPSuggestionsIsPersonal[]; +extern const char kDeprecatedNTPTilesURL[]; +extern const char kDeprecatedNTPTilesIsPersonal[]; -extern const char kNumPersonalSuggestions[]; +extern const char kNumPersonalTiles[]; extern const char kPopularSitesOverrideURL[]; extern const char kPopularSitesOverrideCountry[];
diff --git a/components/pdf/renderer/pdf_accessibility_tree.cc b/components/pdf/renderer/pdf_accessibility_tree.cc index 0763ca2..b408901 100644 --- a/components/pdf/renderer/pdf_accessibility_tree.cc +++ b/components/pdf/renderer/pdf_accessibility_tree.cc
@@ -65,6 +65,9 @@ void PdfAccessibilityTree::SetAccessibilityDocInfo( const PP_PrivateAccessibilityDocInfo& doc_info) { + if (!GetRenderAccessibility()) + return; + doc_info_ = doc_info; doc_node_ = CreateNode(ui::AX_ROLE_GROUP); }
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc index ed0adbc0..7992f78 100644 --- a/components/plugins/renderer/webview_plugin.cc +++ b/components/plugins/renderer/webview_plugin.cc
@@ -209,6 +209,13 @@ bool is_visible) { DCHECK(container_); + base::AutoReset<bool> is_resizing(&is_resizing_, true); + + if (static_cast<gfx::Rect>(window_rect) != rect_) { + rect_ = window_rect; + web_view_->resize(rect_.size()); + } + // Plugin updates are forbidden during Blink layout. Therefore, // UpdatePluginForNewGeometry must be posted to a task to run asynchronously. base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -348,19 +355,13 @@ const blink::WebRect& window_rect, const blink::WebRect& unobscured_rect) { DCHECK(container_); + if (!delegate_) + return; - base::AutoReset<bool> is_resizing(&is_resizing_, true); - - if (static_cast<gfx::Rect>(window_rect) != rect_) { - rect_ = window_rect; - web_view_->resize(rect_.size()); - } - - if (delegate_) { - delegate_->OnUnobscuredRectUpdate(gfx::Rect(unobscured_rect)); - // The delegate may have dirtied style and layout of the WebView. - // See for example the resizePoster function in plugin_poster.html. - // Run the lifecycle now so that it is clean. - web_view_->updateAllLifecyclePhases(); - } + // The delegate may instantiate a new plugin. + delegate_->OnUnobscuredRectUpdate(gfx::Rect(unobscured_rect)); + // The delegate may have dirtied style and layout of the WebView. + // See for example the resizePoster function in plugin_poster.html. + // Run the lifecycle now so that it is clean. + web_view_->updateAllLifecyclePhases(); }
diff --git a/components/translate/core/browser/resources/translate.js b/components/translate/core/browser/resources/translate.js index fb59e660..79c5793 100644 --- a/components/translate/core/browser/resources/translate.js +++ b/components/translate/core/browser/resources/translate.js
@@ -258,12 +258,15 @@ lib = google.translate.TranslateService({ // translateApiKey is predefined by translate_script.cc. 'key': translateApiKey, + 'serverParams': serverParams, 'useSecureConnection': true }); translateApiKey = undefined; + serverParams = undefined; } catch (err) { errorCode = ERROR['INITIALIZATION_ERROR']; translateApiKey = undefined; + serverParams = undefined; return; } // The TranslateService is not available immediately as it needs to start
diff --git a/components/translate/core/browser/translate_script.cc b/components/translate/core/browser/translate_script.cc index 511ac6c..875fc7f4 100644 --- a/components/translate/core/browser/translate_script.cc +++ b/components/translate/core/browser/translate_script.cc
@@ -19,6 +19,7 @@ #include "components/translate/core/browser/translate_url_util.h" #include "components/translate/core/common/translate_switches.h" #include "components/translate/core/common/translate_util.h" +#include "components/variations/variations_associated_data.h" #include "google_apis/google_api_keys.h" #include "grit/components_resources.h" #include "net/base/escape.h" @@ -48,6 +49,8 @@ const char TranslateScript::kJavascriptLoaderCallbackQueryName[] = "jlc"; const char TranslateScript::kJavascriptLoaderCallbackQueryValue[] = "cr.googleTranslate.onLoadJavascript"; +const char kTranslateServerStudy[] = "TranslateServerStudy"; +const char kServerParams[] = "server_params"; TranslateScript::TranslateScript() : expiration_delay_(base::TimeDelta::FromDays(kExpirationDelayDays)), @@ -132,6 +135,16 @@ data_ = base::StringPrintf("var translateApiKey = '%s';\n", google_apis::GetAPIKey().c_str()); + // Insert server params to pass experimental params to google translate + // server. + std::string server_params; + std::map<std::string, std::string> params; + if (variations::GetVariationParams(kTranslateServerStudy, ¶ms)) { + server_params = params[kServerParams]; + } + base::StringAppendF(&data_, "var serverParams = '%s';\n", + server_params.c_str()); + GURL security_origin = translate::GetTranslateSecurityOrigin(); base::StringAppendF( &data_, "var securityOrigin = '%s';", security_origin.spec().c_str());
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm index 8aa8bf8..1b84156 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.mm +++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -82,6 +82,12 @@ @"AXLineTextMarkerRangeForTextMarker"; NSString* const NSAccessibilitySelectTextWithCriteriaParameterizedAttribute = @"AXSelectTextWithCriteria"; +NSString* const NSAccessibilityBoundsForTextMarkerRangeParameterizedAttribute = + @"AXBoundsForTextMarkerRange"; +NSString* const NSAccessibilityTextMarkerRangeForUnorderedTextMarkersParameterizedAttribute = + @"AXTextMarkerRangeForUnorderedTextMarkers"; +NSString* const NSAccessibilityIndexForChildUIElementParameterizedAttribute = + @"AXIndexForChildUIElement"; // Actions. NSString* const NSAccessibilityScrollToVisibleAction = @"AXScrollToVisible"; @@ -2003,7 +2009,9 @@ [self internalRole] != ui::AX_ROLE_GRID) { return nil; } - if (![parameter isKindOfClass:[NSArray self]]) + if (![parameter isKindOfClass:[NSArray class]]) + return nil; + if (2 != [parameter count]) return nil; NSArray* array = parameter; int column = [[array objectAtIndex:0] intValue]; @@ -2271,9 +2279,8 @@ return nil; } - if ([attribute - isEqualToString: - NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute]) { + if ([attribute isEqualToString: + NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute]) { BrowserAccessibility* object; int offset; ui::AXTextAffinity affinity; @@ -2281,13 +2288,100 @@ return nil; DCHECK(object); - int start_offset = + int startOffset = object->GetLineStartBoundary(offset, ui::BACKWARDS_DIRECTION, affinity); - int end_offset = + int endOffset = object->GetLineStartBoundary(offset, ui::FORWARDS_DIRECTION, affinity); return CreateTextMarkerRange( - *object, start_offset, ui::AX_TEXT_AFFINITY_UPSTREAM, - *object, end_offset, ui::AX_TEXT_AFFINITY_DOWNSTREAM); + *object, startOffset, ui::AX_TEXT_AFFINITY_UPSTREAM, + *object, endOffset, ui::AX_TEXT_AFFINITY_DOWNSTREAM); + } + + if ([attribute isEqualToString: + NSAccessibilityBoundsForTextMarkerRangeParameterizedAttribute]) { + BrowserAccessibility* startObject; + BrowserAccessibility* endObject; + int startOffset, endOffset; + ui::AXTextAffinity startAffinity, endAffinity; + if (!GetTextMarkerRange(parameter, + &startObject, &startOffset, &startAffinity, + &endObject, &endOffset, &endAffinity)) { + return nil; + } + DCHECK(startObject && endObject); + DCHECK_GE(startOffset, 0); + DCHECK_GE(endOffset, 0); + + gfx::Rect rect = BrowserAccessibilityManager::GetLocalBoundsForRange( + *startObject, startOffset, *endObject, endOffset); + NSPoint origin = NSMakePoint(rect.x(), rect.y()); + NSSize size = NSMakeSize(rect.width(), rect.height()); + NSPoint pointInScreen = [self pointInScreen:origin size:size]; + NSRect nsrect = NSMakeRect( + pointInScreen.x, pointInScreen.y, rect.width(), rect.height()); + return [NSValue valueWithRect:nsrect]; + } + + if ([attribute isEqualToString: + NSAccessibilityTextMarkerRangeForUnorderedTextMarkersParameterizedAttribute]) { + if (![parameter isKindOfClass:[NSArray class]]) + return nil; + + NSArray* array = parameter; + id first = [array objectAtIndex:0]; + id second = [array objectAtIndex:1]; + BrowserAccessibility* object1; + int offset1; + ui::AXTextAffinity affinity1; + if (!GetTextMarkerData(first, &object1, &offset1, &affinity1)) + return nil; + + BrowserAccessibility* object2; + int offset2; + ui::AXTextAffinity affinity2; + if (!GetTextMarkerData(second, &object2, &offset2, &affinity2)) + return nil; + + bool isInOrder = true; + if (object1 == object2) { + if (offset2 > offset1) + isInOrder = true; + else if (offset2 < offset1) + isInOrder = false; + else + return nil; + } + + ui::AXTreeOrder order = BrowserAccessibilityManager::CompareNodes( + *object1, *object2); + if (order == ui::AX_TREE_ORDER_BEFORE || + (order == ui::AX_TREE_ORDER_EQUAL && offset1 < offset2)) { + return CreateTextMarkerRange(*object1, offset1, affinity1, + *object2, offset2, affinity2); + } + if (order == ui::AX_TREE_ORDER_AFTER || + (order == ui::AX_TREE_ORDER_EQUAL && offset1 > offset2)) { + return CreateTextMarkerRange(*object2, offset2, affinity2, + *object1, offset1, affinity1); + } + return nil; + } + + if ([attribute isEqualToString: + NSAccessibilityIndexForChildUIElementParameterizedAttribute]) { + if (![parameter isKindOfClass:[BrowserAccessibilityCocoa class]]) + return nil; + + BrowserAccessibilityCocoa* childCocoaObj = + (BrowserAccessibilityCocoa*)parameter; + BrowserAccessibility* child = [childCocoaObj browserAccessibility]; + if (!child) + return nil; + + if (child->GetParent() != browserAccessibility_) + return nil; + + return @(child->GetIndexInParent()); } return nil; @@ -2305,9 +2399,7 @@ @"AXUIElementForTextMarker", @"AXTextMarkerRangeForUIElement", @"AXLineForTextMarker", @"AXTextMarkerRangeForLine", @"AXStringForTextMarkerRange", @"AXTextMarkerForPosition", - @"AXBoundsForTextMarkerRange", @"AXAttributedStringForTextMarkerRange", - @"AXTextMarkerRangeForUnorderedTextMarkers", @"AXNextTextMarkerForTextMarker", @"AXPreviousTextMarkerForTextMarker", @"AXLeftWordTextMarkerRangeForTextMarker", @@ -2325,6 +2417,9 @@ @"AXNextParagraphEndTextMarkerForTextMarker", @"AXPreviousParagraphStartTextMarkerForTextMarker", @"AXStyleTextMarkerRangeForTextMarker", @"AXLengthForTextMarkerRange", + NSAccessibilityBoundsForTextMarkerRangeParameterizedAttribute, + NSAccessibilityTextMarkerRangeForUnorderedTextMarkersParameterizedAttribute, + NSAccessibilityIndexForChildUIElementParameterizedAttribute, NSAccessibilityBoundsForRangeParameterizedAttribute, NSAccessibilityStringForRangeParameterizedAttribute, NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute,
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc index 148bc70..7cef0bb5 100644 --- a/content/browser/accessibility/browser_accessibility_manager.cc +++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -718,6 +718,31 @@ } // static +ui::AXTreeOrder BrowserAccessibilityManager::CompareNodes( + const BrowserAccessibility& object1, + const BrowserAccessibility& object2) { + if (&object1 == &object2) + return ui::AX_TREE_ORDER_EQUAL; + + BrowserAccessibility* common_parent; + int child_index1; + int child_index2; + if (FindIndicesInCommonParent( + object1, object2, &common_parent, &child_index1, &child_index2)) { + if (child_index1 < child_index2) + return ui::AX_TREE_ORDER_BEFORE; + if (child_index1 > child_index2) + return ui::AX_TREE_ORDER_AFTER; + } + + if (object2.IsDescendantOf(&object1)) + return ui::AX_TREE_ORDER_BEFORE; + if (object1.IsDescendantOf(&object2)) + return ui::AX_TREE_ORDER_AFTER; + + return ui::AX_TREE_ORDER_UNDEFINED; +} + std::vector<const BrowserAccessibility*> BrowserAccessibilityManager::FindTextOnlyObjectsInRange( const BrowserAccessibility& start_object, @@ -861,6 +886,69 @@ return text; } +// static +gfx::Rect BrowserAccessibilityManager::GetLocalBoundsForRange( + const BrowserAccessibility& start_object, + int start_offset, + const BrowserAccessibility& end_object, + int end_offset) { + DCHECK_GE(start_offset, 0); + DCHECK_GE(end_offset, 0); + + if (&start_object == &end_object && start_object.IsSimpleTextControl()) { + if (start_offset > end_offset) + std::swap(start_offset, end_offset); + + if (start_offset >= static_cast<int>(start_object.GetText().length()) || + end_offset > static_cast<int>(start_object.GetText().length())) { + return gfx::Rect(); + } + + return start_object.GetLocalBoundsForRange( + start_offset, end_offset - start_offset); + } + + gfx::Rect result; + const BrowserAccessibility* first = &start_object; + const BrowserAccessibility* last = &end_object; + + switch (CompareNodes(*first, *last)) { + case ui::AX_TREE_ORDER_BEFORE: + case ui::AX_TREE_ORDER_EQUAL: + break; + case ui::AX_TREE_ORDER_AFTER: + std::swap(first, last); + std::swap(start_offset, end_offset); + break; + default: + return gfx::Rect(); + } + + const BrowserAccessibility* current = first; + do { + if (current->IsTextOnlyObject()) { + int len = static_cast<int>(current->GetText().size()); + int start_char_index = 0; + int end_char_index = len; + if (current == first) + start_char_index = start_offset; + if (current == last) + end_char_index = end_offset; + result.Union(current->GetLocalBoundsForRange( + start_char_index, end_char_index - start_char_index)); + } else { + result.Union(current->GetLocalBoundsRect()); + } + + if (current == last) + break; + + current = NextInTreeOrder(current); + } while (current); + + return result; +} + void BrowserAccessibilityManager::OnNodeDataWillChange( ui::AXTree* tree, const ui::AXNodeData& old_node_data,
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h index 45957d9..a1bb8e9 100644 --- a/content/browser/accessibility/browser_accessibility_manager.h +++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -320,6 +320,13 @@ int* child_index1, int* child_index2); + // Sets |out_is_before| to true if |object1| comes before |object2| + // in tree order (pre-order traversal), and false if the objects are the + // same or not in the same tree. + static ui::AXTreeOrder CompareNodes( + const BrowserAccessibility& object1, + const BrowserAccessibility& object2); + static std::vector<const BrowserAccessibility*> FindTextOnlyObjectsInRange( const BrowserAccessibility& start_object, const BrowserAccessibility& end_object); @@ -336,6 +343,12 @@ const BrowserAccessibility& end_object, int end_offset); + static gfx::Rect GetLocalBoundsForRange( + const BrowserAccessibility& start_object, + int start_offset, + const BrowserAccessibility& end_object, + int end_offset); + // Accessors. AXTreeIDRegistry::AXTreeID ax_tree_id() const { return ax_tree_id_; }
diff --git a/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/content/browser/accessibility/browser_accessibility_manager_unittest.cc index 805edf83..dfb0cf5 100644 --- a/content/browser/accessibility/browser_accessibility_manager_unittest.cc +++ b/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -718,6 +718,106 @@ root_accessible->GetLocalBoundsForRange(0, 13).ToString()); } +TEST(BrowserAccessibilityManagerTest, BoundsForRangeMultiElement) { + ui::AXNodeData root; + root.id = 1; + root.role = ui::AX_ROLE_ROOT_WEB_AREA; + + ui::AXNodeData static_text; + static_text.id = 2; + static_text.SetName("ABC"); + static_text.role = ui::AX_ROLE_STATIC_TEXT; + static_text.location = gfx::RectF(0, 20, 33, 9); + root.child_ids.push_back(2); + + ui::AXNodeData inline_text1; + inline_text1.id = 3; + inline_text1.SetName("ABC"); + inline_text1.role = ui::AX_ROLE_INLINE_TEXT_BOX; + inline_text1.location = gfx::RectF(0, 20, 33, 9); + inline_text1.AddIntAttribute(ui::AX_ATTR_TEXT_DIRECTION, + ui::AX_TEXT_DIRECTION_LTR); + std::vector<int32_t> character_offsets { 10, 21, 33 }; + inline_text1.AddIntListAttribute( + ui::AX_ATTR_CHARACTER_OFFSETS, character_offsets); + static_text.child_ids.push_back(3); + + ui::AXNodeData static_text2; + static_text2.id = 4; + static_text2.SetName("ABC"); + static_text2.role = ui::AX_ROLE_STATIC_TEXT; + static_text2.location = gfx::RectF(10, 40, 33, 9); + root.child_ids.push_back(4); + + ui::AXNodeData inline_text2; + inline_text2.id = 5; + inline_text2.SetName("ABC"); + inline_text2.role = ui::AX_ROLE_INLINE_TEXT_BOX; + inline_text2.location = gfx::RectF(10, 40, 33, 9); + inline_text2.AddIntAttribute(ui::AX_ATTR_TEXT_DIRECTION, + ui::AX_TEXT_DIRECTION_LTR); + inline_text2.AddIntListAttribute( + ui::AX_ATTR_CHARACTER_OFFSETS, character_offsets); + static_text2.child_ids.push_back(5); + + std::unique_ptr<BrowserAccessibilityManager> manager( + BrowserAccessibilityManager::Create( + MakeAXTreeUpdate( + root, static_text, inline_text1, static_text2, inline_text2), + nullptr, new CountedBrowserAccessibilityFactory())); + + BrowserAccessibility* root_accessible = manager->GetRoot(); + ASSERT_NE(nullptr, root_accessible); + BrowserAccessibility* static_text_accessible = + root_accessible->PlatformGetChild(0); + ASSERT_NE(nullptr, static_text_accessible); + BrowserAccessibility* static_text_accessible2 = + root_accessible->PlatformGetChild(1); + ASSERT_NE(nullptr, static_text_accessible); + + // The first line. + EXPECT_EQ(gfx::Rect(0, 20, 33, 9).ToString(), + manager->GetLocalBoundsForRange( + *static_text_accessible, 0, + *static_text_accessible, 3).ToString()); + + // Part of the first line. + EXPECT_EQ(gfx::Rect(0, 20, 21, 9).ToString(), + manager->GetLocalBoundsForRange( + *static_text_accessible, 0, + *static_text_accessible, 2).ToString()); + + // Part of the first line. + EXPECT_EQ(gfx::Rect(10, 20, 23, 9).ToString(), + manager->GetLocalBoundsForRange( + *static_text_accessible, 1, + *static_text_accessible, 3).ToString()); + + // The second line. + EXPECT_EQ(gfx::Rect(10, 40, 33, 9).ToString(), + manager->GetLocalBoundsForRange( + *static_text_accessible2, 0, + *static_text_accessible2, 3).ToString()); + + // All of both lines. + EXPECT_EQ(gfx::Rect(0, 20, 43, 29).ToString(), + manager->GetLocalBoundsForRange( + *static_text_accessible, 0, + *static_text_accessible2, 3).ToString()); + + // Part of both lines. + EXPECT_EQ(gfx::Rect(10, 20, 23, 29).ToString(), + manager->GetLocalBoundsForRange( + *static_text_accessible, 2, + *static_text_accessible2, 1).ToString()); + + // Part of both lines in reverse order. + EXPECT_EQ(gfx::Rect(10, 20, 23, 29).ToString(), + manager->GetLocalBoundsForRange( + *static_text_accessible2, 1, + *static_text_accessible, 2).ToString()); +} + TEST(BrowserAccessibilityManagerTest, BoundsForRangeBiDi) { // In this example, we assume that the string "123abc" is rendered with // "123" going left-to-right and "abc" going right-to-left. In other @@ -990,6 +1090,38 @@ EXPECT_EQ(node3_accessible, manager->PreviousInTreeOrder(node4_accessible)); EXPECT_EQ(node2_accessible, manager->PreviousInTreeOrder(node3_accessible)); EXPECT_EQ(root_accessible, manager->PreviousInTreeOrder(node2_accessible)); + + EXPECT_EQ(ui::AX_TREE_ORDER_EQUAL, + BrowserAccessibilityManager::CompareNodes( + *root_accessible, *root_accessible)); + + EXPECT_EQ(ui::AX_TREE_ORDER_BEFORE, + BrowserAccessibilityManager::CompareNodes( + *node2_accessible, *node3_accessible)); + EXPECT_EQ(ui::AX_TREE_ORDER_AFTER, + BrowserAccessibilityManager::CompareNodes( + *node3_accessible, *node2_accessible)); + + EXPECT_EQ(ui::AX_TREE_ORDER_BEFORE, + BrowserAccessibilityManager::CompareNodes( + *node2_accessible, *node4_accessible)); + EXPECT_EQ(ui::AX_TREE_ORDER_AFTER, + BrowserAccessibilityManager::CompareNodes( + *node4_accessible, *node2_accessible)); + + EXPECT_EQ(ui::AX_TREE_ORDER_BEFORE, + BrowserAccessibilityManager::CompareNodes( + *node3_accessible, *node4_accessible)); + EXPECT_EQ(ui::AX_TREE_ORDER_AFTER, + BrowserAccessibilityManager::CompareNodes( + *node4_accessible, *node3_accessible)); + + EXPECT_EQ(ui::AX_TREE_ORDER_BEFORE, + BrowserAccessibilityManager::CompareNodes( + *root_accessible, *node2_accessible)); + EXPECT_EQ(ui::AX_TREE_ORDER_AFTER, + BrowserAccessibilityManager::CompareNodes( + *node2_accessible, *root_accessible)); } TEST(BrowserAccessibilityManagerTest, TestNextPreviousTextOnlyObject) {
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 14a90b2..21c29ee 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -1352,7 +1352,7 @@ BrowserThread::IO, FROM_HERE, base::Bind(base::IgnoreResult(&GpuProcessHost::Get), GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - CAUSE_FOR_GPU_LAUNCH_BROWSER_STARTUP)); + true /* force_create */)); } #if defined(OS_MACOSX)
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index 8a60ed1..0a2423a 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -44,7 +44,6 @@ #include "content/browser/gpu/gpu_data_manager_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/common/gpu/client/context_provider_command_buffer.h" -#include "content/common/gpu_process_launch_causes.h" #include "content/common/host_shared_bitmap_manager.h" #include "content/public/common/content_switches.h" #include "gpu/GLES2/gl2extchromium.h" @@ -312,8 +311,7 @@ callback_factory_.GetWeakPtr(), compositor, create_gpu_output_surface, 0)); if (!use_mus) { - BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel( - CAUSE_FOR_GPU_LAUNCH_SHARED_WORKER_THREAD_CONTEXT, callback); + BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel(callback); } else { #if defined(MOJO_RUNNER_CLIENT) ui::GpuService::GetInstance()->EstablishGpuChannel(callback); @@ -458,8 +456,7 @@ callback_factory_.GetWeakPtr(), compositor, create_gpu_output_surface, num_attempts + 1)); if (!use_mus) { - BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel( - CAUSE_FOR_GPU_LAUNCH_SHARED_WORKER_THREAD_CONTEXT, callback); + BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel(callback); } else { #if defined(MOJO_RUNNER_CLIENT) ui::GpuService::GetInstance()->EstablishGpuChannel(callback); @@ -801,8 +798,7 @@ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host; if (!use_mus) { gpu_channel_host = - BrowserGpuChannelHostFactory::instance()->EstablishGpuChannelSync( - CAUSE_FOR_GPU_LAUNCH_BROWSER_SHARED_MAIN_THREAD_CONTEXT); + BrowserGpuChannelHostFactory::instance()->EstablishGpuChannelSync(); } else { #if defined(MOJO_RUNNER_CLIENT) gpu_channel_host = ui::GpuService::GetInstance()->EstablishGpuChannelSync();
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc index f4242bb..ca8034bb 100644 --- a/content/browser/frame_host/navigation_controller_impl_unittest.cc +++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -5331,13 +5331,8 @@ observer.details().ssl_status.connection_status); EXPECT_EQ(default_ssl_status.content_status, observer.details().ssl_status.content_status); - EXPECT_EQ(default_ssl_status.num_unknown_scts, - observer.details().ssl_status.num_unknown_scts); - EXPECT_EQ(default_ssl_status.num_invalid_scts, - observer.details().ssl_status.num_invalid_scts); - EXPECT_EQ(default_ssl_status.num_valid_scts, - observer.details().ssl_status.num_valid_scts); - + EXPECT_EQ(default_ssl_status.sct_statuses, + observer.details().ssl_status.sct_statuses); EXPECT_EQ(1, main_test_rfh()->GetProcess()->bad_msg_count()); }
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc index e71f1a9..d3e8ceba 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.cc +++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -40,8 +40,7 @@ class BrowserGpuChannelHostFactory::EstablishRequest : public base::RefCountedThreadSafe<EstablishRequest> { public: - static scoped_refptr<EstablishRequest> Create(CauseForGpuLaunch cause, - int gpu_client_id, + static scoped_refptr<EstablishRequest> Create(int gpu_client_id, uint64_t gpu_client_tracing_id, int gpu_host_id); void Wait(); @@ -53,8 +52,7 @@ private: friend class base::RefCountedThreadSafe<EstablishRequest>; - explicit EstablishRequest(CauseForGpuLaunch cause, - int gpu_client_id, + explicit EstablishRequest(int gpu_client_id, uint64_t gpu_client_tracing_id, int gpu_host_id); ~EstablishRequest() {} @@ -65,7 +63,6 @@ void FinishOnMain(); base::WaitableEvent event_; - CauseForGpuLaunch cause_for_gpu_launch_; const int gpu_client_id_; const uint64_t gpu_client_tracing_id_; int gpu_host_id_; @@ -78,12 +75,11 @@ scoped_refptr<BrowserGpuChannelHostFactory::EstablishRequest> BrowserGpuChannelHostFactory::EstablishRequest::Create( - CauseForGpuLaunch cause, int gpu_client_id, uint64_t gpu_client_tracing_id, int gpu_host_id) { - scoped_refptr<EstablishRequest> establish_request = new EstablishRequest( - cause, gpu_client_id, gpu_client_tracing_id, gpu_host_id); + scoped_refptr<EstablishRequest> establish_request = + new EstablishRequest(gpu_client_id, gpu_client_tracing_id, gpu_host_id); scoped_refptr<base::SingleThreadTaskRunner> task_runner = BrowserThread::GetTaskRunnerForThread(BrowserThread::IO); // PostTask outside the constructor to ensure at least one reference exists. @@ -95,13 +91,11 @@ } BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest( - CauseForGpuLaunch cause, int gpu_client_id, uint64_t gpu_client_tracing_id, int gpu_host_id) : event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), - cause_for_gpu_launch_(cause), gpu_client_id_(gpu_client_id), gpu_client_tracing_id_(gpu_client_tracing_id), gpu_host_id_(gpu_host_id), @@ -117,8 +111,7 @@ "BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO")); GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); if (!host) { - host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - cause_for_gpu_launch_); + host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED); if (!host) { LOG(ERROR) << "Failed to launch GPU process."; FinishOnIO(); @@ -216,8 +209,7 @@ DCHECK(!instance_); instance_ = new BrowserGpuChannelHostFactory(); if (establish_gpu_channel) { - instance_->EstablishGpuChannel(CAUSE_FOR_GPU_LAUNCH_BROWSER_STARTUP, - base::Closure()); + instance_->EstablishGpuChannel(base::Closure()); } } @@ -287,9 +279,8 @@ // task on the UI thread first, so we cannot block here.) #if !defined(OS_ANDROID) scoped_refptr<gpu::GpuChannelHost> -BrowserGpuChannelHostFactory::EstablishGpuChannelSync( - CauseForGpuLaunch cause_for_gpu_launch) { - EstablishGpuChannel(cause_for_gpu_launch, base::Closure()); +BrowserGpuChannelHostFactory::EstablishGpuChannelSync() { + EstablishGpuChannel(base::Closure()); if (pending_request_.get()) pending_request_->Wait(); @@ -299,7 +290,6 @@ #endif void BrowserGpuChannelHostFactory::EstablishGpuChannel( - CauseForGpuLaunch cause_for_gpu_launch, const base::Closure& callback) { #if defined(MOJO_RUNNER_CLIENT) DCHECK(!shell::ShellIsRemote()); @@ -314,9 +304,7 @@ if (!gpu_channel_.get() && !pending_request_.get()) { // We should only get here if the context was lost. pending_request_ = EstablishRequest::Create( - cause_for_gpu_launch, gpu_client_id_, - gpu_client_tracing_id_, - gpu_host_id_); + gpu_client_id_, gpu_client_tracing_id_, gpu_host_id_); } if (!callback.is_null()) {
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h index d0692ae..aaf7f09 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.h +++ b/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -16,7 +16,6 @@ #include "base/memory/ref_counted.h" #include "build/build_config.h" #include "content/common/content_export.h" -#include "content/common/gpu_process_launch_causes.h" #include "gpu/ipc/client/gpu_channel_host.h" #include "ipc/message_filter.h" @@ -38,11 +37,9 @@ int GpuProcessHostId() { return gpu_host_id_; } #if !defined(OS_ANDROID) - scoped_refptr<gpu::GpuChannelHost> EstablishGpuChannelSync( - CauseForGpuLaunch cause_for_gpu_launch); + scoped_refptr<gpu::GpuChannelHost> EstablishGpuChannelSync(); #endif - void EstablishGpuChannel(CauseForGpuLaunch cause_for_gpu_launch, - const base::Closure& callback); + void EstablishGpuChannel(const base::Closure& callback); gpu::GpuChannelHost* GetGpuChannel(); int GetGpuChannelId() { return gpu_client_id_; }
diff --git a/content/browser/gpu/browser_gpu_memory_buffer_manager.cc b/content/browser/gpu/browser_gpu_memory_buffer_manager.cc index 09d20976..718c009 100644 --- a/content/browser/gpu/browser_gpu_memory_buffer_manager.cc +++ b/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
@@ -531,8 +531,7 @@ GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); if (!host) { - host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE); + host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED); if (!host) { LOG(ERROR) << "Failed to launch GPU process."; callback.Run(gfx::GpuMemoryBufferHandle());
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc index 0b58845..4d7367c 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private.cc +++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -390,8 +390,7 @@ #else GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, #endif - CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED, - new GpuMsg_CollectGraphicsInfo()); + true /* force_create */, new GpuMsg_CollectGraphicsInfo()); } bool GpuDataManagerImplPrivate::IsEssentialGpuInfoAvailable() const { @@ -412,7 +411,7 @@ void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate() const { GpuProcessHost::SendOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, + false /* force_create */, new GpuMsg_GetVideoMemoryUsageStats()); } @@ -458,7 +457,7 @@ void GpuDataManagerImplPrivate::DisableGpuWatchdog() { GpuProcessHost::SendOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, + false /* force_create */, new GpuMsg_DisableWatchdog); } @@ -937,8 +936,7 @@ ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched(); // Pass the notification to the GPU process to notify observers there. GpuProcessHost::SendOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, - new GpuMsg_GpuSwitched); + false /* force_create */, new GpuMsg_GpuSwitched); } bool GpuDataManagerImplPrivate::UpdateActiveGpu(uint32_t vendor_id,
diff --git a/content/browser/gpu/gpu_ipc_browsertests.cc b/content/browser/gpu/gpu_ipc_browsertests.cc index 016e491..3982823 100644 --- a/content/browser/gpu/gpu_ipc_browsertests.cc +++ b/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -9,7 +9,6 @@ #include "content/browser/gpu/browser_gpu_channel_host_factory.h" #include "content/browser/gpu/gpu_process_host_ui_shim.h" #include "content/common/gpu/client/context_provider_command_buffer.h" -#include "content/common/gpu_process_launch_causes.h" #include "content/public/browser/gpu_data_manager.h" #include "content/public/common/content_switches.h" #include "content/public/test/content_browser_test.h" @@ -21,9 +20,6 @@ namespace { -constexpr content::CauseForGpuLaunch kInitCause = - content::CAUSE_FOR_GPU_LAUNCH_BROWSER_STARTUP; - scoped_refptr<content::ContextProviderCommandBuffer> CreateContext( scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) { // This is for an offscreen context, so the default framebuffer doesn't need @@ -59,7 +55,7 @@ content::BrowserGpuChannelHostFactory::instance(); CHECK(factory); base::RunLoop run_loop; - factory->EstablishGpuChannel(kInitCause, run_loop.QuitClosure()); + factory->EstablishGpuChannel(run_loop.QuitClosure()); run_loop.Run(); scoped_refptr<gpu::GpuChannelHost> gpu_channel_host( factory->GetGpuChannel()); @@ -134,7 +130,7 @@ void EstablishAndWait() { base::RunLoop run_loop; - GetFactory()->EstablishGpuChannel(kInitCause, run_loop.QuitClosure()); + GetFactory()->EstablishGpuChannel(run_loop.QuitClosure()); run_loop.Run(); } @@ -170,7 +166,7 @@ MAYBE_EstablishAndTerminate) { DCHECK(!IsChannelEstablished()); base::RunLoop run_loop; - GetFactory()->EstablishGpuChannel(kInitCause, run_loop.QuitClosure()); + GetFactory()->EstablishGpuChannel(run_loop.QuitClosure()); GetFactory()->Terminate(); // The callback should still trigger. @@ -189,12 +185,11 @@ MAYBE_AlreadyEstablished) { DCHECK(!IsChannelEstablished()); scoped_refptr<gpu::GpuChannelHost> gpu_channel = - GetFactory()->EstablishGpuChannelSync(kInitCause); + GetFactory()->EstablishGpuChannelSync(); // Expect established callback immediately. bool event = false; GetFactory()->EstablishGpuChannel( - kInitCause, base::Bind(&BrowserGpuChannelHostFactoryTest::Signal, &event)); EXPECT_TRUE(event); EXPECT_EQ(gpu_channel.get(), GetGpuChannel());
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 62681024..d027355 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -176,11 +176,10 @@ // only be accessed from the IO thread. GpuProcessHost* g_gpu_process_hosts[GpuProcessHost::GPU_PROCESS_KIND_COUNT]; - void SendGpuProcessMessage(GpuProcessHost::GpuProcessKind kind, - CauseForGpuLaunch cause, + bool force_create, IPC::Message* message) { - GpuProcessHost* host = GpuProcessHost::Get(kind, cause); + GpuProcessHost* host = GpuProcessHost::Get(kind, force_create); if (host) { host->Send(message); } else { @@ -317,8 +316,7 @@ } // static -GpuProcessHost* GpuProcessHost::Get(GpuProcessKind kind, - CauseForGpuLaunch cause) { +GpuProcessHost* GpuProcessHost::Get(GpuProcessKind kind, bool force_create) { #if defined(MOJO_SHELL_CLIENT) DCHECK(!shell::ShellIsRemote()); #endif @@ -333,17 +331,13 @@ if (g_gpu_process_hosts[kind] && ValidateHost(g_gpu_process_hosts[kind])) return g_gpu_process_hosts[kind]; - if (cause == CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH) - return NULL; + if (!force_create) + return nullptr; static int last_host_id = 0; int host_id; host_id = ++last_host_id; - UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause", - cause, - CAUSE_FOR_GPU_LAUNCH_MAX_ENUM); - GpuProcessHost* host = new GpuProcessHost(host_id, kind); if (host->Init()) return host; @@ -381,12 +375,11 @@ // static void GpuProcessHost::SendOnIO(GpuProcessKind kind, - CauseForGpuLaunch cause, + bool force_create, IPC::Message* message) { if (!BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind( - &SendGpuProcessMessage, kind, cause, message))) { + base::Bind(&SendGpuProcessMessage, kind, force_create, message))) { delete message; } }
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h index 1d83279..bb3510b 100644 --- a/content/browser/gpu/gpu_process_host.h +++ b/content/browser/gpu/gpu_process_host.h
@@ -21,7 +21,6 @@ #include "base/time/time.h" #include "build/build_config.h" #include "content/common/content_export.h" -#include "content/common/gpu_process_launch_causes.h" #include "content/public/browser/browser_child_process_host_delegate.h" #include "content/public/browser/gpu_data_manager.h" #include "gpu/command_buffer/common/constants.h" @@ -83,23 +82,26 @@ static bool gpu_enabled() { return gpu_enabled_; } static int gpu_crash_count() { return gpu_crash_count_; } - // Creates a new GpuProcessHost or gets an existing one, resulting in the - // launching of a GPU process if required. Returns null on failure. It - // is not safe to store the pointer once control has returned to the message - // loop as it can be destroyed. Instead store the associated GPU host ID. - // This could return NULL if GPU access is not allowed (blacklisted). + // Creates a new GpuProcessHost (if |force_create| is turned on) or gets an + // existing one, resulting in the launching of a GPU process if required. + // Returns null on failure. It is not safe to store the pointer once control + // has returned to the message loop as it can be destroyed. Instead store the + // associated GPU host ID. This could return NULL if GPU access is not + // allowed (blacklisted). CONTENT_EXPORT static GpuProcessHost* Get(GpuProcessKind kind, - CauseForGpuLaunch cause); + bool force_create = true); // Retrieves a list of process handles for all gpu processes. static void GetProcessHandles( const GpuDataManager::GetGpuProcessHandlesCallback& callback); // Helper function to send the given message to the GPU process on the IO - // thread. Calls Get and if a host is returned, sends it. Can be called from - // any thread. Deletes the message if it cannot be sent. + // thread. Calls Get and if a host is returned, sends it. |force_create| can + // be set to force the creation of GpuProcessHost if one doesn't already + // exist. This function can be called from any thread. Deletes the message if + // it cannot be sent. CONTENT_EXPORT static void SendOnIO(GpuProcessKind kind, - CauseForGpuLaunch cause, + bool force_create, IPC::Message* message); CONTENT_EXPORT static void RegisterGpuMainThreadFactory(
diff --git a/content/browser/media/android/browser_surface_view_manager.cc b/content/browser/media/android/browser_surface_view_manager.cc index b720e69..6263e28 100644 --- a/content/browser/media/android/browser_surface_view_manager.cc +++ b/content/browser/media/android/browser_surface_view_manager.cc
@@ -20,9 +20,8 @@ namespace { void SendDestroyingVideoSurfaceOnIO(int surface_id, const base::Closure& done_cb) { - GpuProcessHost* host = - GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH); + GpuProcessHost* host = GpuProcessHost::Get( + GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */); if (host) host->SendDestroyingVideoSurface(surface_id, done_cb); else
diff --git a/content/browser/mojo/mojo_shell_context.cc b/content/browser/mojo/mojo_shell_context.cc index 1921f9ebf..2836bf4 100644 --- a/content/browser/mojo/mojo_shell_context.cc +++ b/content/browser/mojo/mojo_shell_context.cc
@@ -16,7 +16,6 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "content/browser/gpu/gpu_process_host.h" -#include "content/common/gpu_process_launch_causes.h" #include "content/common/mojo/constants.h" #include "content/common/mojo/mojo_shell_connection_impl.h" #include "content/common/process_control.mojom.h" @@ -95,8 +94,7 @@ void RequestGpuProcessControl( mojo::InterfaceRequest<mojom::ProcessControl> request) { BrowserChildProcessHostDelegate* process_host = - GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - CAUSE_FOR_GPU_LAUNCH_MOJO_SETUP); + GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED); if (!process_host) { DLOG(ERROR) << "GPU process host not available."; return;
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index c06a342..53bc140 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -56,7 +56,6 @@ #include "content/browser/gpu/gpu_surface_tracker.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/common/gpu/client/context_provider_command_buffer.h" -#include "content/common/gpu_process_launch_causes.h" #include "content/common/host_shared_bitmap_manager.h" #include "content/public/browser/android/compositor.h" #include "content/public/browser/android/compositor_client.h" @@ -562,7 +561,6 @@ BrowserGpuChannelHostFactory::instance(); if (!factory->GetGpuChannel()) { factory->EstablishGpuChannel( - CAUSE_FOR_GPU_LAUNCH_DISPLAY_COMPOSITOR_CONTEXT, base::Bind(&CompositorImpl::OnGpuChannelEstablished, weak_factory_.GetWeakPtr())); establish_gpu_channel_timeout_.Start(
diff --git a/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc b/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc index 4937c3a..fece159d 100644 --- a/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc +++ b/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
@@ -202,7 +202,6 @@ DCHECK(BrowserGpuChannelHostFactory::instance()); BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel( - CAUSE_FOR_GPU_LAUNCH_JPEGDECODEACCELERATOR_INITIALIZE, base::Bind(&VideoCaptureGpuJpegDecoder::GpuChannelEstablishedOnUIThread, task_runner, weak_this)); }
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index f4b2ef1..f6b4919 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc
@@ -622,7 +622,6 @@ } void RenderMessageFilter::OnEstablishGpuChannel( - CauseForGpuLaunch cause_for_gpu_launch, IPC::Message* reply_ptr) { DCHECK_CURRENTLY_ON(BrowserThread::IO); std::unique_ptr<IPC::Message> reply(reply_ptr); @@ -639,8 +638,7 @@ GpuProcessHost* host = GpuProcessHost::FromID(gpu_process_id_); if (!host) { - host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - cause_for_gpu_launch); + host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED); if (!host) { reply->set_reply_error(); Send(reply.release());
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index 591f7825..bd3d44d 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h
@@ -21,7 +21,6 @@ #include "build/build_config.h" #include "cc/resources/shared_bitmap_manager.h" #include "content/common/cache_storage/cache_storage_types.h" -#include "content/common/gpu_process_launch_causes.h" #include "content/common/host_discardable_shared_memory_manager.h" #include "content/common/host_shared_bitmap_manager.h" #include "content/public/browser/browser_message_filter.h" @@ -145,7 +144,7 @@ void OnGenerateRoutingID(int* route_id); // Message handlers called on the browser IO thread: - void OnEstablishGpuChannel(CauseForGpuLaunch, IPC::Message* reply); + void OnEstablishGpuChannel(IPC::Message* reply); void OnHasGpuProcess(IPC::Message* reply); // Helper callbacks for the message handlers. void EstablishChannelCallback(std::unique_ptr<IPC::Message> reply,
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 5d56ec1..cadbf88b 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -57,7 +57,6 @@ #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/common/gpu_host_messages.h" -#include "content/common/gpu_process_launch_causes.h" #include "content/common/input/did_overscroll_params.h" #include "content/common/input_messages.h" #include "content/common/view_messages.h"
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc index cd1abb6..d787d5c 100644 --- a/content/browser/service_worker/service_worker_context_core.cc +++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -509,7 +509,9 @@ void ServiceWorkerContextCore::AddLiveRegistration( ServiceWorkerRegistration* registration) { - DCHECK(!GetLiveRegistration(registration->id())); + // TODO(nhiroki): Change CHECK to DCHECK after https://crbug.com/619294 is + // fixed. + CHECK(!GetLiveRegistration(registration->id())); live_registrations_[registration->id()] = registration; if (observer_list_.get()) { observer_list_->Notify(FROM_HERE,
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 837230d..6c23bd38 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -252,6 +252,10 @@ WebRuntimeFeatures::enableRenderingPipelineThrottling( base::FeatureList::IsEnabled(features::kRenderingPipelineThrottling)); + if (base::FeatureList::IsEnabled( + features::kSendBeaconThrowForBlobWithNonSimpleType)) + WebRuntimeFeatures::enableSendBeaconThrowForBlobWithNonSimpleType(true); + #if defined(OS_ANDROID) WebRuntimeFeatures::enablePaymentRequest( base::FeatureList::IsEnabled(features::kWebPayments));
diff --git a/content/common/child_process_messages.h b/content/common/child_process_messages.h index 34d3e644..a0fbc17e 100644 --- a/content/common/child_process_messages.h +++ b/content/common/child_process_messages.h
@@ -17,7 +17,6 @@ #include "cc/resources/shared_bitmap_manager.h" #include "content/common/content_export.h" #include "content/common/content_param_traits_macros.h" -#include "content/common/gpu_process_launch_causes.h" #include "content/common/host_discardable_shared_memory_manager.h" #include "gpu/command_buffer/common/sync_token.h" #include "gpu/ipc/common/gpu_param_traits_macros.h" @@ -28,9 +27,6 @@ #include "ui/gfx/ipc/gfx_param_traits.h" #include "ui/gfx/ipc/skia/gfx_skia_param_traits.h" -IPC_ENUM_TRAITS_MAX_VALUE(content::CauseForGpuLaunch, - content::CAUSE_FOR_GPU_LAUNCH_MAX_ENUM - 1) - IPC_ENUM_TRAITS_MAX_VALUE(tracked_objects::ThreadData::Status, tracked_objects::ThreadData::STATUS_LAST) @@ -127,8 +123,7 @@ // A renderer sends this when it wants to create a connection to the GPU // process. The browser will create the GPU process if necessary, and will // return a handle to the channel via a GpuChannelEstablished message. -IPC_SYNC_MESSAGE_CONTROL1_3(ChildProcessHostMsg_EstablishGpuChannel, - content::CauseForGpuLaunch, +IPC_SYNC_MESSAGE_CONTROL0_3(ChildProcessHostMsg_EstablishGpuChannel, int /* client id */, IPC::ChannelHandle /* handle to channel */, gpu::GPUInfo /* stats about GPU process*/)
diff --git a/content/common/gpu_process_launch_causes.h b/content/common/gpu_process_launch_causes.h deleted file mode 100644 index dba1ced..0000000 --- a/content/common/gpu_process_launch_causes.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_COMMON_GPU_PROCESS_LAUNCH_CAUSES_H_ -#define CONTENT_COMMON_GPU_PROCESS_LAUNCH_CAUSES_H_ - -namespace content { - -// If you change this enum you also need to update -// tools/metrics/histograms/histograms.xml -enum CauseForGpuLaunch { - // Start enum from 2 to keep the same values for the histogram. - CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED = 2, - CAUSE_FOR_GPU_LAUNCH_RENDERWIDGETFULLSCREENPEPPER_CREATECONTEXT, - // Deprecated - // CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE, - CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH = 4, - CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE, - CAUSE_FOR_GPU_LAUNCH_PEPPERPLATFORMCONTEXT3DIMPL_INITIALIZE, - CAUSE_FOR_GPU_LAUNCH_BROWSER_STARTUP, - CAUSE_FOR_GPU_LAUNCH_CANVAS_2D, - CAUSE_FOR_GPU_LAUNCH_PEPPERVIDEOENCODERACCELERATOR_INITIALIZE, - CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE, - CAUSE_FOR_GPU_LAUNCH_JPEGDECODEACCELERATOR_INITIALIZE, - CAUSE_FOR_GPU_LAUNCH_MOJO_SETUP, - CAUSE_FOR_GPU_LAUNCH_GET_GPU_SERVICE_REGISTRY, - CAUSE_FOR_GPU_LAUNCH_BROWSER_SHARED_MAIN_THREAD_CONTEXT, - CAUSE_FOR_GPU_LAUNCH_RENDERER_SHARED_MAIN_THREAD_CONTEXT, - CAUSE_FOR_GPU_LAUNCH_WEBGL_CONTEXT, - CAUSE_FOR_GPU_LAUNCH_SHARED_WORKER_THREAD_CONTEXT, - CAUSE_FOR_GPU_LAUNCH_RENDERER_VERIFY_GPU_COMPOSITING, - CAUSE_FOR_GPU_LAUNCH_DISPLAY_COMPOSITOR_CONTEXT, - CAUSE_FOR_GPU_LAUNCH_MEDIA_CONTEXT, - - // All new values should be inserted above this point so that - // existing values continue to match up with those in histograms.xml. - CAUSE_FOR_GPU_LAUNCH_MAX_ENUM -}; - -} // namespace content - -#endif // CONTENT_COMMON_GPU_PROCESS_LAUNCH_CAUSES_H_
diff --git a/content/common/ssl_status_serialization.cc b/content/common/ssl_status_serialization.cc index 96349da..a105e7e 100644 --- a/content/common/ssl_status_serialization.cc +++ b/content/common/ssl_status_serialization.cc
@@ -26,6 +26,23 @@ return false; } +// Checks that an integer |sct_status| is a valid net::ct::SCTVerifyStatus enum +// value. Returns true if valid, false otherwise. +bool CheckSCTStatus(uint32_t sct_status) { + switch (sct_status) { + case net::ct::SCT_STATUS_LOG_UNKNOWN: + case net::ct::SCT_STATUS_INVALID: + case net::ct::SCT_STATUS_OK: + case net::ct::SCT_STATUS_MAX: + return true; + case net::ct::SCT_STATUS_NONE: + // SCT_STATUS_NONE should never happen, so it isn't valid to + // receive a status of NONE in a serialized SSLStatus. + return false; + } + return false; +} + } // namespace namespace content { @@ -38,9 +55,10 @@ pickle.WriteInt(ssl_status.security_bits); pickle.WriteInt(ssl_status.key_exchange_info); pickle.WriteInt(ssl_status.connection_status); - pickle.WriteUInt32(ssl_status.num_unknown_scts); - pickle.WriteUInt32(ssl_status.num_invalid_scts); - pickle.WriteUInt32(ssl_status.num_valid_scts); + pickle.WriteUInt32(ssl_status.sct_statuses.size()); + for (const auto& sct_status : ssl_status.sct_statuses) { + pickle.WriteUInt32(sct_status); + } pickle.WriteBool(ssl_status.pkp_bypassed); return std::string(static_cast<const char*>(pickle.data()), pickle.size()); } @@ -60,11 +78,27 @@ !iter.ReadUInt32(&ssl_status->cert_status) || !iter.ReadInt(&ssl_status->security_bits) || !iter.ReadInt(&ssl_status->key_exchange_info) || - !iter.ReadInt(&ssl_status->connection_status) || - !iter.ReadUInt32(&ssl_status->num_unknown_scts) || - !iter.ReadUInt32(&ssl_status->num_invalid_scts) || - !iter.ReadUInt32(&ssl_status->num_valid_scts) || - !iter.ReadBool(&ssl_status->pkp_bypassed)) { + !iter.ReadInt(&ssl_status->connection_status)) { + *ssl_status = SSLStatus(); + return false; + } + + uint32_t num_sct_statuses; + if (!iter.ReadUInt32(&num_sct_statuses)) { + return false; + } + + for (uint32_t i = 0; i < num_sct_statuses; i++) { + uint32_t sct_status; + if (!iter.ReadUInt32(&sct_status) || !CheckSCTStatus(sct_status)) { + *ssl_status = SSLStatus(); + return false; + } + ssl_status->sct_statuses.push_back( + static_cast<net::ct::SCTVerifyStatus>(sct_status)); + } + + if (!iter.ReadBool(&ssl_status->pkp_bypassed)) { *ssl_status = SSLStatus(); return false; }
diff --git a/content/common/ssl_status_serialization_unittest.cc b/content/common/ssl_status_serialization_unittest.cc index d230c32..398a7f4 100644 --- a/content/common/ssl_status_serialization_unittest.cc +++ b/content/common/ssl_status_serialization_unittest.cc
@@ -18,9 +18,7 @@ status->security_bits = 80; status->key_exchange_info = 23; status->connection_status = net::SSL_CONNECTION_VERSION_TLS1_2; - status->num_unknown_scts = 0; - status->num_invalid_scts = 0; - status->num_valid_scts = 1; + status->sct_statuses.push_back(net::ct::SCT_STATUS_OK); } bool SSLStatusAreEqual(const SSLStatus& a, const SSLStatus &b) { @@ -37,9 +35,7 @@ << "\nKey exchange info: " << status.key_exchange_info << "\nConnection status: " << status.connection_status << "\nContent Status: " << status.content_status - << "\nNumber of unknown SCTs: " << status.num_unknown_scts - << "\nNumber of invalid SCTs: " << status.num_invalid_scts - << "\nNumber of valid SCTs: " << status.num_valid_scts; + << "\nNumber of SCTs: " << status.sct_statuses.size(); } // Test that a valid serialized SSLStatus returns true on @@ -109,4 +105,46 @@ EXPECT_PRED2(SSLStatusAreEqual, SSLStatus(), invalid_deserialized); } +// Serialize a status with an empty |sct_statuses| field and test that +// deserializing works. +TEST(SSLStatusSerializationTest, DeserializeEmptySCTStatuses) { + SSLStatus status; + SetTestStatus(&status); + status.sct_statuses.clear(); + std::string serialized = SerializeSecurityInfo(status); + + SSLStatus deserialized; + ASSERT_TRUE(DeserializeSecurityInfo(serialized, &deserialized)); + EXPECT_PRED2(SSLStatusAreEqual, status, deserialized); +} + +// Serialize a status with multiple different |sct_statuses| and test that +// deserializing works. +TEST(SSLStatusSerializationTest, DeserializeMultipleSCTStatuses) { + SSLStatus status; + SetTestStatus(&status); + status.sct_statuses.push_back(net::ct::SCT_STATUS_LOG_UNKNOWN); + status.sct_statuses.push_back(net::ct::SCT_STATUS_LOG_UNKNOWN); + status.sct_statuses.push_back(net::ct::SCT_STATUS_OK); + status.sct_statuses.push_back(net::ct::SCT_STATUS_INVALID); + std::string serialized = SerializeSecurityInfo(status); + + SSLStatus deserialized; + ASSERT_TRUE(DeserializeSecurityInfo(serialized, &deserialized)); + EXPECT_PRED2(SSLStatusAreEqual, status, deserialized); +} + +// Serialize a status with a bad SCTVerifyStatus value and test that +// deserializing it fails. +TEST(SSLStatusSerializationTest, DeserializeBogusSCTVerifyStatus) { + SSLStatus status; + SetTestStatus(&status); + status.sct_statuses.push_back(static_cast<net::ct::SCTVerifyStatus>(100)); + std::string serialized = SerializeSecurityInfo(status); + + SSLStatus deserialized; + ASSERT_FALSE(DeserializeSecurityInfo(serialized, &deserialized)); + EXPECT_PRED2(SSLStatusAreEqual, SSLStatus(), deserialized); +} + } // namespace
diff --git a/content/content_common.gypi b/content/content_common.gypi index c35a8316..0874e15 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi
@@ -342,7 +342,6 @@ 'common/gpu/client/context_provider_command_buffer.cc', 'common/gpu/client/context_provider_command_buffer.h', 'common/gpu_host_messages.h', - 'common/gpu_process_launch_causes.h', 'common/host_discardable_shared_memory_manager.cc', 'common/host_discardable_shared_memory_manager.h', 'common/host_shared_bitmap_manager.cc',
diff --git a/content/public/browser/gpu_service_registry.cc b/content/public/browser/gpu_service_registry.cc index 3747d90..53b0761 100644 --- a/content/public/browser/gpu_service_registry.cc +++ b/content/public/browser/gpu_service_registry.cc
@@ -10,8 +10,7 @@ shell::InterfaceProvider* GetGpuRemoteInterfaces() { GpuProcessHost* host = - GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - CAUSE_FOR_GPU_LAUNCH_GET_GPU_SERVICE_REGISTRY); + GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED); return host->GetRemoteInterfaces(); }
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index d5ff3f8..300b692 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -141,6 +141,11 @@ // https://wicg.github.io/webusb const base::Feature kWebUsb{"WebUSB", base::FEATURE_ENABLED_BY_DEFAULT}; +// Make sendBeacon throw for a Blob with a non simple type. +const base::Feature kSendBeaconThrowForBlobWithNonSimpleType{ + "SendBeaconThrowForBlobWithNonSimpleType", + base::FEATURE_DISABLED_BY_DEFAULT}; + #if defined(OS_ANDROID) // Allow videos to autoplay without a user gesture if muted. const base::Feature kAutoplayMutedVideos{"AutoplayMutedVideos",
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 3bc3c3b..7a1d388 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -43,6 +43,8 @@ CONTENT_EXPORT extern const base::Feature kWebGLImageChromium; CONTENT_EXPORT extern const base::Feature kWebRtcEcdsaDefault; CONTENT_EXPORT extern const base::Feature kWebUsb; +CONTENT_EXPORT +extern const base::Feature kSendBeaconThrowForBlobWithNonSimpleType; #if defined(OS_ANDROID) CONTENT_EXPORT extern const base::Feature kAutoplayMutedVideos;
diff --git a/content/public/common/ssl_status.cc b/content/public/common/ssl_status.cc index 709f4188..aedcc519 100644 --- a/content/public/common/ssl_status.cc +++ b/content/public/common/ssl_status.cc
@@ -17,9 +17,6 @@ key_exchange_info(0), connection_status(0), content_status(NORMAL_CONTENT), - num_unknown_scts(0), - num_invalid_scts(0), - num_valid_scts(0), pkp_bypassed(false) {} SSLStatus::SSLStatus(SecurityStyle security_style, @@ -32,29 +29,9 @@ key_exchange_info(ssl_info.key_exchange_info), connection_status(ssl_info.connection_status), content_status(NORMAL_CONTENT), - num_unknown_scts(0), - num_invalid_scts(0), - num_valid_scts(0), pkp_bypassed(ssl_info.pkp_bypassed) { - // Count unknown, invalid and valid SCTs. for (const auto& sct_and_status : ssl_info.signed_certificate_timestamps) { - switch (sct_and_status.status) { - case net::ct::SCT_STATUS_LOG_UNKNOWN: - num_unknown_scts++; - break; - case net::ct::SCT_STATUS_INVALID: - num_invalid_scts++; - break; - case net::ct::SCT_STATUS_OK: - num_valid_scts++; - break; - case net::ct::SCT_STATUS_NONE: - case net::ct::SCT_STATUS_MAX: - // These enum values do not represent SCTs that are taken into account - // for CT compliance calculations, so we ignore them. - NOTREACHED(); - break; - } + sct_statuses.push_back(sct_and_status.status); } }
diff --git a/content/public/common/ssl_status.h b/content/public/common/ssl_status.h index 8233da7..e8e6ab7 100644 --- a/content/public/common/ssl_status.h +++ b/content/public/common/ssl_status.h
@@ -5,9 +5,12 @@ #ifndef CONTENT_PUBLIC_COMMON_SSL_STATUS_H_ #define CONTENT_PUBLIC_COMMON_SSL_STATUS_H_ +#include <vector> + #include "content/common/content_export.h" #include "content/public/common/security_style.h" #include "net/cert/cert_status_flags.h" +#include "net/cert/sct_status_flags.h" namespace net { class SSLInfo; @@ -46,9 +49,7 @@ key_exchange_info == status.key_exchange_info && connection_status == status.connection_status && content_status == status.content_status && - num_unknown_scts == status.num_unknown_scts && - num_invalid_scts == status.num_invalid_scts && - num_valid_scts == status.num_valid_scts && + sct_statuses == status.sct_statuses && pkp_bypassed == status.pkp_bypassed; } @@ -61,10 +62,10 @@ int connection_status; // A combination of the ContentStatusFlags above. int content_status; - // Signed Certificate Timestamps (SCTs) of Certificate Transparency (CT). - uint32_t num_unknown_scts; - uint32_t num_invalid_scts; - uint32_t num_valid_scts; + // The validation statuses of the Signed Certificate Timestamps (SCTs) + // of Certificate Transparency (CT) that were served with the + // main resource. + std::vector<net::ct::SCTVerifyStatus> sct_statuses; // True if PKP was bypassed due to a local trust anchor. bool pkp_bypassed; };
diff --git a/content/renderer/pepper/pepper_video_encoder_host.cc b/content/renderer/pepper/pepper_video_encoder_host.cc index 0d0997b..c25d57b 100644 --- a/content/renderer/pepper/pepper_video_encoder_host.cc +++ b/content/renderer/pepper/pepper_video_encoder_host.cc
@@ -523,8 +523,7 @@ // There is no guarantee that we have a 3D context to work with. So // we create a dummy command buffer to communicate with the gpu process. scoped_refptr<gpu::GpuChannelHost> channel = - RenderThreadImpl::current()->EstablishGpuChannelSync( - CAUSE_FOR_GPU_LAUNCH_PEPPERVIDEOENCODERACCELERATOR_INITIALIZE); + RenderThreadImpl::current()->EstablishGpuChannelSync(); if (!channel) return false;
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc index a7bed46..927f371 100644 --- a/content/renderer/pepper/ppb_graphics_3d_impl.cc +++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -241,8 +241,7 @@ return false; scoped_refptr<gpu::GpuChannelHost> channel = - render_thread->EstablishGpuChannelSync( - CAUSE_FOR_GPU_LAUNCH_PEPPERPLATFORMCONTEXT3DIMPL_INITIALIZE); + render_thread->EstablishGpuChannelSync(); if (!channel) return false;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 1b898bb2..3cedbac5 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -77,7 +77,6 @@ #include "content/common/frame_messages.h" #include "content/common/frame_owner_properties.h" #include "content/common/gpu/client/context_provider_command_buffer.h" -#include "content/common/gpu_process_launch_causes.h" #include "content/common/render_process_messages.h" #include "content/common/resource_messages.h" #include "content/common/service_worker/embedded_worker_setup.mojom.h" @@ -1447,7 +1446,7 @@ const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); scoped_refptr<gpu::GpuChannelHost> gpu_channel_host = - EstablishGpuChannelSync(CAUSE_FOR_GPU_LAUNCH_MEDIA_CONTEXT); + EstablishGpuChannelSync(); if (!gpu_channel_host) return nullptr; // This context is only used to create textures and mailbox them, so @@ -1491,8 +1490,8 @@ GL_NO_ERROR) return shared_main_thread_contexts_; - scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync( - CAUSE_FOR_GPU_LAUNCH_RENDERER_SHARED_MAIN_THREAD_CONTEXT)); + scoped_refptr<gpu::GpuChannelHost> gpu_channel_host( + EstablishGpuChannelSync()); if (!gpu_channel_host) { shared_main_thread_contexts_ = nullptr; return nullptr; @@ -1767,8 +1766,7 @@ RenderViewImpl::Create(compositor_deps, params, false); } -scoped_refptr<gpu::GpuChannelHost> RenderThreadImpl::EstablishGpuChannelSync( - CauseForGpuLaunch cause_for_gpu_launch) { +scoped_refptr<gpu::GpuChannelHost> RenderThreadImpl::EstablishGpuChannelSync() { TRACE_EVENT0("gpu", "RenderThreadImpl::EstablishGpuChannelSync"); if (gpu_channel_) { @@ -1788,7 +1786,7 @@ gpu::GPUInfo gpu_info; // Ask the browser for the channel name. if (!Send(new ChildProcessHostMsg_EstablishGpuChannel( - cause_for_gpu_launch, &client_id, &channel_handle, &gpu_info)) || + &client_id, &channel_handle, &gpu_info)) || !channel_handle.mojo_handle.is_valid()) { // Otherwise cancel the connection. return nullptr; @@ -1850,8 +1848,7 @@ // before creating any context providers. scoped_refptr<gpu::GpuChannelHost> gpu_channel_host; if (!use_software) { - gpu_channel_host = EstablishGpuChannelSync( - CAUSE_FOR_GPU_LAUNCH_RENDERER_VERIFY_GPU_COMPOSITING); + gpu_channel_host = EstablishGpuChannelSync(); if (!gpu_channel_host) { // Cause the compositor to wait and try again. return nullptr; @@ -2115,8 +2112,8 @@ return shared_worker_context_provider_; } - scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync( - CAUSE_FOR_GPU_LAUNCH_SHARED_WORKER_THREAD_CONTEXT)); + scoped_refptr<gpu::GpuChannelHost> gpu_channel_host( + EstablishGpuChannelSync()); if (!gpu_channel_host) { shared_worker_context_provider_ = nullptr; return shared_worker_context_provider_;
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index bb0553c..b8c2371e 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -27,7 +27,6 @@ #include "content/common/content_export.h" #include "content/common/frame.mojom.h" #include "content/common/frame_replication_state.h" -#include "content/common/gpu_process_launch_causes.h" #include "content/common/render_frame_message_filter.mojom.h" #include "content/common/storage_partition_service.mojom.h" #include "content/public/renderer/render_thread.h" @@ -232,7 +231,7 @@ // established or if it has been lost (for example if the GPU plugin crashed). // If there is a pending asynchronous request, it will be completed by the // time this routine returns. - scoped_refptr<gpu::GpuChannelHost> EstablishGpuChannelSync(CauseForGpuLaunch); + scoped_refptr<gpu::GpuChannelHost> EstablishGpuChannelSync(); std::unique_ptr<cc::OutputSurface> CreateCompositorOutputSurface( bool use_software,
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 515bfa27..96188e3e 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -43,7 +43,6 @@ #include "content/common/file_utilities_messages.h" #include "content/common/frame_messages.h" #include "content/common/gpu/client/context_provider_command_buffer.h" -#include "content/common/gpu_process_launch_causes.h" #include "content/common/render_process_messages.h" #include "content/public/common/content_switches.h" #include "content/public/common/webplugininfo.h" @@ -678,8 +677,7 @@ bool RendererBlinkPlatformImpl::canAccelerate2dCanvas() { RenderThreadImpl* thread = RenderThreadImpl::current(); - scoped_refptr<gpu::GpuChannelHost> host = - thread->EstablishGpuChannelSync(CAUSE_FOR_GPU_LAUNCH_CANVAS_2D); + scoped_refptr<gpu::GpuChannelHost> host = thread->EstablishGpuChannelSync(); if (!host) return false; @@ -1057,8 +1055,7 @@ } scoped_refptr<gpu::GpuChannelHost> gpu_channel_host( - RenderThreadImpl::current()->EstablishGpuChannelSync( - CAUSE_FOR_GPU_LAUNCH_WEBGL_CONTEXT)); + RenderThreadImpl::current()->EstablishGpuChannelSync()); if (!gpu_channel_host) { std::string error_message( "OffscreenContext Creation failed, GpuChannelHost creation failed");
diff --git a/ios/chrome/browser/autofill/personal_data_manager_factory.cc b/ios/chrome/browser/autofill/personal_data_manager_factory.cc index e217913..4e0a8399 100644 --- a/ios/chrome/browser/autofill/personal_data_manager_factory.cc +++ b/ios/chrome/browser/autofill/personal_data_manager_factory.cc
@@ -19,10 +19,12 @@ #include "ios/chrome/browser/signin/signin_manager_factory.h" #include "ios/chrome/browser/web_data_service_factory.h" +namespace autofill { + // static -autofill::PersonalDataManager* PersonalDataManagerFactory::GetForBrowserState( +PersonalDataManager* PersonalDataManagerFactory::GetForBrowserState( ios::ChromeBrowserState* browser_state) { - return static_cast<autofill::PersonalDataManager*>( + return static_cast<PersonalDataManager*>( GetInstance()->GetServiceForBrowserState(browser_state, true)); } @@ -47,9 +49,8 @@ web::BrowserState* context) const { ios::ChromeBrowserState* chrome_browser_state = ios::ChromeBrowserState::FromBrowserState(context); - std::unique_ptr<autofill::PersonalDataManager> service( - new autofill::PersonalDataManager( - GetApplicationContext()->GetApplicationLocale())); + std::unique_ptr<PersonalDataManager> service( + new PersonalDataManager(GetApplicationContext()->GetApplicationLocale())); service->Init( ios::WebDataServiceFactory::GetAutofillWebDataForBrowserState( chrome_browser_state, ServiceAccessType::EXPLICIT_ACCESS), @@ -60,3 +61,5 @@ chrome_browser_state->IsOffTheRecord()); return std::move(service); } + +} // namespace autofill
diff --git a/ios/chrome/browser/autofill/personal_data_manager_factory.h b/ios/chrome/browser/autofill/personal_data_manager_factory.h index 2ff07be..ec988e5 100644 --- a/ios/chrome/browser/autofill/personal_data_manager_factory.h +++ b/ios/chrome/browser/autofill/personal_data_manager_factory.h
@@ -15,19 +15,19 @@ struct DefaultSingletonTraits; } // namespace base -namespace autofill { -class PersonalDataManager; -} - namespace ios { class ChromeBrowserState; } +namespace autofill { + +class PersonalDataManager; + // Singleton that owns all PersonalDataManagers and associates them with // ios::ChromeBrowserState. class PersonalDataManagerFactory : public BrowserStateKeyedServiceFactory { public: - static autofill::PersonalDataManager* GetForBrowserState( + static PersonalDataManager* GetForBrowserState( ios::ChromeBrowserState* browser_state); static PersonalDataManagerFactory* GetInstance(); @@ -44,4 +44,10 @@ DISALLOW_COPY_AND_ASSIGN(PersonalDataManagerFactory); }; +} // namespace autofill + +// TODO(crbug.com/513344): Remove this typedef once downstream code has +// been fixed to use the fully namespaced name. +using PersonalDataManagerFactory = autofill::PersonalDataManagerFactory; + #endif // IOS_CHROME_BROWSER_AUTOFILL_PERSONAL_DATA_MANAGER_FACTORY_H_
diff --git a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm index e662ddaa..214d6fb 100644 --- a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm +++ b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
@@ -52,6 +52,7 @@ // TODO(erg): This needs to be something else. I don't think putting every // FooServiceFactory here will scale or is desirable long term. void EnsureBrowserStateKeyedServiceFactoriesBuilt() { + autofill::PersonalDataManagerFactory::GetInstance(); dom_distiller::DomDistillerServiceFactory::GetInstance(); ios::AboutSigninInternalsFactory::GetInstance(); ios::AccountConsistencyServiceFactory::GetInstance(); @@ -84,7 +85,6 @@ IOSChromePasswordStoreFactory::GetInstance(); IOSChromeProfileInvalidationProviderFactory::GetInstance(); OAuth2TokenServiceFactory::GetInstance(); - PersonalDataManagerFactory::GetInstance(); SigninClientFactory::GetInstance(); suggestions::SuggestionsServiceFactory::GetInstance(); SyncSetupServiceFactory::GetInstance();
diff --git a/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.mm b/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.mm index 1486c61ca..61d6df5 100644 --- a/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.mm +++ b/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.mm
@@ -225,7 +225,8 @@ base::Unretained(this))); autofill::PersonalDataManager* data_manager = - PersonalDataManagerFactory::GetForBrowserState(browser_state_); + autofill::PersonalDataManagerFactory::GetForBrowserState( + browser_state_); if (data_manager) data_manager->Refresh(); } @@ -292,7 +293,8 @@ base::Unretained(this))); autofill::PersonalDataManager* data_manager = - PersonalDataManagerFactory::GetForBrowserState(browser_state_); + autofill::PersonalDataManagerFactory::GetForBrowserState( + browser_state_); if (data_manager) data_manager->Refresh(); }
diff --git a/ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.cc b/ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.cc index 4c8a4a0..f59e95c4 100644 --- a/ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.cc +++ b/ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.cc
@@ -93,8 +93,8 @@ // The ProfileSyncService depends on various SyncableServices being around // when it is shut down. Specify those dependencies here to build the proper // destruction order. + DependsOn(autofill::PersonalDataManagerFactory::GetInstance()); DependsOn(ios::AboutSigninInternalsFactory::GetInstance()); - DependsOn(PersonalDataManagerFactory::GetInstance()); DependsOn(ios::BookmarkModelFactory::GetInstance()); DependsOn(SigninClientFactory::GetInstance()); DependsOn(ios::HistoryServiceFactory::GetInstance());
diff --git a/ios/chrome/browser/sync/ios_chrome_sync_client.mm b/ios/chrome/browser/sync/ios_chrome_sync_client.mm index 83494f4..268dbe1 100644 --- a/ios/chrome/browser/sync/ios_chrome_sync_client.mm +++ b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
@@ -199,7 +199,8 @@ autofill::PersonalDataManager* IOSChromeSyncClient::GetPersonalDataManager() { DCHECK_CURRENTLY_ON(web::WebThread::UI); - return PersonalDataManagerFactory::GetForBrowserState(browser_state_); + return autofill::PersonalDataManagerFactory::GetForBrowserState( + browser_state_); } base::Closure IOSChromeSyncClient::GetPasswordStateChangedCallback() {
diff --git a/ios/chrome/browser/ui/autofill/autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/autofill_client_ios.mm index 68bc3bdf..c7b6f59 100644 --- a/ios/chrome/browser/ui/autofill/autofill_client_ios.mm +++ b/ios/chrome/browser/ui/autofill/autofill_client_ios.mm
@@ -46,7 +46,7 @@ } PersonalDataManager* AutofillClientIOS::GetPersonalDataManager() { - return PersonalDataManagerFactory::GetForBrowserState( + return autofill::PersonalDataManagerFactory::GetForBrowserState( browser_state_->GetOriginalChromeBrowserState()); }
diff --git a/media/mojo/services/mojo_renderer_service.cc b/media/mojo/services/mojo_renderer_service.cc index 6b7e0f7..7646b83 100644 --- a/media/mojo/services/mojo_renderer_service.cc +++ b/media/mojo/services/mojo_renderer_service.cc
@@ -166,7 +166,7 @@ } void MojoRendererService::UpdateMediaTime(bool force) { - const uint64_t media_time = renderer_->GetMediaTime().InMicroseconds(); + const int64_t media_time = renderer_->GetMediaTime().InMicroseconds(); if (!force && media_time == last_media_time_usec_) return;
diff --git a/media/mojo/services/mojo_renderer_service.h b/media/mojo/services/mojo_renderer_service.h index 1bccd35..57b3be0 100644 --- a/media/mojo/services/mojo_renderer_service.h +++ b/media/mojo/services/mojo_renderer_service.h
@@ -103,7 +103,7 @@ std::unique_ptr<DemuxerStreamProviderShim> stream_provider_; base::RepeatingTimer time_update_timer_; - uint64_t last_media_time_usec_; + int64_t last_media_time_usec_; mojom::RendererClientPtr client_;
diff --git a/mojo/public/cpp/bindings/lib/buffer.h b/mojo/public/cpp/bindings/lib/buffer.h index c3b570e..213a4459 100644 --- a/mojo/public/cpp/bindings/lib/buffer.h +++ b/mojo/public/cpp/bindings/lib/buffer.h
@@ -7,15 +7,61 @@ #include <stddef.h> +#include "base/logging.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/lib/bindings_internal.h" + namespace mojo { namespace internal { -// Buffer provides a way to allocate memory. Allocations are 8-byte aligned and -// zero-initialized. Allocations remain valid for the lifetime of the Buffer. +// Buffer provides an interface to allocate memory blocks which are 8-byte +// aligned and zero-initialized. It doesn't own the underlying memory. Users +// must ensure that the memory stays valid while using the allocated blocks from +// Buffer. class Buffer { public: - virtual ~Buffer() {} - virtual void* Allocate(size_t num_bytes) = 0; + Buffer() {} + + // The memory must have been zero-initialized. |data| must be 8-byte + // aligned. + void Initialize(void* data, size_t size) { + DCHECK(IsAligned(data)); + + data_ = data; + size_ = size; + cursor_ = reinterpret_cast<uintptr_t>(data); + data_end_ = cursor_ + size; + } + + size_t size() const { return size_; } + + void* data() const { return data_; } + + // Allocates |num_bytes| from the buffer and returns a pointer to the start of + // the allocated block. + // The resulting address is 8-byte aligned, and the content of the memory is + // zero-filled. + void* Allocate(size_t num_bytes) { + num_bytes = Align(num_bytes); + uintptr_t result = cursor_; + cursor_ += num_bytes; + if (cursor_ > data_end_ || cursor_ < result) { + NOTREACHED(); + cursor_ -= num_bytes; + return nullptr; + } + + return reinterpret_cast<void*>(result); + } + + private: + void* data_ = nullptr; + size_t size_ = 0; + + uintptr_t cursor_ = 0; + uintptr_t data_end_ = 0; + + DISALLOW_COPY_AND_ASSIGN(Buffer); }; } // namespace internal
diff --git a/mojo/public/cpp/bindings/lib/fixed_buffer.cc b/mojo/public/cpp/bindings/lib/fixed_buffer.cc index 50b8a21..725a193 100644 --- a/mojo/public/cpp/bindings/lib/fixed_buffer.cc +++ b/mojo/public/cpp/bindings/lib/fixed_buffer.cc
@@ -4,56 +4,25 @@ #include "mojo/public/cpp/bindings/lib/fixed_buffer.h" -#include <stddef.h> #include <stdlib.h> -#include <algorithm> - -#include "base/logging.h" -#include "mojo/public/cpp/bindings/lib/serialization_util.h" - namespace mojo { namespace internal { -FixedBuffer::FixedBuffer() : ptr_(nullptr), cursor_(0), size_(0) {} - -void FixedBuffer::Initialize(void* memory, size_t size) { - DCHECK(size == internal::Align(size)); - - ptr_ = static_cast<char*>(memory); - cursor_ = 0; - size_ = size; -} - -void* FixedBuffer::Allocate(size_t delta) { - delta = internal::Align(delta); - - if (delta == 0 || delta > size_ - cursor_) { - NOTREACHED(); - return nullptr; - } - - char* result = ptr_ + cursor_; - cursor_ += delta; - - return result; -} - FixedBufferForTesting::FixedBufferForTesting(size_t size) { - size_ = internal::Align(size); + size = internal::Align(size); // Use calloc here to ensure all message memory is zero'd out. - ptr_ = static_cast<char*>(calloc(size_, 1)); + void* ptr = calloc(size, 1); + Initialize(ptr, size); } FixedBufferForTesting::~FixedBufferForTesting() { - free(ptr_); + free(data()); } void* FixedBufferForTesting::Leak() { - char* ptr = ptr_; - ptr_ = nullptr; - cursor_ = 0; - size_ = 0; + void* ptr = data(); + Initialize(nullptr, 0); return ptr; }
diff --git a/mojo/public/cpp/bindings/lib/fixed_buffer.h b/mojo/public/cpp/bindings/lib/fixed_buffer.h index 9a5704b4..7345d939 100644 --- a/mojo/public/cpp/bindings/lib/fixed_buffer.h +++ b/mojo/public/cpp/bindings/lib/fixed_buffer.h
@@ -13,56 +13,12 @@ namespace mojo { namespace internal { -// FixedBuffer provides a simple way to allocate objects within a fixed chunk -// of memory. Objects are allocated by calling the |Allocate| method, which -// extends the buffer accordingly. Objects allocated in this way are not freed -// explicitly. Instead, they remain valid so long as the FixedBuffer remains -// valid. The Leak method may be used to steal the underlying memory from the -// FixedBuffer. -// -// Typical usage: -// -// { -// FixedBuffer buf(8 + 8); -// -// int* a = static_cast<int*>(buf->Allocate(sizeof(int))); -// *a = 2; -// -// double* b = static_cast<double*>(buf->Allocate(sizeof(double))); -// *b = 3.14f; -// -// void* data = buf.Leak(); -// Process(data); -// -// free(data); -// } - -class FixedBuffer : public Buffer { - public: - FixedBuffer(); - - // |size| should be aligned using internal::Align. - void Initialize(void* memory, size_t size); - - size_t size() const { return size_; } - - // Grows the buffer by |num_bytes| and returns a pointer to the start of the - // addition. The resulting address is 8-byte aligned, and the content of the - // memory is zero-filled. - void* Allocate(size_t num_bytes) override; - - protected: - char* ptr_; - size_t cursor_; - size_t size_; - - DISALLOW_COPY_AND_ASSIGN(FixedBuffer); -}; - -class FixedBufferForTesting : public FixedBuffer { +// FixedBufferForTesting owns its buffer. The Leak method may be used to steal +// the underlying memory. +class FixedBufferForTesting : public Buffer { public: explicit FixedBufferForTesting(size_t size); - ~FixedBufferForTesting() override; + ~FixedBufferForTesting(); // Returns the internal memory owned by the Buffer to the caller. The Buffer // relinquishes its pointer, effectively resetting the state of the Buffer
diff --git a/mojo/public/cpp/bindings/lib/message_buffer.cc b/mojo/public/cpp/bindings/lib/message_buffer.cc index af79cfd..cc12ef6 100644 --- a/mojo/public/cpp/bindings/lib/message_buffer.cc +++ b/mojo/public/cpp/bindings/lib/message_buffer.cc
@@ -13,54 +13,35 @@ MessageBuffer::MessageBuffer(size_t capacity, bool zero_initialized) { DCHECK_LE(capacity, std::numeric_limits<uint32_t>::max()); - data_num_bytes_ = static_cast<uint32_t>(capacity); MojoResult rv = AllocMessage(capacity, nullptr, 0, MOJO_ALLOC_MESSAGE_FLAG_NONE, &message_); CHECK_EQ(rv, MOJO_RESULT_OK); - if (capacity == 0) { - buffer_ = nullptr; - } else { - rv = GetMessageBuffer(message_.get(), &buffer_); + void* buffer = nullptr; + if (capacity != 0) { + rv = GetMessageBuffer(message_.get(), &buffer); CHECK_EQ(rv, MOJO_RESULT_OK); if (zero_initialized) - memset(buffer_, 0, capacity); + memset(buffer, 0, capacity); } + Initialize(buffer, capacity); } MessageBuffer::MessageBuffer(ScopedMessageHandle message, uint32_t num_bytes) { message_ = std::move(message); - data_num_bytes_ = num_bytes; - if (num_bytes == 0) { - buffer_ = nullptr; - } else { - MojoResult rv = GetMessageBuffer(message_.get(), &buffer_); + void* buffer = nullptr; + if (num_bytes != 0) { + MojoResult rv = GetMessageBuffer(message_.get(), &buffer); CHECK_EQ(rv, MOJO_RESULT_OK); } + Initialize(buffer, num_bytes); } MessageBuffer::~MessageBuffer() {} -void* MessageBuffer::Allocate(size_t delta) { - delta = internal::Align(delta); - - DCHECK_LE(delta, static_cast<size_t>(data_num_bytes_)); - DCHECK_GT(bytes_claimed_ + static_cast<uint32_t>(delta), bytes_claimed_); - - uint32_t new_bytes_claimed = bytes_claimed_ + static_cast<uint32_t>(delta); - if (new_bytes_claimed > data_num_bytes_) { - NOTREACHED(); - return nullptr; - } - - char* start = static_cast<char*>(buffer_) + bytes_claimed_; - bytes_claimed_ = new_bytes_claimed; - return static_cast<void*>(start); -} - void MessageBuffer::NotifyBadMessage(const std::string& error) { DCHECK(message_.is_valid()); MojoResult result = mojo::NotifyBadMessage(message_.get(), error);
diff --git a/mojo/public/cpp/bindings/lib/message_buffer.h b/mojo/public/cpp/bindings/lib/message_buffer.h index 03821314..96d5140 100644 --- a/mojo/public/cpp/bindings/lib/message_buffer.h +++ b/mojo/public/cpp/bindings/lib/message_buffer.h
@@ -5,7 +5,6 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ #define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ -#include <stddef.h> #include <stdint.h> #include <utility> @@ -17,7 +16,7 @@ namespace mojo { namespace internal { -// A fixed-size Buffer implementation using a Mojo message object for storage. +// A fixed-size Buffer using a Mojo message object for storage. class MessageBuffer : public Buffer { public: // Initializes this buffer to carry a fixed byte capacity and no handles. @@ -26,24 +25,14 @@ // Initializes this buffer from an existing Mojo MessageHandle. MessageBuffer(ScopedMessageHandle message, uint32_t num_bytes); - ~MessageBuffer() override; - - void* data() const { return buffer_; } - uint32_t data_num_bytes() const { return data_num_bytes_; } - - // Buffer: - void* Allocate(size_t delta) override; + ~MessageBuffer(); ScopedMessageHandle TakeMessage() { return std::move(message_); } void NotifyBadMessage(const std::string& error); private: - uint32_t data_num_bytes_ = 0; ScopedMessageHandle message_; - void* buffer_; - - uint32_t bytes_claimed_ = 0; DISALLOW_COPY_AND_ASSIGN(MessageBuffer); };
diff --git a/mojo/public/cpp/bindings/lib/serialization.h b/mojo/public/cpp/bindings/lib/serialization.h index 6d7dd8e..e51d5f9 100644 --- a/mojo/public/cpp/bindings/lib/serialization.h +++ b/mojo/public/cpp/bindings/lib/serialization.h
@@ -11,7 +11,7 @@ #include "mojo/public/cpp/bindings/array_traits_standard.h" #include "mojo/public/cpp/bindings/array_traits_stl.h" #include "mojo/public/cpp/bindings/lib/array_serialization.h" -#include "mojo/public/cpp/bindings/lib/fixed_buffer.h" +#include "mojo/public/cpp/bindings/lib/buffer.h" #include "mojo/public/cpp/bindings/lib/handle_interface_serialization.h" #include "mojo/public/cpp/bindings/lib/map_serialization.h" #include "mojo/public/cpp/bindings/lib/native_enum_serialization.h" @@ -53,7 +53,7 @@ DCHECK(IsAligned(result_buffer)); } - FixedBuffer buffer; + Buffer buffer; buffer.Initialize(result_buffer, size); typename MojomType::Struct::Data_* data = nullptr; Serialize<MojomType>(*input, &buffer, &data, &context);
diff --git a/mojo/public/cpp/bindings/message.h b/mojo/public/cpp/bindings/message.h index 2f4ec40e..6c4730c3 100644 --- a/mojo/public/cpp/bindings/message.h +++ b/mojo/public/cpp/bindings/message.h
@@ -47,7 +47,9 @@ // Transfers data and handles to |destination|. void MoveTo(Message* destination); - uint32_t data_num_bytes() const { return buffer_->data_num_bytes(); } + uint32_t data_num_bytes() const { + return static_cast<uint32_t>(buffer_->size()); + } // Access the raw bytes of the message. const uint8_t* data() const { @@ -89,8 +91,8 @@ const uint8_t* payload() const { return data() + header()->num_bytes; } uint8_t* mutable_payload() { return const_cast<uint8_t*>(payload()); } uint32_t payload_num_bytes() const { - DCHECK(buffer_->data_num_bytes() >= header()->num_bytes); - size_t num_bytes = buffer_->data_num_bytes() - header()->num_bytes; + DCHECK(data_num_bytes() >= header()->num_bytes); + size_t num_bytes = data_num_bytes() - header()->num_bytes; DCHECK(num_bytes <= std::numeric_limits<uint32_t>::max()); return static_cast<uint32_t>(num_bytes); }
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl index dd87be7..28d6399 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
@@ -2,7 +2,9 @@ class {{class_name}} { public: - static {{class_name}}* New(mojo::internal::Buffer* buf); + static {{class_name}}* New(mojo::internal::Buffer* buf) { + return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}(); + } static bool Validate(const void* data, mojo::internal::ValidationContext* validation_context);
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl index a2e57084..b5f4462 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
@@ -2,11 +2,6 @@ {%- set class_name = struct.name ~ "_Data" %} // static -{{class_name}}* {{class_name}}::New(mojo::internal::Buffer* buf) { - return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}(); -} - -// static bool {{class_name}}::Validate( const void* data, mojo::internal::ValidationContext* validation_context) {
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl index be2db4c..d6585407 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
@@ -6,7 +6,11 @@ public: // Used to identify Mojom Union Data Classes. typedef void MojomUnionDataType; - static {{class_name}}* New(mojo::internal::Buffer* buf); + + static {{class_name}}* New(mojo::internal::Buffer* buf) { + return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}(); + } + {{class_name}}(); // Do nothing in the destructor since it won't be called. ~{{class_name}}() {}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl index fc6eddf..df08792 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
@@ -3,11 +3,6 @@ {%- set enum_name = union.name ~ "_Tag" -%} // static -{{class_name}}* {{class_name}}::New(mojo::internal::Buffer* buf) { - return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}(); -} - -// static bool {{class_name}}::Validate( const void* data, mojo::internal::ValidationContext* validation_context,
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index f6eee4d..8fe401c 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -128,6 +128,7 @@ quic_allow_server_migration(false), quic_disable_bidirectional_streams(false), quic_force_hol_blocking(false), + quic_race_cert_verification(false), proxy_delegate(NULL), enable_token_binding(false) { quic_supported_versions.push_back(QUIC_VERSION_34); @@ -188,6 +189,7 @@ params.quic_migrate_sessions_early, params.quic_allow_server_migration, params.quic_force_hol_blocking, + params.quic_race_cert_verification, params.quic_connection_options, params.enable_token_binding), spdy_session_pool_(params.host_resolver, @@ -341,6 +343,8 @@ dict->SetString("disabled_reason", quic_stream_factory_.QuicDisabledReasonString()); dict->SetBoolean("force_hol_blocking", params_.quic_force_hol_blocking); + dict->SetBoolean("race_cert_verification", + params_.quic_race_cert_verification); return std::move(dict); }
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index 6980027..3f324aa 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -181,6 +181,8 @@ bool quic_disable_bidirectional_streams; // If true, enable force HOL blocking. For measurement purposes. bool quic_force_hol_blocking; + // If true, race cert verification with host resolution. + bool quic_race_cert_verification; ProxyDelegate* proxy_delegate; // Enable support for Token Binding.
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc index d38cf0b..dbf4986 100644 --- a/net/nqe/network_quality_estimator.cc +++ b/net/nqe/network_quality_estimator.cc
@@ -801,8 +801,12 @@ LoadTimingInfo load_timing_info; request.GetLoadTimingInfo(&load_timing_info); - DCHECK(!load_timing_info.send_start.is_null() && - !load_timing_info.receive_headers_end.is_null()); + // If the load timing info is unavailable, it probably means that the request + // did not go over the network. + if (load_timing_info.send_start.is_null() || + load_timing_info.receive_headers_end.is_null()) { + return; + } // Record UMA only for successful requests that have completed. if (!request.status().is_success() || request.status().is_io_pending())
diff --git a/net/quic/chromium/crypto/proof_verifier_chromium.cc b/net/quic/chromium/crypto/proof_verifier_chromium.cc index d66b9ff7..9a7396e 100644 --- a/net/quic/chromium/crypto/proof_verifier_chromium.cc +++ b/net/quic/chromium/crypto/proof_verifier_chromium.cc
@@ -78,6 +78,16 @@ std::unique_ptr<ProofVerifyDetails>* verify_details, std::unique_ptr<ProofVerifierCallback> callback); + // Starts the certificate chain verification of |certs|. If |QUIC_PENDING| is + // returned, then |callback| will be invoked asynchronously when the + // verification completes. + QuicAsyncStatus VerifyCertChain( + const std::string& hostname, + const std::vector<std::string>& certs, + std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* verify_details, + std::unique_ptr<ProofVerifierCallback> callback); + private: enum State { STATE_NONE, @@ -85,6 +95,19 @@ STATE_VERIFY_CERT_COMPLETE, }; + // Convert |certs| to |cert_|(X509Certificate). Returns true if successful. + bool GetX509Certificate(const vector<string>& certs, + std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* verify_details); + + // Start the cert verification. + QuicAsyncStatus VerifyCert( + const string& hostname, + const uint16_t port, + std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* verify_details, + std::unique_ptr<ProofVerifierCallback> callback); + int DoLoop(int last_io_result); void OnIOComplete(int result); int DoVerifyCert(int result); @@ -125,6 +148,9 @@ // passed to CertVerifier::Verify. int cert_verify_flags_; + // If set to true, enforces policy checking in DoVerifyCertComplete(). + bool enforce_policy_checking_; + State next_state_; base::TimeTicks start_time_; @@ -148,6 +174,7 @@ transport_security_state_(transport_security_state), cert_transparency_verifier_(cert_transparency_verifier), cert_verify_flags_(cert_verify_flags), + enforce_policy_checking_(true), next_state_(STATE_NONE), start_time_(base::TimeTicks::Now()), net_log_(net_log) { @@ -195,12 +222,76 @@ verify_details_.reset(new ProofVerifyDetailsChromium); + // Converts |certs| to |cert_|. + if (!GetX509Certificate(certs, error_details, verify_details)) + return QUIC_FAILURE; + + if (!cert_sct.empty()) { + // Note that this is a completely synchronous operation: The CT Log Verifier + // gets all the data it needs for SCT verification and does not do any + // external communication. + cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct, + &verify_details_->ct_verify_result, + net_log_); + } + + // We call VerifySignature first to avoid copying of server_config and + // signature. + if (!signature.empty() && + !VerifySignature(server_config, quic_version, chlo_hash, signature, + certs[0])) { + *error_details = "Failed to verify signature of server config"; + DLOG(WARNING) << *error_details; + verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; + *verify_details = std::move(verify_details_); + return QUIC_FAILURE; + } + + DCHECK(enforce_policy_checking_); + return VerifyCert(hostname, port, error_details, verify_details, + std::move(callback)); +} + +QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain( + const string& hostname, + const vector<string>& certs, + std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* verify_details, + std::unique_ptr<ProofVerifierCallback> callback) { + DCHECK(error_details); + DCHECK(verify_details); + DCHECK(callback); + + error_details->clear(); + + if (STATE_NONE != next_state_) { + *error_details = "Certificate is already set and VerifyCertChain has begun"; + DLOG(DFATAL) << *error_details; + return QUIC_FAILURE; + } + + verify_details_.reset(new ProofVerifyDetailsChromium); + + // Converts |certs| to |cert_|. + if (!GetX509Certificate(certs, error_details, verify_details)) + return QUIC_FAILURE; + + enforce_policy_checking_ = false; + // |port| is not needed because |enforce_policy_checking_| is false. + return VerifyCert(hostname, /*port=*/0, error_details, verify_details, + std::move(callback)); +} + +bool ProofVerifierChromium::Job::GetX509Certificate( + const vector<string>& certs, + std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* verify_details) { if (certs.empty()) { *error_details = "Failed to create certificate chain. Certs are empty."; DLOG(WARNING) << *error_details; verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; *verify_details = std::move(verify_details_); - return QUIC_FAILURE; + return false; } // Convert certs to X509Certificate. @@ -214,29 +305,17 @@ DLOG(WARNING) << *error_details; verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; *verify_details = std::move(verify_details_); - return QUIC_FAILURE; + return false; } + return true; +} - if (!cert_sct.empty()) { - // Note that this is a completely synchronous operation: The CT Log Verifier - // gets all the data it needs for SCT verification and does not do any - // external communication. - cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct, - &verify_details_->ct_verify_result, - net_log_); - } - - // We call VerifySignature first to avoid copying of server_config and - // signature. - if (!VerifySignature(server_config, quic_version, chlo_hash, signature, - certs[0])) { - *error_details = "Failed to verify signature of server config"; - DLOG(WARNING) << *error_details; - verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; - *verify_details = std::move(verify_details_); - return QUIC_FAILURE; - } - +QuicAsyncStatus ProofVerifierChromium::Job::VerifyCert( + const string& hostname, + const uint16_t port, + std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* verify_details, + std::unique_ptr<ProofVerifierCallback> callback) { hostname_ = hostname; port_ = port; @@ -315,7 +394,8 @@ // If the connection was good, check HPKP and CT status simultaneously, // but prefer to treat the HPKP error as more serious, if there was one. - if ((result == OK || + if (enforce_policy_checking_ && + (result == OK || (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) { if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) { ct::EVPolicyCompliance ev_policy_compliance = @@ -505,9 +585,32 @@ QuicAsyncStatus status = job->VerifyProof( hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct, signature, error_details, verify_details, std::move(callback)); - if (status == QUIC_PENDING) { + if (status == QUIC_PENDING) active_jobs_.insert(job.release()); + return status; +} + +QuicAsyncStatus ProofVerifierChromium::VerifyCertChain( + const std::string& hostname, + const std::vector<std::string>& certs, + const ProofVerifyContext* verify_context, + std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* verify_details, + std::unique_ptr<ProofVerifierCallback> callback) { + if (!verify_context) { + *error_details = "Missing context"; + return QUIC_FAILURE; } + const ProofVerifyContextChromium* chromium_context = + reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); + std::unique_ptr<Job> job( + new Job(this, cert_verifier_, ct_policy_enforcer_, + transport_security_state_, cert_transparency_verifier_, + chromium_context->cert_verify_flags, chromium_context->net_log)); + QuicAsyncStatus status = job->VerifyCertChain( + hostname, certs, error_details, verify_details, std::move(callback)); + if (status == QUIC_PENDING) + active_jobs_.insert(job.release()); return status; }
diff --git a/net/quic/chromium/crypto/proof_verifier_chromium.h b/net/quic/chromium/crypto/proof_verifier_chromium.h index e8eda86097..bc4acce1 100644 --- a/net/quic/chromium/crypto/proof_verifier_chromium.h +++ b/net/quic/chromium/crypto/proof_verifier_chromium.h
@@ -85,6 +85,13 @@ std::string* error_details, std::unique_ptr<ProofVerifyDetails>* verify_details, std::unique_ptr<ProofVerifierCallback> callback) override; + QuicAsyncStatus VerifyCertChain( + const std::string& hostname, + const std::vector<std::string>& certs, + const ProofVerifyContext* verify_context, + std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* verify_details, + std::unique_ptr<ProofVerifierCallback> callback) override; private: class Job;
diff --git a/net/quic/chromium/crypto/proof_verifier_chromium_test.cc b/net/quic/chromium/crypto/proof_verifier_chromium_test.cc index fa05362..91f9aed 100644 --- a/net/quic/chromium/crypto/proof_verifier_chromium_test.cc +++ b/net/quic/chromium/crypto/proof_verifier_chromium_test.cc
@@ -588,5 +588,34 @@ CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED); } +// Tests that the VerifyCertChain verifies certificates. +TEST_F(ProofVerifierChromiumTest, VerifyCertChain) { + scoped_refptr<X509Certificate> test_cert = GetTestServerCertificate(); + ASSERT_TRUE(test_cert); + + CertVerifyResult dummy_result; + dummy_result.verified_cert = test_cert; + dummy_result.cert_status = 0; + + MockCertVerifier dummy_verifier; + dummy_verifier.AddResultForCert(test_cert.get(), dummy_result, OK); + + ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_, + &transport_security_state_, + ct_verifier_.get()); + + std::unique_ptr<DummyProofVerifierCallback> callback( + new DummyProofVerifierCallback); + QuicAsyncStatus status = proof_verifier.VerifyCertChain( + kTestHostname, certs_, verify_context_.get(), &error_details_, &details_, + std::move(callback)); + ASSERT_EQ(QUIC_SUCCESS, status); + + ASSERT_TRUE(details_.get()); + ProofVerifyDetailsChromium* verify_details = + static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_EQ(0u, verify_details->cert_verify_result.cert_status); +} + } // namespace test } // namespace net
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc index f58f965a..d3cafeb 100644 --- a/net/quic/chromium/quic_stream_factory.cc +++ b/net/quic/chromium/quic_stream_factory.cc
@@ -40,6 +40,7 @@ #include "net/quic/chromium/quic_chromium_connection_helper.h" #include "net/quic/chromium/quic_chromium_packet_reader.h" #include "net/quic/chromium/quic_chromium_packet_writer.h" +#include "net/quic/core/crypto/proof_verifier.h" #include "net/quic/core/crypto/properties_based_quic_server_info.h" #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/crypto/quic_server_info.h" @@ -168,6 +169,88 @@ } // namespace +// Responsible for verifying the certificates saved in +// QuicCryptoClientConfig, and for notifying any associated requests when +// complete. Results from cert verification are ignored. +class QuicStreamFactory::CertVerifierJob { + public: + // ProofVerifierCallbackImpl is passed as the callback method to + // VerifyCertChain. The ProofVerifier calls this class with the result of cert + // verification when verification is performed asynchronously. + class ProofVerifierCallbackImpl : public ProofVerifierCallback { + public: + explicit ProofVerifierCallbackImpl(CertVerifierJob* job) : job_(job) {} + + ~ProofVerifierCallbackImpl() override {} + + void Run(bool ok, + const std::string& error_details, + std::unique_ptr<ProofVerifyDetails>* details) override { + if (job_ == nullptr) + return; + job_->verify_callback_ = nullptr; + job_->OnComplete(); + } + + void Cancel() { job_ = nullptr; } + + private: + CertVerifierJob* job_; + }; + + CertVerifierJob(const QuicServerId& server_id, + int cert_verify_flags, + const BoundNetLog& net_log) + : server_id_(server_id), + verify_callback_(nullptr), + verify_context_(base::WrapUnique( + new ProofVerifyContextChromium(cert_verify_flags, net_log))), + net_log_(net_log), + weak_factory_(this) {} + + ~CertVerifierJob() { + if (verify_callback_) + verify_callback_->Cancel(); + } + + // Starts verification of certs cached in the |crypto_config|. + QuicAsyncStatus Run(QuicCryptoClientConfig* crypto_config, + const CompletionCallback& callback) { + QuicCryptoClientConfig::CachedState* cached = + crypto_config->LookupOrCreate(server_id_); + ProofVerifierCallbackImpl* verify_callback = + new ProofVerifierCallbackImpl(this); + QuicAsyncStatus status = crypto_config->proof_verifier()->VerifyCertChain( + server_id_.host(), cached->certs(), verify_context_.get(), + &verify_error_details_, &verify_details_, + std::unique_ptr<ProofVerifierCallback>(verify_callback)); + if (status == QUIC_PENDING) { + verify_callback_ = verify_callback; + callback_ = callback; + } + return status; + } + + void OnComplete() { + if (!callback_.is_null()) + callback_.Run(OK); + } + + const QuicServerId& server_id() const { return server_id_; } + + private: + QuicServerId server_id_; + ProofVerifierCallbackImpl* verify_callback_; + std::unique_ptr<ProofVerifyContext> verify_context_; + std::unique_ptr<ProofVerifyDetails> verify_details_; + std::string verify_error_details_; + const BoundNetLog net_log_; + CompletionCallback callback_; + base::WeakPtrFactory<CertVerifierJob> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(CertVerifierJob); +}; + // Responsible for creating a new QUIC session to the specified server, and // for notifying any associated requests when complete. class QuicStreamFactory::Job { @@ -365,9 +448,8 @@ int QuicStreamFactory::Job::DoResolveHost() { // Start loading the data now, and wait for it after we resolve the host. - if (server_info_) { + if (server_info_) server_info_->Start(); - } io_state_ = STATE_RESOLVE_HOST_COMPLETE; dns_resolution_start_time_ = base::TimeTicks::Now(); @@ -389,9 +471,8 @@ // Inform the factory of this resolution, which will set up // a session alias, if possible. - if (factory_->OnResolution(key_, address_list_)) { + if (factory_->OnResolution(key_, address_list_)) return OK; - } if (server_info_) io_state_ = STATE_LOAD_SERVER_INFO; @@ -470,14 +551,12 @@ return rv; } - if (!session_->connection()->connected()) { + if (!session_->connection()->connected()) return ERR_CONNECTION_CLOSED; - } session_->StartReading(); - if (!session_->connection()->connected()) { + if (!session_->connection()->connected()) return ERR_QUIC_PROTOCOL_ERROR; - } bool require_confirmation = factory_->require_confirmation() || was_alternative_service_recently_broken_; @@ -486,8 +565,9 @@ base::Bind(&QuicStreamFactory::Job::OnIOComplete, GetWeakPtr())); if (!session_->connection()->connected() && - session_->error() == QUIC_PROOF_INVALID) + session_->error() == QUIC_PROOF_INVALID) { return ERR_QUIC_HANDSHAKE_FAILED; + } return rv; } @@ -504,9 +584,8 @@ int QuicStreamFactory::Job::DoConnectComplete(int rv) { if (session_ && session_->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { num_sent_client_hellos_ += session_->GetNumSentClientHellos(); - if (num_sent_client_hellos_ >= QuicCryptoClientStream::kMaxClientHellos) { + if (num_sent_client_hellos_ >= QuicCryptoClientStream::kMaxClientHellos) return ERR_QUIC_HANDSHAKE_FAILED; - } // The handshake was rejected statelessly, so create another connection // to resume the handshake. io_state_ = STATE_CONNECT; @@ -635,6 +714,7 @@ bool migrate_sessions_early, bool allow_server_migration, bool force_hol_blocking, + bool race_cert_verification, const QuicTagVector& connection_options, bool enable_token_binding) : require_confirmation_(true), @@ -691,6 +771,7 @@ migrate_sessions_on_network_change_), allow_server_migration_(allow_server_migration), force_hol_blocking_(force_hol_blocking), + race_cert_verification_(race_cert_verification), port_seed_(random_generator_->RandUint64()), check_persisted_supports_quic_(true), has_initialized_data_(false), @@ -758,6 +839,8 @@ STLDeleteElements(&(active_jobs_[server_id])); active_jobs_.erase(server_id); } + while (!active_cert_verifier_jobs_.empty()) + active_cert_verifier_jobs_.erase(active_cert_verifier_jobs_.begin()); if (ssl_config_service_.get()) ssl_config_service_->RemoveObserver(this); if (migrate_sessions_on_network_change_) { @@ -889,11 +972,12 @@ // don't wait for Cache thread to load the data for that server. load_from_disk_cache = false; } - if (load_from_disk_cache && CryptoConfigCacheIsEmpty(server_id)) { + if (load_from_disk_cache && CryptoConfigCacheIsEmpty(server_id)) quic_server_info = quic_server_info_factory_->GetForServer(server_id); - } } + ignore_result(StartCertVerifyJob(server_id, cert_verify_flags, net_log)); + QuicSessionKey key(destination, server_id); std::unique_ptr<Job> job( new Job(this, host_resolver_, key, WasQuicRecentlyBroken(server_id), @@ -954,9 +1038,8 @@ const AddressList& address_list) { const QuicServerId& server_id(key.server_id()); DCHECK(!HasActiveSession(server_id)); - if (disable_connection_pooling_) { + if (disable_connection_pooling_) return false; - } for (const IPEndPoint& address : address_list) { if (!ContainsKey(ip_aliases_, address)) continue; @@ -1026,6 +1109,10 @@ job_requests_map_.erase(server_id); } +void QuicStreamFactory::OnCertVerifyJobComplete(CertVerifierJob* job, int rv) { + active_cert_verifier_jobs_.erase(job->server_id()); +} + std::unique_ptr<QuicHttpStream> QuicStreamFactory::CreateFromSession( QuicChromiumClientSession* session) { return std::unique_ptr<QuicHttpStream>( @@ -1141,9 +1228,8 @@ DCHECK_EQ(session, active_sessions_[server_id]); // Track sessions which have recently gone away so that we can disable // port suggestions. - if (session->goaway_received()) { + if (session->goaway_received()) gone_away_aliases_.insert(*it); - } active_sessions_.erase(server_id); ProcessGoingAwaySession(session, server_id, true); @@ -1152,9 +1238,8 @@ if (!aliases.empty()) { const IPEndPoint peer_address = session->connection()->peer_address(); ip_aliases_[peer_address].erase(session); - if (ip_aliases_[peer_address].empty()) { + if (ip_aliases_[peer_address].empty()) ip_aliases_.erase(peer_address); - } } session_aliases_.erase(session); } @@ -1259,9 +1344,8 @@ QuicChromiumClientSession* session) { const AliasSet& aliases = session_aliases_[session]; - if (aliases.empty()) { + if (aliases.empty()) return; - } for (const QuicSessionKey& key : aliases) { const QuicServerId& server_id = key.server_id(); @@ -1273,9 +1357,8 @@ const IPEndPoint peer_address = session->connection()->peer_address(); ip_aliases_[peer_address].erase(session); - if (ip_aliases_[peer_address].empty()) { + if (ip_aliases_[peer_address].empty()) ip_aliases_.erase(peer_address); - } QuicSessionKey key = *aliases.begin(); session_aliases_.erase(session); Job* job = new Job(this, host_resolver_, session, key); @@ -1371,9 +1454,8 @@ NetworkChangeNotifier::NetworkList network_list; NetworkChangeNotifier::GetConnectedNetworks(&network_list); for (NetworkHandle new_network : network_list) { - if (new_network != old_network) { + if (new_network != old_network) return new_network; - } } return NetworkChangeNotifier::kInvalidNetworkHandle; } @@ -1579,6 +1661,11 @@ return ContainsKey(active_jobs_, server_id); } +bool QuicStreamFactory::HasActiveCertVerifierJob( + const QuicServerId& server_id) const { + return ContainsKey(active_cert_verifier_jobs_, server_id); +} + int QuicStreamFactory::ConfigureSocket(DatagramClientSocket* socket, IPEndPoint addr, NetworkHandle network) { @@ -1667,15 +1754,13 @@ // Passing in kInvalidNetworkHandle binds socket to default network. int rv = ConfigureSocket(socket.get(), addr, NetworkChangeNotifier::kInvalidNetworkHandle); - if (rv != OK) { + if (rv != OK) return rv; - } - if (enable_port_selection) { + if (enable_port_selection) DCHECK_LE(1u, port_suggester->call_count()); - } else { + else DCHECK_EQ(0u, port_suggester->call_count()); - } if (!helper_.get()) { helper_.reset( @@ -1789,6 +1874,29 @@ return cached->IsEmpty(); } +QuicAsyncStatus QuicStreamFactory::StartCertVerifyJob( + const QuicServerId& server_id, + int cert_verify_flags, + const BoundNetLog& net_log) { + if (!race_cert_verification_) + return QUIC_FAILURE; + QuicCryptoClientConfig::CachedState* cached = + crypto_config_.LookupOrCreate(server_id); + if (!cached || cached->certs().empty() || + HasActiveCertVerifierJob(server_id)) { + return QUIC_FAILURE; + } + std::unique_ptr<CertVerifierJob> cert_verifier_job( + new CertVerifierJob(server_id, cert_verify_flags, net_log)); + QuicAsyncStatus status = cert_verifier_job->Run( + &crypto_config_, + base::Bind(&QuicStreamFactory::OnCertVerifyJobComplete, + base::Unretained(this), cert_verifier_job.get())); + if (status == QUIC_PENDING) + active_cert_verifier_jobs_[server_id] = std::move(cert_verifier_job); + return status; +} + void QuicStreamFactory::InitializeCachedStateInCryptoConfig( const QuicServerId& server_id, const std::unique_ptr<QuicServerInfo>& server_info,
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h index 35a6ac3..fad86df 100644 --- a/net/quic/chromium/quic_stream_factory.h +++ b/net/quic/chromium/quic_stream_factory.h
@@ -194,6 +194,7 @@ bool migrate_sessions_early, bool allow_server_migration, bool force_hol_blocking, + bool race_cert_verification, const QuicTagVector& connection_options, bool enable_token_binding); ~QuicStreamFactory() override; @@ -373,6 +374,7 @@ private: class Job; + class CertVerifierJob; friend class test::QuicStreamFactoryPeer; FRIEND_TEST_ALL_PREFIXES(HttpStreamFactoryTest, QuicLossyProxyMarkedAsBad); @@ -390,6 +392,8 @@ typedef std::map<QuicServerId, RequestSet> ServerIDRequestsMap; typedef std::deque<enum QuicChromiumClientSession::QuicDisabledReason> DisabledReasonsQueue; + typedef std::map<QuicServerId, std::unique_ptr<CertVerifierJob>> + CertVerifierJobMap; enum FactoryStatus { OPEN, // New streams may be created. @@ -409,8 +413,10 @@ bool OnResolution(const QuicSessionKey& key, const AddressList& address_list); void OnJobComplete(Job* job, int rv); + void OnCertVerifyJobComplete(CertVerifierJob* job, int rv); bool HasActiveSession(const QuicServerId& server_id) const; bool HasActiveJob(const QuicServerId& server_id) const; + bool HasActiveCertVerifierJob(const QuicServerId& server_id) const; int CreateSession(const QuicSessionKey& key, int cert_verify_flags, std::unique_ptr<QuicServerInfo> quic_server_info, @@ -432,6 +438,13 @@ bool CryptoConfigCacheIsEmpty(const QuicServerId& server_id); + // Starts an asynchronous job for cert verification if + // |race_cert_verification_| is enabled and if there are cached certs for the + // given |server_id|. + QuicAsyncStatus StartCertVerifyJob(const QuicServerId& server_id, + int cert_verify_flags, + const BoundNetLog& net_log); + // Initializes the cached state associated with |server_id| in // |crypto_config_| with the information in |server_info|. Populates // |connection_id| with the next server designated connection id, @@ -509,6 +522,8 @@ ServerIDRequestsMap job_requests_map_; RequestMap active_requests_; + CertVerifierJobMap active_cert_verifier_jobs_; + QuicVersionVector supported_versions_; // Determine if we should consistently select a client UDP port. If false, @@ -598,6 +613,9 @@ // If set, force HOL blocking. For measurement purposes. const bool force_hol_blocking_; + // Set if cert verification is to be raced with host resolution. + bool race_cert_verification_; + // Each profile will (probably) have a unique port_seed_ value. This value // is used to help seed a pseudo-random number generator (PortSuggester) so // that we consistently (within this profile) suggest the same ephemeral
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc index 80831d8b..0528ca2c 100644 --- a/net/quic/chromium/quic_stream_factory_test.cc +++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -322,16 +322,16 @@ migrate_sessions_on_network_change_(false), migrate_sessions_early_(false), allow_server_migration_(false), - force_hol_blocking_(false) { + force_hol_blocking_(false), + race_cert_verification_(false) { clock_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); } ~QuicStreamFactoryTestBase() { // If |factory_| was initialized, then it took over ownership of |clock_|. // If |factory_| was not initialized, then |clock_| needs to be destroyed. - if (!factory_) { + if (!factory_) delete clock_; - } } void Initialize() { @@ -355,7 +355,8 @@ disable_quic_on_timeout_with_open_streams_, idle_connection_timeout_seconds_, migrate_sessions_on_network_change_, migrate_sessions_early_, allow_server_migration_, force_hol_blocking_, - QuicTagVector(), /*enable_token_binding*/ false)); + race_cert_verification_, QuicTagVector(), + /*enable_token_binding*/ false)); factory_->set_require_confirmation(false); EXPECT_FALSE(factory_->has_quic_server_info_factory()); factory_->set_quic_server_info_factory(new MockQuicServerInfoFactory()); @@ -380,6 +381,11 @@ return QuicStreamFactoryPeer::HasActiveSession(factory_.get(), server_id); } + bool HasActiveCertVerifierJob(const QuicServerId& server_id) { + return QuicStreamFactoryPeer::HasActiveCertVerifierJob(factory_.get(), + server_id); + } + QuicChromiumClientSession* GetActiveSession( const HostPortPair& host_port_pair) { QuicServerId server_id(host_port_pair, PRIVACY_MODE_DISABLED); @@ -549,6 +555,7 @@ bool migrate_sessions_early_; bool allow_server_migration_; bool force_hol_blocking_; + bool race_cert_verification_; }; class QuicStreamFactoryTest : public QuicStreamFactoryTestBase, @@ -4239,6 +4246,63 @@ EXPECT_EQ(test_cert2, cached2->certs()[0]); } +TEST_P(QuicStreamFactoryTest, StartCertVerifyJob) { + Initialize(); + + MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)}; + SequencedSocketData socket_data(reads, arraysize(reads), nullptr, 0); + socket_factory_.AddSocketDataProvider(&socket_data); + + // Save current state of |race_cert_verification|. + bool race_cert_verification = + QuicStreamFactoryPeer::GetRaceCertVerification(factory_.get()); + + // Load server config. + HostPortPair host_port_pair(kDefaultServerHostName, kDefaultServerPort); + QuicServerId quic_server_id(host_port_pair_, privacy_mode_); + QuicStreamFactoryPeer::CacheDummyServerConfig(factory_.get(), quic_server_id); + + QuicStreamFactoryPeer::SetRaceCertVerification(factory_.get(), true); + EXPECT_FALSE(HasActiveCertVerifierJob(quic_server_id)); + + // Start CertVerifyJob. + QuicAsyncStatus status = QuicStreamFactoryPeer::StartCertVerifyJob( + factory_.get(), quic_server_id, /*cert_verify_flags=*/0, net_log_); + if (status == QUIC_PENDING) { + // Verify CertVerifierJob has started. + EXPECT_TRUE(HasActiveCertVerifierJob(quic_server_id)); + + while (HasActiveCertVerifierJob(quic_server_id)) { + base::RunLoop().RunUntilIdle(); + } + } + // Verify CertVerifierJob has finished. + EXPECT_FALSE(HasActiveCertVerifierJob(quic_server_id)); + + // Start a QUIC request. + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request(host_port_pair_, privacy_mode_, + /*cert_verify_flags=*/0, url_, "GET", net_log_, + callback_.callback())); + + EXPECT_EQ(OK, callback_.WaitForResult()); + + std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + EXPECT_TRUE(stream.get()); + + // Restore |race_cert_verification|. + QuicStreamFactoryPeer::SetRaceCertVerification(factory_.get(), + race_cert_verification); + + EXPECT_TRUE(socket_data.AllReadDataConsumed()); + EXPECT_TRUE(socket_data.AllWriteDataConsumed()); + + // Verify there are no outstanding CertVerifierJobs after request has + // finished. + EXPECT_FALSE(HasActiveCertVerifierJob(quic_server_id)); +} + TEST_P(QuicStreamFactoryTest, QuicDoingZeroRTT) { Initialize();
diff --git a/net/quic/core/crypto/proof_verifier.h b/net/quic/core/crypto/proof_verifier.h index 5a53a7b..c87b5c8c 100644 --- a/net/quic/core/crypto/proof_verifier.h +++ b/net/quic/core/crypto/proof_verifier.h
@@ -86,6 +86,26 @@ std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, std::unique_ptr<ProofVerifierCallback> callback) = 0; + + // VerifyCertChain checks that |certs| is a valid chain for |hostname|. On + // success, it returns QUIC_SUCCESS. On failure, it returns QUIC_FAILURE and + // sets |*error_details| to a description of the problem. In either case it + // may set |*details|, which the caller takes ownership of. + // + // |context| specifies an implementation specific struct (which may be nullptr + // for some implementations) that provides useful information for the + // verifier, e.g. logging handles. + // + // This function may also return QUIC_PENDING, in which case the ProofVerifier + // will call back, on the original thread, via |callback| when complete. + // In this case, the ProofVerifier will take ownership of |callback|. + virtual QuicAsyncStatus VerifyCertChain( + const std::string& hostname, + const std::vector<std::string>& certs, + const ProofVerifyContext* context, + std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* details, + std::unique_ptr<ProofVerifierCallback> callback) = 0; }; } // namespace net
diff --git a/net/quic/test_tools/quic_stream_factory_peer.cc b/net/quic/test_tools/quic_stream_factory_peer.cc index b3e4087..afeeb11 100644 --- a/net/quic/test_tools/quic_stream_factory_peer.cc +++ b/net/quic/test_tools/quic_stream_factory_peer.cc
@@ -7,11 +7,14 @@ #include <string> #include <vector> +#include "net/cert/x509_certificate.h" #include "net/quic/chromium/quic_chromium_client_session.h" #include "net/quic/chromium/quic_http_stream.h" #include "net/quic/chromium/quic_stream_factory.h" #include "net/quic/core/crypto/quic_crypto_client_config.h" #include "net/quic/core/quic_clock.h" +#include "net/test/cert_test_util.h" +#include "net/test/test_data_directory.h" using std::string; using std::vector; @@ -33,6 +36,12 @@ return factory->HasActiveSession(server_id); } +bool QuicStreamFactoryPeer::HasActiveCertVerifierJob( + QuicStreamFactory* factory, + const QuicServerId& server_id) { + return factory->HasActiveCertVerifierJob(server_id); +} + QuicChromiumClientSession* QuicStreamFactoryPeer::GetActiveSession( QuicStreamFactory* factory, const QuicServerId& server_id) { @@ -82,6 +91,25 @@ factory->delay_tcp_race_ = delay_tcp_race; } +bool QuicStreamFactoryPeer::GetRaceCertVerification( + QuicStreamFactory* factory) { + return factory->race_cert_verification_; +} + +void QuicStreamFactoryPeer::SetRaceCertVerification( + QuicStreamFactory* factory, + bool race_cert_verification) { + factory->race_cert_verification_ = race_cert_verification; +} + +QuicAsyncStatus QuicStreamFactoryPeer::StartCertVerifyJob( + QuicStreamFactory* factory, + const QuicServerId& server_id, + int cert_verify_flags, + const BoundNetLog& net_log) { + return factory->StartCertVerifyJob(server_id, cert_verify_flags, net_log); +} + void QuicStreamFactoryPeer::SetYieldAfterPackets(QuicStreamFactory* factory, int yield_after_packets) { factory->yield_after_packets_ = yield_after_packets; @@ -149,9 +177,15 @@ string server_config(reinterpret_cast<const char*>(&scfg), sizeof(scfg)); string source_address_token("test_source_address_token"); string signature("test_signature"); - string test_cert("test_cert"); + vector<string> certs; - certs.push_back(test_cert); + // Load a certificate that is valid for *.example.org + scoped_refptr<X509Certificate> cert( + ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem")); + DCHECK(cert); + std::string der_bytes; + DCHECK(X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_bytes)); + certs.push_back(der_bytes); QuicCryptoClientConfig* crypto_config = &factory->crypto_config_; QuicCryptoClientConfig::CachedState* cached = @@ -159,6 +193,7 @@ QuicClock clock; cached->Initialize(server_config, source_address_token, certs, "", "", signature, clock.WallNow()); + DCHECK(!cached->certs().empty()); } QuicClientPushPromiseIndex* QuicStreamFactoryPeer::GetPushPromiseIndex(
diff --git a/net/quic/test_tools/quic_stream_factory_peer.h b/net/quic/test_tools/quic_stream_factory_peer.h index a1832217..2ccdc04 100644 --- a/net/quic/test_tools/quic_stream_factory_peer.h +++ b/net/quic/test_tools/quic_stream_factory_peer.h
@@ -12,6 +12,7 @@ #include "base/task_runner.h" #include "net/base/host_port_pair.h" #include "net/base/privacy_mode.h" +#include "net/log/net_log.h" #include "net/quic/core/quic_protocol.h" #include "net/quic/core/quic_server_id.h" #include "net/quic/core/quic_time.h" @@ -36,6 +37,9 @@ static bool HasActiveSession(QuicStreamFactory* factory, const QuicServerId& server_id); + static bool HasActiveCertVerifierJob(QuicStreamFactory* factory, + const QuicServerId& server_id); + static QuicChromiumClientSession* GetActiveSession( QuicStreamFactory* factory, const QuicServerId& server_id); @@ -59,6 +63,16 @@ static void SetDelayTcpRace(QuicStreamFactory* factory, bool delay_tcp_race); + static bool GetRaceCertVerification(QuicStreamFactory* factory); + + static void SetRaceCertVerification(QuicStreamFactory* factory, + bool race_cert_verification); + + static QuicAsyncStatus StartCertVerifyJob(QuicStreamFactory* factory, + const QuicServerId& server_id, + int cert_verify_flags, + const BoundNetLog& net_log); + static void SetYieldAfterPackets(QuicStreamFactory* factory, int yield_after_packets);
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc index 59662bd6..3de46fa 100644 --- a/net/tools/quic/test_tools/quic_test_client.cc +++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -97,6 +97,16 @@ signature, context, error_details, details, std::move(callback)); } + QuicAsyncStatus VerifyCertChain( + const std::string& hostname, + const std::vector<std::string>& certs, + const ProofVerifyContext* verify_context, + std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* verify_details, + std::unique_ptr<ProofVerifierCallback> callback) override { + return QUIC_SUCCESS; + } + const string& common_name() const { return common_name_; } const string& cert_sct() const { return cert_sct_; }
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc index 8b9ba3a..8c8945cd 100644 --- a/net/url_request/url_request_context_builder.cc +++ b/net/url_request/url_request_context_builder.cc
@@ -196,7 +196,8 @@ quic_close_sessions_on_ip_change(false), quic_migrate_sessions_on_network_change(false), quic_migrate_sessions_early(false), - quic_disable_bidirectional_streams(false) {} + quic_disable_bidirectional_streams(false), + quic_race_cert_verification(false) {} URLRequestContextBuilder::HttpNetworkSessionParams::~HttpNetworkSessionParams() {} @@ -455,6 +456,8 @@ http_network_session_params_.quic_migrate_sessions_early; network_session_params.quic_disable_bidirectional_streams = http_network_session_params_.quic_disable_bidirectional_streams; + network_session_params.quic_race_cert_verification = + http_network_session_params_.quic_race_cert_verification; if (proxy_delegate_) { network_session_params.proxy_delegate = proxy_delegate_.get(); storage->set_proxy_delegate(std::move(proxy_delegate_));
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h index 813d85e..552b60a 100644 --- a/net/url_request/url_request_context_builder.h +++ b/net/url_request/url_request_context_builder.h
@@ -107,6 +107,7 @@ bool quic_migrate_sessions_on_network_change; bool quic_migrate_sessions_early; bool quic_disable_bidirectional_streams; + bool quic_race_cert_verification; }; URLRequestContextBuilder(); @@ -285,6 +286,11 @@ quic_disable_bidirectional_streams; } + void set_quic_race_cert_verification(bool quic_race_cert_verification) { + http_network_session_params_.quic_race_cert_verification = + quic_race_cert_verification; + } + void set_throttling_enabled(bool throttling_enabled) { throttling_enabled_ = throttling_enabled; }
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 1c76c47..24e0a1b 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1404,10 +1404,16 @@ crbug.com/619452 editing/spelling/inline-spelling-markers-hidpi-composited.html [ NeedsManualRebaseline ] crbug.com/630870 svg/animations/use-animate-width-and-height.html [ Skip ] - -crbug.com/541703 http/tests/security/xss-eval.html [ Skip ] - # Flaky on Win7 dbg and Mac10.11 (retina) crbug.com/634019 [ Win7 Debug Mac10.11 Retina ] virtual/asyncawait/inspector/sources/debugger-async/async-await/async-callstack-async-await1.html [ Pass Timeout ] crbug.com/634073 [ Win7 ] transforms/2d/hindi-rotated.html [ Pass Failure ] + +# This test breaks when the feature introduced in the bug is enabled. We keep +# this tested without the feature by using the virtual test. See +# virtual/stable/http/tests/navigation/beacon-cross-origin-redirect-blob-expected.txt +crbug.com/490015 http/tests/navigation/beacon-cross-origin-redirect-blob.html [ Skip ] +# This test doesn't need to be run with the stable release mode. +crbug.com/490015 virtual/stable/http/tests/navigation/beacon-blob-with-non-simple-type.html [ Skip ] +# This test fails with the stable release mode. +crbug.com/490015 virtual/stable/http/tests/navigation/same-and-different-back.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites index b846440..a73430f 100644 --- a/third_party/WebKit/LayoutTests/VirtualTestSuites +++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -69,6 +69,11 @@ }, { "prefix": "stable", + "base": "http/tests/navigation", + "args": ["--stable-release-mode"] + }, + { + "prefix": "stable", "base": "animations-unprefixed", "args": ["--stable-release-mode"] },
diff --git a/third_party/WebKit/LayoutTests/fast/dom/shadow/link-in-shadow-tree-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/shadow/link-in-shadow-tree-expected.txt deleted file mode 100644 index a482b58..0000000 --- a/third_party/WebKit/LayoutTests/fast/dom/shadow/link-in-shadow-tree-expected.txt +++ /dev/null
@@ -1,9 +0,0 @@ -CONSOLE WARNING: line 28: HTML element <link> is ignored in shadow tree. -PASS computedBackgroundColor(spanInShadow) is "rgba(0, 0, 0, 0)" -PASS computedBackgroundColor(spanInHostChildren) is "rgba(0, 0, 0, 0)" -PASS computedBackgroundColor(spanOutsideOfShadow) is "rgba(0, 0, 0, 0)" -PASS successfullyParsed is true - -TEST COMPLETE -tehepero -tehepero
diff --git a/third_party/WebKit/LayoutTests/fast/dom/shadow/link-in-shadow-tree.html b/third_party/WebKit/LayoutTests/fast/dom/shadow/link-in-shadow-tree.html deleted file mode 100644 index 343636a3..0000000 --- a/third_party/WebKit/LayoutTests/fast/dom/shadow/link-in-shadow-tree.html +++ /dev/null
@@ -1,42 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -</head> -<body> -<div id="container"><span id="in-host-children" class="kotori" href="/">tehepero</span></div> -<div><span id="outside-of-shadow" class="kotori" href="/">tehepero</span></div> - -<script src="../../../resources/js-test.js"></script> -<script> -function computedBackgroundColor(elem) { - var style = document.defaultView.getComputedStyle(elem, ''); - return style.backgroundColor; -} - -var container = document.getElementById('container'); - -var shadowRoot = container.createShadowRoot(); - -var link = document.createElement('link'); -link.setAttribute('rel', 'stylesheet'); -link.setAttribute('href', 'resources/link-in-shadow-style.css'); - -var spanInShadow = document.createElement('span'); -spanInShadow.innerHTML = 'tehepero'; -spanInShadow.className = 'kotori'; - -shadowRoot.appendChild(link); -shadowRoot.appendChild(spanInShadow); -shadowRoot.appendChild(document.createElement('content')); - -var spanInHostChildren = document.getElementById('in-host-children'); -var spanOutsideOfShadow = document.getElementById('outside-of-shadow'); - -shouldBe('computedBackgroundColor(spanInShadow)', '"rgba(0, 0, 0, 0)"'); -shouldBe('computedBackgroundColor(spanInHostChildren)', '"rgba(0, 0, 0, 0)"'); -shouldBe('computedBackgroundColor(spanOutsideOfShadow)', '"rgba(0, 0, 0, 0)"'); - -var successfullyParsed = true; -</script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/navigation/beacon-blob-with-non-simple-type.html b/third_party/WebKit/LayoutTests/http/tests/navigation/beacon-blob-with-non-simple-type.html new file mode 100644 index 0000000..04fad8f --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/navigation/beacon-blob-with-non-simple-type.html
@@ -0,0 +1,14 @@ +<!DOCTYPE HTML> +<script src="/js-test-resources/testharness.js"></script> +<script src="/js-test-resources/testharnessreport.js"></script> +<script> +test(() => { + assert_throws( + 'SecurityError', + () => { + navigator.sendBeacon("/", + new Blob(["X"], {type: "image/png"})); + }); +}, "navigator.sendBeacon() to a cross-origin target with a Blob body with " + + "non-simple type should throw."); +</script>
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/media/track/track-cue-rendering-horizontal-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/media/track/track-cue-rendering-horizontal-expected.png deleted file mode 100644 index c61f5361..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/media/track/track-cue-rendering-horizontal-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/media/track/track-cue-rendering-horizontal-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/media/track/track-cue-rendering-horizontal-expected.txt deleted file mode 100644 index 591c5fe..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/media/track/track-cue-rendering-horizontal-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x260 - LayoutBlockFlow {HTML} at (0,0) size 800x260 - LayoutBlockFlow {BODY} at (8,8) size 784x244 - LayoutText {#text} at (0,0) size 0x0 -layer at (8,8) size 320x240 - LayoutVideo {VIDEO} at (0,0) size 320x240 -layer at (8,8) size 320x240 - LayoutBlockFlow (relative positioned) {DIV} at (0,0) size 320x240 [color=#FFFFFF] -layer at (8,8) size 320x240 - LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x240 - LayoutBlockFlow {DIV} at (0,208) size 320x32 -layer at (8,8) size 320x198 - LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 320x198
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/link-title.html b/third_party/WebKit/LayoutTests/shadow-dom/link-title.html new file mode 100644 index 0000000..1e191c3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/shadow-dom/link-title.html
@@ -0,0 +1,44 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="resources/shadow-dom.js"></script> +<body> + <div id="host"> + <template mode-data="open"> + <link rel="stylesheet" title="preferred1" href="data:text/css,#shadowChild1 { color: green }"> + <link rel="stylesheet" title="title1" href="data:text/css,#shadowChild2 { color: green }"> + <link rel="alternate stylesheet" title="prefered1" href="data:text/css,#shadowChild3 { color: green }"> + <link rel="alternate stylesheet" title="title1" href="data:text/css,#shadowChild4 { color: green }"> + <div id="shadowChild1"></div> + <div id="shadowChild2"></div> + <div id="shadowChild3"></div> + <div id="shadowChild4"></div> + </template> + </div> + <div id="bodyChild1"></div> + <div id="bodyChild2"></div> + <script>convertTemplatesToShadowRootsWithin(host);</script> + <link rel="stylesheet" title="preferred1" href="data:text/css,#bodyChild1 { color: green }"> + <link rel="stylesheet" title="non-preferred" href="data:text/css,#bodyChild2 { color: green }"> +</body> +<script> +function colorFor(elem) { + return document.defaultView.getComputedStyle(elem, '').color; +} + +test(() => { + assert_equals(colorFor(bodyChild1), 'rgb(0, 128, 0)', 'A link in a shadow tree does not have any effect on the preferred stylesheet on a document tree.'); + assert_equals(colorFor(bodyChild2), 'rgb(0, 0, 0)', 'A non-preferred stylesheet should not be used.'); +}, '<link rel="stylesheet" title="xxx"> in a document tree should work without interference from a shadow tree.'); + +test(() => { + assert_equals(colorFor(host.shadowRoot.querySelector('#shadowChild1')), 'rgb(0, 128, 0)'); + assert_equals(colorFor(host.shadowRoot.querySelector('#shadowChild2')), 'rgb(0, 128, 0)'); +}, '<link rel="stylesheet" title="xxx"> shoule behave as <link rel="stylesheet"> (always enabled because title is ignored) in a connected shadow tree.'); + +test(() => { + assert_equals(colorFor(host.shadowRoot.querySelector('#shadowChild3')), 'rgb(0, 0, 0)'); + assert_equals(colorFor(host.shadowRoot.querySelector('#shadowChild4')), 'rgb(0, 0, 0)'); +}, '<link rel="alternate stylesheet" title="xxx"> shoule behave as <link rel="alternate stylesheet"> (never enabled because title is ignored) in a connected shadow tree.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/link.html b/third_party/WebKit/LayoutTests/shadow-dom/link.html new file mode 100644 index 0000000..487b68e --- /dev/null +++ b/third_party/WebKit/LayoutTests/shadow-dom/link.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<body> + <div id="host"></div> + <div id="bodyChild"></div> +</body> +<script> +function colorFor(elem) { + return document.defaultView.getComputedStyle(elem, '').color; +} + +async_test((test) => { + let link = document.createElement('link'); + link.setAttribute('rel', 'stylesheet'); + link.setAttribute('href', 'data:text/css,div { color: green }'); + link.addEventListener("load", test.step_func_done(() => { + assert_equals(colorFor(bodyChild), 'rgb(0, 0, 0)', 'An element in a document tree should not be styled.'); + assert_equals(colorFor(shadowChild), 'rgb(0, 128, 0)', 'An element in a shadow tree should be styled.'); + })); + let sr = host.attachShadow({ mode: 'open' }); + let shadowChild = document.createElement('div'); + sr.appendChild(shadowChild); + sr.appendChild(link); +}, '<link rel=stylesheet> should load a stylesheet in a connected shadow tree.'); +</script>
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/navigation/README.txt b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/navigation/README.txt new file mode 100644 index 0000000..5344067 --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/navigation/README.txt
@@ -0,0 +1,3 @@ +This directory contains expectations to keep the sendBeacon tested both for +the experimental web platform features flag turned on and off until +http://crbug.com/490015 is resolved.
diff --git a/third_party/WebKit/LayoutTests/http/tests/navigation/beacon-cross-origin-redirect-blob-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/navigation/beacon-cross-origin-redirect-blob-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/http/tests/navigation/beacon-cross-origin-redirect-blob-expected.txt rename to third_party/WebKit/LayoutTests/virtual/stable/http/tests/navigation/beacon-cross-origin-redirect-blob-expected.txt
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi index 58ebe536..b689e35 100644 --- a/third_party/WebKit/Source/core/core.gypi +++ b/third_party/WebKit/Source/core/core.gypi
@@ -1952,7 +1952,6 @@ 'loader/TextTrackLoader.h', 'loader/ThreadableLoader.cpp', 'loader/ThreadableLoaderClient.h', - 'loader/ThreadableLoaderClientWrapper.h', 'loader/WorkerThreadableLoader.cpp', 'loader/WorkerThreadableLoader.h', 'loader/appcache/ApplicationCache.cpp',
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp index 3e86c474..cb25b3e 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp +++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -227,10 +227,10 @@ void StyleResolver::appendCSSStyleSheet(CSSStyleSheet& cssSheet) { - ASSERT(!cssSheet.disabled()); - ASSERT(cssSheet.ownerDocument()); - ASSERT(cssSheet.ownerNode()); - ASSERT(isHTMLStyleElement(cssSheet.ownerNode()) || isSVGStyleElement(cssSheet.ownerNode()) || cssSheet.ownerNode()->treeScope() == cssSheet.ownerDocument()); + DCHECK(!cssSheet.disabled()); + DCHECK(cssSheet.ownerDocument()); + DCHECK(cssSheet.ownerNode()); + DCHECK(isHTMLStyleElement(cssSheet.ownerNode()) || isSVGStyleElement(cssSheet.ownerNode()) || cssSheet.ownerNode()->isConnected()); if (cssSheet.mediaQueries() && !m_medium->eval(cssSheet.mediaQueries(), &m_viewportDependentMediaQueryResults, &m_deviceDependentMediaQueryResults)) return;
diff --git a/third_party/WebKit/Source/core/dom/ShadowTreeStyleSheetCollection.cpp b/third_party/WebKit/Source/core/dom/ShadowTreeStyleSheetCollection.cpp index 31aabc7..b244565 100644 --- a/third_party/WebKit/Source/core/dom/ShadowTreeStyleSheetCollection.cpp +++ b/third_party/WebKit/Source/core/dom/ShadowTreeStyleSheetCollection.cpp
@@ -51,9 +51,6 @@ StyleSheetCandidate candidate(*n); DCHECK(!candidate.isXSL()); - if (!candidate.isCSSStyle()) - continue; - StyleSheet* sheet = candidate.sheet(); if (!sheet) continue;
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/third_party/WebKit/Source/core/dom/StyleEngine.cpp index a5fb3f8..a15af6c 100644 --- a/third_party/WebKit/Source/core/dom/StyleEngine.cpp +++ b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
@@ -191,8 +191,8 @@ if (!node->isConnected() || document().isDetached()) return; - TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_document; DCHECK(!isXSLStyleSheet(*node)); + TreeScope& treeScope = node->treeScope(); TreeScopeStyleSheetCollection* collection = ensureStyleSheetCollectionFor(treeScope); DCHECK(collection); collection->addStyleSheetCandidateNode(node);
diff --git a/third_party/WebKit/Source/core/dom/StyleSheetCandidate.cpp b/third_party/WebKit/Source/core/dom/StyleSheetCandidate.cpp index e2f7b23..d1a15e4 100644 --- a/third_party/WebKit/Source/core/dom/StyleSheetCandidate.cpp +++ b/third_party/WebKit/Source/core/dom/StyleSheetCandidate.cpp
@@ -88,8 +88,12 @@ if (!sheet || sheet->disabled() || !sheet->isCSSStyleSheet()) return false; - if (sheet->ownerNode() && sheet->ownerNode()->isInShadowTree()) - return true; + if (sheet->ownerNode() && sheet->ownerNode()->isInShadowTree()) { + if (isCSSStyle()) + return true; + if (isHTMLLink() && !isImport()) + return !isAlternate(); + } const AtomicString& title = this->title(); if (!isEnabledViaScript() && !title.isEmpty() && title != currentPreferrableName)
diff --git a/third_party/WebKit/Source/core/fetch/FetchUtils.cpp b/third_party/WebKit/Source/core/fetch/FetchUtils.cpp index d199685..566de16 100644 --- a/third_party/WebKit/Source/core/fetch/FetchUtils.cpp +++ b/third_party/WebKit/Source/core/fetch/FetchUtils.cpp
@@ -105,16 +105,20 @@ || equalIgnoringCase(name, "save-data")) return true; - if (equalIgnoringCase(name, "content-type")) { - AtomicString mimeType = extractMIMETypeFromMediaType(value); - return equalIgnoringCase(mimeType, "application/x-www-form-urlencoded") - || equalIgnoringCase(mimeType, "multipart/form-data") - || equalIgnoringCase(mimeType, "text/plain"); - } + if (equalIgnoringCase(name, "content-type")) + return isSimpleContentType(value); return false; } +bool FetchUtils::isSimpleContentType(const AtomicString& mediaType) +{ + AtomicString mimeType = extractMIMETypeFromMediaType(mediaType); + return equalIgnoringCase(mimeType, "application/x-www-form-urlencoded") + || equalIgnoringCase(mimeType, "multipart/form-data") + || equalIgnoringCase(mimeType, "text/plain"); +} + bool FetchUtils::isSimpleRequest(const String& method, const HTTPHeaderMap& headerMap) { if (!isSimpleMethod(method))
diff --git a/third_party/WebKit/Source/core/fetch/FetchUtils.h b/third_party/WebKit/Source/core/fetch/FetchUtils.h index c2ff2e4c..b9f99c11 100644 --- a/third_party/WebKit/Source/core/fetch/FetchUtils.h +++ b/third_party/WebKit/Source/core/fetch/FetchUtils.h
@@ -18,6 +18,7 @@ public: static bool isSimpleMethod(const String& method); static bool isSimpleHeader(const AtomicString& name, const AtomicString& value); + static bool isSimpleContentType(const AtomicString& mediaType); static bool isSimpleRequest(const String& method, const HTTPHeaderMap&); static bool isForbiddenMethod(const String& method); static bool isUsefulMethod(const String& method) { return !isForbiddenMethod(method); }
diff --git a/third_party/WebKit/Source/core/fileapi/FileReaderLoader.h b/third_party/WebKit/Source/core/fileapi/FileReaderLoader.h index c1ab823..be30c0d 100644 --- a/third_party/WebKit/Source/core/fileapi/FileReaderLoader.h +++ b/third_party/WebKit/Source/core/fileapi/FileReaderLoader.h
@@ -34,6 +34,7 @@ #include "core/CoreExport.h" #include "core/fileapi/FileError.h" #include "core/loader/ThreadableLoaderClient.h" +#include "platform/heap/Handle.h" #include "platform/weborigin/KURL.h" #include "wtf/Forward.h" #include "wtf/PtrUtil.h" @@ -69,7 +70,6 @@ return wrapUnique(new FileReaderLoader(readType, client)); } - FileReaderLoader(ReadType, FileReaderLoaderClient*); ~FileReaderLoader() override; void start(ExecutionContext*, PassRefPtr<BlobDataHandle>); @@ -106,6 +106,8 @@ void setDataType(const String& dataType) { m_dataType = dataType; } private: + FileReaderLoader(ReadType, FileReaderLoaderClient*); + void startInternal(ExecutionContext&, const Stream*, PassRefPtr<BlobDataHandle>); void cleanup(); @@ -122,7 +124,7 @@ KURL m_urlForReading; bool m_urlForReadingIsStream; - std::unique_ptr<ThreadableLoader> m_loader; + Persistent<ThreadableLoader> m_loader; std::unique_ptr<ArrayBufferBuilder> m_rawData; bool m_isRawDataConverted;
diff --git a/third_party/WebKit/Source/core/fileapi/FileReaderSync.cpp b/third_party/WebKit/Source/core/fileapi/FileReaderSync.cpp index 09aaa19..efee518 100644 --- a/third_party/WebKit/Source/core/fileapi/FileReaderSync.cpp +++ b/third_party/WebKit/Source/core/fileapi/FileReaderSync.cpp
@@ -46,39 +46,39 @@ { ASSERT(blob); - FileReaderLoader loader(FileReaderLoader::ReadAsArrayBuffer, nullptr); - startLoading(executionContext, loader, *blob, exceptionState); + std::unique_ptr<FileReaderLoader> loader = FileReaderLoader::create(FileReaderLoader::ReadAsArrayBuffer, nullptr); + startLoading(executionContext, *loader, *blob, exceptionState); - return loader.arrayBufferResult(); + return loader->arrayBufferResult(); } String FileReaderSync::readAsBinaryString(ExecutionContext* executionContext, Blob* blob, ExceptionState& exceptionState) { ASSERT(blob); - FileReaderLoader loader(FileReaderLoader::ReadAsBinaryString, 0); - startLoading(executionContext, loader, *blob, exceptionState); - return loader.stringResult(); + std::unique_ptr<FileReaderLoader> loader = FileReaderLoader::create(FileReaderLoader::ReadAsBinaryString, nullptr); + startLoading(executionContext, *loader, *blob, exceptionState); + return loader->stringResult(); } String FileReaderSync::readAsText(ExecutionContext* executionContext, Blob* blob, const String& encoding, ExceptionState& exceptionState) { ASSERT(blob); - FileReaderLoader loader(FileReaderLoader::ReadAsText, nullptr); - loader.setEncoding(encoding); - startLoading(executionContext, loader, *blob, exceptionState); - return loader.stringResult(); + std::unique_ptr<FileReaderLoader> loader = FileReaderLoader::create(FileReaderLoader::ReadAsText, nullptr); + loader->setEncoding(encoding); + startLoading(executionContext, *loader, *blob, exceptionState); + return loader->stringResult(); } String FileReaderSync::readAsDataURL(ExecutionContext* executionContext, Blob* blob, ExceptionState& exceptionState) { ASSERT(blob); - FileReaderLoader loader(FileReaderLoader::ReadAsDataURL, nullptr); - loader.setDataType(blob->type()); - startLoading(executionContext, loader, *blob, exceptionState); - return loader.stringResult(); + std::unique_ptr<FileReaderLoader> loader = FileReaderLoader::create(FileReaderLoader::ReadAsDataURL, nullptr); + loader->setDataType(blob->type()); + startLoading(executionContext, *loader, *blob, exceptionState); + return loader->stringResult(); } void FileReaderSync::startLoading(ExecutionContext* executionContext, FileReaderLoader& loader, const Blob& blob, ExceptionState& exceptionState)
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp index 4784dd74..deba6ab 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.cpp +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -373,12 +373,6 @@ void FrameView::invalidateRect(const IntRect& rect) { - if (!parent()) { - if (HostWindow* window = getHostWindow()) - window->invalidateRect(rect); - return; - } - LayoutPartItem layoutItem = m_frame->ownerLayoutItem(); if (layoutItem.isNull()) return; @@ -1462,7 +1456,7 @@ return true; } -void FrameView::scrollContentsSlowPath(const IntRect& updateRect) +void FrameView::scrollContentsSlowPath() { TRACE_EVENT0("blink", "FrameView::scrollContentsSlowPath"); // We need full invalidation during slow scrolling. For slimming paint, full invalidation @@ -1493,8 +1487,6 @@ return; } } - - getHostWindow()->invalidateRect(updateRect); } void FrameView::restoreScrollbar() @@ -2186,15 +2178,6 @@ } } -IntRect FrameView::windowClipRect(IncludeScrollbarsInRect scrollbarInclusion) const -{ - ASSERT(m_frame->view() == this); - - LayoutRect clipRect(LayoutPoint(), LayoutSize(visibleContentSize(scrollbarInclusion))); - layoutViewItem().mapToVisualRectInAncestorSpace(&layoutView()->containerForPaintInvalidation(), clipRect); - return enclosingIntRect(clipRect); -} - bool FrameView::shouldUseIntegerScrollOffset() const { if (m_frame->settings() && !m_frame->settings()->preferCompositingToLCDTextEnabled()) @@ -3660,19 +3643,6 @@ } } -IntRect FrameView::rectToCopyOnScroll() const -{ - IntRect scrollViewRect = convertToRootFrame(IntRect((shouldPlaceVerticalScrollbarOnLeft() && verticalScrollbar()) ? verticalScrollbar()->width() : 0, 0, visibleWidth(), visibleHeight())); - if (hasOverlayScrollbars()) { - int verticalScrollbarWidth = (verticalScrollbar() && !hasLayerForVerticalScrollbar()) ? verticalScrollbar()->width() : 0; - int horizontalScrollbarHeight = (horizontalScrollbar() && !hasLayerForHorizontalScrollbar()) ? horizontalScrollbar()->height() : 0; - - scrollViewRect.setWidth(scrollViewRect.width() - verticalScrollbarWidth); - scrollViewRect.setHeight(scrollViewRect.height() - horizontalScrollbarHeight); - } - return scrollViewRect; -} - void FrameView::scrollContentsIfNeeded() { if (m_pendingScrollDelta.isZero()) @@ -3691,12 +3661,8 @@ TRACE_EVENT0("blink", "FrameView::scrollContents"); - IntRect clipRect = windowClipRect(); - IntRect updateRect = clipRect; - updateRect.intersect(rectToCopyOnScroll()); - if (!scrollContentsFastPath(-scrollDelta)) - scrollContentsSlowPath(updateRect); + scrollContentsSlowPath(); // This call will move children with native widgets (plugins) and invalidate them as well. frameRectsChanged();
diff --git a/third_party/WebKit/Source/core/frame/FrameView.h b/third_party/WebKit/Source/core/frame/FrameView.h index 2087bfe..9511bd3 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.h +++ b/third_party/WebKit/Source/core/frame/FrameView.h
@@ -405,9 +405,6 @@ // host window in the window's coordinate space. HostWindow* getHostWindow() const; - // Returns a clip rect in host window coordinates. Used to clip the blit on a scroll. - IntRect windowClipRect(IncludeScrollbarsInRect = ExcludeScrollbars) const; - typedef HeapHashSet<Member<Widget>> ChildrenWidgetSet; // Functions for child manipulation and inspection. @@ -627,7 +624,7 @@ bool scrollContentsFastPath(const IntSize& scrollDelta); // Scroll the content by invalidating everything. - void scrollContentsSlowPath(const IntRect& updateRect); + void scrollContentsSlowPath(); // These functions are used to create/destroy scrollbars. void setHasHorizontalScrollbar(bool); @@ -757,8 +754,6 @@ void adjustScrollPositionFromUpdateScrollbars(); bool visualViewportSuppliesScrollbars() const; - IntRect rectToCopyOnScroll() const; - bool isFrameViewScrollbar(const Widget* child) const { return horizontalScrollbar() == child || verticalScrollbar() == child; } ScrollingCoordinator* scrollingCoordinator() const;
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp index 5e5e2dd8..c8864ba 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -356,8 +356,7 @@ void LocalFrame::reload(FrameLoadType loadType, ClientRedirectPolicy clientRedirectPolicy) { - ASSERT(loadType == FrameLoadTypeReload || loadType == FrameLoadTypeReloadBypassingCache); - ASSERT(clientRedirectPolicy == ClientRedirectPolicy::NotClientRedirect || loadType == FrameLoadTypeReload); + DCHECK(isReloadLoadType(loadType)); if (clientRedirectPolicy == ClientRedirectPolicy::NotClientRedirect) { if (!m_loader.currentItem()) return; @@ -366,6 +365,7 @@ request.setClientRedirect(clientRedirectPolicy); m_loader.load(request, loadType); } else { + DCHECK_EQ(FrameLoadTypeReload, loadType); m_navigationScheduler->scheduleReload(); } }
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h index a41064e3..be04cc78 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.h +++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -1286,6 +1286,7 @@ MultipleOriginsInTimingAllowOrigin = 1482, StarInTimingAllowOrigin = 1483, SVGSMILAdditiveAnimation = 1484, + SendBeaconWithNonSimpleContentType = 1485, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp index 4427d83..5a9d71f 100644 --- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
@@ -133,7 +133,7 @@ bool HTMLLinkElement::shouldLoadLink() { - return isConnected(); + return isInDocumentTree() || (isConnected() && m_relAttribute.isStyleSheet()); } bool HTMLLinkElement::loadLink(const String& type, const String& as, const String& media, const KURL& url) @@ -143,8 +143,7 @@ LinkResource* HTMLLinkElement::linkResourceToProcess() { - bool visible = isConnected() && !isInShadowTree(); - if (!visible) { + if (!shouldLoadLink()) { ASSERT(!linkStyle() || !linkStyle()->hasSheet()); return nullptr; } @@ -203,8 +202,9 @@ logAddElementIfIsolatedWorldAndInDocument("link", relAttr, hrefAttr); if (!insertionPoint->isConnected()) return InsertionDone; - - if (isInShadowTree()) { + DCHECK(isConnected()); + if (!shouldLoadLink()) { + DCHECK(isInShadowTree()); String message = "HTML element <link> is ignored in shadow tree."; document().addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); return InsertionDone; @@ -222,15 +222,15 @@ void HTMLLinkElement::removedFrom(ContainerNode* insertionPoint) { - // Store the result of isInShadowTree() here before Node::removedFrom(..) clears the flags. - bool wasInShadowTree = isInShadowTree(); + // Store the result of isConnected() here before Node::removedFrom(..) clears the flags. + bool wasConnected = isConnected(); HTMLElement::removedFrom(insertionPoint); if (!insertionPoint->isConnected()) return; m_linkLoader->released(); - if (wasInShadowTree) { + if (!wasConnected) { ASSERT(!linkStyle() || !linkStyle()->hasSheet()); return; } @@ -440,8 +440,8 @@ void LinkStyle::setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource* cachedStyleSheet) { - if (!m_owner->isInDocumentTree()) { - // While the stylesheet is asynchronously loading, the owner can be moved out of a document tree. + if (!m_owner->isConnected()) { + // While the stylesheet is asynchronously loading, the owner can be disconnected from a document. // In that case, cancel any processing on the loaded content. m_loading = false; removePendingSheet(); @@ -658,7 +658,7 @@ m_loading = true; String title = m_owner->title(); - if (!title.isEmpty() && !m_owner->isAlternate() && m_disabledState != EnabledViaScript) + if (!title.isEmpty() && !m_owner->isAlternate() && m_disabledState != EnabledViaScript && m_owner->isInDocumentTree()) document().styleEngine().setPreferredStylesheetSetNameIfNotSet(title); bool mediaQueryMatches = true;
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp index 3e592171..9087a88 100644 --- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp +++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
@@ -167,7 +167,7 @@ } ImageBitmapFactories::ImageBitmapLoader::ImageBitmapLoader(ImageBitmapFactories& factory, Optional<IntRect> cropRect, ScriptState* scriptState, const ImageBitmapOptions& options) - : m_loader(FileReaderLoader::ReadAsArrayBuffer, this) + : m_loader(FileReaderLoader::create(FileReaderLoader::ReadAsArrayBuffer, this)) , m_factory(&factory) , m_resolver(ScriptPromiseResolver::create(scriptState)) , m_cropRect(cropRect) @@ -177,7 +177,7 @@ void ImageBitmapFactories::ImageBitmapLoader::loadBlobAsync(ExecutionContext* context, Blob* blob) { - m_loader.start(context, blob->blobDataHandle()); + m_loader->start(context, blob->blobDataHandle()); } DEFINE_TRACE(ImageBitmapFactories) @@ -195,7 +195,7 @@ void ImageBitmapFactories::ImageBitmapLoader::didFinishLoading() { - DOMArrayBuffer* arrayBuffer = m_loader.arrayBufferResult(); + DOMArrayBuffer* arrayBuffer = m_loader->arrayBufferResult(); if (!arrayBuffer) { rejectPromise(); return;
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h index de3f72a..119e3df 100644 --- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h +++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h
@@ -40,6 +40,7 @@ #include "core/imagebitmap/ImageBitmapOptions.h" #include "platform/Supplementable.h" #include "platform/geometry/IntRect.h" +#include <memory> class SkImage; @@ -101,7 +102,7 @@ void didFinishLoading() override; void didFail(FileError::ErrorCode) override; - FileReaderLoader m_loader; + std::unique_ptr<FileReaderLoader> m_loader; Member<ImageBitmapFactories> m_factory; Member<ScriptPromiseResolver> m_resolver; Optional<IntRect> m_cropRect;
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp index 6f3bc3f..33ebc16 100644 --- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp +++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
@@ -126,14 +126,12 @@ void DocumentThreadableLoader::loadResourceSynchronously(Document& document, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOptions) { - // The loader will be deleted as soon as this function exits. - std::unique_ptr<DocumentThreadableLoader> loader = wrapUnique(new DocumentThreadableLoader(document, &client, LoadSynchronously, options, resourceLoaderOptions)); - loader->start(request); + (new DocumentThreadableLoader(document, &client, LoadSynchronously, options, resourceLoaderOptions))->start(request); } -std::unique_ptr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document& document, ThreadableLoaderClient* client, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOptions) +DocumentThreadableLoader* DocumentThreadableLoader::create(Document& document, ThreadableLoaderClient* client, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOptions) { - return wrapUnique(new DocumentThreadableLoader(document, client, LoadAsynchronously, options, resourceLoaderOptions)); + return new DocumentThreadableLoader(document, client, LoadAsynchronously, options, resourceLoaderOptions); } DocumentThreadableLoader::DocumentThreadableLoader(Document& document, ThreadableLoaderClient* client, BlockingBehavior blockingBehavior, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOptions) @@ -172,7 +170,6 @@ ThreadableLoaderClient* client = m_client; clear(); client->didFail(ResourceError(errorDomainBlinkInternal, 0, request.url().getString(), "Cross origin requests are not supported.")); - // |this| may be dead here. return; } @@ -253,26 +250,22 @@ m_fallbackRequestForServiceWorker.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::Controlling); } loadRequest(newRequest, m_resourceLoaderOptions); - // |this| may be dead here. return; } dispatchInitialRequest(newRequest); - // |this| may be dead here in async mode. } void DocumentThreadableLoader::dispatchInitialRequest(const ResourceRequest& request) { if (!request.isExternalRequest() && (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests)) { loadRequest(request, m_resourceLoaderOptions); - // |this| may be dead here in async mode. return; } ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl || request.isExternalRequest()); makeCrossOriginAccessRequest(request); - // |this| may be dead here in async mode. } void DocumentThreadableLoader::makeCrossOriginAccessRequest(const ResourceRequest& request) @@ -290,7 +283,6 @@ ThreadableLoaderClient* client = m_client; clear(); client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, request.url().getString(), "Cross origin requests are only supported for protocol schemes: " + SchemeRegistry::listOfCORSEnabledURLSchemes() + ".")); - // |this| may be dead here in async mode. return; } @@ -299,7 +291,6 @@ ThreadableLoaderClient* client = m_client; clear(); client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, request.url().getString(), "Requests to internal network resources are not allowed from non-secure contexts (see https://goo.gl/Y0ZkNV). This is an experimental restriction which is part of 'https://mikewest.github.io/cors-rfc1918/'.")); - // |this| may be dead here in async mode. return; } @@ -319,7 +310,6 @@ crossOriginRequest.setHTTPReferrer(SecurityPolicy::generateReferrer(m_referrerAfterRedirect.referrerPolicy, crossOriginRequest.url(), m_referrerAfterRedirect.referrer)); } loadRequest(crossOriginRequest, crossOriginOptions); - // |this| may be dead here in async mode. } else { m_crossOriginNonSimpleRequest = true; // Do not set the Origin header for preflight requests. @@ -338,14 +328,12 @@ bool canSkipPreflight = CrossOriginPreflightResultCache::shared().canSkipPreflight(getSecurityOrigin()->toString(), m_actualRequest.url(), effectiveAllowCredentials(), m_actualRequest.httpMethod(), m_actualRequest.httpHeaderFields()); if (canSkipPreflight && !shouldForcePreflight) { loadActualRequest(); - // |this| may be dead here in async mode. } else { ResourceRequest preflightRequest = createAccessControlPreflightRequest(m_actualRequest, getSecurityOrigin()); // Create a ResourceLoaderOptions for preflight. ResourceLoaderOptions preflightOptions = m_actualOptions; preflightOptions.allowCredentials = DoNotAllowStoredCredentials; loadRequest(preflightRequest, preflightOptions); - // |this| may be dead here in async mode. } } } @@ -353,9 +341,7 @@ DocumentThreadableLoader::~DocumentThreadableLoader() { CHECK(!m_client); - - // TODO(oilpan): Remove this once DocumentThreadableLoader is once again a ResourceOwner. - clearResource(); + DCHECK(!m_resource); } void DocumentThreadableLoader::overrideTimeout(unsigned long timeoutMilliseconds) @@ -387,7 +373,6 @@ void DocumentThreadableLoader::cancel() { cancelWithError(ResourceError()); - // |this| may be dead here. } void DocumentThreadableLoader::cancelWithError(const ResourceError& error) @@ -408,7 +393,6 @@ ThreadableLoaderClient* client = m_client; clear(); client->didFail(errorForCallback); - // |this| may be dead here in async mode. } void DocumentThreadableLoader::setDefersLoading(bool value) @@ -420,10 +404,6 @@ void DocumentThreadableLoader::clear() { m_client = nullptr; - - if (!m_async) - return; - m_timeoutTimer.stop(); m_requestStartedSeconds = 0.0; clearResource(); @@ -445,7 +425,6 @@ reportResponseReceived(resource->identifier(), redirectResponse); handlePreflightFailure(redirectResponse.url().getString(), "Response for preflight is invalid (redirect)"); - // |this| may be dead here. request = ResourceRequest(); @@ -488,7 +467,6 @@ ThreadableLoaderClient* client = m_client; clear(); client->didFailRedirectCheck(); - // |this| may be dead here. request = ResourceRequest(); @@ -506,10 +484,7 @@ ThreadableLoaderClient* client = m_client; clear(); client->didFailRedirectCheck(); - // |this| may be dead here. - request = ResourceRequest(); - return; } @@ -538,10 +513,7 @@ ThreadableLoaderClient* client = m_client; clear(); client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, redirectResponse.url().getString(), accessControlErrorDescription)); - // |this| may be dead here. - request = ResourceRequest(); - return; } @@ -587,7 +559,6 @@ ThreadableLoaderClient* client = m_client; clear(); client->didFailRedirectCheck(); - // |this| may be dead here } void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) @@ -597,7 +568,6 @@ ASSERT(m_async); m_client->didSendData(bytesSent, totalBytesToBeSent); - // |this| may be dead here. } void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength) @@ -608,7 +578,6 @@ ASSERT(m_async); m_client->didDownloadData(dataLength); - // |this| may be dead here. } void DocumentThreadableLoader::didReceiveResourceTiming(Resource* resource, const ResourceTimingInfo& info) @@ -618,7 +587,6 @@ ASSERT(m_async); m_client->didReceiveResourceTiming(info); - // |this| may be dead here. } void DocumentThreadableLoader::responseReceived(Resource* resource, const ResourceResponse& response, std::unique_ptr<WebDataConsumerHandle> handle) @@ -630,7 +598,6 @@ m_isUsingDataConsumerHandle = true; handleResponse(resource->identifier(), response, std::move(handle)); - // |this| may be dead here. } void DocumentThreadableLoader::handlePreflightResponse(const ResourceResponse& response) @@ -639,19 +606,16 @@ if (!passesAccessControlCheck(response, effectiveAllowCredentials(), getSecurityOrigin(), accessControlErrorDescription, m_requestContext)) { handlePreflightFailure(response.url().getString(), "Response to preflight request doesn't pass access control check: " + accessControlErrorDescription); - // |this| may be dead here in async mode. return; } if (!passesPreflightStatusCheck(response, accessControlErrorDescription)) { handlePreflightFailure(response.url().getString(), accessControlErrorDescription); - // |this| may be dead here in async mode. return; } if (m_actualRequest.isExternalRequest() && !passesExternalPreflightCheck(response, accessControlErrorDescription)) { handlePreflightFailure(response.url().getString(), accessControlErrorDescription); - // |this| may be dead here in async mode. return; } @@ -660,7 +624,6 @@ || !preflightResult->allowsCrossOriginMethod(m_actualRequest.httpMethod(), accessControlErrorDescription) || !preflightResult->allowsCrossOriginHeaders(m_actualRequest.httpHeaderFields(), accessControlErrorDescription)) { handlePreflightFailure(response.url().getString(), accessControlErrorDescription); - // |this| may be dead here in async mode. return; } @@ -688,7 +651,6 @@ if (!m_actualRequest.isNull()) { reportResponseReceived(identifier, response); handlePreflightResponse(response); - // |this| may be dead here in async mode. return; } @@ -701,7 +663,6 @@ ASSERT(!m_fallbackRequestForServiceWorker.isNull()); reportResponseReceived(identifier, response); loadFallbackRequestForServiceWorker(); - // |this| may be dead here in async mode. return; } m_fallbackRequestForServiceWorker = ResourceRequest(); @@ -729,7 +690,6 @@ ThreadableLoaderClient* client = m_client; clear(); client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, response.url().getString(), accessControlErrorDescription)); - // |this| may be dead here. return; } } @@ -742,7 +702,6 @@ if (!m_actualRequest.isNull()) return; m_client->didReceiveCachedMetadata(data, size); - // |this| may be dead here. } void DocumentThreadableLoader::dataReceived(Resource* resource, const char* data, size_t dataLength) @@ -756,7 +715,6 @@ // TODO(junov): Fix the ThreadableLoader ecosystem to use size_t. // Until then, we use safeCast to trap potential overflows. handleReceivedData(data, safeCast<unsigned>(dataLength)); - // |this| may be dead here. } void DocumentThreadableLoader::handleReceivedData(const char* data, size_t dataLength) @@ -770,7 +728,6 @@ ASSERT(m_fallbackRequestForServiceWorker.isNull()); m_client->didReceiveData(data, dataLength); - // |this| may be dead here in async mode. } void DocumentThreadableLoader::notifyFinished(Resource* resource) @@ -781,10 +738,8 @@ if (resource->errorOccurred()) { handleError(resource->resourceError()); - // |this| may be dead here. } else { handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime()); - // |this| may be dead here. } } @@ -799,20 +754,15 @@ ASSERT(!m_sameOriginRequest); ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); loadActualRequest(); - // |this| may be dead here in async mode. return; } ThreadableLoaderClient* client = m_client; - m_client = nullptr; - // Don't clear the resource as the client may need to access the downloaded - // file which will be released when the resource is destoryed. - if (m_async) { - m_timeoutTimer.stop(); - m_requestStartedSeconds = 0.0; - } + // Protect the resource in |didFinishLoading| in order not to release the + // downloaded file. + Persistent<Resource> protect = resource(); + clear(); client->didFinishLoading(identifier, finishTime); - // |this| may be dead here in async mode. } void DocumentThreadableLoader::didTimeout(TimerBase* timer) @@ -825,7 +775,6 @@ ResourceError error("net", timeoutError, resource()->url(), String()); error.setIsTimeout(true); cancelWithError(error); - // |this| may be dead here. } void DocumentThreadableLoader::loadFallbackRequestForServiceWorker() @@ -834,7 +783,6 @@ ResourceRequest fallbackRequest(m_fallbackRequestForServiceWorker); m_fallbackRequestForServiceWorker = ResourceRequest(); dispatchInitialRequest(fallbackRequest); - // |this| may be dead here in async mode. } void DocumentThreadableLoader::loadActualRequest() @@ -855,7 +803,6 @@ actualRequest.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All); loadRequest(actualRequest, actualOptions); - // |this| may be dead here in async mode. } void DocumentThreadableLoader::handlePreflightFailure(const String& url, const String& errorDescription) @@ -868,7 +815,6 @@ ThreadableLoaderClient* client = m_client; clear(); client->didFailAccessControlCheck(error); - // |this| may be dead here in async mode. } void DocumentThreadableLoader::handleError(const ResourceError& error) @@ -881,7 +827,6 @@ ThreadableLoaderClient* client = m_client; clear(); client->didFail(copiedError); - // |this| may be dead here. } void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, ResourceLoaderOptions resourceLoaderOptions) @@ -917,7 +862,6 @@ setResource(RawResource::fetch(newRequest, document().fetcher())); // setResource() might call notifyFinished() synchronously, and thus - // clear() might be called and |this| may be dead here. if (!self) return; @@ -931,7 +875,6 @@ if (!client) return; client->didFail(ResourceError(errorDomainBlinkInternal, 0, requestURL.getString(), "Failed to start loading.")); - // |this| may be dead here. return; } @@ -1026,4 +969,11 @@ return *m_document; } +DEFINE_TRACE(DocumentThreadableLoader) +{ + visitor->trace(m_resource); + visitor->trace(m_document); + ThreadableLoader::trace(visitor); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h index 1cb373d..227541b 100644 --- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h +++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h
@@ -55,10 +55,9 @@ class ThreadableLoaderClient; class CORE_EXPORT DocumentThreadableLoader final : public ThreadableLoader, private RawResourceClient { - USING_FAST_MALLOC(DocumentThreadableLoader); public: static void loadResourceSynchronously(Document&, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&, const ResourceLoaderOptions&); - static std::unique_ptr<DocumentThreadableLoader> create(Document&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&); + static DocumentThreadableLoader* create(Document&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&); ~DocumentThreadableLoader() override; void start(const ResourceRequest&) override; @@ -69,6 +68,8 @@ void cancel() override; void setDefersLoading(bool); + DECLARE_TRACE(); + private: enum BlockingBehavior { LoadSynchronously, @@ -169,14 +170,14 @@ m_resource->addClient(this); } } - Persistent<RawResource> m_resource; + Member<RawResource> m_resource; // End of ResourceOwner re-implementation, see above. SecurityOrigin* getSecurityOrigin() const; Document& document() const; ThreadableLoaderClient* m_client; - WeakPersistent<Document> m_document; + Member<Document> m_document; const ThreadableLoaderOptions m_options; // Some items may be overridden by m_forceDoNotAllowStoredCredentials
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp index ebfae33..79e12d4d 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -119,8 +119,7 @@ // recover if blocking of a script is leading to a page break and the user // reloads the page. const FrameLoadType loadType = document.frame()->loader().loadType(); - const bool isReload = loadType == FrameLoadTypeReload || loadType == FrameLoadTypeReloadBypassingCache || loadType == FrameLoadTypeReloadMainResource; - if (isReload) { + if (isReloadLoadType(loadType)) { // Recording this metric since an increase in number of reloads for pages // where a script was blocked could be indicative of a page break. document.loader()->didObserveLoadingBehavior(WebLoadingBehaviorFlag::WebLoadingBehaviorDocumentWriteBlockReload);
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp index d7635f44..f0076ae8 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp +++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -110,12 +110,23 @@ bool isBackForwardLoadType(FrameLoadType type) { - return type == FrameLoadTypeBackForward || type == FrameLoadTypeInitialHistoryLoad; + return type == FrameLoadTypeBackForward + || type == FrameLoadTypeInitialHistoryLoad; +} + +bool isReloadLoadType(FrameLoadType type) +{ + return type == FrameLoadTypeReload + || type == FrameLoadTypeReloadMainResource + || type == FrameLoadTypeReloadBypassingCache; } static bool needsHistoryItemRestore(FrameLoadType type) { - return type == FrameLoadTypeBackForward || type == FrameLoadTypeReload + // TODO(toyoshim): Check if this should return true for + // FrameLoadTypeReloadMainResource. + return type == FrameLoadTypeBackForward + || type == FrameLoadTypeReload || type == FrameLoadTypeReloadBypassingCache; } @@ -139,7 +150,7 @@ ResourceRequest FrameLoader::resourceRequestForReload(FrameLoadType frameLoadType, const KURL& overrideURL, ClientRedirectPolicy clientRedirectPolicy) { - ASSERT(frameLoadType == FrameLoadTypeReload || frameLoadType == FrameLoadTypeReloadMainResource || frameLoadType == FrameLoadTypeReloadBypassingCache); + DCHECK(isReloadLoadType(frameLoadType)); WebCachePolicy cachePolicy = frameLoadType == FrameLoadTypeReloadBypassingCache ? WebCachePolicy::BypassingCache : WebCachePolicy::ValidatingCacheData; if (!m_currentItem) return ResourceRequest(); @@ -868,7 +879,7 @@ static NavigationType determineNavigationType(FrameLoadType frameLoadType, bool isFormSubmission, bool haveEvent) { - bool isReload = frameLoadType == FrameLoadTypeReload || frameLoadType == FrameLoadTypeReloadMainResource || frameLoadType == FrameLoadTypeReloadBypassingCache; + bool isReload = isReloadLoadType(frameLoadType); bool isBackForward = isBackForwardLoadType(frameLoadType); if (isFormSubmission) return (isReload || isBackForward) ? NavigationTypeFormResubmitted : NavigationTypeFormSubmitted; @@ -1293,9 +1304,7 @@ // We don't do this if we are submitting a form with method other than "GET", explicitly reloading, // currently displaying a frameset, or if the URL does not have a fragment. return (!isFormSubmission || equalIgnoringCase(httpMethod, HTTPNames::GET)) - && loadType != FrameLoadTypeReload - && loadType != FrameLoadTypeReloadBypassingCache - && loadType != FrameLoadTypeReloadMainResource + && !isReloadLoadType(loadType) && loadType != FrameLoadTypeBackForward && url.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(m_frame->document()->url(), url)
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.h b/third_party/WebKit/Source/core/loader/FrameLoader.h index b4e621a..834f1ddf 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.h +++ b/third_party/WebKit/Source/core/loader/FrameLoader.h
@@ -64,6 +64,7 @@ struct FrameLoadRequest; CORE_EXPORT bool isBackForwardLoadType(FrameLoadType); +CORE_EXPORT bool isReloadLoadType(FrameLoadType); class CORE_EXPORT FrameLoader final { WTF_MAKE_NONCOPYABLE(FrameLoader);
diff --git a/third_party/WebKit/Source/core/loader/MockThreadableLoader.h b/third_party/WebKit/Source/core/loader/MockThreadableLoader.h index 47691965..99a81061 100644 --- a/third_party/WebKit/Source/core/loader/MockThreadableLoader.h +++ b/third_party/WebKit/Source/core/loader/MockThreadableLoader.h
@@ -14,7 +14,7 @@ class MockThreadableLoader : public ThreadableLoader { public: - static std::unique_ptr<MockThreadableLoader> create() { return wrapUnique(new testing::StrictMock<MockThreadableLoader>); } + static MockThreadableLoader* create() { return new testing::StrictMock<MockThreadableLoader>; } MOCK_METHOD1(start, void(const ResourceRequest&)); MOCK_METHOD1(overrideTimeout, void(unsigned long));
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoader.cpp index 16f78451..11d2d47 100644 --- a/third_party/WebKit/Source/core/loader/ThreadableLoader.cpp +++ b/third_party/WebKit/Source/core/loader/ThreadableLoader.cpp
@@ -33,15 +33,12 @@ #include "core/dom/Document.h" #include "core/dom/ExecutionContext.h" #include "core/loader/DocumentThreadableLoader.h" -#include "core/loader/ThreadableLoaderClientWrapper.h" #include "core/loader/WorkerThreadableLoader.h" #include "core/workers/WorkerGlobalScope.h" -#include "core/workers/WorkerThread.h" -#include <memory> namespace blink { -std::unique_ptr<ThreadableLoader> ThreadableLoader::create(ExecutionContext& context, ThreadableLoaderClient* client, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOptions) +ThreadableLoader* ThreadableLoader::create(ExecutionContext& context, ThreadableLoaderClient* client, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOptions) { ASSERT(client);
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoader.h b/third_party/WebKit/Source/core/loader/ThreadableLoader.h index 4d26431..9a1be36 100644 --- a/third_party/WebKit/Source/core/loader/ThreadableLoader.h +++ b/third_party/WebKit/Source/core/loader/ThreadableLoader.h
@@ -34,6 +34,7 @@ #include "core/CoreExport.h" #include "core/fetch/ResourceLoaderOptions.h" #include "platform/CrossThreadCopier.h" +#include "platform/heap/Handle.h" #include "wtf/Allocator.h" #include "wtf/Noncopyable.h" #include <memory> @@ -126,7 +127,7 @@ // - ResourceLoaderOptions argument will be passed to the FetchRequest // that this ThreadableLoader creates. It can be altered e.g. when // redirect happens. -class CORE_EXPORT ThreadableLoader { +class CORE_EXPORT ThreadableLoader : public GarbageCollectedFinalized<ThreadableLoader> { WTF_MAKE_NONCOPYABLE(ThreadableLoader); public: // ThreadableLoaderClient methods may not destroy the ThreadableLoader @@ -167,7 +168,7 @@ // - may call cancel() // - can destroy the ThreadableLoader instance in them (by clearing // std::unique_ptr<ThreadableLoader>). - static std::unique_ptr<ThreadableLoader> create(ExecutionContext&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&); + static ThreadableLoader* create(ExecutionContext&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&); // The methods on the ThreadableLoaderClient passed on create() call // may be called synchronous to start() call. @@ -184,6 +185,8 @@ virtual ~ThreadableLoader() { } + DEFINE_INLINE_VIRTUAL_TRACE() {} + protected: ThreadableLoader() { } };
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoaderClientWrapper.h b/third_party/WebKit/Source/core/loader/ThreadableLoaderClientWrapper.h deleted file mode 100644 index c78779b..0000000 --- a/third_party/WebKit/Source/core/loader/ThreadableLoaderClientWrapper.h +++ /dev/null
@@ -1,158 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ThreadableLoaderClientWrapper_h -#define ThreadableLoaderClientWrapper_h - -#include "core/loader/ThreadableLoaderClient.h" -#include "core/timing/WorkerGlobalScopePerformance.h" -#include "core/workers/WorkerGlobalScope.h" -#include "platform/heap/Handle.h" -#include "platform/network/ResourceResponse.h" -#include "platform/network/ResourceTimingInfo.h" -#include "wtf/Threading.h" -#include "wtf/Vector.h" -#include <memory> - -namespace blink { - -class ThreadableLoaderClientWrapper final : public GarbageCollected<ThreadableLoaderClientWrapper> { -public: - ThreadableLoaderClientWrapper(WorkerGlobalScope& workerGlobalScope, ThreadableLoaderClient* client) - : m_workerGlobalScope(workerGlobalScope) - , m_client(client) - { - } - - void clearClient() - { - m_done = true; - m_client = nullptr; - } - - bool done() const { return m_done; } - - void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) - { - if (m_client) - m_client->didSendData(bytesSent, totalBytesToBeSent); - } - - void didReceiveResponse(unsigned long identifier, std::unique_ptr<CrossThreadResourceResponseData> responseData, std::unique_ptr<WebDataConsumerHandle> handle) - { - ResourceResponse response(responseData.get()); - - if (m_client) - m_client->didReceiveResponse(identifier, response, std::move(handle)); - } - - void didReceiveData(std::unique_ptr<Vector<char>> data) - { - RELEASE_ASSERT(data->size() <= std::numeric_limits<unsigned>::max()); - - if (m_client) - m_client->didReceiveData(data->data(), data->size()); - } - - void didReceiveCachedMetadata(std::unique_ptr<Vector<char>> data) - { - if (m_client) - m_client->didReceiveCachedMetadata(data->data(), data->size()); - } - - void didFinishLoading(unsigned long identifier, double finishTime) - { - m_done = true; - if (m_client) { - ThreadableLoaderClient* client = m_client; - m_client = nullptr; - client->didFinishLoading(identifier, finishTime); - } - } - - void didFail(const ResourceError& error) - { - m_done = true; - if (m_client) { - ThreadableLoaderClient* client = m_client; - m_client = nullptr; - client->didFail(error); - } - } - - void didFailAccessControlCheck(const ResourceError& error) - { - m_done = true; - if (m_client) { - ThreadableLoaderClient* client = m_client; - m_client = nullptr; - client->didFailAccessControlCheck(error); - } - } - - void didFailRedirectCheck() - { - m_done = true; - if (m_client) { - ThreadableLoaderClient* client = m_client; - m_client = nullptr; - client->didFailRedirectCheck(); - } - } - - void didDownloadData(int dataLength) - { - if (m_client) - m_client->didDownloadData(dataLength); - } - - void didReceiveResourceTiming(std::unique_ptr<CrossThreadResourceTimingInfoData> timingData) - { - std::unique_ptr<ResourceTimingInfo> info(ResourceTimingInfo::adopt(std::move(timingData))); - if (m_client) { - WorkerGlobalScopePerformance::performance(*m_workerGlobalScope)->addResourceTiming(*info); - m_client->didReceiveResourceTiming(*info); - } - } - - DEFINE_INLINE_TRACE() - { - visitor->trace(m_workerGlobalScope); - } - -private: - Member<WorkerGlobalScope> m_workerGlobalScope; - ThreadableLoaderClient* m_client = nullptr; - bool m_done = false; -}; - -} // namespace blink - -#endif // ThreadableLoaderClientWrapper_h
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp index d9e53d2..668a004 100644 --- a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp +++ b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
@@ -157,7 +157,7 @@ std::unique_ptr<DummyPageHolder> m_dummyPageHolder; Checkpoint m_checkpoint; - std::unique_ptr<DocumentThreadableLoader> m_loader; + Persistent<DocumentThreadableLoader> m_loader; }; class WorkerThreadableLoaderTestHelper : public ThreadableLoaderTestHelper, public WorkerLoaderProxyProvider { @@ -213,7 +213,7 @@ { ASSERT(m_workerThread); ASSERT(m_workerThread->isCurrentThread()); - m_loader.reset(); + m_loader = nullptr; } Checkpoint& checkpoint() override @@ -336,7 +336,7 @@ std::unique_ptr<DummyPageHolder> m_dummyPageHolder; Checkpoint m_checkpoint; // |m_loader| must be touched only from the worker thread only. - std::unique_ptr<ThreadableLoader> m_loader; + CrossThreadPersistent<ThreadableLoader> m_loader; }; class ThreadableLoaderTest : public ::testing::TestWithParam<ThreadableLoaderToTest> {
diff --git a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp index 35343b41..ab02e4ff 100644 --- a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp +++ b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp
@@ -36,306 +36,234 @@ #include "core/timing/WorkerGlobalScopePerformance.h" #include "core/workers/WorkerGlobalScope.h" #include "core/workers/WorkerLoaderProxy.h" -#include "core/workers/WorkerThread.h" #include "platform/CrossThreadFunctional.h" -#include "platform/WaitableEvent.h" #include "platform/heap/SafePoint.h" #include "platform/network/ResourceError.h" #include "platform/network/ResourceRequest.h" #include "platform/network/ResourceResponse.h" #include "platform/network/ResourceTimingInfo.h" #include "platform/weborigin/SecurityPolicy.h" -#include "public/platform/Platform.h" -#include "wtf/PtrUtil.h" -#include "wtf/Vector.h" #include "wtf/debug/Alias.h" #include <memory> namespace blink { -static std::unique_ptr<Vector<char>> createVectorFromMemoryRegion(const char* data, unsigned dataLength) +namespace { + +std::unique_ptr<Vector<char>> createVectorFromMemoryRegion(const char* data, unsigned dataLength) { std::unique_ptr<Vector<char>> buffer = wrapUnique(new Vector<char>(dataLength)); memcpy(buffer->data(), data, dataLength); return buffer; } -WorkerThreadableLoader::WorkerThreadableLoader(WorkerGlobalScope& workerGlobalScope, ThreadableLoaderClient* client, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOptions, BlockingBehavior blockingBehavior) - : m_workerGlobalScope(&workerGlobalScope) - , m_workerClientWrapper(new ThreadableLoaderClientWrapper(workerGlobalScope, client)) -{ - if (blockingBehavior == LoadAsynchronously) { - m_bridge = new MainThreadAsyncBridge(workerGlobalScope, m_workerClientWrapper, options, resourceLoaderOptions); - } else { - m_bridge = new MainThreadSyncBridge(workerGlobalScope, m_workerClientWrapper, options, resourceLoaderOptions); +} // namespace + +class WorkerThreadableLoader::AsyncTaskForwarder final : public WorkerThreadableLoader::TaskForwarder { +public: + explicit AsyncTaskForwarder(PassRefPtr<WorkerLoaderProxy> loaderProxy) + : m_loaderProxy(loaderProxy) + { + DCHECK(isMainThread()); } + ~AsyncTaskForwarder() override + { + DCHECK(isMainThread()); + } + + void forwardTask(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) override + { + DCHECK(isMainThread()); + m_loaderProxy->postTaskToWorkerGlobalScope(location, std::move(task)); + } + void forwardTaskWithDoneSignal(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) override + { + DCHECK(isMainThread()); + m_loaderProxy->postTaskToWorkerGlobalScope(location, std::move(task)); + } + void abort() override + { + DCHECK(isMainThread()); + } + +private: + RefPtr<WorkerLoaderProxy> m_loaderProxy; +}; + +struct WorkerThreadableLoader::TaskWithLocation final { + TaskWithLocation(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) + : m_location(location) + , m_task(std::move(task)) + { + } + TaskWithLocation(TaskWithLocation&& task) + : TaskWithLocation(task.m_location, std::move(task.m_task)) + { + } + ~TaskWithLocation() = default; + + WebTraceLocation m_location; + std::unique_ptr<ExecutionContextTask> m_task; +}; + +// Observing functions and wait() need to be called on the worker thread. +// Setting functions and signal() need to be called on the main thread. +// All observing functions must be called after wait() returns, and all +// setting functions must be called before signal() is called. +class WorkerThreadableLoader::WaitableEventWithTasks final : public ThreadSafeRefCounted<WaitableEventWithTasks> { +public: + static PassRefPtr<WaitableEventWithTasks> create() { return adoptRef(new WaitableEventWithTasks); } + + void signal() + { + DCHECK(isMainThread()); + CHECK(!m_isSignalCalled); + m_isSignalCalled = true; + m_event.signal(); + } + void wait() + { + DCHECK(!isMainThread()); + CHECK(!m_isWaitDone); + m_event.wait(); + m_isWaitDone = true; + } + + // Observing functions + bool isAborted() const + { + DCHECK(!isMainThread()); + CHECK(m_isWaitDone); + return m_isAborted; + } + Vector<TaskWithLocation> take() + { + DCHECK(!isMainThread()); + CHECK(m_isWaitDone); + return std::move(m_tasks); + } + + // Setting functions + void append(TaskWithLocation task) + { + DCHECK(isMainThread()); + CHECK(!m_isSignalCalled); + m_tasks.append(std::move(task)); + } + void setIsAborted() + { + DCHECK(isMainThread()); + CHECK(!m_isSignalCalled); + m_isAborted = true; + } + +private: + WaitableEventWithTasks() {} + + WaitableEvent m_event; + Vector<TaskWithLocation> m_tasks; + bool m_isAborted = false; + bool m_isSignalCalled = false; + bool m_isWaitDone = false; +}; + +class WorkerThreadableLoader::SyncTaskForwarder final : public WorkerThreadableLoader::TaskForwarder { +public: + explicit SyncTaskForwarder(PassRefPtr<WaitableEventWithTasks> eventWithTasks) + : m_eventWithTasks(eventWithTasks) + { + DCHECK(isMainThread()); + } + ~SyncTaskForwarder() override + { + DCHECK(isMainThread()); + } + + void forwardTask(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) override + { + DCHECK(isMainThread()); + m_eventWithTasks->append(TaskWithLocation(location, std::move(task))); + } + void forwardTaskWithDoneSignal(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) override + { + DCHECK(isMainThread()); + m_eventWithTasks->append(TaskWithLocation(location, std::move(task))); + m_eventWithTasks->signal(); + } + void abort() override + { + DCHECK(isMainThread()); + m_eventWithTasks->setIsAborted(); + m_eventWithTasks->signal(); + } + +private: + RefPtr<WaitableEventWithTasks> m_eventWithTasks; +}; + +WorkerThreadableLoader::WorkerThreadableLoader( + WorkerGlobalScope& workerGlobalScope, + ThreadableLoaderClient* client, + const ThreadableLoaderOptions& options, + const ResourceLoaderOptions& resourceLoaderOptions, + BlockingBehavior blockingBehavior) + : m_workerGlobalScope(&workerGlobalScope) + , m_workerLoaderProxy(workerGlobalScope.thread()->workerLoaderProxy()) + , m_client(client) + , m_threadableLoaderOptions(options) + , m_resourceLoaderOptions(resourceLoaderOptions) + , m_blockingBehavior(blockingBehavior) +{ + DCHECK(client); } void WorkerThreadableLoader::loadResourceSynchronously(WorkerGlobalScope& workerGlobalScope, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOptions) { - std::unique_ptr<WorkerThreadableLoader> loader = wrapUnique(new WorkerThreadableLoader(workerGlobalScope, &client, options, resourceLoaderOptions, LoadSynchronously)); - loader->start(request); + (new WorkerThreadableLoader(workerGlobalScope, &client, options, resourceLoaderOptions, LoadSynchronously))->start(request); } WorkerThreadableLoader::~WorkerThreadableLoader() { - DCHECK(m_workerClientWrapper->done()); - m_bridge->destroy(); - m_bridge = nullptr; + DCHECK(!m_peer); + DCHECK(!m_client); } -void WorkerThreadableLoader::start(const ResourceRequest& request) +void WorkerThreadableLoader::start(const ResourceRequest& originalRequest) { - ResourceRequest requestToPass(request); - if (!requestToPass.didSetHTTPReferrer()) - requestToPass.setHTTPReferrer(SecurityPolicy::generateReferrer(m_workerGlobalScope->getReferrerPolicy(), request.url(), m_workerGlobalScope->outgoingReferrer())); - m_bridge->start(requestToPass, *m_workerGlobalScope); -} + ResourceRequest request(originalRequest); + if (!request.didSetHTTPReferrer()) + request.setHTTPReferrer(SecurityPolicy::generateReferrer(m_workerGlobalScope->getReferrerPolicy(), request.url(), m_workerGlobalScope->outgoingReferrer())); -void WorkerThreadableLoader::overrideTimeout(unsigned long timeoutMilliseconds) -{ - ASSERT(m_bridge); - m_bridge->overrideTimeout(timeoutMilliseconds); -} + DCHECK(!isMainThread()); + RefPtr<WaitableEventWithTasks> eventWithTasks; + if (m_blockingBehavior == LoadSynchronously) + eventWithTasks = WaitableEventWithTasks::create(); -void WorkerThreadableLoader::cancel() -{ - ASSERT(m_bridge); - m_bridge->cancel(); -} + m_workerLoaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask( + &Peer::createAndStart, + wrapCrossThreadPersistent(this), + m_workerLoaderProxy, + wrapCrossThreadPersistent(m_workerGlobalScope->thread()->getWorkerThreadLifecycleContext()), + request, + m_threadableLoaderOptions, + m_resourceLoaderOptions, + eventWithTasks)); -WorkerThreadableLoader::MainThreadBridgeBase::MainThreadBridgeBase( - ThreadableLoaderClientWrapper* workerClientWrapper, - PassRefPtr<WorkerLoaderProxy> loaderProxy) - : m_workerClientWrapper(workerClientWrapper) - , m_loaderProxy(loaderProxy) -{ - ASSERT(m_workerClientWrapper.get()); - ASSERT(m_loaderProxy.get()); -} - -WorkerThreadableLoader::MainThreadBridgeBase::~MainThreadBridgeBase() -{ -} - -void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadCreateLoader(ThreadableLoaderOptions options, ResourceLoaderOptions resourceLoaderOptions, ExecutionContext* context) -{ - ASSERT(isMainThread()); - Document* document = toDocument(context); - - resourceLoaderOptions.requestInitiatorContext = WorkerContext; - m_mainThreadLoader = DocumentThreadableLoader::create(*document, this, options, resourceLoaderOptions); - ASSERT(m_mainThreadLoader); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadStart(std::unique_ptr<CrossThreadResourceRequestData> requestData) -{ - ASSERT(isMainThread()); - ASSERT(m_mainThreadLoader); - m_mainThreadLoader->start(ResourceRequest(requestData.get())); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::createLoaderInMainThread(const ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOptions) -{ - m_loaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&MainThreadBridgeBase::mainThreadCreateLoader, crossThreadUnretained(this), options, resourceLoaderOptions)); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::startInMainThread(const ResourceRequest& request, const WorkerGlobalScope& workerGlobalScope) -{ - loaderProxy()->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&MainThreadBridgeBase::mainThreadStart, crossThreadUnretained(this), request)); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadDestroy(ExecutionContext* context) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - delete this; -} - -void WorkerThreadableLoader::MainThreadBridgeBase::destroy() -{ - // Ensure that no more client callbacks are done in the worker context's - // thread. - // ThreadableLoaderClientWrapper is an on-heap class and this function can - // be called in the finalization step but it is safe because - // m_workerClientWrapper is a CrossThreadPersistent. - m_workerClientWrapper->clearClient(); - - // "delete this" and m_mainThreadLoader::deref() on the worker object's - // thread. - m_loaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&MainThreadBridgeBase::mainThreadDestroy, crossThreadUnretained(this))); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadOverrideTimeout(unsigned long timeoutMilliseconds, ExecutionContext* context) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - - if (!m_mainThreadLoader) + if (m_blockingBehavior == LoadAsynchronously) return; - m_mainThreadLoader->overrideTimeout(timeoutMilliseconds); -} -void WorkerThreadableLoader::MainThreadBridgeBase::overrideTimeout(unsigned long timeoutMilliseconds) -{ - m_loaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&MainThreadBridgeBase::mainThreadOverrideTimeout, crossThreadUnretained(this), timeoutMilliseconds)); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::mainThreadCancel(ExecutionContext* context) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - - if (!m_mainThreadLoader) - return; - m_mainThreadLoader->cancel(); - m_mainThreadLoader = nullptr; -} - -void WorkerThreadableLoader::MainThreadBridgeBase::cancel() -{ - m_loaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&MainThreadBridgeBase::mainThreadCancel, crossThreadUnretained(this))); - ThreadableLoaderClientWrapper* clientWrapper = m_workerClientWrapper; - if (!clientWrapper->done()) { - // If the client hasn't reached a termination state, then transition it - // by sending a cancellation error. - // Note: no more client callbacks will be done after this method -- the - // m_workerClientWrapper->clearClient() call ensures that. - ResourceError error(String(), 0, String(), String()); - error.setIsCancellation(true); - clientWrapper->didFail(error); - } - // |this| might be already destructed here because didFail() might - // clear a reference to ThreadableLoader, which might destruct - // WorkerThreadableLoader and then MainThreadBridge. - // Therefore we call clearClient() directly, rather than calling - // this->m_workerClientWrapper->clearClient(). - clientWrapper->clearClient(); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) -{ - forwardTaskToWorker(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoaderClientWrapper::didSendData, m_workerClientWrapper, bytesSent, totalBytesToBeSent)); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::didReceiveResponse(unsigned long identifier, const ResourceResponse& response, std::unique_ptr<WebDataConsumerHandle> handle) -{ - forwardTaskToWorker(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoaderClientWrapper::didReceiveResponse, m_workerClientWrapper, identifier, response, passed(std::move(handle)))); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::didReceiveData(const char* data, unsigned dataLength) -{ - forwardTaskToWorker(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoaderClientWrapper::didReceiveData, m_workerClientWrapper, passed(createVectorFromMemoryRegion(data, dataLength)))); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::didDownloadData(int dataLength) -{ - forwardTaskToWorker(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoaderClientWrapper::didDownloadData, m_workerClientWrapper, dataLength)); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::didReceiveCachedMetadata(const char* data, int dataLength) -{ - forwardTaskToWorker(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoaderClientWrapper::didReceiveCachedMetadata, m_workerClientWrapper, passed(createVectorFromMemoryRegion(data, dataLength)))); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::didFinishLoading(unsigned long identifier, double finishTime) -{ - forwardTaskToWorkerOnLoaderDone(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoaderClientWrapper::didFinishLoading, m_workerClientWrapper, identifier, finishTime)); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::didFail(const ResourceError& error) -{ - forwardTaskToWorkerOnLoaderDone(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoaderClientWrapper::didFail, m_workerClientWrapper, error)); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::didFailAccessControlCheck(const ResourceError& error) -{ - forwardTaskToWorkerOnLoaderDone(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoaderClientWrapper::didFailAccessControlCheck, m_workerClientWrapper, error)); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::didFailRedirectCheck() -{ - forwardTaskToWorkerOnLoaderDone(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoaderClientWrapper::didFailRedirectCheck, m_workerClientWrapper)); -} - -void WorkerThreadableLoader::MainThreadBridgeBase::didReceiveResourceTiming(const ResourceTimingInfo& info) -{ - forwardTaskToWorker(BLINK_FROM_HERE, createCrossThreadTask(&ThreadableLoaderClientWrapper::didReceiveResourceTiming, m_workerClientWrapper, info)); -} - -WorkerThreadableLoader::MainThreadAsyncBridge::MainThreadAsyncBridge( - WorkerGlobalScope& workerGlobalScope, - ThreadableLoaderClientWrapper* workerClientWrapper, - const ThreadableLoaderOptions& options, - const ResourceLoaderOptions& resourceLoaderOptions) - : MainThreadBridgeBase(workerClientWrapper, workerGlobalScope.thread()->workerLoaderProxy()) -{ - createLoaderInMainThread(options, resourceLoaderOptions); -} - -void WorkerThreadableLoader::MainThreadAsyncBridge::start(const ResourceRequest& request, const WorkerGlobalScope& workerGlobalScope) -{ - startInMainThread(request, workerGlobalScope); -} - -WorkerThreadableLoader::MainThreadAsyncBridge::~MainThreadAsyncBridge() -{ -} - -void WorkerThreadableLoader::MainThreadAsyncBridge::forwardTaskToWorker(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) -{ - loaderProxy()->postTaskToWorkerGlobalScope(location, std::move(task)); -} - -void WorkerThreadableLoader::MainThreadAsyncBridge::forwardTaskToWorkerOnLoaderDone(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) -{ - loaderProxy()->postTaskToWorkerGlobalScope(location, std::move(task)); -} - -WorkerThreadableLoader::MainThreadSyncBridge::MainThreadSyncBridge( - WorkerGlobalScope& workerGlobalScope, - ThreadableLoaderClientWrapper* workerClientWrapper, - const ThreadableLoaderOptions& options, - const ResourceLoaderOptions& resourceLoaderOptions) - : MainThreadBridgeBase(workerClientWrapper, workerGlobalScope.thread()->workerLoaderProxy()) - , m_done(false) -{ - createLoaderInMainThread(options, resourceLoaderOptions); -} - -void WorkerThreadableLoader::MainThreadSyncBridge::start(const ResourceRequest& request, const WorkerGlobalScope& workerGlobalScope) -{ - WaitableEvent* terminationEvent = workerGlobalScope.thread()->terminationEvent(); - m_loaderDoneEvent = wrapUnique(new WaitableEvent()); - - startInMainThread(request, workerGlobalScope); - - size_t signaledIndex; { - Vector<WaitableEvent*> events; - // Order is important; indicies are used later. - events.append(terminationEvent); - events.append(m_loaderDoneEvent.get()); - SafePointScope scope(BlinkGC::HeapPointersOnStack); - signaledIndex = WaitableEvent::waitMultiple(events); + eventWithTasks->wait(); } - // |signaledIndex| is 0; which is terminationEvent. - if (signaledIndex == 0) { + + if (eventWithTasks->isAborted()) { + // This thread is going to terminate. cancel(); return; } - // The following code must be run only after |m_loaderDoneEvent| is - // signalled. - - Vector<ClientTask> tasks; - { - MutexLocker lock(m_lock); - ASSERT(m_done); - m_clientTasks.swap(tasks); - } - for (const auto& task : tasks) { + for (const auto& task : eventWithTasks->take()) { // Store the program counter where the task is posted from, and alias // it to ensure it is stored in the crash dump. const void* programCounter = task.m_location.program_counter(); @@ -347,38 +275,333 @@ } } -WorkerThreadableLoader::MainThreadSyncBridge::ClientTask::ClientTask(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) - : m_location(location) - , m_task(std::move(task)) {} - -WorkerThreadableLoader::MainThreadSyncBridge::ClientTask::~ClientTask() = default; -WorkerThreadableLoader::MainThreadSyncBridge::ClientTask::ClientTask(ClientTask&&) = default; - -WorkerThreadableLoader::MainThreadSyncBridge::~MainThreadSyncBridge() +void WorkerThreadableLoader::overrideTimeout(unsigned long timeoutMilliseconds) { - ASSERT(isMainThread()); + DCHECK(!isMainThread()); + if (!m_peer) + return; + m_workerLoaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&Peer::overrideTimeout, m_peer, timeoutMilliseconds)); } -void WorkerThreadableLoader::MainThreadSyncBridge::forwardTaskToWorker(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) +void WorkerThreadableLoader::cancel() { - ASSERT(isMainThread()); + DCHECK(!isMainThread()); + if (m_peer) { + m_workerLoaderProxy->postTaskToLoader(BLINK_FROM_HERE, createCrossThreadTask(&Peer::cancel, m_peer)); + m_peer = nullptr; + } - MutexLocker lock(m_lock); - RELEASE_ASSERT(!m_done); + if (!m_client) + return; - m_clientTasks.append(ClientTask(location, std::move(task))); + // If the client hasn't reached a termination state, then transition it + // by sending a cancellation error. + // Note: no more client callbacks will be done after this method -- the + // clearClient() call ensures that. + ResourceError error(String(), 0, String(), String()); + error.setIsCancellation(true); + didFail(error); + DCHECK(!m_client); } -void WorkerThreadableLoader::MainThreadSyncBridge::forwardTaskToWorkerOnLoaderDone(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task) +void WorkerThreadableLoader::didStart(Peer* peer) { - ASSERT(isMainThread()); + DCHECK(!isMainThread()); + DCHECK(!m_peer); + DCHECK(peer); + if (!m_client) { + // The loading is already cancelled. + return; + } - MutexLocker lock(m_lock); - RELEASE_ASSERT(!m_done); + m_peer = peer; +} - m_clientTasks.append(ClientTask(location, std::move(task))); - m_done = true; - m_loaderDoneEvent->signal(); +void WorkerThreadableLoader::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) +{ + DCHECK(!isMainThread()); + if (!m_client) + return; + m_client->didSendData(bytesSent, totalBytesToBeSent); +} + +void WorkerThreadableLoader::didReceiveResponse(unsigned long identifier, std::unique_ptr<CrossThreadResourceResponseData> responseData, std::unique_ptr<WebDataConsumerHandle> handle) +{ + DCHECK(!isMainThread()); + if (!m_client) + return; + ResourceResponse response(responseData.get()); + m_client->didReceiveResponse(identifier, response, std::move(handle)); +} + +void WorkerThreadableLoader::didReceiveData(std::unique_ptr<Vector<char>> data) +{ + DCHECK(!isMainThread()); + CHECK_LE(data->size(), std::numeric_limits<unsigned>::max()); + if (!m_client) + return; + m_client->didReceiveData(data->data(), data->size()); +} + +void WorkerThreadableLoader::didReceiveCachedMetadata(std::unique_ptr<Vector<char>> data) +{ + DCHECK(!isMainThread()); + if (!m_client) + return; + m_client->didReceiveCachedMetadata(data->data(), data->size()); +} + +void WorkerThreadableLoader::didFinishLoading(unsigned long identifier, double finishTime) +{ + DCHECK(!isMainThread()); + if (!m_client) + return; + auto* client = m_client; + m_client = nullptr; + m_peer = nullptr; + client->didFinishLoading(identifier, finishTime); +} + +void WorkerThreadableLoader::didFail(const ResourceError& error) +{ + DCHECK(!isMainThread()); + if (!m_client) + return; + auto* client = m_client; + m_client = nullptr; + m_peer = nullptr; + client->didFail(error); +} + +void WorkerThreadableLoader::didFailAccessControlCheck(const ResourceError& error) +{ + DCHECK(!isMainThread()); + if (!m_client) + return; + auto* client = m_client; + m_client = nullptr; + m_peer = nullptr; + client->didFailAccessControlCheck(error); +} + +void WorkerThreadableLoader::didFailRedirectCheck() +{ + DCHECK(!isMainThread()); + if (!m_client) + return; + auto* client = m_client; + m_client = nullptr; + m_peer = nullptr; + client->didFailRedirectCheck(); +} + +void WorkerThreadableLoader::didDownloadData(int dataLength) +{ + DCHECK(!isMainThread()); + if (!m_client) + return; + m_client->didDownloadData(dataLength); +} + +void WorkerThreadableLoader::didReceiveResourceTiming(std::unique_ptr<CrossThreadResourceTimingInfoData> timingData) +{ + DCHECK(!isMainThread()); + if (!m_client) + return; + std::unique_ptr<ResourceTimingInfo> info(ResourceTimingInfo::adopt(std::move(timingData))); + WorkerGlobalScopePerformance::performance(*m_workerGlobalScope)->addResourceTiming(*info); + m_client->didReceiveResourceTiming(*info); +} + +DEFINE_TRACE(WorkerThreadableLoader) +{ + visitor->trace(m_workerGlobalScope); + ThreadableLoader::trace(visitor); +} + +void WorkerThreadableLoader::Peer::createAndStart( + WorkerThreadableLoader* workerLoader, + PassRefPtr<WorkerLoaderProxy> passLoaderProxy, + WorkerThreadLifecycleContext* workerThreadLifecycleContext, + std::unique_ptr<CrossThreadResourceRequestData> request, + const ThreadableLoaderOptions& options, + const ResourceLoaderOptions& resourceLoaderOptions, + PassRefPtr<WaitableEventWithTasks> eventWithTasks, + ExecutionContext* executionContext) +{ + DCHECK(isMainThread()); + TaskForwarder* forwarder; + RefPtr<WorkerLoaderProxy> loaderProxy = passLoaderProxy; + if (eventWithTasks) + forwarder = new SyncTaskForwarder(eventWithTasks); + else + forwarder = new AsyncTaskForwarder(loaderProxy); + + Peer* peer = new Peer(forwarder, workerThreadLifecycleContext); + if (peer->wasContextDestroyedBeforeObserverCreation()) { + // The thread is already terminating. + forwarder->abort(); + peer->m_forwarder = nullptr; + return; + } + peer->m_workerLoader = workerLoader; + peer->start(*toDocument(executionContext), std::move(request), options, resourceLoaderOptions); + forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&WorkerThreadableLoader::didStart, wrapCrossThreadPersistent(workerLoader), wrapCrossThreadPersistent(peer))); +} + +WorkerThreadableLoader::Peer::~Peer() +{ + DCHECK(isMainThread()); + DCHECK(!m_workerLoader); +} + +void WorkerThreadableLoader::Peer::overrideTimeout(unsigned long timeoutMilliseconds) +{ + DCHECK(isMainThread()); + if (!m_mainThreadLoader) + return; + m_mainThreadLoader->overrideTimeout(timeoutMilliseconds); +} + +void WorkerThreadableLoader::Peer::cancel() +{ + DCHECK(isMainThread()); + if (!m_mainThreadLoader) + return; + m_mainThreadLoader->cancel(); + m_mainThreadLoader = nullptr; +} + +void WorkerThreadableLoader::Peer::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) +{ + DCHECK(isMainThread()); + CrossThreadPersistent<WorkerThreadableLoader> workerLoader = m_workerLoader.get(); + if (!workerLoader || !m_forwarder) + return; + m_forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&WorkerThreadableLoader::didSendData, workerLoader, bytesSent, totalBytesToBeSent)); +} + +void WorkerThreadableLoader::Peer::didReceiveResponse(unsigned long identifier, const ResourceResponse& response, std::unique_ptr<WebDataConsumerHandle> handle) +{ + DCHECK(isMainThread()); + CrossThreadPersistent<WorkerThreadableLoader> workerLoader = m_workerLoader.get(); + if (!workerLoader || !m_forwarder) + return; + m_forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&WorkerThreadableLoader::didReceiveResponse, workerLoader, identifier, response, passed(std::move(handle)))); +} + +void WorkerThreadableLoader::Peer::didReceiveData(const char* data, unsigned dataLength) +{ + DCHECK(isMainThread()); + CrossThreadPersistent<WorkerThreadableLoader> workerLoader = m_workerLoader.get(); + if (!workerLoader || !m_forwarder) + return; + m_forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&WorkerThreadableLoader::didReceiveData, workerLoader, passed(createVectorFromMemoryRegion(data, dataLength)))); +} + +void WorkerThreadableLoader::Peer::didDownloadData(int dataLength) +{ + DCHECK(isMainThread()); + CrossThreadPersistent<WorkerThreadableLoader> workerLoader = m_workerLoader.get(); + if (!workerLoader || !m_forwarder) + return; + m_forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&WorkerThreadableLoader::didDownloadData, workerLoader, dataLength)); +} + +void WorkerThreadableLoader::Peer::didReceiveCachedMetadata(const char* data, int dataLength) +{ + DCHECK(isMainThread()); + CrossThreadPersistent<WorkerThreadableLoader> workerLoader = m_workerLoader.get(); + if (!workerLoader || !m_forwarder) + return; + m_forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&WorkerThreadableLoader::didReceiveCachedMetadata, workerLoader, passed(createVectorFromMemoryRegion(data, dataLength)))); +} + +void WorkerThreadableLoader::Peer::didFinishLoading(unsigned long identifier, double finishTime) +{ + DCHECK(isMainThread()); + CrossThreadPersistent<WorkerThreadableLoader> workerLoader = m_workerLoader.get(); + if (!workerLoader || !m_forwarder) + return; + m_forwarder->forwardTaskWithDoneSignal(BLINK_FROM_HERE, createCrossThreadTask(&WorkerThreadableLoader::didFinishLoading, workerLoader, identifier, finishTime)); + m_forwarder = nullptr; +} + +void WorkerThreadableLoader::Peer::didFail(const ResourceError& error) +{ + DCHECK(isMainThread()); + CrossThreadPersistent<WorkerThreadableLoader> workerLoader = m_workerLoader.get(); + if (!workerLoader || !m_forwarder) + return; + m_forwarder->forwardTaskWithDoneSignal(BLINK_FROM_HERE, createCrossThreadTask(&WorkerThreadableLoader::didFail, workerLoader, error)); + m_forwarder = nullptr; +} + +void WorkerThreadableLoader::Peer::didFailAccessControlCheck(const ResourceError& error) +{ + DCHECK(isMainThread()); + CrossThreadPersistent<WorkerThreadableLoader> workerLoader = m_workerLoader.get(); + if (!workerLoader || !m_forwarder) + return; + m_forwarder->forwardTaskWithDoneSignal(BLINK_FROM_HERE, createCrossThreadTask(&WorkerThreadableLoader::didFailAccessControlCheck, workerLoader, error)); + m_forwarder = nullptr; +} + +void WorkerThreadableLoader::Peer::didFailRedirectCheck() +{ + DCHECK(isMainThread()); + CrossThreadPersistent<WorkerThreadableLoader> workerLoader = m_workerLoader.get(); + if (!workerLoader || !m_forwarder) + return; + m_forwarder->forwardTaskWithDoneSignal(BLINK_FROM_HERE, createCrossThreadTask(&WorkerThreadableLoader::didFailRedirectCheck, workerLoader)); + m_forwarder = nullptr; +} + +void WorkerThreadableLoader::Peer::didReceiveResourceTiming(const ResourceTimingInfo& info) +{ + DCHECK(isMainThread()); + CrossThreadPersistent<WorkerThreadableLoader> workerLoader = m_workerLoader.get(); + if (!workerLoader || !m_forwarder) + return; + m_forwarder->forwardTask(BLINK_FROM_HERE, createCrossThreadTask(&WorkerThreadableLoader::didReceiveResourceTiming, workerLoader, info)); +} + +void WorkerThreadableLoader::Peer::contextDestroyed() +{ + DCHECK(isMainThread()); + if (m_forwarder) { + m_forwarder->abort(); + m_forwarder = nullptr; + } + m_workerLoader = nullptr; + cancel(); +} + +DEFINE_TRACE(WorkerThreadableLoader::Peer) +{ + visitor->trace(m_forwarder); + visitor->trace(m_mainThreadLoader); + WorkerThreadLifecycleObserver::trace(visitor); +} + +WorkerThreadableLoader::Peer::Peer(TaskForwarder* forwarder, WorkerThreadLifecycleContext* context) + : WorkerThreadLifecycleObserver(context) + , m_forwarder(forwarder) +{ + DCHECK(isMainThread()); +} + +void WorkerThreadableLoader::Peer::start( + Document& document, + std::unique_ptr<CrossThreadResourceRequestData> request, + const ThreadableLoaderOptions& options, + const ResourceLoaderOptions& originalResourceLoaderOptions) +{ + DCHECK(isMainThread()); + ResourceLoaderOptions resourceLoaderOptions = originalResourceLoaderOptions; + resourceLoaderOptions.requestInitiatorContext = WorkerContext; + m_mainThreadLoader = DocumentThreadableLoader::create(document, this, options, resourceLoaderOptions); + m_mainThreadLoader->start(ResourceRequest(request.get())); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h index 7e5c0854..02c0d8a 100644 --- a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h +++ b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h
@@ -31,181 +31,143 @@ #ifndef WorkerThreadableLoader_h #define WorkerThreadableLoader_h +#include "core/dom/ExecutionContextTask.h" #include "core/loader/ThreadableLoader.h" #include "core/loader/ThreadableLoaderClient.h" -#include "core/loader/ThreadableLoaderClientWrapper.h" +#include "core/workers/WorkerThread.h" +#include "core/workers/WorkerThreadLifecycleObserver.h" +#include "platform/WaitableEvent.h" #include "platform/heap/Handle.h" -#include "platform/weborigin/Referrer.h" -#include "wtf/Functional.h" +#include "public/platform/WebTraceLocation.h" #include "wtf/PassRefPtr.h" -#include "wtf/PtrUtil.h" #include "wtf/RefPtr.h" #include "wtf/Threading.h" -#include "wtf/ThreadingPrimitives.h" #include "wtf/Vector.h" #include "wtf/text/WTFString.h" #include <memory> namespace blink { -class ExecutionContextTask; class ResourceError; class ResourceRequest; class ResourceResponse; -class WaitableEvent; class WorkerGlobalScope; class WorkerLoaderProxy; struct CrossThreadResourceRequestData; +struct CrossThreadResourceTimingInfoData; +// TODO(yhirano): Draw a diagram to illustrate the class relationship. +// TODO(yhirano): Rename inner classes so that readers can see in which thread +// they are living easily. class WorkerThreadableLoader final : public ThreadableLoader { - USING_FAST_MALLOC(WorkerThreadableLoader); public: static void loadResourceSynchronously(WorkerGlobalScope&, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&, const ResourceLoaderOptions&); - static std::unique_ptr<WorkerThreadableLoader> create(WorkerGlobalScope& workerGlobalScope, ThreadableLoaderClient* client, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOptions) + static WorkerThreadableLoader* create(WorkerGlobalScope& workerGlobalScope, ThreadableLoaderClient* client, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOptions) { - return wrapUnique(new WorkerThreadableLoader(workerGlobalScope, client, options, resourceLoaderOptions, LoadAsynchronously)); + return new WorkerThreadableLoader(workerGlobalScope, client, options, resourceLoaderOptions, LoadAsynchronously); } ~WorkerThreadableLoader() override; + // ThreadableLoader functions void start(const ResourceRequest&) override; - void overrideTimeout(unsigned long timeout) override; - void cancel() override; + DECLARE_TRACE(); + private: enum BlockingBehavior { LoadSynchronously, LoadAsynchronously }; - // Creates a loader on the main thread and bridges communication between - // the main thread and the worker context's thread where WorkerThreadableLoader runs. - // - // Regarding the bridge and lifetimes of items used in callbacks, there are a few cases: - // - // all cases. All tasks posted from the worker context's thread are ok because - // the last task posted always is "mainThreadDestroy", so MainThreadBridge is - // around for all tasks that use it on the main thread. - // - // case 1. worker.terminate is called. - // In this case, no more tasks are posted from the worker object's thread to the worker - // context's thread -- WorkerGlobalScopeProxy implementation enforces this. - // - // case 2. xhr gets aborted and the worker context continues running. - // The ThreadableLoaderClientWrapper has the underlying client cleared, so no more calls - // go through it. All tasks posted from the worker object's thread to the worker context's - // thread do "ThreadableLoaderClientWrapper::ref" (automatically inside of the cross thread copy - // done in createCrossThreadTask), so the ThreadableLoaderClientWrapper instance is there until all - // tasks are executed. - class MainThreadBridgeBase : public ThreadableLoaderClient { + // A TaskForwarder forwards an ExecutionContextTask to the worker thread. + class TaskForwarder : public GarbageCollectedFinalized<TaskForwarder> { public: - // All executed on the worker context's thread. - MainThreadBridgeBase(ThreadableLoaderClientWrapper*, PassRefPtr<WorkerLoaderProxy>); - virtual void start(const ResourceRequest&, const WorkerGlobalScope&) = 0; - void overrideTimeout(unsigned long timeoutMilliseconds); + virtual ~TaskForwarder() {} + virtual void forwardTask(const WebTraceLocation&, std::unique_ptr<ExecutionContextTask>) = 0; + virtual void forwardTaskWithDoneSignal(const WebTraceLocation&, std::unique_ptr<ExecutionContextTask>) = 0; + virtual void abort() = 0; + + DEFINE_INLINE_VIRTUAL_TRACE() {} + }; + class AsyncTaskForwarder; + struct TaskWithLocation; + class WaitableEventWithTasks; + class SyncTaskForwarder; + + // An instance of this class lives in the main thread. It is a + // ThreadableLoaderClient for a DocumentThreadableLoader and forward + // notifications to the associated WorkerThreadableLoader living in the + // worker thread. + class Peer final : public GarbageCollectedFinalized<Peer>, public ThreadableLoaderClient, public WorkerThreadLifecycleObserver { + USING_GARBAGE_COLLECTED_MIXIN(Peer); + public: + static void createAndStart( + WorkerThreadableLoader*, + PassRefPtr<WorkerLoaderProxy>, + WorkerThreadLifecycleContext*, + std::unique_ptr<CrossThreadResourceRequestData>, + const ThreadableLoaderOptions&, + const ResourceLoaderOptions&, + PassRefPtr<WaitableEventWithTasks>, + ExecutionContext*); + ~Peer() override; + + void overrideTimeout(unsigned long timeoutMillisecond); void cancel(); - void destroy(); - // All executed on the main thread. - void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) final; - void didReceiveResponse(unsigned long identifier, const ResourceResponse&, std::unique_ptr<WebDataConsumerHandle>) final; - void didReceiveData(const char*, unsigned dataLength) final; - void didDownloadData(int dataLength) final; - void didReceiveCachedMetadata(const char*, int dataLength) final; - void didFinishLoading(unsigned long identifier, double finishTime) final; - void didFail(const ResourceError&) final; - void didFailAccessControlCheck(const ResourceError&) final; - void didFailRedirectCheck() final; - void didReceiveResourceTiming(const ResourceTimingInfo&) final; + void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override; + void didReceiveResponse(unsigned long identifier, const ResourceResponse&, std::unique_ptr<WebDataConsumerHandle>) override; + void didReceiveData(const char*, unsigned dataLength) override; + void didDownloadData(int dataLength) override; + void didReceiveCachedMetadata(const char*, int dataLength) override; + void didFinishLoading(unsigned long identifier, double finishTime) override; + void didFail(const ResourceError&) override; + void didFailAccessControlCheck(const ResourceError&) override; + void didFailRedirectCheck() override; + void didReceiveResourceTiming(const ResourceTimingInfo&) override; - protected: - ~MainThreadBridgeBase() override; + void contextDestroyed() override; - // Posts a task to the main thread to run mainThreadCreateLoader(). - void createLoaderInMainThread(const ThreadableLoaderOptions&, const ResourceLoaderOptions&); - // Posts a task to the main thread to run mainThreadStart(); - void startInMainThread(const ResourceRequest&, const WorkerGlobalScope&); - - WorkerLoaderProxy* loaderProxy() - { - return m_loaderProxy.get(); - } + DECLARE_TRACE(); private: - // The following methods are overridden by the subclasses to implement - // code to forward did.* method invocations to the worker context's - // thread which is specialized for sync and async case respectively. - virtual void forwardTaskToWorker(const WebTraceLocation&, std::unique_ptr<ExecutionContextTask>) = 0; - virtual void forwardTaskToWorkerOnLoaderDone(const WebTraceLocation&, std::unique_ptr<ExecutionContextTask>) = 0; + Peer(TaskForwarder*, WorkerThreadLifecycleContext*); + void start(Document&, std::unique_ptr<CrossThreadResourceRequestData>, const ThreadableLoaderOptions&, const ResourceLoaderOptions&); - // All executed on the main thread. - void mainThreadCreateLoader(ThreadableLoaderOptions, ResourceLoaderOptions, ExecutionContext*); - void mainThreadStart(std::unique_ptr<CrossThreadResourceRequestData>); - void mainThreadDestroy(ExecutionContext*); - void mainThreadOverrideTimeout(unsigned long timeoutMilliseconds, ExecutionContext*); - void mainThreadCancel(ExecutionContext*); + Member<TaskForwarder> m_forwarder; + Member<ThreadableLoader> m_mainThreadLoader; - // Only to be used on the main thread. - std::unique_ptr<ThreadableLoader> m_mainThreadLoader; - - // |m_workerClientWrapper| holds an pointer created on the worker - // thread, and |this| instance is created on the main thread. - CrossThreadPersistent<ThreadableLoaderClientWrapper> m_workerClientWrapper; - - // Used on the worker context thread. - RefPtr<WorkerLoaderProxy> m_loaderProxy; - }; - - class MainThreadAsyncBridge final : public MainThreadBridgeBase { - public: - MainThreadAsyncBridge(WorkerGlobalScope&, ThreadableLoaderClientWrapper*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&); - void start(const ResourceRequest&, const WorkerGlobalScope&) override; - - private: - ~MainThreadAsyncBridge() override; - - void forwardTaskToWorker(const WebTraceLocation&, std::unique_ptr<ExecutionContextTask>) override; - void forwardTaskToWorkerOnLoaderDone(const WebTraceLocation&, std::unique_ptr<ExecutionContextTask>) override; - }; - - class MainThreadSyncBridge final : public MainThreadBridgeBase { - public: - MainThreadSyncBridge(WorkerGlobalScope&, ThreadableLoaderClientWrapper*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&); - void start(const ResourceRequest&, const WorkerGlobalScope&) override; - - private: - struct ClientTask { - WebTraceLocation m_location; - std::unique_ptr<ExecutionContextTask> m_task; - - ClientTask(const WebTraceLocation&, std::unique_ptr<ExecutionContextTask>); - ~ClientTask(); - - ClientTask(ClientTask&&); - }; - - ~MainThreadSyncBridge() override; - - void forwardTaskToWorker(const WebTraceLocation&, std::unique_ptr<ExecutionContextTask>) override; - void forwardTaskToWorkerOnLoaderDone(const WebTraceLocation&, std::unique_ptr<ExecutionContextTask>) override; - - bool m_done; - std::unique_ptr<WaitableEvent> m_loaderDoneEvent; - // Thread-safety: |m_clientTasks| can be written (i.e. Closures are added) - // on the main thread only before |m_loaderDoneEvent| is signaled and can be read - // on the worker context thread only after |m_loaderDoneEvent| is signaled. - Vector<ClientTask> m_clientTasks; - Mutex m_lock; + // |*m_workerLoader| lives in the worker thread. + CrossThreadWeakPersistent<WorkerThreadableLoader> m_workerLoader; }; WorkerThreadableLoader(WorkerGlobalScope&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&, BlockingBehavior); + void didStart(Peer*); - Persistent<WorkerGlobalScope> m_workerGlobalScope; - const Persistent<ThreadableLoaderClientWrapper> m_workerClientWrapper; + void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent); + void didReceiveResponse(unsigned long identifier, std::unique_ptr<CrossThreadResourceResponseData>, std::unique_ptr<WebDataConsumerHandle>); + void didReceiveData(std::unique_ptr<Vector<char>> data); + void didReceiveCachedMetadata(std::unique_ptr<Vector<char>> data); + void didFinishLoading(unsigned long identifier, double finishTime); + void didFail(const ResourceError&); + void didFailAccessControlCheck(const ResourceError&); + void didFailRedirectCheck(); + void didDownloadData(int dataLength); + void didReceiveResourceTiming(std::unique_ptr<CrossThreadResourceTimingInfoData>); - MainThreadBridgeBase* m_bridge; + Member<WorkerGlobalScope> m_workerGlobalScope; + RefPtr<WorkerLoaderProxy> m_workerLoaderProxy; + ThreadableLoaderClient* m_client; + + ThreadableLoaderOptions m_threadableLoaderOptions; + ResourceLoaderOptions m_resourceLoaderOptions; + BlockingBehavior m_blockingBehavior; + + // |*m_peer| lives in the main thread. + CrossThreadPersistent<Peer> m_peer; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/page/EventSource.cpp b/third_party/WebKit/Source/core/page/EventSource.cpp index 7a5b32e2..1cbd5d48 100644 --- a/third_party/WebKit/Source/core/page/EventSource.cpp +++ b/third_party/WebKit/Source/core/page/EventSource.cpp
@@ -360,6 +360,7 @@ DEFINE_TRACE(EventSource) { visitor->trace(m_parser); + visitor->trace(m_loader); EventTargetWithInlineData::trace(visitor); ActiveDOMObject::trace(visitor); EventSourceParser::Client::trace(visitor);
diff --git a/third_party/WebKit/Source/core/page/EventSource.h b/third_party/WebKit/Source/core/page/EventSource.h index 24c1598..0e6336e 100644 --- a/third_party/WebKit/Source/core/page/EventSource.h +++ b/third_party/WebKit/Source/core/page/EventSource.h
@@ -122,7 +122,7 @@ State m_state; Member<EventSourceParser> m_parser; - std::unique_ptr<ThreadableLoader> m_loader; + Member<ThreadableLoader> m_loader; Timer<EventSource> m_connectTimer; unsigned long long m_reconnectDelay;
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp index 429e18c4..d248345 100644 --- a/third_party/WebKit/Source/core/testing/Internals.cpp +++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -175,6 +175,8 @@ result = DocumentMarker::AllMarkers(); else if (equalIgnoringCase(markerType, "Spelling")) result = DocumentMarker::Spelling; + else if (equalIgnoringCase(markerType, "Grammar")) + result = DocumentMarker::Grammar; else if (equalIgnoringCase(markerType, "TextMatch")) result = DocumentMarker::TextMatch; else @@ -1610,6 +1612,15 @@ return result; } +bool Internals::hasGrammarMarker(Document* document, int from, int length) +{ + ASSERT(document); + if (!document->frame()) + return false; + + return document->frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length); +} + unsigned Internals::numberOfScrollableAreas(Document* document) { ASSERT(document);
diff --git a/third_party/WebKit/Source/core/testing/Internals.h b/third_party/WebKit/Source/core/testing/Internals.h index 6dacf270..674cd8d6 100644 --- a/third_party/WebKit/Source/core/testing/Internals.h +++ b/third_party/WebKit/Source/core/testing/Internals.h
@@ -209,6 +209,7 @@ unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowChildFrameContent, ExceptionState&) const; bool hasSpellingMarker(Document*, int from, int length); + bool hasGrammarMarker(Document*, int from, int length); void setContinuousSpellCheckingEnabled(bool); bool canHyphenate(const AtomicString& locale);
diff --git a/third_party/WebKit/Source/core/testing/Internals.idl b/third_party/WebKit/Source/core/testing/Internals.idl index e1affa68..64012a1 100644 --- a/third_party/WebKit/Source/core/testing/Internals.idl +++ b/third_party/WebKit/Source/core/testing/Internals.idl
@@ -160,6 +160,7 @@ boolean ignoreClipping, boolean allowChildFrameContent); boolean hasSpellingMarker(Document document, long from, long length); + boolean hasGrammarMarker(Document document, long from, long length); void setContinuousSpellCheckingEnabled(boolean enabled); bool canHyphenate(DOMString locale);
diff --git a/third_party/WebKit/Source/core/workers/WorkerEventQueue.cpp b/third_party/WebKit/Source/core/workers/WorkerEventQueue.cpp index 0439a3d..94e74bc 100644 --- a/third_party/WebKit/Source/core/workers/WorkerEventQueue.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerEventQueue.cpp
@@ -30,7 +30,6 @@ #include "core/dom/ExecutionContextTask.h" #include "core/events/Event.h" #include "core/inspector/InspectorInstrumentation.h" -#include "wtf/PtrUtil.h" namespace blink { @@ -47,98 +46,58 @@ WorkerEventQueue::~WorkerEventQueue() { - DCHECK(m_eventTaskMap.isEmpty()); + DCHECK(m_pendingEvents.isEmpty()); } DEFINE_TRACE(WorkerEventQueue) { visitor->trace(m_executionContext); - visitor->trace(m_eventTaskMap); + visitor->trace(m_pendingEvents); EventQueue::trace(visitor); } -class WorkerEventQueue::EventDispatcherTask : public ExecutionContextTask { -public: - static std::unique_ptr<EventDispatcherTask> create(Event* event, WorkerEventQueue* eventQueue) - { - return wrapUnique(new EventDispatcherTask(event, eventQueue)); - } - - ~EventDispatcherTask() override - { - if (m_event) { - InspectorInstrumentation::asyncTaskCanceled(m_event->target()->getExecutionContext(), m_event); - m_eventQueue->m_eventTaskMap.remove(m_event); - } - } - - void dispatchEvent(ExecutionContext* context, Event* event) - { - InspectorInstrumentation::AsyncTask asyncTask(context, event); - event->target()->dispatchEvent(event); - } - - virtual void performTask(ExecutionContext* context) - { - if (m_isCancelled) - return; - - m_eventQueue->m_eventTaskMap.remove(m_event.get()); - dispatchEvent(context, m_event); - m_event.clear(); - } - - void cancel() - { - m_isCancelled = true; - m_event.clear(); - } - -private: - EventDispatcherTask(Event* event, WorkerEventQueue* eventQueue) - : m_event(event) - , m_eventQueue(eventQueue) - , m_isCancelled(false) - { - } - - Persistent<Event> m_event; - Persistent<WorkerEventQueue> m_eventQueue; - bool m_isCancelled; -}; - bool WorkerEventQueue::enqueueEvent(Event* event) { if (m_isClosed) return false; InspectorInstrumentation::asyncTaskScheduled(event->target()->getExecutionContext(), event->type(), event); - std::unique_ptr<EventDispatcherTask> task = EventDispatcherTask::create(event, this); - m_eventTaskMap.add(event, task.get()); - m_executionContext->postTask(BLINK_FROM_HERE, std::move(task)); + m_pendingEvents.add(event); + m_executionContext->postTask(BLINK_FROM_HERE, createSameThreadTask(&WorkerEventQueue::dispatchEvent, wrapPersistent(this), wrapWeakPersistent(event))); return true; } bool WorkerEventQueue::cancelEvent(Event* event) { - EventDispatcherTask* task = m_eventTaskMap.get(event); - if (!task) + if (!removeEvent(event)) return false; - task->cancel(); InspectorInstrumentation::asyncTaskCanceled(event->target()->getExecutionContext(), event); - m_eventTaskMap.remove(event); return true; } void WorkerEventQueue::close() { m_isClosed = true; - for (const auto& entry : m_eventTaskMap) { - Event* event = entry.key.get(); - EventDispatcherTask* task = entry.value; + for (const auto& event : m_pendingEvents) InspectorInstrumentation::asyncTaskCanceled(event->target()->getExecutionContext(), event); - task->cancel(); - } - m_eventTaskMap.clear(); + m_pendingEvents.clear(); +} + +bool WorkerEventQueue::removeEvent(Event* event) +{ + auto found = m_pendingEvents.find(event); + if (found == m_pendingEvents.end()) + return false; + m_pendingEvents.remove(found); + return true; +} + +void WorkerEventQueue::dispatchEvent(Event* event, ExecutionContext* executionContext) +{ + if (!event || !removeEvent(event)) + return; + + InspectorInstrumentation::AsyncTask asyncTask(executionContext, event); + event->target()->dispatchEvent(event); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerEventQueue.h b/third_party/WebKit/Source/core/workers/WorkerEventQueue.h index d61230a6..bb69c809e 100644 --- a/third_party/WebKit/Source/core/workers/WorkerEventQueue.h +++ b/third_party/WebKit/Source/core/workers/WorkerEventQueue.h
@@ -28,7 +28,6 @@ #define WorkerEventQueue_h #include "core/events/EventQueue.h" -#include "wtf/HashMap.h" #include "wtf/HashSet.h" namespace blink { @@ -50,13 +49,13 @@ private: explicit WorkerEventQueue(ExecutionContext*); + bool removeEvent(Event*); + void dispatchEvent(Event*, ExecutionContext*); Member<ExecutionContext> m_executionContext; bool m_isClosed; - class EventDispatcherTask; - using EventTaskMap = HeapHashMap<Member<Event>, EventDispatcherTask*>; - EventTaskMap m_eventTaskMap; + HeapHashSet<Member<Event>> m_pendingEvents; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.h b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.h index 58131ad..59fe7583 100644 --- a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.h +++ b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.h
@@ -114,7 +114,7 @@ std::unique_ptr<WTF::Closure> m_responseCallback; std::unique_ptr<WTF::Closure> m_finishedCallback; - std::unique_ptr<ThreadableLoader> m_threadableLoader; + Persistent<ThreadableLoader> m_threadableLoader; String m_responseEncoding; std::unique_ptr<TextResourceDecoder> m_decoder; StringBuilder m_script;
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp index 2170fac..463ebb703 100644 --- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp +++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -165,7 +165,7 @@ void cancel() { - m_loader.cancel(); + m_loader->cancel(); } DEFINE_INLINE_TRACE() @@ -176,13 +176,13 @@ private: BlobLoader(XMLHttpRequest* xhr, PassRefPtr<BlobDataHandle> handle) : m_xhr(xhr) - , m_loader(FileReaderLoader::ReadByClient, this) + , m_loader(FileReaderLoader::create(FileReaderLoader::ReadByClient, this)) { - m_loader.start(m_xhr->getExecutionContext(), handle); + m_loader->start(m_xhr->getExecutionContext(), handle); } Member<XMLHttpRequest> m_xhr; - FileReaderLoader m_loader; + std::unique_ptr<FileReaderLoader> m_loader; }; XMLHttpRequest* XMLHttpRequest::create(ScriptState* scriptState) @@ -1024,7 +1024,7 @@ // If, window.onload contains open() and send(), m_loader will be set to // non 0 value. So, we cannot continue the outer open(). In such case, // just abort the outer open() by returning false. - std::unique_ptr<ThreadableLoader> loader = std::move(m_loader); + ThreadableLoader* loader = m_loader.release(); loader->cancel(); // If abort() called internalAbort() and a nested open() ended up @@ -1707,6 +1707,7 @@ { visitor->trace(m_responseBlob); visitor->trace(m_responseLegacyStream); + visitor->trace(m_loader); visitor->trace(m_responseDocument); visitor->trace(m_responseDocumentParser); visitor->trace(m_responseArrayBuffer);
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h index 526d9283b..5614333c 100644 --- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h +++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h
@@ -265,7 +265,7 @@ Member<Blob> m_responseBlob; Member<Stream> m_responseLegacyStream; - std::unique_ptr<ThreadableLoader> m_loader; + Member<ThreadableLoader> m_loader; State m_state; ResourceResponse m_response;
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js index 6507123..ab3f4c6 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js +++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js
@@ -229,7 +229,8 @@ * @param {string=} additionalCssClassName * @return {boolean} */ - setSearchRegex: function(regex, additionalCssClassName) { + setSearchRegex: function(regex, additionalCssClassName) + { var cssClasses = WebInspector.highlightedSearchResultClassName; if (additionalCssClassName) cssClasses += " " + additionalCssClassName; @@ -237,7 +238,7 @@ this._applySearch(regex, this.nameElement, cssClasses); var valueType = this.property.value.type; - if (valueType !== "object" && valueType !== "array") + if (valueType !== "object") this._applySearch(regex, this.valueElement, cssClasses); return !!this._highlightChanges.length;
diff --git a/third_party/WebKit/Source/devtools/front_end/components/RemoteObjectPreviewFormatter.js b/third_party/WebKit/Source/devtools/front_end/components/RemoteObjectPreviewFormatter.js index 8121eac3..310ee14 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/RemoteObjectPreviewFormatter.js +++ b/third_party/WebKit/Source/devtools/front_end/components/RemoteObjectPreviewFormatter.js
@@ -21,7 +21,7 @@ parentElement.appendChild(this.renderPropertyPreview(preview.type, preview.subtype, description)); return; } - if (description && preview.subtype !== "array") { + if (description && preview.subtype !== "array" && preview.subtype !== "typedarray") { var text = preview.subtype ? description : this._abbreviateFullQualifiedClassName(description); parentElement.createTextChildren(text, " "); } @@ -49,7 +49,7 @@ */ _appendPropertiesPreview: function(parentElement, preview) { - var isArray = preview.subtype === "array"; + var isArray = preview.subtype === "array" || preview.subtype === "typedarray"; var arrayLength = WebInspector.RemoteObject.arrayLength(preview); var properties = preview.properties; if (isArray)
diff --git a/third_party/WebKit/Source/devtools/front_end/components/objectValue.css b/third_party/WebKit/Source/devtools/front_end/components/objectValue.css index 667cca9..78c3e65c 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/objectValue.css +++ b/third_party/WebKit/Source/devtools/front_end/components/objectValue.css
@@ -39,11 +39,13 @@ } .object-value-object, +.object-value-promise, .object-value-map, .object-value-set, .object-value-iterator, .object-value-generator, .object-value-node, +.object-value-typedarray, .object-value-array { position: relative; vertical-align: baseline; @@ -84,20 +86,25 @@ } .object-value-object .section, +.object-value-promise .section, .object-formatted-map .section, .object-value-set .section, .object-value-iterator .section, .object-value-generator .section, .object-value-node .section, +.object-value-typedarray .section, .object-value-array .section { position: static; } -.object-value-object .section > .header::before { + +.object-value-object .section > .header::before, +.object-value-promise .section > .header::before { margin-top: 0; } .object-value-object .properties-tree, +.object-value-promise .properties-tree, .object-value-map .properties-tree, .object-value-set .properties-tree, .object-value-iterator .properties-tree,
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js index 6be49043..b2e0855 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js +++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
@@ -49,6 +49,7 @@ /** @type {!Object.<string, function(!WebInspector.RemoteObject, !Element, boolean=)>} */ this._customFormatters = { "array": this._formatParameterAsArray, + "typedarray": this._formatParameterAsArray, "error": this._formatParameterAsError, "function": this._formatParameterAsFunction, "generator": this._formatParameterAsObject, @@ -56,6 +57,7 @@ "map": this._formatParameterAsObject, "node": this._formatParameterAsNode, "object": this._formatParameterAsObject, + "promise": this._formatParameterAsObject, "proxy": this._formatParameterAsObject, "set": this._formatParameterAsObject, "string": this._formatParameterAsString @@ -711,7 +713,7 @@ { if (this._message.type === WebInspector.ConsoleMessage.MessageType.DirXML) { // Prevent infinite expansion of cross-referencing arrays. - return this._formatParameter(output, output.subtype === "array", false); + return this._formatParameter(output, output.subtype === "array" || output.subtype === "typedarray", false); } return this._previewFormatter.renderPropertyPreview(output.type, output.subtype, output.description); },
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js index f14fe2a..cf7f738 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
@@ -315,7 +315,7 @@ */ WebInspector.RemoteObject.arrayLength = function(object) { - if (object.subtype !== "array") + if (object.subtype !== "array" && object.subtype !== "typedarray") return 0; var matches = object.description.match(/\[([0-9]+)\]/); if (!matches) @@ -1327,7 +1327,7 @@ */ WebInspector.RemoteArray.objectAsArray = function(object) { - if (!object || object.type !== "object" || object.subtype !== "array") + if (!object || object.type !== "object" || (object.subtype !== "array" && object.subtype !== "typedarray")) throw new Error("Object is empty or not an array"); return new WebInspector.RemoteArray(object); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js index 75a28f9..3827720b 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js
@@ -686,7 +686,7 @@ var resultSet = {}; try { for (var o = object; o; o = Object.getPrototypeOf(o)) { - if (type === "array" && o === object && ArrayBuffer.isView(o) && o.length > 9999) + if ((type === "array" || type === "typedarray") && o === object && ArrayBuffer.isView(o) && o.length > 9999) continue; var names = Object.getOwnPropertyNames(o); var isArray = Array.isArray(o);
diff --git a/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp b/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp index 33a1b2df..b1893de4 100644 --- a/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp +++ b/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp
@@ -9,6 +9,7 @@ #include "core/dom/DOMArrayBufferView.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" +#include "core/fetch/FetchUtils.h" #include "core/fileapi/Blob.h" #include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" @@ -111,16 +112,25 @@ int bytes = 0; bool allowed; - if (data.isArrayBufferView()) + if (data.isArrayBufferView()) { allowed = BeaconLoader::sendBeacon(impl.frame(), allowance, url, data.getAsArrayBufferView(), bytes); - else if (data.isBlob()) - allowed = BeaconLoader::sendBeacon(impl.frame(), allowance, url, data.getAsBlob(), bytes); - else if (data.isString()) + } else if (data.isBlob()) { + Blob* blob = data.getAsBlob(); + if (!FetchUtils::isSimpleContentType(AtomicString(blob->type()))) { + UseCounter::count(context, UseCounter::SendBeaconWithNonSimpleContentType); + if (RuntimeEnabledFeatures::sendBeaconThrowForBlobWithNonSimpleTypeEnabled()) { + exceptionState.throwSecurityError("sendBeacon() with a Blob whose type is not CORS-safelisted MIME type is disallowed experimentally. See http://crbug.com/490015 for details."); + return false; + } + } + allowed = BeaconLoader::sendBeacon(impl.frame(), allowance, url, blob, bytes); + } else if (data.isString()) { allowed = BeaconLoader::sendBeacon(impl.frame(), allowance, url, data.getAsString(), bytes); - else if (data.isFormData()) + } else if (data.isFormData()) { allowed = BeaconLoader::sendBeacon(impl.frame(), allowance, url, data.getAsFormData(), bytes); - else + } else { allowed = BeaconLoader::sendBeacon(impl.frame(), allowance, url, String(), bytes); + } return impl.beaconResult(context, allowed, bytes); }
diff --git a/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp b/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp index 83ed30b..a7db03f 100644 --- a/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp +++ b/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp
@@ -34,7 +34,7 @@ class FakeLoaderFactory : public FetchBlobDataConsumerHandle::LoaderFactory { public: - std::unique_ptr<ThreadableLoader> create(ExecutionContext&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&) override + ThreadableLoader* create(ExecutionContext&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&) override { ASSERT_NOT_REACHED(); return nullptr;
diff --git a/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.cpp b/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.cpp index 5db39ff..11474211 100644 --- a/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.cpp +++ b/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.cpp
@@ -76,7 +76,7 @@ m_updater->update(createUnexpectedErrorDataConsumerHandle()); if (m_loader) { m_loader->cancel(); - m_loader.reset(); + m_loader = nullptr; } } @@ -103,7 +103,7 @@ } private: - std::unique_ptr<ThreadableLoader> createLoader(ExecutionContext* executionContext, ThreadableLoaderClient* client) const + ThreadableLoader* createLoader(ExecutionContext* executionContext, ThreadableLoaderClient* client) const { ThreadableLoaderOptions options; options.preflightPolicy = ConsiderPreflight; @@ -134,14 +134,14 @@ void didFinishLoading(unsigned long, double) override { - m_loader.reset(); + m_loader = nullptr; } void didFail(const ResourceError&) override { if (!m_receivedResponse) m_updater->update(createUnexpectedErrorDataConsumerHandle()); - m_loader.reset(); + m_loader = nullptr; } void didFailRedirectCheck() override @@ -154,14 +154,14 @@ RefPtr<BlobDataHandle> m_blobDataHandle; Persistent<FetchBlobDataConsumerHandle::LoaderFactory> m_loaderFactory; - std::unique_ptr<ThreadableLoader> m_loader; + Persistent<ThreadableLoader> m_loader; bool m_receivedResponse; }; class DefaultLoaderFactory final : public FetchBlobDataConsumerHandle::LoaderFactory { public: - std::unique_ptr<ThreadableLoader> create( + ThreadableLoader* create( ExecutionContext& executionContext, ThreadableLoaderClient* client, const ThreadableLoaderOptions& options,
diff --git a/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.h b/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.h index d484f78..e7c867b7 100644 --- a/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.h +++ b/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.h
@@ -25,7 +25,7 @@ public: class MODULES_EXPORT LoaderFactory : public GarbageCollectedFinalized<LoaderFactory> { public: - virtual std::unique_ptr<ThreadableLoader> create(ExecutionContext&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&) = 0; + virtual ThreadableLoader* create(ExecutionContext&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&) = 0; virtual ~LoaderFactory() { } DEFINE_INLINE_VIRTUAL_TRACE() { } };
diff --git a/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandleTest.cpp b/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandleTest.cpp index 50c03d4..b49316ca 100644 --- a/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandleTest.cpp +++ b/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandleTest.cpp
@@ -53,12 +53,7 @@ class MockLoaderFactory : public FetchBlobDataConsumerHandle::LoaderFactory { public: - std::unique_ptr<ThreadableLoader> create(ExecutionContext& executionContext, ThreadableLoaderClient* client, const ThreadableLoaderOptions& threadableLoaderOptions, const ResourceLoaderOptions& resourceLoaderOptions) override - { - return wrapUnique(createInternal(executionContext, client, threadableLoaderOptions, resourceLoaderOptions)); - } - - MOCK_METHOD4(createInternal, ThreadableLoader*(ExecutionContext&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&)); + MOCK_METHOD4(create, ThreadableLoader*(ExecutionContext&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&)); }; PassRefPtr<BlobDataHandle> createBlobDataHandle(const char* s) @@ -100,18 +95,17 @@ ThreadableLoaderOptions options; ResourceLoaderOptions resourceLoaderOptions; - std::unique_ptr<MockThreadableLoader> loader = MockThreadableLoader::create(); - MockThreadableLoader* loaderPtr = loader.get(); + Persistent<MockThreadableLoader> loader = MockThreadableLoader::create(); InSequence s; EXPECT_CALL(checkpoint, Call(1)); - EXPECT_CALL(*factory, createInternal(Ref(document()), _, _, _)).WillOnce(DoAll( + EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(DoAll( SaveArg<2>(&options), SaveArg<3>(&resourceLoaderOptions), - Return(loader.release()))); - EXPECT_CALL(*loaderPtr, start(_)).WillOnce(SaveArg<0>(&request)); + Return(loader.get()))); + EXPECT_CALL(*loader, start(_)).WillOnce(SaveArg<0>(&request)); EXPECT_CALL(checkpoint, Call(2)); - EXPECT_CALL(*loaderPtr, cancel()); + EXPECT_CALL(*loader, cancel()); RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time"); std::unique_ptr<WebDataConsumerHandle> handle @@ -145,15 +139,14 @@ auto factory = new StrictMock<MockLoaderFactory>; Checkpoint checkpoint; - std::unique_ptr<MockThreadableLoader> loader = MockThreadableLoader::create(); - MockThreadableLoader* loaderPtr = loader.get(); + Persistent<MockThreadableLoader> loader = MockThreadableLoader::create(); InSequence s; EXPECT_CALL(checkpoint, Call(1)); - EXPECT_CALL(*factory, createInternal(Ref(document()), _, _, _)).WillOnce(Return(loader.release())); - EXPECT_CALL(*loaderPtr, start(_)); + EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(Return(loader.get())); + EXPECT_CALL(*loader, start(_)); EXPECT_CALL(checkpoint, Call(2)); - EXPECT_CALL(*loaderPtr, cancel()); + EXPECT_CALL(*loader, cancel()); EXPECT_CALL(checkpoint, Call(3)); RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time"); @@ -175,16 +168,15 @@ auto factory = new StrictMock<MockLoaderFactory>; Checkpoint checkpoint; - std::unique_ptr<MockThreadableLoader> loader = MockThreadableLoader::create(); - MockThreadableLoader* loaderPtr = loader.get(); + Persistent<MockThreadableLoader> loader = MockThreadableLoader::create(); InSequence s; EXPECT_CALL(checkpoint, Call(1)); - EXPECT_CALL(*factory, createInternal(Ref(document()), _, _, _)).WillOnce(Return(loader.release())); - EXPECT_CALL(*loaderPtr, start(_)); + EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(Return(loader.get())); + EXPECT_CALL(*loader, start(_)); EXPECT_CALL(checkpoint, Call(2)); EXPECT_CALL(checkpoint, Call(3)); - EXPECT_CALL(*loaderPtr, cancel()); + EXPECT_CALL(*loader, cancel()); EXPECT_CALL(checkpoint, Call(4)); RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time"); @@ -210,16 +202,15 @@ auto factory = new StrictMock<MockLoaderFactory>; Checkpoint checkpoint; - std::unique_ptr<MockThreadableLoader> loader = MockThreadableLoader::create(); - MockThreadableLoader* loaderPtr = loader.get(); + Persistent<MockThreadableLoader> loader = MockThreadableLoader::create(); ThreadableLoaderClient* client = nullptr; InSequence s; EXPECT_CALL(checkpoint, Call(1)); - EXPECT_CALL(*factory, createInternal(Ref(document()), _, _, _)).WillOnce(DoAll(SaveArg<1>(&client), Return(loader.release()))); - EXPECT_CALL(*loaderPtr, start(_)); + EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(DoAll(SaveArg<1>(&client), Return(loader.get()))); + EXPECT_CALL(*loader, start(_)); EXPECT_CALL(checkpoint, Call(2)); - EXPECT_CALL(*loaderPtr, cancel()); + EXPECT_CALL(*loader, cancel()); RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time"); std::unique_ptr<WebDataConsumerHandle> handle @@ -249,16 +240,15 @@ auto factory = new StrictMock<MockLoaderFactory>; Checkpoint checkpoint; - std::unique_ptr<MockThreadableLoader> loader = MockThreadableLoader::create(); - MockThreadableLoader* loaderPtr = loader.get(); + Persistent<MockThreadableLoader> loader = MockThreadableLoader::create(); ThreadableLoaderClient* client = nullptr; InSequence s; EXPECT_CALL(checkpoint, Call(1)); - EXPECT_CALL(*factory, createInternal(Ref(document()), _, _, _)).WillOnce(DoAll(SaveArg<1>(&client), Return(loader.release()))); - EXPECT_CALL(*loaderPtr, start(_)); + EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(DoAll(SaveArg<1>(&client), Return(loader.get()))); + EXPECT_CALL(*loader, start(_)); EXPECT_CALL(checkpoint, Call(2)); - EXPECT_CALL(*loaderPtr, cancel()); + EXPECT_CALL(*loader, cancel()); RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time"); std::unique_ptr<WebDataConsumerHandle> handle @@ -288,14 +278,13 @@ auto factory = new StrictMock<MockLoaderFactory>; Checkpoint checkpoint; - std::unique_ptr<MockThreadableLoader> loader = MockThreadableLoader::create(); - MockThreadableLoader* loaderPtr = loader.get(); + Persistent<MockThreadableLoader> loader = MockThreadableLoader::create(); ThreadableLoaderClient* client = nullptr; InSequence s; EXPECT_CALL(checkpoint, Call(1)); - EXPECT_CALL(*factory, createInternal(Ref(document()), _, _, _)).WillOnce(DoAll(SaveArg<1>(&client), Return(loader.release()))); - EXPECT_CALL(*loaderPtr, start(_)); + EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(DoAll(SaveArg<1>(&client), Return(loader.get()))); + EXPECT_CALL(*loader, start(_)); EXPECT_CALL(checkpoint, Call(2)); RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time"); @@ -318,16 +307,15 @@ auto factory = new StrictMock<MockLoaderFactory>; Checkpoint checkpoint; - std::unique_ptr<MockThreadableLoader> loader = MockThreadableLoader::create(); - MockThreadableLoader* loaderPtr = loader.get(); + Persistent<MockThreadableLoader> loader = MockThreadableLoader::create(); ThreadableLoaderClient* client = nullptr; InSequence s; EXPECT_CALL(checkpoint, Call(1)); - EXPECT_CALL(*factory, createInternal(Ref(document()), _, _, _)).WillOnce(DoAll(SaveArg<1>(&client), Return(loader.release()))); - EXPECT_CALL(*loaderPtr, start(_)); + EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(DoAll(SaveArg<1>(&client), Return(loader.get()))); + EXPECT_CALL(*loader, start(_)); EXPECT_CALL(checkpoint, Call(2)); - EXPECT_CALL(*loaderPtr, cancel()); + EXPECT_CALL(*loader, cancel()); RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time"); std::unique_ptr<WebDataConsumerHandle> handle
diff --git a/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandleTest.cpp b/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandleTest.cpp index f45c7443..ae801dc 100644 --- a/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandleTest.cpp +++ b/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandleTest.cpp
@@ -52,14 +52,14 @@ explicit LoaderFactory(std::unique_ptr<WebDataConsumerHandle> handle) : m_client(nullptr) , m_handle(std::move(handle)) {} - std::unique_ptr<ThreadableLoader> create(ExecutionContext&, ThreadableLoaderClient* client, const ThreadableLoaderOptions&, const ResourceLoaderOptions&) override + ThreadableLoader* create(ExecutionContext&, ThreadableLoaderClient* client, const ThreadableLoaderOptions&, const ResourceLoaderOptions&) override { m_client = client; - std::unique_ptr<MockThreadableLoader> loader = MockThreadableLoader::create(); + MockThreadableLoader* loader = MockThreadableLoader::create(); EXPECT_CALL(*loader, start(_)).WillOnce(InvokeWithoutArgs(this, &LoaderFactory::handleDidReceiveResponse)); EXPECT_CALL(*loader, cancel()).Times(1); - return std::move(loader); + return loader; } private:
diff --git a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp index 0acdab5..f8773e7 100644 --- a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp +++ b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
@@ -169,7 +169,7 @@ Member<FetchManager> m_fetchManager; Member<ScriptPromiseResolver> m_resolver; Member<FetchRequestData> m_request; - std::unique_ptr<ThreadableLoader> m_loader; + Member<ThreadableLoader> m_loader; bool m_failed; bool m_finished; int m_responseHttpStatusCode; @@ -204,6 +204,7 @@ visitor->trace(m_fetchManager); visitor->trace(m_resolver); visitor->trace(m_request); + visitor->trace(m_loader); visitor->trace(m_integrityVerifier); visitor->trace(m_executionContext); } @@ -524,7 +525,7 @@ m_fetchManager = nullptr; if (m_loader) { m_loader->cancel(); - m_loader.reset(); + m_loader = nullptr; } m_executionContext = nullptr; }
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.cpp b/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.cpp index 298931c6..530aee3 100644 --- a/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.cpp +++ b/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.cpp
@@ -65,11 +65,7 @@ m_stopped = true; if (m_threadableLoader) { m_threadableLoader->cancel(); - // WorkerThreadableLoader keeps a Persistent<WorkerGlobalScope> to the - // ExecutionContext it received in |create|. Kill it to prevent - // reference cycles involving a mix of GC and non-GC types that fail to - // clear in ThreadState::cleanup. - m_threadableLoader.reset(); + m_threadableLoader = nullptr; } }
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.h b/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.h index 363b4fb..59f48804 100644 --- a/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.h +++ b/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.h
@@ -46,7 +46,10 @@ void didFail(const ResourceError&) override; void didFailRedirectCheck() override; - DEFINE_INLINE_TRACE() {} + DEFINE_INLINE_TRACE() + { + visitor->trace(m_threadableLoader); + } private: void runCallbackWithEmptyBitmap(); @@ -55,7 +58,7 @@ double m_startTime; RefPtr<SharedBuffer> m_data; std::unique_ptr<ImageCallback> m_imageCallback; - std::unique_ptr<ThreadableLoader> m_threadableLoader; + Member<ThreadableLoader> m_threadableLoader; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp b/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp index c1ccce2..7540e00 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp
@@ -123,9 +123,9 @@ public: BlobLoader(PassRefPtr<BlobDataHandle> blobDataHandle, PresentationConnection* PresentationConnection) : m_PresentationConnection(PresentationConnection) - , m_loader(FileReaderLoader::ReadAsArrayBuffer, this) + , m_loader(FileReaderLoader::create(FileReaderLoader::ReadAsArrayBuffer, this)) { - m_loader.start(m_PresentationConnection->getExecutionContext(), blobDataHandle); + m_loader->start(m_PresentationConnection->getExecutionContext(), blobDataHandle); } ~BlobLoader() override { } @@ -134,7 +134,7 @@ void didReceiveData() override { } void didFinishLoading() override { - m_PresentationConnection->didFinishLoadingBlob(m_loader.arrayBufferResult()); + m_PresentationConnection->didFinishLoadingBlob(m_loader->arrayBufferResult()); } void didFail(FileError::ErrorCode errorCode) override { @@ -143,7 +143,7 @@ void cancel() { - m_loader.cancel(); + m_loader->cancel(); } DEFINE_INLINE_TRACE() @@ -153,7 +153,7 @@ private: Member<PresentationConnection> m_PresentationConnection; - FileReaderLoader m_loader; + std::unique_ptr<FileReaderLoader> m_loader; }; PresentationConnection::PresentationConnection(LocalFrame* frame, const String& id, const String& url)
diff --git a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp index c6dc5fa..ee55c5bbc 100644 --- a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp +++ b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp
@@ -51,18 +51,19 @@ #include "platform/Histogram.h" #include "platform/Logging.h" #include "platform/blob/BlobData.h" -#include "platform/heap/Handle.h" #include "platform/weborigin/KnownPorts.h" #include "platform/weborigin/SecurityOrigin.h" #include "public/platform/Platform.h" #include "public/platform/WebInsecureRequestPolicy.h" #include "wtf/Assertions.h" #include "wtf/HashSet.h" +#include "wtf/MathExtras.h" #include "wtf/StdLibExtras.h" #include "wtf/text/CString.h" #include "wtf/text/StringBuilder.h" -#include "wtf/text/WTFString.h" -#include <memory> + +static const size_t kMaxByteSizeForHistogram = 100 * 1000 * 1000; +static const int32_t kBucketCountForMessageSizeHistogram = 50; namespace blink { @@ -227,6 +228,7 @@ , m_consumedBufferedAmount(0) , m_bufferedAmountAfterClose(0) , m_binaryType(BinaryTypeBlob) + , m_binaryTypeChangesAfterOpen(0) , m_subprotocol("") , m_extensions("") , m_eventQueue(EventQueue::create(this)) @@ -381,6 +383,13 @@ m_channel = nullptr; } +void DOMWebSocket::logBinaryTypeChangesAfterOpen() +{ + DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, binaryTypeChangesHistogram, new CustomCountHistogram("WebCore.WebSocket.BinaryTypeChangesAfterOpen", 1, 1024, 10)); + DVLOG(3) << "WebSocket " << static_cast<void*>(this) << " logBinaryTypeChangesAfterOpen() logging " << m_binaryTypeChangesAfterOpen; + binaryTypeChangesHistogram.count(m_binaryTypeChangesAfterOpen); +} + void DOMWebSocket::send(const String& message, ExceptionState& exceptionState) { CString encodedMessage = message.utf8(); @@ -416,7 +425,7 @@ return; } recordSendTypeHistogram(WebSocketSendTypeArrayBuffer); - + recordSendMessageSizeHistogram(WebSocketSendTypeArrayBuffer, binaryData->byteLength()); ASSERT(m_channel); m_bufferedAmount += binaryData->byteLength(); m_channel->send(*binaryData, 0, binaryData->byteLength()); @@ -435,7 +444,7 @@ return; } recordSendTypeHistogram(WebSocketSendTypeArrayBufferView); - + recordSendMessageSizeHistogram(WebSocketSendTypeArrayBufferView, arrayBufferView->byteLength()); ASSERT(m_channel); m_bufferedAmount += arrayBufferView->byteLength(); m_channel->send(*arrayBufferView->buffer(), arrayBufferView->byteOffset(), arrayBufferView->byteLength()); @@ -453,9 +462,9 @@ updateBufferedAmountAfterClose(binaryData->size()); return; } - recordSendTypeHistogram(WebSocketSendTypeBlob); - unsigned long long size = binaryData->size(); + recordSendTypeHistogram(WebSocketSendTypeBlob); + recordSendMessageSizeHistogram(WebSocketSendTypeBlob, clampTo<size_t>(size, 0, kMaxByteSizeForHistogram)); m_bufferedAmount += size; ASSERT(m_channel); @@ -564,16 +573,25 @@ void DOMWebSocket::setBinaryType(const String& binaryType) { if (binaryType == "blob") { - m_binaryType = BinaryTypeBlob; + setBinaryTypeInternal(BinaryTypeBlob); return; } if (binaryType == "arraybuffer") { - m_binaryType = BinaryTypeArrayBuffer; + setBinaryTypeInternal(BinaryTypeArrayBuffer); return; } ASSERT_NOT_REACHED(); } +void DOMWebSocket::setBinaryTypeInternal(BinaryType binaryType) +{ + if (m_binaryType == binaryType) + return; + m_binaryType = binaryType; + if (m_state == kOpen || m_state == kClosing) + ++m_binaryTypeChangesAfterOpen; +} + const AtomicString& DOMWebSocket::interfaceName() const { return EventTargetNames::DOMWebSocket; @@ -614,7 +632,10 @@ m_channel->close(WebSocketChannel::CloseEventCodeGoingAway, String()); releaseChannel(); } - m_state = kClosed; + if (m_state != kClosed) { + m_state = kClosed; + logBinaryTypeChangesAfterOpen(); + } } void DOMWebSocket::didConnect(const String& subprotocol, const String& extensions) @@ -650,6 +671,7 @@ blobData->appendData(rawData.release(), 0, BlobDataItem::toEndOfFile); Blob* blob = Blob::create(BlobDataHandle::create(std::move(blobData), size)); recordReceiveTypeHistogram(WebSocketReceiveTypeBlob); + recordReceiveMessageSizeHistogram(WebSocketReceiveTypeBlob, size); m_eventQueue->dispatch(MessageEvent::create(blob, SecurityOrigin::create(m_url)->toString())); break; } @@ -657,6 +679,7 @@ case BinaryTypeArrayBuffer: DOMArrayBuffer* arrayBuffer = DOMArrayBuffer::create(binaryData->data(), binaryData->size()); recordReceiveTypeHistogram(WebSocketReceiveTypeArrayBuffer); + recordReceiveMessageSizeHistogram(WebSocketReceiveTypeArrayBuffer, binaryData->size()); m_eventQueue->dispatch(MessageEvent::create(arrayBuffer, SecurityOrigin::create(m_url)->toString())); break; } @@ -666,6 +689,7 @@ { WTF_LOG(Network, "WebSocket %p didError()", this); m_state = kClosed; + logBinaryTypeChangesAfterOpen(); m_eventQueue->dispatch(Event::create(EventTypeNames::error)); } @@ -707,12 +731,62 @@ sendTypeHistogram.count(type); } +void DOMWebSocket::recordSendMessageSizeHistogram(WebSocketSendType type, size_t size) +{ + // Truncate |size| to avoid overflowing int32_t. + int32_t sizeToCount = clampTo<int32_t>(size, 0, kMaxByteSizeForHistogram); + switch (type) { + case WebSocketSendTypeArrayBuffer: { + DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, arrayBufferMessageSizeHistogram, new CustomCountHistogram("WebCore.WebSocket.MessageSize.Send.ArrayBuffer", 1, kMaxByteSizeForHistogram, kBucketCountForMessageSizeHistogram)); + arrayBufferMessageSizeHistogram.count(sizeToCount); + return; + } + + case WebSocketSendTypeArrayBufferView: { + DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, arrayBufferViewMessageSizeHistogram, new CustomCountHistogram("WebCore.WebSocket.MessageSize.Send.ArrayBufferView", 1, kMaxByteSizeForHistogram, kBucketCountForMessageSizeHistogram)); + arrayBufferViewMessageSizeHistogram.count(sizeToCount); + return; + } + + case WebSocketSendTypeBlob: { + DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, blobMessageSizeHistogram, new CustomCountHistogram("WebCore.WebSocket.MessageSize.Send.Blob", 1, kMaxByteSizeForHistogram, kBucketCountForMessageSizeHistogram)); + blobMessageSizeHistogram.count(sizeToCount); + return; + } + + default: + NOTREACHED(); + } +} + void DOMWebSocket::recordReceiveTypeHistogram(WebSocketReceiveType type) { DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, receiveTypeHistogram, new EnumerationHistogram("WebCore.WebSocket.ReceiveType", WebSocketReceiveTypeMax)); receiveTypeHistogram.count(type); } +void DOMWebSocket::recordReceiveMessageSizeHistogram(WebSocketReceiveType type, size_t size) +{ + // Truncate |size| to avoid overflowing int32_t. + int32_t sizeToCount = clampTo<int32_t>(size, 0, kMaxByteSizeForHistogram); + switch (type) { + case WebSocketReceiveTypeArrayBuffer: { + DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, arrayBufferMessageSizeHistogram, new CustomCountHistogram("WebCore.WebSocket.MessageSize.Receive.ArrayBuffer", 1, kMaxByteSizeForHistogram, kBucketCountForMessageSizeHistogram)); + arrayBufferMessageSizeHistogram.count(sizeToCount); + return; + } + + case WebSocketReceiveTypeBlob: { + DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, blobMessageSizeHistogram, new CustomCountHistogram("WebCore.WebSocket.MessageSize.Receive.Blob", 1, kMaxByteSizeForHistogram, kBucketCountForMessageSizeHistogram)); + blobMessageSizeHistogram.count(sizeToCount); + return; + } + + default: + NOTREACHED(); + } +} + DEFINE_TRACE(DOMWebSocket) { visitor->trace(m_channel);
diff --git a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.h b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.h index d030d5d..0fd00ce 100644 --- a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.h +++ b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.h
@@ -49,6 +49,7 @@ #include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" #include <memory> +#include <stddef.h> #include <stdint.h> namespace blink { @@ -199,6 +200,11 @@ WebSocketReceiveTypeMax, }; + enum BinaryType { + BinaryTypeBlob, + BinaryTypeArrayBuffer + }; + // This function is virtual for unittests. // FIXME: Move WebSocketChannel::create here. virtual WebSocketChannel* createChannel(ExecutionContext* context, WebSocketChannelClient* client) @@ -221,12 +227,12 @@ void releaseChannel(); void recordSendTypeHistogram(WebSocketSendType); + void recordSendMessageSizeHistogram(WebSocketSendType, size_t); void recordReceiveTypeHistogram(WebSocketReceiveType); + void recordReceiveMessageSizeHistogram(WebSocketReceiveType, size_t); - enum BinaryType { - BinaryTypeBlob, - BinaryTypeArrayBuffer - }; + void setBinaryTypeInternal(BinaryType); + void logBinaryTypeChangesAfterOpen(); Member<WebSocketChannel> m_channel; @@ -238,6 +244,7 @@ uint64_t m_consumedBufferedAmount; uint64_t m_bufferedAmountAfterClose; BinaryType m_binaryType; + int m_binaryTypeChangesAfterOpen; // The subprotocol the server selected. String m_subprotocol; String m_extensions;
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp index b51bbc8..0f7f935 100644 --- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp +++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
@@ -80,7 +80,7 @@ private: Member<DocumentWebSocketChannel> m_channel; - FileReaderLoader m_loader; + std::unique_ptr<FileReaderLoader> m_loader; }; class DocumentWebSocketChannel::Message : public GarbageCollectedFinalized<DocumentWebSocketChannel::Message> { @@ -110,21 +110,21 @@ DocumentWebSocketChannel::BlobLoader::BlobLoader(PassRefPtr<BlobDataHandle> blobDataHandle, DocumentWebSocketChannel* channel) : m_channel(channel) - , m_loader(FileReaderLoader::ReadAsArrayBuffer, this) + , m_loader(FileReaderLoader::create(FileReaderLoader::ReadAsArrayBuffer, this)) { - m_loader.start(channel->getExecutionContext(), blobDataHandle); + m_loader->start(channel->getExecutionContext(), blobDataHandle); } void DocumentWebSocketChannel::BlobLoader::cancel() { - m_loader.cancel(); + m_loader->cancel(); // didFail will be called immediately. // |this| is deleted here. } void DocumentWebSocketChannel::BlobLoader::didFinishLoading() { - m_channel->didFinishLoadingBlob(m_loader.arrayBufferResult()); + m_channel->didFinishLoadingBlob(m_loader->arrayBufferResult()); // |this| is deleted here. }
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in index c06b026..659fc29 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -245,3 +245,4 @@ WeakMemoryCache DoNotUnlockSharedBuffer ParseHTMLOnMainThread status=test +SendBeaconThrowForBlobWithNonSimpleType status=experimental
diff --git a/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js b/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js index f66ce07..bccd668f 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js +++ b/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js
@@ -463,7 +463,7 @@ var skipGetOwnPropertyNames; try { - skipGetOwnPropertyNames = InjectedScriptHost.isTypedArray(object) && object.length > 500000; + skipGetOwnPropertyNames = InjectedScriptHost.subtype(object) === "typedarray" && object.length > 500000; } catch (e) { } @@ -611,7 +611,7 @@ return "Proxy"; var className = InjectedScriptHost.internalConstructorName(obj); - if (subtype === "array") { + if (subtype === "array" || subtype === "typedarray") { if (typeof obj.length === "number") className += "[" + obj.length + "]"; return className; @@ -913,7 +913,7 @@ continue; // Ignore length property of array. - if (this.subtype === "array" && name === "length") + if ((this.subtype === "array" || this.subtype === "typedarray") && name === "length") continue; // Ignore size property of map, set.
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp index 1ebdc3a..2eb34fb 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp
@@ -46,7 +46,6 @@ v8::Local<v8::External> debuggerExternal = v8::External::New(isolate, inspector); setFunctionProperty(context, injectedScriptHost, "internalConstructorName", V8InjectedScriptHost::internalConstructorNameCallback, debuggerExternal); setFunctionProperty(context, injectedScriptHost, "formatAccessorsAsProperties", V8InjectedScriptHost::formatAccessorsAsProperties, debuggerExternal); - setFunctionProperty(context, injectedScriptHost, "isTypedArray", V8InjectedScriptHost::isTypedArrayCallback, debuggerExternal); setFunctionProperty(context, injectedScriptHost, "subtype", V8InjectedScriptHost::subtypeCallback, debuggerExternal); setFunctionProperty(context, injectedScriptHost, "getInternalProperties", V8InjectedScriptHost::getInternalPropertiesCallback, debuggerExternal); setFunctionProperty(context, injectedScriptHost, "objectHasOwnProperty", V8InjectedScriptHost::objectHasOwnPropertyCallback, debuggerExternal); @@ -77,14 +76,6 @@ info.GetReturnValue().Set(unwrapInspector(info)->client()->formatAccessorsAsProperties(info[0])); } -void V8InjectedScriptHost::isTypedArrayCallback(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - if (info.Length() < 1) - return; - - info.GetReturnValue().Set(info[0]->IsTypedArray()); -} - void V8InjectedScriptHost::subtypeCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { if (info.Length() < 1) @@ -99,10 +90,14 @@ return; } } - if (value->IsArray() || value->IsTypedArray() || value->IsArgumentsObject()) { + if (value->IsArray() || value->IsArgumentsObject()) { info.GetReturnValue().Set(toV8StringInternalized(isolate, "array")); return; } + if (value->IsTypedArray()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "typedarray")); + return; + } if (value->IsDate()) { info.GetReturnValue().Set(toV8StringInternalized(isolate, "date")); return; @@ -135,6 +130,10 @@ info.GetReturnValue().Set(toV8StringInternalized(isolate, "proxy")); return; } + if (value->IsPromise()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "promise")); + return; + } String16 subtype = unwrapInspector(info)->client()->valueSubtype(value); if (!subtype.isEmpty()) { info.GetReturnValue().Set(toV8String(isolate, subtype));
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h index 38c947f..0a3282a 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h +++ b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h
@@ -24,7 +24,6 @@ private: static void internalConstructorNameCallback(const v8::FunctionCallbackInfo<v8::Value>&); static void formatAccessorsAsProperties(const v8::FunctionCallbackInfo<v8::Value>&); - static void isTypedArrayCallback(const v8::FunctionCallbackInfo<v8::Value>&); static void subtypeCallback(const v8::FunctionCallbackInfo<v8::Value>&); static void getInternalPropertiesCallback(const v8::FunctionCallbackInfo<v8::Value>&); static void objectHasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>&);
diff --git a/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json b/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json index 037aeb8..d524de6 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json +++ b/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json
@@ -21,7 +21,7 @@ "exported": true, "properties": [ { "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean", "symbol"], "description": "Object type." }, - { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "map", "set", "iterator", "generator", "error"], "description": "Object subtype hint. Specified for <code>object</code> type values only." }, + { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "map", "set", "iterator", "generator", "error", "proxy", "promise", "typedarray"], "description": "Object subtype hint. Specified for <code>object</code> type values only." }, { "name": "className", "type": "string", "optional": true, "description": "Object class (constructor) name. Specified for <code>object</code> type values only." }, { "name": "value", "type": "any", "optional": true, "description": "Remote object value in case of primitive values or JSON values (if it was requested), or description string if the value can not be JSON-stringified (like NaN, Infinity, -Infinity, -0)." }, { "name": "description", "type": "string", "optional": true, "description": "String representation of the object." },
diff --git a/third_party/WebKit/Source/web/AssociatedURLLoader.cpp b/third_party/WebKit/Source/web/AssociatedURLLoader.cpp index 2e50987..0dfcbad 100644 --- a/third_party/WebKit/Source/web/AssociatedURLLoader.cpp +++ b/third_party/WebKit/Source/web/AssociatedURLLoader.cpp
@@ -404,7 +404,7 @@ if (m_loader) { m_loader->cancel(); - m_loader.reset(); + m_loader = nullptr; } m_clientAdapter.reset(); }
diff --git a/third_party/WebKit/Source/web/AssociatedURLLoader.h b/third_party/WebKit/Source/web/AssociatedURLLoader.h index 06d4717..e57a2006 100644 --- a/third_party/WebKit/Source/web/AssociatedURLLoader.h +++ b/third_party/WebKit/Source/web/AssociatedURLLoader.h
@@ -84,7 +84,7 @@ // An adapter which converts the DocumentThreadableLoaderClient method // calls into the WebURLLoaderClient method calls. std::unique_ptr<ClientAdapter> m_clientAdapter; - std::unique_ptr<DocumentThreadableLoader> m_loader; + Persistent<DocumentThreadableLoader> m_loader; // A ContextLifecycleObserver for cancelling |m_loader| when the Document // is detached.
diff --git a/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp b/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp index b22754b..3523eaa 100644 --- a/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp +++ b/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp
@@ -133,7 +133,7 @@ void RemoteFrameClientImpl::reload(FrameLoadType loadType, ClientRedirectPolicy clientRedirectPolicy) { - ASSERT(loadType == FrameLoadTypeReload || loadType == FrameLoadTypeReloadBypassingCache); + DCHECK(isReloadLoadType(loadType)); if (m_webFrame->client()) m_webFrame->client()->reload(static_cast<WebFrameLoadType>(loadType), static_cast<WebClientRedirectPolicy>(clientRedirectPolicy)); }
diff --git a/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp b/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp index eb850984..881e5b4c 100644 --- a/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp +++ b/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp
@@ -345,4 +345,9 @@ RuntimeEnabledFeatures::setAutoplayMutedVideosEnabled(enable); } +void WebRuntimeFeatures::enableSendBeaconThrowForBlobWithNonSimpleType(bool enable) +{ + RuntimeEnabledFeatures::setSendBeaconThrowForBlobWithNonSimpleTypeEnabled(enable); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/web/tests/TouchActionTest.cpp b/third_party/WebKit/Source/web/tests/TouchActionTest.cpp index 4d101cc..b3f223e 100644 --- a/third_party/WebKit/Source/web/tests/TouchActionTest.cpp +++ b/third_party/WebKit/Source/web/tests/TouchActionTest.cpp
@@ -210,6 +210,13 @@ return webView; } +IntRect windowClipRect(const FrameView& frameView) +{ + LayoutRect clipRect(LayoutPoint(), LayoutSize(frameView.visibleContentSize(ExcludeScrollbars))); + frameView.layoutViewItem().mapToVisualRectInAncestorSpace(&frameView.layoutView()->containerForPaintInvalidation(), clipRect); + return enclosingIntRect(clipRect); +} + void TouchActionTest::runTestOnTree(ContainerNode* root, WebView* webView, TouchActionTrackingWebViewClient& client) { // Find all elements to test the touch-action of in the document. @@ -271,7 +278,7 @@ LocalFrame* mainFrame = static_cast<LocalFrame*>(webView->mainFrame()->toImplBase()->frame()); FrameView* mainFrameView = mainFrame->view(); - IntRect visibleRect = mainFrameView->windowClipRect(); + IntRect visibleRect = windowClipRect(*mainFrameView); ASSERT_TRUE(visibleRect.contains(windowPoint)) << failureContextPos << " Test point not contained in visible area: " << visibleRect.x() << "," << visibleRect.y() << "-" << visibleRect.maxX() << "," << visibleRect.maxY();
diff --git a/third_party/WebKit/public/web/WebRuntimeFeatures.h b/third_party/WebKit/public/web/WebRuntimeFeatures.h index 97aec83..75fc545 100644 --- a/third_party/WebKit/public/web/WebRuntimeFeatures.h +++ b/third_party/WebKit/public/web/WebRuntimeFeatures.h
@@ -119,6 +119,7 @@ BLINK_EXPORT static void forceOverlayFullscreenVideo(bool); BLINK_EXPORT static void enableAutoplayMutedVideos(bool); BLINK_EXPORT static void enableCanvas2dDynamicRenderingModeSwitching(bool); + BLINK_EXPORT static void enableSendBeaconThrowForBlobWithNonSimpleType(bool); private: WebRuntimeFeatures(); };
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index eeb7eb8..5e25e02 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -9170,6 +9170,7 @@ <description> Android: User clicked on a snippet card into the host website. </description> + <obsolete>Deprecated as of 8/2016</obsolete> </action> <action name="MobileNTP.Snippets.Scrolled">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 3be41dae..c3a41fc 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -17646,6 +17646,9 @@ </histogram> <histogram name="GPU.GPUProcessLaunchCause" enum="GPUProcessLaunchCauses"> + <obsolete> + Deprecated 08/2016. + </obsolete> <owner>piman@chromium.org</owner> <summary> Counts enumerating the initial cause for the GPU Process to be launched. @@ -35355,6 +35358,31 @@ </obsolete> </histogram> +<histogram name="NewTabPage.Snippets.CardLongPressed" units="index"> + <owner>peconn@chromium.org</owner> + <summary> + Android: The position of a snippet card when it is long pressed, analagous + to NewTabPage.Snippets.CardClicked. + </summary> +</histogram> + +<histogram name="NewTabPage.Snippets.CardLongPressedAge" units="minutes"> + <owner>peconn@chromium.org</owner> + <summary> + Android: The time difference between when a snippet card is long pressed and + when its content was published. Analagous to + NewTabPage.Snippets.CardClickedAge. + </summary> +</histogram> + +<histogram name="NewTabPage.Snippets.CardLongPressedScoreNew" units="score"> + <owner>peconn@chromium.org</owner> + <summary> + Android: The relevance score of an interest card that is long pressed, + analagous to NewTabPage.Snippets.CardClickedScoreNew. + </summary> +</histogram> + <histogram name="NewTabPage.Snippets.CardShown"> <owner>knn@chromium.org</owner> <summary> @@ -35506,6 +35534,14 @@ </summary> </histogram> +<histogram name="NewTabPage.Snippets.OpenMethod" enum="SnippetOpenMethod"> + <owner>peconn@chromium.org</owner> + <summary> + Android: A histogram detailing how the articles linked from snippets are + opened (eg, plain click, open in new tab, open in incognito). + </summary> +</histogram> + <histogram name="NewTabPage.Snippets.VisitDuration" units="ms"> <owner>mastiz@chromium.org</owner> <summary> @@ -41427,6 +41463,9 @@ </histogram> <histogram name="PLT.BeginToFinish_ContentPrefetcher" units="ms"> + <obsolete> + No longer needed. + </obsolete> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <summary> PLT.BeginToFinish, but for pages which contained prefetch links. @@ -41434,6 +41473,9 @@ </histogram> <histogram name="PLT.BeginToFinish_ContentPrefetcherReferrer" units="ms"> + <obsolete> + No longer needed. + </obsolete> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <summary> PLT.BeginToFinish, but for pages which were referred to by pages which @@ -41462,6 +41504,9 @@ <histogram name="PLT.BeginToFinish_LinkLoadNormal_ExtensionWebRequest" units="ms"> + <obsolete> + No longer needed. + </obsolete> <owner>vabr@chromium.org</owner> <summary> The PLT.BeginToFinish histogram for pages loaded by following a link, after @@ -41521,6 +41566,9 @@ <histogram name="PLT.BeginToFinish_LinkLoadReload_ExtensionWebRequest" units="ms"> + <obsolete> + No longer needed. + </obsolete> <owner>vabr@chromium.org</owner> <summary> The PLT.BeginToFinish histogram for pages reloaded by JavaScript or by @@ -41580,6 +41628,9 @@ <histogram name="PLT.BeginToFinish_LinkLoadStaleOk_ExtensionWebRequest" units="ms"> + <obsolete> + No longer needed. + </obsolete> <owner>vabr@chromium.org</owner> <summary> The PLT.BeginToFinish histogram for pages loads initiated by back/forward @@ -41635,6 +41686,9 @@ </histogram> <histogram name="PLT.BeginToFinish_NormalLoad_ExtensionWebRequest" units="ms"> + <obsolete> + No longer needed. + </obsolete> <owner>vabr@chromium.org</owner> <summary> The PLT.BeginToFinish histogram for pages loaded by entering a URL or a @@ -41670,6 +41724,9 @@ </histogram> <histogram name="PLT.BeginToFinish_SpdyProxy" units="ms"> + <obsolete> + Use PLT.PT_BeginToFinish_DataReductionProxy instead. + </obsolete> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <summary>PLT.BeginToFinish, but for pages fetched over a SPDY proxy.</summary> </histogram> @@ -41694,6 +41751,9 @@ </histogram> <histogram name="PLT.BeginToFinishDoc_ContentPrefetcher" units="ms"> + <obsolete> + No longer needed. + </obsolete> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <summary> PLT.BeginToFinishDoc, but for pages which contained prefetch links. @@ -41701,6 +41761,9 @@ </histogram> <histogram name="PLT.BeginToFinishDoc_ContentPrefetcherReferrer" units="ms"> + <obsolete> + No longer needed. + </obsolete> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <summary> PLT.BeginToFinishDoc, but for pages which were referred to by pages which @@ -41709,6 +41772,9 @@ </histogram> <histogram name="PLT.BeginToFinishDoc_SpdyProxy" units="ms"> + <obsolete> + Use PLT.PT_BeginToFinishDoc_DataReductionProxy instead. + </obsolete> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <summary> PLT.BeginToFinshDoc, but for pages fetched over a SPDY proxy. @@ -63950,6 +64016,19 @@ </summary> </histogram> +<histogram name="WebCore.WebSocket.BinaryTypeChangesAfterOpen"> + <owner>yhirano@chromium.org</owner> + <owner>ricea@chromium.org</owner> + <owner>tyoshino@chromium.org</owner> + <summary> + Count the number of changes to WebSocket.binaryType after the connection + opened, per connection. Assignments that match the existing binaryType are + not counted. This is recorded after WebSocket close, whether explicit or due + to error or navigation. It is not recorded if the render process is + destroyed before the WebSocket is closed. + </summary> +</histogram> + <histogram name="WebCore.WebSocket.HandshakeResult" enum="WebSocketHandshakeResult"> <owner>yhirano@chromium.org</owner> @@ -63961,6 +64040,26 @@ </summary> </histogram> +<histogram name="WebCore.WebSocket.MessageSize.Receive" units="bytes"> + <owner>yhirano@chromium.org</owner> + <owner>ricea@chromium.org</owner> + <owner>tyoshino@chromium.org</owner> + <summary> + The sizes of binary WebSocket messages received, broken down by type. One + entry per message. Clamped to 100 MB. + </summary> +</histogram> + +<histogram name="WebCore.WebSocket.MessageSize.Send" units="bytes"> + <owner>yhirano@chromium.org</owner> + <owner>ricea@chromium.org</owner> + <owner>tyoshino@chromium.org</owner> + <summary> + The sizes of binary WebSocket messages sent, broken down by type. One entry + per message. Clamped to 100 MB. + </summary> +</histogram> + <histogram name="WebCore.WebSocket.PerMessageDeflateContextTakeOverMode" enum="WebSocketPerMessageDeflateContextTakeOverMode"> <owner>yhirano@chromium.org</owner> @@ -77771,6 +77870,7 @@ <int value="1482" label="MultipleOriginsInTimingAllowOrigin"/> <int value="1483" label="StarInTimingAllowOrigin"/> <int value="1484" label="SVGSMILAdditiveAnimation"/> + <int value="1485" label="SendBeaconWithNonSimpleContentType"/> </enum> <enum name="FetchRequestMode" type="int"> @@ -91594,6 +91694,14 @@ <int value="12" label="TAB_CLOSE_ALL_UNDO"/> </enum> +<enum name="SnippetOpenMethod" type="int"> + <int value="0" label="Plain click"/> + <int value="1" label="New Window"/> + <int value="2" label="New Tab"/> + <int value="3" label="Incognito Tab"/> + <int value="4" label="Save for Offline"/> +</enum> + <enum name="SnippetsInteractions" type="int"> <int value="0" label="Snippets were shown to the user"/> <int value="1" label="User scrolled through the snippets"/> @@ -100256,6 +100364,8 @@ <affected-histogram name="NewTabPage.Snippets.CardClickedAge"/> <affected-histogram name="NewTabPage.Snippets.CardClickedScore"/> <affected-histogram name="NewTabPage.Snippets.CardClickedScoreNew"/> + <affected-histogram name="NewTabPage.Snippets.CardLongPressedAge"/> + <affected-histogram name="NewTabPage.Snippets.CardLongPressedScoreNew"/> <affected-histogram name="NewTabPage.Snippets.CardShownAge"/> <affected-histogram name="NewTabPage.Snippets.CardShownScore"/> <affected-histogram name="NewTabPage.Snippets.CardShownScoreNew"/> @@ -102050,6 +102160,19 @@ <affected-histogram name="WebRTC.PeerConnection.SslCipherSuite"/> </histogram_suffixes> +<histogram_suffixes name="WebSocketMessageSizeReceive" separator="."> + <suffix name="ArrayBuffer"/> + <suffix name="Blob"/> + <affected-histogram name="WebCore.WebSocket.MessageSize.Receive"/> +</histogram_suffixes> + +<histogram_suffixes name="WebSocketMessageSizeSend" separator="."> + <suffix name="ArrayBuffer"/> + <suffix name="ArrayBufferView"/> + <suffix name="Blob"/> + <affected-histogram name="WebCore.WebSocket.MessageSize.Send"/> +</histogram_suffixes> + <histogram_suffixes name="WebStoreLinkExperiment"> <suffix name="Disabled" label="Neither extra webstore link is visible"/> <suffix name="FooterLink" label="Link in bottom right of footer"/>
diff --git a/tools/perf/docs/perf_regression_sheriffing.md b/tools/perf/docs/perf_regression_sheriffing.md index 84439038..cae219c 100644 --- a/tools/perf/docs/perf_regression_sheriffing.md +++ b/tools/perf/docs/perf_regression_sheriffing.md
@@ -96,6 +96,9 @@ you didn't see the announcement, double check in the speed infra chat. Ideally these will be associated with the bug for the bot turndown, but it's okay to mark them invalid if you can't find the bug. + You can check the + [recipe](https://chromium.googlesource.com/chromium/tools/build/+/master/scripts/slave/recipe_modules/chromium_tests/chromium_perf.py) + to find a corresponding bot name for waterfall with one for dashboard. If there doesn't seem to be a valid reason for the alert, file a bug on it using the perf dashboard, and cc [the owner](http://go/perf-owners). Then do
diff --git a/ui/accessibility/ax_enums.idl b/ui/accessibility/ax_enums.idl index b0be5c0..92f3af1 100644 --- a/ui/accessibility/ax_enums.idl +++ b/ui/accessibility/ax_enums.idl
@@ -513,4 +513,12 @@ downstream = 0, upstream = 1 }; + + // Compares two nodes in an accessibility tree in pre-order traversal. + enum AXTreeOrder { + undefined, // Not in the same tree, or other error. + before, // First node is before the second one. + equal, // Nodes are the same. + after // First node is after the second one. + }; };
diff --git a/ui/events/cocoa/events_mac_unittest.mm b/ui/events/cocoa/events_mac_unittest.mm index 8c72a30..926cfb0 100644 --- a/ui/events/cocoa/events_mac_unittest.mm +++ b/ui/events/cocoa/events_mac_unittest.mm
@@ -8,7 +8,6 @@ #include <memory> #include "base/mac/scoped_cftyperef.h" -#import "base/mac/scoped_objc_class_swizzler.h" #include "base/mac/sdk_forward_declarations.h" #include "base/macros.h" #include "testing/gtest/include/gtest/gtest.h" @@ -18,35 +17,14 @@ #include "ui/gfx/geometry/point.h" #import "ui/gfx/test/ui_cocoa_test_helper.h" -namespace { - -NSWindow* g_test_window = nil; - -} // namespace - -// Mac APIs for creating test events are frustrating. Quartz APIs have, e.g., -// CGEventCreateMouseEvent() which can't set a window or modifier flags. -// Cocoa APIs have +[NSEvent mouseEventWithType:..] which can't set -// buttonNumber or scroll deltas. To work around this, these tests use some -// Objective C magic to donate member functions to NSEvent temporarily. -@interface MiddleMouseButtonNumberDonor : NSObject -@end - -@interface TestWindowDonor : NSObject -@end - -@implementation MiddleMouseButtonNumberDonor -- (NSInteger)buttonNumber { return 2; } -@end - -@implementation TestWindowDonor -- (NSWindow*)window { return g_test_window; } -@end - namespace ui { namespace { +// Although CGEventFlags is just a typedef to int in 10.10 and earlier headers, +// the 10.11 header makes this a CF_ENUM, but doesn't give an option for "none". +const CGEventFlags kNoEventFlags = static_cast<CGEventFlags>(0); + class EventsMacTest : public CocoaTest { public: EventsMacTest() {} @@ -59,52 +37,32 @@ return window_location; } - void SwizzleMiddleMouseButton() { - DCHECK(!swizzler_); - swizzler_.reset(new base::mac::ScopedObjCClassSwizzler( - [NSEvent class], - [MiddleMouseButtonNumberDonor class], - @selector(buttonNumber))); - } - - void SwizzleTestWindow() { - DCHECK(!g_test_window); - DCHECK(!swizzler_); - g_test_window = test_window(); - swizzler_.reset(new base::mac::ScopedObjCClassSwizzler( - [NSEvent class], [TestWindowDonor class], @selector(window))); - } - - void ClearSwizzle() { - swizzler_.reset(); - g_test_window = nil; - } - - NSEvent* TestMouseEvent(NSEventType type, - const gfx::Point &window_location, - NSInteger modifier_flags) { - NSPoint point = NSPointFromCGPoint(Flip(window_location).ToCGPoint()); - return [NSEvent mouseEventWithType:type - location:point - modifierFlags:modifier_flags - timestamp:0 - windowNumber:[test_window() windowNumber] - context:nil - eventNumber:0 - clickCount:0 - pressure:1.0]; + NSEvent* TestMouseEvent(CGEventType type, + const gfx::Point& window_location, + CGEventFlags event_flags) { + // CGEventCreateMouseEvent() ignores the CGMouseButton parameter unless + // |type| is one of kCGEventOtherMouse{Up,Down,Dragged}. It can be an + // integer up to 31. However, constants are only supplied up to 2. For now, + // just assume "other" means the third/center mouse button, and rely on + // Quartz ignoring it when the type is not "other". + CGMouseButton other_button = kCGMouseButtonCenter; + base::ScopedCFTypeRef<CGEventRef> mouse(CGEventCreateMouseEvent( + nullptr, type, TestWindowPointToScreen(window_location), other_button)); + CGEventSetFlags(mouse, event_flags); + return EventWithTestWindow(mouse); } NSEvent* TestScrollEvent(const gfx::Point& window_location, int32_t delta_x, int32_t delta_y) { - SwizzleTestWindow(); - base::ScopedCFTypeRef<CGEventRef> scroll( - CGEventCreateScrollWheelEvent(NULL, - kCGScrollEventUnitLine, - 2, - delta_y, - delta_x)); + base::ScopedCFTypeRef<CGEventRef> scroll(CGEventCreateScrollWheelEvent( + nullptr, kCGScrollEventUnitLine, 2, delta_y, delta_x)); + CGEventSetLocation(scroll, TestWindowPointToScreen(window_location)); + return EventWithTestWindow(scroll); + } + + private: + CGPoint TestWindowPointToScreen(const gfx::Point& window_location) { // CGEvents are always in global display coordinates. These are like screen // coordinates, but flipped. But first the point needs to be converted out // of window coordinates (which also requires flipping). @@ -116,12 +74,24 @@ CGFloat primary_screen_height = NSHeight([[[NSScreen screens] firstObject] frame]); screen_point.y = primary_screen_height - screen_point.y; - CGEventSetLocation(scroll, NSPointToCGPoint(screen_point)); - return [NSEvent eventWithCGEvent:scroll]; + return NSPointToCGPoint(screen_point); } - private: - std::unique_ptr<base::mac::ScopedObjCClassSwizzler> swizzler_; + NSEvent* EventWithTestWindow(CGEventRef event) { + // These CGEventFields were made public in the 10.7 SDK, but don't help to + // populate the -[NSEvent window] pointer when creating an event with + // +[NSEvent eventWithCGEvent:]. Set that separately, using reflection. + CGEventSetIntegerValueField(event, kCGMouseEventWindowUnderMousePointer, + [test_window() windowNumber]); + CGEventSetIntegerValueField( + event, kCGMouseEventWindowUnderMousePointerThatCanHandleThisEvent, + [test_window() windowNumber]); + NSEvent* ns_event = [NSEvent eventWithCGEvent:event]; + EXPECT_EQ(nil, [ns_event window]); // Verify assumptions. + [ns_event setValue:test_window() forKey:@"_window"]; + EXPECT_EQ(test_window(), [ns_event window]); + return ns_event; + } DISALLOW_COPY_AND_ASSIGN(EventsMacTest); }; @@ -192,20 +162,20 @@ gfx::Point location(5, 10); gfx::Vector2d offset; - NSEvent* event = TestMouseEvent(NSLeftMouseDown, location, 0); + NSEvent* event = + TestMouseEvent(kCGEventLeftMouseDown, location, kNoEventFlags); EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(event)); EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, ui::EventFlagsFromNative(event)); EXPECT_EQ(location, ui::EventLocationFromNative(event)); - SwizzleMiddleMouseButton(); - event = TestMouseEvent(NSOtherMouseDown, location, NSShiftKeyMask); + event = + TestMouseEvent(kCGEventOtherMouseDown, location, kCGEventFlagMaskShift); EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(event)); EXPECT_EQ(ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_SHIFT_DOWN, ui::EventFlagsFromNative(event)); EXPECT_EQ(location, ui::EventLocationFromNative(event)); - ClearSwizzle(); - event = TestMouseEvent(NSRightMouseUp, location, 0); + event = TestMouseEvent(kCGEventRightMouseUp, location, kNoEventFlags); EXPECT_EQ(ui::ET_MOUSE_RELEASED, ui::EventTypeFromNative(event)); EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, ui::EventFlagsFromNative(event)); EXPECT_EQ(location, ui::EventLocationFromNative(event)); @@ -218,7 +188,6 @@ offset = ui::GetMouseWheelOffset(event); EXPECT_GT(offset.y(), 0); EXPECT_EQ(0, offset.x()); - ClearSwizzle(); // Scroll down. event = TestScrollEvent(location, 0, -1); @@ -228,7 +197,6 @@ offset = ui::GetMouseWheelOffset(event); EXPECT_LT(offset.y(), 0); EXPECT_EQ(0, offset.x()); - ClearSwizzle(); // Scroll left. event = TestScrollEvent(location, 1, 0); @@ -238,7 +206,6 @@ offset = ui::GetMouseWheelOffset(event); EXPECT_EQ(0, offset.y()); EXPECT_GT(offset.x(), 0); - ClearSwizzle(); // Scroll right. event = TestScrollEvent(location, -1, 0); @@ -248,7 +215,6 @@ offset = ui::GetMouseWheelOffset(event); EXPECT_EQ(0, offset.y()); EXPECT_LT(offset.x(), 0); - ClearSwizzle(); } // Test correct location when the window has a native titlebar. @@ -263,7 +229,8 @@ DCHECK_EQ(style_mask, [test_window() styleMask]); // EventLocationFromNative should behave the same as the ButtonEvents test. - NSEvent* event = TestMouseEvent(NSLeftMouseDown, location, 0); + NSEvent* event = + TestMouseEvent(kCGEventLeftMouseDown, location, kNoEventFlags); EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(event)); EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, ui::EventFlagsFromNative(event)); EXPECT_EQ(location, ui::EventLocationFromNative(event));
diff --git a/ui/file_manager/file_manager/foreground/elements/files_icon_button.html b/ui/file_manager/file_manager/foreground/elements/files_icon_button.html index f6113e3..e118674 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_icon_button.html +++ b/ui/file_manager/file_manager/foreground/elements/files_icon_button.html
@@ -47,14 +47,14 @@ width: 28px; } - files-toggle-ripple::shadow .ripple.activated { + files-toggle-ripple::shadow .ripple { opacity: 0.1; + @apply(--files-icon-button-activated-theme); } </style> <files-ripple hidden="[[toggles]]"></files-ripple> <files-toggle-ripple activated="[[active]]"></files-toggle-ripple> - <!-- TODO(fukino): Make it possible to insert user-defined element to show them on top of ripple effect. --> </template> <script src="files_icon_button.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/elements/files_metadata_box.html b/ui/file_manager/file_manager/foreground/elements/files_metadata_box.html index 26344044..6b7035c4 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_metadata_box.html +++ b/ui/file_manager/file_manager/foreground/elements/files_metadata_box.html
@@ -27,15 +27,16 @@ .category { color: #E6E6E6; - font-size: 16px; - font-weight: bold; - margin: 12px 15px; + font-size: 133%; + font-weight: 500; + margin: 12px 32px; vertical-align: bottom; } hr { - border-color: #636363; + border-color: white; margin-top: 31px; + opacity: 0.24; } </style> <template>
diff --git a/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.html b/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.html index 6200065..defff3c 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.html +++ b/ui/file_manager/file_manager/foreground/elements/files_metadata_entry.html
@@ -23,22 +23,25 @@ } #padding { - width: 15px; + width: 32px; } #key { - color: #EFEFEF; - font-weight: bold; + color: white; + font-size: 115%; + font-weight: 500; overflow-wrap: break-word; vertical-align: bottom; - width: 150px; + width: 128px; } #value { - color: #D6D6D6; + color: white; + font-size: 115%; + opacity: 0.8; overflow-wrap: break-word; vertical-align: bottom; - width: 150px; + width: 128px; } </style> <template>
diff --git a/ui/file_manager/file_manager/foreground/elements/files_quick_view.css b/ui/file_manager/file_manager/foreground/elements/files_quick_view.css index e29aa7a..04ab61bd 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_quick_view.css +++ b/ui/file_manager/file_manager/foreground/elements/files_quick_view.css
@@ -66,6 +66,14 @@ margin-right: 320px; } +#metadata-button { + background: -webkit-image-set( + url(../images/files/ui/quick_view/info_outline.png) 1x, + url(../images/files/ui/quick_view/2x/info_outline.png) 2x) + center + no-repeat; +} + #innerContentPanel { background-color: transparent; color: white; @@ -92,22 +100,31 @@ } #toolbar { - --paper-toolbar-background: rgb(60, 60, 60); + --paper-toolbar-background: rgb(40, 42, 45); --paper-toolbar-height: 48px; color: white; margin: 0; + opacity: 0.9; padding: 0; width: 100%; z-index: 1; } +#metadata-button { + --files-icon-button-activated-theme: { + background: white; + opacity: 0.3; + }; +} + #buttons { display: flex; position: absolute; right: 0px; } -paper-button { +paper-button, +files-icon-button { border-radius: 2px; height: 32px; margin: 0 8px; @@ -121,19 +138,33 @@ } #metadata-box { - background-color: rgba(40, 40, 44, 0.8); + background-color: rgba(20, 22, 24, 0.8); bottom: 0; height: 100%; margin: 0; + opacity: 0.8; + overflow-y: auto; position: absolute; right: 0; } +::-webkit-scrollbar { + width: 10px; +} + +::-webkit-scrollbar-thumb { + background-clip: content-box; + background-color: rgb(118, 118, 121); + border: 2.5px solid transparent; + width: 5px; +} + [hidden] { display: none; } .no-preview { + font-size: 115%; margin-top: 16px; }
diff --git a/ui/file_manager/file_manager/foreground/elements/files_quick_view.html b/ui/file_manager/file_manager/foreground/elements/files_quick_view.html index d36cef7..4011d96 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_quick_view.html +++ b/ui/file_manager/file_manager/foreground/elements/files_quick_view.html
@@ -8,6 +8,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-dialog/paper-dialog.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-toolbar/paper-toolbar.html"> +<link rel="import" href="files_icon_button.html"> <link rel="import" href="files_metadata_box.html"> <link rel="import" href="files_safe_img.html"> <link rel="import" href="files_tooltip.html"> @@ -23,9 +24,8 @@ <paper-button id="open-button" on-tap="onOpenInNewButtonTap" hidden$="[[isUnsupported_(type)]]" i18n-values="aria-label:QUICK_VIEW_OPEN_IN_NEW_BUTTON_LABEL" tabindex="0" has-tooltip> <iron-icon icon="files:open-in-new"></iron-icon> </paper-button> - <paper-button id-"metadata-button" active="{{metadataBoxActive}}" i18n-values="aria-label:QUICK_VIEW_TOGGLE_METADATA_BOX_BUTTON_LABEL" tabindex="0" toggles has-tooltip> - <iron-icon icon="files:info-outline"></iron-icon> - </paper-button> + <files-icon-button toggles id="metadata-button" active="{{metadataBoxActive}}" i18n-values="aria-label:QUICK_VIEW_TOGGLE_METADATA_BOX_BUTTON_LABEL" tabindex="0" has-tooltip> + </files-icon-button> </div> </paper-toolbar> <div id="mainPanel">
diff --git a/ui/file_manager/file_manager/foreground/elements/files_ripple.js b/ui/file_manager/file_manager/foreground/elements/files_ripple.js index 5972bb9..6b3779a6f 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_ripple.js +++ b/ui/file_manager/file_manager/foreground/elements/files_ripple.js
@@ -27,9 +27,10 @@ pressAnimationPromise_: null, attached: function() { + var node = assert(this.parentElement || this.parentNode.host); // Listen events of parent element. - this.listen(assert(this.parentElement), 'down', 'onDown_'); - this.listen(assert(this.parentElement), 'up', 'onUp_'); + this.listen(node, 'down', 'onDown_'); + this.listen(node, 'up', 'onUp_'); }, /**
diff --git a/ui/file_manager/file_manager/foreground/elements/files_tooltip.js b/ui/file_manager/file_manager/foreground/elements/files_tooltip.js index cf1c7275..cc7059f 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_tooltip.js +++ b/ui/file_manager/file_manager/foreground/elements/files_tooltip.js
@@ -167,7 +167,9 @@ this.style.top = `${Math.round(top)}px`; var left = rect.left + rect.width / 2 - this.offsetWidth / 2; - if (left + this.offsetWidth > document.body.offsetWidth) + if (left < 0) + left = 0; + if (left > document.body.offsetWidth - this.offsetWidth) left = document.body.offsetWidth - this.offsetWidth; this.style.left = `${Math.round(left)}px`;
diff --git a/ui/file_manager/file_manager/foreground/elements/icons.html b/ui/file_manager/file_manager/foreground/elements/icons.html index c74e3d2d..d86e50b 100644 --- a/ui/file_manager/file_manager/foreground/elements/icons.html +++ b/ui/file_manager/file_manager/foreground/elements/icons.html
@@ -20,7 +20,6 @@ <g id="cloud-off"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4c-1.48 0-2.85.43-4.01 1.17l1.46 1.46C10.21 6.23 11.08 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3 0 1.13-.64 2.11-1.56 2.62l1.45 1.45C23.16 18.16 24 16.68 24 15c0-2.64-2.05-4.78-4.65-4.96zM3 5.27l2.75 2.74C2.56 8.15 0 10.77 0 14c0 3.31 2.69 6 6 6h11.73l2 2L21 20.73 4.27 4 3 5.27zM7.73 10l8 8H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h1.73z"/></g> <g id="cloud-queue"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h.71C7.37 7.69 9.48 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3s-1.34 3-3 3z"/></g> <g id="cloud-upload"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"/></g> - <g id="info-outline"><path d="M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 9h2V7h-2v2z"/></g> <g id="open-in-new"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></g> <g id="photo"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></g> </defs>
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/quick_view/2x/info_outline.png b/ui/file_manager/file_manager/foreground/images/files/ui/quick_view/2x/info_outline.png new file mode 100644 index 0000000..ae3a8a0 --- /dev/null +++ b/ui/file_manager/file_manager/foreground/images/files/ui/quick_view/2x/info_outline.png Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/quick_view/info_outline.png b/ui/file_manager/file_manager/foreground/images/files/ui/quick_view/info_outline.png new file mode 100644 index 0000000..e57733f8 --- /dev/null +++ b/ui/file_manager/file_manager/foreground/images/files/ui/quick_view/info_outline.png Binary files differ
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd index c4587b3..93125bf 100644 --- a/ui/strings/ui_strings.grd +++ b/ui/strings/ui_strings.grd
@@ -404,7 +404,7 @@ <message name="IDS_APP_ESC_KEY" desc="Escape key"> Esc </message> - <message name="IDS_APP_TAB_KEY" desc="Tab key"> + <message name="IDS_APP_TAB_KEY" desc="Tab key" meaning="Tab key"> Tab </message> <message name="IDS_APP_INSERT_KEY" desc="Insert key">