diff --git a/DEPS b/DEPS index a8e176c..4621d3d 100644 --- a/DEPS +++ b/DEPS
@@ -92,7 +92,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': 'c56d8851ea987023cc73981a70d261b3f6427545', + 'freetype_revision': 'cf8d9b4ce3fa2c6cd9ccb25585bc17a355c987b0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other.
diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc index 7f700f23..7d9b656 100644 --- a/base/trace_event/process_memory_dump.cc +++ b/base/trace_event/process_memory_dump.cc
@@ -356,8 +356,12 @@ void ProcessMemoryDump::AddOwnershipEdge(const MemoryAllocatorDumpGuid& source, const MemoryAllocatorDumpGuid& target, int importance) { - DCHECK(allocator_dumps_edges_.count(source) == 0 || - allocator_dumps_edges_[source].overridable); + // This will either override an existing edge or create a new one. + auto it = allocator_dumps_edges_.find(source); + if (it != allocator_dumps_edges_.end()) { + DCHECK_EQ(target.ToUint64(), + allocator_dumps_edges_[source].target.ToUint64()); + } allocator_dumps_edges_[source] = { source, target, importance, kEdgeTypeOwnership, false /* overridable */}; } @@ -426,8 +430,9 @@ // Create an edge between local dump of the client and the local dump of the // SharedMemoryTracker. Do not need to create the dumps here since the - // tracker would create them. - AddOwnershipEdge(client_local_dump_guid, local_shm_guid); + // tracker would create them. The importance is also required here for the + // case of single process mode. + AddOwnershipEdge(client_local_dump_guid, local_shm_guid, importance); // TODO(ssid): Handle the case of weak dumps here. This needs a new function // GetOrCreaetGlobalDump() in PMD since we need to change the behavior of
diff --git a/base/trace_event/process_memory_dump_unittest.cc b/base/trace_event/process_memory_dump_unittest.cc index 1c1f3bf..47eb10ce 100644 --- a/base/trace_event/process_memory_dump_unittest.cc +++ b/base/trace_event/process_memory_dump_unittest.cc
@@ -359,7 +359,7 @@ EXPECT_EQ(1, edges.find(shm_local_guid2)->second.importance); EXPECT_FALSE(edges.find(shm_local_guid2)->second.overridable); EXPECT_EQ(shm_local_guid2, edges.find(client_dump2->guid())->second.target); - EXPECT_EQ(0, edges.find(client_dump2->guid())->second.importance); + EXPECT_EQ(1, edges.find(client_dump2->guid())->second.importance); EXPECT_FALSE(edges.find(client_dump2->guid())->second.overridable); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index a943252..3addc59 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -161,7 +161,6 @@ "ContentSuggestionsFaviconsFromNewServer"; public static final String CONTENT_SUGGESTIONS_NOTIFICATIONS = "ContentSuggestionsNotifications"; - public static final String CONTENT_SUGGESTIONS_CATEGORIES = "ContentSuggestionsCategories"; public static final String CONTENT_SUGGESTIONS_LARGE_THUMBNAIL = "ContentSuggestionsLargeThumbnail"; public static final String CONTENT_SUGGESTIONS_SETTINGS = "ContentSuggestionsSettings";
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 654beba..f3d2a81 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
@@ -4,45 +4,20 @@ package org.chromium.chrome.browser.ntp.snippets; -import android.content.res.ColorStateList; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.TransitionDrawable; -import android.media.ThumbnailUtils; -import android.os.StrictMode; -import android.os.SystemClock; -import android.support.annotation.Nullable; -import android.support.v4.text.BidiFormatter; import android.text.TextUtils; -import android.text.format.DateUtils; -import android.view.View; -import android.view.View.MeasureSpec; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; -import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.base.Callback; -import org.chromium.base.Promise; -import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; -import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation; -import org.chromium.chrome.browser.download.DownloadUtils; -import org.chromium.chrome.browser.download.ui.DownloadFilter; import org.chromium.chrome.browser.ntp.ContextMenuManager; import org.chromium.chrome.browser.ntp.ContextMenuManager.ContextMenuItemId; import org.chromium.chrome.browser.ntp.cards.CardViewHolder; import org.chromium.chrome.browser.ntp.cards.ImpressionTracker; import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder; import org.chromium.chrome.browser.ntp.cards.SuggestionsCategoryInfo; -import org.chromium.chrome.browser.suggestions.ImageFetcher; +import org.chromium.chrome.browser.suggestions.SuggestionsBinder; import org.chromium.chrome.browser.suggestions.SuggestionsMetrics; import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; -import org.chromium.chrome.browser.widget.TintedImageView; import org.chromium.chrome.browser.widget.displaystyle.DisplayStyleObserver; import org.chromium.chrome.browser.widget.displaystyle.DisplayStyleObserverAdapter; import org.chromium.chrome.browser.widget.displaystyle.HorizontalDisplayStyle; @@ -50,7 +25,6 @@ import org.chromium.chrome.browser.widget.displaystyle.VerticalDisplayStyle; import org.chromium.ui.mojom.WindowOpenDisposition; -import java.util.concurrent.TimeUnit; /** * A class that represents the view for a single card snippet. */ @@ -62,34 +36,12 @@ public static final RefreshOfflineBadgeVisibilityCallback REFRESH_OFFLINE_BADGE_VISIBILITY_CALLBACK = new RefreshOfflineBadgeVisibilityCallback(); - private static final String ARTICLE_AGE_FORMAT_STRING = " - %s"; - private static final int FADE_IN_ANIMATION_TIME_MS = 300; - private final SuggestionsUiDelegate mUiDelegate; private final UiConfig mUiConfig; - private final ImageFetcher mImageFetcher; + private final SuggestionsBinder mSuggestionsBinder; - private final LinearLayout mTextLayout; - private final TextView mHeadlineTextView; - private final TextView mPublisherTextView; - private final TextView mArticleSnippetTextView; - private final TextView mArticleAgeTextView; - private final TintedImageView mThumbnailView; - private final ImageView mThumbnailVideoOverlay; - private final ImageView mOfflineBadge; - private final View mPublisherBar; - - private final int mThumbnailSize; - /** Total horizontal space occupied by the thumbnail, sum of its size and margin. */ - private final int mThumbnailFootprintPx; - private final int mIconBackgroundColor; - private final ColorStateList mIconForegroundColorList; - - @Nullable - private ImageFetcher.DownloadThumbnailRequest mThumbnailRequest; - private SnippetArticle mArticle; private SuggestionsCategoryInfo mCategoryInfo; - private int mPublisherFaviconSizePx; + private SnippetArticle mArticle; /** * Constructs a {@link SnippetArticleViewHolder} item used to display snippets. @@ -108,29 +60,7 @@ mUiDelegate = uiDelegate; mUiConfig = uiConfig; - mImageFetcher = mUiDelegate.getImageFetcher(); - - mTextLayout = (LinearLayout) itemView.findViewById(R.id.text_layout); - mHeadlineTextView = (TextView) itemView.findViewById(R.id.article_headline); - mPublisherTextView = (TextView) itemView.findViewById(R.id.article_publisher); - mArticleSnippetTextView = (TextView) itemView.findViewById(R.id.article_snippet); - mArticleAgeTextView = (TextView) itemView.findViewById(R.id.article_age); - mThumbnailView = (TintedImageView) itemView.findViewById(R.id.article_thumbnail); - mThumbnailVideoOverlay = - (ImageView) itemView.findViewById(R.id.article_thumbnail_video_overlay); - mPublisherBar = itemView.findViewById(R.id.publisher_bar); - mOfflineBadge = (ImageView) itemView.findViewById(R.id.offline_icon); - - boolean useLargeThumbnailLayout = - ChromeFeatureList.isEnabled(ChromeFeatureList.CONTENT_SUGGESTIONS_LARGE_THUMBNAIL); - mThumbnailSize = itemView.getResources().getDimensionPixelSize(useLargeThumbnailLayout - ? R.dimen.snippets_thumbnail_size_large - : R.dimen.snippets_thumbnail_size); - mThumbnailFootprintPx = mThumbnailSize - + itemView.getResources().getDimensionPixelSize(R.dimen.snippets_thumbnail_margin); - - mIconBackgroundColor = DownloadUtils.getIconBackgroundColor(parent.getContext()); - mIconForegroundColorList = DownloadUtils.getIconForegroundColorList(parent.getContext()); + mSuggestionsBinder = new SuggestionsBinder(itemView, uiDelegate); new ImpressionTracker(itemView, this); new DisplayStyleObserverAdapter(itemView, uiConfig, new DisplayStyleObserver() { @@ -194,33 +124,11 @@ mArticle = article; mCategoryInfo = categoryInfo; + updateLayout(); - mHeadlineTextView.setText(mArticle.mTitle); + mSuggestionsBinder.updateViewInformation(mArticle); - // The favicon of the publisher should match the TextView height. - int widthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - mPublisherTextView.measure(widthSpec, heightSpec); - mPublisherFaviconSizePx = mPublisherTextView.getMeasuredHeight(); - - mArticleSnippetTextView.setText(mArticle.mPreviewText); - mPublisherTextView.setText(getPublisherString(mArticle)); - mArticleAgeTextView.setText(getArticleAge(mArticle)); - setThumbnail(); - - // Set the favicon of the publisher. - // We start initialising with the default favicon to reserve the space and prevent the text - // from moving later. - setDefaultFaviconOnView(); - mImageFetcher.makeFaviconRequest(mArticle, mPublisherFaviconSizePx, new Callback<Bitmap>() { - @Override - public void onResult(Bitmap image) { - setFaviconOnView(image); - } - }); - - mOfflineBadge.setVisibility(View.GONE); refreshOfflineBadgeVisibility(); } @@ -237,37 +145,9 @@ boolean showThumbnail = shouldShowThumbnail(layout); boolean showThumbnailVideoOverlay = shouldShowThumbnailVideoOverlay(showThumbnail); - if (ChromeFeatureList.isEnabled(ChromeFeatureList.CONTENT_SUGGESTIONS_LARGE_THUMBNAIL)) { - mTextLayout.setMinimumHeight(showThumbnail ? mThumbnailSize : 0); - } - mHeadlineTextView.setVisibility(showHeadline ? View.VISIBLE : View.GONE); - mHeadlineTextView.setMaxLines(getHeaderMaxLines(horizontalStyle, verticalStyle, layout)); - mArticleSnippetTextView.setVisibility(showDescription ? View.VISIBLE : View.GONE); - mThumbnailView.setVisibility(showThumbnail ? View.VISIBLE : View.GONE); - mThumbnailVideoOverlay.setVisibility(showThumbnailVideoOverlay ? View.VISIBLE : View.GONE); - - ViewGroup.MarginLayoutParams publisherBarParams = - (ViewGroup.MarginLayoutParams) mPublisherBar.getLayoutParams(); - - if (showDescription) { - publisherBarParams.topMargin = mPublisherBar.getResources().getDimensionPixelSize( - R.dimen.snippets_publisher_margin_top_with_article_snippet); - } else if (showHeadline) { - // When we show a headline and not a description, we reduce the top margin of the - // publisher bar. - publisherBarParams.topMargin = mPublisherBar.getResources().getDimensionPixelSize( - R.dimen.snippets_publisher_margin_top_without_article_snippet); - } else { - // When there is no headline and no description, we remove the top margin of the - // publisher bar. - publisherBarParams.topMargin = 0; - } - - if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CONTENT_SUGGESTIONS_LARGE_THUMBNAIL)) { - ApiCompatibilityUtils.setMarginEnd( - publisherBarParams, showThumbnail ? mThumbnailFootprintPx : 0); - } - mPublisherBar.setLayoutParams(publisherBarParams); + mSuggestionsBinder.updateFieldsVisibility(showHeadline, showDescription, showThumbnail, + showThumbnailVideoOverlay, + getHeaderMaxLines(horizontalStyle, verticalStyle, layout)); } /** If the title is empty (or contains only whitespace characters), we do not show it. */ @@ -311,199 +191,10 @@ return shouldShowDescription(horizontalStyle, verticalStyle, layout) ? 2 : 3; } - private static String getPublisherString(SnippetArticle article) { - // We format the publisher here so that having a publisher name in an RTL language - // doesn't mess up the formatting on an LTR device and vice versa. - return BidiFormatter.getInstance().unicodeWrap(article.mPublisher); - } - - private static String getArticleAge(SnippetArticle article) { - if (article.mPublishTimestampMilliseconds == 0) return ""; - - // DateUtils.getRelativeTimeSpanString(...) calls through to TimeZone.getDefault(). If this - // has never been called before it loads the current time zone from disk. In most likelihood - // this will have been called previously and the current time zone will have been cached, - // but in some cases (eg instrumentation tests) it will cause a strict mode violation. - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); - CharSequence relativeTimeSpan; - try { - long time = SystemClock.elapsedRealtime(); - relativeTimeSpan = - DateUtils.getRelativeTimeSpanString(article.mPublishTimestampMilliseconds, - System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS); - RecordHistogram.recordTimesHistogram("Android.StrictMode.SnippetUIBuildTime", - SystemClock.elapsedRealtime() - time, TimeUnit.MILLISECONDS); - } finally { - StrictMode.setThreadPolicy(oldPolicy); - } - - // We add a dash before the elapsed time, e.g. " - 14 minutes ago". - return String.format(ARTICLE_AGE_FORMAT_STRING, - BidiFormatter.getInstance().unicodeWrap(relativeTimeSpan)); - } - - private void setThumbnailFromBitmap(Bitmap thumbnail) { - assert thumbnail != null; - assert !thumbnail.isRecycled(); - assert thumbnail.getWidth() <= mThumbnailSize || thumbnail.getHeight() <= mThumbnailSize; - - mThumbnailView.setScaleType(ImageView.ScaleType.CENTER_CROP); - mThumbnailView.setBackground(null); - mThumbnailView.setImageBitmap(thumbnail); - mThumbnailView.setTint(null); - } - - private void setThumbnailFromFileType(int fileType) { - mThumbnailView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - mThumbnailView.setBackgroundColor(mIconBackgroundColor); - mThumbnailView.setImageResource( - DownloadUtils.getIconResId(fileType, DownloadUtils.ICON_SIZE_36_DP)); - mThumbnailView.setTint(mIconForegroundColorList); - } - - private void setDownloadThumbnail() { - assert mArticle.isDownload(); - if (!mArticle.isAssetDownload()) { - setThumbnailFromFileType(DownloadFilter.FILTER_PAGE); - return; - } - - int fileType = DownloadFilter.fromMimeType(mArticle.getAssetDownloadMimeType()); - if (fileType == DownloadFilter.FILTER_IMAGE) { - // For image downloads, attempt to fetch a thumbnail. - ImageFetcher.DownloadThumbnailRequest thumbnailRequest = - mImageFetcher.makeDownloadThumbnailRequest(mArticle, mThumbnailSize); - - Promise<Bitmap> thumbnailReceivedPromise = thumbnailRequest.getPromise(); - - if (thumbnailReceivedPromise.isFulfilled()) { - // If the thumbnail was cached, then it will be retrieved synchronously, the promise - // will be fulfilled and we can set the thumbnail immediately. - setThumbnailFromBitmap(thumbnailReceivedPromise.getResult()); - return; - } - - mThumbnailRequest = thumbnailRequest; - - // Queue a callback to be called after the thumbnail is retrieved asynchronously. - thumbnailReceivedPromise.then(new FetchImageCallback(mArticle, mThumbnailSize)); - } - - // Set a placeholder for the file type. - setThumbnailFromFileType(fileType); - } - - private void setThumbnail() { - // If there's still a pending thumbnail fetch, cancel it. - cancelImageFetch(); - - // mThumbnailView's visibility is modified in updateLayout(). - if (mThumbnailView.getVisibility() != View.VISIBLE) return; - Bitmap thumbnail = mArticle.getThumbnailBitmap(); - if (thumbnail != null) { - setThumbnailFromBitmap(thumbnail); - return; - } - - if (mArticle.isDownload()) { - setDownloadThumbnail(); - return; - } - - // Temporarily set placeholder and then fetch the thumbnail from a provider. - mThumbnailView.setBackground(null); - mThumbnailView.setImageResource(R.drawable.ic_snippet_thumbnail_placeholder); - mThumbnailView.setTint(null); - mImageFetcher.makeArticleThumbnailRequest( - mArticle, new FetchImageCallback(mArticle, mThumbnailSize)); - } - /** Updates the visibility of the card's offline badge by checking the bound article's info. */ private void refreshOfflineBadgeVisibility() { boolean visible = mArticle.getOfflinePageOfflineId() != null || mArticle.isAssetDownload(); - if (visible == (mOfflineBadge.getVisibility() == View.VISIBLE)) return; - mOfflineBadge.setVisibility(visible ? View.VISIBLE : View.GONE); - } - - private void cancelImageFetch() { - if (mThumbnailRequest != null) { - mThumbnailRequest.cancel(); - mThumbnailRequest = null; - } - } - - private void fadeThumbnailIn(Bitmap thumbnail) { - assert mThumbnailView.getDrawable() != null; - - mThumbnailView.setScaleType(ImageView.ScaleType.CENTER_CROP); - mThumbnailView.setBackground(null); - mThumbnailView.setTint(null); - int duration = (int) (FADE_IN_ANIMATION_TIME_MS - * ChromeAnimation.Animation.getAnimationMultiplier()); - if (duration == 0) { - mThumbnailView.setImageBitmap(thumbnail); - return; - } - - // Cross-fade between the placeholder and the thumbnail. We cross-fade because the incoming - // image may have transparency and we don't want the previous image showing up behind. - Drawable[] layers = {mThumbnailView.getDrawable(), - new BitmapDrawable(mThumbnailView.getResources(), thumbnail)}; - TransitionDrawable transitionDrawable = new TransitionDrawable(layers); - mThumbnailView.setImageDrawable(transitionDrawable); - transitionDrawable.setCrossFadeEnabled(true); - transitionDrawable.startTransition(duration); - } - - private void setDefaultFaviconOnView() { - setFaviconOnView(ApiCompatibilityUtils.getDrawable( - mPublisherTextView.getContext().getResources(), R.drawable.default_favicon)); - } - - private void setFaviconOnView(Bitmap image) { - setFaviconOnView(new BitmapDrawable(mPublisherTextView.getContext().getResources(), image)); - } - - private void setFaviconOnView(Drawable drawable) { - drawable.setBounds(0, 0, mPublisherFaviconSizePx, mPublisherFaviconSizePx); - ApiCompatibilityUtils.setCompoundDrawablesRelative( - mPublisherTextView, drawable, null, null, null); - mPublisherTextView.setVisibility(View.VISIBLE); - } - - private class FetchImageCallback extends Callback<Bitmap> { - private final SnippetArticle mSuggestion; - private final int mThumbnailSize; - private final boolean mIsBitmapOwned; - - FetchImageCallback(SnippetArticle suggestion, int size) { - mSuggestion = suggestion; - mThumbnailSize = size; - mIsBitmapOwned = suggestion.isArticle(); - } - - @Override - public void onResult(Bitmap thumbnail) { - if (thumbnail == null) return; // Nothing to do, we keep the placeholder. - - // We need to crop and scale the downloaded bitmap, as the ImageView we set it on won't - // be able to do so when using a TransitionDrawable (as opposed to the straight bitmap). - // That's a limitation of TransitionDrawable, which doesn't handle layers of varying - // sizes. - if (thumbnail.getHeight() != mThumbnailSize || thumbnail.getWidth() != mThumbnailSize) { - // Resize the thumbnail. If we fully own the input bitmap (e.g. it isn't cached - // anywhere else), recycle the input image in the process. - thumbnail = ThumbnailUtils.extractThumbnail(thumbnail, mThumbnailSize, - mThumbnailSize, mIsBitmapOwned ? ThumbnailUtils.OPTIONS_RECYCLE_INPUT : 0); - } - - // Store the bitmap to skip the download task next time we display this snippet. - mSuggestion.setThumbnailBitmap(mUiDelegate.getReferencePool().put(thumbnail)); - - if (mSuggestion != mArticle) return; - - fadeThumbnailIn(thumbnail); - } + mSuggestionsBinder.updateOfflineBadgeVisibility(visible); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java new file mode 100644 index 0000000..9832169 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java
@@ -0,0 +1,369 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.suggestions; + +import android.content.res.ColorStateList; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.TransitionDrawable; +import android.media.ThumbnailUtils; +import android.os.StrictMode; +import android.os.SystemClock; +import android.support.annotation.Nullable; +import android.support.v4.text.BidiFormatter; +import android.text.TextUtils; +import android.text.format.DateUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.Callback; +import org.chromium.base.Promise; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation; +import org.chromium.chrome.browser.download.DownloadUtils; +import org.chromium.chrome.browser.download.ui.DownloadFilter; +import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; +import org.chromium.chrome.browser.widget.TintedImageView; + +/** + * This class is directly connected to suggestions view holders. It takes over the responsibility + * of the view holder to update information on the views on the suggestion card. + */ +public class SuggestionsBinder { + private static final String ARTICLE_AGE_FORMAT_STRING = " - %s"; + private static final int FADE_IN_ANIMATION_TIME_MS = 300; + + private final ImageFetcher mImageFetcher; + private final SuggestionsUiDelegate mUiDelegate; + + private final View mCardContainerView; + private final LinearLayout mTextLayout; + private final TextView mHeadlineTextView; + private final TextView mPublisherTextView; + private final TextView mSnippetTextView; + private final TextView mAgeTextView; + private final TintedImageView mThumbnailView; + private final ImageView mThumbnailVideoOverlay; + private final ImageView mOfflineBadge; + private final View mPublisherBar; + + /** Total horizontal space occupied by the thumbnail, sum of its size and margin. */ + private final int mThumbnailFootprintPx; + private final int mThumbnailSize; + + @Nullable + private ImageFetcher.DownloadThumbnailRequest mThumbnailRequest; + + private SnippetArticle mSuggestion; + + public SuggestionsBinder(View cardContainerView, SuggestionsUiDelegate uiDelegate) { + mCardContainerView = cardContainerView; + mUiDelegate = uiDelegate; + mImageFetcher = uiDelegate.getImageFetcher(); + + mTextLayout = mCardContainerView.findViewById(R.id.text_layout); + mThumbnailView = mCardContainerView.findViewById(R.id.article_thumbnail); + + mHeadlineTextView = mCardContainerView.findViewById(R.id.article_headline); + mPublisherTextView = mCardContainerView.findViewById(R.id.article_publisher); + mSnippetTextView = mCardContainerView.findViewById(R.id.article_snippet); + mAgeTextView = mCardContainerView.findViewById(R.id.article_age); + mThumbnailVideoOverlay = + mCardContainerView.findViewById(R.id.article_thumbnail_video_overlay); + mPublisherBar = mCardContainerView.findViewById(R.id.publisher_bar); + mOfflineBadge = mCardContainerView.findViewById(R.id.offline_icon); + + boolean useLargeThumbnailLayout = + ChromeFeatureList.isEnabled(ChromeFeatureList.CONTENT_SUGGESTIONS_LARGE_THUMBNAIL); + mThumbnailSize = mCardContainerView.getResources().getDimensionPixelSize( + useLargeThumbnailLayout ? R.dimen.snippets_thumbnail_size_large + : R.dimen.snippets_thumbnail_size); + mThumbnailFootprintPx = mThumbnailSize + + mCardContainerView.getResources().getDimensionPixelSize( + R.dimen.snippets_thumbnail_margin); + } + + public void updateViewInformation(SnippetArticle suggestion) { + mSuggestion = suggestion; + + mHeadlineTextView.setText(suggestion.mTitle); + mSnippetTextView.setText(suggestion.mPreviewText); + mPublisherTextView.setText(getPublisherString(suggestion)); + mAgeTextView.setText(getArticleAge(suggestion)); + + setFavicon(); + setThumbnail(); + } + + public void updateFieldsVisibility(boolean showHeadline, boolean showDescription, + boolean showThumbnail, boolean showThumbnailVideoOverlay, int headerMaxLines) { + mHeadlineTextView.setVisibility(showHeadline ? View.VISIBLE : View.GONE); + mHeadlineTextView.setMaxLines(headerMaxLines); + mSnippetTextView.setVisibility(showDescription ? View.VISIBLE : View.GONE); + mThumbnailView.setVisibility(showThumbnail ? View.VISIBLE : View.GONE); + mThumbnailVideoOverlay.setVisibility(showThumbnailVideoOverlay ? View.VISIBLE : View.GONE); + + ViewGroup.MarginLayoutParams publisherBarParams = + (ViewGroup.MarginLayoutParams) mPublisherBar.getLayoutParams(); + + if (showDescription) { + publisherBarParams.topMargin = mPublisherBar.getResources().getDimensionPixelSize( + R.dimen.snippets_publisher_margin_top_with_article_snippet); + } else if (showHeadline) { + // When we show a headline and not a description, we reduce the top margin of the + // publisher bar. + publisherBarParams.topMargin = mPublisherBar.getResources().getDimensionPixelSize( + R.dimen.snippets_publisher_margin_top_without_article_snippet); + } else { + // When there is no headline and no description, we remove the top margin of the + // publisher bar. + publisherBarParams.topMargin = 0; + } + + if (ChromeFeatureList.isEnabled(ChromeFeatureList.CONTENT_SUGGESTIONS_LARGE_THUMBNAIL)) { + mTextLayout.setMinimumHeight(showThumbnail ? mThumbnailSize : 0); + } else { + ApiCompatibilityUtils.setMarginEnd( + publisherBarParams, showThumbnail ? mThumbnailFootprintPx : 0); + } + + mPublisherBar.setLayoutParams(publisherBarParams); + } + + public void updateOfflineBadgeVisibility(boolean visible) { + if (visible == (mOfflineBadge.getVisibility() == View.VISIBLE)) return; + mOfflineBadge.setVisibility(visible ? View.VISIBLE : View.GONE); + } + + private void setFavicon() { + // The favicon of the publisher should match the TextView height. + int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + mPublisherTextView.measure(widthSpec, heightSpec); + final int publisherFaviconSizePx = mPublisherTextView.getMeasuredHeight(); + + // Set the favicon of the publisher. + // We start initialising with the default favicon to reserve the space and prevent the text + // from moving later. + setDefaultFaviconOnView(publisherFaviconSizePx); + Callback<Bitmap> faviconCallback = new Callback<Bitmap>() { + @Override + public void onResult(Bitmap bitmap) { + setFaviconOnView(bitmap, publisherFaviconSizePx); + } + }; + + mImageFetcher.makeFaviconRequest(mSuggestion, publisherFaviconSizePx, faviconCallback); + } + + private void setThumbnail() { + // If there's still a pending thumbnail fetch, cancel it. + cancelThumbnailFetch(); + + // mThumbnailView's visibility is modified in updateFieldsVisibility(). + if (mThumbnailView.getVisibility() != View.VISIBLE) return; + + Bitmap thumbnail = mSuggestion.getThumbnailBitmap(); + if (thumbnail != null) { + setThumbnailFromBitmap(thumbnail); + return; + } + + if (mSuggestion.isDownload()) { + setDownloadThumbnail(); + return; + } + + // Temporarily set placeholder and then fetch the thumbnail from a provider. + mThumbnailView.setBackground(null); + mThumbnailView.setImageResource(R.drawable.ic_snippet_thumbnail_placeholder); + mThumbnailView.setTint(null); + + // Fetch thumbnail for the current article. + mImageFetcher.makeArticleThumbnailRequest( + mSuggestion, new FetchThumbnailCallback(mSuggestion, mThumbnailSize)); + } + + private void setDownloadThumbnail() { + assert mSuggestion.isDownload(); + if (!mSuggestion.isAssetDownload()) { + setThumbnailFromFileType(DownloadFilter.FILTER_PAGE); + return; + } + + int fileType = DownloadFilter.fromMimeType(mSuggestion.getAssetDownloadMimeType()); + if (fileType == DownloadFilter.FILTER_IMAGE) { + // For image downloads, attempt to fetch a thumbnail. + ImageFetcher.DownloadThumbnailRequest thumbnailRequest = + mImageFetcher.makeDownloadThumbnailRequest(mSuggestion, mThumbnailSize); + + Promise<Bitmap> thumbnailReceivedPromise = thumbnailRequest.getPromise(); + + if (thumbnailReceivedPromise.isFulfilled()) { + // If the thumbnail was cached, then it will be retrieved synchronously, the promise + // will be fulfilled and we can set the thumbnail immediately. + setThumbnailFromBitmap(thumbnailReceivedPromise.getResult()); + return; + } + + mThumbnailRequest = thumbnailRequest; + + // Queue a callback to be called after the thumbnail is retrieved asynchronously. + thumbnailReceivedPromise.then(new FetchThumbnailCallback(mSuggestion, mThumbnailSize)); + } + + // Set a placeholder for the file type. + setThumbnailFromFileType(fileType); + } + + private void setThumbnailFromBitmap(Bitmap thumbnail) { + assert thumbnail != null; + assert !thumbnail.isRecycled(); + assert thumbnail.getWidth() <= mThumbnailSize || thumbnail.getHeight() <= mThumbnailSize; + + mThumbnailView.setScaleType(ImageView.ScaleType.CENTER_CROP); + mThumbnailView.setBackground(null); + mThumbnailView.setImageBitmap(thumbnail); + mThumbnailView.setTint(null); + } + + private void setThumbnailFromFileType(int fileType) { + int iconBackgroundColor = DownloadUtils.getIconBackgroundColor(mThumbnailView.getContext()); + ColorStateList iconForegroundColorList = + DownloadUtils.getIconForegroundColorList(mThumbnailView.getContext()); + + mThumbnailView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + mThumbnailView.setBackgroundColor(iconBackgroundColor); + mThumbnailView.setImageResource( + DownloadUtils.getIconResId(fileType, DownloadUtils.ICON_SIZE_36_DP)); + mThumbnailView.setTint(iconForegroundColorList); + } + + private void setDefaultFaviconOnView(int faviconSizePx) { + setFaviconOnView( + ApiCompatibilityUtils.getDrawable( + mPublisherTextView.getContext().getResources(), R.drawable.default_favicon), + faviconSizePx); + } + + private void setFaviconOnView(Bitmap image, int faviconSizePx) { + setFaviconOnView(new BitmapDrawable(mPublisherTextView.getContext().getResources(), image), + faviconSizePx); + } + + private void setFaviconOnView(Drawable drawable, int faviconSizePx) { + drawable.setBounds(0, 0, faviconSizePx, faviconSizePx); + ApiCompatibilityUtils.setCompoundDrawablesRelative( + mPublisherTextView, drawable, null, null, null); + mPublisherTextView.setVisibility(View.VISIBLE); + } + + private void cancelThumbnailFetch() { + if (mThumbnailRequest != null) { + mThumbnailRequest.cancel(); + mThumbnailRequest = null; + } + } + + private void fadeThumbnailIn(Bitmap thumbnail) { + assert mThumbnailView.getDrawable() != null; + + mThumbnailView.setScaleType(ImageView.ScaleType.CENTER_CROP); + mThumbnailView.setBackground(null); + mThumbnailView.setTint(null); + int duration = (int) (FADE_IN_ANIMATION_TIME_MS + * ChromeAnimation.Animation.getAnimationMultiplier()); + if (duration == 0) { + mThumbnailView.setImageBitmap(thumbnail); + return; + } + + // Cross-fade between the placeholder and the thumbnail. We cross-fade because the incoming + // image may have transparency and we don't want the previous image showing up behind. + Drawable[] layers = {mThumbnailView.getDrawable(), + new BitmapDrawable(mThumbnailView.getResources(), thumbnail)}; + TransitionDrawable transitionDrawable = new TransitionDrawable(layers); + mThumbnailView.setImageDrawable(transitionDrawable); + transitionDrawable.setCrossFadeEnabled(true); + transitionDrawable.startTransition(duration); + } + + private static String getPublisherString(SnippetArticle suggestion) { + // We format the publisher here so that having a publisher name in an RTL language + // doesn't mess up the formatting on an LTR device and vice versa. + return BidiFormatter.getInstance().unicodeWrap(suggestion.mPublisher); + } + + private static String getArticleAge(SnippetArticle suggestion) { + if (suggestion.mPublishTimestampMilliseconds == 0) return ""; + + // DateUtils.getRelativeTimeSpanString(...) calls through to TimeZone.getDefault(). If this + // has never been called before it loads the current time zone from disk. In most likelihood + // this will have been called previously and the current time zone will have been cached, + // but in some cases (eg instrumentation tests) it will cause a strict mode violation. + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + CharSequence relativeTimeSpan; + try { + long time = SystemClock.elapsedRealtime(); + relativeTimeSpan = + DateUtils.getRelativeTimeSpanString(suggestion.mPublishTimestampMilliseconds, + System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS); + SuggestionsMetrics.recordDateFormattingDuration(SystemClock.elapsedRealtime() - time); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } + + // We add a dash before the elapsed time, e.g. " - 14 minutes ago". + return String.format(ARTICLE_AGE_FORMAT_STRING, + BidiFormatter.getInstance().unicodeWrap(relativeTimeSpan)); + } + + private class FetchThumbnailCallback extends Callback<Bitmap> { + private final SnippetArticle mCapturedSuggestion; + private final int mThumbnailSize; + + FetchThumbnailCallback(SnippetArticle suggestion, int size) { + mCapturedSuggestion = suggestion; + mThumbnailSize = size; + } + + @Override + public void onResult(Bitmap thumbnail) { + if (thumbnail == null) return; // Nothing to do, we keep the placeholder. + + // We need to crop and scale the downloaded bitmap, as the ImageView we set it on won't + // be able to do so when using a TransitionDrawable (as opposed to the straight bitmap). + // That's a limitation of TransitionDrawable, which doesn't handle layers of varying + // sizes. + if (thumbnail.getHeight() != mThumbnailSize || thumbnail.getWidth() != mThumbnailSize) { + // Resize the thumbnail. If the provided bitmap is not cached or used anywhere else + // (that's true for bitmaps returned by SuggestionsSource for ARTICLE + // suggestions but not for those returned by ThumbnailProvider for DOWNLOADS for + // example), recycle the input image in the process. + thumbnail = ThumbnailUtils.extractThumbnail(thumbnail, mThumbnailSize, + mThumbnailSize, + mCapturedSuggestion.isArticle() ? ThumbnailUtils.OPTIONS_RECYCLE_INPUT : 0); + } + + // Store the bitmap to skip the download task next time we display this snippet. + mCapturedSuggestion.setThumbnailBitmap(mUiDelegate.getReferencePool().put(thumbnail)); + + // Check whether the suggestions currently displayed in the view holder is the same as + // the suggestion whose thumbnail we have just fetched. + // This approach allows us to save the thumbnail in its corresponding SnippetArticle + // regardless of whether a new suggestion has been bound to the view holder. This way we + // don't have to cancel fetches and can use the retrieved thumbnail later on. + if (!TextUtils.equals(mCapturedSuggestion.getUrl(), mSuggestion.getUrl())) return; + + fadeThumbnailIn(thumbnail); + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java index 195549ba..e6a76278 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java
@@ -113,6 +113,17 @@ } /** + * Measures the amount of time it takes for date formatting in order to track StrictMode + * violations. + * See https://crbug.com/639877 + * @param duration Duration of date formatting. + */ + static void recordDateFormattingDuration(long duration) { + RecordHistogram.recordTimesHistogram( + "Android.StrictMode.SnippetUIBuildTime", duration, TimeUnit.MILLISECONDS); + } + + /** * One-shot reporter that records the first time the user scrolls a {@link RecyclerView}. If it * should be reused, call {@link #reset()} to rearm it. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileView.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileView.java index 316e0a4..c4040d93 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileView.java
@@ -110,8 +110,8 @@ assert mUrl.equals(tile.getUrl()); if (tile.getIcon() != mIconView.getDrawable()) return false; + if (!tile.getTitle().equals(mTitleView.getText())) return false; if (tile.isOfflineAvailable() != (mBadgeView.getVisibility() == VISIBLE)) return false; - // We don't check the title since it's not likely to change, but that could also be done. return true; }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 8b1fadd..8025440 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1024,6 +1024,7 @@ "java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java", "java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java", "java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java", + "java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java", "java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java", "java/src/org/chromium/chrome/browser/suggestions/Tile.java", "java/src/org/chromium/chrome/browser/suggestions/TileGrid.java",
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 4f9d7ce..ef2019ff 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -990,6 +990,8 @@ "predictors/loading_predictor_factory.h", "predictors/loading_stats_collector.cc", "predictors/loading_stats_collector.h", + "predictors/preconnect_manager.cc", + "predictors/preconnect_manager.h", "predictors/predictor_database.cc", "predictors/predictor_database.h", "predictors/predictor_database_factory.cc", @@ -1550,7 +1552,6 @@ "//components/policy:generated", "//components/policy/core/browser", "//components/policy/proto", - "//components/precache/core", "//components/prefs:prefs", "//components/previews/core", "//components/profile_metrics", @@ -3081,6 +3082,7 @@ "//components/data_usage/android", "//components/payments/content/android", "//components/precache/content", + "//components/precache/core", "//components/resources:components_resources", "//components/toolbar", "//components/web_contents_delegate_android",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index f75a00d..d0e8a37 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2382,11 +2382,6 @@ flag_descriptions::kEnableNtpMostLikelyFaviconsFromServerDescription, kOsAndroid, FEATURE_VALUE_TYPE(ntp_tiles::kNtpMostLikelyFaviconsFromServerFeature)}, - {"enable-content-suggestions-categories", - flag_descriptions::kEnableContentSuggestionsCategoriesName, - flag_descriptions::kEnableContentSuggestionsCategoriesDescription, - kOsAndroid, - FEATURE_VALUE_TYPE(chrome::android::kContentSuggestionsCategories)}, {"enable-content-suggestions-large-thumbnail", flag_descriptions::kEnableContentSuggestionsLargeThumbnailName, flag_descriptions::kEnableContentSuggestionsLargeThumbnailDescription,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index bcfcd7d9..6f97fcb 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -56,7 +56,6 @@ &kChromeHomeFeature, &kChromeHomeExpandButton, &kChromeHomeSwipeLogic, - &kContentSuggestionsCategories, &kContentSuggestionsLargeThumbnail, &kContentSuggestionsVideoOverlay, &kContentSuggestionsSettings, @@ -145,9 +144,6 @@ const base::Feature kChromeHomeSwipeLogic{"ChromeHomeSwipeLogic", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kContentSuggestionsCategories{ - "ContentSuggestionsCategories", base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kContentSuggestionsLargeThumbnail{ "ContentSuggestionsLargeThumbnail", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h index fe80482..350b8c8 100644 --- a/chrome/browser/android/chrome_feature_list.h +++ b/chrome/browser/android/chrome_feature_list.h
@@ -22,7 +22,6 @@ extern const base::Feature kChromeHomeFeature; extern const base::Feature kChromeHomeExpandButton; extern const base::Feature kChromeHomeSwipeLogic; -extern const base::Feature kContentSuggestionsCategories; extern const base::Feature kContentSuggestionsLargeThumbnail; extern const base::Feature kContentSuggestionsVideoOverlay; extern const base::Feature kContentSuggestionsSettings;
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.cc b/chrome/browser/android/ntp/most_visited_sites_bridge.cc index 42135b7..93693cf 100644 --- a/chrome/browser/android/ntp/most_visited_sites_bridge.cc +++ b/chrome/browser/android/ntp/most_visited_sites_bridge.cc
@@ -10,11 +10,15 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" #include "chrome/browser/thumbnails/thumbnail_list_source.h" +#include "components/history/core/browser/history_service.h" #include "components/ntp_tiles/metrics.h" #include "components/ntp_tiles/most_visited_sites.h" #include "components/rappor/rappor_service_impl.h" @@ -39,21 +43,80 @@ class JavaHomePageClient : public MostVisitedSites::HomePageClient { public: - JavaHomePageClient(JNIEnv* env, const JavaParamRef<jobject>& obj); + JavaHomePageClient(JNIEnv* env, + const JavaParamRef<jobject>& obj, + Profile* profile); bool IsHomePageEnabled() const override; bool IsNewTabPageUsedAsHomePage() const override; - GURL GetHomepageUrl() const override; + GURL GetHomePageUrl() const override; + void QueryHomePageTitle(TitleCallback title_callback) override; private: + void OnTitleEntryFound(bool success, + const history::URLRow& row, + const history::VisitVector& visits); + ScopedJavaGlobalRef<jobject> client_; + Profile* profile_; + + // Used in loading titles. + base::CancelableTaskTracker task_tracker_; + TitleCallback title_callback_; DISALLOW_COPY_AND_ASSIGN(JavaHomePageClient); }; JavaHomePageClient::JavaHomePageClient(JNIEnv* env, - const JavaParamRef<jobject>& obj) - : client_(env, obj) {} + const JavaParamRef<jobject>& obj, + Profile* profile) + : client_(env, obj), profile_(profile) { + DCHECK(profile); +} + +void JavaHomePageClient::QueryHomePageTitle( + base::OnceCallback<void(const base::Optional<base::string16>&)> + title_callback) { + if (!title_callback_.is_null()) { + // A finished task always has to call the callback. + DCHECK(task_tracker_.HasTrackedTasks()); + // If the last callback was not called, drop it as data would be stale. + task_tracker_.TryCancelAll(); + } + DCHECK(!title_callback.is_null()); + title_callback_ = std::move(title_callback); + GURL url = GetHomePageUrl(); + if (url.is_empty()) { + std::move(title_callback_).Run(base::nullopt); + return; + } + history::HistoryService* const history_service = + HistoryServiceFactory::GetForProfileIfExists( + profile_, ServiceAccessType::EXPLICIT_ACCESS); + if (!history_service) { + std::move(title_callback_).Run(base::nullopt); + return; + } + // If the client is destroyed, the tracker will cancel this task automatically + // and the callback will not be called. Therefore, base::Unretained works. + // TODO(fhorschig): Bind the title_callback_ to |OnTitleEntryFound| as soon as + // |QueryURL| supports base::OnceCallback. + history_service->QueryURL(url, + /*want_visits=*/false, + base::Bind(&JavaHomePageClient::OnTitleEntryFound, + base::Unretained(this)), + &task_tracker_); +} + +void JavaHomePageClient::OnTitleEntryFound(bool success, + const history::URLRow& row, + const history::VisitVector& visits) { + if (!success) { + std::move(title_callback_).Run(base::nullopt); + return; + } + std::move(title_callback_).Run(row.title()); +} bool JavaHomePageClient::IsHomePageEnabled() const { return Java_HomePageClient_isHomePageEnabled(AttachCurrentThread(), client_); @@ -64,7 +127,7 @@ client_); } -GURL JavaHomePageClient::GetHomepageUrl() const { +GURL JavaHomePageClient::GetHomePageUrl() const { base::android::ScopedJavaLocalRef<jstring> url = Java_HomePageClient_getHomePageUrl(AttachCurrentThread(), client_); if (url.is_null()) { @@ -127,7 +190,8 @@ } MostVisitedSitesBridge::MostVisitedSitesBridge(Profile* profile) - : most_visited_(ChromeMostVisitedSitesFactory::NewForProfile(profile)) { + : most_visited_(ChromeMostVisitedSitesFactory::NewForProfile(profile)), + profile_(profile) { // Register the thumbnails debugging page. // TODO(sfiera): find thumbnails a home. They don't belong here. content::URLDataSource::Add(profile, new ThumbnailListSource(profile)); @@ -161,7 +225,7 @@ const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jobject>& j_client) { most_visited_->SetHomePageClient( - base::MakeUnique<JavaHomePageClient>(env, j_client)); + base::MakeUnique<JavaHomePageClient>(env, j_client, profile_)); } void MostVisitedSitesBridge::AddOrRemoveBlacklistedUrl(
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.h b/chrome/browser/android/ntp/most_visited_sites_bridge.h index fe8fd5f..3eede8c 100644 --- a/chrome/browser/android/ntp/most_visited_sites_bridge.h +++ b/chrome/browser/android/ntp/most_visited_sites_bridge.h
@@ -68,6 +68,7 @@ std::unique_ptr<JavaObserver> java_observer_; std::unique_ptr<ntp_tiles::MostVisitedSites> most_visited_; + Profile* profile_; DISALLOW_COPY_AND_ASSIGN(MostVisitedSitesBridge); };
diff --git a/chrome/browser/cryptauth/chrome_cryptauth_service.cc b/chrome/browser/cryptauth/chrome_cryptauth_service.cc index cd4673c..132e6d66 100644 --- a/chrome/browser/cryptauth/chrome_cryptauth_service.cc +++ b/chrome/browser/cryptauth/chrome_cryptauth_service.cc
@@ -131,21 +131,12 @@ return device_info; } -std::string GetAccountIdImpl(Profile* profile) { -#if defined(OS_CHROMEOS) - SigninManagerBase* manager = SigninManagerFactory::GetForProfile(profile); -#else - SigninManager* manager = SigninManagerFactory::GetForProfile(profile); -#endif - return manager ? manager->GetAuthenticatedAccountId() : std::string(); -} - std::unique_ptr<cryptauth::CryptAuthClientFactory> CreateCryptAuthClientFactoryImpl(Profile* profile) { return base::MakeUnique<cryptauth::CryptAuthClientFactoryImpl>( ProfileOAuth2TokenServiceFactory::GetForProfile(profile), - GetAccountIdImpl(profile), profile->GetRequestContext(), - GetDeviceClassifierImpl()); + SigninManagerFactory::GetForProfile(profile)->GetAuthenticatedAccountId(), + profile->GetRequestContext(), GetDeviceClassifierImpl()); } std::unique_ptr<cryptauth::SecureMessageDelegate> @@ -200,9 +191,14 @@ ProfileOAuth2TokenService* token_service = ProfileOAuth2TokenServiceFactory::GetForProfile(profile); + // Note: ChromeCryptAuthServiceFactory DependsOn(OAuth2TokenServiceFactory), + // so |token_service| is guaranteed to outlast this service. + SigninManagerBase* signin_manager = + SigninManagerFactory::GetForProfile(profile); + return base::WrapUnique(new ChromeCryptAuthService( std::move(gcm_manager), std::move(device_manager), - std::move(enrollment_manager), profile, token_service)); + std::move(enrollment_manager), profile, token_service, signin_manager)); } ChromeCryptAuthService::ChromeCryptAuthService( @@ -210,28 +206,42 @@ std::unique_ptr<cryptauth::CryptAuthDeviceManager> device_manager, std::unique_ptr<cryptauth::CryptAuthEnrollmentManager> enrollment_manager, Profile* profile, - OAuth2TokenService* token_service) + OAuth2TokenService* token_service, + SigninManagerBase* signin_manager) : KeyedService(), cryptauth::CryptAuthService(), gcm_manager_(std::move(gcm_manager)), enrollment_manager_(std::move(enrollment_manager)), device_manager_(std::move(device_manager)), profile_(profile), - token_service_(token_service) { + token_service_(token_service), + signin_manager_(signin_manager) { gcm_manager_->StartListening(); - if (!token_service_->RefreshTokenIsAvailable(GetAccountId())) { + if (!signin_manager_->IsAuthenticated()) { + PA_LOG(INFO) << "Profile is not authenticated yet; " + << "waiting before starting CryptAuth managers."; + signin_manager_->AddObserver(this); + return; + } + + std::string account_id = signin_manager_->GetAuthenticatedAccountId(); + if (!token_service_->RefreshTokenIsAvailable(account_id)) { PA_LOG(INFO) << "Refresh token not yet available; " << "waiting before starting CryptAuth managers."; token_service_->AddObserver(this); - } else { - PerformEnrollmentAndDeviceSync(); + return; } + + // Profile is authenticated and there is a refresh token available for the + // authenticated account id. + PerformEnrollmentAndDeviceSync(); } ChromeCryptAuthService::~ChromeCryptAuthService() {} void ChromeCryptAuthService::Shutdown() { + signin_manager_->RemoveObserver(this); token_service_->RemoveObserver(this); enrollment_manager_.reset(); device_manager_.reset(); @@ -253,7 +263,7 @@ } std::string ChromeCryptAuthService::GetAccountId() { - return GetAccountIdImpl(profile_); + return signin_manager_->GetAuthenticatedAccountId(); } std::unique_ptr<cryptauth::SecureMessageDelegate> @@ -278,6 +288,20 @@ enrollment_manager_->RemoveObserver(this); } +void ChromeCryptAuthService::GoogleSigninSucceeded( + const std::string& account_id, + const std::string& username) { + signin_manager_->RemoveObserver(this); + if (!token_service_->RefreshTokenIsAvailable(account_id)) { + PA_LOG(INFO) << "Refresh token not yet available; " + << "waiting before starting CryptAuth managers."; + token_service_->AddObserver(this); + return; + } + + PerformEnrollmentAndDeviceSync(); +} + void ChromeCryptAuthService::OnRefreshTokenAvailable( const std::string& account_id) { if (account_id == GetAccountId()) { @@ -287,6 +311,8 @@ } void ChromeCryptAuthService::PerformEnrollmentAndDeviceSync() { + DCHECK(signin_manager_->IsAuthenticated()); + DCHECK(token_service_->RefreshTokenIsAvailable(GetAccountId())); if (enrollment_manager_->IsEnrollmentValid()) { device_manager_->Start(); } else {
diff --git a/chrome/browser/cryptauth/chrome_cryptauth_service.h b/chrome/browser/cryptauth/chrome_cryptauth_service.h index 9aa6c11e..478cea7e 100644 --- a/chrome/browser/cryptauth/chrome_cryptauth_service.h +++ b/chrome/browser/cryptauth/chrome_cryptauth_service.h
@@ -12,6 +12,7 @@ #include "components/cryptauth/cryptauth_service.h" #include "components/cryptauth/proto/cryptauth_api.pb.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/signin/core/browser/signin_manager_base.h" #include "google_apis/gaia/oauth2_token_service.h" class Profile; @@ -25,7 +26,8 @@ : public KeyedService, public cryptauth::CryptAuthService, public cryptauth::CryptAuthEnrollmentManager::Observer, - public OAuth2TokenService::Observer { + public OAuth2TokenService::Observer, + public SigninManagerBase::Observer { public: static std::unique_ptr<ChromeCryptAuthService> Create(Profile* profile); ~ChromeCryptAuthService() override; @@ -56,12 +58,17 @@ std::unique_ptr<cryptauth::CryptAuthDeviceManager> device_manager, std::unique_ptr<cryptauth::CryptAuthEnrollmentManager> enrollment_manager, Profile* profile, - OAuth2TokenService* token_service); + OAuth2TokenService* token_service, + SigninManagerBase* signin_manager); private: // OAuth2TokenService::Observer: void OnRefreshTokenAvailable(const std::string& account_id) override; + // SigninManagerBase::Observer: + void GoogleSigninSucceeded(const std::string& account_id, + const std::string& username) override; + void PerformEnrollmentAndDeviceSync(); std::unique_ptr<cryptauth::CryptAuthGCMManager> gcm_manager_; @@ -69,6 +76,7 @@ std::unique_ptr<cryptauth::CryptAuthDeviceManager> device_manager_; Profile* profile_; OAuth2TokenService* token_service_; + SigninManagerBase* signin_manager_; DISALLOW_COPY_AND_ASSIGN(ChromeCryptAuthService); };
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc index b875323..cf6a8ec 100644 --- a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc +++ b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
@@ -14,6 +14,7 @@ #include "base/values.h" #include "chrome/browser/browsing_data/browsing_data_helper.h" +#include "base/task_scheduler/post_task.h" #include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h" #include "chrome/browser/plugins/plugin_data_remover_helper.h" #include "chrome/browser/plugins/plugin_prefs.h" @@ -283,8 +284,10 @@ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA) { // If we're being asked to remove plugin data, check whether it's actually // supported. - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, + PostTaskWithTraits( + FROM_HERE, + {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN, + base::TaskPriority::USER_VISIBLE}, base::BindOnce( &BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported, this, PluginPrefs::GetForProfile(GetProfile())));
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 221a679..0fb9012c 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -26,8 +26,8 @@ "Enable Material Design policy page"; const char kEnableMaterialDesignPolicyPageDescription[] = - "If enabled, the chrome://md-policy URL loads the Material Design " - "policy page."; + "If enabled, the chrome://md-policy URL loads the Material Design policy " + "page."; // Material Design version of chrome://extensions @@ -44,8 +44,7 @@ "Enable Material Design feedback"; const char kEnableMaterialDesignFeedbackDescription[] = - "If enabled, reporting an issue will load the Material Design feedback " - "UI."; + "If enabled, reporting an issue will load the Material Design feedback UI."; const char kContextualSuggestionsCarouselName[] = "Enable Contextual Suggestions"; @@ -67,8 +66,8 @@ "Use Blink's zoom for device scale factor."; const char kEnableUseZoomForDsfDescription[] = - "If enabled, Blink uses its zooming mechanism to scale content for " - "device scale factor."; + "If enabled, Blink uses its zooming mechanism to scale content for device " + "scale factor."; const char kEnableUseZoomForDsfChoiceDefault[] = "Default"; @@ -122,16 +121,16 @@ const char kPrintPdfAsImageName[] = "Print Pdf as Image"; const char kPrintPdfAsImageDescription[] = - "If enabled, an option to print PDF files as images will be available " - "in print preview."; + "If enabled, an option to print PDF files as images will be available in " + "print preview."; #endif #if !defined(DISABLE_NACL) const char kNaclName[] = "Native Client"; const char kNaclDescription[] = - "Support Native Client for all web applications, even those that were " - "not installed from the Chrome Web Store."; + "Support Native Client for all web applications, even those that were not " + "installed from the Chrome Web Store."; const char kNaclDebugName[] = "Native Client GDB-based debugging"; const char kNaclDebugDescription[] = @@ -146,8 +145,8 @@ "Restrict Native Client GDB-based debugging by pattern"; const char kNaclDebugMaskDescription[] = "Restricts Native Client application GDB-based debugging by URL of " - "manifest file. Native Client GDB-based debugging must be enabled for " - "this option to work."; + "manifest file. Native Client GDB-based debugging must be enabled for this " + "option to work."; const char kNaclDebugMaskChoiceDebugAll[] = "Debug everything."; const char kNaclDebugMaskChoiceExcludeUtilsPnacl[] = "Debug everything except secure shell and the PNaCl translator."; @@ -157,12 +156,12 @@ #endif const char kEnableHttpFormWarningName[] = - "Show in-form warnings for sensitive fields when the top-level page is " - "not HTTPS"; + "Show in-form warnings for sensitive fields when the top-level page is not " + "HTTPS"; const char kEnableHttpFormWarningDescription[] = - "Attaches a warning UI to any password or credit card fields detected " - "when the top-level page is not HTTPS"; + "Attaches a warning UI to any password or credit card fields detected when " + "the top-level page is not HTTPS"; const char kMarkHttpAsName[] = "Mark non-secure origins as non-secure"; @@ -181,14 +180,14 @@ "Material Design Incognito NTP."; extern const char kMaterialDesignIncognitoNTPDescription[] = - "If enabled, the Incognito New Tab page uses the new material design " - "with a better readable text."; + "If enabled, the Incognito New Tab page uses the new material design with " + "a better readable text."; const char kSavePageAsMhtmlName[] = "Save Page as MHTML"; const char kSavePageAsMhtmlDescription[] = - "Enables saving pages as MHTML: a single text file containing HTML and " - "all sub-resources."; + "Enables saving pages as MHTML: a single text file containing HTML and all " + "sub-resources."; // Flag and values for MHTML Generator options lab. @@ -212,9 +211,9 @@ const char kCloudPrintXpsName[] = "XPS in Google Cloud Print"; const char kCloudPrintXpsDescription[] = - "XPS enables advanced options for classic printers connected to the " - "Cloud Print with Chrome. Printers must be re-connected after changing " - "this flag."; + "XPS enables advanced options for classic printers connected to the Cloud " + "Print with Chrome. Printers must be re-connected after changing this " + "flag."; #endif // defined(OS_WIN) @@ -257,8 +256,8 @@ const char kSecondaryUiMdDescription[] = "Extends the --top-chrome-md setting to secondary UI (bubbles, dialogs, " - "etc.). On Mac, this enables MacViews, which uses toolkit-views for " - "native browser dialogs."; + "etc.). On Mac, this enables MacViews, which uses toolkit-views for native " + "browser dialogs."; const char kScrollPredictionDescription[] = "Predicts the finger's future position during scrolls allowing time to " @@ -309,14 +308,14 @@ const char kTouchAdjustmentName[] = "Touch adjustment"; const char kTouchAdjustmentDescription[] = - "Refine the position of a touch gesture in order to compensate for " - "touches having poor resolution compared to a mouse."; + "Refine the position of a touch gesture in order to compensate for touches " + "having poor resolution compared to a mouse."; const char kCompositedLayerBordersName[] = "Composited render layer borders"; const char kCompositedLayerBordersDescription[] = - "Renders a border around composited Render Layers to help debug and " - "study layer compositing."; + "Renders a border around composited Render Layers to help debug and study " + "layer compositing."; const char kGlCompositedTextureQuadBordersName[] = "GL composited texture quad borders"; @@ -328,8 +327,8 @@ const char kShowOverdrawFeedbackName[] = "Show overdraw feedback"; const char kShowOverdrawFeedbackDescription[] = - "Visualize overdraw by color-coding elements based on if they have " - "other elements drawn underneath."; + "Visualize overdraw by color-coding elements based on if they have other " + "elements drawn underneath."; const char kUiPartialSwapName[] = "Partial swap"; @@ -346,8 +345,8 @@ const char kInertVisualViewportName[] = "Inert visual viewport."; const char kInertVisualViewportDescription[] = - "Experiment to have all APIs reflect the layout viewport. This will " - "make window.scroll properties relative to the layout viewport."; + "Experiment to have all APIs reflect the layout viewport. This will make " + "window.scroll properties relative to the layout viewport."; const char kInProductHelpDemoModeChoiceName[] = "In-Product Help Demo Mode"; @@ -391,8 +390,8 @@ const char kExtensionsOnChromeUrlsName[] = "Extensions on chrome:// URLs"; const char kExtensionsOnChromeUrlsDescription[] = - "Enables running extensions on chrome:// URLs, where extensions " - "explicitly request this permission."; + "Enables running extensions on chrome:// URLs, where extensions explicitly " + "request this permission."; const char kExperimentalFullscreenExitUIName[] = "Experimental fullscreen exit UI"; @@ -410,8 +409,8 @@ const char kFetchKeepaliveTimeoutSettingName[] = "Fetch API keepalive timeout setting"; const char kFetchKeepaliveTimeoutSettingDescription[] = - "This is for setting " - "the timeout value for Fetch API with keepalive option and SendBeacon"; + "This is for setting the timeout value for Fetch API with keepalive option " + "and SendBeacon"; const char kUserConsentForExtensionScriptsName[] = "User consent for extension scripts"; @@ -455,8 +454,8 @@ "Contextual Search - URL Actions"; const char kContextualSearchUrlActionsDescription[] = - "Whether or not URL actions using Contextual Cards data in the " - "Contextual Search Bar is enabled."; + "Whether or not URL actions using Contextual Cards data in the Contextual " + "Search Bar is enabled."; #endif // defined(OS_ANDROID) @@ -468,21 +467,21 @@ const char kOverlayScrollbarsName[] = "Overlay Scrollbars"; const char kOverlayScrollbarsDescription[] = - "Enable the experimental overlay scrollbars implementation. You must " - "also enable threaded compositing to have the scrollbars animate."; + "Enable the experimental overlay scrollbars implementation. You must also " + "enable threaded compositing to have the scrollbars animate."; const char kShowAutofillTypePredictionsName[] = "Show Autofill predictions"; const char kShowAutofillTypePredictionsDescription[] = - "Annotates web forms with Autofill field type predictions as " - "placeholder text."; + "Annotates web forms with Autofill field type predictions as placeholder " + "text."; const char kTcpFastOpenName[] = "TCP Fast Open"; const char kTcpFastOpenDescription[] = - "Enable the option to send extra authentication information in the " - "initial SYN packet for a previously connected client, allowing faster " - "data send start."; + "Enable the option to send extra authentication information in the initial " + "SYN packet for a previously connected client, allowing faster data send " + "start."; const char kTouchDragDropName[] = "Touch initiated drag and drop"; @@ -493,8 +492,8 @@ const char kTouchSelectionStrategyName[] = "Touch text selection strategy"; const char kTouchSelectionStrategyDescription[] = - "Controls how text selection granularity changes when touch text " - "selection handles are dragged. Non-default behavior is experimental."; + "Controls how text selection granularity changes when touch text selection " + "handles are dragged. Non-default behavior is experimental."; const char kTouchSelectionStrategyCharacter[] = "Character"; @@ -504,8 +503,7 @@ "Use Google Payments sandbox servers"; const char kWalletServiceUseSandboxDescription[] = - "For developers: use the sandbox service for Google Payments API " - "calls."; + "For developers: use the sandbox service for Google Payments API calls."; const char kOverscrollHistoryNavigationName[] = "Overscroll history navigation"; @@ -559,21 +557,19 @@ const char kWebrtcHwVP8EncodingName[] = "WebRTC hardware vp8 video encoding"; const char kWebrtcHwVP8EncodingDescription[] = - "Support in WebRTC for encoding vp8 video streams using platform " - "hardware."; + "Support in WebRTC for encoding vp8 video streams using platform hardware."; const char kWebrtcSrtpAesGcmName[] = "Negotiation with GCM cipher suites for SRTP in WebRTC"; const char kWebrtcSrtpAesGcmDescription[] = - "When enabled, WebRTC will try to negotiate GCM cipher suites for " - "SRTP."; + "When enabled, WebRTC will try to negotiate GCM cipher suites for SRTP."; const char kWebrtcStunOriginName[] = "WebRTC Stun origin header"; const char kWebrtcStunOriginDescription[] = - "When enabled, Stun messages generated by WebRTC will contain the " - "Origin header."; + "When enabled, Stun messages generated by WebRTC will contain the Origin " + "header."; const char kWebrtcEchoCanceller3Name[] = "WebRTC Echo Canceller 3."; @@ -595,9 +591,9 @@ "WebRTC H.264 software video encoder/decoder"; const char kWebrtcH264WithOpenh264FfmpegDescription[] = - "When enabled, an H.264 software video encoder/decoder pair is " - "included. If a hardware encoder/decoder is also available it may be " - "used instead of this encoder/decoder."; + "When enabled, an H.264 software video encoder/decoder pair is included. " + "If a hardware encoder/decoder is also available it may be used instead of " + "this encoder/decoder."; #endif // BUILDFLAG(ENABLE_WEBRTC) @@ -613,8 +609,8 @@ "WebVR experimental rendering optimizations"; const char kWebvrExperimentalRenderingDescription[] = - "Enabling this option activates experimental rendering path " - "optimizations for WebVR."; + "Enabling this option activates experimental rendering path optimizations " + "for WebVR."; #endif // BUILDFLAG(ENABLE_VR) @@ -667,8 +663,8 @@ "Document Level Event Listeners Passive Default"; const char kPassiveEventListenersDueToFlingDescription[] = - "Forces touchstart, and first touchmove per scroll event listeners " - "during fling to be treated as passive."; + "Forces touchstart, and first touchmove per scroll event listeners during " + "fling to be treated as passive."; const char kPassiveEventListenersDueToFlingName[] = "Touch Event Listeners Passive Default During Fling"; @@ -681,11 +677,10 @@ "Passive Event Listener Override"; const char kPassiveEventListenerDefaultDescription[] = - "Forces touchstart, touchmove, mousewheel and wheel event listeners " - "(which haven't requested otherwise) to be treated as passive. This " - "will break touch/wheel behavior on some websites but is useful for " - "demonstrating the potential performance benefits of adopting passive " - "event listeners."; + "Forces touchstart, touchmove, mousewheel and wheel event listeners (which " + "haven't requested otherwise) to be treated as passive. This will break " + "touch/wheel behavior on some websites but is useful for demonstrating the " + "potential performance benefits of adopting passive event listeners."; const char kImportantSitesInCbdName[] = "Important sites options in clear browsing data dialog"; @@ -767,10 +762,9 @@ "Latest stable JavaScript features"; const char kJavascriptHarmonyShippingDescription[] = - "Some web pages use legacy or non-standard JavaScript extensions that " - "may conflict with the latest JavaScript features. This flag allows " - "disabling support of those features for compatibility with such " - "pages."; + "Some web pages use legacy or non-standard JavaScript extensions that may " + "conflict with the latest JavaScript features. This flag allows disabling " + "support of those features for compatibility with such pages."; const char kJavascriptHarmonyName[] = "Experimental JavaScript"; @@ -805,8 +799,7 @@ "Download button when opening a page with media url."; const char kMediaDocumentDownloadButtonDescription[] = - "Allow a download button to show up when opening a page with media " - "url."; + "Allow a download button to show up when opening a page with media url."; #endif // defined(OS_ANDROID) @@ -848,9 +841,9 @@ const char kExperimentalSecurityFeaturesDescription[] = "Enables several security features that will likely break one or more " - "pages that you visit on a daily basis. Strict mixed content checking, " - "for example. And locking powerful features to secure contexts. This " - "flag will probably annoy you."; + "pages that you visit on a daily basis. Strict mixed content checking, for " + "example. And locking powerful features to secure contexts. This flag will " + "probably annoy you."; const char kExperimentalWebPlatformFeaturesName[] = "Experimental Web Platform features"; @@ -861,14 +854,13 @@ const char kOriginTrialsName[] = "Origin Trials"; const char kOriginTrialsDescription[] = - "Enables origin trials for controlling access to feature/API " - "experiments."; + "Enables origin trials for controlling access to feature/API experiments."; const char kBleAdvertisingInExtensionsName[] = "BLE Advertising in Chrome Apps"; const char kBleAdvertisingInExtensionsDescription[] = - "Enables BLE Advertising in Chrome Apps. BLE Advertising might " - "interfere with regular use of Bluetooth Low Energy features."; + "Enables BLE Advertising in Chrome Apps. BLE Advertising might interfere " + "with regular use of Bluetooth Low Energy features."; const char kDevtoolsExperimentsName[] = "Developer Tools experiments"; @@ -916,9 +908,9 @@ "Reduce default 'referer' header granularity."; const char kReducedReferrerGranularityDescription[] = - "If a page hasn't set an explicit referrer policy, setting this flag " - "will reduce the amount of information in the 'referer' header for " - "cross-origin requests."; + "If a page hasn't set an explicit referrer policy, setting this flag will " + "reduce the amount of information in the 'referer' header for cross-origin " + "requests."; #if defined(OS_CHROMEOS) @@ -975,34 +967,33 @@ const char kRequestTabletSiteDescription[] = "Allows the user to request tablet site. Web content is often optimized " - "for tablet devices. When this option is selected the user agent string " - "is changed to indicate a tablet device. Web content optimized for " - "tablets is received there after for the current tab."; + "for tablet devices. When this option is selected the user agent string is " + "changed to indicate a tablet device. Web content optimized for tablets is " + "received there after for the current tab."; const char kDebugPackedAppName[] = "Debugging for packed apps"; const char kDebugPackedAppDescription[] = - "Enables debugging context menu options such as Inspect Element for " - "packed applications."; + "Enables debugging context menu options such as Inspect Element for packed " + "applications."; const char kDropSyncCredentialName[] = "Drop sync credentials from password manager"; const char kDropSyncCredentialDescription[] = - "The password manager will not offer to save the credential used to " - "sync."; + "The password manager will not offer to save the credential used to sync."; const char kPasswordGenerationName[] = "Password generation"; const char kPasswordGenerationDescription[] = - "Allow the user to have Chrome generate passwords when it detects " - "account creation pages."; + "Allow the user to have Chrome generate passwords when it detects account " + "creation pages."; const char kPasswordForceSavingName[] = "Force-saving of passwords"; const char kPasswordForceSavingDescription[] = - "Allow the user to manually enforce password saving instead of relying " - "on password manager's heuristics."; + "Allow the user to manually enforce password saving instead of relying on " + "password manager's heuristics."; const char kManualPasswordGenerationName[] = "Manual password generation."; @@ -1054,9 +1045,9 @@ const char kPushApiBackgroundModeName[] = "Enable Push API background mode"; const char kPushApiBackgroundModeDescription[] = - "Enable background mode for the Push API. This allows Chrome to " - "continue running after the last window is closed, and to launch at OS " - "startup, if the Push API needs it."; + "Enable background mode for the Push API. This allows Chrome to continue " + "running after the last window is closed, and to launch at OS startup, if " + "the Push API needs it."; const char kEnableNavigationTracingName[] = "Enable navigation tracing"; @@ -1083,9 +1074,8 @@ const char kTraceUploadUrlDescription[] = "This is to be used in conjunction with the enable-navigation-tracing " "flag. Please select the label that best describes the recorded traces. " - "This will choose the destination the traces are uploaded to. If you " - "are not sure, select other. If left empty, no traces will be " - "uploaded."; + "This will choose the destination the traces are uploaded to. If you are " + "not sure, select other. If left empty, no traces will be uploaded."; const char kDisableAudioForDesktopShareName[] = "Disable Audio For Desktop Share"; @@ -1122,8 +1112,8 @@ const char kSyncAppListName[] = "App Launcher sync"; const char kSyncAppListDescription[] = - "Enable App Launcher sync. This also enables Folders where available " - "(non OSX)."; + "Enable App Launcher sync. This also enables Folders where available (non " + "OSX)."; const char kDriveSearchInChromeLauncherName[] = "Drive Search in Chrome App Launcher"; @@ -1144,8 +1134,7 @@ "V8 caching strategy for CacheStorage."; const char kV8CacheStrategiesForCacheStorageDescription[] = - "Caching strategy of scripts in CacheStorage for the V8 JavaScript " - "engine."; + "Caching strategy of scripts in CacheStorage for the V8 JavaScript engine."; const char kV8CacheStrategiesForCacheStorageNormal[] = "Normal"; @@ -1169,8 +1158,8 @@ const char kDataReductionProxyLoFiDescription[] = "Forces Data Saver Lo-Fi mode to be always enabled, enabled only on " - "cellular connections, or disabled. Data Saver must be enabled for " - "Lo-Fi mode to be used."; + "cellular connections, or disabled. Data Saver must be enabled for Lo-Fi " + "mode to be used."; const char kDataReductionProxyLoFiAlwaysOn[] = "Always on"; @@ -1209,9 +1198,9 @@ "Data Saver 1 MB Savings Promo"; const char kEnableDataReductionProxySavingsPromoDescription[] = - "Enable a Data Saver promo for 1 MB of savings. If Data Saver has " - "already saved 1 MB of data, then the promo will not be shown. Data " - "Saver must be enabled for the promo to be shown."; + "Enable a Data Saver promo for 1 MB of savings. If Data Saver has already " + "saved 1 MB of data, then the promo will not be shown. Data Saver must be " + "enabled for the promo to be shown."; #if defined(OS_ANDROID) @@ -1242,8 +1231,8 @@ const char kLcdTextName[] = "LCD text antialiasing"; const char kLcdTextDescription[] = - "If disabled, text is rendered with grayscale antialiasing instead of " - "LCD (subpixel) when doing accelerated compositing."; + "If disabled, text is rendered with grayscale antialiasing instead of LCD " + "(subpixel) when doing accelerated compositing."; const char kDistanceFieldTextName[] = "Distance field text"; @@ -1297,9 +1286,9 @@ "Reset the App Launcher install state on every restart."; const char kResetAppListInstallStateDescription[] = - "Reset the App Launcher install state on every restart. While this flag " - "is set, Chrome will forget the launcher has been installed each time " - "it starts. This is used for testing the App Launcher install flow."; + "Reset the App Launcher install state on every restart. While this flag is " + "set, Chrome will forget the launcher has been installed each time it " + "starts. This is used for testing the App Launcher install flow."; #if defined(OS_CHROMEOS) @@ -1329,8 +1318,7 @@ "Allow tab detaching in fullscreen"; const char kTabDetachingInFullscreenDescription[] = - "Allow tabs to detach from the tabstrip when in fullscreen mode on " - "Mac."; + "Allow tabs to detach from the tabstrip when in fullscreen mode on Mac."; const char kFullscreenToolbarRevealName[] = "Enables the toolbar in fullscreen to reveal itself."; @@ -1356,8 +1344,8 @@ "Quit notification for hosted apps"; const char kHostedAppQuitNotificationDescription[] = - "Display a notification when quitting Chrome if hosted apps are " - "currently running."; + "Display a notification when quitting Chrome if hosted apps are currently " + "running."; #if defined(OS_ANDROID) @@ -1396,8 +1384,8 @@ const char kPermissionActionReportingName[] = "Permission Action Reporting"; const char kPermissionActionReportingDescription[] = - "Enables permission action reporting to Safe Browsing servers for opted " - "in users."; + "Enables permission action reporting to Safe Browsing servers for opted in " + "users."; const char kPermissionsBlacklistName[] = "Permissions Blacklist"; @@ -1409,28 +1397,28 @@ const char kThreadedScrollingDescription[] = "Threaded handling of scroll-related input events. Disabling this will " - "force all such scroll events to be handled on the main thread. Note " - "that this can dramatically hurt scrolling performance of most websites " - "and is intended for testing purposes only."; + "force all such scroll events to be handled on the main thread. Note that " + "this can dramatically hurt scrolling performance of most websites and is " + "intended for testing purposes only."; const char kHarfbuzzRendertextName[] = "HarfBuzz for UI text"; const char kHarfbuzzRendertextDescription[] = - "Enable cross-platform HarfBuzz layout engine for UI text. Doesn't " - "affect web content."; + "Enable cross-platform HarfBuzz layout engine for UI text. Doesn't affect " + "web content."; const char kEmbeddedExtensionOptionsName[] = "Embedded extension options"; const char kEmbeddedExtensionOptionsDescription[] = - "Display extension options as an embedded element in " - "chrome://extensions rather than opening a new tab."; + "Display extension options as an embedded element in chrome://extensions " + "rather than opening a new tab."; const char kTabAudioMutingName[] = "Tab audio muting UI control"; const char kTabAudioMutingDescription[] = - "When enabled, the audio indicators in the tab strip double as tab " - "audio mute controls. This also adds commands in the tab context menu " - "for quickly muting multiple selected tabs."; + "When enabled, the audio indicators in the tab strip double as tab audio " + "mute controls. This also adds commands in the tab context menu for " + "quickly muting multiple selected tabs."; const char kEasyUnlockBluetoothLowEnergyDiscoveryName[] = "Smart Lock Bluetooth Low Energy Discovery"; @@ -1444,17 +1432,17 @@ "Smart Lock proximity detection"; const char kEasyUnlockProximityDetectionDescription[] = - "Enables a Smart Lock setting that restricts unlocking to only work " - "when your phone is very close to (roughly, within an arm's length of) " - "the Chrome device."; + "Enables a Smart Lock setting that restricts unlocking to only work when " + "your phone is very close to (roughly, within an arm's length of) the " + "Chrome device."; const char kWifiCredentialSyncName[] = "WiFi credential sync"; const char kWifiCredentialSyncDescription[] = - "Enables synchronizing WiFi network settings across devices. When " - "enabled, the WiFi credential datatype is registered with Chrome Sync, " - "and WiFi credentials are synchronized subject to user preferences. " - "(See also, chrome://settings/syncSetup.)"; + "Enables synchronizing WiFi network settings across devices. When enabled, " + "the WiFi credential datatype is registered with Chrome Sync, and WiFi " + "credentials are synchronized subject to user preferences. (See also, " + "chrome://settings/syncSetup.)"; const char kSyncSandboxName[] = "Use Chrome Sync sandbox"; @@ -1465,8 +1453,8 @@ const char kDatasaverPromptDescription[] = "Enables a prompt, which appears when a cellular network connection is " - "detected, to take the user to the Data Saver extension page on Chrome " - "Web Store."; + "detected, to take the user to the Data Saver extension page on Chrome Web " + "Store."; const char kDatasaverPromptDemoMode[] = "Demo mode"; @@ -1476,9 +1464,9 @@ const char kTrySupportedChannelLayoutsDescription[] = "Causes audio output streams to check if channel layouts other than the " - "default hardware layout are available. Turning this on will allow the " - "OS to do stereo to surround expansion if supported. May expose third " - "party driver bugs, use with caution."; + "default hardware layout are available. Turning this on will allow the OS " + "to do stereo to surround expansion if supported. May expose third party " + "driver bugs, use with caution."; #if defined(OS_MACOSX) @@ -1511,8 +1499,8 @@ const char kAppWindowCyclingDescription[] = "Changes the behavior of Cmd+` when a Chrome App becomes active. When " "enabled, Chrome Apps will not be cycled when Cmd+` is pressed from a " - "browser window, and browser windows will not be cycled when a Chrome " - "App is active."; + "browser window, and browser windows will not be cycled when a Chrome App " + "is active."; #endif // defined(OS_MACOSX) @@ -1531,8 +1519,8 @@ "Simplified full screen / mouse lock UI."; const char kSimplifiedFullscreenUiDescription[] = - "A simplified new user experience when entering page-triggered full " - "screen or mouse pointer lock states."; + "A simplified new user experience when entering page-triggered full screen " + "or mouse pointer lock states."; const char kExperimentalKeyboardLockUiName[] = "Experimental keyboard lock UI."; @@ -1580,8 +1568,8 @@ "Main frame's domContentLoaded (iframes ignored)."; const char kProgressBarCompletionResourcesBeforeDclAndSameOriginIframes[] = - "domContentLoaded and all resources loads started before " - "domContentLoaded (main frame and same origin iframes)."; + "domContentLoaded and all resources loads started before domContentLoaded " + "(main frame and same origin iframes)."; #endif // defined(OS_ANDROID) @@ -1589,8 +1577,8 @@ "Block scripts loaded via document.write"; const char kDisallowDocWrittenScriptsUiDescription[] = - "Disallows fetches for third-party parser-blocking scripts inserted " - "into the main frame via document.write."; + "Disallows fetches for third-party parser-blocking scripts inserted into " + "the main frame via document.write."; #if defined(OS_WIN) @@ -1618,8 +1606,8 @@ "Enable offering upload of Autofilled credit cards"; const char kAutofillCreditCardUploadDescription[] = - "Enables a new option to upload credit cards to Google Payments for " - "sync to all Chrome devices."; + "Enables a new option to upload credit cards to Google Payments for sync " + "to all Chrome devices."; #endif // defined(TOOLKIT_VIEWS) || defined(OS_ANDROID) @@ -1633,8 +1621,8 @@ const char kForceTextDirectionDescription[] = "Explicitly force the per-character directionality of UI text to " - "left-to-right (LTR) or right-to-left (RTL) mode, overriding the " - "default direction of the character language."; + "left-to-right (LTR) or right-to-left (RTL) mode, overriding the default " + "direction of the character language."; const char kForceDirectionLtr[] = "Left-to-right"; @@ -1652,8 +1640,7 @@ const char kEnableGroupedHistoryName[] = "Group history by domain"; const char kEnableGroupedHistoryDescription[] = - "Group history by website domain (i.e. google.com) on " - "chrome://history."; + "Group history by website domain (i.e. google.com) on chrome://history."; const char kSaveasMenuLabelExperimentName[] = "Switch 'Save as' menu labels to 'Download'"; @@ -1677,9 +1664,9 @@ "New omnibox answers in suggest types"; const char kNewOmniboxAnswerTypesDescription[] = - "Enables new types of answers in the omnibox suggest drop-down: " - "currency conversions, dictionary definitions, sports scores, " - "translations, and when is."; + "Enables new types of answers in the omnibox suggest drop-down: currency " + "conversions, dictionary definitions, sports scores, translations, and " + "when is."; const char kEnableZeroSuggestRedirectToChromeName[] = "Experimental contextual omnibox suggestion"; @@ -1687,14 +1674,14 @@ const char kEnableZeroSuggestRedirectToChromeDescription[] = "Change omnibox contextual suggestions to an experimental source. Note " "that this is not an on/off switch for contextual omnibox and it only " - "applies to suggestions provided before the user starts typing a URL or " - "a search query (i.e. zero suggest)."; + "applies to suggestions provided before the user starts typing a URL or a " + "search query (i.e. zero suggest)."; const char kFillOnAccountSelectName[] = "Fill passwords on account selection"; const char kFillOnAccountSelectDescription[] = - "Filling of passwords when an account is explicitly selected by the " - "user rather than autofilling credentials on page load."; + "Filling of passwords when an account is explicitly selected by the user " + "rather than autofilling credentials on page load."; const char kEnableClearBrowsingDataCountersName[] = "Enable Clear browsing data counters."; @@ -1707,16 +1694,15 @@ const char kTabsInCbdName[] = "Enable tabs for the Clear Browsing Data dialog."; const char kTabsInCbdDescription[] = - "Enables a basic and an advanced tab for the Clear Browsing Data " - "dialog."; + "Enables a basic and an advanced tab for the Clear Browsing Data dialog."; #endif // defined(OS_ANDROID) const char kNotificationsNativeFlagName[] = "Enable native notifications."; const char kNotificationsNativeFlagDescription[] = - "Enable support for using the native notification toasts and " - "notification center on platforms where these are available."; + "Enable support for using the native notification toasts and notification " + "center on platforms where these are available."; #if defined(OS_ANDROID) @@ -1731,21 +1717,21 @@ "Enable custom layouts for Web Notifications."; const char kEnableWebNotificationCustomLayoutsDescription[] = - "Enable custom layouts for Web Notifications. They will have subtle " - "layout improvements that are otherwise not possible."; + "Enable custom layouts for Web Notifications. They will have subtle layout " + "improvements that are otherwise not possible."; const char kGoogleProfileInfoName[] = "Google profile name and icon"; const char kGoogleProfileInfoDescription[] = - "Enables using Google information to populate the profile name and icon " - "in the avatar menu."; + "Enables using Google information to populate the profile name and icon in " + "the avatar menu."; const char kOfferStoreUnmaskedWalletCardsName[] = "Google Payments card saving checkbox"; const char kOfferStoreUnmaskedWalletCardsDescription[] = - "Show the checkbox to offer local saving of a credit card downloaded " - "from the server."; + "Show the checkbox to offer local saving of a credit card downloaded from " + "the server."; const char kOfflineAutoReloadName[] = "Offline Auto-Reload Mode"; @@ -1764,10 +1750,10 @@ const char kShowSavedCopyDescription[] = "When a page fails to load, if a stale copy of the page exists in the " - "browser cache, a button will be presented to allow the user to load " - "that stale copy. The primary enabling choice puts the button in the " - "most salient position on the error page; the secondary enabling choice " - "puts it secondary to the reload button."; + "browser cache, a button will be presented to allow the user to load that " + "stale copy. The primary enabling choice puts the button in the most " + "salient position on the error page; the secondary enabling choice puts it " + "secondary to the reload button."; const char kEnableShowSavedCopyPrimary[] = "Enable: Primary"; @@ -1800,8 +1786,8 @@ const char kPhysicalKeyboardAutocorrectName[] = "Physical keyboard autocorrect"; const char kPhysicalKeyboardAutocorrectDescription[] = - "Enable physical keyboard autocorrect for US keyboard, which can " - "provide suggestions as typing on physical keyboard."; + "Enable physical keyboard autocorrect for US keyboard, which can provide " + "suggestions as typing on physical keyboard."; const char kVoiceInputName[] = "Voice input on virtual keyboard"; @@ -1822,8 +1808,8 @@ const char kGestureTypingName[] = "Gesture typing for the virtual keyboard."; const char kGestureTypingDescription[] = - "Enable/Disable gesture typing option in the settings page for the " - "virtual keyboard."; + "Enable/Disable gesture typing option in the settings page for the virtual " + "keyboard."; const char kGestureEditingName[] = "Gesture editing for the virtual keyboard."; @@ -1837,12 +1823,10 @@ const char kCaptivePortalBypassProxyDescription[] = "If proxy is configured, it usually prevents from authorization on " "different captive portals. This enables opening captive portal " - "authorization dialog in a separate window, which ignores proxy " - "settings."; + "authorization dialog in a separate window, which ignores proxy settings."; const char kTouchscreenCalibrationName[] = - "Enable/disable touchscreen calibration option in material design " - "settings"; + "Enable/disable touchscreen calibration option in material design settings"; const char kTouchscreenCalibrationDescription[] = "If enabled, the user can calibrate the touch screen displays in " @@ -1868,8 +1852,8 @@ const char kSimpleCacheBackendName[] = "Simple Cache for HTTP"; const char kSimpleCacheBackendDescription[] = - "The Simple Cache for HTTP is a new cache. It relies on the filesystem " - "for disk space allocation."; + "The Simple Cache for HTTP is a new cache. It relies on the filesystem for " + "disk space allocation."; // Spelling feedback field trial. @@ -1898,9 +1882,9 @@ const char kTopDocumentIsolationName[] = "Top document isolation"; const char kTopDocumentIsolationDescription[] = - "Highly experimental performance mode where cross-site iframes are kept " - "in a separate process from the top document. In this mode, iframes " - "from different third-party sites will be allowed to share a process."; + "Highly experimental performance mode where cross-site iframes are kept in " + "a separate process from the top document. In this mode, iframes from " + "different third-party sites will be allowed to share a process."; // Cross process guest frames isolation mode @@ -1908,8 +1892,8 @@ "Cross process frames for guests"; const char kCrossProcessGuestViewIsolationDescription[] = - "Highly experimental where guests such as <webview> are implemented " - "on the out-of-process iframe infrastructure."; + "Highly experimental where guests such as <webview> are implemented on " + "the out-of-process iframe infrastructure."; // Task Scheduler @@ -1996,8 +1980,7 @@ const char kSettingsWindowName[] = "Show settings in a window"; const char kSettingsWindowDescription[] = - "Settings will be shown in a dedicated window instead of as a browser " - "tab."; + "Settings will be shown in a dedicated window instead of as a browser tab."; // Extension Content Verification @@ -2007,9 +1990,9 @@ const char kExtensionContentVerificationDescription[] = "This flag can be used to turn on verification that the contents of the " "files on disk for extensions from the webstore match what they're " - "expected to be. This can be used to turn on this feature if it would " - "not otherwise have been turned on, but cannot be used to turn it off " - "(because this setting can be tampered with by malware)."; + "expected to be. This can be used to turn on this feature if it would not " + "otherwise have been turned on, but cannot be used to turn it off (because " + "this setting can be tampered with by malware)."; const char kExtensionContentVerificationBootstrap[] = "Bootstrap (get expected hashes, but do not enforce them)"; @@ -2026,8 +2009,8 @@ "Simulated hardware 'Ok Google' features"; const char kExperimentalHotwordHardwareDescription[] = - "Enables an experimental version of 'Ok Google' hotword detection " - "features that have a hardware dependency."; + "Enables an experimental version of 'Ok Google' hotword detection features " + "that have a hardware dependency."; // Message center strings @@ -2048,15 +2031,15 @@ "Cast Streaming hardware video encoding"; const char kCastStreamingHwEncodingDescription[] = - "This option enables support in Cast Streaming for encoding video " - "streams using platform hardware."; + "This option enables support in Cast Streaming for encoding video streams " + "using platform hardware."; const char kAllowInsecureLocalhostName[] = "Allow invalid certificates for resources loaded from localhost."; const char kAllowInsecureLocalhostDescription[] = - "Allows requests to localhost over HTTPS even when an invalid " - "certificate is presented."; + "Allows requests to localhost over HTTPS even when an invalid certificate " + "is presented."; #if defined(OS_WIN) || defined(OS_MACOSX) @@ -2065,10 +2048,10 @@ const char kAutomaticTabDiscardingName[] = "Automatic tab discarding"; const char kAutomaticTabDiscardingDescription[] = - "If enabled, tabs get automatically discarded from memory when the " - "system memory is low. Discarded tabs are still visible on the tab " - "strip and get reloaded when clicked on. Info about discarded tabs can " - "be found at chrome://discards."; + "If enabled, tabs get automatically discarded from memory when the system " + "memory is low. Discarded tabs are still visible on the tab strip and get " + "reloaded when clicked on. Info about discarded tabs can be found at " + "chrome://discards."; #endif // defined(OS_WIN) || defined(OS_MACOSX) @@ -2131,8 +2114,8 @@ "Use background loader instead of prerenderer to load pages."; const char kNewBackgroundLoaderDescription[] = - "Use background loader instead of prerenderer to asynchronously " - "download pages."; + "Use background loader instead of prerenderer to asynchronously download " + "pages."; const char kNtpPopularSitesName[] = "Show popular sites on the New Tab page"; @@ -2160,10 +2143,10 @@ const char kWebPaymentsModifiersName[] = "Enable web payment modifiers"; const char kWebPaymentsModifiersDescription[] = - "If the website provides modifiers in the payment request, show the " - "custom total for each payment instrument, update the shopping cart " - "when instruments are switched, and send modified payment method " - "specific data to the payment app."; + "If the website provides modifiers in the payment request, show the custom " + "total for each payment instrument, update the shopping cart when " + "instruments are switched, and send modified payment method specific data " + "to the payment app."; const char kXGEOVisibleNetworksName[] = "Enable XGEO Visible Networks"; @@ -2187,8 +2170,8 @@ "Xperf."; const char kMergeKeyCharEventsName[] = - "Enable or disable merging merging the key event (WM_KEY*) with char " - "event (WM_CHAR)."; + "Enable or disable merging merging the key event (WM_KEY*) with char event " + "(WM_CHAR)."; const char kMergeKeyCharEventsDescription[] = "If disabled, Chrome will handle WM_KEY* and WM_CHAR separately."; @@ -2196,8 +2179,8 @@ const char kUseWinrtMidiApiName[] = "Use Windows Runtime MIDI API"; const char kUseWinrtMidiApiDescription[] = - "Use Windows Runtime MIDI API for WebMIDI (effective only on Windows 10 " - "or later)."; + "Use Windows Runtime MIDI API for WebMIDI (effective only on Windows 10 or " + "later)."; #endif // defined(OS_WIN) @@ -2295,8 +2278,8 @@ const char kEnableScrollAnchoringName[] = "Scroll Anchoring"; const char kEnableScrollAnchoringDescription[] = - "Adjusts scroll position to prevent visible jumps when offscreen " - "content changes."; + "Adjusts scroll position to prevent visible jumps when offscreen content " + "changes."; #if defined(OS_CHROMEOS) @@ -2308,8 +2291,8 @@ const char kEnableAndroidWallpapersAppName[] = "Android Wallpapers App"; const char kEnableAndroidWallpapersAppDescription[] = - "Enables the Android Wallpapers App as the default Wallpaper App on " - "Chrome OS."; + "Enables the Android Wallpapers App as the default Wallpaper App on Chrome " + "OS."; const char kEnableTouchSupportForScreenMagnifierName[] = "Touch support for screen magnifier"; @@ -2348,15 +2331,15 @@ "Content suggestions category ranker (e.g. on NTP)"; const char kContentSuggestionsCategoryRankerDescription[] = - "Set category ranker to order categories of content suggestions (e.g. " - "on the NTP)."; + "Set category ranker to order categories of content suggestions (e.g. on " + "the NTP)."; const char kEnableNtpSnippetsVisibilityName[] = "Make New Tab Page Snippets more visible."; const char kEnableNtpSnippetsVisibilityDescription[] = - "If enabled, the NTP snippets will become more discoverable with a " - "larger portion of the first card above the fold."; + "If enabled, the NTP snippets will become more discoverable with a larger " + "portion of the first card above the fold."; const char kEnableContentSuggestionsNewFaviconServerName[] = "Get favicons for content suggestions from a new server."; @@ -2378,13 +2361,6 @@ "If enabled, missing favicons for NTP tiles get downloaded from Google. " "This only applies to tiles that originate from synced history."; -const char kEnableContentSuggestionsCategoriesName[] = - "Organize content suggestions by categories."; - -const char kEnableContentSuggestionsCategoriesDescription[] = - "If enabled, the content suggestions will be grouped by categories or " - "topics. Only remote content suggestions are shown when this is enabled."; - const char kEnableContentSuggestionsLargeThumbnailName[] = "Large thumbnails layout for content suggestions cards."; @@ -2416,63 +2392,62 @@ "Show server-side suggestions on the New Tab page"; const char kEnableNtpRemoteSuggestionsDescription[] = - "If enabled, the list of content suggestions on the New Tab page (see " - "#enable-ntp-snippets) will contain server-side suggestions (e.g., " - "Articles for you). Furthermore, it allows to override the source used " - "to retrieve these server-side suggestions."; + "If enabled, the list of content suggestions on the New Tab page will " + "contain server-side suggestions (e.g., Articles for you). Furthermore, it " + "allows to override the source used to retrieve these server-side " + "suggestions."; const char kEnableNtpRecentOfflineTabSuggestionsName[] = "Show recent offline tabs on the New Tab page"; const char kEnableNtpRecentOfflineTabSuggestionsDescription[] = - "If enabled, the list of content suggestions on the New Tab page (see " - "#enable-ntp-snippets) will contain pages that were captured offline " - "during browsing (see #offlining-recent-pages)"; + "If enabled, the list of content suggestions on the New Tab page will " + "contain pages that were captured offline during browsing (see " + "#offlining-recent-pages)"; const char kEnableNtpAssetDownloadSuggestionsName[] = "Show asset downloads on the New Tab page"; const char kEnableNtpAssetDownloadSuggestionsDescription[] = - "If enabled, the list of content suggestions on the New Tab page (see " - "#enable-ntp-snippets) will contain assets (e.g. books, pictures, " - "audio) that the user downloaded for later use."; + "If enabled, the list of content suggestions on the New Tab page will " + "contain assets (e.g. books, pictures, audio) that the user downloaded for " + "later use."; const char kEnableNtpOfflinePageDownloadSuggestionsName[] = "Show offline page downloads on the New Tab page"; const char kEnableNtpOfflinePageDownloadSuggestionsDescription[] = - "If enabled, the list of content suggestions on the New Tab page (see " - "#enable-ntp-snippets) will contain pages that the user downloaded for " - "later use."; + "If enabled, the list of content suggestions on the New Tab page will " + "contain pages that the user downloaded for later use."; const char kEnableNtpBookmarkSuggestionsName[] = "Show recently visited bookmarks on the New Tab page"; const char kEnableNtpBookmarkSuggestionsDescription[] = - "If enabled, the list of content suggestions on the New Tab page (see " - "#enable-ntp-snippets) will contain recently visited bookmarks."; + "If enabled, the list of content suggestions on the New Tab page will " + "contain recently visited bookmarks."; const char kEnableNtpPhysicalWebPageSuggestionsName[] = "Show Physical Web pages on the New Tab page"; const char kEnableNtpPhysicalWebPageSuggestionsDescription[] = - "If enabled, the list of content suggestions on the New Tab page (see " - "#enable-ntp-snippets) will contain pages that are available through " - "Physical Web (see #enable-physical-web)"; + "If enabled, the list of content suggestions on the New Tab page will " + "contain pages that are available through Physical Web (see " + "#enable-physical-web)"; const char kEnableNtpForeignSessionsSuggestionsName[] = "Show recent foreign tabs on the New Tab page"; const char kEnableNtpForeignSessionsSuggestionsDescription[] = - "If enabled, the list of content suggestions on the New Tab page (see " - "#enable-ntp-snippets) will contain recent foreign tabs."; + "If enabled, the list of content suggestions on the New Tab page will " + "contain recent foreign tabs."; const char kEnableNtpSuggestionsNotificationsName[] = "Notify about new content suggestions available at the New Tab page"; const char kEnableNtpSuggestionsNotificationsDescription[] = "If enabled, notifications will inform about new content suggestions on " - "the New Tab page (see #enable-ntp-snippets)."; + "the New Tab page."; const char kNtpCondensedLayoutName[] = "Condensed NTP layout"; @@ -2497,8 +2472,8 @@ "Enable offlining of recently visited pages"; const char kOffliningRecentPagesDescription[] = - "Enable storing recently visited pages locally for offline use. " - "Requires Offline Pages to be enabled."; + "Enable storing recently visited pages locally for offline use. Requires " + "Offline Pages to be enabled."; const char kOfflinePagesCtName[] = "Enable Offline Pages CT features."; @@ -2518,8 +2493,7 @@ "Use expanded autofill credit card popup layout."; const char kEnableExpandedAutofillCreditCardPopupLayoutDescription[] = - "If enabled, displays autofill credit card popup using expanded " - "layout."; + "If enabled, displays autofill credit card popup using expanded layout."; #endif // defined(OS_ANDROID) @@ -2571,23 +2545,22 @@ const char kFontCacheScalingName[] = "FontCache scaling"; const char kFontCacheScalingDescription[] = - "Reuse a cached font in the renderer to serve different sizes of font " - "for faster layout."; + "Reuse a cached font in the renderer to serve different sizes of font for " + "faster layout."; const char kFramebustingName[] = "Framebusting requires same-origin or a user gesture"; const char kFramebustingDescription[] = - "Don't permit an iframe to navigate the top level browsing context " - "unless they are same-origin or the iframe is processing a user " - "gesture."; + "Don't permit an iframe to navigate the top level browsing context unless " + "they are same-origin or the iframe is processing a user gesture."; const char kVibrateRequiresUserGestureName[] = "Requiring user gesture for the Vibration API"; const char kVibrateRequiresUserGestureDescription[] = - "Block the Vibration API if no user gesture has been received on " - "the frame or any embedded frame."; + "Block the Vibration API if no user gesture has been received on the frame " + "or any embedded frame."; #if defined(OS_ANDROID) #if BUILDFLAG(ENABLE_VR) @@ -2621,21 +2594,19 @@ const char kEnableAndroidPayIntegrationV1Name[] = "Enable Android Pay v1"; const char kEnableAndroidPayIntegrationV1Description[] = - "Enable integration with Android Pay using the first version of the " - "API"; + "Enable integration with Android Pay using the first version of the API"; const char kEnableAndroidPayIntegrationV2Name[] = "Enable Android Pay v2"; const char kEnableAndroidPayIntegrationV2Description[] = - "Enable integration with Android Pay using the second version of the " - "API"; + "Enable integration with Android Pay using the second version of the API"; const char kEnableWebPaymentsSingleAppUiSkipName[] = "Enable Web Payments single app UI skip"; const char kEnableWebPaymentsSingleAppUiSkipDescription[] = - "Enable Web Payments to skip showing its UI if the developer specifies " - "a single app."; + "Enable Web Payments to skip showing its UI if the developer specifies a " + "single app."; const char kAndroidPaymentAppsName[] = "Android payment apps"; @@ -2687,8 +2658,8 @@ "Lock screen orientation when playing a video fullscreen."; const char kVideoFullscreenOrientationLockDescription[] = - "Lock the screen orientation of the device to match video orientation " - "when a video goes fullscreen. Only on phones."; + "Lock the screen orientation of the device to match video orientation when " + "a video goes fullscreen. Only on phones."; // Video rotate-to-fullscreen experiment strings. @@ -2771,8 +2742,8 @@ "Have consistent omnibox geolocation access."; const char kEnableConsistentOmniboxGeolocationDescription[] = - "Have consistent geolocation access between the omnibox and default " - "search engine."; + "Have consistent geolocation access between the omnibox and default search " + "engine."; #endif // defined(OS_ANDROID) @@ -2782,8 +2753,8 @@ const char kMediaRemotingDescription[] = "When Casting a tab to a remote device, enabling this turns on an " - "optimization that forwards the content bitstream directly to the " - "remote device when a video is fullscreened."; + "optimization that forwards the content bitstream directly to the remote " + "device when a video is fullscreened."; // Play Services LSD permission prompt chrome://flags strings @@ -2805,8 +2776,8 @@ const char kWindows10CustomTitlebarName[] = "Custom-drawn Windows 10 Titlebar"; const char kWindows10CustomTitlebarDescription[] = - "If enabled, Chrome will draw the titlebar and caption buttons instead " - "of deferring to Windows."; + "If enabled, Chrome will draw the titlebar and caption buttons instead of " + "deferring to Windows."; #endif // defined(OS_WIN) @@ -2825,8 +2796,8 @@ const char kAiaFetchingName[] = "Intermediate Certificate Fetching"; const char kAiaFetchingDescription[] = - "Enable intermediate certificate fetching when a server does not " - "provide sufficient certificates to build a chain to a trusted root."; + "Enable intermediate certificate fetching when a server does not provide " + "sufficient certificates to build a chain to a trusted root."; #endif // defined(OS_ANDROID) @@ -2845,8 +2816,8 @@ const char kEnableDesktopIosPromotionsName[] = "Desktop to iOS promotions."; const char kEnableDesktopIosPromotionsDescription[] = - "Enable Desktop to iOS promotions, and allow users to see them if they " - "are eligible."; + "Enable Desktop to iOS promotions, and allow users to see them if they are " + "eligible."; #endif // defined(OS_WIN) @@ -2870,8 +2841,8 @@ const char kOmniboxTailSuggestionsName[] = "Omnibox tail suggestions"; const char kOmniboxTailSuggestionsDescription[] = - "Enable receiving tail suggestions, a type of search suggestion " - "based on the last few words in the query, for the Omnibox."; + "Enable receiving tail suggestions, a type of search suggestion based on " + "the last few words in the query, for the Omnibox."; const char kPauseBackgroundTabsName[] = "Pause background tabs"; const char kPauseBackgroundTabsDescription[] = @@ -2913,8 +2884,7 @@ #endif // defined(OS_ANDROID) const char kDebugShortcutsDescription[] = - "Enables additional keyboard shortcuts that are useful for debugging " - "Ash."; + "Enables additional keyboard shortcuts that are useful for debugging Ash."; const char kMemoryAblationName[] = "Memory ablation experiment"; const char kMemoryAblationDescription[] = @@ -2938,8 +2908,8 @@ "Experimental Chromecast support for Video Player"; const char kVideoPlayerChromecastSupportDescription[] = - "This option enables experimental Chromecast support for Video Player " - "app on ChromeOS."; + "This option enables experimental Chromecast support for Video Player app " + "on ChromeOS."; const char kNewZipUnpackerName[] = "New ZIP unpacker"; @@ -2961,8 +2931,8 @@ const char kEnableFullscreenAppListName[] = "Enable The Peeking Launcher"; const char kEnableFullscreenAppListDescription[] = - "The peeking launcher UI supports touch and provides more space for upcoming " - "features."; + "The peeking launcher UI supports touch and provides more space for " + "upcoming features."; const char kMemoryPressureThresholdName[] = "Memory discard strategy for advanced pressure handling"; @@ -2985,8 +2955,7 @@ const char kWakeOnPacketsName[] = "Wake On Packets"; const char kWakeOnPacketsDescription[] = - "Enables waking the device based on the receipt of some network " - "packets."; + "Enables waking the device based on the receipt of some network packets."; const char kQuickUnlockPinName[] = "Quick Unlock (PIN)"; @@ -3004,8 +2973,8 @@ const char kQuickUnlockFingerprintDescription[] = "Enabling fingerprint quick unlock allows you to setup and use a " - "fingerprint to unlock your Chromebook on the lock screen after you " - "have signed into your device."; + "fingerprint to unlock your Chromebook on the lock screen after you have " + "signed into your device."; const char kExperimentalAccessibilityFeaturesName[] = "Experimental accessibility features"; @@ -3051,8 +3020,8 @@ const char kMtpWriteSupportName[] = "MTP write support"; const char kMtpWriteSupportDescription[] = - "MTP write support in File System API (and file manager). In-place " - "editing operations are not supported."; + "MTP write support in File System API (and file manager). In-place editing " + "operations are not supported."; const char kCrosRegionsModeName[] = "Cros-regions load mode"; @@ -3070,8 +3039,8 @@ const char kPrinterProviderSearchAppDescription[] = "Enables Chrome Web Store Gallery app for printer drivers. The app " - "searches Chrome Web Store for extensions that support printing to a " - "USB printer with specific USB ID."; + "searches Chrome Web Store for extensions that support printing to a USB " + "printer with specific USB ID."; const char kArcBootCompleted[] = "Load Android apps automatically"; @@ -3087,8 +3056,7 @@ "Emoji, handwriting and voice input on opt-in IME menu"; const char kEnableEhvInputDescription[] = - "Enable access to emoji, handwriting and voice input form opt-in IME " - "menu."; + "Enable access to emoji, handwriting and voice input form opt-in IME menu."; const char kEnableEncryptionMigrationName[] = "Enable encryption migration of user data"; @@ -3282,8 +3250,7 @@ "Identity consistency between browser and cookie jar"; const char kAccountConsistencyDescription[] = - "When enabled, the browser manages signing in and out of Google " - "accounts."; + "When enabled, the browser manages signing in and out of Google accounts."; const char kAccountConsistencyChoiceMirror[] = "Mirror"; const char kAccountConsistencyChoiceDice[] = "Dice"; @@ -3314,8 +3281,8 @@ const char kDisableNewVirtualKeyboardBehaviorName[] = "New window behavior for the accessibility keyboard"; const char kDisableNewVirtualKeyboardBehaviorDescription[] = - "Disable new window behavior for the accessibility keyboard " - "in non-sticky mode (do not change work area in non-sticky mode)."; + "Disable new window behavior for the accessibility keyboard in non-sticky " + "mode (do not change work area in non-sticky mode)."; const char kUiDevToolsName[] = "Enable native UI inspection"; const char kUiDevToolsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index afbb68a..916041f 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -907,9 +907,6 @@ extern const char kEnableContentSuggestionsNewFaviconServerName[]; extern const char kEnableContentSuggestionsNewFaviconServerDescription[]; -extern const char kEnableContentSuggestionsCategoriesName[]; -extern const char kEnableContentSuggestionsCategoriesDescription[]; - extern const char kEnableContentSuggestionsLargeThumbnailName[]; extern const char kEnableContentSuggestionsLargeThumbnailDescription[];
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc index e69d467..4a91125 100644 --- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc +++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -157,20 +157,10 @@ #endif } -bool AreLocalCategoriesEnabled() { -#if defined(OS_ANDROID) - return !base::FeatureList::IsEnabled( - chrome::android::kContentSuggestionsCategories); -#else - return false; -#endif -} - #if BUILDFLAG(ENABLE_OFFLINE_PAGES) bool IsRecentTabProviderEnabled() { - return AreLocalCategoriesEnabled() && - base::FeatureList::IsEnabled( + return base::FeatureList::IsEnabled( ntp_snippets::kRecentOfflineTabSuggestionsFeature) && base::FeatureList::IsEnabled( offline_pages::kOffliningRecentPagesFeature); @@ -220,8 +210,7 @@ } bool IsDownloadsProviderEnabled() { - return AreLocalCategoriesEnabled() && - (AreAssetDownloadsEnabled() || AreOfflinePageDownloadsEnabled()); + return AreAssetDownloadsEnabled() || AreOfflinePageDownloadsEnabled(); } void RegisterDownloadsProviderIfEnabled(ContentSuggestionsService* service, @@ -273,8 +262,7 @@ #if defined(OS_ANDROID) bool IsPhysicalWebPageProviderEnabled() { - return AreLocalCategoriesEnabled() && - base::FeatureList::IsEnabled( + return base::FeatureList::IsEnabled( ntp_snippets::kPhysicalWebPageSuggestionsFeature) && base::FeatureList::IsEnabled(chrome::android::kPhysicalWebFeature); } @@ -368,9 +356,8 @@ } bool IsForeignSessionsProviderEnabled() { - return AreLocalCategoriesEnabled() && - base::FeatureList::IsEnabled( - ntp_snippets::kForeignSessionsSuggestionsFeature); + return base::FeatureList::IsEnabled( + ntp_snippets::kForeignSessionsSuggestionsFeature); } void RegisterForeignSessionsProviderIfEnabled(
diff --git a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc index 07caa63..3802f70f 100644 --- a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc
@@ -49,6 +49,8 @@ const char kHistogramServiceWorkerLoad[] = "PageLoad.Clients.ServiceWorker.DocumentTiming.NavigationToLoadEventFired"; +const char kHistogramServiceWorkerParseStartInbox[] = + "PageLoad.Clients.ServiceWorker.ParseTiming.NavigationToParseStart.inbox"; const char kHistogramServiceWorkerFirstContentfulPaintInbox[] = "PageLoad.Clients.ServiceWorker.PaintTiming." "NavigationToFirstContentfulPaint.inbox"; @@ -68,6 +70,8 @@ "PageLoad.Clients.ServiceWorker.DocumentTiming.NavigationToLoadEventFired." "inbox"; +const char kHistogramServiceWorkerParseStartSearch[] = + "PageLoad.Clients.ServiceWorker.ParseTiming.NavigationToParseStart.search"; const char kHistogramServiceWorkerFirstContentfulPaintSearch[] = "PageLoad.Clients.ServiceWorker.PaintTiming." "NavigationToFirstContentfulPaint.search"; @@ -316,6 +320,14 @@ timing.parse_timing->parse_start, info)) { PAGE_LOAD_HISTOGRAM(internal::kHistogramServiceWorkerParseStart, timing.parse_timing->parse_start.value()); + + if (IsInboxSite(info.url)) { + PAGE_LOAD_HISTOGRAM(internal::kHistogramServiceWorkerParseStartInbox, + timing.parse_timing->parse_start.value()); + } else if (page_load_metrics::IsGoogleSearchResultUrl(info.url)) { + PAGE_LOAD_HISTOGRAM(internal::kHistogramServiceWorkerParseStartSearch, + timing.parse_timing->parse_start.value()); + } if (IsForwardBackLoad(transition_)) { PAGE_LOAD_HISTOGRAM( internal::kHistogramServiceWorkerParseStartForwardBack,
diff --git a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h index e03159b..a5448c2 100644 --- a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h
@@ -27,6 +27,7 @@ extern const char kHistogramServiceWorkerDomContentLoaded[]; extern const char kHistogramServiceWorkerLoad[]; +extern const char kHistogramServiceWorkerParseStartInbox[]; extern const char kHistogramServiceWorkerFirstContentfulPaintInbox[]; extern const char kHistogramServiceWorkerFirstMeaningfulPaintInbox[]; extern const char @@ -36,6 +37,7 @@ extern const char kHistogramServiceWorkerDomContentLoadedInbox[]; extern const char kHistogramServiceWorkerLoadInbox[]; +extern const char kHistogramServiceWorkerParseStartSearch[]; extern const char kHistogramServiceWorkerFirstContentfulPaintSearch[]; extern const char kHistogramServiceWorkerFirstMeaningfulPaintSearch[]; extern const char
diff --git a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer_unittest.cc index 14df9d8d..abd488db 100644 --- a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer_unittest.cc
@@ -58,6 +58,8 @@ void AssertNoInboxHistogramsLogged() { histogram_tester().ExpectTotalCount( + internal::kHistogramServiceWorkerParseStartInbox, 0); + histogram_tester().ExpectTotalCount( internal::kHistogramServiceWorkerFirstContentfulPaintInbox, 0); histogram_tester().ExpectTotalCount( internal::kHistogramServiceWorkerParseStartToFirstContentfulPaintInbox, @@ -75,6 +77,8 @@ void AssertNoSearchHistogramsLogged() { histogram_tester().ExpectTotalCount( + internal::kHistogramServiceWorkerParseStartSearch, 0); + histogram_tester().ExpectTotalCount( internal::kHistogramServiceWorkerFirstContentfulPaintSearch, 0); histogram_tester().ExpectTotalCount( internal::kHistogramServiceWorkerParseStartToFirstContentfulPaintSearch, @@ -258,6 +262,17 @@ SimulateTimingAndMetadataUpdate(timing, metadata); histogram_tester().ExpectTotalCount( + internal::kHistogramServiceWorkerParseStart, 1); + histogram_tester().ExpectBucketCount( + internal::kHistogramServiceWorkerParseStart, + timing.parse_timing->parse_start.value().InMilliseconds(), 1); + histogram_tester().ExpectTotalCount( + internal::kHistogramServiceWorkerParseStartInbox, 1); + histogram_tester().ExpectBucketCount( + internal::kHistogramServiceWorkerParseStartInbox, + timing.parse_timing->parse_start.value().InMilliseconds(), 1); + + histogram_tester().ExpectTotalCount( internal::kHistogramServiceWorkerFirstContentfulPaint, 1); histogram_tester().ExpectBucketCount( internal::kHistogramServiceWorkerFirstContentfulPaint, @@ -363,6 +378,17 @@ SimulateTimingAndMetadataUpdate(timing, metadata); histogram_tester().ExpectTotalCount( + internal::kHistogramServiceWorkerParseStart, 1); + histogram_tester().ExpectBucketCount( + internal::kHistogramServiceWorkerParseStart, + timing.parse_timing->parse_start.value().InMilliseconds(), 1); + histogram_tester().ExpectTotalCount( + internal::kHistogramServiceWorkerParseStartSearch, 1); + histogram_tester().ExpectBucketCount( + internal::kHistogramServiceWorkerParseStartSearch, + timing.parse_timing->parse_start.value().InMilliseconds(), 1); + + histogram_tester().ExpectTotalCount( internal::kHistogramServiceWorkerFirstContentfulPaint, 1); histogram_tester().ExpectBucketCount( internal::kHistogramServiceWorkerFirstContentfulPaint,
diff --git a/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc b/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc index a664ede5..311162fd 100644 --- a/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc +++ b/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc
@@ -110,9 +110,11 @@ std::unique_ptr<MockPasswordFormManager> SavePasswordInfoBarDelegateTest::CreateMockFormManager() { - return std::unique_ptr<MockPasswordFormManager>( - new MockPasswordFormManager(&password_manager_, &client_, - driver_.AsWeakPtr(), test_form(), &fetcher_)); + auto manager = base::MakeUnique<MockPasswordFormManager>( + &password_manager_, &client_, driver_.AsWeakPtr(), test_form(), + &fetcher_); + manager->Init(nullptr); + return manager; } std::unique_ptr<ConfirmInfoBarDelegate>
diff --git a/chrome/browser/precache/precache_manager_factory.cc b/chrome/browser/precache/precache_manager_factory.cc index 54d6c736..3ec3cfb7 100644 --- a/chrome/browser/precache/precache_manager_factory.cc +++ b/chrome/browser/precache/precache_manager_factory.cc
@@ -54,8 +54,6 @@ new PrecacheDatabase()); base::FilePath db_path(browser_context->GetPath().Append( base::FilePath(FILE_PATH_LITERAL("PrecacheDatabase")))); - auto* loading_predictor = predictors::LoadingPredictorFactory::GetForProfile( - Profile::FromBrowserContext(browser_context)); return new PrecacheManager( browser_context, ProfileSyncServiceFactory::GetSyncServiceForBrowserContext( @@ -65,8 +63,6 @@ ServiceAccessType::IMPLICIT_ACCESS), DataReductionProxyChromeSettingsFactory::GetForBrowserContext( browser_context), - loading_predictor ? loading_predictor->resource_prefetch_predictor() - : nullptr, db_path, std::move(precache_database)); }
diff --git a/chrome/browser/predictors/loading_predictor.cc b/chrome/browser/predictors/loading_predictor.cc index d9b9411..d6c7f9b 100644 --- a/chrome/browser/predictors/loading_predictor.cc +++ b/chrome/browser/predictors/loading_predictor.cc
@@ -31,6 +31,8 @@ observer_(nullptr), weak_factory_(this) { resource_prefetch_predictor_->SetStatsCollector(stats_collector_.get()); + preconnect_manager_ = base::MakeUnique<PreconnectManager>( + GetWeakPtr(), profile_->GetRequestContext()); } LoadingPredictor::~LoadingPredictor() = default; @@ -38,13 +40,31 @@ void LoadingPredictor::PrepareForPageLoad(const GURL& url, HintOrigin origin) { if (active_hints_.find(url) != active_hints_.end()) return; - ResourcePrefetchPredictor::Prediction prediction; - if (!resource_prefetch_predictor_->GetPrefetchData(url, &prediction)) - return; - // To report hint durations. - active_hints_.emplace(url, base::TimeTicks::Now()); - MaybeAddPrefetch(url, prediction, origin); + bool hint_activated = false; + + { + ResourcePrefetchPredictor::Prediction prediction; + if (resource_prefetch_predictor_->GetPrefetchData(url, &prediction)) { + MaybeAddPrefetch(url, prediction.subresource_urls, origin); + hint_activated = true; + } + } + + if (!hint_activated) { + PreconnectPrediction prediction; + if (resource_prefetch_predictor_->PredictPreconnectOrigins(url, + &prediction)) { + MaybeAddPreconnect(url, prediction.preconnect_origins, + prediction.preresolve_hosts, origin); + hint_activated = true; + } + } + + if (hint_activated) { + // To report hint durations and deduplicate hints to the same url. + active_hints_.emplace(url, base::TimeTicks::Now()); + } } void LoadingPredictor::CancelPageLoadHint(const GURL& url) { @@ -70,12 +90,12 @@ for (auto& kv : prefetches_) prefetchers.push_back(std::move(kv.second.first)); - // |prefetchers| must be destroyed on the IO thread. + // |prefetchers| and |preconnect_manager_| must be destroyed on the IO thread. content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::BindOnce( - [](std::vector<std::unique_ptr<ResourcePrefetcher>> prefetchers) {}, - std::move(prefetchers))); + base::BindOnce([](std::vector<std::unique_ptr<ResourcePrefetcher>>, + std::unique_ptr<PreconnectManager>) {}, + std::move(prefetchers), std::move(preconnect_manager_))); } void LoadingPredictor::OnMainFrameRequest(const URLRequestSummary& summary) { @@ -126,7 +146,7 @@ const GURL& url = hint_it->first; MaybeRemovePrefetch(url); - + MaybeRemovePreconnect(url); UMA_HISTOGRAM_TIMES( internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, base::TimeTicks::Now() - hint_it->second); @@ -165,10 +185,9 @@ } } -void LoadingPredictor::MaybeAddPrefetch( - const GURL& url, - const ResourcePrefetchPredictor::Prediction& prediction, - HintOrigin origin) { +void LoadingPredictor::MaybeAddPrefetch(const GURL& url, + const std::vector<GURL>& urls, + HintOrigin origin) { if (!config_.IsPrefetchingEnabledForOrigin(profile_, origin)) return; std::string host = url.host(); @@ -178,8 +197,7 @@ auto prefetcher = base::MakeUnique<ResourcePrefetcher>( GetWeakPtr(), profile_->GetRequestContext(), config_.max_prefetches_inflight_per_navigation, - config_.max_prefetches_inflight_per_host_per_navigation, url, - prediction.subresource_urls); + config_.max_prefetches_inflight_per_host_per_navigation, url, urls); // base::Unretained(prefetcher.get()) is fine, as |prefetcher| is always // destructed on the IO thread, and the destruction task is posted from the // UI thread, after the current task. Since the IO thread is FIFO, then @@ -240,6 +258,39 @@ prefetches_.erase(it); } +void LoadingPredictor::MaybeAddPreconnect( + const GURL& url, + const std::vector<GURL>& preconnect_origins, + const std::vector<GURL>& preresolve_hosts, + HintOrigin origin) { + // In case Shutdown() has been already called. + if (!preconnect_manager_) + return; + if (!config_.IsPreconnectEnabledForOrigin(profile_, origin)) + return; + + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&PreconnectManager::Start, + base::Unretained(preconnect_manager_.get()), url, + preconnect_origins, preresolve_hosts)); +} + +void LoadingPredictor::MaybeRemovePreconnect(const GURL& url) { + // In case Shutdown() has been already called. + if (!preconnect_manager_) + return; + + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&PreconnectManager::Stop, + base::Unretained(preconnect_manager_.get()), url)); +} + +void LoadingPredictor::PreconnectFinished(const GURL& url) { + NOTIMPLEMENTED(); +} + TestLoadingObserver::~TestLoadingObserver() { predictor_->SetObserverForTesting(nullptr); }
diff --git a/chrome/browser/predictors/loading_predictor.h b/chrome/browser/predictors/loading_predictor.h index 2aa3f67..b28cc3c0 100644 --- a/chrome/browser/predictors/loading_predictor.h +++ b/chrome/browser/predictors/loading_predictor.h
@@ -9,11 +9,13 @@ #include <memory> #include <string> #include <utility> +#include <vector> #include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "chrome/browser/predictors/loading_data_collector.h" +#include "chrome/browser/predictors/preconnect_manager.h" #include "chrome/browser/predictors/resource_prefetch_common.h" #include "chrome/browser/predictors/resource_prefetch_predictor.h" #include "chrome/browser/predictors/resource_prefetcher.h" @@ -41,7 +43,8 @@ // // All methods must be called from the UI thread. class LoadingPredictor : public KeyedService, - public ResourcePrefetcher::Delegate { + public ResourcePrefetcher::Delegate, + public PreconnectManager::Delegate { public: LoadingPredictor(const LoadingPredictorConfig& config, Profile* profile); ~LoadingPredictor() override; @@ -79,6 +82,9 @@ ResourcePrefetcher* prefetcher, std::unique_ptr<ResourcePrefetcher::PrefetcherStats> stats) override; + // PreconnectManager::Delegate: + void PreconnectFinished(const GURL& url) override; + // Sets the |observer| to be notified when prefetches start and // finish. A previously registered observer will be discarded. Call this with // a nullptr parameter to de-register the observer. @@ -92,16 +98,23 @@ std::map<GURL, base::TimeTicks>::iterator hint_it); void CleanupAbandonedHintsAndNavigations(const NavigationID& navigation_id); - // May start a prefetch for |url| with the data from |prediction|, and a - // given hint |origin|. A new prefetch may not start if there is already - // one in flight, for instance. + // May start a prefetch of |urls| for |url| with a given hint |origin|. A new + // prefetch may not start if there is already one in flight, for instance. void MaybeAddPrefetch(const GURL& url, - const ResourcePrefetchPredictor::Prediction& prediction, + const std::vector<GURL>& urls, HintOrigin origin); - // If a prefetch exists for |url|, stop it. void MaybeRemovePrefetch(const GURL& url); + // May start a preconnect to |preconnect_origins| and preresolve of + // |preresolve_hosts| for |url| with a given hint |origin|. + void MaybeAddPreconnect(const GURL& url, + const std::vector<GURL>& preconnect_origins, + const std::vector<GURL>& preresolve_hosts, + HintOrigin origin); + // If a preconnect exists for |url|, stop it. + void MaybeRemovePreconnect(const GURL& url); + // For testing. void set_mock_resource_prefetch_predictor( std::unique_ptr<ResourcePrefetchPredictor> predictor) { @@ -113,6 +126,7 @@ std::unique_ptr<ResourcePrefetchPredictor> resource_prefetch_predictor_; std::unique_ptr<LoadingStatsCollector> stats_collector_; std::unique_ptr<LoadingDataCollector> loading_data_collector_; + std::unique_ptr<PreconnectManager> preconnect_manager_; std::map<GURL, base::TimeTicks> active_hints_; // Initial URL. std::map<NavigationID, GURL> active_navigations_;
diff --git a/chrome/browser/predictors/loading_test_util.cc b/chrome/browser/predictors/loading_test_util.cc index ef41145f..6ef83fe 100644 --- a/chrome/browser/predictors/loading_test_util.cc +++ b/chrome/browser/predictors/loading_test_util.cc
@@ -73,15 +73,6 @@ redirect->set_consecutive_misses(consecutive_misses); } -void InitializePrecacheResource(precache::PrecacheResource* resource, - const std::string& url, - double weight_ratio, - precache::PrecacheResource::Type type) { - resource->set_url(url); - resource->set_weight_ratio(weight_ratio); - resource->set_type(type); -} - void InitializeOriginStat(OriginStat* origin_stat, const std::string& origin, int number_of_hits, @@ -99,25 +90,6 @@ origin_stat->set_accessed_network(accessed_network); } -void InitializeExperiment(precache::PrecacheManifest* manifest, - uint32_t experiment_id, - const std::vector<bool>& bitset) { - std::string binary_bitset; - for (size_t i = 0; i < (bitset.size() + 7) / 8; ++i) { - char c = 0; - for (size_t j = 0; j < 8; ++j) { - if (i * 8 + j < bitset.size() && bitset[i * 8 + j]) - c |= (1 << j); - } - binary_bitset.push_back(c); - } - - precache::PrecacheResourceSelection prs; - prs.set_bitset(binary_bitset); - (*manifest->mutable_experiments() - ->mutable_resources_by_experiment_group())[experiment_id] = prs; -} - PrefetchData CreatePrefetchData(const std::string& primary_key, uint64_t last_visit_time) { PrefetchData data; @@ -134,12 +106,6 @@ return data; } -precache::PrecacheManifest CreateManifestData(int64_t id) { - precache::PrecacheManifest manifest; - manifest.mutable_id()->set_id(id); - return manifest; -} - OriginData CreateOriginData(const std::string& host, uint64_t last_visit_time) { OriginData data; data.set_host(host); @@ -496,37 +462,3 @@ } } // namespace predictors - -namespace precache { - -std::ostream& operator<<(std::ostream& os, const PrecacheManifest& manifest) { - os << "[" << manifest.id().id() << "]" << std::endl; - for (const PrecacheResource& resource : manifest.resource()) - os << "\t\t" << resource << std::endl; - return os; -} - -std::ostream& operator<<(std::ostream& os, const PrecacheResource& resource) { - return os << "[" << resource.url() << "," << resource.top_host_name() << "," - << resource.weight_ratio() << "," << resource.weight() << "]"; -} - -bool operator==(const PrecacheManifest& lhs, const PrecacheManifest& rhs) { - bool equal = lhs.id().id() == rhs.id().id() && - lhs.resource_size() == rhs.resource_size(); - - if (!equal) - return false; - - for (int i = 0; i < lhs.resource_size(); ++i) - equal = equal && lhs.resource(i) == rhs.resource(i); - - return equal; -} - -bool operator==(const PrecacheResource& lhs, const PrecacheResource& rhs) { - return lhs.url() == rhs.url() && - AlmostEqual(lhs.weight_ratio(), rhs.weight_ratio()); -} - -} // namespace precache
diff --git a/chrome/browser/predictors/loading_test_util.h b/chrome/browser/predictors/loading_test_util.h index 2fe23ac..9c8c1b84 100644 --- a/chrome/browser/predictors/loading_test_util.h +++ b/chrome/browser/predictors/loading_test_util.h
@@ -53,11 +53,6 @@ int number_of_misses, int consecutive_misses); -void InitializePrecacheResource(precache::PrecacheResource* resource, - const std::string& url, - double weight_ratio, - precache::PrecacheResource::Type type); - void InitializeOriginStat(OriginStat* origin_stat, const std::string& origin, int number_of_hits, @@ -67,15 +62,10 @@ bool always_access_network, bool accessed_network); -void InitializeExperiment(precache::PrecacheManifest* manifest, - uint32_t experiment_id, - const std::vector<bool>& bitset); - PrefetchData CreatePrefetchData(const std::string& primary_key, uint64_t last_visit_time = 0); RedirectData CreateRedirectData(const std::string& primary_key, uint64_t last_visit_time = 0); -precache::PrecacheManifest CreateManifestData(int64_t id = 0); OriginData CreateOriginData(const std::string& host, uint64_t last_visit_time = 0); @@ -208,16 +198,4 @@ } // namespace predictors -namespace precache { - -std::ostream& operator<<(std::ostream& stream, - const PrecacheManifest& manifest); -std::ostream& operator<<(std::ostream& stream, - const PrecacheResource& resource); - -bool operator==(const PrecacheManifest& lhs, const PrecacheManifest& rhs); -bool operator==(const PrecacheResource& lhs, const PrecacheResource& rhs); - -} // namespace precache - #endif // CHROME_BROWSER_PREDICTORS_LOADING_TEST_UTIL_H_
diff --git a/chrome/browser/predictors/preconnect_manager.cc b/chrome/browser/predictors/preconnect_manager.cc new file mode 100644 index 0000000..98e8df6f --- /dev/null +++ b/chrome/browser/predictors/preconnect_manager.cc
@@ -0,0 +1,35 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/predictors/preconnect_manager.h" + +#include <utility> + +#include "content/public/browser/browser_thread.h" + +namespace predictors { + +PreconnectManager::PreconnectManager( + base::WeakPtr<Delegate> delegate, + scoped_refptr<net::URLRequestContextGetter> context_getter) + : delegate_(std::move(delegate)), + context_getter_(std::move(context_getter)) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); +} + +PreconnectManager::~PreconnectManager() { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); +} + +void PreconnectManager::Start(const GURL& url, + const std::vector<GURL>& preconnect_origins, + const std::vector<GURL>& preresolve_hosts) { + NOTIMPLEMENTED(); +} + +void PreconnectManager::Stop(const GURL& url) { + NOTIMPLEMENTED(); +} + +} // namespace predictors
diff --git a/chrome/browser/predictors/preconnect_manager.h b/chrome/browser/predictors/preconnect_manager.h new file mode 100644 index 0000000..55518860 --- /dev/null +++ b/chrome/browser/predictors/preconnect_manager.h
@@ -0,0 +1,59 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PREDICTORS_PRECONNECT_MANAGER_H_ +#define CHROME_BROWSER_PREDICTORS_PRECONNECT_MANAGER_H_ + +#include <vector> + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "net/url_request/url_request_context_getter.h" +#include "url/gurl.h" + +namespace predictors { + +// PreconnectManager is responsible for preresolving and preconnecting to +// origins based on the input list of URLs. +// - The input list of URLs is associated with a main frame url that can be +// used for cancelling. +// - Limits the total number of preresolves in flight. +// - Preresolves an URL before preconnecting to it to have a better control on +// number of speculative dns requests in flight. +// - When stopped, waits for the pending preresolve requests to finish without +// issuing preconnects for them. +// - All methods of the class except the constructor must be called on the IO +// thread. The constructor must be called on the UI thread. +class PreconnectManager { + public: + class Delegate { + public: + virtual ~Delegate() {} + + // Called when all preresolve jobs for the |url| are finished. Note that + // some preconnect jobs can be still in progress, because they are + // fire-and-forget. + // Is called on the UI thread. + virtual void PreconnectFinished(const GURL& url) = 0; + }; + + PreconnectManager(base::WeakPtr<Delegate> delegate, + scoped_refptr<net::URLRequestContextGetter> context_getter); + ~PreconnectManager(); + + // Starts preconnect and preresolve jobs keyed by |url|. + void Start(const GURL& url, + const std::vector<GURL>& preconnect_origins, + const std::vector<GURL>& preresolve_hosts); + // No additional jobs keyed by the |url| will be queued after this. + void Stop(const GURL& url); + + private: + base::WeakPtr<Delegate> delegate_; + scoped_refptr<net::URLRequestContextGetter> context_getter_; +}; + +} // namespace predictors + +#endif // CHROME_BROWSER_PREDICTORS_PRECONNECT_MANAGER_H_
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.cc b/chrome/browser/predictors/resource_prefetch_predictor.cc index 4ac25ba9..06086247 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor.cc
@@ -23,7 +23,6 @@ #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/url_utils.h" #include "components/mime_util/mime_util.h" -#include "components/precache/core/precache_manifest_util.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/resource_request_info.h" #include "content/public/browser/web_contents.h" @@ -50,7 +49,6 @@ "application/font-sfnt", "application/font-ttf"}; -const size_t kMaxManifestByteSize = 16 * 1024; const size_t kNumSampleHosts = 50; const size_t kReportReadinessThreshold = 50; const float kMinOriginConfidenceToTriggerPreconnect = 0.75; @@ -100,12 +98,6 @@ origin->set_accessed_network(summary.accessed_network); } -bool IsManifestTooOld(const precache::PrecacheManifest& manifest) { - const base::TimeDelta kMaxManifestAge = base::TimeDelta::FromDays(5); - return base::Time::Now() - base::Time::FromDoubleT(manifest.id().id()) > - kMaxManifestAge; -} - // Used to fetch the visit count for a URL from the History database. class GetUrlVisitCountTask : public history::HistoryDBTask { public: @@ -161,27 +153,16 @@ ResourcePrefetchPredictor::PrefetchDataMap* host_resource_data, ResourcePrefetchPredictor::RedirectDataMap* url_redirect_data, ResourcePrefetchPredictor::RedirectDataMap* host_redirect_data, - ResourcePrefetchPredictor::ManifestDataMap* manifest_data, ResourcePrefetchPredictor::OriginDataMap* origin_data) { url_resource_data->InitializeOnDBThread(); host_resource_data->InitializeOnDBThread(); url_redirect_data->InitializeOnDBThread(); host_redirect_data->InitializeOnDBThread(); - manifest_data->InitializeOnDBThread(); origin_data->InitializeOnDBThread(); } } // namespace -namespace internal { - -bool ManifestCompare::operator()(const precache::PrecacheManifest& lhs, - const precache::PrecacheManifest& rhs) const { - return lhs.id().id() < rhs.id().id(); -} - -} // namespace internal - PreconnectPrediction::PreconnectPrediction() = default; PreconnectPrediction::PreconnectPrediction( const PreconnectPrediction& prediction) = default; @@ -413,8 +394,6 @@ tables_, tables_->url_redirect_table(), config_.max_urls_to_track); auto host_redirect_data = base::MakeUnique<RedirectDataMap>( tables_, tables_->host_redirect_table(), config_.max_hosts_to_track); - auto manifest_data = base::MakeUnique<ManifestDataMap>( - tables_, tables_->manifest_table(), config_.max_hosts_to_track); auto origin_data = base::MakeUnique<OriginDataMap>( tables_, tables_->origin_table(), config_.max_hosts_to_track); @@ -422,13 +401,12 @@ // will be passed to the reply task. auto task = base::BindOnce(InitializeOnDBThread, url_resource_data.get(), host_resource_data.get(), url_redirect_data.get(), - host_redirect_data.get(), manifest_data.get(), - origin_data.get()); + host_redirect_data.get(), origin_data.get()); auto reply = base::BindOnce( &ResourcePrefetchPredictor::CreateCaches, weak_factory_.GetWeakPtr(), std::move(url_resource_data), std::move(host_resource_data), std::move(url_redirect_data), std::move(host_redirect_data), - std::move(manifest_data), std::move(origin_data)); + std::move(origin_data)); BrowserThread::PostTaskAndReply(BrowserThread::DB, FROM_HERE, std::move(task), std::move(reply)); @@ -677,33 +655,17 @@ // Use host data if the URL-based prediction isn't available. std::string main_frame_url_host = main_frame_url.host(); if (GetRedirectEndpoint(main_frame_url_host, *host_redirect_data_, - &redirect_endpoint)) { - if (PopulatePrefetcherRequest(redirect_endpoint, *host_resource_data_, - urls)) { - if (prediction) { - prediction->is_host = true; - prediction->main_frame_key = redirect_endpoint; - prediction->is_redirected = (redirect_endpoint != main_frame_url_host); - } - return true; + &redirect_endpoint) && + PopulatePrefetcherRequest(redirect_endpoint, *host_resource_data_, + urls)) { + if (prediction) { + prediction->is_host = true; + prediction->main_frame_key = redirect_endpoint; + prediction->is_redirected = (redirect_endpoint != main_frame_url_host); } - - if (config_.is_manifests_enabled) { - // Use manifest data for host if available. - std::string manifest_host = redirect_endpoint; - if (base::StartsWith(manifest_host, "www.", base::CompareCase::SENSITIVE)) - manifest_host.assign(manifest_host, 4, std::string::npos); - if (PopulateFromManifest(manifest_host, urls)) { - if (prediction) { - prediction->is_host = true; - prediction->main_frame_key = redirect_endpoint; - prediction->is_redirected = - (redirect_endpoint != main_frame_url_host); - } - return true; - } - } + return true; } + return false; } @@ -763,66 +725,11 @@ return has_prefetchable_resource; } -bool ResourcePrefetchPredictor::PopulateFromManifest( - const std::string& manifest_host, - std::vector<GURL>* urls) const { - precache::PrecacheManifest manifest; - if (!manifest_data_->TryGetData(manifest_host, &manifest)) - return false; - - if (IsManifestTooOld(manifest)) - return false; - - // This is roughly in line with the threshold we use for resource confidence. - const float kMinWeight = 0.7f; - - // Don't prefetch resource if it has false bit in any of the following - // bitsets. All bits assumed to be true if an optional has no value. - base::Optional<std::vector<bool>> not_unused = - precache::GetResourceBitset(manifest, internal::kUnusedRemovedExperiment); - base::Optional<std::vector<bool>> not_versioned = precache::GetResourceBitset( - manifest, internal::kVersionedRemovedExperiment); - base::Optional<std::vector<bool>> not_no_store = precache::GetResourceBitset( - manifest, internal::kNoStoreRemovedExperiment); - - std::vector<const precache::PrecacheResource*> filtered_resources; - - bool has_prefetchable_resource = false; - for (int i = 0; i < manifest.resource_size(); ++i) { - const precache::PrecacheResource& resource = manifest.resource(i); - if (resource.weight_ratio() > kMinWeight && - (!not_unused.has_value() || not_unused.value()[i]) && - (!not_versioned.has_value() || not_versioned.value()[i]) && - (!not_no_store.has_value() || not_no_store.value()[i])) { - has_prefetchable_resource = true; - if (urls) - filtered_resources.push_back(&resource); - } - } - - if (urls) { - std::sort( - filtered_resources.begin(), filtered_resources.end(), - [](const precache::PrecacheResource* x, - const precache::PrecacheResource* y) { - return ResourcePrefetchPredictorTables::ComputePrecacheResourceScore( - *x) > - ResourcePrefetchPredictorTables::ComputePrecacheResourceScore( - *y); - }); - for (auto* resource : filtered_resources) - urls->emplace_back(resource->url()); - } - - return has_prefetchable_resource; -} - void ResourcePrefetchPredictor::CreateCaches( std::unique_ptr<PrefetchDataMap> url_resource_data, std::unique_ptr<PrefetchDataMap> host_resource_data, std::unique_ptr<RedirectDataMap> url_redirect_data, std::unique_ptr<RedirectDataMap> host_redirect_data, - std::unique_ptr<ManifestDataMap> manifest_data, std::unique_ptr<OriginDataMap> origin_data) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(INITIALIZING, initialization_state_); @@ -831,14 +738,12 @@ DCHECK(host_resource_data); DCHECK(url_redirect_data); DCHECK(host_redirect_data); - DCHECK(manifest_data); DCHECK(origin_data); url_resource_data_ = std::move(url_resource_data); host_resource_data_ = std::move(host_resource_data); url_redirect_data_ = std::move(url_redirect_data); host_redirect_data_ = std::move(host_redirect_data); - manifest_data_ = std::move(manifest_data); origin_data_ = std::move(origin_data); ConnectToHistoryService(); @@ -880,27 +785,23 @@ host_resource_data_->DeleteAllData(); url_redirect_data_->DeleteAllData(); host_redirect_data_->DeleteAllData(); - manifest_data_->DeleteAllData(); origin_data_->DeleteAllData(); } void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) { std::vector<std::string> urls_to_delete; std::vector<std::string> hosts_to_delete; - std::vector<std::string> manifest_hosts_to_delete; // Transform GURLs to keys for given database. for (const auto& it : urls) { urls_to_delete.emplace_back(it.url().spec()); hosts_to_delete.emplace_back(it.url().host()); - manifest_hosts_to_delete.emplace_back(history::HostForTopHosts(it.url())); } url_resource_data_->DeleteData(urls_to_delete); host_resource_data_->DeleteData(hosts_to_delete); url_redirect_data_->DeleteData(urls_to_delete); host_redirect_data_->DeleteData(hosts_to_delete); - manifest_data_->DeleteData(manifest_hosts_to_delete); origin_data_->DeleteData(hosts_to_delete); } @@ -1277,75 +1178,6 @@ } } -void ResourcePrefetchPredictor::OnManifestFetched( - const std::string& host, - const precache::PrecacheManifest& manifest) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (initialization_state_ != INITIALIZED) - return; - - if (!config_.is_manifests_enabled || IsManifestTooOld(manifest)) - return; - - // The manifest host has "www." prefix stripped, the manifest host could - // correspond to two different hosts in the prefetch database. - UpdatePrefetchDataByManifest(host, host_resource_data_.get(), manifest); - UpdatePrefetchDataByManifest("www." + host, host_resource_data_.get(), - manifest); - - // The manifest is too large to store. - if (host.length() > ResourcePrefetchPredictorTables::kMaxStringLength || - static_cast<uint32_t>(manifest.ByteSize()) > kMaxManifestByteSize) { - return; - } - - precache::PrecacheManifest data = manifest; - precache::RemoveUnknownFields(&data); - manifest_data_->UpdateData(host, data); -} - -void ResourcePrefetchPredictor::UpdatePrefetchDataByManifest( - const std::string& key, - PrefetchDataMap* resource_data, - const precache::PrecacheManifest& manifest) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK_EQ(INITIALIZED, initialization_state_); - - PrefetchData data; - bool exists = resource_data->TryGetData(key, &data); - if (!exists) - return; - - std::map<std::string, int> manifest_index; - for (int i = 0; i < manifest.resource_size(); ++i) - manifest_index.insert({manifest.resource(i).url(), i}); - - base::Optional<std::vector<bool>> not_unused = - precache::GetResourceBitset(manifest, internal::kUnusedRemovedExperiment); - - bool was_updated = false; - if (not_unused.has_value()) { - // Remove unused resources from |data|. - auto new_end = std::remove_if( - data.mutable_resources()->begin(), data.mutable_resources()->end(), - [&](const ResourceData& x) { - auto it = manifest_index.find(x.resource_url()); - if (it == manifest_index.end()) - return false; - return !not_unused.value()[it->second]; - }); - was_updated = new_end != data.mutable_resources()->end(); - data.mutable_resources()->erase(new_end, data.mutable_resources()->end()); - } - - if (was_updated) { - if (data.resources_size() == 0) - resource_data->DeleteData({key}); - else - resource_data->UpdateData(key, data); - } -} - void ResourcePrefetchPredictor::ConnectToHistoryService() { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(INITIALIZING, initialization_state_);
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.h b/chrome/browser/predictors/resource_prefetch_predictor.h index d1e6806..2aa0fbf 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor.h +++ b/chrome/browser/predictors/resource_prefetch_predictor.h
@@ -28,7 +28,6 @@ #include "components/history/core/browser/history_service_observer.h" #include "components/history/core/browser/history_types.h" #include "components/keyed_service/core/keyed_service.h" -#include "components/precache/content/precache_manager.h" #include "content/public/common/resource_type.h" #include "url/gurl.h" @@ -49,11 +48,6 @@ const uint32_t kUnusedRemovedExperiment = 0xf7f77166; const uint32_t kNoStoreRemovedExperiment = 0xd90a199a; -struct ManifestCompare { - bool operator()(const precache::PrecacheManifest& lhs, - const precache::PrecacheManifest& rhs) const; -}; - struct LastVisitTimeCompare { template <typename T> bool operator()(const T& lhs, const T& rhs) const { @@ -99,9 +93,7 @@ // it to disk in the DB thread through the ResourcePrefetchPredictorTables. It // initiates resource prefetching using the ResourcePrefetcherManager. Owned // by profile. -class ResourcePrefetchPredictor - : public history::HistoryServiceObserver, - public precache::PrecacheManager::Delegate { +class ResourcePrefetchPredictor : public history::HistoryServiceObserver { public: // Data collected for origin-based prediction, for a single origin during a // page load (see PageRequestSummary). @@ -194,8 +186,6 @@ GlowplugKeyValueData<PrefetchData, internal::LastVisitTimeCompare>; using RedirectDataMap = GlowplugKeyValueData<RedirectData, internal::LastVisitTimeCompare>; - using ManifestDataMap = GlowplugKeyValueData<precache::PrecacheManifest, - internal::ManifestCompare>; using OriginDataMap = GlowplugKeyValueData<OriginData, internal::LastVisitTimeCompare>; using NavigationMap = @@ -229,10 +219,6 @@ // number of hits. bool IsResourcePrefetchable(const ResourceData& resource) const; - // precache::PrecacheManager::Delegate: - void OnManifestFetched(const std::string& host, - const precache::PrecacheManifest& manifest) override; - // Sets the |observer| to be notified when the resource prefetch predictor // data changes. Previously registered observer will be discarded. Call // this with nullptr parameter to de-register observer. @@ -287,12 +273,6 @@ NavigationUrlNotInDBAndDBFull); FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, RedirectUrlNotInDB); FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, RedirectUrlInDB); - FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, ManifestHostNotInDB); - FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, ManifestHostInDB); - FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, - ManifestHostNotInDBAndDBFull); - FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, - ManifestUnusedRemoved); FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, OnMainFrameRequest); FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, OnMainFrameRedirect); FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, @@ -300,7 +280,6 @@ FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, GetCorrectPLT); FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, PopulatePrefetcherRequest); - FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, PopulateFromManifest); FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, GetRedirectEndpoint); FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, GetPrefetchData); FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, @@ -349,19 +328,12 @@ const PrefetchDataMap& resource_data, std::vector<GURL>* urls) const; - // Returns true iff the manifest table contains PrecacheManifest that can be - // used for a |manifest_host| and fills |urls| with resources that need to be - // prefetched. |urls| may be nullptr to get the return value only. - bool PopulateFromManifest(const std::string& manifest_host, - std::vector<GURL>* urls) const; - // Callback for the task to read the predictor database. Takes ownership of // all arguments. void CreateCaches(std::unique_ptr<PrefetchDataMap> url_resource_data, std::unique_ptr<PrefetchDataMap> host_resource_data, std::unique_ptr<RedirectDataMap> url_redirect_data, std::unique_ptr<RedirectDataMap> host_redirect_data, - std::unique_ptr<ManifestDataMap> manifest_data, std::unique_ptr<OriginDataMap> origin_data); // Called during initialization when history is read and the predictor @@ -411,12 +383,6 @@ void OnHistoryServiceLoaded( history::HistoryService* history_service) override; - // Updates list of resources in the |resource_data| for the |key| according to - // the |manifest|. - void UpdatePrefetchDataByManifest(const std::string& key, - PrefetchDataMap* resource_data, - const precache::PrecacheManifest& manifest); - // Used to connect to HistoryService or register for service loaded // notificatioan. void ConnectToHistoryService(); @@ -438,7 +404,6 @@ std::unique_ptr<PrefetchDataMap> host_resource_data_; std::unique_ptr<RedirectDataMap> url_redirect_data_; std::unique_ptr<RedirectDataMap> host_redirect_data_; - std::unique_ptr<ManifestDataMap> manifest_data_; std::unique_ptr<OriginDataMap> origin_data_; NavigationMap inflight_navigations_;
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_tables.cc b/chrome/browser/predictors/resource_prefetch_predictor_tables.cc index bfce3282c..0ee56dd 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor_tables.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor_tables.cc
@@ -24,7 +24,6 @@ const char kHostResourceTableName[] = "resource_prefetch_predictor_host"; const char kHostRedirectTableName[] = "resource_prefetch_predictor_host_redirect"; -const char kManifestTableName[] = "resource_prefetch_predictor_manifest"; const char kOriginTableName[] = "resource_prefetch_predictor_origin"; const char kCreateGlobalMetadataStatementTemplate[] = @@ -37,26 +36,6 @@ "proto BLOB, " "PRIMARY KEY(key))"; -predictors::ResourceData::ResourceType PrecacheResourceTypeToResourceType( - precache::PrecacheResource::Type resource_type) { - using precache::PrecacheResource; - using predictors::ResourceData; - switch (resource_type) { - case PrecacheResource::RESOURCE_TYPE_IMAGE: - return ResourceData::RESOURCE_TYPE_IMAGE; - case PrecacheResource::RESOURCE_TYPE_FONT: - return ResourceData::RESOURCE_TYPE_FONT_RESOURCE; - case PrecacheResource::RESOURCE_TYPE_STYLESHEET: - return ResourceData::RESOURCE_TYPE_STYLESHEET; - case PrecacheResource::RESOURCE_TYPE_SCRIPT: - return ResourceData::RESOURCE_TYPE_SCRIPT; - case PrecacheResource::RESOURCE_TYPE_OTHER: - case PrecacheResource::RESOURCE_TYPE_UNKNOWN: - default: - return ResourceData::RESOURCE_TYPE_SUB_RESOURCE; - } -} - int GetResourceTypeMultiplier( predictors::ResourceData::ResourceType resource_type) { switch (resource_type) { @@ -144,9 +123,6 @@ kHostResourceTableName); host_redirect_table_ = base::MakeUnique<GlowplugKeyValueTable<RedirectData>>( kHostRedirectTableName); - manifest_table_ = - base::MakeUnique<GlowplugKeyValueTable<precache::PrecacheManifest>>( - kManifestTableName); origin_table_ = base::MakeUnique<GlowplugKeyValueTable<OriginData>>(kOriginTableName); } @@ -187,15 +163,6 @@ } // static -float ResourcePrefetchPredictorTables::ComputePrecacheResourceScore( - const precache::PrecacheResource& resource) { - int type_multiplier = GetResourceTypeMultiplier( - PrecacheResourceTypeToResourceType(resource.type())); - // This means a strict ordering, since the weight_ratio is in [0,1). - return type_multiplier * 10 + resource.weight_ratio(); -} - -// static float ResourcePrefetchPredictorTables::ComputeOriginScore( const OriginStat& origin) { // The ranking is done by considering, in this order: @@ -250,10 +217,6 @@ ResourcePrefetchPredictorTables::host_redirect_table() { return host_redirect_table_.get(); } -GlowplugKeyValueTable<precache::PrecacheManifest>* -ResourcePrefetchPredictorTables::manifest_table() { - return manifest_table_.get(); -} GlowplugKeyValueTable<OriginData>* ResourcePrefetchPredictorTables::origin_table() { return origin_table_.get(); @@ -272,6 +235,8 @@ "resource_prefetch_predictor_url_metadata"; static const char kHostMetadataTableName[] = "resource_prefetch_predictor_host_metadata"; + static const char kManifestTableName[] = + "resource_prefetch_predictor_manifest"; if (incompatible_version) { for (const char* table_name : @@ -334,7 +299,7 @@ for (const char* table_name : {kUrlResourceTableName, kHostResourceTableName, kUrlRedirectTableName, - kHostRedirectTableName, kManifestTableName, kOriginTableName}) { + kHostRedirectTableName, kOriginTableName}) { success = success && (db->DoesTableExist(table_name) || db->Execute(base::StringPrintf(
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_tables.h b/chrome/browser/predictors/resource_prefetch_predictor_tables.h index 9d92dc83..adb9e6f 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor_tables.h +++ b/chrome/browser/predictors/resource_prefetch_predictor_tables.h
@@ -17,7 +17,6 @@ #include "chrome/browser/predictors/predictor_table_base.h" #include "chrome/browser/predictors/resource_prefetch_common.h" #include "chrome/browser/predictors/resource_prefetch_predictor.pb.h" -#include "components/precache/core/proto/precache.pb.h" namespace tracked_objects { class Location; @@ -34,8 +33,6 @@ // - UrlRedirectTable - key: url, value: RedirectData // - HostResourceTable - key: host, value: PrefetchData // - HostRedirectTable - key: host, value: RedirectData -// - ManifestTable - key: host with stripped "www." prefix, -// value: precache::PrecacheManifest // - OriginTable - key: host, value: OriginData class ResourcePrefetchPredictorTables : public PredictorTableBase { public: @@ -50,7 +47,6 @@ virtual GlowplugKeyValueTable<RedirectData>* url_redirect_table(); virtual GlowplugKeyValueTable<PrefetchData>* host_resource_table(); virtual GlowplugKeyValueTable<RedirectData>* host_redirect_table(); - virtual GlowplugKeyValueTable<precache::PrecacheManifest>* manifest_table(); virtual GlowplugKeyValueTable<OriginData>* origin_table(); // Removes the resources with more than |max_consecutive_misses| consecutive @@ -67,10 +63,6 @@ // misses from |data|. static void TrimRedirects(RedirectData* data, size_t max_consecutive_misses); - // Computes score of |data|. - static float ComputePrecacheResourceScore( - const precache::PrecacheResource& data); - // Removes the origins with more than |max_consecutive_misses| consecutive // misses from |data|. static void TrimOrigins(OriginData* data, size_t max_consecutive_misses); @@ -99,7 +91,7 @@ // Database version. Always increment it when any change is made to the data // schema (including the .proto). - static constexpr int kDatabaseVersion = 9; + static constexpr int kDatabaseVersion = 10; // PredictorTableBase: void CreateTableIfNonExistent() override; @@ -113,8 +105,6 @@ std::unique_ptr<GlowplugKeyValueTable<RedirectData>> url_redirect_table_; std::unique_ptr<GlowplugKeyValueTable<PrefetchData>> host_resource_table_; std::unique_ptr<GlowplugKeyValueTable<RedirectData>> host_redirect_table_; - std::unique_ptr<GlowplugKeyValueTable<precache::PrecacheManifest>> - manifest_table_; std::unique_ptr<GlowplugKeyValueTable<OriginData>> origin_table_; DISALLOW_COPY_AND_ASSIGN(ResourcePrefetchPredictorTables);
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_tables_unittest.cc b/chrome/browser/predictors/resource_prefetch_predictor_tables_unittest.cc index 34fd28f..ae72502 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor_tables_unittest.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor_tables_unittest.cc
@@ -28,7 +28,6 @@ using PrefetchDataMap = std::map<std::string, PrefetchData>; using RedirectDataMap = std::map<std::string, RedirectData>; - using ManifestDataMap = std::map<std::string, precache::PrecacheManifest>; using OriginDataMap = std::map<std::string, OriginData>; void SetUp() override; @@ -39,7 +38,6 @@ PrefetchDataMap* host_resource_data, RedirectDataMap* url_redirect_data, RedirectDataMap* host_redirect_data, - ManifestDataMap* manifest_data, OriginDataMap* origin_data) const; protected: @@ -56,8 +54,8 @@ private: // Initializes the tables, |test_url_data_|, |test_host_data_|, - // |test_url_redirect_data_|, |test_host_redirect_data_|, - // |test_manifest_data_|, and |test_origin_data|. + // |test_url_redirect_data_|, |test_host_redirect_data_| and + // |test_origin_data|. void InitializeSampleData(); // Checks that the input PrefetchData are the same, although the resources @@ -74,14 +72,6 @@ void TestRedirectsAreEqual(const std::vector<RedirectStat>& lhs, const std::vector<RedirectStat>& rhs) const; - // Checks that the input ManifestData are the same, although the resources - // can be in different order. - void TestManifestDataAreEqual(const ManifestDataMap& lhs, - const ManifestDataMap& rhs) const; - void TestManifestResourcesAreEqual( - const std::vector<precache::PrecacheResource>& lhs, - const std::vector<precache::PrecacheResource>& rhs) const; - void TestOriginDataAreEqual(const OriginDataMap& lhs, const OriginDataMap& rhs) const; void TestOriginStatsAreEqual(const std::vector<OriginStat>& lhs, @@ -89,14 +79,12 @@ void AddKey(PrefetchDataMap* m, const std::string& key) const; void AddKey(RedirectDataMap* m, const std::string& key) const; - void AddKey(ManifestDataMap* m, const std::string& key) const; void AddKey(OriginDataMap* m, const std::string& key) const; PrefetchDataMap test_url_data_; PrefetchDataMap test_host_data_; RedirectDataMap test_url_redirect_data_; RedirectDataMap test_host_redirect_data_; - ManifestDataMap test_manifest_data_; OriginDataMap test_origin_data_; }; @@ -135,18 +123,15 @@ void ResourcePrefetchPredictorTablesTest::TestGetAllData() { PrefetchDataMap actual_url_data, actual_host_data; RedirectDataMap actual_url_redirect_data, actual_host_redirect_data; - ManifestDataMap actual_manifest_data; OriginDataMap actual_origin_data; GetAllData(&actual_url_data, &actual_host_data, &actual_url_redirect_data, - &actual_host_redirect_data, &actual_manifest_data, - &actual_origin_data); + &actual_host_redirect_data, &actual_origin_data); TestPrefetchDataAreEqual(test_url_data_, actual_url_data); TestPrefetchDataAreEqual(test_host_data_, actual_host_data); TestRedirectDataAreEqual(test_url_redirect_data_, actual_url_redirect_data); TestRedirectDataAreEqual(test_host_redirect_data_, actual_host_redirect_data); - TestManifestDataAreEqual(test_manifest_data_, actual_manifest_data); TestOriginDataAreEqual(test_origin_data_, actual_origin_data); } @@ -170,11 +155,6 @@ &GlowplugKeyValueTable<RedirectData>::DeleteData, base::Unretained(tables_->host_redirect_table()), hosts_to_delete)); - hosts_to_delete = {"en.wikipedia.org"}; - tables_->ExecuteDBTaskOnDBThread(base::BindOnce( - &GlowplugKeyValueTable<precache::PrecacheManifest>::DeleteData, - base::Unretained(tables_->manifest_table()), hosts_to_delete)); - hosts_to_delete = {"twitter.com"}; tables_->ExecuteDBTaskOnDBThread(base::BindOnce( &GlowplugKeyValueTable<OriginData>::DeleteData, @@ -182,22 +162,18 @@ PrefetchDataMap actual_url_data, actual_host_data; RedirectDataMap actual_url_redirect_data, actual_host_redirect_data; - ManifestDataMap actual_manifest_data; OriginDataMap actual_origin_data; GetAllData(&actual_url_data, &actual_host_data, &actual_url_redirect_data, - &actual_host_redirect_data, &actual_manifest_data, - &actual_origin_data); + &actual_host_redirect_data, &actual_origin_data); PrefetchDataMap expected_url_data, expected_host_data; RedirectDataMap expected_url_redirect_data, expected_host_redirect_data; - ManifestDataMap expected_manifest_data; OriginDataMap expected_origin_data; AddKey(&expected_url_data, "http://www.reddit.com"); AddKey(&expected_host_data, "www.facebook.com"); AddKey(&expected_url_redirect_data, "http://nyt.com"); AddKey(&expected_host_redirect_data, "bbc.com"); - AddKey(&expected_manifest_data, "youtube.com"); AddKey(&expected_origin_data, "abc.xyz"); TestPrefetchDataAreEqual(expected_url_data, actual_url_data); @@ -206,7 +182,6 @@ actual_url_redirect_data); TestRedirectDataAreEqual(expected_host_redirect_data, actual_host_redirect_data); - TestManifestDataAreEqual(expected_manifest_data, actual_manifest_data); TestOriginDataAreEqual(expected_origin_data, actual_origin_data); } @@ -261,15 +236,6 @@ base::Unretained(tables_->host_redirect_table()), microsoft.primary_key(), microsoft)); - precache::PrecacheManifest theverge; - InitializePrecacheResource(theverge.add_resource(), - "https://www.theverge.com/main.js", 0.7, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - - tables_->ExecuteDBTaskOnDBThread(base::BindOnce( - &GlowplugKeyValueTable<precache::PrecacheManifest>::UpdateData, - base::Unretained(tables_->manifest_table()), "theverge.com", theverge)); - OriginData twitter = CreateOriginData("twitter.com"); InitializeOriginStat(twitter.add_origins(), "https://dogs.twitter.com", 10, 1, 0, 12., false, true); @@ -279,15 +245,12 @@ PrefetchDataMap actual_url_data, actual_host_data; RedirectDataMap actual_url_redirect_data, actual_host_redirect_data; - ManifestDataMap actual_manifest_data; OriginDataMap actual_origin_data; GetAllData(&actual_url_data, &actual_host_data, &actual_url_redirect_data, - &actual_host_redirect_data, &actual_manifest_data, - &actual_origin_data); + &actual_host_redirect_data, &actual_origin_data); PrefetchDataMap expected_url_data, expected_host_data; RedirectDataMap expected_url_redirect_data, expected_host_redirect_data; - ManifestDataMap expected_manifest_data; OriginDataMap expected_origin_data; AddKey(&expected_url_data, "http://www.reddit.com"); AddKey(&expected_url_data, "http://www.yahoo.com"); @@ -305,10 +268,6 @@ expected_host_redirect_data.insert( std::make_pair("microsoft.com", microsoft)); - AddKey(&expected_manifest_data, "youtube.com"); - AddKey(&expected_manifest_data, "en.wikipedia.org"); - expected_manifest_data.insert(std::make_pair("theverge.com", theverge)); - AddKey(&expected_origin_data, "abc.xyz"); expected_origin_data.insert({"twitter.com", twitter}); @@ -318,7 +277,6 @@ actual_url_redirect_data); TestRedirectDataAreEqual(expected_host_redirect_data, actual_host_redirect_data); - TestManifestDataAreEqual(expected_manifest_data, actual_manifest_data); } void ResourcePrefetchPredictorTablesTest::TestDeleteAllData() { @@ -326,16 +284,13 @@ PrefetchDataMap actual_url_data, actual_host_data; RedirectDataMap actual_url_redirect_data, actual_host_redirect_data; - ManifestDataMap actual_manifest_data; OriginDataMap actual_origin_data; GetAllData(&actual_url_data, &actual_host_data, &actual_url_redirect_data, - &actual_host_redirect_data, &actual_manifest_data, - &actual_origin_data); + &actual_host_redirect_data, &actual_origin_data); EXPECT_TRUE(actual_url_data.empty()); EXPECT_TRUE(actual_host_data.empty()); EXPECT_TRUE(actual_url_redirect_data.empty()); EXPECT_TRUE(actual_host_redirect_data.empty()); - EXPECT_TRUE(actual_manifest_data.empty()); } void ResourcePrefetchPredictorTablesTest::TestPrefetchDataAreEqual( @@ -426,48 +381,6 @@ EXPECT_TRUE(lhs_index.empty()); } -void ResourcePrefetchPredictorTablesTest::TestManifestDataAreEqual( - const ManifestDataMap& lhs, - const ManifestDataMap& rhs) const { - EXPECT_EQ(lhs.size(), rhs.size()); - - for (const auto& m : rhs) { - const auto lhs_it = lhs.find(m.first); - ASSERT_TRUE(lhs_it != lhs.end()) << m.first; - EXPECT_EQ(lhs_it->second.id().id(), m.second.id().id()); - - std::vector<precache::PrecacheResource> lhs_resources( - lhs_it->second.resource().begin(), lhs_it->second.resource().end()); - std::vector<precache::PrecacheResource> rhs_resources( - m.second.resource().begin(), m.second.resource().end()); - - TestManifestResourcesAreEqual(lhs_resources, rhs_resources); - } -} - -void ResourcePrefetchPredictorTablesTest::TestManifestResourcesAreEqual( - const std::vector<precache::PrecacheResource>& lhs, - const std::vector<precache::PrecacheResource>& rhs) const { - EXPECT_EQ(lhs.size(), rhs.size()); - - std::map<std::string, precache::PrecacheResource> lhs_index; - // Repeated resources are not allowed. - for (const auto& r : lhs) - EXPECT_TRUE(lhs_index.insert(std::make_pair(r.url(), r)).second); - - for (const auto& r : rhs) { - auto lhs_it = lhs_index.find(r.url()); - if (lhs_it != lhs_index.end()) { - EXPECT_EQ(r, lhs_it->second); - lhs_index.erase(lhs_it); - } else { - ADD_FAILURE() << r.url(); - } - } - - EXPECT_TRUE(lhs_index.empty()); -} - void ResourcePrefetchPredictorTablesTest::TestOriginDataAreEqual( const OriginDataMap& lhs, const OriginDataMap& rhs) const { @@ -532,13 +445,6 @@ m->insert(*it); } -void ResourcePrefetchPredictorTablesTest::AddKey(ManifestDataMap* m, - const std::string& key) const { - auto it = test_manifest_data_.find(key); - ASSERT_TRUE(it != test_manifest_data_.end()); - m->insert(*it); -} - void ResourcePrefetchPredictorTablesTest::AddKey(OriginDataMap* m, const std::string& key) const { auto it = test_origin_data_.find(key); @@ -559,9 +465,6 @@ tables_->ExecuteDBTaskOnDBThread( base::BindOnce(&GlowplugKeyValueTable<RedirectData>::DeleteAllData, base::Unretained(tables_->host_redirect_table()))); - tables_->ExecuteDBTaskOnDBThread(base::BindOnce( - &GlowplugKeyValueTable<precache::PrecacheManifest>::DeleteAllData, - base::Unretained(tables_->manifest_table()))); tables_->ExecuteDBTaskOnDBThread( base::BindOnce(&GlowplugKeyValueTable<OriginData>::DeleteAllData, base::Unretained(tables_->origin_table()))); @@ -572,7 +475,6 @@ PrefetchDataMap* host_resource_data, RedirectDataMap* url_redirect_data, RedirectDataMap* host_redirect_data, - ManifestDataMap* manifest_data, OriginDataMap* origin_data) const { tables_->ExecuteDBTaskOnDBThread(base::BindOnce( &GlowplugKeyValueTable<PrefetchData>::GetAllData, @@ -586,9 +488,6 @@ tables_->ExecuteDBTaskOnDBThread(base::BindOnce( &GlowplugKeyValueTable<RedirectData>::GetAllData, base::Unretained(tables_->host_redirect_table()), host_redirect_data)); - tables_->ExecuteDBTaskOnDBThread(base::BindOnce( - &GlowplugKeyValueTable<precache::PrecacheManifest>::GetAllData, - base::Unretained(tables_->manifest_table()), manifest_data)); tables_->ExecuteDBTaskOnDBThread( base::BindOnce(&GlowplugKeyValueTable<OriginData>::GetAllData, base::Unretained(tables_->origin_table()), origin_data)); @@ -753,36 +652,6 @@ microsoft.primary_key(), microsoft)); } - { // Manifest data. - precache::PrecacheManifest wikipedia; - InitializePrecacheResource( - wikipedia.add_resource(), "https://en.wikipedia.org/script.js", 0.7, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - InitializePrecacheResource(wikipedia.add_resource(), - "https://en.wikipedia.org/image.png", 0.3, - precache::PrecacheResource::RESOURCE_TYPE_IMAGE); - - precache::PrecacheManifest youtube; - InitializePrecacheResource(youtube.add_resource(), - "https://youtube.com/photo.jpg", 0.5, - precache::PrecacheResource::RESOURCE_TYPE_IMAGE); - InitializePrecacheResource( - youtube.add_resource(), "https://youtube.com/base.js", 0.2, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - - test_manifest_data_.clear(); - test_manifest_data_.insert(std::make_pair("en.wikipedia.org", wikipedia)); - test_manifest_data_.insert(std::make_pair("youtube.com", youtube)); - - tables_->ExecuteDBTaskOnDBThread(base::BindOnce( - &GlowplugKeyValueTable<precache::PrecacheManifest>::UpdateData, - base::Unretained(tables_->manifest_table()), "en.wikipedia.org", - wikipedia)); - tables_->ExecuteDBTaskOnDBThread(base::BindOnce( - &GlowplugKeyValueTable<precache::PrecacheManifest>::UpdateData, - base::Unretained(tables_->manifest_table()), "youtube.com", youtube)); - } - { // Origin data. OriginData twitter; twitter.set_host("twitter.com"); @@ -861,33 +730,6 @@ compute_score(net::HIGHEST, content::RESOURCE_TYPE_SCRIPT, 42.)); } -TEST_F(ResourcePrefetchPredictorTablesTest, ComputePrecacheResourceScore) { - auto compute_score = [](precache::PrecacheResource::Type resource_type, - float weight_ratio) { - precache::PrecacheResource resource; - InitializePrecacheResource(&resource, "", weight_ratio, resource_type); - return ResourcePrefetchPredictorTables::ComputePrecacheResourceScore( - resource); - }; - - // Stylesheets are the most impotant followed by scripts, fonts and images in - // this order. - EXPECT_GT( - compute_score(precache::PrecacheResource::RESOURCE_TYPE_STYLESHEET, 0.1), - compute_score(precache::PrecacheResource::RESOURCE_TYPE_SCRIPT, 0.9)); - EXPECT_GT( - compute_score(precache::PrecacheResource::RESOURCE_TYPE_SCRIPT, 0.1), - compute_score(precache::PrecacheResource::RESOURCE_TYPE_FONT, 0.9)); - EXPECT_GT( - compute_score(precache::PrecacheResource::RESOURCE_TYPE_FONT, 0.1), - compute_score(precache::PrecacheResource::RESOURCE_TYPE_IMAGE, 0.9)); - - // If resource types are equal, weight ratio matters. - EXPECT_GT( - compute_score(precache::PrecacheResource::RESOURCE_TYPE_SCRIPT, 0.7), - compute_score(precache::PrecacheResource::RESOURCE_TYPE_SCRIPT, 0.6)); -} - TEST_F(ResourcePrefetchPredictorTablesTest, ComputeOriginScore) { auto compute_score = [](int hits, int misses, double average_position, bool always_access_network, bool accessed_network) { @@ -965,15 +807,13 @@ PrefetchDataMap url_data, host_data; RedirectDataMap url_redirect_data, host_redirect_data; - ManifestDataMap manifest_data; OriginDataMap origin_data; GetAllData(&url_data, &host_data, &url_redirect_data, &host_redirect_data, - &manifest_data, &origin_data); + &origin_data); EXPECT_TRUE(url_data.empty()); EXPECT_TRUE(host_data.empty()); EXPECT_TRUE(url_redirect_data.empty()); EXPECT_TRUE(host_redirect_data.empty()); - EXPECT_TRUE(manifest_data.empty()); EXPECT_TRUE(origin_data.empty()); }
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc b/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc index 7038919..979196f11 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc
@@ -39,7 +39,6 @@ using PrefetchDataMap = std::map<std::string, PrefetchData>; using RedirectDataMap = std::map<std::string, RedirectData>; using OriginDataMap = std::map<std::string, OriginData>; -using ManifestDataMap = std::map<std::string, precache::PrecacheManifest>; template <typename T> class FakeGlowplugKeyValueTable : public GlowplugKeyValueTable<T> { @@ -94,10 +93,6 @@ return &host_redirect_table_; } - GlowplugKeyValueTable<precache::PrecacheManifest>* manifest_table() override { - return &manifest_table_; - } - GlowplugKeyValueTable<OriginData>* origin_table() override { return &origin_table_; } @@ -106,7 +101,6 @@ FakeGlowplugKeyValueTable<RedirectData> url_redirect_table_; FakeGlowplugKeyValueTable<PrefetchData> host_resource_table_; FakeGlowplugKeyValueTable<RedirectData> host_redirect_table_; - FakeGlowplugKeyValueTable<precache::PrecacheManifest> manifest_table_; FakeGlowplugKeyValueTable<OriginData> origin_table_; protected: @@ -187,7 +181,6 @@ PrefetchDataMap test_host_data_; RedirectDataMap test_url_redirect_data_; RedirectDataMap test_host_redirect_data_; - ManifestDataMap test_manifest_data_; OriginDataMap test_origin_data_; MockURLRequestJobFactory url_request_job_factory_; @@ -235,8 +228,6 @@ mock_tables_->host_resource_table_.data_); EXPECT_EQ(*predictor_->host_redirect_data_->data_cache_, mock_tables_->host_redirect_table_.data_); - EXPECT_EQ(*predictor_->manifest_data_->data_cache_, - mock_tables_->manifest_table_.data_); EXPECT_EQ(*predictor_->origin_data_->data_cache_, mock_tables_->origin_table_.data_); loading_predictor_ = nullptr; @@ -356,24 +347,6 @@ std::make_pair(microsoft.primary_key(), microsoft)); } - { // Manifest data. - precache::PrecacheManifest google = CreateManifestData(11); - InitializePrecacheResource( - google.add_resource(), "http://google.com/script.js", 0.5, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - InitializePrecacheResource( - google.add_resource(), "http://static.google.com/style.css", 0.333, - precache::PrecacheResource::RESOURCE_TYPE_STYLESHEET); - - precache::PrecacheManifest facebook = CreateManifestData(12); - InitializePrecacheResource( - facebook.add_resource(), "http://fb.com/static.css", 0.99, - precache::PrecacheResource::RESOURCE_TYPE_STYLESHEET); - - test_manifest_data_.insert(std::make_pair("google.com", google)); - test_manifest_data_.insert(std::make_pair("facebook.com", facebook)); - } - { // Origin data. OriginData google = CreateOriginData("google.com", 12); InitializeOriginStat(google.add_origins(), "https://static.google.com", 12, @@ -407,7 +380,6 @@ EXPECT_TRUE(mock_tables_->url_redirect_table_.data_.empty()); EXPECT_TRUE(mock_tables_->host_resource_table_.data_.empty()); EXPECT_TRUE(mock_tables_->host_redirect_table_.data_.empty()); - EXPECT_TRUE(mock_tables_->manifest_table_.data_.empty()); EXPECT_TRUE(mock_tables_->origin_table_.data_.empty()); } @@ -417,7 +389,6 @@ mock_tables_->url_redirect_table_.data_ = test_url_redirect_data_; mock_tables_->host_resource_table_.data_ = test_host_data_; mock_tables_->host_redirect_table_.data_ = test_host_redirect_data_; - mock_tables_->manifest_table_.data_ = test_manifest_data_; mock_tables_->origin_table_.data_ = test_origin_data_; ResetPredictor(); @@ -929,129 +900,6 @@ expected_host_redirect_data); } -TEST_F(ResourcePrefetchPredictorTest, ManifestHostNotInDB) { - precache::PrecacheManifest manifest = - CreateManifestData(base::Time::Now().ToDoubleT()); - InitializePrecacheResource(manifest.add_resource(), - "http://cdn.google.com/script.js", 0.9, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - InitializePrecacheResource( - manifest.add_resource(), "http://cdn.google.com/style.css", 0.75, - precache::PrecacheResource::RESOURCE_TYPE_STYLESHEET); - - predictor_->OnManifestFetched("google.com", manifest); - - EXPECT_EQ(mock_tables_->manifest_table_.data_, - ManifestDataMap({{"google.com", manifest}})); -} - -TEST_F(ResourcePrefetchPredictorTest, ManifestHostInDB) { - mock_tables_->manifest_table_.data_ = test_manifest_data_; - ResetPredictor(); - InitializePredictor(); - - precache::PrecacheManifest manifest = - CreateManifestData(base::Time::Now().ToDoubleT()); - InitializePrecacheResource(manifest.add_resource(), - "http://google.com/image.jpg", 0.1, - precache::PrecacheResource::RESOURCE_TYPE_IMAGE); - - predictor_->OnManifestFetched("google.com", manifest); - - ManifestDataMap expected_data = test_manifest_data_; - expected_data["google.com"] = manifest; - EXPECT_EQ(mock_tables_->manifest_table_.data_, expected_data); -} - -TEST_F(ResourcePrefetchPredictorTest, ManifestHostNotInDBAndDBFull) { - mock_tables_->manifest_table_.data_ = test_manifest_data_; - ResetPredictor(); - InitializePredictor(); - - precache::PrecacheManifest manifest = - CreateManifestData(base::Time::Now().ToDoubleT()); - InitializePrecacheResource(manifest.add_resource(), - "http://en.wikipedia.org/logo.png", 1.0, - precache::PrecacheResource::RESOURCE_TYPE_IMAGE); - - predictor_->OnManifestFetched("en.wikipedia.org", manifest); - - ManifestDataMap expected_data = test_manifest_data_; - expected_data.erase("google.com"); - expected_data["en.wikipedia.org"] = manifest; - EXPECT_EQ(mock_tables_->manifest_table_.data_, expected_data); -} - -TEST_F(ResourcePrefetchPredictorTest, ManifestUnknownFieldsRemoved) { - precache::PrecacheManifest manifest = - CreateManifestData(base::Time::Now().ToDoubleT()); - InitializePrecacheResource(manifest.add_resource(), - "http://cdn.google.com/script.js", 0.9, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - InitializePrecacheResource( - manifest.add_resource(), "http://cdn.google.com/style.css", 0.75, - precache::PrecacheResource::RESOURCE_TYPE_STYLESHEET); - - precache::PrecacheManifest manifest_with_unknown_fields(manifest); - manifest_with_unknown_fields.mutable_id()->mutable_unknown_fields()->append( - "DATA"); - manifest_with_unknown_fields.mutable_unknown_fields()->append("DATA"); - for (auto& resource : *manifest_with_unknown_fields.mutable_resource()) { - resource.mutable_unknown_fields()->append("DATA"); - } - - predictor_->OnManifestFetched("google.com", manifest_with_unknown_fields); - - EXPECT_EQ(mock_tables_->manifest_table_.data_["google.com"].ByteSize(), - manifest.ByteSize()); -} - -TEST_F(ResourcePrefetchPredictorTest, ManifestTooOld) { - base::Time old_time = base::Time::Now() - base::TimeDelta::FromDays(7); - precache::PrecacheManifest manifest = - CreateManifestData(old_time.ToDoubleT()); - InitializePrecacheResource(manifest.add_resource(), - "http://cdn.google.com/script.js", 0.9, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - InitializePrecacheResource( - manifest.add_resource(), "http://cdn.google.com/style.css", 0.75, - precache::PrecacheResource::RESOURCE_TYPE_STYLESHEET); - - predictor_->OnManifestFetched("google.com", manifest); - - EXPECT_TRUE(mock_tables_->manifest_table_.data_.empty()); -} - -TEST_F(ResourcePrefetchPredictorTest, ManifestUnusedRemoved) { - const std::string& script_url = "http://cdn.google.com/script.js"; - const std::string& style_url = "http://cdn.google.com/style.css"; - PrefetchData google = CreatePrefetchData("www.google.com"); - InitializeResourceData(google.add_resources(), script_url, - content::RESOURCE_TYPE_SCRIPT, 10, 0, 1, 2.1, - net::MEDIUM, false, false); - InitializeResourceData(google.add_resources(), style_url, - content::RESOURCE_TYPE_SCRIPT, 10, 0, 1, 2.1, - net::MEDIUM, false, false); - predictor_->host_resource_data_->UpdateData(google.primary_key(), google); - - precache::PrecacheManifest manifest = - CreateManifestData(base::Time::Now().ToDoubleT()); - InitializePrecacheResource(manifest.add_resource(), script_url, 0.9, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - InitializePrecacheResource( - manifest.add_resource(), style_url, 0.75, - precache::PrecacheResource::RESOURCE_TYPE_STYLESHEET); - InitializeExperiment(&manifest, internal::kUnusedRemovedExperiment, - {true, false}); - - predictor_->OnManifestFetched("google.com", manifest); - - // style_url should be removed. - google.mutable_resources()->RemoveLast(); - EXPECT_EQ(mock_tables_->host_resource_table_.data_, - PrefetchDataMap({{google.primary_key(), google}})); -} - TEST_F(ResourcePrefetchPredictorTest, DeleteUrls) { ResetPredictor(false); InitializePredictor(); @@ -1109,13 +957,6 @@ redirect.second); } - ManifestDataMap manifests; - manifests.insert({"google.com", CreateManifestData()}); - manifests.insert({"apple.com", CreateManifestData()}); - manifests.insert({"en.wikipedia.org", CreateManifestData()}); - for (const auto& manifest : manifests) - predictor_->manifest_data_->UpdateData(manifest.first, manifest.second); - // TODO(alexilin): Add origin data. history::URLRows rows; @@ -1132,22 +973,18 @@ url_redirects.erase("http://www.apple.com/"); host_redirects.erase("www.google.com"); host_redirects.erase("www.nike.com"); - manifests.erase("google.com"); - manifests.erase("apple.com"); predictor_->DeleteUrls(rows); EXPECT_EQ(mock_tables_->url_resource_table_.data_, url_resources); EXPECT_EQ(mock_tables_->host_resource_table_.data_, host_resources); EXPECT_EQ(mock_tables_->url_redirect_table_.data_, url_redirects); EXPECT_EQ(mock_tables_->host_redirect_table_.data_, host_redirects); - EXPECT_EQ(mock_tables_->manifest_table_.data_, manifests); predictor_->DeleteAllUrls(); EXPECT_TRUE(mock_tables_->url_resource_table_.data_.empty()); EXPECT_TRUE(mock_tables_->host_resource_table_.data_.empty()); EXPECT_TRUE(mock_tables_->url_redirect_table_.data_.empty()); EXPECT_TRUE(mock_tables_->host_redirect_table_.data_.empty()); - EXPECT_TRUE(mock_tables_->manifest_table_.data_.empty()); } TEST_F(ResourcePrefetchPredictorTest, OnMainFrameRequest) { @@ -1434,61 +1271,6 @@ EXPECT_TRUE(urls.empty()); } -TEST_F(ResourcePrefetchPredictorTest, PopulateFromManifest) { - // The data that will be used in populating. - precache::PrecacheManifest google = - CreateManifestData(base::Time::Now().ToDoubleT()); - InitializePrecacheResource(google.add_resource(), - "https://static.google.com/good.js", 0.9, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - InitializePrecacheResource(google.add_resource(), - "https://static.google.com/versioned_removed", 0.8, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - InitializePrecacheResource(google.add_resource(), - "https://static.google.com/unused_removed", 0.8, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - InitializePrecacheResource(google.add_resource(), - "https://static.google.com/no_store", 0.8, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - InitializePrecacheResource( - google.add_resource(), "https://static.google.com/good.css", 0.75, - precache::PrecacheResource::RESOURCE_TYPE_STYLESHEET); - InitializePrecacheResource(google.add_resource(), - "https://static.google.com/low_confidence", 0.6, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - InitializeExperiment(&google, internal::kVersionedRemovedExperiment, - {true, false, true, true, true}); - InitializeExperiment(&google, internal::kUnusedRemovedExperiment, - {true, true, false, true, true}); - InitializeExperiment(&google, internal::kNoStoreRemovedExperiment, - {true, true, true, false, true}); - - // The data that's too old. - base::Time old_time = base::Time::Now() - base::TimeDelta::FromDays(7); - precache::PrecacheManifest facebook = - CreateManifestData(old_time.ToDoubleT()); - InitializePrecacheResource(facebook.add_resource(), - "https://static.facebook.com/good", 0.9, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - - predictor_->manifest_data_->UpdateData("google.com", google); - predictor_->manifest_data_->UpdateData("facebook.com", facebook); - - std::vector<GURL> urls; - EXPECT_TRUE(predictor_->PopulateFromManifest("google.com", &urls)); - EXPECT_EQ(urls, - std::vector<GURL>({GURL("https://static.google.com/good.css"), - GURL("https://static.google.com/good.js")})); - - urls.clear(); - EXPECT_FALSE(predictor_->PopulateFromManifest("facebook.com", &urls)); - EXPECT_TRUE(urls.empty()); - - urls.clear(); - EXPECT_FALSE(predictor_->PopulateFromManifest("404.com", &urls)); - EXPECT_TRUE(urls.empty()); -} - TEST_F(ResourcePrefetchPredictorTest, GetRedirectEndpoint) { // The data to be requested for the confident endpoint. RedirectData nyt = CreateRedirectData("http://nyt.com", 1); @@ -1537,18 +1319,6 @@ // No prefetch data. EXPECT_FALSE(predictor_->GetPrefetchData(main_frame_url, &prediction)); - // Add a manifest associated with the main frame host. - const std::string& resource_url = "https://static.google.com/resource"; - precache::PrecacheManifest manifest = - CreateManifestData(base::Time::Now().ToDoubleT()); - InitializePrecacheResource(manifest.add_resource(), resource_url, 0.9, - precache::PrecacheResource::RESOURCE_TYPE_SCRIPT); - predictor_->manifest_data_->UpdateData("google.com", manifest); - - urls.clear(); - EXPECT_TRUE(predictor_->GetPrefetchData(main_frame_url, &prediction)); - EXPECT_THAT(urls, UnorderedElementsAre(GURL(resource_url))); - // Add a resource associated with the main frame host. PrefetchData google_host = CreatePrefetchData("google.com", 2); const std::string script_url = "https://cdn.google.com/script.js";
diff --git a/chrome/browser/predictors/resource_prefetcher.cc b/chrome/browser/predictors/resource_prefetcher.cc index b5374be..282e8ab 100644 --- a/chrome/browser/predictors/resource_prefetcher.cc +++ b/chrome/browser/predictors/resource_prefetcher.cc
@@ -57,8 +57,8 @@ const GURL& main_frame_url, const std::vector<GURL>& urls) : state_(INITIALIZED), - delegate_(delegate), - context_getter_(context_getter), + delegate_(std::move(delegate)), + context_getter_(std::move(context_getter)), max_concurrent_requests_(max_concurrent_requests), max_concurrent_requests_per_host_(max_concurrent_requests_per_host), main_frame_url_(main_frame_url),
diff --git a/chrome/browser/signin/signin_tracker_unittest.cc b/chrome/browser/signin/signin_tracker_unittest.cc index 772432f..35985a8f 100644 --- a/chrome/browser/signin/signin_tracker_unittest.cc +++ b/chrome/browser/signin/signin_tracker_unittest.cc
@@ -66,7 +66,7 @@ static_cast<FakeProfileOAuth2TokenService*>( ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())); - mock_signin_manager_ = static_cast<FakeSigninManagerForTesting*>( + fake_signin_manager_ = static_cast<FakeSigninManagerForTesting*>( SigninManagerFactory::GetForProfile(profile_.get())); tracker_ = @@ -91,7 +91,7 @@ content::TestBrowserThreadBundle thread_bundle_; std::unique_ptr<SigninTracker> tracker_; std::unique_ptr<TestingProfile> profile_; - FakeSigninManagerForTesting* mock_signin_manager_; + FakeSigninManagerForTesting* fake_signin_manager_; FakeProfileOAuth2TokenService* fake_oauth2_token_service_; MockObserver observer_; }; @@ -105,7 +105,7 @@ EXPECT_CALL(observer_, SigninSuccess()).Times(0); EXPECT_CALL(observer_, SigninFailed(error)); - mock_signin_manager_->FailSignin(error); + fake_signin_manager_->FailSignin(error); } #endif // !defined(OS_CHROMEOS) @@ -119,6 +119,21 @@ std::string email = "user@gmail.com"; std::string account_id = service->SeedAccountInfo(gaia_id, email); - mock_signin_manager_->SetAuthenticatedAccountInfo(gaia_id, email); + fake_signin_manager_->SetAuthenticatedAccountInfo(gaia_id, email); fake_oauth2_token_service_->UpdateCredentials(account_id, "refresh_token"); } + +#if !defined(OS_CHROMEOS) +TEST_F(SigninTrackerTest, SignInSucceedsWithExistingAccount) { + EXPECT_CALL(observer_, SigninSuccess()); + EXPECT_CALL(observer_, SigninFailed(_)).Times(0); + + AccountTrackerService* service = + AccountTrackerServiceFactory::GetForProfile(profile_.get()); + std::string gaia_id = "gaia_id"; + std::string email = "user@gmail.com"; + std::string account_id = service->SeedAccountInfo(gaia_id, email); + fake_oauth2_token_service_->UpdateCredentials(account_id, "refresh_token"); + fake_signin_manager_->SignIn(gaia_id, email, std::string()); +} +#endif
diff --git a/chrome/utility/extensions/extensions_handler.cc b/chrome/utility/extensions/extensions_handler.cc index 648c7782..b487c95 100644 --- a/chrome/utility/extensions/extensions_handler.cc +++ b/chrome/utility/extensions/extensions_handler.cc
@@ -234,7 +234,7 @@ itunes::FindLibraryLocationInPrefXml(itunes_xml_data)); content::UtilityThread::Get()->Send( new ChromeUtilityHostMsg_GotITunesDirectory(library_path)); - content::UtilityThread::Get()->ReleaseProcessIfNeeded(); + content::UtilityThread::Get()->ReleaseProcess(); } #endif // defined(OS_WIN) @@ -246,7 +246,7 @@ bool result = parser.Parse(iapps::ReadFileAsString(std::move(file))); content::UtilityThread::Get()->Send( new ChromeUtilityHostMsg_GotITunesLibrary(result, parser.library())); - content::UtilityThread::Get()->ReleaseProcessIfNeeded(); + content::UtilityThread::Get()->ReleaseProcess(); } void ExtensionsHandler::OnParsePicasaPMPDatabase( @@ -272,7 +272,7 @@ content::UtilityThread::Get()->Send( new ChromeUtilityHostMsg_ParsePicasaPMPDatabase_Finished( parse_success, reader.albums(), reader.folders())); - content::UtilityThread::Get()->ReleaseProcessIfNeeded(); + content::UtilityThread::Get()->ReleaseProcess(); } void ExtensionsHandler::OnIndexPicasaAlbumsContents( @@ -283,7 +283,7 @@ content::UtilityThread::Get()->Send( new ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished( indexer.albums_images())); - content::UtilityThread::Get()->ReleaseProcessIfNeeded(); + content::UtilityThread::Get()->ReleaseProcess(); } #endif // defined(OS_WIN) || defined(OS_MACOSX)
diff --git a/chrome/utility/printing_handler.cc b/chrome/utility/printing_handler.cc index 146ef7a..83366b9a 100644 --- a/chrome/utility/printing_handler.cc +++ b/chrome/utility/printing_handler.cc
@@ -37,8 +37,8 @@ return content::UtilityThread::Get()->Send(message); } -void ReleaseProcessIfNeeded() { - content::UtilityThread::Get()->ReleaseProcessIfNeeded(); +void ReleaseProcess() { + content::UtilityThread::Get()->ReleaseProcess(); } #if defined(OS_WIN) @@ -126,7 +126,7 @@ } void PrintingHandler::OnRenderPDFPagesToMetafileStop() { - ReleaseProcessIfNeeded(); + ReleaseProcess(); } #endif // defined(OS_WIN) @@ -145,7 +145,7 @@ } else { Send(new ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Failed()); } - ReleaseProcessIfNeeded(); + ReleaseProcess(); } #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) @@ -317,7 +317,7 @@ Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Failed( printer_name)); } - ReleaseProcessIfNeeded(); + ReleaseProcess(); } void PrintingHandler::OnGetPrinterSemanticCapsAndDefaults( @@ -337,7 +337,7 @@ Send(new ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Failed( printer_name)); } - ReleaseProcessIfNeeded(); + ReleaseProcess(); } #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
diff --git a/chrome/utility/profile_import_handler.cc b/chrome/utility/profile_import_handler.cc index 2aa3674a7..a3a03102 100644 --- a/chrome/utility/profile_import_handler.cc +++ b/chrome/utility/profile_import_handler.cc
@@ -80,5 +80,5 @@ importer_ = NULL; bridge_ = NULL; import_thread_.reset(); - content::UtilityThread::Get()->ReleaseProcessIfNeeded(); + content::UtilityThread::Get()->ReleaseProcess(); }
diff --git a/components/browsing_data/core/counters/browsing_data_counter.cc b/components/browsing_data/core/counters/browsing_data_counter.cc index 243eee8..62befe0 100644 --- a/components/browsing_data/core/counters/browsing_data_counter.cc +++ b/components/browsing_data/core/counters/browsing_data_counter.cc
@@ -19,8 +19,7 @@ } BrowsingDataCounter::BrowsingDataCounter() - : initialized_(false), - state_(State::IDLE) {} + : initialized_(false), use_delay_(true), state_(State::IDLE) {} BrowsingDataCounter::~BrowsingDataCounter() {} @@ -43,6 +42,7 @@ void BrowsingDataCounter::InitWithoutPref(base::Time begin_time, const Callback& callback) { DCHECK(!initialized_); + use_delay_ = false; callback_ = callback; clear_browsing_data_tab_ = ClearBrowsingDataTab::ADVANCED; begin_time_ = begin_time; @@ -71,9 +71,14 @@ state_transitions_.clear(); state_transitions_.push_back(state_); - timer_.Start(FROM_HERE, - base::TimeDelta::FromMilliseconds(kDelayUntilShowCalculatingMs), - this, &BrowsingDataCounter::TransitionToShowCalculating); + if (use_delay_) { + timer_.Start( + FROM_HERE, + base::TimeDelta::FromMilliseconds(kDelayUntilShowCalculatingMs), this, + &BrowsingDataCounter::TransitionToShowCalculating); + } else { + state_ = State::READY_TO_REPORT_RESULT; + } Count(); }
diff --git a/components/browsing_data/core/counters/browsing_data_counter.h b/components/browsing_data/core/counters/browsing_data_counter.h index bb180b4..3173a6d 100644 --- a/components/browsing_data/core/counters/browsing_data_counter.h +++ b/components/browsing_data/core/counters/browsing_data_counter.h
@@ -109,6 +109,7 @@ // Can be called instead of |Init()|, to create a counter that doesn't // observe pref changes and counts data that was changed since |begin_time|. + // This mode doesn't use delayed responses. void InitWithoutPref(base::Time begin_time, const Callback& callback); // Name of the preference associated with this counter. @@ -178,6 +179,9 @@ // Whether this class was properly initialized by calling |Init|. bool initialized_; + // Whether to introduce a delayed response to avoid flickering. + bool use_delay_; + // State of the counter. State state_;
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc index ad0dba3b..adf31a3 100644 --- a/components/ntp_tiles/most_visited_sites.cc +++ b/components/ntp_tiles/most_visited_sites.cc
@@ -44,6 +44,15 @@ url1.path_piece() == url2.path_piece(); } +bool HasHomeTile(const NTPTilesVector& tiles) { + for (const auto& tile : tiles) { + if (tile.source == TileSource::HOMEPAGE) { + return true; + } + } + return false; +} + } // namespace MostVisitedSites::MostVisitedSites( @@ -239,7 +248,7 @@ } mv_source_ = TileSource::TOP_SITES; - SaveNewTilesAndNotify(std::move(tiles)); + InitiateNotificationForNewTiles(std::move(tiles)); } void MostVisitedSites::OnSuggestionsProfileChanged( @@ -295,7 +304,7 @@ } mv_source_ = TileSource::SUGGESTIONS_SERVICE; - SaveNewTilesAndNotify(std::move(tiles)); + InitiateNotificationForNewTiles(std::move(tiles)); } NTPTilesVector MostVisitedSites::CreateWhitelistEntryPointTiles( @@ -375,16 +384,27 @@ return popular_sites_tiles; } -NTPTilesVector MostVisitedSites::CreatePersonalTilesWithHomeTile( - NTPTilesVector tiles) const { +void MostVisitedSites::OnHomePageTitleDetermined( + NTPTilesVector tiles, + const base::Optional<base::string16>& title) { + if (!title.has_value()) { + return; // If there is no title, the most recent tile was already sent out. + } + SaveTilesAndNotify(InsertHomeTile(std::move(tiles), title.value())); +} + +NTPTilesVector MostVisitedSites::InsertHomeTile( + NTPTilesVector tiles, + const base::string16& title) const { DCHECK(home_page_client_); DCHECK_GT(num_sites_, 0u); - const GURL& home_page_url = home_page_client_->GetHomepageUrl(); + const GURL& home_page_url = home_page_client_->GetHomePageUrl(); NTPTilesVector new_tiles; // Add the home tile as first tile. NTPTile home_tile; home_tile.url = home_page_url; + home_tile.title = title; home_tile.source = TileSource::HOMEPAGE; new_tiles.push_back(std::move(home_tile)); @@ -393,6 +413,7 @@ break; } + // TODO(fhorschig): Introduce a more sophisticated deduplication. if (tile.url.host() == home_page_url.host()) { continue; } @@ -402,13 +423,22 @@ return new_tiles; } -void MostVisitedSites::SaveNewTilesAndNotify(NTPTilesVector personal_tiles) { +void MostVisitedSites::InitiateNotificationForNewTiles( + NTPTilesVector new_tiles) { + if (ShouldAddHomeTile() && !HasHomeTile(new_tiles)) { + home_page_client_->QueryHomePageTitle( + base::BindOnce(&MostVisitedSites::OnHomePageTitleDetermined, + base::Unretained(this), new_tiles)); + // Don't wait for the homepage title from history but immediately serve a + // copy of new tiles. + new_tiles = InsertHomeTile(std::move(new_tiles), base::string16()); + } + SaveTilesAndNotify(std::move(new_tiles)); +} + +void MostVisitedSites::SaveTilesAndNotify(NTPTilesVector personal_tiles) { std::set<std::string> used_hosts; size_t num_actual_tiles = 0u; - - if (ShouldAddHomeTile()) { - personal_tiles = CreatePersonalTilesWithHomeTile(std::move(personal_tiles)); - } AddToHostsAndTotalCount(personal_tiles, &used_hosts, &num_actual_tiles); NTPTilesVector whitelist_tiles = @@ -487,9 +517,9 @@ home_page_client_ && // No platform-specific implementation - no tile. home_page_client_->IsHomePageEnabled() && !home_page_client_->IsNewTabPageUsedAsHomePage() && - !home_page_client_->GetHomepageUrl().is_empty() && + !home_page_client_->GetHomePageUrl().is_empty() && !(top_sites_ && - top_sites_->IsBlacklisted(home_page_client_->GetHomepageUrl())); + top_sites_->IsBlacklisted(home_page_client_->GetHomePageUrl())); } void MostVisitedSites::AddToHostsAndTotalCount(const NTPTilesVector& new_tiles,
diff --git a/components/ntp_tiles/most_visited_sites.h b/components/ntp_tiles/most_visited_sites.h index 12ed83a09..661623d 100644 --- a/components/ntp_tiles/most_visited_sites.h +++ b/components/ntp_tiles/most_visited_sites.h
@@ -12,6 +12,7 @@ #include <string> #include <vector> +#include "base/callback_forward.h" #include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/macros.h" @@ -95,10 +96,14 @@ // platform-specific implementation. class HomePageClient { public: + using TitleCallback = + base::OnceCallback<void(const base::Optional<base::string16>& title)>; + virtual ~HomePageClient() = default; virtual bool IsHomePageEnabled() const = 0; virtual bool IsNewTabPageUsedAsHomePage() const = 0; - virtual GURL GetHomepageUrl() const = 0; + virtual GURL GetHomePageUrl() const = 0; + virtual void QueryHomePageTitle(TitleCallback title_callback) = 0; }; // Construct a MostVisitedSites instance. @@ -193,10 +198,14 @@ const std::set<std::string>& used_hosts, size_t num_actual_tiles); + // Initiates a query for the home page tile if needed and calls + // |SaveTilesAndNotify| in the end. + void InitiateNotificationForNewTiles(NTPTilesVector new_tiles); + // Takes the personal tiles, creates and merges in whitelist and popular tiles // if appropriate, and saves the new tiles. Notifies the observer if the tiles // were actually changed. - void SaveNewTilesAndNotify(NTPTilesVector personal_tiles); + void SaveTilesAndNotify(NTPTilesVector personal_tiles); void OnPopularSitesDownloaded(bool success); @@ -211,7 +220,11 @@ // Adds the home page as first tile to |tiles| and returns them as new vector. // Drops existing tiles with the same host as the home page and tiles that // would exceed the maximum. - NTPTilesVector CreatePersonalTilesWithHomeTile(NTPTilesVector tiles) const; + NTPTilesVector InsertHomeTile(NTPTilesVector tiles, + const base::string16& title) const; + + void OnHomePageTitleDetermined(NTPTilesVector tiles, + const base::Optional<base::string16>& title); // Returns true if there is a valid home page that can be pinned as tile. bool ShouldAddHomeTile() const;
diff --git a/components/ntp_tiles/most_visited_sites_unittest.cc b/components/ntp_tiles/most_visited_sites_unittest.cc index 5a0d9e18f..a4458b1 100644 --- a/components/ntp_tiles/most_visited_sites_unittest.cc +++ b/components/ntp_tiles/most_visited_sites_unittest.cc
@@ -71,6 +71,7 @@ using testing::_; const char kHomePageUrl[] = "http://ho.me/"; +const char kHomePageTitle[] = "Home"; std::string PrintTile(const std::string& title, const std::string& url, @@ -222,7 +223,11 @@ bool IsNewTabPageUsedAsHomePage() const override { return ntp_is_homepage_; } - GURL GetHomepageUrl() const override { return home_page_url_; } + GURL GetHomePageUrl() const override { return home_page_url_; } + + void QueryHomePageTitle(TitleCallback title_callback) override { + std::move(title_callback).Run(home_page_title_); + } void SetHomePageEnabled(bool home_page_enabled) { home_page_enabled_ = home_page_enabled; @@ -234,10 +239,15 @@ void SetHomePageUrl(GURL home_page_url) { home_page_url_ = home_page_url; } + void SetHomePageTitle(const base::Optional<base::string16>& home_page_title) { + home_page_title_ = home_page_title; + } + private: bool home_page_enabled_; bool ntp_is_homepage_; GURL home_page_url_; + base::Optional<base::string16> home_page_title_; }; class MockIconCacher : public IconCacher { @@ -463,6 +473,34 @@ base::RunLoop().RunUntilIdle(); } +TEST_P(MostVisitedSitesTest, ShouldIncludeHomeTileWithUrlBeforeQueryingName) { + // Because the query time for the real name might take a while, provide the + // home tile with URL as title immediately and update the tiles as soon as the + // real title was found. + FakeHomePageClient* home_page_client = RegisterNewHomePageClient(); + home_page_client->SetHomePageEnabled(true); + home_page_client->SetHomePageTitle(base::UTF8ToUTF16(kHomePageTitle)); + DisableRemoteSuggestions(); + EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_, false)) + .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{})); + EXPECT_CALL(*mock_top_sites_, SyncWithHistory()); + EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomePageUrl)))) + .Times(AnyNumber()) + .WillRepeatedly(Return(false)); + { + testing::Sequence seq; + EXPECT_CALL(mock_observer_, + OnMostVisitedURLsAvailable(Not(Contains( + MatchesTile("", kHomePageUrl, TileSource::HOMEPAGE))))); + EXPECT_CALL(mock_observer_, + OnMostVisitedURLsAvailable(Not(Contains(MatchesTile( + kHomePageTitle, kHomePageUrl, TileSource::HOMEPAGE))))); + } + most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_, + /*num_sites=*/3); + base::RunLoop().RunUntilIdle(); +} + TEST_P(MostVisitedSitesTest, ShouldUpdateHomePageTileOnHomePageStateChanged) { FakeHomePageClient* home_page_client = RegisterNewHomePageClient(); home_page_client->SetHomePageEnabled(true);
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index d89ec30..3546bfe7 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -726,6 +726,8 @@ password_manager::PasswordStore* store = client_->GetPasswordStore(); // May be null in tests. if (store) { + metrics_util::LogSyncPasswordHashChange( + metrics_util::SyncPasswordHashChange::SAVED_IN_CONTENT_AREA); store->SaveSyncPasswordHash( provisional_save_manager_->submitted_form()->password_value); }
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.cc b/components/password_manager/core/browser/password_manager_metrics_util.cc index a7bc2fe..503a9f9 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.cc +++ b/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -199,6 +199,12 @@ SubmittedFormFrame::SUBMITTED_FORM_FRAME_COUNT); } +void LogSyncPasswordHashChange(SyncPasswordHashChange event) { + UMA_HISTOGRAM_ENUMERATION( + "PasswordManager.SyncPasswordHashChange", event, + SyncPasswordHashChange::SAVED_SYNC_PASSWORD_CHANGE_COUNT); +} + } // namespace metrics_util } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h index dc8bdae..a23a9db 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.h +++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -193,6 +193,13 @@ SUBMITTED_FORM_FRAME_COUNT }; +enum class SyncPasswordHashChange { + SAVED_ON_CHROME_SIGNIN, + SAVED_IN_CONTENT_AREA, + CLEARED_ON_CHROME_SIGNOUT, + SAVED_SYNC_PASSWORD_CHANGE_COUNT +}; + // Metrics: "PasswordManager.AccessPasswordInSettings" enum AccessPasswordInSettingsEvent { ACCESS_PASSWORD_VIEWED = 0, @@ -297,6 +304,9 @@ // Log a frame of a submitted password form. void LogSubmittedFormFrame(SubmittedFormFrame frame); +// Log a save sync password change event. +void LogSyncPasswordHashChange(SyncPasswordHashChange event); + } // namespace metrics_util } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_store_signin_notifier.cc b/components/password_manager/core/browser/password_store_signin_notifier.cc index 6b1786a..e874af1 100644 --- a/components/password_manager/core/browser/password_store_signin_notifier.cc +++ b/components/password_manager/core/browser/password_store_signin_notifier.cc
@@ -4,6 +4,7 @@ #include "components/password_manager/core/browser/password_store_signin_notifier.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_store.h" namespace password_manager { @@ -13,11 +14,15 @@ PasswordStoreSigninNotifier::~PasswordStoreSigninNotifier() {} void PasswordStoreSigninNotifier::NotifySignin(const std::string& password) { + metrics_util::LogSyncPasswordHashChange( + metrics_util::SyncPasswordHashChange::SAVED_ON_CHROME_SIGNIN); if (store_) store_->SaveSyncPasswordHash(base::UTF8ToUTF16(password)); } void PasswordStoreSigninNotifier::NotifySignedOut() { + metrics_util::LogSyncPasswordHashChange( + metrics_util::SyncPasswordHashChange::CLEARED_ON_CHROME_SIGNOUT); if (store_) store_->ClearSyncPasswordHash(); }
diff --git a/components/precache/content/precache_manager.cc b/components/precache/content/precache_manager.cc index d9ad0ae9..16283f64 100644 --- a/components/precache/content/precache_manager.cc +++ b/components/precache/content/precache_manager.cc
@@ -65,14 +65,12 @@ const history::HistoryService* const history_service, const data_reduction_proxy::DataReductionProxySettings* data_reduction_proxy_settings, - Delegate* delegate, const base::FilePath& db_path, std::unique_ptr<PrecacheDatabase> precache_database) : browser_context_(browser_context), sync_service_(sync_service), history_service_(history_service), data_reduction_proxy_settings_(data_reduction_proxy_settings), - delegate_(delegate), is_precaching_(false) { precache_database_ = std::move(precache_database); BrowserThread::PostTask( @@ -463,13 +461,6 @@ is_precaching_ = false; } -void PrecacheManager::OnManifestFetched(const std::string& host, - const PrecacheManifest& manifest) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (delegate_) - delegate_->OnManifestFetched(host, manifest); -} - void PrecacheManager::OnHostsReceived( const history::TopHostsList& host_counts) { DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/components/precache/content/precache_manager.h b/components/precache/content/precache_manager.h index 3f678e9..afd5e6c 100644 --- a/components/precache/content/precache_manager.h +++ b/components/precache/content/precache_manager.h
@@ -55,7 +55,6 @@ class PrecacheDatabase; class PrecacheUnfinishedWork; -class PrecacheManifest; extern const char kPrecacheFieldTrialName[]; @@ -74,13 +73,6 @@ public PrecacheFetcher::PrecacheDelegate, public base::SupportsWeakPtr<PrecacheManager> { public: - class Delegate { - public: - // Called when a precache manifest has been successfully fetched and parsed. - virtual void OnManifestFetched(const std::string& host, - const PrecacheManifest& manifest) = 0; - }; - typedef base::Callback<void(bool)> PrecacheCompletionCallback; PrecacheManager(content::BrowserContext* browser_context, @@ -88,7 +80,6 @@ const history::HistoryService* history_service, const data_reduction_proxy::DataReductionProxySettings* data_reduction_proxy_settings, - Delegate* delegate, const base::FilePath& db_path, std::unique_ptr<PrecacheDatabase> precache_database); ~PrecacheManager() override; @@ -162,8 +153,6 @@ // From PrecacheFetcher::PrecacheDelegate. void OnDone() override; - void OnManifestFetched(const std::string& host, - const PrecacheManifest& manifest) override; // Registers the precache synthetic field trial for users whom the precache // task was run recently. |last_precache_time| is the last time precache task @@ -230,10 +219,6 @@ const data_reduction_proxy::DataReductionProxySettings* const data_reduction_proxy_settings_; - // The Delegate corresponding to the browser context. Used to notify the - // browser about a new available manifest. May be null. - Delegate* delegate_; - // The PrecacheFetcher used to precache resources. Should only be used on the // UI thread. std::unique_ptr<PrecacheFetcher> precache_fetcher_;
diff --git a/components/precache/content/precache_manager_unittest.cc b/components/precache/content/precache_manager_unittest.cc index 4c39812..67ef094 100644 --- a/components/precache/content/precache_manager_unittest.cc +++ b/components/precache/content/precache_manager_unittest.cc
@@ -107,12 +107,6 @@ const base::Callback<void(int)>& callback)); }; -class MockPrecacheManagerDelegate : public PrecacheManager::Delegate { - public: - MOCK_METHOD2(OnManifestFetched, - void(const std::string& host, const PrecacheManifest& manifest)); -}; - ACTION_P(ReturnHosts, starting_hosts) { arg1.Run(starting_hosts); } @@ -144,14 +138,12 @@ const history::HistoryService* history_service, const data_reduction_proxy::DataReductionProxySettings* data_reduction_proxy_settings, - Delegate* delegate_, const base::FilePath& db_path, std::unique_ptr<PrecacheDatabase> precache_database) : PrecacheManager(browser_context, sync_service, history_service, data_reduction_proxy_settings, - delegate_, db_path, std::move(precache_database)), control_group_(false) {} @@ -210,8 +202,7 @@ base::FilePath(FILE_PATH_LITERAL("precache_database"))); precache_manager_.reset(new PrecacheManagerUnderTest( &browser_context_, nullptr /* sync_service */, &history_service_, - nullptr /* data_reduction_proxy_settings */, - &precache_manager_delegate_, db_path, + nullptr /* data_reduction_proxy_settings */, db_path, base::WrapUnique(precache_database))); } @@ -255,7 +246,6 @@ net::FakeURLFetcherFactory factory_; TestPrecacheCompletionCallback precache_callback_; testing::NiceMock<MockHistoryService> history_service_; - testing::NiceMock<MockPrecacheManagerDelegate> precache_manager_delegate_; base::HistogramTester histograms_; net::HttpResponseInfo info_; variations::testing::VariationParamsManager variation_params_;
diff --git a/components/precache/core/precache_fetcher.cc b/components/precache/core/precache_fetcher.cc index a17c6ea..00766ad 100644 --- a/components/precache/core/precache_fetcher.cc +++ b/components/precache/core/precache_fetcher.cc
@@ -848,7 +848,6 @@ PrecacheManifest manifest; if (ParseProtoFromFetchResponse(*source.network_url_fetcher(), &manifest)) { - precache_delegate_->OnManifestFetched(source.referrer(), manifest); const base::Optional<std::vector<bool>> resource_bitset = GetResourceBitset(manifest, experiment_id_); const int32_t included_resources_max =
diff --git a/components/precache/core/precache_fetcher.h b/components/precache/core/precache_fetcher.h index b8c937abb..9868d1c0 100644 --- a/components/precache/core/precache_fetcher.h +++ b/components/precache/core/precache_fetcher.h
@@ -128,10 +128,6 @@ // were fetched or not. If the PrecacheFetcher is destroyed before OnDone is // called, then precaching will be canceled and OnDone will not be called. virtual void OnDone() = 0; - - // Called when a precache manifest has been successfully fetched and parsed. - virtual void OnManifestFetched(const std::string& host, - const PrecacheManifest& manifest) = 0; }; // Visible for testing.
diff --git a/components/precache/core/precache_fetcher_unittest.cc b/components/precache/core/precache_fetcher_unittest.cc index e790f95..178e96b 100644 --- a/components/precache/core/precache_fetcher_unittest.cc +++ b/components/precache/core/precache_fetcher_unittest.cc
@@ -118,22 +118,12 @@ on_done_was_called_ = true; } - void OnManifestFetched(const std::string& host, - const PrecacheManifest& manifest) override { - hosts.push_back(host); - } - bool was_on_done_called() const { return on_done_was_called_; } - void clear_manifest_hosts() { hosts.clear(); } - - std::vector<std::string> get_manifest_hosts() const { return hosts; } - private: bool on_done_was_called_; - std::vector<std::string> hosts; }; class MockURLFetcherFactory : public net::URLFetcherFactory { @@ -583,10 +573,6 @@ expected_requested_urls.emplace_back(kGoodResourceURL); EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - - std::vector<std::string> expected_manifest_hosts = { - "good-manifest.com", "forced-starting-url.com"}; - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); histogram.ExpectUniqueSample("Precache.Fetch.PercentCompleted", 100, 1); @@ -673,8 +659,6 @@ EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - std::vector<std::string> expected_manifest_hosts = {"good-manifest.com"}; - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); histogram.ExpectUniqueSample("Precache.Fetch.PercentCompleted", 100, 1); @@ -749,8 +733,6 @@ EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - std::vector<std::string> expected_manifest_hosts = {"good-manifest.com"}; - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); histogram.ExpectUniqueSample("Precache.Fetch.PercentCompleted", 100, 1); @@ -818,7 +800,6 @@ "http://manifest-url-prefix.com/manifest2.com"); EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - EXPECT_TRUE(precache_delegate_.get_manifest_hosts().empty()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); } @@ -853,8 +834,6 @@ EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - std::vector<std::string> expected_manifest_hosts = {"good-manifest.com"}; - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); } @@ -894,8 +873,6 @@ EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - std::vector<std::string> expected_manifest_hosts = {"good-manifest.com"}; - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); } @@ -925,8 +902,6 @@ expected_requested_urls.emplace_back(kGoodManifestURL); EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - std::vector<std::string> expected_manifest_hosts = {"good-manifest.com"}; - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); } @@ -955,8 +930,6 @@ expected_requested_urls.emplace_back(kGoodManifestURL); EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - std::vector<std::string> expected_manifest_hosts = {"good-manifest.com"}; - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); } @@ -993,7 +966,6 @@ expected_requested_urls.emplace_back(kConfigURL); EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - EXPECT_TRUE(precache_delegate_.get_manifest_hosts().empty()); EXPECT_FALSE(precache_delegate_.was_on_done_called()); histogram.ExpectTotalCount("Precache.Fetch.TimeToComplete", 0); @@ -1027,7 +999,6 @@ expected_requested_urls.emplace_back(PRECACHE_CONFIG_SETTINGS_URL); EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - EXPECT_TRUE(precache_delegate_.get_manifest_hosts().empty()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); } @@ -1068,8 +1039,6 @@ expected_requested_urls.push_back(manifest_url); EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - std::vector<std::string> expected_manifest_hosts = {"starting-url.com"}; - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); } @@ -1124,8 +1093,6 @@ EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - std::vector<std::string> expected_manifest_hosts = {"good-manifest.com"}; - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); histogram.ExpectUniqueSample("Precache.Fetch.PercentCompleted", 100, 1); @@ -1185,8 +1152,6 @@ EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - std::vector<std::string> expected_manifest_hosts = {"good-manifest.com"}; - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); histogram.ExpectUniqueSample("Precache.Fetch.PercentCompleted", 100, 1); @@ -1272,8 +1237,6 @@ // reason, we are seeing it fetch all but 4 resources. Meh, close enough. EXPECT_EQ(1 + 1 + kNumResources - 4, url_callback_.requested_urls().size()); - std::vector<std::string> expected_manifest_hosts = {"good-manifest.com"}; - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); histogram.ExpectTotalCount("Precache.Fetch.PercentCompleted", 1); @@ -1296,7 +1259,6 @@ PrecacheConfigurationSettings config; std::vector<GURL> expected_requested_urls; - std::vector<std::string> expected_manifest_hosts; config.set_top_sites_count(kNumTopHosts); factory_.SetFakeResponse(GURL(kConfigURL), config.SerializeAsString(), @@ -1310,7 +1272,6 @@ for (size_t i = 0; i < kNumTopHosts; ++i) { const std::string top_host_url = base::StringPrintf("top-host-%zu.com", i); expected_requested_urls.emplace_back(kManifestURLPrefix + top_host_url); - expected_manifest_hosts.push_back(top_host_url); } for (size_t i = 0; i < kNumTopHosts; ++i) { @@ -1352,7 +1313,6 @@ EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); histogram.ExpectUniqueSample("Precache.Fetch.PercentCompleted", 100, 1); @@ -1389,7 +1349,6 @@ // The config is fetched, but not the invalid manifest URL. EXPECT_EQ(1UL, url_callback_.requested_urls().size()); - EXPECT_TRUE(precache_delegate_.get_manifest_hosts().empty()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); // manifest.com will have been failed to complete, in this case. @@ -1430,8 +1389,6 @@ // The config and manifest are fetched, but not the invalid resource URL. EXPECT_EQ(2UL, url_callback_.requested_urls().size()); - std::vector<std::string> expected_manifest_hosts = {"bad-manifest.com"}; - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); // bad-manifest.com will have been completed. @@ -1596,7 +1553,6 @@ const size_t kNumResources = 5; std::vector<GURL> expected_requested_urls; - std::vector<std::string> expected_manifest_hosts; PrecacheConfigurationSettings config; config.set_top_sites_count(kNumTopHosts); @@ -1613,7 +1569,6 @@ for (size_t i = 0; i < kNumTopHosts; ++i) { const std::string top_host_url = base::StringPrintf("top-host-%zu.com", i); expected_requested_urls.emplace_back(kManifestURLPrefix + top_host_url); - expected_manifest_hosts.push_back(top_host_url); } // Visit counts and weights are chosen in such a way that resource requests @@ -1662,7 +1617,6 @@ } EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); } @@ -1679,7 +1633,6 @@ const size_t kNumResources = 5; std::vector<GURL> expected_requested_urls; - std::vector<std::string> expected_manifest_hosts; PrecacheConfigurationSettings config; config.set_top_sites_count(kNumTopHosts); @@ -1696,7 +1649,6 @@ std::vector<std::pair<std::string, float>> resources; for (size_t i = 0; i < kNumTopHosts; ++i) { const std::string top_host_url = base::StringPrintf("top-host-%zu.com", i); - expected_manifest_hosts.push_back(top_host_url); TopHost* top_host = unfinished_work->add_top_host(); top_host->set_hostname(top_host_url); top_host->set_visits(kNumTopHosts - i); @@ -1760,11 +1712,9 @@ EXPECT_TRUE(cancelled_work->top_host().empty()); EXPECT_EQ(kNumTopHosts * kNumResources, static_cast<size_t>(cancelled_work->resource().size())); - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_FALSE(precache_delegate_.was_on_done_called()); url_callback_.clear_requested_urls(); - precache_delegate_.clear_manifest_hosts(); // Continuing with the precache should fetch all resources, as the previous // run was cancelled before any finished. They should be fetched in global @@ -1782,7 +1732,6 @@ base::RunLoop().RunUntilIdle(); } EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - EXPECT_TRUE(precache_delegate_.get_manifest_hosts().empty()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); histogram.ExpectBucketCount("Precache.Fetch.MinWeight", @@ -1795,7 +1744,6 @@ const size_t kNumResources = 5; std::vector<GURL> expected_requested_urls; - std::vector<std::string> expected_manifest_hosts; PrecacheConfigurationSettings config; config.set_total_resources_count(2); @@ -1814,8 +1762,6 @@ expected_requested_urls.emplace_back(kManifestURLPrefix + top_host->hostname()); - expected_manifest_hosts.push_back(top_host->hostname()); - PrecacheManifest manifest; for (size_t i = 0; i < kNumResources; ++i) { const float weight = 1 - static_cast<float>(i) / kNumResources; @@ -1846,7 +1792,6 @@ } EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); const float expected_min_weight = @@ -1861,7 +1806,6 @@ const size_t kNumResources = 5; std::vector<GURL> expected_requested_urls; - std::vector<std::string> expected_manifest_hosts; PrecacheConfigurationSettings config; config.set_min_weight(3); @@ -1880,7 +1824,6 @@ expected_requested_urls.emplace_back(kManifestURLPrefix + top_host->hostname()); - expected_manifest_hosts.push_back(top_host->hostname()); PrecacheManifest manifest; for (size_t i = 0; i < kNumResources; ++i) { @@ -1911,7 +1854,6 @@ } EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); } @@ -1925,7 +1867,6 @@ PrecacheConfigurationSettings config; std::vector<GURL> expected_requested_urls; - std::vector<std::string> expected_manifest_hosts; std::unique_ptr<PrecacheUnfinishedWork> cancelled_work; config.set_top_sites_count(kNumTopHosts); @@ -1940,7 +1881,6 @@ for (size_t i = 0; i < kNumTopHosts; ++i) { const std::string top_host_url = base::StringPrintf("top-host-%zu.com", i); expected_requested_urls.emplace_back(kManifestURLPrefix + top_host_url); - expected_manifest_hosts.push_back(top_host_url); } int num_resources = 0; @@ -2000,14 +1940,12 @@ static_cast<size_t>(cancelled_work->resource().size())); EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_FALSE(precache_delegate_.was_on_done_called()); // Continuing with the precache should fetch all resources, as the previous // run was cancelled before any finished. expected_requested_urls.clear(); url_callback_.clear_requested_urls(); - precache_delegate_.clear_manifest_hosts(); for (size_t i = 0; i < kNumTopHosts; ++i) { for (size_t j = 0; j < kNumResources; ++j) { expected_requested_urls.emplace_back( @@ -2024,7 +1962,6 @@ base::RunLoop().RunUntilIdle(); } EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - EXPECT_TRUE(precache_delegate_.get_manifest_hosts().empty()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); } @@ -2043,14 +1980,12 @@ factory_.SetFakeResponse(GURL(kConfigURL), config.SerializeAsString(), net::HTTP_OK, net::URLRequestStatus::SUCCESS); std::vector<GURL> expected_requested_urls; - std::vector<std::string> expected_manifest_hosts; expected_requested_urls.emplace_back(kConfigURL); for (size_t i = 0; i < kNumTopHosts; ++i) { const std::string top_host_url = base::StringPrintf("top-host-%zu.com", i); expected_requested_urls.emplace_back(std::string(kManifestURLPrefix) + top_host_url); - expected_manifest_hosts.push_back(top_host_url); } for (size_t i = 0; i < kNumTopHosts; ++i) { @@ -2088,7 +2023,6 @@ } EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - EXPECT_EQ(expected_manifest_hosts, precache_delegate_.get_manifest_hosts()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); EXPECT_EQ(0, unfinished_work->top_host_size()); @@ -2102,7 +2036,6 @@ // any resources. expected_requested_urls.clear(); url_callback_.clear_requested_urls(); - precache_delegate_.clear_manifest_hosts(); { PrecacheFetcher precache_fetcher( request_context_.get(), GURL(), std::string(), @@ -2114,7 +2047,6 @@ EXPECT_EQ(0U, precache_fetcher.quota_.remaining()); } EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls()); - EXPECT_TRUE(precache_delegate_.get_manifest_hosts().empty()); EXPECT_TRUE(precache_delegate_.was_on_done_called()); histogram.ExpectTotalCount("Precache.Fetch.PercentCompleted", 2);
diff --git a/components/signin/core/browser/android/BUILD.gn b/components/signin/core/browser/android/BUILD.gn index d9dda3e..96540483 100644 --- a/components/signin/core/browser/android/BUILD.gn +++ b/components/signin/core/browser/android/BUILD.gn
@@ -22,6 +22,7 @@ java_files = [ "java/src/org/chromium/components/signin/AccountManagerDelegate.java", "java/src/org/chromium/components/signin/AccountManagerHelper.java", + "java/src/org/chromium/components/signin/AccountsChangeObserver.java", "java/src/org/chromium/components/signin/AuthException.java", "java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java", "java/src/org/chromium/components/signin/ChromeSigninController.java",
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java index 004d68c..15666713 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java
@@ -8,6 +8,7 @@ import android.accounts.AuthenticatorDescription; import android.app.Activity; import android.support.annotation.AnyThread; +import android.support.annotation.MainThread; import android.support.annotation.Nullable; import android.support.annotation.WorkerThread; @@ -19,6 +20,20 @@ */ public interface AccountManagerDelegate { /** + * Adds an observer to get notified about accounts changes. + * @param observer the observer to add. + */ + @MainThread + void addObserver(AccountsChangeObserver observer); + + /** + * Removes an observer that was previously added using {@link #addObserver}. + * @param observer the observer to remove. + */ + @MainThread + void removeObserver(AccountsChangeObserver observer); + + /** * Get all the accounts for a given {@code type}. * This is deprecated an will be removed soon. */
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java index 2b08786c..9692855 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java
@@ -73,6 +73,26 @@ } /** + * Adds an observer to receive accounts change notifications. + * @param observer the observer to add. + */ + @MainThread + public void addObserver(AccountsChangeObserver observer) { + ThreadUtils.assertOnUiThread(); + mDelegate.addObserver(observer); + } + + /** + * Removes an observer that was previously added using {@link #addObserver}. + * @param observer the observer to remove. + */ + @MainThread + public void removeObserver(AccountsChangeObserver observer) { + ThreadUtils.assertOnUiThread(); + mDelegate.removeObserver(observer); + } + + /** * @param delegate the account manager to use as a backend service */ private AccountManagerHelper(AccountManagerDelegate delegate) {
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountsChangeObserver.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountsChangeObserver.java new file mode 100644 index 0000000..370403a --- /dev/null +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountsChangeObserver.java
@@ -0,0 +1,20 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.signin; + +import android.support.annotation.MainThread; + +/** + * Observer that receives account change notifications. Use {@link AccountManagerHelper#addObserver} + * and {@link AccountManagerHelper#removeObserver} to update registrations. + */ +public interface AccountsChangeObserver { + /** + * Called on every change to the accounts or to the error condition that occurred while getting + * accounts. + */ + @MainThread + void onAccountsChanged(); +}
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java index f1231936..9bc930ab 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java
@@ -13,6 +13,10 @@ import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; @@ -27,6 +31,7 @@ import org.chromium.base.Callback; import org.chromium.base.ContextUtils; import org.chromium.base.Log; +import org.chromium.base.ObserverList; import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.MainDex; import org.chromium.base.library_loader.LibraryLoader; @@ -42,10 +47,33 @@ @MainDex public class SystemAccountManagerDelegate implements AccountManagerDelegate { private final AccountManager mAccountManager; + private final ObserverList<AccountsChangeObserver> mObservers = new ObserverList<>(); + private static final String TAG = "Auth"; public SystemAccountManagerDelegate() { mAccountManager = AccountManager.get(ContextUtils.getApplicationContext()); + + BroadcastReceiver accountsChangedBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(final Context context, final Intent intent) { + fireOnAccountsChangedNotification(); + } + }; + IntentFilter accountsChangedIntentFilter = new IntentFilter(); + accountsChangedIntentFilter.addAction(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION); + ContextUtils.getApplicationContext().registerReceiver( + accountsChangedBroadcastReceiver, accountsChangedIntentFilter); + } + + @Override + public void addObserver(AccountsChangeObserver observer) { + mObservers.addObserver(observer); + } + + @Override + public void removeObserver(AccountsChangeObserver observer) { + mObservers.removeObserver(observer); } @Override @@ -57,6 +85,10 @@ Account[] accounts = mAccountManager.getAccountsByType(type); long elapsed = SystemClock.elapsedRealtime() - now; recordElapsedTimeHistogram("Signin.AndroidGetAccountsTime_AccountManager", elapsed); + if (ThreadUtils.runningOnUiThread()) { + recordElapsedTimeHistogram( + "Signin.AndroidGetAccountsTimeUiThread_AccountManager", elapsed); + } return accounts; } @@ -182,4 +214,10 @@ "android.permission.MANAGE_ACCOUNTS", Process.myPid(), Process.myUid()) == PackageManager.PERMISSION_GRANTED; } + + private void fireOnAccountsChangedNotification() { + for (AccountsChangeObserver observer : mObservers) { + observer.onAccountsChanged(); + } + } }
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java index d61073e84..804d3b4 100644 --- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java +++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java
@@ -13,11 +13,13 @@ import org.chromium.base.Callback; import org.chromium.base.Log; +import org.chromium.base.ObserverList; import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; import org.chromium.components.signin.AccountManagerDelegate; import org.chromium.components.signin.AccountManagerDelegateException; import org.chromium.components.signin.AccountManagerHelper; +import org.chromium.components.signin.AccountsChangeObserver; import java.util.ArrayList; import java.util.HashSet; @@ -44,6 +46,7 @@ private final Context mContext; private final Set<AccountHolder> mAccounts = new HashSet<>(); + private final ObserverList<AccountsChangeObserver> mObservers = new ObserverList<>(); @VisibleForTesting public FakeAccountManagerDelegate(Context context, Account... accounts) { @@ -56,6 +59,16 @@ } @Override + public void addObserver(AccountsChangeObserver observer) { + mObservers.addObserver(observer); + } + + @Override + public void removeObserver(AccountsChangeObserver observer) { + mObservers.removeObserver(observer); + } + + @Override public Account[] getAccountsByType(String type) { if (!AccountManagerHelper.GOOGLE_ACCOUNT_TYPE.equals(type)) { throw new IllegalArgumentException("Invalid account type: " + type); @@ -90,6 +103,9 @@ public void addAccountHolderExplicitly(AccountHolder accountHolder) { boolean added = mAccounts.add(accountHolder); Assert.assertTrue("Account was already added", added); + for (AccountsChangeObserver observer : mObservers) { + observer.onAccountsChanged(); + } } /** @@ -100,6 +116,9 @@ public void removeAccountHolderExplicitly(AccountHolder accountHolder) { boolean removed = mAccounts.remove(accountHolder); Assert.assertTrue("Account was already added", removed); + for (AccountsChangeObserver observer : mObservers) { + observer.onAccountsChanged(); + } } @Override
diff --git a/components/signin/core/browser/signin_tracker.cc b/components/signin/core/browser/signin_tracker.cc index b13365d..24e23983 100644 --- a/components/signin/core/browser/signin_tracker.cc +++ b/components/signin/core/browser/signin_tracker.cc
@@ -32,6 +32,12 @@ cookie_manager_service_->AddObserver(this); } +void SigninTracker::GoogleSigninSucceeded(const std::string& account_id, + const std::string& username) { + if (token_service_->RefreshTokenIsAvailable(account_id)) + observer_->SigninSuccess(); +} + void SigninTracker::GoogleSigninFailed(const GoogleServiceAuthError& error) { observer_->SigninFailed(error); }
diff --git a/components/signin/core/browser/signin_tracker.h b/components/signin/core/browser/signin_tracker.h index cabbedf..e433df587 100644 --- a/components/signin/core/browser/signin_tracker.h +++ b/components/signin/core/browser/signin_tracker.h
@@ -80,6 +80,8 @@ ~SigninTracker() override; // SigninManagerBase::Observer implementation. + void GoogleSigninSucceeded(const std::string& account_id, + const std::string& username) override; void GoogleSigninFailed(const GoogleServiceAuthError& error) override; // OAuth2TokenService::Observer implementation.
diff --git a/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc b/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc index b7c3ff8..717527d3 100644 --- a/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc +++ b/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
@@ -21,7 +21,6 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" -#include "content/public/common/content_switches.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/cache_test_util.h" #include "content/public/test/content_browser_test.h" @@ -153,8 +152,6 @@ public: void SetUpCommandLine(base::CommandLine* command_line) override { ContentBrowserTest::SetUpCommandLine(command_line); - command_line->AppendSwitch( - switches::kEnableExperimentalWebPlatformFeatures); // We're redirecting all hosts to localhost even on HTTPS, so we'll get // certificate errors.
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index 88185f1..f6d1b57 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -87,7 +87,6 @@ #include "content/public/browser/stream_info.h" #include "content/public/common/browser_side_navigation_policy.h" #include "content/public/common/content_features.h" -#include "content/public/common/content_switches.h" #include "content/public/common/resource_request.h" #include "content/public/common/resource_request_body.h" #include "content/public/common/resource_request_completion_status.h" @@ -347,10 +346,7 @@ allow_cross_origin_auth_prompt_(false), create_download_handler_intercept_(download_handler_intercept), main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), - io_thread_task_runner_(io_thread_runner), - experimental_web_features_enabled_( - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableExperimentalWebPlatformFeatures)) { + io_thread_task_runner_(io_thread_runner) { DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); DCHECK(!g_resource_dispatcher_host); g_resource_dispatcher_host = this; @@ -1603,13 +1599,11 @@ base::MakeUnique<WakeLockResourceThrottle>(request->url().host())); } - // The experimental Clear-Site-Data throttle. - if (experimental_web_features_enabled_) { - std::unique_ptr<ResourceThrottle> clear_site_data_throttle = - ClearSiteDataThrottle::MaybeCreateThrottleForRequest(request); - if (clear_site_data_throttle) - throttles.push_back(std::move(clear_site_data_throttle)); - } + // The Clear-Site-Data throttle. + std::unique_ptr<ResourceThrottle> clear_site_data_throttle = + ClearSiteDataThrottle::MaybeCreateThrottleForRequest(request); + if (clear_site_data_throttle) + throttles.push_back(std::move(clear_site_data_throttle)); // TODO(ricea): Stop looking this up so much. ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request);
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h index 0b3d32c..2b95db9 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.h +++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -830,9 +830,6 @@ // Task runner for the IO thead. scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_; - // Whether experimental web platform features are enabled. - bool experimental_web_features_enabled_; - DISALLOW_COPY_AND_ASSIGN(ResourceDispatcherHostImpl); };
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc index 77b4cd77..a92a970 100644 --- a/content/browser/service_worker/embedded_worker_test_helper.cc +++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -298,7 +298,8 @@ new MockServiceWorkerDatabaseTaskManager( base::ThreadTaskRunnerHandle::Get())); wrapper_->InitInternal(user_data_directory, std::move(database_task_manager), - base::ThreadTaskRunnerHandle::Get(), nullptr, nullptr); + base::ThreadTaskRunnerHandle::Get(), nullptr, nullptr, + nullptr, nullptr); wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id()); wrapper_->process_manager()->SetNewProcessIdForTest(new_render_process_id());
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc index 751da4a..9933f3c 100644 --- a/content/browser/service_worker/service_worker_context_core.cc +++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -33,11 +33,13 @@ #include "content/browser/service_worker/service_worker_registration.h" #include "content/browser/service_worker/service_worker_storage.h" #include "content/browser/service_worker/service_worker_version.h" +#include "content/browser/url_loader_factory_getter.h" #include "content/common/service_worker/service_worker_utils.h" #include "content/public/browser/browser_thread.h" #include "ipc/ipc_message.h" #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" +#include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "url/gurl.h" @@ -239,12 +241,16 @@ const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread, storage::QuotaManagerProxy* quota_manager_proxy, storage::SpecialStoragePolicy* special_storage_policy, + base::WeakPtr<storage::BlobStorageContext> blob_storage_context, + URLLoaderFactoryGetter* url_loader_factory_getter, base::ObserverListThreadSafe<ServiceWorkerContextCoreObserver>* observer_list, ServiceWorkerContextWrapper* wrapper) : wrapper_(wrapper), providers_(base::MakeUnique<ProcessToProviderMap>()), provider_by_uuid_(base::MakeUnique<ProviderByClientUUIDMap>()), + blob_storage_context_(std::move(blob_storage_context)), + loader_factory_getter_(url_loader_factory_getter), force_update_on_page_load_(false), next_handle_id_(0), next_registration_handle_id_(0),
diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h index 29120b0..62d6a42 100644 --- a/content/browser/service_worker/service_worker_context_core.h +++ b/content/browser/service_worker/service_worker_context_core.h
@@ -35,6 +35,7 @@ } namespace storage { +class BlobStorageContext; class QuotaManagerProxy; class SpecialStoragePolicy; } @@ -51,6 +52,7 @@ class ServiceWorkerProviderHost; class ServiceWorkerRegistration; class ServiceWorkerStorage; +class URLLoaderFactoryGetter; // This class manages data associated with service workers. // The class is single threaded and should only be used on the IO thread. @@ -111,6 +113,8 @@ // ServiceWorkerContextWrapper. When Notify() of |observer_list| is called in // ServiceWorkerContextCore, the methods of ServiceWorkerContextCoreObserver // will be called on the thread which called AddObserver() of |observer_list|. + // |blob_context| and |url_loader_factory_getter| are used only + // when IsServicificationEnabled is true. ServiceWorkerContextCore( const base::FilePath& user_data_directory, std::unique_ptr<ServiceWorkerDatabaseTaskManager> @@ -118,6 +122,8 @@ const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread, storage::QuotaManagerProxy* quota_manager_proxy, storage::SpecialStoragePolicy* special_storage_policy, + base::WeakPtr<storage::BlobStorageContext> blob_context, + URLLoaderFactoryGetter* url_loader_factory_getter, base::ObserverListThreadSafe<ServiceWorkerContextCoreObserver>* observer_list, ServiceWorkerContextWrapper* wrapper); @@ -307,6 +313,14 @@ int service_worker_provider_id, mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info); + base::WeakPtr<storage::BlobStorageContext> blob_storage_context() { + return blob_storage_context_; + } + + URLLoaderFactoryGetter* loader_factory_getter() { + return loader_factory_getter_.get(); + } + base::WeakPtr<ServiceWorkerContextCore> AsWeakPtr() { return weak_factory_.GetWeakPtr(); } @@ -380,6 +394,10 @@ std::map<int, ServiceWorkerNavigationHandleCore*> navigation_handle_cores_map_; + // IsServicificationEnabled + base::WeakPtr<storage::BlobStorageContext> blob_storage_context_; + scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_; + bool force_update_on_page_load_; int next_handle_id_; int next_registration_handle_id_;
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index 1c6f549..9b33159 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -31,6 +31,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/service_worker_context_observer.h" #include "net/base/url_util.h" +#include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/quota/special_storage_policy.h" @@ -183,7 +184,9 @@ void ServiceWorkerContextWrapper::Init( const base::FilePath& user_data_directory, storage::QuotaManagerProxy* quota_manager_proxy, - storage::SpecialStoragePolicy* special_storage_policy) { + storage::SpecialStoragePolicy* special_storage_policy, + ChromeBlobStorageContext* blob_context, + URLLoaderFactoryGetter* loader_factory_getter) { DCHECK_CURRENTLY_ON(BrowserThread::UI); is_incognito_ = user_data_directory.empty(); @@ -193,7 +196,8 @@ scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread = BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE); InitInternal(user_data_directory, std::move(database_task_manager), - disk_cache_thread, quota_manager_proxy, special_storage_policy); + disk_cache_thread, quota_manager_proxy, special_storage_policy, + blob_context, loader_factory_getter); } void ServiceWorkerContextWrapper::Shutdown() { @@ -842,14 +846,18 @@ std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager, const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread, storage::QuotaManagerProxy* quota_manager_proxy, - storage::SpecialStoragePolicy* special_storage_policy) { + storage::SpecialStoragePolicy* special_storage_policy, + ChromeBlobStorageContext* blob_context, + URLLoaderFactoryGetter* loader_factory_getter) { if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&ServiceWorkerContextWrapper::InitInternal, this, user_data_directory, base::Passed(&database_task_manager), disk_cache_thread, base::RetainedRef(quota_manager_proxy), - base::RetainedRef(special_storage_policy))); + base::RetainedRef(special_storage_policy), + base::RetainedRef(blob_context), + base::RetainedRef(loader_factory_getter))); return; } // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed. @@ -860,10 +868,15 @@ if (quota_manager_proxy) { quota_manager_proxy->RegisterClient(new ServiceWorkerQuotaClient(this)); } + + base::WeakPtr<storage::BlobStorageContext> blob_storage_context = + (blob_context && blob_context->context()) + ? blob_context->context()->AsWeakPtr() + : nullptr; context_core_.reset(new ServiceWorkerContextCore( user_data_directory, std::move(database_task_manager), disk_cache_thread, - quota_manager_proxy, special_storage_policy, core_observer_list_.get(), - this)); + quota_manager_proxy, special_storage_policy, blob_storage_context, + loader_factory_getter, core_observer_list_.get(), this)); } void ServiceWorkerContextWrapper::ShutdownOnIO() {
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h index 71f341d..5d871cd4 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.h +++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -34,9 +34,11 @@ namespace content { class BrowserContext; +class ChromeBlobStorageContext; class ResourceContext; class ServiceWorkerContextObserver; class StoragePartitionImpl; +class URLLoaderFactoryGetter; // A refcounted wrapper class for our core object. Higher level content lib // classes keep references to this class on mutliple threads. The inner core @@ -61,9 +63,13 @@ // Init and Shutdown are for use on the UI thread when the profile, // storagepartition is being setup and torn down. + // |blob_context| and |url_loader_factory_getter| are used only + // when IsServicificationEnabled is true. void Init(const base::FilePath& user_data_directory, storage::QuotaManagerProxy* quota_manager_proxy, - storage::SpecialStoragePolicy* special_storage_policy); + storage::SpecialStoragePolicy* special_storage_policy, + ChromeBlobStorageContext* blob_context, + URLLoaderFactoryGetter* url_loader_factory_getter); void Shutdown(); // Must be called on the IO thread. @@ -273,7 +279,9 @@ std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager, const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread, storage::QuotaManagerProxy* quota_manager_proxy, - storage::SpecialStoragePolicy* special_storage_policy); + storage::SpecialStoragePolicy* special_storage_policy, + ChromeBlobStorageContext* blob_context, + URLLoaderFactoryGetter* url_loader_factory_getter); void ShutdownOnIO(); void DidFindRegistrationForFindReady(
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc index 0cb948b..46ab2ab81 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -981,9 +981,11 @@ } } -void ServiceWorkerDispatcherHost::OnSetHostedVersionId(int provider_id, - int64_t version_id, - int embedded_worker_id) { +void ServiceWorkerDispatcherHost::OnSetHostedVersionId( + int provider_id, + int64_t version_id, + int embedded_worker_id, + mojom::URLLoaderFactoryAssociatedRequest request) { TRACE_EVENT0("ServiceWorker", "ServiceWorkerDispatcherHost::OnSetHostedVersionId"); if (!GetContext()) @@ -1044,6 +1046,9 @@ provider_host->SetHostedVersion(version); + if (ServiceWorkerUtils::IsServicificationEnabled()) + provider_host->CreateScriptURLLoaderFactory(std::move(request)); + // Retrieve the registration associated with |version|. The registration // must be alive because the version keeps it during starting worker. ServiceWorkerRegistration* registration =
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h index 3af8eed..a11901c 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.h +++ b/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -20,6 +20,7 @@ #include "content/common/service_worker/service_worker_types.h" #include "content/public/browser/browser_associated_interface.h" #include "content/public/browser/browser_message_filter.h" +#include "mojo/public/cpp/bindings/strong_associated_binding_set.h" class GURL; @@ -119,9 +120,11 @@ // mojom::ServiceWorkerDispatcherHost implementation void OnProviderCreated(ServiceWorkerProviderHostInfo info) override; - void OnSetHostedVersionId(int provider_id, - int64_t version_id, - int embedded_worker_id) override; + void OnSetHostedVersionId( + int provider_id, + int64_t version_id, + int embedded_worker_id, + mojom::URLLoaderFactoryAssociatedRequest request) override; // IPC Message handlers void OnRegisterServiceWorker(int thread_id,
diff --git a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc index 0ebbc82..2faeab1 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -200,7 +200,7 @@ int64_t version_id, int embedded_worker_id) { dispatcher_host_->OnSetHostedVersionId(provider_id, version_id, - embedded_worker_id); + embedded_worker_id, nullptr); } void SendProviderCreated(ServiceWorkerProviderType type,
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc index 33b03804..2a40898 100644 --- a/content/browser/service_worker/service_worker_provider_host.cc +++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -19,6 +19,7 @@ #include "content/browser/service_worker/service_worker_handle.h" #include "content/browser/service_worker/service_worker_registration_handle.h" #include "content/browser/service_worker/service_worker_version.h" +#include "content/browser/url_loader_factory_getter.h" #include "content/common/service_worker/service_worker_messages.h" #include "content/common/service_worker/service_worker_types.h" #include "content/common/service_worker/service_worker_utils.h" @@ -31,6 +32,7 @@ #include "content/public/common/resource_request_body.h" #include "mojo/public/cpp/bindings/strong_associated_binding.h" #include "net/base/url_util.h" +#include "storage/browser/blob/blob_storage_context.h" namespace content { @@ -96,6 +98,155 @@ context->RemoveProviderHost(process_id, provider_id); } +// Used by a Service Worker for script loading (for all script loading for now, +// but to be used only during installation once script streaming lands). +// For now this is just a proxy loader for the network loader. +// Eventually this should replace the existing URLRequestJob-based request +// interception for script loading, namely ServiceWorkerWriteToCacheJob. +// TODO(kinuko): Implement this. Hook up the existing code in +// ServiceWorkerContextRequestHandler. +class ScriptURLLoader : public mojom::URLLoader, public mojom::URLLoaderClient { + public: + ScriptURLLoader( + int32_t routing_id, + int32_t request_id, + uint32_t options, + const ResourceRequest& resource_request, + mojom::URLLoaderClientPtr client, + base::WeakPtr<ServiceWorkerContextCore> context, + base::WeakPtr<ServiceWorkerProviderHost> provider_host, + base::WeakPtr<storage::BlobStorageContext> blob_storage_context, + scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter, + const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) + : network_client_binding_(this), + forwarding_client_(std::move(client)), + provider_host_(provider_host) { + mojom::URLLoaderClientPtr network_client; + network_client_binding_.Bind(mojo::MakeRequest(&network_client)); + loader_factory_getter->GetNetworkFactory()->get()->CreateLoaderAndStart( + mojo::MakeRequest(&network_loader_), routing_id, request_id, options, + resource_request, std::move(network_client), traffic_annotation); + } + ~ScriptURLLoader() override {} + + // mojom::URLLoader: + void FollowRedirect() override { network_loader_->FollowRedirect(); } + void SetPriority(net::RequestPriority priority, + int32_t intra_priority_value) override { + network_loader_->SetPriority(priority, intra_priority_value); + } + + // mojom::URLLoaderClient for simply proxying network: + void OnReceiveResponse( + const ResourceResponseHead& response_head, + const base::Optional<net::SSLInfo>& ssl_info, + mojom::DownloadedTempFilePtr downloaded_file) override { + if (provider_host_) { + // We don't have complete info here, but fill in what we have now. + // At least we need headers and SSL info. + net::HttpResponseInfo response_info; + response_info.headers = response_head.headers; + if (ssl_info.has_value()) + response_info.ssl_info = *ssl_info; + response_info.was_fetched_via_spdy = response_head.was_fetched_via_spdy; + response_info.was_alpn_negotiated = response_head.was_alpn_negotiated; + response_info.alpn_negotiated_protocol = + response_head.alpn_negotiated_protocol; + response_info.connection_info = response_head.connection_info; + response_info.socket_address = response_head.socket_address; + + DCHECK(provider_host_->IsHostToRunningServiceWorker()); + provider_host_->running_hosted_version()->SetMainScriptHttpResponseInfo( + response_info); + } + forwarding_client_->OnReceiveResponse(response_head, ssl_info, + std::move(downloaded_file)); + } + void OnReceiveRedirect(const net::RedirectInfo& redirect_info, + const ResourceResponseHead& response_head) override { + forwarding_client_->OnReceiveRedirect(redirect_info, response_head); + } + void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override { + forwarding_client_->OnDataDownloaded(data_len, encoded_data_len); + } + void OnUploadProgress(int64_t current_position, + int64_t total_size, + OnUploadProgressCallback ack_callback) override { + forwarding_client_->OnUploadProgress(current_position, total_size, + std::move(ack_callback)); + } + void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override { + forwarding_client_->OnReceiveCachedMetadata(data); + } + void OnTransferSizeUpdated(int32_t transfer_size_diff) override { + forwarding_client_->OnTransferSizeUpdated(transfer_size_diff); + } + void OnStartLoadingResponseBody( + mojo::ScopedDataPipeConsumerHandle body) override { + forwarding_client_->OnStartLoadingResponseBody(std::move(body)); + } + void OnComplete(const ResourceRequestCompletionStatus& status) override { + forwarding_client_->OnComplete(status); + } + + private: + mojom::URLLoaderAssociatedPtr network_loader_; + mojo::Binding<mojom::URLLoaderClient> network_client_binding_; + mojom::URLLoaderClientPtr forwarding_client_; + base::WeakPtr<ServiceWorkerProviderHost> provider_host_; + + DISALLOW_COPY_AND_ASSIGN(ScriptURLLoader); +}; + +// Created per one controller worker for script loading (only during +// installation, eventually). This is kept alive while +// ServiceWorkerNetworkProvider in the renderer process is alive. +// Used only when IsServicificationEnabled is true. +class ScriptURLLoaderFactory : public mojom::URLLoaderFactory { + public: + ScriptURLLoaderFactory( + base::WeakPtr<ServiceWorkerContextCore> context, + base::WeakPtr<ServiceWorkerProviderHost> provider_host, + base::WeakPtr<storage::BlobStorageContext> blob_storage_context, + scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter) + : context_(context), + provider_host_(provider_host), + blob_storage_context_(blob_storage_context), + loader_factory_getter_(loader_factory_getter) {} + ~ScriptURLLoaderFactory() override {} + + // mojom::URLLoaderFactory: + void CreateLoaderAndStart(mojom::URLLoaderAssociatedRequest request, + int32_t routing_id, + int32_t request_id, + uint32_t options, + const ResourceRequest& resource_request, + mojom::URLLoaderClientPtr client, + const net::MutableNetworkTrafficAnnotationTag& + traffic_annotation) override { + mojo::MakeStrongAssociatedBinding( + base::MakeUnique<ScriptURLLoader>( + routing_id, request_id, options, resource_request, + std::move(client), context_, provider_host_, blob_storage_context_, + loader_factory_getter_, traffic_annotation), + std::move(request)); + } + + void SyncLoad(int32_t routing_id, + int32_t request_id, + const ResourceRequest& request, + SyncLoadCallback callback) override { + NOTREACHED(); + } + + private: + base::WeakPtr<ServiceWorkerContextCore> context_; + base::WeakPtr<ServiceWorkerProviderHost> provider_host_; + base::WeakPtr<storage::BlobStorageContext> blob_storage_context_; + scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_; + DISALLOW_COPY_AND_ASSIGN(ScriptURLLoaderFactory); +}; + } // anonymous namespace ServiceWorkerProviderHost::OneShotGetReadyCallback::OneShotGetReadyCallback( @@ -332,6 +483,16 @@ running_hosted_version_ = version; } +void ServiceWorkerProviderHost::CreateScriptURLLoaderFactory( + mojom::URLLoaderFactoryAssociatedRequest script_loader_factory_request) { + DCHECK(ServiceWorkerUtils::IsServicificationEnabled()); + mojo::MakeStrongAssociatedBinding( + base::MakeUnique<ScriptURLLoaderFactory>( + context_, AsWeakPtr(), context_->blob_storage_context(), + context_->loader_factory_getter()), + std::move(script_loader_factory_request)); +} + bool ServiceWorkerProviderHost::IsProviderForClient() const { switch (info_.type) { case SERVICE_WORKER_PROVIDER_FOR_WINDOW: @@ -566,6 +727,7 @@ std::unique_ptr<ServiceWorkerProviderHost> ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() { DCHECK(!IsBrowserSideNavigationEnabled()); + DCHECK(!ServiceWorkerUtils::IsServicificationEnabled()); DCHECK_NE(ChildProcessHost::kInvalidUniqueID, render_process_id_); DCHECK_NE(MSG_ROUTING_NONE, info_.route_id); DCHECK_EQ(kDocumentMainThreadId, render_thread_id_); @@ -599,6 +761,7 @@ void ServiceWorkerProviderHost::CompleteCrossSiteTransfer( ServiceWorkerProviderHost* provisional_host) { DCHECK(!IsBrowserSideNavigationEnabled()); + DCHECK(!ServiceWorkerUtils::IsServicificationEnabled()); DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_); DCHECK_NE(ChildProcessHost::kInvalidUniqueID, provisional_host->process_id()); DCHECK_NE(MSG_ROUTING_NONE, provisional_host->frame_id());
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h index 2229000..a71839a 100644 --- a/content/browser/service_worker/service_worker_provider_host.h +++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -203,6 +203,12 @@ void SetHostedVersion(ServiceWorkerVersion* version); + // Creates a per-controller-worker URLLoaderFactory for script loading. + // The created factory is kept alive while the controller worker is alive. + // Used only when IsServicificationEnabled is true. + void CreateScriptURLLoaderFactory( + mojom::URLLoaderFactoryAssociatedRequest script_loader_factory_request); + // Returns a handler for a request, the handler may return NULL if // the request doesn't require special handling. std::unique_ptr<ServiceWorkerRequestHandler> CreateRequestHandler(
diff --git a/content/browser/service_worker/service_worker_url_loader_job.cc b/content/browser/service_worker/service_worker_url_loader_job.cc index 89bbdf42..7e10fab 100644 --- a/content/browser/service_worker/service_worker_url_loader_job.cc +++ b/content/browser/service_worker/service_worker_url_loader_job.cc
@@ -182,9 +182,7 @@ void ServiceWorkerURLLoaderJob::CommitResponseHeaders() { DCHECK_EQ(Status::kStarted, status_); status_ = Status::kSentHeader; - url_loader_client_->OnReceiveResponse( - response_head_, base::nullopt /* TODO(scottmg): ssl info */, - mojom::DownloadedTempFilePtr()); + url_loader_client_->OnReceiveResponse(response_head_, ssl_info_, nullptr); } void ServiceWorkerURLLoaderJob::CommitCompleted(int error_code) { @@ -247,6 +245,15 @@ return; } + // Creates a new HttpResponseInfo using the the ServiceWorker script's + // HttpResponseInfo to show HTTPS padlock. + // TODO(horo): When we support mixed-content (HTTP) no-cors requests from a + // ServiceWorker, we have to check the security level of the responses. + const net::HttpResponseInfo* main_script_http_info = + version->GetMainScriptHttpResponseInfo(); + DCHECK(main_script_http_info); + ssl_info_ = main_script_http_info->ssl_info; + std::move(loader_callback_) .Run(base::Bind(&ServiceWorkerURLLoaderJob::StartResponse, weak_factory_.GetWeakPtr(), response, @@ -268,9 +275,6 @@ SaveResponseHeaders(response.status_code, response.status_text, response.headers); - // TODO(kinuko): Set the script's HTTP response info via - // version->GetMainScriptHttpResponseInfo() for HTTPS padlock. - // Ideally, we would always get a data pipe fom SWFetchDispatcher and use // this case. See: // https://docs.google.com/a/google.com/document/d/1_ROmusFvd8ATwIZa29-P6Ls5yyLjfld0KvKchVfA84Y/edit?usp=drive_web
diff --git a/content/browser/service_worker/service_worker_url_loader_job.h b/content/browser/service_worker/service_worker_url_loader_job.h index 86037a2..ce479ea7 100644 --- a/content/browser/service_worker/service_worker_url_loader_job.h +++ b/content/browser/service_worker/service_worker_url_loader_job.h
@@ -156,6 +156,7 @@ bool did_navigation_preload_ = false; ResourceResponseHead response_head_; + base::Optional<net::SSLInfo> ssl_info_; // URLLoaderClient binding for loading a blob. mojo::Binding<mojom::URLLoaderClient> blob_client_binding_;
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 578247e4..6faa3fd 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -903,13 +903,7 @@ } void ServiceWorkerVersion::OnScriptLoaded() { - DCHECK(GetMainScriptHttpResponseInfo() || - // TODO(scottmg|falken): This DCHECK is currently triggered in - // --network-service because ServiceWorkerReadFromCacheJob isn't being - // used to retrieve the service worker js. This should be removed once - // that's done. - (IsBrowserSideNavigationEnabled() && - base::FeatureList::IsEnabled(features::kNetworkService))); + DCHECK(GetMainScriptHttpResponseInfo()); if (IsInstalled(status())) UMA_HISTOGRAM_BOOLEAN("ServiceWorker.ScriptLoadSuccess", true); }
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 9bc18af4c..4ff9f579 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -497,8 +497,6 @@ partition->cache_storage_context_->Init(path, quota_manager_proxy); partition->service_worker_context_ = new ServiceWorkerContextWrapper(context); - partition->service_worker_context_->Init(path, quota_manager_proxy.get(), - context->GetSpecialStoragePolicy()); partition->service_worker_context_->set_storage_partition(partition.get()); partition->appcache_service_ = @@ -530,6 +528,9 @@ partition->bluetooth_allowed_devices_map_ = new BluetoothAllowedDevicesMap(); + scoped_refptr<ChromeBlobStorageContext> blob_context = + ChromeBlobStorageContext::GetFor(context); + if (base::FeatureList::IsEnabled(features::kNetworkService)) { static mojom::NetworkServicePtr* g_network_service = new mojom::NetworkServicePtr; @@ -546,8 +547,6 @@ ->CreateNetworkContext(MakeRequest(&partition->network_context_), std::move(context_params)); - scoped_refptr<ChromeBlobStorageContext> blob_context = - ChromeBlobStorageContext::GetFor(context); BlobURLLoaderFactory::BlobContextGetter blob_getter = base::BindOnce(&BlobStorageContextGetter, blob_context); partition->blob_url_loader_factory_ = BlobURLLoaderFactory::Create( @@ -557,6 +556,10 @@ partition->url_loader_factory_getter_->Initialize(partition.get()); } + partition->service_worker_context_->Init( + path, quota_manager_proxy.get(), context->GetSpecialStoragePolicy(), + blob_context.get(), partition->url_loader_factory_getter_.get()); + return partition; }
diff --git a/content/child/service_worker/service_worker_network_provider.cc b/content/child/service_worker/service_worker_network_provider.cc index 364d0dc..e609bd0a 100644 --- a/content/child/service_worker/service_worker_network_provider.cc +++ b/content/child/service_worker/service_worker_network_provider.cc
@@ -193,6 +193,7 @@ context_ = new ServiceWorkerProviderContext( provider_id_, provider_type, std::move(client_request), ChildThreadImpl::current()->thread_safe_sender()); + ChildThreadImpl::current()->channel()->GetRemoteAssociatedInterface( &dispatcher_host_); dispatcher_host_->OnProviderCreated(std::move(host_info)); @@ -224,8 +225,9 @@ DCHECK_NE(kInvalidServiceWorkerProviderId, provider_id_); if (!ChildThreadImpl::current()) return; // May be null in some tests. - dispatcher_host_->OnSetHostedVersionId(provider_id(), version_id, - embedded_worker_id); + dispatcher_host_->OnSetHostedVersionId( + provider_id(), version_id, embedded_worker_id, + mojo::MakeRequest(&script_loader_factory_)); } bool ServiceWorkerNetworkProvider::IsControlledByServiceWorker() const {
diff --git a/content/child/service_worker/service_worker_network_provider.h b/content/child/service_worker/service_worker_network_provider.h index 113d260..94daf22 100644 --- a/content/child/service_worker/service_worker_network_provider.h +++ b/content/child/service_worker/service_worker_network_provider.h
@@ -72,6 +72,12 @@ // ServiceWorkerVersion should be used. void SetServiceWorkerVersionId(int64_t version_id, int embedded_worker_id); + mojom::URLLoaderFactory* script_loader_factory() { + if (script_loader_factory_.is_bound()) + return script_loader_factory_.get(); + return nullptr; + } + bool IsControlledByServiceWorker() const; private: @@ -79,6 +85,8 @@ scoped_refptr<ServiceWorkerProviderContext> context_; mojom::ServiceWorkerDispatcherHostAssociatedPtr dispatcher_host_; mojom::ServiceWorkerProviderHostAssociatedPtr provider_host_; + mojom::URLLoaderFactoryAssociatedPtr script_loader_factory_; + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerNetworkProvider); };
diff --git a/content/common/service_worker/service_worker.mojom b/content/common/service_worker/service_worker.mojom index 7e8f5c8..344edf9 100644 --- a/content/common/service_worker/service_worker.mojom +++ b/content/common/service_worker/service_worker.mojom
@@ -5,6 +5,7 @@ module content.mojom; import "content/common/service_worker/service_worker_provider.mojom"; +import "content/public/common/url_loader_factory.mojom"; // Per-process browser-side interface. // The renderer uses this interface to tell the browser when potential service @@ -20,8 +21,12 @@ // Informs the browser that a service worker is starting up. |provider_id| // identifies the ServiceWorkerProviderHost hosting the service // worker. |version_id| identifies the ServiceWorkerVersion and - // |embedded_worker_id| identifies the EmbeddedWorkerInstance. + // |embedded_worker_id| identifies the EmbeddedWorkerInstance. + // If ServiceWorkerUtils::IsServicificationEnabled() is true, this also + // populates |script_loader_factory| for script loading for the service + // worker. OnSetHostedVersionId(int32 provider_id, int64 version_id, - int32 embedded_worker_id); -}; \ No newline at end of file + int32 embedded_worker_id, + associated URLLoaderFactory& script_loader_factory); +};
diff --git a/content/common/service_worker/service_worker_provider.mojom b/content/common/service_worker/service_worker_provider.mojom index 4016e42..922135f 100644 --- a/content/common/service_worker/service_worker_provider.mojom +++ b/content/common/service_worker/service_worker_provider.mojom
@@ -18,4 +18,4 @@ bool is_parent_frame_secure; associated ServiceWorkerProviderHost& host_request; associated ServiceWorkerProvider client_ptr_info; -}; \ No newline at end of file +};
diff --git a/content/public/utility/utility_thread.h b/content/public/utility/utility_thread.h index 49aa8a6..6d1c3627 100644 --- a/content/public/utility/utility_thread.h +++ b/content/public/utility/utility_thread.h
@@ -18,8 +18,8 @@ UtilityThread(); ~UtilityThread() override; - // Releases the process. TODO(noel): rename this routine and update callers. - virtual void ReleaseProcessIfNeeded() = 0; + // Releases the process. + virtual void ReleaseProcess() = 0; // Initializes blink if it hasn't already been initialized. virtual void EnsureBlinkInitialized() = 0;
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index ca2c49f..580e320 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -770,6 +770,7 @@ "//third_party/webrtc/api:video_frame_api", "//third_party/webrtc/api/audio_codecs:builtin_audio_decoder_factory", "//third_party/webrtc/api/audio_codecs:builtin_audio_encoder_factory", + "//third_party/webrtc/common_video:common_video", "//third_party/webrtc/media:rtc_media", "//third_party/webrtc/media:rtc_media_base", "//third_party/webrtc/modules/audio_device",
diff --git a/content/renderer/media/gpu/rtc_video_encoder.cc b/content/renderer/media/gpu/rtc_video_encoder.cc index 2185d7e..8c671e5 100644 --- a/content/renderer/media/gpu/rtc_video_encoder.cc +++ b/content/renderer/media/gpu/rtc_video_encoder.cc
@@ -47,25 +47,16 @@ DISALLOW_IMPLICIT_CONSTRUCTORS(RTCTimestamps); }; -// Translate from webrtc::VideoCodecType and webrtc::VideoCodec to -// media::VideoCodecProfile. -media::VideoCodecProfile WebRTCVideoCodecToVideoCodecProfile( - webrtc::VideoCodecType type, - const webrtc::VideoCodec* codec_settings) { - DCHECK_EQ(type, codec_settings->codecType); - switch (type) { - case webrtc::kVideoCodecVP8: - return media::VP8PROFILE_ANY; - case webrtc::kVideoCodecVP9: - return media::VP9PROFILE_MIN; - case webrtc::kVideoCodecH264: - // TODO(magjed): WebRTC is only using Baseline profile for now. Update - // once http://crbug/webrtc/6337 is fixed. - return media::H264PROFILE_BASELINE; - default: - NOTREACHED() << "Unrecognized video codec type"; - return media::VIDEO_CODEC_PROFILE_UNKNOWN; +webrtc::VideoCodecType ProfileToWebRtcVideoCodecType( + media::VideoCodecProfile profile) { + if (profile >= media::VP8PROFILE_MIN && profile <= media::VP8PROFILE_MAX) { + return webrtc::kVideoCodecVP8; + } else if (profile >= media::H264PROFILE_MIN && + profile <= media::H264PROFILE_MAX) { + return webrtc::kVideoCodecH264; } + NOTREACHED() << "Invalid profile " << GetProfileName(profile); + return webrtc::kVideoCodecUnknown; } // Populates struct webrtc::RTPFragmentationHeader for H264 codec. @@ -792,12 +783,12 @@ } RTCVideoEncoder::RTCVideoEncoder( - webrtc::VideoCodecType type, + media::VideoCodecProfile profile, media::GpuVideoAcceleratorFactories* gpu_factories) - : video_codec_type_(type), + : profile_(profile), gpu_factories_(gpu_factories), gpu_task_runner_(gpu_factories->GetTaskRunner()) { - DVLOG(1) << "RTCVideoEncoder(): codec type=" << type; + DVLOG(1) << "RTCVideoEncoder(): profile=" << GetProfileName(profile); } RTCVideoEncoder::~RTCVideoEncoder() { @@ -818,9 +809,7 @@ Release(); } - impl_ = new Impl(gpu_factories_, video_codec_type_); - const media::VideoCodecProfile profile = WebRTCVideoCodecToVideoCodecProfile( - impl_->video_codec_type(), codec_settings); + impl_ = new Impl(gpu_factories_, ProfileToWebRtcVideoCodecType(profile_)); base::WaitableEvent initialization_waiter( base::WaitableEvent::ResetPolicy::MANUAL, @@ -828,17 +817,14 @@ int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED; gpu_task_runner_->PostTask( FROM_HERE, - base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA, - impl_, + base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA, impl_, gfx::Size(codec_settings->width, codec_settings->height), - codec_settings->startBitrate, - profile, - &initialization_waiter, + codec_settings->startBitrate, profile_, &initialization_waiter, &initialization_retval)); // webrtc::VideoEncoder expects this call to be synchronous. initialization_waiter.Wait(); - RecordInitEncodeUMA(initialization_retval, profile); + RecordInitEncodeUMA(initialization_retval, profile_); return initialization_retval; }
diff --git a/content/renderer/media/gpu/rtc_video_encoder.h b/content/renderer/media/gpu/rtc_video_encoder.h index bef4f21c..67d59b3 100644 --- a/content/renderer/media/gpu/rtc_video_encoder.h +++ b/content/renderer/media/gpu/rtc_video_encoder.h
@@ -41,7 +41,7 @@ class CONTENT_EXPORT RTCVideoEncoder : NON_EXPORTED_BASE(public webrtc::VideoEncoder) { public: - RTCVideoEncoder(webrtc::VideoCodecType type, + RTCVideoEncoder(media::VideoCodecProfile profile, media::GpuVideoAcceleratorFactories* gpu_factories); ~RTCVideoEncoder() override; @@ -68,8 +68,7 @@ void RecordInitEncodeUMA(int32_t init_retval, media::VideoCodecProfile profile); - // The video codec type, as reported to WebRTC. - const webrtc::VideoCodecType video_codec_type_; + const media::VideoCodecProfile profile_; // Factory for creating VEAs, shared memory buffers, etc. media::GpuVideoAcceleratorFactories* gpu_factories_;
diff --git a/content/renderer/media/gpu/rtc_video_encoder_factory.cc b/content/renderer/media/gpu/rtc_video_encoder_factory.cc index f3189de..bbece0d 100644 --- a/content/renderer/media/gpu/rtc_video_encoder_factory.cc +++ b/content/renderer/media/gpu/rtc_video_encoder_factory.cc
@@ -11,23 +11,23 @@ #include "content/renderer/media/gpu/rtc_video_encoder.h" #include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h" #include "media/renderers/gpu_video_accelerator_factories.h" -#include "media/video/video_encode_accelerator.h" +#include "third_party/webrtc/common_video/h264/profile_level_id.h" namespace content { namespace { // Translate from media::VideoEncodeAccelerator::SupportedProfile to -// one or more instances of cricket::WebRtcVideoEncoderFactory::VideoCodec -void VEAToWebRTCCodecs( - std::vector<cricket::VideoCodec>* codecs, +// cricket::WebRtcVideoEncoderFactory::VideoCodec, or return nothing if the +// profile isn't supported. +base::Optional<cricket::VideoCodec> VEAToWebRTCCodec( const media::VideoEncodeAccelerator::SupportedProfile& profile) { DCHECK_EQ(profile.max_framerate_denominator, 1U); if (profile.profile >= media::VP8PROFILE_MIN && profile.profile <= media::VP8PROFILE_MAX) { if (base::FeatureList::IsEnabled(features::kWebRtcHWVP8Encoding)) { - codecs->push_back(cricket::VideoCodec("VP8")); + return base::Optional<cricket::VideoCodec>(cricket::VideoCodec("VP8")); } } else if (profile.profile >= media::H264PROFILE_MIN && profile.profile <= media::H264PROFILE_MAX) { @@ -41,10 +41,41 @@ #endif // BUILDFLAG(RTC_USE_H264) && !defined(MEDIA_DISABLE_FFMPEG) if (webrtc_h264_sw_enabled || base::FeatureList::IsEnabled(features::kWebRtcHWH264Encoding)) { - // TODO(magjed): Propagate H264 profile information. - codecs->push_back(cricket::VideoCodec("H264")); + webrtc::H264::Profile h264_profile; + switch (profile.profile) { + case media::H264PROFILE_BASELINE: + h264_profile = webrtc::H264::kProfileBaseline; + break; + case media::H264PROFILE_MAIN: + h264_profile = webrtc::H264::kProfileMain; + break; + case media::H264PROFILE_HIGH: + h264_profile = webrtc::H264::kProfileHigh; + break; + default: + // Unsupported H264 profile in WebRTC. + return base::Optional<cricket::VideoCodec>(); + } + + const int width = profile.max_resolution.width(); + const int height = profile.max_resolution.height(); + const int fps = profile.max_framerate_numerator; + DCHECK_EQ(1u, profile.max_framerate_denominator); + + const rtc::Optional<webrtc::H264::Level> h264_level = + webrtc::H264::SupportedLevel(width * height, fps); + const webrtc::H264::ProfileLevelId profile_level_id( + h264_profile, h264_level.value_or(webrtc::H264::kLevel1)); + + cricket::VideoCodec codec("H264"); + codec.SetParam(cricket::kH264FmtpProfileLevelId, + *webrtc::H264::ProfileLevelIdToString(profile_level_id)); + codec.SetParam(cricket::kH264FmtpLevelAsymmetryAllowed, "1"); + codec.SetParam(cricket::kH264FmtpPacketizationMode, "1"); + return base::Optional<cricket::VideoCodec>(codec); } } + return base::Optional<cricket::VideoCodec>(); } } // anonymous namespace @@ -54,20 +85,36 @@ : gpu_factories_(gpu_factories) { const media::VideoEncodeAccelerator::SupportedProfiles& profiles = gpu_factories_->GetVideoEncodeAcceleratorSupportedProfiles(); - for (const auto& profile : profiles) - VEAToWebRTCCodecs(&supported_codecs_, profile); + for (const auto& profile : profiles) { + base::Optional<cricket::VideoCodec> codec = VEAToWebRTCCodec(profile); + if (codec) { + supported_codecs_.push_back(std::move(*codec)); + profiles_.push_back(profile.profile); + } + } + // There should be a 1:1 mapping between media::VideoCodecProfile and + // cricket::VideoCodec. + CHECK_EQ(profiles_.size(), supported_codecs_.size()); } RTCVideoEncoderFactory::~RTCVideoEncoderFactory() {} webrtc::VideoEncoder* RTCVideoEncoderFactory::CreateVideoEncoder( const cricket::VideoCodec& codec) { - for (const cricket::VideoCodec& supported_codec : supported_codecs_) { - if (cricket::CodecNamesEq(codec.name, supported_codec.name)) { - webrtc::VideoCodecType type = webrtc::PayloadNameToCodecType(codec.name) - .value_or(webrtc::kVideoCodecUnknown); - return new RTCVideoEncoder(type, gpu_factories_); + for (size_t i = 0; i < supported_codecs_.size(); ++i) { + if (!cricket::CodecNamesEq(codec.name, supported_codecs_[i].name)) + continue; + // Check H264 profile. + using webrtc::H264::ParseSdpProfileLevelId; + if (cricket::CodecNamesEq(codec.name.c_str(), cricket::kH264CodecName) && + ParseSdpProfileLevelId(codec.params)->profile != + ParseSdpProfileLevelId(supported_codecs_[i].params)->profile) { + continue; } + // There should be a 1:1 mapping between media::VideoCodecProfile and + // cricket::VideoCodec. + CHECK_EQ(profiles_.size(), supported_codecs_.size()); + return new RTCVideoEncoder(profiles_[i], gpu_factories_); } return nullptr; }
diff --git a/content/renderer/media/gpu/rtc_video_encoder_factory.h b/content/renderer/media/gpu/rtc_video_encoder_factory.h index 307f8f92..c5bcde0 100644 --- a/content/renderer/media/gpu/rtc_video_encoder_factory.h +++ b/content/renderer/media/gpu/rtc_video_encoder_factory.h
@@ -39,6 +39,9 @@ media::GpuVideoAcceleratorFactories* gpu_factories_; // List of supported cricket::WebRtcVideoEncoderFactory::VideoCodec. + // |profiles_| and |supported_codecs_| have the same length and the profile + // for |supported_codecs_[i]| is |profiles_[i]|. + std::vector<media::VideoCodecProfile> profiles_; std::vector<cricket::VideoCodec> supported_codecs_; DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoderFactory);
diff --git a/content/renderer/media/gpu/rtc_video_encoder_unittest.cc b/content/renderer/media/gpu/rtc_video_encoder_unittest.cc index 3fd7a91b..889b024 100644 --- a/content/renderer/media/gpu/rtc_video_encoder_unittest.cc +++ b/content/renderer/media/gpu/rtc_video_encoder_unittest.cc
@@ -113,7 +113,19 @@ void CreateEncoder(webrtc::VideoCodecType codec_type) { DVLOG(3) << __func__; - rtc_encoder_ = base::MakeUnique<RTCVideoEncoder>(codec_type, + media::VideoCodecProfile media_profile; + switch (codec_type) { + case webrtc::kVideoCodecVP8: + media_profile = media::VP8PROFILE_ANY; + break; + case webrtc::kVideoCodecH264: + media_profile = media::H264PROFILE_BASELINE; + break; + default: + ADD_FAILURE() << "Unexpected codec type: " << codec_type; + media_profile = media::VIDEO_CODEC_PROFILE_UNKNOWN; + } + rtc_encoder_ = base::MakeUnique<RTCVideoEncoder>(media_profile, mock_gpu_factories_.get()); }
diff --git a/content/renderer/media/renderer_webaudiodevice_impl.cc b/content/renderer/media/renderer_webaudiodevice_impl.cc index ef941bec..568052e5 100644 --- a/content/renderer/media/renderer_webaudiodevice_impl.cc +++ b/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -65,12 +65,9 @@ hardware_params.sample_rate(), 0); break; case media::AudioLatency::LATENCY_EXACT_MS: - // TODO(andrew.macpherson@soundtrap.com): http://crbug.com/708917 - return std::min(4096, - media::AudioLatency::GetExactBufferSize( - base::TimeDelta::FromSecondsD(latency_hint.Seconds()), - hardware_params.sample_rate(), - hardware_params.frames_per_buffer())); + return media::AudioLatency::GetExactBufferSize( + base::TimeDelta::FromSecondsD(latency_hint.Seconds()), + hardware_params.sample_rate(), hardware_params.frames_per_buffer()); break; default: NOTREACHED();
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc index f88d4d3..92be82d 100644 --- a/content/renderer/service_worker/service_worker_context_client.cc +++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -38,6 +38,7 @@ #include "content/common/service_worker/service_worker_event_dispatcher.mojom.h" #include "content/common/service_worker/service_worker_messages.h" #include "content/common/service_worker/service_worker_status_code.h" +#include "content/common/service_worker/service_worker_utils.h" #include "content/common/worker_url_loader_factory_provider.mojom.h" #include "content/public/common/content_features.h" #include "content/public/common/push_event_payload.h" @@ -103,6 +104,19 @@ request.SetExtraData(extra_data.release()); } + std::unique_ptr<blink::WebURLLoader> CreateURLLoader( + const blink::WebURLRequest& request, + base::SingleThreadTaskRunner* task_runner) override { + RenderThreadImpl* child_thread = RenderThreadImpl::current(); + if (child_thread && provider_->script_loader_factory() && + ServiceWorkerUtils::IsServicificationEnabled()) { + return base::MakeUnique<WebURLLoaderImpl>( + child_thread->resource_dispatcher(), task_runner, + provider_->script_loader_factory()); + } + return nullptr; + } + int GetProviderID() const override { return provider_->provider_id(); } private:
diff --git a/content/shell/browser/layout_test/layout_test_browser_context.cc b/content/shell/browser/layout_test/layout_test_browser_context.cc index 3ba2ba7..d8ccd83 100644 --- a/content/shell/browser/layout_test/layout_test_browser_context.cc +++ b/content/shell/browser/layout_test/layout_test_browser_context.cc
@@ -12,6 +12,7 @@ #include "base/logging.h" #include "base/path_service.h" #include "base/strings/string_util.h" +#include "base/task_scheduler/post_task.h" #include "build/build_config.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/push_messaging_service.h" @@ -73,7 +74,9 @@ return new net::URLRequestFileJob( request, network_delegate, path, - BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)); + base::CreateTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})); } };
diff --git a/content/shell/browser/shell_download_manager_delegate.cc b/content/shell/browser/shell_download_manager_delegate.cc index 789b40c..5156d50 100644 --- a/content/shell/browser/shell_download_manager_delegate.cc +++ b/content/shell/browser/shell_download_manager_delegate.cc
@@ -16,6 +16,7 @@ #include "base/macros.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/task_scheduler/post_task.h" #include "build/build_config.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" @@ -83,16 +84,14 @@ download->GetId(), callback); - BrowserThread::PostTask( - BrowserThread::FILE, + PostTaskWithTraits( FROM_HERE, + {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN, + base::TaskPriority::USER_VISIBLE}, base::Bind(&ShellDownloadManagerDelegate::GenerateFilename, - download->GetURL(), - download->GetContentDisposition(), - download->GetSuggestedFilename(), - download->GetMimeType(), - default_download_path_, - filename_determined_callback)); + download->GetURL(), download->GetContentDisposition(), + download->GetSuggestedFilename(), download->GetMimeType(), + default_download_path_, filename_determined_callback)); return true; } @@ -116,7 +115,6 @@ const std::string& mime_type, const base::FilePath& suggested_directory, const FilenameDeterminedCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::FILE); base::FilePath generated_name = net::GenerateFileName(url, content_disposition, std::string(),
diff --git a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc index bf0ffca..b275d6a 100644 --- a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc +++ b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
@@ -217,11 +217,9 @@ media::AudioLatency::GetHighLatencyBufferSize(hw_sample_rate, 0); break; case blink::WebAudioLatencyHint::kCategoryExact: - // TODO(andrew.macpherson@soundtrap.com): http://crbug.com/708917 - buffer_size = std::min( - 4096, media::AudioLatency::GetExactBufferSize( - base::TimeDelta::FromSecondsD(latency_hint.Seconds()), - hw_sample_rate, hw_buffer_size)); + buffer_size = media::AudioLatency::GetExactBufferSize( + base::TimeDelta::FromSecondsD(latency_hint.Seconds()), hw_sample_rate, + hw_buffer_size); break; default: NOTREACHED();
diff --git a/content/utility/utility_service_factory.cc b/content/utility/utility_service_factory.cc index a4eedeed..abe5f28 100644 --- a/content/utility/utility_service_factory.cc +++ b/content/utility/utility_service_factory.cc
@@ -122,14 +122,14 @@ } void UtilityServiceFactory::OnServiceQuit() { - UtilityThread::Get()->ReleaseProcessIfNeeded(); + UtilityThread::Get()->ReleaseProcess(); } void UtilityServiceFactory::OnLoadFailed() { UtilityThreadImpl* utility_thread = static_cast<UtilityThreadImpl*>(UtilityThread::Get()); utility_thread->Shutdown(); - utility_thread->ReleaseProcessIfNeeded(); + utility_thread->ReleaseProcess(); } std::unique_ptr<service_manager::Service>
diff --git a/content/utility/utility_thread_impl.cc b/content/utility/utility_thread_impl.cc index d7059fd..fd49df6 100644 --- a/content/utility/utility_thread_impl.cc +++ b/content/utility/utility_thread_impl.cc
@@ -39,7 +39,7 @@ ChildThreadImpl::Shutdown(); } -void UtilityThreadImpl::ReleaseProcessIfNeeded() { +void UtilityThreadImpl::ReleaseProcess() { if (!IsInBrowserProcess()) { ChildProcess::current()->ReleaseProcess(); return;
diff --git a/content/utility/utility_thread_impl.h b/content/utility/utility_thread_impl.h index 9bfdc75..ac132ff 100644 --- a/content/utility/utility_thread_impl.h +++ b/content/utility/utility_thread_impl.h
@@ -39,7 +39,7 @@ void Shutdown() override; // UtilityThread: - void ReleaseProcessIfNeeded() override; + void ReleaseProcess() override; void EnsureBlinkInitialized() override; private:
diff --git a/gin/v8_platform_unittest.cc b/gin/v8_platform_unittest.cc index e3643d3da..3a5abe3 100644 --- a/gin/v8_platform_unittest.cc +++ b/gin/v8_platform_unittest.cc
@@ -8,7 +8,7 @@ #include "testing/gtest/include/gtest/gtest.h" class TestTraceStateObserver - : public NON_EXPORTED_BASE(v8::Platform::TraceStateObserver) { + : public NON_EXPORTED_BASE(v8::TracingController::TraceStateObserver) { public: void OnTraceEnabled() final { ++enabled_; } void OnTraceDisabled() final { ++disabled_; }
diff --git a/headless/BUILD.gn b/headless/BUILD.gn index 384124f2..d692ed5 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn
@@ -167,9 +167,12 @@ generated_devtools_api = [] generated_devtools_api_js = [] +generated_devtools_api_js_externs = [] foreach(domain, devtools_domains) { generated_devtools_api_js += [ "$target_gen_dir/public/devtools_js/" + domain + ".js" ] + generated_devtools_api_js_externs += + [ "$target_gen_dir/public/devtools_js/externs/externs_" + domain + ".js" ] generated_devtools_api += [ "$target_gen_dir/public/devtools/domains/" + domain + ".cc", "$target_gen_dir/public/devtools/domains/" + domain + ".h", @@ -191,10 +194,12 @@ "$root_gen_dir/blink/core/inspector/protocol.json", ] - outputs = generated_devtools_api + generated_devtools_api_js + outputs = generated_devtools_api + generated_devtools_api_js + + generated_devtools_api_js_externs sources = [ "lib/browser/devtools_api/domain_cc.template", + "lib/browser/devtools_api/domain_externs_js.template", "lib/browser/devtools_api/domain_h.template", "lib/browser/devtools_api/domain_js.template", "lib/browser/devtools_api/domain_type_conversions_h.template",
diff --git a/headless/lib/browser/devtools_api/client_api_generator.py b/headless/lib/browser/devtools_api/client_api_generator.py index 7a8ea343..d2ce3de 100644 --- a/headless/lib/browser/devtools_api/client_api_generator.py +++ b/headless/lib/browser/devtools_api/client_api_generator.py
@@ -518,6 +518,10 @@ jinja_env, os.path.join(output_dirname, 'devtools_js'), json_api, 'domain', ['js'], lambda domain_name: domain_name) + GeneratePerDomain( + jinja_env, os.path.join(output_dirname, 'devtools_js', 'externs'), + json_api, 'domain_externs', ['js'], + lambda domain_name: 'externs_%s' % (domain_name, )) def GenerateTypes(jinja_env, output_dirname, json_api):
diff --git a/headless/lib/browser/devtools_api/devtools_connection.js b/headless/lib/browser/devtools_api/devtools_connection.js index d31d4add3..3061c196 100644 --- a/headless/lib/browser/devtools_api/devtools_connection.js +++ b/headless/lib/browser/devtools_api/devtools_connection.js
@@ -10,13 +10,14 @@ 'use strict'; -goog.module('chromium.DevTools.Connection'); +goog.provide('chromium.DevTools.Connection'); /** * Handles sending and receiving DevTools JSON protocol messages over the * provided low level message transport. + * @export */ -class Connection { +chromium.DevTools.Connection = class { /** * @param {!Object} transport The API providing transport for devtools * commands. @@ -31,7 +32,7 @@ /** * An object containing pending DevTools protocol commands keyed by id. * - * @private {!Map<number, !Connection.PendingCommand>} + * @private {!Map<number, !chromium.DevTools.Connection.PendingCommand>} */ this.pendingCommands_ = new Map(); @@ -42,7 +43,9 @@ * An object containing DevTools protocol events we are listening for keyed * by name. * - * @private {!Map<string, !Map<number, !Connection.EventFunction>>} + * @private {!Map<string, + * !Map<number, + * !chromium.DevTools.Connection.EventFunction>>} */ this.eventListeners_ = new Map(); @@ -62,8 +65,9 @@ * * @param {string} eventName Name of the DevTools protocol event to listen * for. - * @param {!Connection.EventFunction} listener The callback issued when we - * receive a DevTools protocol event corresponding to the given name. + * @param {!chromium.DevTools.Connection.EventFunction} listener The callback + * issued when we receive a DevTools protocol event corresponding to the + * given name. * @return {number} The id of this event listener. */ addEventListener(eventName, listener) { @@ -100,7 +104,8 @@ * @param {string} method The name of the DevTools protocol command method. * @param {!Object=} params An object containing the command parameters if * any. - * @return {!Promise<!Object>} A promise for the results object. + * @return {!Promise<!TYPE>} A promise for the results object. + * @template TYPE */ sendDevToolsMessage(method, params = {}) { let id = this.commandId_; @@ -165,7 +170,7 @@ /** * @typedef {function(Object): undefined|function(string): undefined} */ -Connection.EventFunction; +chromium.DevTools.Connection.EventFunction; /** * @typedef {{ @@ -173,6 +178,4 @@ * reject: function(!Object) * }} */ -Connection.PendingCommand; - -exports = Connection; +chromium.DevTools.Connection.PendingCommand;
diff --git a/headless/lib/browser/devtools_api/domain_externs_js.template b/headless/lib/browser/devtools_api/domain_externs_js.template new file mode 100644 index 0000000..0f9c6e0 --- /dev/null +++ b/headless/lib/browser/devtools_api/domain_externs_js.template
@@ -0,0 +1,176 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +{# Changes to the externs must be reflected in the generated API too. #} + +/** + * Experimental bindings for the {{domain.domain}} DevTools Domain. Note these + * are subject to change without warning. Use at your own risk. + * @param {!chromium.DevTools.Connection} connection The DevTools connection. + * @constructor + */ +chromium.DevTools.Experimental{{domain.domain}} = function(connection) {}; + +/** + * Removes an event listener. + * + * @param {number} id The id of the event listener to remove. + * @return {boolean} Whether the event listener was actually removed. + */ +chromium.DevTools.Experimental{{domain.domain}}.prototype.removeEventListener = function(id) {}; + +/** + * Bindings for the {{domain.domain}} DevTools Domain. + * @param {!chromium.DevTools.Connection} connection The DevTools connection. + * @constructor + */ +chromium.DevTools.{{domain.domain}} = function(connection) {}; + +/** @type {!chromium.DevTools.Experimental{{domain.domain}}} */ +chromium.DevTools.{{domain.domain}}.prototype.experimental; + +/** + * Removes an event listener. + * + * @param {number} id The id of the event listener to remove. + * @return {boolean} Whether the event listener was actually removed. + */ +chromium.DevTools.{{domain.domain}}.prototype.removeEventListener = function(id) {}; + +{# Generate enums. #} +{% for type in domain.types %} + {% if not "enum" in type %}{% continue %}{% endif %} +/** + {% if type.description %} + * {{type.description}} + * + {% endif %} + * @enum {string} + */ +chromium.DevTools.{{domain.domain}}.{{type.id}} = { + {% for literal in type.enum %} + {{ literal | sanitize_literal | dash_to_camelcase | camelcase_to_hacker_style | upper }}: "{{ literal }}"{{',' if not loop.last}} + {% endfor %} +}; + +{% endfor %} + +{# Generate types. #} +{% for type in domain.types %} + {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %} +/** + {% if type.description %} + * {{type.description}} + * + {% endif %} + {% for property in type.properties %} + {% if property.description %} + * {{property.name}}: {{property.description}} + {% endif %} + {% endfor %} + * + {% if type.properties %} + * @typedef {{ '{{' }} + {% for property in type.properties %} + {% if property.optional %} + * {{property.name}}: ({{ resolve_type(property).js_type }}|undefined){{',' if not loop.last}} + {% else %} + * {{property.name}}: {{ resolve_type(property).js_type }}{{',' if not loop.last}} + {% endif %} + {% endfor %} + * {{ '}}' }} + {% else %} + * @typedef {undefined} + {% endif %} + */ +chromium.DevTools.{{domain.domain}}.{{type.id}}; + +{% endfor %} + +{# Generate all commands for Experimental Domain. #} +{% for command in domain.commands %} + {% set method_name = command.name | sanitize_literal %} + {% set title_case_method_name = method_name | to_title_case %} + {% set result_type = '{!Promise<chromium.DevTools.' + domain.domain + '.' + title_case_method_name + 'Result>}' %} + +/** + {% if command.description %} + * {{ command.description }} + * + {% endif %} + {% if command.parameters|length > 0 %} + * @param {{ '{chromium.DevTools.' + domain.domain + '.' + title_case_method_name + 'Params}' }} params + {% endif %} + * @return {{result_type}} + */ + {% if command.parameters|length > 0 %} +chromium.DevTools.Experimental{{domain.domain}}.prototype.{{method_name}} = function(params) {}; + {% else %} +chromium.DevTools.Experimental{{domain.domain}}.prototype.{{method_name}} = function() {}; + {% endif %} +{% endfor %} + +{# Generate all events Experimental Domain. #} +{% for event in domain.events %} + {% if event.parameters|length > 0 %} + {% set param_type = '{!function(!chromium.DevTools.' + domain.domain + '.' + event.name | to_title_case + 'Params)}' %} + {% else %} + {% set param_type = '{!function()}' %} + {% endif %} + +/** + {% if event.description %} + * {{ event.description }} + * + {% endif %} + * @param {{param_type}} listener + * @return {number} The id of this event listener. + */ +chromium.DevTools.Experimental{{domain.domain}}.prototype.on{{event.name | to_title_case}} = function(listener) {}; +{% endfor %} + + +{# Generate non-Experimental commands. #} +{% for command in domain.commands %} + {% if command.Experimental %}{% continue %}{% endif %} + {% set method_name = command.name | sanitize_literal %} + {% set title_case_method_name = method_name | to_title_case %} + {% set result_type = '{!Promise<chromium.DevTools.' + domain.domain + '.' + title_case_method_name + 'Result>}' %} + +/** + {% if command.description %} + * {{ command.description }} + * + {% endif %} + {% if command.parameters|length > 0 %} + * @param {{ '{chromium.DevTools.' + domain.domain + '.' + title_case_method_name + 'Params}' }} params + {% endif %} + * @return {{result_type}} + */ + {% if command.parameters|length > 0 %} +chromium.DevTools.{{domain.domain}}.prototype.{{method_name}} = function(params) {}; + {% else %} +chromium.DevTools.{{domain.domain}}.prototype.{{method_name}} = function() {}; + {% endif %} +{% endfor %} + +{# Generate non-Experimental events. #} +{% for event in domain.events %} + {% if event.Experimental %}{% continue %}{% endif %} + {% if event.parameters|length > 0 %} + {% set param_type = '{!function(!chromium.DevTools.' + domain.domain + '.' + event.name | to_title_case + 'Params)}' %} + {% else %} + {% set param_type = '{!function()}' %} + {% endif %} + +/** + {% if event.description %} + * {{ event.description }} + * + {% endif %} + * @param {{param_type}} listener + * @return {number} The id of this event listener. + */ +chromium.DevTools.{{domain.domain}}.prototype.on{{event.name | to_title_case}} = function(listener) {}; +{% endfor %}
diff --git a/headless/lib/browser/devtools_api/domain_js.template b/headless/lib/browser/devtools_api/domain_js.template index d8bdc67..0b701ed 100644 --- a/headless/lib/browser/devtools_api/domain_js.template +++ b/headless/lib/browser/devtools_api/domain_js.template
@@ -2,161 +2,75 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +{# Changes to the generated API must be reflected in the externs too. #} + /** * @fileoverview Generated DevTools bindings for the {{domain.domain}} Domain. - * Note bindings are not generated for experimental commands and events, if you - * need to use one of those you must use the - * <code>chromium.DevTools.Connection</code> class directly. */ 'use strict'; -goog.module('chromium.DevTools.{{domain.domain}}'); -const Connection = goog.require('chromium.DevTools.Connection'); +goog.provide('chromium.DevTools.Experimental{{domain.domain}}'); +goog.provide('chromium.DevTools.{{domain.domain}}'); +goog.require('chromium.DevTools.Connection'); {% for domain_name in domain.js_dependencies %} -const {{domain_name}} = goog.require('chromium.DevTools.{{domain_name}}'); +goog.require('chromium.DevTools.{{domain_name}}'); {% endfor %} {% for forward_declaration in domain.js_forward_declarations %} goog.forwardDeclare('chromium.DevTools.{{forward_declaration}}'); {% endfor %} +goog.scope(function() { +const Connection = chromium.DevTools.Connection; +{% for domain_name in domain.js_dependencies %} +const {{domain_name}} = chromium.DevTools.{{domain_name}}; +{% endfor %} + /** * Experimental bindings for the {{domain.domain}} DevTools Domain. Note these * are subject to change without warning. Use at your own risk. + * @param {!Connection} connection The DevTools connection. + * @constructor */ -class Experimental{{domain.domain}} { - /** - * @param {!Connection} connection The DevTools connection. - */ - constructor(connection) { - /** @private {!Connection} */ - this.connection_ = connection; - }; +chromium.DevTools.Experimental{{domain.domain}} = function(connection) { + /** @private {!Connection} */ + this.connection_ = connection; +} - /** - * Removes an event listener. - * - * @param {number} id The id of the event listener to remove. - * @return {boolean} Whether the event listener was actually removed. - */ - removeEventListener(id) { - return this.connection_.removeEventListener(id); - } +const Experimental{{domain.domain}} = chromium.DevTools.Experimental{{domain.domain}}; -{# Generate all commands. #} -{% for command in domain.commands %} - {% set method_name = command.name | sanitize_literal %} - {% set title_case_method_name = method_name | to_title_case %} - {% if command.parameters|length > 0 %} - {% set param_name = 'params' %} - {% set param_type = '{' + domain.domain + '.' + title_case_method_name + 'Params}' %} - {% else %} - {% set param_name = 'opt_params' %} - {% set param_type = '{' + domain.domain + '.' + title_case_method_name + 'Params=}' %} - {% endif %} - {% set result_type = '{!Promise<' + domain.domain + '.' + title_case_method_name + 'Result>}' %} - - /** - {% if command.description %} - * {{ command.description }} - {% endif %} - * @param {{param_type}} {{param_name}} - * @return {{result_type}} - */ - {{method_name}}({{param_name}}) { - return /** @type {{result_type}} **/( - this.connection_.sendDevToolsMessage( - '{{domain.domain}}.{{command.name}}', {{param_name}})); - } -{% endfor %} - -{# Generate all events. #} -{% for event in domain.events %} - {% set param_type = '{!function(!' + domain.domain + '.' + event.name | to_title_case + 'Params)}' %} - - /** - {% if event.description %} - * {{ event.description }} - {% endif %} - * @param {{param_type}} listener - * @return {number} The id of this event listener. - */ - on{{event.name | to_title_case}}(listener) { - return this.connection_.addEventListener( - '{{domain.domain}}.{{event.name}}', /** @type {!function(!Object): undefined} */ (listener)); - } -{% endfor %} +/** + * Removes an event listener. + * + * @param {number} id The id of the event listener to remove. + * @return {boolean} Whether the event listener was actually removed. + */ +Experimental{{domain.domain}}.prototype.removeEventListener = function(id) { + return this.connection_.removeEventListener(id); } /** * Bindings for the {{domain.domain}} DevTools Domain. + * @param {!Connection} connection The DevTools connection. + * @constructor */ -class {{domain.domain}} { - /** - * @param {!Connection} connection The DevTools connection. - */ - constructor(connection) { - /** @private {!Connection} */ - this.connection_ = connection; +chromium.DevTools.{{domain.domain}} = function(connection) { + /** @private {!Connection} */ + this.connection_ = connection; - /** @type {!Experimental{{domain.domain}}} */ - this.experimental = new Experimental{{domain.domain}}(connection); - }; + /** @type {!Experimental{{domain.domain}}} */ + this.experimental = new Experimental{{domain.domain}}(connection); +} - /** - * Removes an event listener. - * - * @param {number} id The id of the event listener to remove. - * @return {boolean} Whether the event listener was actually removed. - */ - removeEventListener(id) { - return this.connection_.removeEventListener(id); - } +const {{domain.domain}} = chromium.DevTools.{{domain.domain}}; -{# Generate non-experimental commands. #} -{% for command in domain.commands %} - {% if command.experimental %}{% continue %}{% endif %} - {% set method_name = command.name | sanitize_literal %} - {% set title_case_method_name = method_name | to_title_case %} - {% if command.parameters|length > 0 %} - {% set param_name = 'params' %} - {% set param_type = '{' + domain.domain + '.' + title_case_method_name + 'Params}' %} - {% else %} - {% set param_name = 'opt_params' %} - {% set param_type = '{' + domain.domain + '.' + title_case_method_name + 'Params=}' %} - {% endif %} - {% set result_type = '{!Promise<' + domain.domain + '.' + title_case_method_name + 'Result>}' %} - - /** - {% if command.description %} - * {{ command.description }} - {% endif %} - * @param {{param_type}} {{param_name}} - * @return {{result_type}} - */ - {{method_name}}({{param_name}}) { - return /** @type {{result_type}} **/( - this.connection_.sendDevToolsMessage( - '{{domain.domain}}.{{command.name}}', {{param_name}})); - } -{% endfor %} - -{# Generate non-experimental events. #} -{% for event in domain.events %} - {% if event.experimental %}{% continue %}{% endif %} - {% set param_type = '{!function(!' + domain.domain + '.' + event.name | to_title_case + 'Params)}' %} - - /** - {% if event.description %} - * {{ event.description }} - {% endif %} - * @param {{param_type}} listener - * @return {number} The id of this event listener. - */ - on{{event.name | to_title_case}}(listener) { - return this.connection_.addEventListener( - '{{domain.domain}}.{{event.name}}', /** @type {!function(!Object): undefined} */ (listener)); - } -{% endfor %} +/** + * Removes an event listener. + * + * @param {number} id The id of the event listener to remove. + * @return {boolean} Whether the event listener was actually removed. + */ +{{domain.domain}}.prototype.removeEventListener = function(id) { + return this.connection_.removeEventListener(id); } {# Generate enums. #} @@ -207,7 +121,108 @@ */ {{domain.domain}}.{{type.id}}; - {% endfor %} -exports = {{domain.domain}}; +{# Generate all commands for Experimental Domain. #} +{% for command in domain.commands %} + {% set method_name = command.name | sanitize_literal %} + {% set title_case_method_name = method_name | to_title_case %} + {% set result_type = '{!Promise<' + domain.domain + '.' + title_case_method_name + 'Result>}' %} + +/** + {% if command.description %} + * {{ command.description }} + * + {% endif %} + {% if command.parameters|length > 0 %} + * @param {{ '{' + domain.domain + '.' + title_case_method_name + 'Params}' }} params + {% endif %} + * @return {{result_type}} + */ + {% if command.parameters|length > 0 %} +Experimental{{domain.domain}}.prototype.{{method_name}} = function(params) { + return this.connection_.sendDevToolsMessage('{{domain.domain}}.{{command.name}}', params); +}; + {% else %} +Experimental{{domain.domain}}.prototype.{{method_name}} = function() { + return this.connection_.sendDevToolsMessage('{{domain.domain}}.{{command.name}}', {}); +}; + {% endif %} +{% endfor %} + +{# Generate all events Experimental Domain. #} +{% for event in domain.events %} + {% if event.parameters|length > 0 %} + {% set param_type = '{!function(!' + domain.domain + '.' + event.name | to_title_case + 'Params)}' %} + {% else %} + {% set param_type = '{!function()}' %} + {% endif %} + +/** + {% if event.description %} + * {{ event.description }} + * + {% endif %} + * @param {{param_type}} listener + * @return {number} The id of this event listener. + */ +Experimental{{domain.domain}}.prototype.on{{event.name | to_title_case}} = function(listener) { + return this.connection_.addEventListener( + '{{domain.domain}}.{{event.name}}', /** @type {!function(!Object): undefined} */ (listener)); +}; +{% endfor %} + + +{# Generate non-Experimental commands. #} +{% for command in domain.commands %} + {% if command.Experimental %}{% continue %}{% endif %} + {% set method_name = command.name | sanitize_literal %} + {% set title_case_method_name = method_name | to_title_case %} + {% set result_type = '{!Promise<' + domain.domain + '.' + title_case_method_name + 'Result>}' %} + +/** + {% if command.description %} + * {{ command.description }} + * + {% endif %} + {% if command.parameters|length > 0 %} + * @param {{ '{' + domain.domain + '.' + title_case_method_name + 'Params}' }} params + {% endif %} + * @return {{result_type}} + */ + {% if command.parameters|length > 0 %} +{{domain.domain}}.prototype.{{method_name}} = function(params) { + return this.connection_.sendDevToolsMessage('{{domain.domain}}.{{command.name}}', params); +}; + {% else %} +{{domain.domain}}.prototype.{{method_name}} = function() { + return this.connection_.sendDevToolsMessage('{{domain.domain}}.{{command.name}}', {}); +}; + {% endif %} +{% endfor %} + +{# Generate non-Experimental events. #} +{% for event in domain.events %} + {% if event.Experimental %}{% continue %}{% endif %} + {% if event.parameters|length > 0 %} + {% set param_type = '{!function(!' + domain.domain + '.' + event.name | to_title_case + 'Params)}' %} + {% else %} + {% set param_type = '{!function()}' %} + {% endif %} + +/** + {% if event.description %} + * {{ event.description }} + * + {% endif %} + * @param {{param_type}} listener + * @return {number} The id of this event listener. + */ +{{domain.domain}}.prototype.on{{event.name | to_title_case}} = function(listener) { + return this.connection_.addEventListener( + '{{domain.domain}}.{{event.name}}', /** @type {!function(!Object): undefined} */ (listener)); +}; +{% endfor %} + +}); // goog.scope +
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 03d2806c58..6ceff6a 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -1789,10 +1789,11 @@ new ToolbarModelDelegateIOS([_model webStateList])); _toolbarModelIOS.reset([_dependencyFactory newToolbarModelIOSWithDelegate:_toolbarModelDelegate.get()]); - _toolbarController = [_dependencyFactory - newWebToolbarControllerWithDelegate:self - urlLoader:self - preloadProvider:_preloadController]; + _toolbarController = + [_dependencyFactory newWebToolbarControllerWithDelegate:self + urlLoader:self + preloadProvider:_preloadController + dispatcher:self.dispatcher]; [_dispatcher startDispatchingToTarget:_toolbarController forProtocol:@protocol(OmniboxFocuser)]; [_toolbarController setTabCount:[_model count]]; @@ -4020,6 +4021,16 @@ return card; } +#pragma mark - BrowserCommands + +- (void)goBack { + [[_model currentTab] goBack]; +} + +- (void)goForward { + [[_model currentTab] goForward]; +} + #pragma mark - Command Handling - (IBAction)chromeExecuteCommand:(id)sender { @@ -4030,9 +4041,6 @@ Tab* currentTab = [_model currentTab]; switch (command) { - case IDC_BACK: - [[_model currentTab] goBack]; - break; case IDC_BOOKMARK_PAGE: [self initializeBookmarkInteractionController]; [_bookmarkInteractionController @@ -4068,9 +4076,6 @@ case IDC_FIND_UPDATE: [self searchFindInPage]; break; - case IDC_FORWARD: - [[_model currentTab] goForward]; - break; case IDC_FULLSCREEN: NOTIMPLEMENTED(); break;
diff --git a/ios/chrome/browser/ui/browser_view_controller_dependency_factory.h b/ios/chrome/browser/ui/browser_view_controller_dependency_factory.h index e38cefe..7b57a2d 100644 --- a/ios/chrome/browser/ui/browser_view_controller_dependency_factory.h +++ b/ios/chrome/browser/ui/browser_view_controller_dependency_factory.h
@@ -10,6 +10,7 @@ #include "ios/chrome/browser/ui/tabs/tab_strip_controller.h" @class AlertCoordinator; +@protocol BrowserCommands; @class KeyCommandsProvider; @class MessageBubbleView; @class PKPass; @@ -65,7 +66,8 @@ - (WebToolbarController*) newWebToolbarControllerWithDelegate:(id<WebToolbarDelegate>)delegate urlLoader:(id<UrlLoader>)urlLoader - preloadProvider:(id<PreloadProvider>)preload; + preloadProvider:(id<PreloadProvider>)preload + dispatcher:(id<BrowserCommands>)dispatcher; // Returns a new keyboard commands coordinator to handle keyboard commands. - (KeyCommandsProvider*)newKeyCommandsProvider;
diff --git a/ios/chrome/browser/ui/browser_view_controller_dependency_factory.mm b/ios/chrome/browser/ui/browser_view_controller_dependency_factory.mm index 3708124..36a34f2 100644 --- a/ios/chrome/browser/ui/browser_view_controller_dependency_factory.mm +++ b/ios/chrome/browser/ui/browser_view_controller_dependency_factory.mm
@@ -81,11 +81,13 @@ - (WebToolbarController*) newWebToolbarControllerWithDelegate:(id<WebToolbarDelegate>)delegate urlLoader:(id<UrlLoader>)urlLoader - preloadProvider:(id<PreloadProvider>)preload { + preloadProvider:(id<PreloadProvider>)preload + dispatcher:(id<BrowserCommands>)dispatcher { return [[WebToolbarController alloc] initWithDelegate:delegate urlLoader:urlLoader browserState:browserState_ - preloadProvider:preload]; + preloadProvider:preload + dispatcher:dispatcher]; } - (KeyCommandsProvider*)newKeyCommandsProvider {
diff --git a/ios/chrome/browser/ui/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view_controller_unittest.mm index 11d3e6ee..72f2e73 100644 --- a/ios/chrome/browser/ui/browser_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/browser_view_controller_unittest.mm
@@ -236,7 +236,8 @@ [[[factory stub] andReturn:nil] newWebToolbarControllerWithDelegate:[OCMArg any] urlLoader:[OCMArg any] - preloadProvider:[OCMArg any]]; + preloadProvider:[OCMArg any] + dispatcher:[OCMArg any]]; [[[factory stub] andReturn:shareController_] shareControllerInstance]; [[[factory stub] andReturn:passKitViewController_] newPassKitViewControllerForPass:nil];
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h index 94d30e1e..ee911d0 100644 --- a/ios/chrome/browser/ui/commands/browser_commands.h +++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -9,9 +9,15 @@ // which in practice is the BrowserViewController instance displaying the tab. @protocol BrowserCommands -// Close the current tab. +// Closes the current tab. - (void)closeCurrentTab; +// Navigates backwards in the current tab's history. +- (void)goBack; + +// Navigates forwards in the current tab's history. +- (void)goForward; + @end #endif // IOS_CHROME_BROWSER_UI_COMMANDS_BROWSER_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/commands/ios_command_ids.h b/ios/chrome/browser/ui/commands/ios_command_ids.h index 2a2d01b..58a4aa3 100644 --- a/ios/chrome/browser/ui/commands/ios_command_ids.h +++ b/ios/chrome/browser/ui/commands/ios_command_ids.h
@@ -13,8 +13,6 @@ // also need to be updated. // clang-format off -#define IDC_BACK 33000 -#define IDC_FORWARD 33001 #define IDC_RELOAD 33002 #define IDC_STOP 33006 #define IDC_NEW_TAB 34014
diff --git a/ios/chrome/browser/ui/key_commands_provider.mm b/ios/chrome/browser/ui/key_commands_provider.mm index ffabada..e09cb7c 100644 --- a/ios/chrome/browser/ui/key_commands_provider.mm +++ b/ios/chrome/browser/ui/key_commands_provider.mm
@@ -39,22 +39,36 @@ const BOOL hasTabs = [consumer tabsCount] > 0; const BOOL useRTLLayout = UseRTLLayout(); - const NSInteger browseLeft = useRTLLayout ? IDC_FORWARD : IDC_BACK; - const NSInteger browseRight = useRTLLayout ? IDC_BACK : IDC_FORWARD; + + // Blocks for navigating forward/back. + void (^browseLeft)(); + void (^browseRight)(); + if (useRTLLayout) { + browseLeft = ^{ + if ([weakConsumer canGoForward]) + [weakDispatcher goForward]; + }; + browseRight = ^{ + if ([weakConsumer canGoBack]) + [weakDispatcher goBack]; + }; + } else { + browseLeft = ^{ + if ([weakConsumer canGoBack]) + [weakDispatcher goBack]; + }; + browseRight = ^{ + if ([weakConsumer canGoForward]) + [weakDispatcher goForward]; + }; + } + const int browseLeftDescriptionID = useRTLLayout ? IDS_IOS_KEYBOARD_HISTORY_FORWARD : IDS_IOS_KEYBOARD_HISTORY_BACK; const int browseRightDescriptionID = useRTLLayout ? IDS_IOS_KEYBOARD_HISTORY_BACK : IDS_IOS_KEYBOARD_HISTORY_FORWARD; - BOOL (^canBrowseLeft)() = ^() { - return useRTLLayout ? [weakConsumer canGoForward] - : [weakConsumer canGoBack]; - }; - BOOL (^canBrowseRight)() = ^() { - return useRTLLayout ? [weakConsumer canGoBack] - : [weakConsumer canGoForward]; - }; // Initialize the array of commands with an estimated capacity. NSMutableArray* keyCommands = [NSMutableArray arrayWithCapacity:32]; @@ -155,18 +169,14 @@ title:l10n_util::GetNSStringWithFixup( browseLeftDescriptionID) action:^{ - if (canBrowseLeft()) { - execute(browseLeft); - } + browseLeft(); }], [UIKeyCommand cr_keyCommandWithInput:UIKeyInputRightArrow modifierFlags:UIKeyModifierCommand title:l10n_util::GetNSStringWithFixup( browseRightDescriptionID) action:^{ - if (canBrowseRight()) { - execute(browseRight); - } + browseRight(); }], ]]; } @@ -225,17 +235,13 @@ modifierFlags:UIKeyModifierCommand title:nil action:^{ - if (canBrowseLeft()) { - execute(browseLeft); - } + browseLeft(); }], [UIKeyCommand cr_keyCommandWithInput:@"]" modifierFlags:UIKeyModifierCommand title:nil action:^{ - if (canBrowseRight()) { - execute(browseRight); - } + browseRight(); }], [UIKeyCommand cr_keyCommandWithInput:@"." modifierFlags:UIKeyModifierCommand
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm b/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm index 0381854..13e228c 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm
@@ -70,8 +70,8 @@ DCHECK(!_toolbarController); DCHECK(readingListModel); - _toolbarController = [[NewTabPageToolbarController alloc] init]; - [_toolbarController setDispatcher:dispatcher]; + _toolbarController = + [[NewTabPageToolbarController alloc] initWithDispatcher:dispatcher]; _toolbarController.readingListModel = readingListModel; UIView* toolbarView = [_toolbarController view];
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.h b/ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.h index 8e90625..58533816 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.h +++ b/ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.h
@@ -7,9 +7,10 @@ #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h" +@protocol BrowserCommands; @protocol GoogleLandingDataSource; -@protocol UrlLoader; @protocol OmniboxFocuser; +@protocol UrlLoader; @protocol WebToolbarDelegate; // New tab page specific toolbar. The background view is hidden and the @@ -20,10 +21,13 @@ // Designated initializer. The underlying ToolbarController is initialized with // ToolbarControllerStyleLightMode. -- (instancetype)init; +- (instancetype)initWithDispatcher: + (id<BrowserCommands, OmniboxFocuser, UrlLoader, WebToolbarDelegate>) + dispatcher; -@property(nonatomic, weak) id<UrlLoader, OmniboxFocuser, WebToolbarDelegate> - dispatcher; +@property(nonatomic, readonly, weak) + id<BrowserCommands, OmniboxFocuser, UrlLoader, WebToolbarDelegate> + dispatcher; // |YES| if the toolbar can show the forward arrow. - (void)setCanGoForward:(BOOL)canGoForward;
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.mm b/ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.mm index deeb6f8..7d601fa 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.mm
@@ -62,8 +62,11 @@ @synthesize canGoForward = _canGoForward; @synthesize canGoBack = _canGoBack; -- (instancetype)init { - self = [super initWithStyle:ToolbarControllerStyleLightMode]; +- (instancetype)initWithDispatcher: + (id<BrowserCommands, OmniboxFocuser, UrlLoader, WebToolbarDelegate>) + dispatcher { + self = [super initWithStyle:ToolbarControllerStyleLightMode + dispatcher:dispatcher]; if (self) { [self.backgroundView setHidden:YES]; @@ -125,13 +128,18 @@ initWithTarget:self action:@selector(handleLongPress:)]; [_backButton addGestureRecognizer:backLongPress]; + [_backButton addTarget:self.dispatcher + action:@selector(goBack) + forControlEvents:UIControlEventTouchUpInside]; + UILongPressGestureRecognizer* forwardLongPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; [_forwardButton addGestureRecognizer:forwardLongPress]; - [_backButton setTag:IDC_BACK]; - [_forwardButton setTag:IDC_FORWARD]; + [_forwardButton addTarget:self.dispatcher + action:@selector(goForward) + forControlEvents:UIControlEventTouchUpInside]; [_omniboxFocuser addTarget:self action:@selector(focusOmnibox:)
diff --git a/ios/chrome/browser/ui/omnibox_perftest.mm b/ios/chrome/browser/ui/omnibox_perftest.mm index 66538de..3f76fa3 100644 --- a/ios/chrome/browser/ui/omnibox_perftest.mm +++ b/ios/chrome/browser/ui/omnibox_perftest.mm
@@ -107,7 +107,8 @@ initWithDelegate:webToolbarDelegate urlLoader:urlLoader browserState:chrome_browser_state_.get() - preloadProvider:nil]; + preloadProvider:nil + dispatcher:nil]; UIView* toolbarView = [toolbar_ view]; CGRect toolbarFrame = toolbarView.frame; toolbarFrame.origin = CGPointZero;
diff --git a/ios/chrome/browser/ui/stack_view/stack_view_toolbar_controller.mm b/ios/chrome/browser/ui/stack_view/stack_view_toolbar_controller.mm index 8960e4f9..357dd92 100644 --- a/ios/chrome/browser/ui/stack_view/stack_view_toolbar_controller.mm +++ b/ios/chrome/browser/ui/stack_view/stack_view_toolbar_controller.mm
@@ -30,7 +30,7 @@ } - (instancetype)initWithStackViewToolbar { - self = [super initWithStyle:ToolbarControllerStyleDarkMode]; + self = [super initWithStyle:ToolbarControllerStyleDarkMode dispatcher:nil]; if (self) { _stackViewToolbar = [[UIView alloc] initWithFrame:[self specificControlsArea]];
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller.h b/ios/chrome/browser/ui/toolbar/toolbar_controller.h index fd9c388..d85fca6 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_controller.h +++ b/ios/chrome/browser/ui/toolbar/toolbar_controller.h
@@ -18,6 +18,7 @@ #include "ios/chrome/browser/ui/ui_util.h" #import "ios/chrome/browser/ui/util/relaxed_bounds_constraints_hittest.h" +@protocol BrowserCommands; class ReadingListModel; @class ToolsMenuConfiguration; @@ -134,8 +135,15 @@ // The reading list model reflected by the toolbar. @property(nonatomic, readwrite, assign) ReadingListModel* readingListModel; -// Designated initializer. |style| determines how the toolbar draws itself. +// The command dispatcher this and any subordinate objects should use. +@property(nonatomic, readonly, weak) id<BrowserCommands> dispatcher; + +// Designated initializer. +// |style| determines how the toolbar draws itself. +// |dispatcher| is is the dispatcher for calling methods handled in other +// parts of the app. - (instancetype)initWithStyle:(ToolbarControllerStyle)style + dispatcher:(id<BrowserCommands>)dispatcher NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/toolbar_controller.mm index 9ceeae4..d3cdf8d1 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_controller.mm +++ b/ios/chrome/browser/ui/toolbar/toolbar_controller.mm
@@ -249,6 +249,7 @@ @synthesize shadowView = shadowView_; @synthesize toolsPopupController = toolsPopupController_; @synthesize style = style_; +@synthesize dispatcher = dispatcher_; - (void)setReadingListModel:(ReadingListModel*)readingListModel { readingListModel_ = readingListModel; @@ -259,10 +260,12 @@ } } -- (instancetype)initWithStyle:(ToolbarControllerStyle)style { +- (instancetype)initWithStyle:(ToolbarControllerStyle)style + dispatcher:(id<BrowserCommands>)dispatcher { self = [super init]; if (self) { style_ = style; + dispatcher_ = dispatcher; DCHECK_LT(style_, ToolbarControllerStyleMaxStyles); InterfaceIdiom idiom = IsIPadIdiom() ? IPAD_IDIOM : IPHONE_IDIOM; @@ -558,9 +561,12 @@ [button addTarget:self action:@selector(recordUserMetrics:) forControlEvents:UIControlEventTouchUpInside]; - [button addTarget:button - action:@selector(chromeExecuteCommand:) - forControlEvents:UIControlEventTouchUpInside]; + // Only register buttons with defined tags for -chromeExecuteCommand:. + if (button.tag) { + [button addTarget:button + action:@selector(chromeExecuteCommand:) + forControlEvents:UIControlEventTouchUpInside]; + } } - (CGRect)shareButtonAnchorRect {
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller_unittest.mm b/ios/chrome/browser/ui/toolbar/toolbar_controller_unittest.mm index 06979e0..6064f5c 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_controller_unittest.mm +++ b/ios/chrome/browser/ui/toolbar/toolbar_controller_unittest.mm
@@ -35,8 +35,9 @@ protected: void SetUp() override { PlatformTest::SetUp(); - toolbarController_ = [[ToolbarController alloc] - initWithStyle:ToolbarControllerStyleLightMode]; + toolbarController_ = + [[ToolbarController alloc] initWithStyle:ToolbarControllerStyleLightMode + dispatcher:nil]; } ToolbarController* toolbarController_;
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.h b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.h index 38f3812..4ae4ce5 100644 --- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.h +++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.h
@@ -13,6 +13,7 @@ #include "ios/public/provider/chrome/browser/voice/voice_search_controller_delegate.h" #include "ios/web/public/navigation_item_list.h" +@protocol BrowserCommands; @protocol PreloadProvider; @class Tab; @protocol ToolbarFrameDelegate; @@ -88,7 +89,8 @@ @property(nonatomic, weak, readonly) id<UrlLoader> urlLoader; // Mark inherited initializer as unavailable. -- (instancetype)initWithStyle:(ToolbarControllerStyle)style NS_UNAVAILABLE; +- (instancetype)initWithStyle:(ToolbarControllerStyle)style + dispatcher:(id<BrowserCommands>)dispatcher NS_UNAVAILABLE; // Create a new web toolbar controller whose omnibox is backed by // |browserState|. @@ -96,6 +98,7 @@ urlLoader:(id<UrlLoader>)urlLoader browserState:(ios::ChromeBrowserState*)browserState preloadProvider:(id<PreloadProvider>)preloader + dispatcher:(id<BrowserCommands>)dispatcher NS_DESIGNATED_INITIALIZER; // Called when the browser state this object was initialized with is being
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm index bedfe15b..d29d4d4 100644 --- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm +++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
@@ -37,6 +37,7 @@ #import "ios/chrome/browser/ui/animation_util.h" #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" +#import "ios/chrome/browser/ui/commands/browser_commands.h" #import "ios/chrome/browser/ui/commands/generic_chrome_command.h" #include "ios/chrome/browser/ui/commands/ios_command_ids.h" #import "ios/chrome/browser/ui/history/tab_history_popup_controller.h" @@ -369,7 +370,8 @@ - (instancetype)initWithDelegate:(id<WebToolbarDelegate>)delegate urlLoader:(id<UrlLoader>)urlLoader browserState:(ios::ChromeBrowserState*)browserState - preloadProvider:(id<PreloadProvider>)preloader { + preloadProvider:(id<PreloadProvider>)preloader + dispatcher:(id<BrowserCommands>)dispatcher { DCHECK(delegate); DCHECK(urlLoader); DCHECK(browserState); @@ -377,8 +379,10 @@ _urlLoader = urlLoader; _browserState = browserState; _incognito = browserState->IsOffTheRecord(); - self = [super initWithStyle:(_incognito ? ToolbarControllerStyleIncognitoMode - : ToolbarControllerStyleLightMode)]; + ToolbarControllerStyle style = + (_incognito ? ToolbarControllerStyleIncognitoMode + : ToolbarControllerStyleLightMode); + self = [super initWithStyle:style dispatcher:dispatcher]; if (!self) return nil; @@ -501,6 +505,14 @@ [_voiceSearchButton setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeadingMargin()]; + + // Assign tags before calling -setUpButton, since only buttons with tags + // have -chromeExecuteCommand added as a target. + [_reloadButton setTag:IDC_RELOAD]; + [_stopButton setTag:IDC_STOP]; + [_starButton setTag:IDC_BOOKMARK_PAGE]; + [_voiceSearchButton setTag:IDC_VOICE_SEARCH]; + [_webToolbar addSubview:_voiceSearchButton]; [_webToolbar addSubview:_starButton]; [_webToolbar addSubview:_stopButton]; @@ -542,6 +554,14 @@ hasDisabledImage:YES synchronously:NO]; + // Assign targets for buttons using the dispatcher. + [_backButton addTarget:self.dispatcher + action:@selector(goBack) + forControlEvents:UIControlEventTouchUpInside]; + [_forwardButton addTarget:self.dispatcher + action:@selector(goForward) + forControlEvents:UIControlEventTouchUpInside]; + _backButtonMode = ToolbarButtonModeNormal; _forwardButtonMode = ToolbarButtonModeNormal; UILongPressGestureRecognizer* backLongPress = @@ -569,13 +589,6 @@ action:@selector(cancelOmniboxEdit) forControlEvents:UIControlEventTouchUpInside]; - [_backButton setTag:IDC_BACK]; - [_forwardButton setTag:IDC_FORWARD]; - [_reloadButton setTag:IDC_RELOAD]; - [_stopButton setTag:IDC_STOP]; - [_starButton setTag:IDC_BOOKMARK_PAGE]; - [_voiceSearchButton setTag:IDC_VOICE_SEARCH]; - SetA11yLabelAndUiAutomationName(_backButton, IDS_ACCNAME_BACK, @"Back"); SetA11yLabelAndUiAutomationName(_forwardButton, IDS_ACCNAME_FORWARD, @"Forward");
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller_unittest.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller_unittest.mm index 500e4b24..163ecf7 100644 --- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller_unittest.mm +++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller_unittest.mm
@@ -77,7 +77,8 @@ initWithDelegate:delegate urlLoader:urlLoader browserState:chrome_browser_state_.get() - preloadProvider:nil]; + preloadProvider:nil + dispatcher:nil]; [web_toolbar_controller_ setUnitTesting:YES]; } void TearDown() override {
diff --git a/ios/chrome/browser/web/cache_egtest.mm b/ios/chrome/browser/web/cache_egtest.mm index 75ed8f5..60805bd 100644 --- a/ios/chrome/browser/web/cache_egtest.mm +++ b/ios/chrome/browser/web/cache_egtest.mm
@@ -169,9 +169,7 @@ // Navigates back to the previous webpage. // TODO(crbug.com/638674): Evaluate if this can move to shared code. - (void)goBack { - GenericChromeCommand* backCommand = - [[GenericChromeCommand alloc] initWithTag:IDC_BACK]; - chrome_test_util::RunCommandWithActiveViewController(backCommand); + [chrome_test_util::BrowserCommandDispatcherForMainBVC() goBack]; [ChromeEarlGrey waitForPageToFinishLoading]; }
diff --git a/ios/chrome/browser/web/visible_url_egtest.mm b/ios/chrome/browser/web/visible_url_egtest.mm index c83999d..70ac2a1 100644 --- a/ios/chrome/browser/web/visible_url_egtest.mm +++ b/ios/chrome/browser/web/visible_url_egtest.mm
@@ -519,12 +519,9 @@ performAction:grey_tap()]; [ChromeEarlGrey waitForWebViewContainingText:kTestPage1]; - // Quickly (using chrome command) navigate forward twice and wait for - // kChromeUIVersionURL to load. - GenericChromeCommand* forwardCommand = - [[GenericChromeCommand alloc] initWithTag:IDC_FORWARD]; - chrome_test_util::RunCommandWithActiveViewController(forwardCommand); - chrome_test_util::RunCommandWithActiveViewController(forwardCommand); + // Quickly navigate forward twice and wait for kChromeUIVersionURL to load. + [chrome_test_util::BrowserCommandDispatcherForMainBVC() goForward]; + [chrome_test_util::BrowserCommandDispatcherForMainBVC() goForward]; const std::string version = version_info::GetVersionNumber(); [ChromeEarlGrey waitForWebViewContainingText:version];
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm index 2eff22544..c0aba2f 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -124,16 +124,14 @@ } + (void)goBack { - base::scoped_nsobject<GenericChromeCommand> reloadCommand( - [[GenericChromeCommand alloc] initWithTag:IDC_BACK]); - chrome_test_util::RunCommandWithActiveViewController(reloadCommand); + [chrome_test_util::BrowserCommandDispatcherForMainBVC() goBack]; + [ChromeEarlGrey waitForPageToFinishLoading]; } + (void)goForward { - base::scoped_nsobject<GenericChromeCommand> reloadCommand( - [[GenericChromeCommand alloc] initWithTag:IDC_FORWARD]); - chrome_test_util::RunCommandWithActiveViewController(reloadCommand); + [chrome_test_util::BrowserCommandDispatcherForMainBVC() goForward]; + [ChromeEarlGrey waitForPageToFinishLoading]; }
diff --git a/media/BUILD.gn b/media/BUILD.gn index 5436d6f3..bd12c8a 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -594,6 +594,13 @@ "base/vector_math.h", "base/vector_math_testing.h", ] + if (is_mac) { + # These need to be included here because audio_latency.cc depends on them. + sources += [ + "base/mac/audio_latency_mac.cc", + "base/mac/audio_latency_mac.h", + ] + } configs += [ ":media_config", ":media_implementation",
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc index 904ee12..8e45f5e 100644 --- a/media/audio/audio_manager_unittest.cc +++ b/media/audio/audio_manager_unittest.cc
@@ -26,6 +26,7 @@ #include "media/audio/fake_audio_log_factory.h" #include "media/audio/fake_audio_manager.h" #include "media/audio/test_audio_thread.h" +#include "media/base/limits.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,6 +34,11 @@ #include "media/audio/alsa/audio_manager_alsa.h" #endif // defined(USE_ALSA) +#if defined(OS_MACOSX) +#include "media/audio/mac/audio_manager_mac.h" +#include "media/base/mac/audio_latency_mac.h" +#endif + #if defined(OS_WIN) #include "base/win/scoped_com_initializer.h" #include "media/audio/win/audio_manager_win.h" @@ -677,4 +683,97 @@ audio_manager_->DisableOutputDebugRecording(); } +#if defined(OS_MACOSX) || defined(USE_CRAS) +class TestAudioSourceCallback : public AudioOutputStream::AudioSourceCallback { + public: + TestAudioSourceCallback(int expected_frames_per_buffer, + base::WaitableEvent* event) + : expected_frames_per_buffer_(expected_frames_per_buffer), + event_(event){}; + ~TestAudioSourceCallback() override{}; + + int OnMoreData(base::TimeDelta, + base::TimeTicks, + int, + AudioBus* dest) override { + EXPECT_EQ(dest->frames(), expected_frames_per_buffer_); + event_->Signal(); + return 0; + } + + void OnError() override { FAIL(); } + + private: + DISALLOW_COPY_AND_ASSIGN(TestAudioSourceCallback); + + const int expected_frames_per_buffer_; + base::WaitableEvent* event_; +}; + +// Test that we can create an AudioOutputStream with kMinAudioBufferSize and +// kMaxAudioBufferSize and that the callback AudioBus is the expected size. +TEST_F(AudioManagerTest, CheckMinMaxAudioBufferSizeCallbacks) { + ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable()); + +#if defined(OS_MACOSX) + CreateAudioManagerForTesting<AudioManagerMac>(); +#elif defined(USE_CRAS) + CreateAudioManagerForTesting<AudioManagerCras>(); +#endif + + DCHECK(audio_manager_); + + AudioParameters default_params; + GetDefaultOutputStreamParameters(&default_params); + ASSERT_LT(default_params.frames_per_buffer(), + media::limits::kMaxAudioBufferSize); + +#if defined(OS_MACOSX) + // On OSX the preferred output buffer size is higher than the minimum + // but users may request the minimum size explicitly. + ASSERT_GT(default_params.frames_per_buffer(), + GetMinAudioBufferSizeMacOS(media::limits::kMinAudioBufferSize, + default_params.sample_rate())); +#elif defined(USE_CRAS) + // On CRAS the preferred output buffer size varies per board and may be as low + // as the minimum for some boards. + ASSERT_GE(default_params.frames_per_buffer(), + media::limits::kMinAudioBufferSize); +#else + NOTREACHED(); +#endif + + AudioOutputStream* stream; + base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, + base::WaitableEvent::InitialState::NOT_SIGNALED); + + // Create an output stream with the minimum buffer size parameters and ensure + // that no errors are returned. + AudioParameters min_params = default_params; + min_params.set_frames_per_buffer(media::limits::kMinAudioBufferSize); + stream = audio_manager_->MakeAudioOutputStreamProxy(min_params, ""); + ASSERT_TRUE(stream); + EXPECT_TRUE(stream->Open()); + event.Reset(); + TestAudioSourceCallback min_source(min_params.frames_per_buffer(), &event); + stream->Start(&min_source); + event.Wait(); + stream->Stop(); + stream->Close(); + + // Verify the same for the maximum buffer size. + AudioParameters max_params = default_params; + max_params.set_frames_per_buffer(media::limits::kMaxAudioBufferSize); + stream = audio_manager_->MakeAudioOutputStreamProxy(max_params, ""); + ASSERT_TRUE(stream); + EXPECT_TRUE(stream->Open()); + event.Reset(); + TestAudioSourceCallback max_source(max_params.frames_per_buffer(), &event); + stream->Start(&max_source); + event.Wait(); + stream->Stop(); + stream->Close(); +} +#endif + } // namespace media
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc index 2e6d346..f3beab2 100644 --- a/media/audio/cras/audio_manager_cras.cc +++ b/media/audio/cras/audio_manager_cras.cc
@@ -24,6 +24,7 @@ #include "media/audio/cras/cras_input.h" #include "media/audio/cras/cras_unified.h" #include "media/base/channel_layout.h" +#include "media/base/limits.h" #include "media/base/localized_strings.h" // cras_util.h headers pull in min/max macros... @@ -40,10 +41,6 @@ // Default sample rate for input and output streams. const int kDefaultSampleRate = 48000; -// Define bounds for the output buffer size. -const int kMinimumOutputBufferSize = 512; -const int kMaximumOutputBufferSize = 8192; - // Default input buffer size. const int kDefaultInputBufferSize = 1024; @@ -308,7 +305,7 @@ return 768; else if (board == "samus") return 256; - return kMinimumOutputBufferSize; + return 512; } AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters( @@ -323,8 +320,9 @@ bits_per_sample = input_params.bits_per_sample(); channel_layout = input_params.channel_layout(); buffer_size = - std::min(kMaximumOutputBufferSize, - std::max(buffer_size, input_params.frames_per_buffer())); + std::min(static_cast<int>(limits::kMaxAudioBufferSize), + std::max(static_cast<int>(limits::kMinAudioBufferSize), + input_params.frames_per_buffer())); } int user_buffer_size = GetUserBufferSize();
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc index 09b6433..8478e0f 100644 --- a/media/audio/mac/audio_manager_mac.cc +++ b/media/audio/mac/audio_manager_mac.cc
@@ -27,6 +27,7 @@ #include "media/base/bind_to_current_loop.h" #include "media/base/channel_layout.h" #include "media/base/limits.h" +#include "media/base/mac/audio_latency_mac.h" #include "media/base/media_switches.h" namespace media { @@ -34,10 +35,6 @@ // Maximum number of output streams that can be open simultaneously. static const int kMaxOutputStreams = 50; -// Define bounds for for low-latency input and output streams. -static const int kMinimumInputOutputBufferSize = 128; -static const int kMaximumInputOutputBufferSize = 4096; - // Default sample-rate on most Apple hardware. static const int kFallbackSampleRate = 44100; @@ -836,11 +833,17 @@ // Allow pass through buffer sizes. If concurrent input and output streams // exist, they will use the smallest buffer size amongst them. As such, each // stream must be able to FIFO requests appropriately when this happens. - int buffer_size = ChooseBufferSize(false, hardware_sample_rate); + int buffer_size; if (has_valid_input_params) { + // If passed in via the input_params we allow buffer sizes to go as + // low as the the kMinAudioBufferSize, ignoring what + // ChooseBufferSize() normally returns. buffer_size = - std::min(kMaximumInputOutputBufferSize, - std::max(input_params.frames_per_buffer(), buffer_size)); + std::min(static_cast<int>(limits::kMaxAudioBufferSize), + std::max(input_params.frames_per_buffer(), + static_cast<int>(limits::kMinAudioBufferSize))); + } else { + buffer_size = ChooseBufferSize(false, hardware_sample_rate); } int hardware_channels; @@ -887,7 +890,7 @@ } int AudioManagerMac::ChooseBufferSize(bool is_input, int sample_rate) { - // kMinimumInputOutputBufferSize is too small for the output side because + // kMinAudioBufferSize is too small for the output side because // CoreAudio can get into under-run if the renderer fails delivering data // to the browser within the allowed time by the OS. The workaround is to // use 256 samples as the default output buffer size for sample rates @@ -895,20 +898,12 @@ // TODO(xians): Remove this workaround after WebAudio supports user defined // buffer size. See https://github.com/WebAudio/web-audio-api/issues/348 // for details. - int buffer_size = is_input ? - kMinimumInputOutputBufferSize : 2 * kMinimumInputOutputBufferSize; + int buffer_size = + is_input ? limits::kMinAudioBufferSize : 2 * limits::kMinAudioBufferSize; const int user_buffer_size = GetUserBufferSize(); - if (user_buffer_size) { - buffer_size = user_buffer_size; - } else if (sample_rate > 48000) { - // The default buffer size is too small for higher sample rates and may lead - // to glitching. Adjust upwards by multiples of the default size. - if (sample_rate <= 96000) - buffer_size = 2 * kMinimumInputOutputBufferSize; - else if (sample_rate <= 192000) - buffer_size = 4 * kMinimumInputOutputBufferSize; - } - + buffer_size = user_buffer_size + ? user_buffer_size + : GetMinAudioBufferSizeMacOS(buffer_size, sample_rate); return buffer_size; }
diff --git a/media/base/audio_latency.cc b/media/base/audio_latency.cc index 61b3724..3c657a4 100644 --- a/media/base/audio_latency.cc +++ b/media/base/audio_latency.cc
@@ -11,6 +11,11 @@ #include "base/logging.h" #include "base/time/time.h" #include "build/build_config.h" +#include "media/base/limits.h" + +#if defined(OS_MACOSX) +#include "media/base/mac/audio_latency_mac.h" +#endif namespace media { @@ -130,16 +135,32 @@ int AudioLatency::GetExactBufferSize(base::TimeDelta duration, int sample_rate, int hardware_buffer_size) { - const double requested_buffer_size = duration.InSecondsF() * sample_rate; - DCHECK_NE(0, hardware_buffer_size); +// Other platforms do not currently support custom buffer sizes. +#if !defined(OS_MACOSX) && !defined(USE_CRAS) + return hardware_buffer_size; +#else + const double requested_buffer_size = duration.InSecondsF() * sample_rate; + int minimum_buffer_size = hardware_buffer_size; + +// On OSX and CRAS the preferred buffer size is larger than the minimum, +// however we allow values down to the minimum if requested explicitly. +#if defined(OS_MACOSX) + minimum_buffer_size = + GetMinAudioBufferSizeMacOS(limits::kMinAudioBufferSize, sample_rate); +#elif defined(USE_CRAS) + minimum_buffer_size = limits::kMinAudioBufferSize; +#endif + // Round the requested size to the nearest multiple of the hardware size const int buffer_size = std::round(std::max(requested_buffer_size, 1.0) / hardware_buffer_size) * hardware_buffer_size; - return std::max(buffer_size, hardware_buffer_size); + return std::min(static_cast<int>(limits::kMaxAudioBufferSize), + std::max(buffer_size, minimum_buffer_size)); +#endif } } // namespace media
diff --git a/media/base/limits.h b/media/base/limits.h index f936c8b..2a73c59 100644 --- a/media/base/limits.h +++ b/media/base/limits.h
@@ -7,6 +7,8 @@ #ifndef MEDIA_BASE_LIMITS_H_ #define MEDIA_BASE_LIMITS_H_ +#include "build/build_config.h" + namespace media { namespace limits { @@ -58,6 +60,17 @@ kMaxInitDataLength = 64 * 1024, // 64 KB kMaxSessionResponseLength = 64 * 1024, // 64 KB kMaxKeySystemLength = 256, + +// Minimum and maximum buffer sizes for certain audio platforms. +#if defined(OS_MACOSX) + kMinAudioBufferSize = 128, + kMaxAudioBufferSize = 4096, +#elif defined(USE_CRAS) + // Though CRAS has different per-board defaults, allow explicitly requesting + // this buffer size on any board. + kMinAudioBufferSize = 256, + kMaxAudioBufferSize = 8192, +#endif }; } // namespace limits
diff --git a/media/base/mac/audio_latency_mac.cc b/media/base/mac/audio_latency_mac.cc new file mode 100644 index 0000000..223e3ad8 --- /dev/null +++ b/media/base/mac/audio_latency_mac.cc
@@ -0,0 +1,23 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/mac/audio_latency_mac.h" +#include "media/base/limits.h" + +namespace media { + +int GetMinAudioBufferSizeMacOS(int min_buffer_size, int sample_rate) { + int buffer_size = min_buffer_size; + if (sample_rate > 48000) { + // The default buffer size is too small for higher sample rates and may lead + // to glitching. Adjust upwards by multiples of the default size. + if (sample_rate <= 96000) + buffer_size = 2 * limits::kMinAudioBufferSize; + else if (sample_rate <= 192000) + buffer_size = 4 * limits::kMinAudioBufferSize; + } + return buffer_size; +} + +} // namespace media
diff --git a/media/base/mac/audio_latency_mac.h b/media/base/mac/audio_latency_mac.h new file mode 100644 index 0000000..e6ad4ef7 --- /dev/null +++ b/media/base/mac/audio_latency_mac.h
@@ -0,0 +1,18 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_MAC_AUDIO_LATENCY_MAC_H_ +#define MEDIA_BASE_MAC_AUDIO_LATENCY_MAC_H_ + +#include "base/macros.h" +#include "media/base/media_export.h" + +namespace media { + +MEDIA_EXPORT int GetMinAudioBufferSizeMacOS(int min_buffer_size, + int sample_rate); + +} // namespace media + +#endif // MEDIA_BASE_MAC_AUDIO_LATENCY_MAC_H_
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc index a218682..8afb950 100644 --- a/media/filters/gpu_video_decoder.cc +++ b/media/filters/gpu_video_decoder.cc
@@ -82,24 +82,22 @@ // resources. enum { kMaxInFlightDecodes = 4 }; +struct GpuVideoDecoder::PendingDecoderBuffer { + PendingDecoderBuffer(std::unique_ptr<SHMBuffer> s, + const scoped_refptr<DecoderBuffer>& b, + const DecodeCB& done_cb) + : shm_buffer(std::move(s)), buffer(b), done_cb(done_cb) {} + std::unique_ptr<SHMBuffer> shm_buffer; + scoped_refptr<DecoderBuffer> buffer; + DecodeCB done_cb; +}; + GpuVideoDecoder::SHMBuffer::SHMBuffer(std::unique_ptr<base::SharedMemory> m, size_t s) : shm(std::move(m)), size(s) {} GpuVideoDecoder::SHMBuffer::~SHMBuffer() {} -GpuVideoDecoder::PendingDecoderBuffer::PendingDecoderBuffer( - SHMBuffer* s, - const scoped_refptr<DecoderBuffer>& b, - const DecodeCB& done_cb) - : shm_buffer(s), buffer(b), done_cb(done_cb) { -} - -GpuVideoDecoder::PendingDecoderBuffer::PendingDecoderBuffer( - const PendingDecoderBuffer& other) = default; - -GpuVideoDecoder::PendingDecoderBuffer::~PendingDecoderBuffer() {} - GpuVideoDecoder::BufferData::BufferData(int32_t bbid, base::TimeDelta ts, const gfx::Rect& vr, @@ -461,9 +459,9 @@ next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; DCHECK( !base::ContainsKey(bitstream_buffers_in_decoder_, bitstream_buffer.id())); - bitstream_buffers_in_decoder_.insert(std::make_pair( + bitstream_buffers_in_decoder_.emplace( bitstream_buffer.id(), - PendingDecoderBuffer(shm_buffer.release(), buffer, decode_cb))); + PendingDecoderBuffer(std::move(shm_buffer), buffer, decode_cb)); DCHECK_LE(static_cast<int>(bitstream_buffers_in_decoder_.size()), kMaxInFlightDecodes); RecordBufferData(bitstream_buffer, *buffer.get()); @@ -763,14 +761,14 @@ return NULL; return base::MakeUnique<SHMBuffer>(std::move(shm), size_to_allocate); } - std::unique_ptr<SHMBuffer> ret(available_shm_segments_.back()); + std::unique_ptr<SHMBuffer> ret(std::move(available_shm_segments_.back())); available_shm_segments_.pop_back(); return ret; } void GpuVideoDecoder::PutSHM(std::unique_ptr<SHMBuffer> shm_buffer) { DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); - available_shm_segments_.push_back(shm_buffer.release()); + available_shm_segments_.push_back(std::move(shm_buffer)); } void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32_t id) { @@ -785,7 +783,7 @@ return; } - PutSHM(base::WrapUnique(it->second.shm_buffer)); + PutSHM(std::move(it->second.shm_buffer)); it->second.done_cb.Run(state_ == kError ? DecodeStatus::DECODE_ERROR : DecodeStatus::OK); bitstream_buffers_in_decoder_.erase(it); @@ -805,15 +803,9 @@ base::ResetAndReturn(&request_overlay_info_cb_) .Run(false, ProvideOverlayInfoCB()); - for (size_t i = 0; i < available_shm_segments_.size(); ++i) { - delete available_shm_segments_[i]; - } - available_shm_segments_.clear(); - for (std::map<int32_t, PendingDecoderBuffer>::iterator it = bitstream_buffers_in_decoder_.begin(); it != bitstream_buffers_in_decoder_.end(); ++it) { - delete it->second.shm_buffer; it->second.done_cb.Run(DecodeStatus::ABORTED); } bitstream_buffers_in_decoder_.clear();
diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h index 634a46a..4463a0e 100644 --- a/media/filters/gpu_video_decoder.h +++ b/media/filters/gpu_video_decoder.h
@@ -99,16 +99,7 @@ }; // A SHMBuffer and the DecoderBuffer its data came from. - struct PendingDecoderBuffer { - PendingDecoderBuffer(SHMBuffer* s, - const scoped_refptr<DecoderBuffer>& b, - const DecodeCB& done_cb); - PendingDecoderBuffer(const PendingDecoderBuffer& other); - ~PendingDecoderBuffer(); - SHMBuffer* shm_buffer; - scoped_refptr<DecoderBuffer> buffer; - DecodeCB done_cb; - }; + struct PendingDecoderBuffer; typedef std::map<int32_t, PictureBuffer> PictureBufferMap; @@ -196,7 +187,7 @@ // Shared-memory buffer pool. Since allocating SHM segments requires a // round-trip to the browser process, we keep allocation out of the // steady-state of the decoder. - std::vector<SHMBuffer*> available_shm_segments_; + std::vector<std::unique_ptr<SHMBuffer>> available_shm_segments_; // Placeholder sync token that was created and validated after the most // recent picture buffers were created.
diff --git a/services/test/user_id/BUILD.gn b/services/test/user_id/BUILD.gn new file mode 100644 index 0000000..b8853ec --- /dev/null +++ b/services/test/user_id/BUILD.gn
@@ -0,0 +1,26 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//services/catalog/public/tools/catalog.gni") +import("//services/service_manager/public/cpp/service.gni") +import("//services/service_manager/public/service_manifest.gni") + +source_set("lib") { + sources = [ + "user_id_service.cc", + "user_id_service.h", + ] + + deps = [ + "//base", + "//services/service_manager/public/cpp", + "//services/service_manager/public/interfaces", + "//services/test/user_id/public/interfaces", + ] +} + +service_manifest("manifest") { + name = "user_id" + source = "manifest.json" +}
diff --git a/services/test/user_id/README.md b/services/test/user_id/README.md new file mode 100644 index 0000000..370b6bfb --- /dev/null +++ b/services/test/user_id/README.md
@@ -0,0 +1 @@ +A simple service that can be used for testing per-user services.
diff --git a/services/test/user_id/manifest.json b/services/test/user_id/manifest.json new file mode 100644 index 0000000..a8708dd --- /dev/null +++ b/services/test/user_id/manifest.json
@@ -0,0 +1,11 @@ +{ + "name": "user_id", + "display_name": "User ID Service", + "interface_provider_specs": { + "service_manager:connector": { + "provides": { + "user_id" : [ "user_id::mojom::UserId" ] + } + } + } +}
diff --git a/services/test/user_id/public/interfaces/BUILD.gn b/services/test/user_id/public/interfaces/BUILD.gn new file mode 100644 index 0000000..a87f2fc --- /dev/null +++ b/services/test/user_id/public/interfaces/BUILD.gn
@@ -0,0 +1,11 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "user_id.mojom", + ] +}
diff --git a/services/test/user_id/public/interfaces/OWNERS b/services/test/user_id/public/interfaces/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/services/test/user_id/public/interfaces/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/services/test/user_id/public/interfaces/user_id.mojom b/services/test/user_id/public/interfaces/user_id.mojom new file mode 100644 index 0000000..a22579f --- /dev/null +++ b/services/test/user_id/public/interfaces/user_id.mojom
@@ -0,0 +1,12 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module user_id.mojom; + +// Provides access to the user ID of the service in which this interface is +// running. +interface UserId { + // Returns the user ID of the service in which this interface is running. + GetUserId() => (string user_id); +};
diff --git a/services/test/user_id/user_id_service.cc b/services/test/user_id/user_id_service.cc new file mode 100644 index 0000000..34a12a8 --- /dev/null +++ b/services/test/user_id/user_id_service.cc
@@ -0,0 +1,42 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/test/user_id/user_id_service.h" + +#include "services/service_manager/public/cpp/service_context.h" + +namespace user_id { + +std::unique_ptr<service_manager::Service> CreateUserIdService() { + return base::MakeUnique<UserIdService>(); +} + +UserIdService::UserIdService() { + registry_.AddInterface<mojom::UserId>( + base::Bind(&UserIdService::BindUserIdRequest, base::Unretained(this))); +} + +UserIdService::~UserIdService() {} + +void UserIdService::OnStart() {} + +void UserIdService::OnBindInterface( + const service_manager::BindSourceInfo& source_info, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) { + registry_.BindInterface(source_info, interface_name, + std::move(interface_pipe)); +} + +void UserIdService::BindUserIdRequest( + const service_manager::BindSourceInfo& source_info, + mojom::UserIdRequest request) { + bindings_.AddBinding(this, std::move(request)); +} + +void UserIdService::GetUserId(GetUserIdCallback callback) { + std::move(callback).Run(context()->identity().user_id()); +} + +} // namespace user_id
diff --git a/services/test/user_id/user_id_service.h b/services/test/user_id/user_id_service.h new file mode 100644 index 0000000..b8174a4 --- /dev/null +++ b/services/test/user_id/user_id_service.h
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_USER_ID_USER_ID_SERVICE_H_ +#define SERVICES_USER_ID_USER_ID_SERVICE_H_ + +#include "mojo/public/cpp/bindings/binding_set.h" +#include "services/service_manager/public/cpp/binder_registry.h" +#include "services/service_manager/public/cpp/service.h" +#include "services/test/user_id/public/interfaces/user_id.mojom.h" + +namespace user_id { + +std::unique_ptr<service_manager::Service> CreateUserIdService(); + +class UserIdService : public service_manager::Service, public mojom::UserId { + public: + UserIdService(); + ~UserIdService() override; + + private: + // service_manager::Service: + void OnStart() override; + void OnBindInterface(const service_manager::BindSourceInfo& source_info, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) override; + + // mojom::UserId: + void GetUserId(GetUserIdCallback callback) override; + + void BindUserIdRequest(const service_manager::BindSourceInfo& source_info, + mojom::UserIdRequest request); + + service_manager::BinderRegistry registry_; + mojo::BindingSet<mojom::UserId> bindings_; + + DISALLOW_COPY_AND_ASSIGN(UserIdService); +}; + +} // namespace user_id + +#endif // SERVICES_USER_ID_USER_ID_SERVICE_H_
diff --git a/third_party/WebKit/LayoutTests/LeakExpectations b/third_party/WebKit/LayoutTests/LeakExpectations index fcdd5e1..9b17571 100644 --- a/third_party/WebKit/LayoutTests/LeakExpectations +++ b/third_party/WebKit/LayoutTests/LeakExpectations
@@ -9,9 +9,6 @@ # ask hajimehoshi@. # ########################################################################### -# FIXME: The below tests fails when the leak detector is disabled. -crbug.com/366029 compositing/fixed-body-background-positioned.html [ Failure Pass ] - # FIXME: The below tests crashes when the leak detector is run on debug builds crbug.com/366043 [ Debug ] fast/history/history-traversal-is-asynchronous.html [ Crash ]
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests index cc25550..e9406fde 100644 --- a/third_party/WebKit/LayoutTests/NeverFixTests +++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -252,7 +252,6 @@ # WPT subdirectories without owners. external/wpt/accelerometer [ WontFix ] external/wpt/assumptions [ WontFix ] -external/wpt/clear-site-data [ WontFix ] external/wpt/css/css-transforms-2 [ WontFix ] external/wpt/css-values [ WontFix ] external/wpt/gyroscope [ WontFix ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations index 3534e37..edbe374 100644 --- a/third_party/WebKit/LayoutTests/W3CImportExpectations +++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -42,6 +42,8 @@ # external/wpt/battery-status [ Pass ] ## Owners: ortuno@chromium.org,scheib@chromium.org # external/wpt/bluetooth [ Pass ] +## Owners: msramek@chromium.org,mkwst@chromium.org +# external/wpt/clear-site-data [ Pass ] ## Owners: none; No tests in the directory. # external/wpt/common [ Pass ] ## Owners: foolip@chromium.org
diff --git a/third_party/WebKit/LayoutTests/external/wpt/WebIDL/ecmascript-binding/legacy-platform-object-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/WebIDL/ecmascript-binding/legacy-platform-object-expected.txt new file mode 100644 index 0000000..52167af6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/WebIDL/ecmascript-binding/legacy-platform-object-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +FAIL Test [[DefineOwnProperty]] with no indexed property setter support. assert_equals: (assert_prop_desc_equals: property 'writable') expected false but got true +FAIL Test [[DefineOwnProperty]] with indexed property setter support. assert_equals: (assert_prop_desc_equals: property 'enumerable') expected true but got false +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/WebIDL/ecmascript-binding/legacy-platform-object.html b/third_party/WebKit/LayoutTests/external/wpt/WebIDL/ecmascript-binding/legacy-platform-object.html new file mode 100644 index 0000000..0c5326f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/WebIDL/ecmascript-binding/legacy-platform-object.html
@@ -0,0 +1,113 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Legacy platform objects</title> +<link rel="help" href="https://heycam.github.io/webidl/#es-legacy-platform-objects"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +function assert_prop_desc_equals(object, property_key, expected) { + let actual = Object.getOwnPropertyDescriptor(object, property_key); + if (expected === undefined) { + assert_equals( + actual, undefined, + "(assert_prop_desc_equals: no property descriptor expected)"); + return; + } + for (p in actual) { + assert_true( + expected.hasOwnProperty(p), + "(assert_prop_desc_equals: property '" + p + "' is not expected)"); + assert_equals( + actual[p], expected[p], + "(assert_prop_desc_equals: property '" + p + "')"); + } + for (p in expected) { + assert_true( + actual.hasOwnProperty(p), + "(assert_prop_desc_equals: expected property '" + p + "' missing)"); + } +} + +// https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty +// 3.9.3. [[DefineOwnProperty]] + +test(function() { + let span = document.createElement("span"); + span.className = "foo"; + // DOMTokenList supports an indexed property getter but not a setter. + let domTokenList = span.classList; + // Confirm the test settings. + assert_equals(domTokenList.length, 1); + assert_prop_desc_equals(domTokenList, "0", + {value: "foo", writable: false, enumerable: true, + configurable: true}); + assert_prop_desc_equals(domTokenList, "1", undefined); + // Actual test + assert_throws(new TypeError(), () => + Object.defineProperty(domTokenList, "0", {value: true, writable: true})); + assert_throws(new TypeError(), () => + Object.defineProperty(domTokenList, "1", {value: true, writable: true})); + assert_throws(new TypeError(), () => + Object.defineProperty(domTokenList, "0", {get: () => {}})); + assert_throws(new TypeError(), () => + Object.defineProperty(domTokenList, "0", {set: () => {}})); + assert_throws(new TypeError(), () => + Object.defineProperty(domTokenList, "1", {get: () => {}})); + assert_throws(new TypeError(), () => + Object.defineProperty(domTokenList, "1", {set: () => {}})); + assert_equals(domTokenList[0], "foo"); + assert_equals(domTokenList[1], undefined); + domTokenList[0] = "bar"; + domTokenList[1] = "bar"; + assert_equals(domTokenList[0], "foo"); + assert_equals(domTokenList[1], undefined); + assert_throws(new TypeError(), () => { + "use strict"; + domTokenList[0] = "bar"; + }); + assert_throws(new TypeError(), () => { + "use strict"; + domTokenList[1] = "bar"; + }); + // Nothing must change after all. + assert_equals(domTokenList.length, 1); + assert_prop_desc_equals(domTokenList, "0", + {value: "foo", writable: false, enumerable: true, + configurable: true}); + assert_prop_desc_equals(domTokenList, "1", undefined); +}, "Test [[DefineOwnProperty]] with no indexed property setter support."); + +test(function() { + // HTMLSelectElement supports an indexed property setter. + let select = document.createElement("select"); + let option0 = document.createElement("option"); + let option1 = document.createElement("option"); + // Confirm the test settings. + assert_equals(select.length, 0); + assert_prop_desc_equals(select, "0", undefined); + // Try to define an accessor property with non supported property index. + assert_throws(new TypeError(), () => + Object.defineProperty(select, "0", {get: () => {}})); + assert_throws(new TypeError(), () => + Object.defineProperty(select, "0", {set: () => {}})); + assert_prop_desc_equals(select, "0", undefined); + // writable, enumerable, configurable will be ignored. + Object.defineProperty(select, "0", {value: option0, writable: false, + enumerable: false, configurable: false}); + assert_prop_desc_equals(select, "0", + {value: option0, writable: true, enumerable: true, + configurable: true}); + select[1] = option1; + assert_prop_desc_equals(select, "1", + {value: option1, writable: true, enumerable: true, + configurable: true}); + // Try to define an accessor property with a supported property index. + assert_throws(new TypeError(), () => + Object.defineProperty(select, "0", {get: () => {}})); + assert_throws(new TypeError(), () => + Object.defineProperty(select, "0", {set: () => {}})); + assert_prop_desc_equals(select, "0", + {value: option0, writable: true, enumerable: true, + configurable: true}); +}, "Test [[DefineOwnProperty]] with indexed property setter support."); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/navigation-insecure.html b/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/navigation-insecure.html new file mode 100644 index 0000000..c156aa10 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/navigation-insecure.html
@@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="support/test_utils.js"></script> + </head> + + <body> + <script> + /** + * @param Array.<Array.<Datatype>> combination A combination of datatypes. + * @param Dict.<string, boolean> report A map between a datatype name and + * whether it is empty. + * @return boolean Whether all datatypes are still nonempty. + */ + function verifyDatatypes(report) { + TestUtils.DATATYPES.forEach(function(datatype) { + assert_false( + report[datatype.name], + datatype.name + " should NOT have been cleared."); + }); + } + + TestUtils.COMBINATIONS.forEach(function(combination) { + var test_name = + "Do not clear datatypes on insecure navigation (header: " + + combination.map(function(e) { return e.name; }).join(", ") + + ")"; + + promise_test(function(test) { + return new Promise(function(resolve_test, reject_test) { + TestUtils.populateDatatypes() + .then(function() { + // Navigate to a resource with a Clear-Site-Data header in + // an iframe, then verify that no data have been deleted. + return new Promise(function(resolve, reject) { + window.addEventListener("message", resolve); + var iframe = document.createElement("iframe"); + iframe.src = TestUtils.getClearSiteDataUrl(combination); + document.body.appendChild(iframe); + }).then(function(messageEvent) { + verifyDatatypes(messageEvent.data); + resolve_test(); + }); + }); + }); + }, test_name); + }); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/navigation.html b/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/navigation.html deleted file mode 100644 index cd0f83e1..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/navigation.html +++ /dev/null
@@ -1,66 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <script src="support/test_utils.js"></script> - </head> - - <body> - <script> - /** Ensures that all datatypes are nonempty. */ - function populateDatatypes() { - return Promise.all(TestUtils.DATATYPES.map(function(datatype) { - return datatype.add().then(datatype.isEmpty().then(function(isEmpty) { - assert_false( - isEmpty, - datatype.name + " has to be nonempty before the test starts."); - })); - })); - } - - /** - * @param Array.<Array.<Datatype>> combination A combination of datatypes. - * @param Dict.<string, boolean> report A map between a datatype name and - * whether it is empty. - * @return boolean Whether all datatypes are empty if and only if they are - * included in the |combination|. - */ - function verifyDatatypes(combination, report) { - TestUtils.DATATYPES.forEach(function(datatype) { - if (combination.indexOf(datatype) != -1) { - assert_true( - report[datatype.name], - datatype.name + " should have been cleared."); - } else { - assert_false( - report[datatype.name], - datatype.name + " should NOT have been cleared."); - } - }) - } - - TestUtils.COMBINATIONS.forEach(function(combination) { - var test_name = - "Clear datatypes on navigation: " + - combination.map(function(e) { return e.name; }).join(", "); - - promise_test(function(test) { - return populateDatatypes() - .then(function() { - // Navigate to a resource with a Clear-Site-Data header in an - // iframe, then verify that the correct types have been deleted. - return new Promise(function(resolve, reject) { - window.addEventListener("message", resolve); - var iframe = document.createElement("iframe"); - iframe.src = TestUtils.getClearSiteDataUrl(combination); - document.body.appendChild(iframe); - }).then(function(messageEvent) { - verifyDatatypes(combination, messageEvent.data); - }); - }); - }, test_name); - }); - </script> - </body> -</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/navigation.https.html b/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/navigation.https.html new file mode 100644 index 0000000..a8f83903e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/navigation.https.html
@@ -0,0 +1,59 @@ +<!DOCTYPE html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="support/test_utils.js"></script> + </head> + + <body> + <script> + /** + * @param Array.<Array.<Datatype>> combination A combination of datatypes. + * @param Dict.<string, boolean> report A map between a datatype name and + * whether it is empty. + * @return boolean Whether all datatypes are empty if and only if they are + * included in the |combination|. + */ + function verifyDatatypes(combination, report) { + TestUtils.DATATYPES.forEach(function(datatype) { + if (combination.indexOf(datatype) != -1) { + assert_true( + report[datatype.name], + datatype.name + " should have been cleared."); + } else { + assert_false( + report[datatype.name], + datatype.name + " should NOT have been cleared."); + } + }); + } + + TestUtils.COMBINATIONS.forEach(function(combination) { + var test_name = + "Clear datatypes on navigation: " + + combination.map(function(e) { return e.name; }).join(", "); + + promise_test(function(test) { + return new Promise(function(resolve_test, reject_test) { + TestUtils.populateDatatypes() + .then(function() { + // Navigate to a resource with a Clear-Site-Data header in + // an iframe, then verify that the correct types have been + // deleted. + return new Promise(function(resolve, reject) { + window.addEventListener("message", resolve); + var iframe = document.createElement("iframe"); + iframe.src = TestUtils.getClearSiteDataUrl(combination); + document.body.appendChild(iframe); + }).then(function(messageEvent) { + verifyDatatypes(combination, messageEvent.data); + resolve_test(); + }); + }); + }); + }, test_name); + }); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/support/echo-clear-site-data.py b/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/support/echo-clear-site-data.py index e8ec8d55..ab85002 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/support/echo-clear-site-data.py +++ b/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/support/echo-clear-site-data.py
@@ -34,7 +34,7 @@ # embedder whether the data deletion succeeded. def main(request, response): types = [key for key in request.GET.keys()] - header = json.dumps({ "types": types }) + header = ",".join("\"" + type + "\"" for type in types) return ([("Clear-Site-Data", header), ("Content-Type", "text/html")], RESPONSE)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/support/test_utils.js b/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/support/test_utils.js index 6aff373..35b0a01 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/support/test_utils.js +++ b/third_party/WebKit/LayoutTests/external/wpt/clear-site-data/support/test_utils.js
@@ -75,6 +75,26 @@ })(); /** + * Ensures that all datatypes are nonempty. Should be called in the test + * setup phase. + */ + TestUtils.populateDatatypes = function() { + return Promise.all(TestUtils.DATATYPES.map(function(datatype) { + return new Promise(function(resolve, reject) { + datatype.add().then(function() { + datatype.isEmpty().then(function(isEmpty) { + assert_false( + isEmpty, + datatype.name + + " has to be nonempty before the test starts."); + resolve(); + }); + }); + }); + })); + }; + + /** * Get the support server URL that returns a Clear-Site-Data header * to clear |datatypes|. * @param{Array.<Datatype>} datatypes The list of datatypes to be deleted.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/collections/HTMLCollection-supported-property-indices-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/collections/HTMLCollection-supported-property-indices-expected.txt index e9f5af1..6d9d338 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/collections/HTMLCollection-supported-property-indices-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/collections/HTMLCollection-supported-property-indices-expected.txt
@@ -4,7 +4,7 @@ PASS Handling of property names that look like integers around 2^31 PASS Handling of property names that look like integers around 2^32 FAIL Trying to set an expando that would shadow an already-existing indexed property assert_true: expected true got false -FAIL Trying to set an expando with an indexed property name past the end of the list assert_equals: expected (undefined) undefined but got (number) 5 +PASS Trying to set an expando with an indexed property name past the end of the list FAIL Trying to delete an indexed property name should never work assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-getElementsByTagName-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-getElementsByTagName-expected.txt index 59d64579..9b84c84 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-getElementsByTagName-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-getElementsByTagName-expected.txt
@@ -1,11 +1,8 @@ This is a testharness.js-based test. PASS Interfaces PASS Caching is allowed -FAIL Shouldn't be able to set unsigned properties on a HTMLCollection (non-strict mode) assert_equals: expected (undefined) undefined but got (string) "foopy" -FAIL Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode) assert_throws: function "function () { - "use strict"; - l[5] = "foopy" - }" did not throw +PASS Shouldn't be able to set unsigned properties on a HTMLCollection (non-strict mode) +PASS Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode) PASS Should be able to set expando shadowing a proto prop (item) PASS Should be able to set expando shadowing a proto prop (namedItem) FAIL hasOwnProperty, getOwnPropertyDescriptor, getOwnPropertyNames assert_true: desc.enumerable expected true got false
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-getElementsByTagName-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-getElementsByTagName-expected.txt index efd83ed..8310187 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-getElementsByTagName-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-getElementsByTagName-expected.txt
@@ -1,11 +1,8 @@ This is a testharness.js-based test. PASS Interfaces PASS Caching is allowed -FAIL Shouldn't be able to set unsigned properties on a HTMLCollection (non-strict mode) assert_equals: expected (undefined) undefined but got (string) "foopy" -FAIL Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode) assert_throws: function "function () { - "use strict"; - l[5] = "foopy" - }" did not throw +PASS Shouldn't be able to set unsigned properties on a HTMLCollection (non-strict mode) +PASS Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode) PASS Should be able to set expando shadowing a proto prop (item) PASS Should be able to set expando shadowing a proto prop (namedItem) FAIL hasOwnProperty, getOwnPropertyDescriptor, getOwnPropertyNames assert_true: desc.enumerable expected true got false
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-expected.txt index f053637..8e34f3e8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-expected.txt
@@ -1,7 +1,7 @@ This is a testharness.js-based test. PASS Indexed properties of the window object (non-strict mode) -FAIL Indexed properties of the window object (non-strict mode) 1 assert_throws: function "() => Object.defineProperty(window, 0, { value: "bar" })" did not throw -FAIL Indexed properties of the window object (non-strict mode) 2 assert_throws: function "() => Object.defineProperty(window, 1, { value: "bar" })" did not throw +FAIL Indexed properties of the window object (non-strict mode) 1 assert_equals: expected false but got true +PASS Indexed properties of the window object (non-strict mode) 2 PASS Indexed properties of the window object (non-strict mode) 3 Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-strict-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-strict-expected.txt index c0da5b2f..6c32654 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-strict-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-strict-expected.txt
@@ -1,11 +1,7 @@ This is a testharness.js-based test. PASS Indexed properties of the window object (strict mode) -FAIL Indexed properties of the window object (strict mode) 1 assert_throws: function "function () { - window[0] = "foo"; - }" did not throw -FAIL Indexed properties of the window object (strict mode) 2 assert_throws: function "function () { - window[1] = "foo"; - }" did not throw +FAIL Indexed properties of the window object (strict mode) 1 assert_throws: function "() => delete window[0]" did not throw +PASS Indexed properties of the window object (strict mode) 2 PASS Indexed properties of the window object (strict mode) 3 Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getter-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getter-expected.txt deleted file mode 100644 index 1a9b070..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getter-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -PASS TextTrackCueList getter -FAIL TextTrackCueList getter, no indexed set/create assert_equals: expected (undefined) undefined but got (string) "foo" -FAIL TextTrackCueList getter, no indexed set/create (strict) assert_equals: expected (undefined) undefined but got (string) "foo" -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getter-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getter-expected.txt deleted file mode 100644 index a04bfe2..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getter-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -PASS TextTrackList getter -PASS TextTrackList getter, no indexed set/create -FAIL TextTrackList getter, no indexed set/create (strict) assert_throws: function "function (){ video.textTracks[0] = 'foo'; }" did not throw -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/media/track/opera/interfaces/TextTrackCueList/getter-expected.txt b/third_party/WebKit/LayoutTests/media/track/opera/interfaces/TextTrackCueList/getter-expected.txt deleted file mode 100644 index 1a9b070..0000000 --- a/third_party/WebKit/LayoutTests/media/track/opera/interfaces/TextTrackCueList/getter-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -PASS TextTrackCueList getter -FAIL TextTrackCueList getter, no indexed set/create assert_equals: expected (undefined) undefined but got (string) "foo" -FAIL TextTrackCueList getter, no indexed set/create (strict) assert_equals: expected (undefined) undefined but got (string) "foo" -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/media/track/opera/interfaces/TextTrackList/getter-expected.txt b/third_party/WebKit/LayoutTests/media/track/opera/interfaces/TextTrackList/getter-expected.txt deleted file mode 100644 index a04bfe2..0000000 --- a/third_party/WebKit/LayoutTests/media/track/opera/interfaces/TextTrackList/getter-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -PASS TextTrackList getter -PASS TextTrackList getter, no indexed set/create -FAIL TextTrackList getter, no indexed set/create (strict) assert_throws: function "function (){ video.textTracks[0] = 'foo'; }" did not throw -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl index ce5780e5..16f28f3 100644 --- a/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl +++ b/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl
@@ -111,7 +111,7 @@ {##############################################################################} {% block indexed_property_setter_callback %} -{% if indexed_property_setter or named_property_setter %} +{% if indexed_property_getter or named_property_setter %} {% set setter = indexed_property_setter or named_property_setter %} void {{v8_class_or_partial}}::indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) { {% if setter.is_ce_reactions %} @@ -126,7 +126,7 @@ {{cpp_class}}V8Internal::indexedPropertySetter(index, v8Value, info); {% endif %} - {% else %}{# otherwise, named property #} + {% elif named_property_setter %} const AtomicString& propertyName = AtomicString::Number(index); @@ -136,7 +136,19 @@ {{cpp_class}}V8Internal::namedPropertySetter(propertyName, v8Value, info); {% endif %} - {% endif %}{# indexed_property_setter #} + {% else %}{# neither of indexed_property_setter nor named_property_setter #} + + // No indexed property setter defined. Do not fall back to the default + // setter. + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "{{interface_name}}"); + exceptionState.ThrowTypeError("Index property setter is not supported."); + } + + {% endif %}{# indexed/named_property_setter #} } {% endif %} @@ -212,6 +224,53 @@ {##############################################################################} +{% block indexed_property_definer_callback %} +{% if indexed_property_getter %} +void {{v8_class_or_partial}}::indexedPropertyDefinerCallback( + uint32_t index, + const v8::PropertyDescriptor& desc, + const v8::PropertyCallbackInfo<v8::Value>& info) { +{% if indexed_property_setter %} + // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty + // 3.9.3. [[DefineOwnProperty]] + // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then + // return false. + if (desc.has_get() || desc.has_set()) { + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "{{interface_name}}"); + exceptionState.ThrowTypeError("Accessor properties are not allowed."); + } + return; + } + + // Return nothing and fall back to indexedPropertySetterCallback. +{% else %}{# indexed_property_setter #} + // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty + // 3.9.3. [[DefineOwnProperty]] + // step 1.2. If O does not implement an interface with an indexed property + // setter, then return false. + // + // https://html.spec.whatwg.org/C/window-object.html#windowproxy-defineownproperty + // 7.4.6 [[DefineOwnProperty]] (P, Desc) + // step 2.1. If P is an array index property name, return false. + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "{{interface_name}}"); + exceptionState.ThrowTypeError("Index property setter is not supported."); + } +{% endif %}{# indexed_property_setter #} +} + +{% endif %}{# indexed_property_getter #} +{% endblock %} + + +{##############################################################################} {% block named_property_getter %} {% if named_property_getter and not named_property_getter.is_custom %} {% set getter = named_property_getter %} @@ -707,17 +766,28 @@ '%s::indexedPropertyGetterCallback' % v8_class_or_partial %} {% set indexed_property_setter_callback = '%s::indexedPropertySetterCallback' % v8_class_or_partial - if indexed_property_setter or named_property_setter else 'nullptr' %} -{% set indexed_property_query_callback = 'nullptr' %}{# Unused #} + if indexed_property_getter or named_property_setter else 'nullptr' %} +{% set indexed_property_descriptor_callback = 'nullptr' %} {% set indexed_property_deleter_callback = '%s::indexedPropertyDeleterCallback' % v8_class_or_partial if indexed_property_deleter or named_property_deleter else 'nullptr' %} {% set indexed_property_enumerator_callback = 'IndexedPropertyEnumerator<%s>' % cpp_class if indexed_property_getter.is_enumerable else 'nullptr' %} +{% set indexed_property_definer_callback = + '%s::indexedPropertyDefinerCallback' % v8_class_or_partial + if indexed_property_getter else 'nullptr' %} {% set property_handler_flags = 'v8::PropertyHandlerFlags::kNone' %} -v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig({{indexed_property_getter_callback}}, {{indexed_property_setter_callback}}, {{indexed_property_query_callback}}, {{indexed_property_deleter_callback}}, {{indexed_property_enumerator_callback}}, v8::Local<v8::Value>(), {{property_handler_flags}}); +v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig( + {{indexed_property_getter_callback}}, + {{indexed_property_setter_callback}}, + {{indexed_property_descriptor_callback}}, + {{indexed_property_deleter_callback}}, + {{indexed_property_enumerator_callback}}, + {{indexed_property_definer_callback}}, + v8::Local<v8::Value>(), + {{property_handler_flags}}); {{target}}->SetHandler(indexedPropertyHandlerConfig); {%- endmacro %}
diff --git a/third_party/WebKit/Source/bindings/templates/interface.h.tmpl b/third_party/WebKit/Source/bindings/templates/interface.h.tmpl index b294016..d2b9735 100644 --- a/third_party/WebKit/Source/bindings/templates/interface.h.tmpl +++ b/third_party/WebKit/Source/bindings/templates/interface.h.tmpl
@@ -245,12 +245,15 @@ {% if indexed_property_getter or named_property_getter %} {{exported}}static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&); {% endif %} - {% if indexed_property_setter or named_property_setter %} + {% if indexed_property_getter or named_property_setter %} {{exported}}static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&); {% endif %} {% if indexed_property_deleter or named_property_deleter %} {{exported}}static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>&); {% endif %} + {% if indexed_property_getter %} + {{exported}}static void indexedPropertyDefinerCallback(uint32_t index, const v8::PropertyDescriptor&, const v8::PropertyCallbackInfo<v8::Value>&); + {% endif %} {% if needs_runtime_enabled_installer %} {{exported if has_partial_interface else ''}}static void InstallRuntimeEnabledFeatures(
diff --git a/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl index 37623a3..ea50c0a 100644 --- a/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl +++ b/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
@@ -244,6 +244,7 @@ {% block indexed_property_getter_callback %}{% endblock %} {% block indexed_property_setter_callback %}{% endblock %} {% block indexed_property_deleter_callback %}{% endblock %} +{% block indexed_property_definer_callback %}{% endblock %} {% if has_access_check_callbacks and not is_partial %} bool {{v8_class_or_partial}}::securityCheck(v8::Local<v8::Context> accessingContext, v8::Local<v8::Object> accessedObject, v8::Local<v8::Value> data) {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp index 9be6fb7a..a77e2aa 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp
@@ -177,6 +177,28 @@ V8TestIntegerIndexed::indexedPropertyDeleterCustom(index, info); } +void V8TestIntegerIndexed::indexedPropertyDefinerCallback( + uint32_t index, + const v8::PropertyDescriptor& desc, + const v8::PropertyCallbackInfo<v8::Value>& info) { + // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty + // 3.9.3. [[DefineOwnProperty]] + // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then + // return false. + if (desc.has_get() || desc.has_set()) { + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "TestIntegerIndexed"); + exceptionState.ThrowTypeError("Accessor properties are not allowed."); + } + return; + } + + // Return nothing and fall back to indexedPropertySetterCallback. +} + static const V8DOMConfiguration::AccessorConfiguration V8TestIntegerIndexedAccessors[] = { { "length", V8TestIntegerIndexed::lengthAttributeGetterCallback, V8TestIntegerIndexed::lengthAttributeSetterCallback, nullptr, nullptr, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kAllWorlds }, }; @@ -208,7 +230,15 @@ signature, V8TestIntegerIndexedMethods, WTF_ARRAY_LENGTH(V8TestIntegerIndexedMethods)); // Indexed properties - v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(V8TestIntegerIndexed::indexedPropertyGetterCallback, V8TestIntegerIndexed::indexedPropertySetterCallback, nullptr, V8TestIntegerIndexed::indexedPropertyDeleterCallback, IndexedPropertyEnumerator<TestIntegerIndexed>, v8::Local<v8::Value>(), v8::PropertyHandlerFlags::kNone); + v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig( + V8TestIntegerIndexed::indexedPropertyGetterCallback, + V8TestIntegerIndexed::indexedPropertySetterCallback, + nullptr, + V8TestIntegerIndexed::indexedPropertyDeleterCallback, + IndexedPropertyEnumerator<TestIntegerIndexed>, + V8TestIntegerIndexed::indexedPropertyDefinerCallback, + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone); instanceTemplate->SetHandler(indexedPropertyHandlerConfig); // Named properties v8::NamedPropertyHandlerConfiguration namedPropertyHandlerConfig(V8TestIntegerIndexed::namedPropertyGetterCallback, V8TestIntegerIndexed::namedPropertySetterCallback, V8TestIntegerIndexed::namedPropertyQueryCallback, V8TestIntegerIndexed::namedPropertyDeleterCallback, V8TestIntegerIndexed::namedPropertyEnumeratorCallback, v8::Local<v8::Value>(), static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kOnlyInterceptStrings) | int(v8::PropertyHandlerFlags::kNonMasking)));
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.h index 01f15d6..77a16fd1 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.h
@@ -67,6 +67,7 @@ CORE_EXPORT static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>&); + CORE_EXPORT static void indexedPropertyDefinerCallback(uint32_t index, const v8::PropertyDescriptor&, const v8::PropertyCallbackInfo<v8::Value>&); static void InstallRuntimeEnabledFeaturesOnTemplate( v8::Isolate*,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp index 7cbb68b5..809d9c6c 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp
@@ -177,6 +177,28 @@ V8TestIntegerIndexedGlobal::indexedPropertyDeleterCustom(index, info); } +void V8TestIntegerIndexedGlobal::indexedPropertyDefinerCallback( + uint32_t index, + const v8::PropertyDescriptor& desc, + const v8::PropertyCallbackInfo<v8::Value>& info) { + // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty + // 3.9.3. [[DefineOwnProperty]] + // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then + // return false. + if (desc.has_get() || desc.has_set()) { + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "TestIntegerIndexedGlobal"); + exceptionState.ThrowTypeError("Accessor properties are not allowed."); + } + return; + } + + // Return nothing and fall back to indexedPropertySetterCallback. +} + static const V8DOMConfiguration::AccessorConfiguration V8TestIntegerIndexedGlobalAccessors[] = { { "length", V8TestIntegerIndexedGlobal::lengthAttributeGetterCallback, V8TestIntegerIndexedGlobal::lengthAttributeSetterCallback, nullptr, nullptr, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::kOnInstance, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kAllWorlds }, }; @@ -214,7 +236,15 @@ signature, V8TestIntegerIndexedGlobalMethods, WTF_ARRAY_LENGTH(V8TestIntegerIndexedGlobalMethods)); // Indexed properties - v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(V8TestIntegerIndexedGlobal::indexedPropertyGetterCallback, V8TestIntegerIndexedGlobal::indexedPropertySetterCallback, nullptr, V8TestIntegerIndexedGlobal::indexedPropertyDeleterCallback, IndexedPropertyEnumerator<TestIntegerIndexedGlobal>, v8::Local<v8::Value>(), v8::PropertyHandlerFlags::kNone); + v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig( + V8TestIntegerIndexedGlobal::indexedPropertyGetterCallback, + V8TestIntegerIndexedGlobal::indexedPropertySetterCallback, + nullptr, + V8TestIntegerIndexedGlobal::indexedPropertyDeleterCallback, + IndexedPropertyEnumerator<TestIntegerIndexedGlobal>, + V8TestIntegerIndexedGlobal::indexedPropertyDefinerCallback, + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone); instanceTemplate->SetHandler(indexedPropertyHandlerConfig); // Array iterator (@@iterator)
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.h index a2313828..daac288 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.h
@@ -68,6 +68,7 @@ CORE_EXPORT static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>&); + CORE_EXPORT static void indexedPropertyDefinerCallback(uint32_t index, const v8::PropertyDescriptor&, const v8::PropertyCallbackInfo<v8::Value>&); static void InstallRuntimeEnabledFeaturesOnTemplate( v8::Isolate*,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp index 6f75b849..7c97aa8 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp
@@ -177,6 +177,28 @@ V8TestIntegerIndexedPrimaryGlobal::indexedPropertyDeleterCustom(index, info); } +void V8TestIntegerIndexedPrimaryGlobal::indexedPropertyDefinerCallback( + uint32_t index, + const v8::PropertyDescriptor& desc, + const v8::PropertyCallbackInfo<v8::Value>& info) { + // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty + // 3.9.3. [[DefineOwnProperty]] + // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then + // return false. + if (desc.has_get() || desc.has_set()) { + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "TestIntegerIndexedPrimaryGlobal"); + exceptionState.ThrowTypeError("Accessor properties are not allowed."); + } + return; + } + + // Return nothing and fall back to indexedPropertySetterCallback. +} + static const V8DOMConfiguration::AccessorConfiguration V8TestIntegerIndexedPrimaryGlobalAccessors[] = { { "length", V8TestIntegerIndexedPrimaryGlobal::lengthAttributeGetterCallback, V8TestIntegerIndexedPrimaryGlobal::lengthAttributeSetterCallback, nullptr, nullptr, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::kOnInstance, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kAllWorlds }, }; @@ -214,7 +236,15 @@ signature, V8TestIntegerIndexedPrimaryGlobalMethods, WTF_ARRAY_LENGTH(V8TestIntegerIndexedPrimaryGlobalMethods)); // Indexed properties - v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(V8TestIntegerIndexedPrimaryGlobal::indexedPropertyGetterCallback, V8TestIntegerIndexedPrimaryGlobal::indexedPropertySetterCallback, nullptr, V8TestIntegerIndexedPrimaryGlobal::indexedPropertyDeleterCallback, IndexedPropertyEnumerator<TestIntegerIndexedPrimaryGlobal>, v8::Local<v8::Value>(), v8::PropertyHandlerFlags::kNone); + v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig( + V8TestIntegerIndexedPrimaryGlobal::indexedPropertyGetterCallback, + V8TestIntegerIndexedPrimaryGlobal::indexedPropertySetterCallback, + nullptr, + V8TestIntegerIndexedPrimaryGlobal::indexedPropertyDeleterCallback, + IndexedPropertyEnumerator<TestIntegerIndexedPrimaryGlobal>, + V8TestIntegerIndexedPrimaryGlobal::indexedPropertyDefinerCallback, + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone); instanceTemplate->SetHandler(indexedPropertyHandlerConfig); // Array iterator (@@iterator)
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.h index 502e16f..4d3faa4d 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.h
@@ -68,6 +68,7 @@ CORE_EXPORT static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>&); + CORE_EXPORT static void indexedPropertyDefinerCallback(uint32_t index, const v8::PropertyDescriptor&, const v8::PropertyCallbackInfo<v8::Value>&); static void InstallRuntimeEnabledFeaturesOnTemplate( v8::Isolate*,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp index 9ecd142..892677490 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
@@ -2898,6 +2898,28 @@ TestInterfaceImplementationV8Internal::indexedPropertyDeleter(index, info); } +void V8TestInterface::indexedPropertyDefinerCallback( + uint32_t index, + const v8::PropertyDescriptor& desc, + const v8::PropertyCallbackInfo<v8::Value>& info) { + // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty + // 3.9.3. [[DefineOwnProperty]] + // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then + // return false. + if (desc.has_get() || desc.has_set()) { + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "TestInterface"); + exceptionState.ThrowTypeError("Accessor properties are not allowed."); + } + return; + } + + // Return nothing and fall back to indexedPropertySetterCallback. +} + // Suppress warning: global constructors, because AttributeConfiguration is trivial // and does not depend on another global objects. #if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__) @@ -3031,7 +3053,15 @@ signature, V8TestInterfaceMethods, WTF_ARRAY_LENGTH(V8TestInterfaceMethods)); // Indexed properties - v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(V8TestInterface::indexedPropertyGetterCallback, V8TestInterface::indexedPropertySetterCallback, nullptr, V8TestInterface::indexedPropertyDeleterCallback, IndexedPropertyEnumerator<TestInterfaceImplementation>, v8::Local<v8::Value>(), v8::PropertyHandlerFlags::kNone); + v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig( + V8TestInterface::indexedPropertyGetterCallback, + V8TestInterface::indexedPropertySetterCallback, + nullptr, + V8TestInterface::indexedPropertyDeleterCallback, + IndexedPropertyEnumerator<TestInterfaceImplementation>, + V8TestInterface::indexedPropertyDefinerCallback, + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone); instanceTemplate->SetHandler(indexedPropertyHandlerConfig); // Named properties v8::NamedPropertyHandlerConfiguration namedPropertyHandlerConfig(V8TestInterface::namedPropertyGetterCallback, V8TestInterface::namedPropertySetterCallback, V8TestInterface::namedPropertyQueryCallback, V8TestInterface::namedPropertyDeleterCallback, V8TestInterface::namedPropertyEnumeratorCallback, v8::Local<v8::Value>(), static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kOnlyInterceptStrings) | int(v8::PropertyHandlerFlags::kNonMasking)));
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h index 31e5de10..b66c4036 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h
@@ -223,6 +223,7 @@ CORE_EXPORT static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>&); + CORE_EXPORT static void indexedPropertyDefinerCallback(uint32_t index, const v8::PropertyDescriptor&, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void InstallRuntimeEnabledFeaturesOnTemplate( v8::Isolate*,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp index 670b815..7613d4bd 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
@@ -587,6 +587,28 @@ TestInterface2V8Internal::indexedPropertyDeleter(index, info); } +void V8TestInterface2::indexedPropertyDefinerCallback( + uint32_t index, + const v8::PropertyDescriptor& desc, + const v8::PropertyCallbackInfo<v8::Value>& info) { + // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty + // 3.9.3. [[DefineOwnProperty]] + // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then + // return false. + if (desc.has_get() || desc.has_set()) { + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "TestInterface2"); + exceptionState.ThrowTypeError("Accessor properties are not allowed."); + } + return; + } + + // Return nothing and fall back to indexedPropertySetterCallback. +} + static const V8DOMConfiguration::AccessorConfiguration V8TestInterface2Accessors[] = { { "size", V8TestInterface2::sizeAttributeGetterCallback, nullptr, nullptr, nullptr, static_cast<v8::PropertyAttribute>(v8::DontEnum | v8::ReadOnly), V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kAllWorlds }, }; @@ -647,7 +669,15 @@ signature, V8TestInterface2Methods, WTF_ARRAY_LENGTH(V8TestInterface2Methods)); // Indexed properties - v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(V8TestInterface2::indexedPropertyGetterCallback, V8TestInterface2::indexedPropertySetterCallback, nullptr, V8TestInterface2::indexedPropertyDeleterCallback, IndexedPropertyEnumerator<TestInterface2>, v8::Local<v8::Value>(), v8::PropertyHandlerFlags::kNone); + v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig( + V8TestInterface2::indexedPropertyGetterCallback, + V8TestInterface2::indexedPropertySetterCallback, + nullptr, + V8TestInterface2::indexedPropertyDeleterCallback, + IndexedPropertyEnumerator<TestInterface2>, + V8TestInterface2::indexedPropertyDefinerCallback, + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone); instanceTemplate->SetHandler(indexedPropertyHandlerConfig); // Named properties v8::NamedPropertyHandlerConfiguration namedPropertyHandlerConfig(V8TestInterface2::namedPropertyGetterCallback, V8TestInterface2::namedPropertySetterCallback, V8TestInterface2::namedPropertyQueryCallback, V8TestInterface2::namedPropertyDeleterCallback, V8TestInterface2::namedPropertyEnumeratorCallback, v8::Local<v8::Value>(), static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kOnlyInterceptStrings) | int(v8::PropertyHandlerFlags::kNonMasking)));
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h index 40384c7..4c6c8bc7 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h
@@ -80,6 +80,7 @@ CORE_EXPORT static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>&); + CORE_EXPORT static void indexedPropertyDefinerCallback(uint32_t index, const v8::PropertyDescriptor&, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void InstallRuntimeEnabledFeaturesOnTemplate( v8::Isolate*,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp index e3cd8f5..53453a3 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
@@ -174,6 +174,28 @@ V8TestInterface3::indexedPropertyDeleterCustom(index, info); } +void V8TestInterface3::indexedPropertyDefinerCallback( + uint32_t index, + const v8::PropertyDescriptor& desc, + const v8::PropertyCallbackInfo<v8::Value>& info) { + // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty + // 3.9.3. [[DefineOwnProperty]] + // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then + // return false. + if (desc.has_get() || desc.has_set()) { + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "TestInterface3"); + exceptionState.ThrowTypeError("Accessor properties are not allowed."); + } + return; + } + + // Return nothing and fall back to indexedPropertySetterCallback. +} + static const V8DOMConfiguration::AccessorConfiguration V8TestInterface3Accessors[] = { { "length", V8TestInterface3::lengthAttributeGetterCallback, nullptr, nullptr, nullptr, static_cast<v8::PropertyAttribute>(v8::ReadOnly), V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kAllWorlds }, @@ -208,7 +230,15 @@ signature, V8TestInterface3Methods, WTF_ARRAY_LENGTH(V8TestInterface3Methods)); // Indexed properties - v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(V8TestInterface3::indexedPropertyGetterCallback, V8TestInterface3::indexedPropertySetterCallback, nullptr, V8TestInterface3::indexedPropertyDeleterCallback, IndexedPropertyEnumerator<TestInterface3>, v8::Local<v8::Value>(), v8::PropertyHandlerFlags::kNone); + v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig( + V8TestInterface3::indexedPropertyGetterCallback, + V8TestInterface3::indexedPropertySetterCallback, + nullptr, + V8TestInterface3::indexedPropertyDeleterCallback, + IndexedPropertyEnumerator<TestInterface3>, + V8TestInterface3::indexedPropertyDefinerCallback, + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone); instanceTemplate->SetHandler(indexedPropertyHandlerConfig); // Named properties v8::NamedPropertyHandlerConfiguration namedPropertyHandlerConfig(V8TestInterface3::namedPropertyGetterCallback, V8TestInterface3::namedPropertySetterCallback, V8TestInterface3::namedPropertyQueryCallback, V8TestInterface3::namedPropertyDeleterCallback, V8TestInterface3::namedPropertyEnumeratorCallback, v8::Local<v8::Value>(), static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kOnlyInterceptStrings) | int(v8::PropertyHandlerFlags::kNonMasking)));
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.h index e84d2da..1acec8c8 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.h
@@ -68,6 +68,7 @@ CORE_EXPORT static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>&); + CORE_EXPORT static void indexedPropertyDefinerCallback(uint32_t index, const v8::PropertyDescriptor&, const v8::PropertyCallbackInfo<v8::Value>&); static void InstallRuntimeEnabledFeaturesOnTemplate( v8::Isolate*,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp index e5cfffe..abca1805 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -12266,6 +12266,28 @@ TestObjectV8Internal::indexedPropertyDeleter(index, info); } +void V8TestObject::indexedPropertyDefinerCallback( + uint32_t index, + const v8::PropertyDescriptor& desc, + const v8::PropertyCallbackInfo<v8::Value>& info) { + // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty + // 3.9.3. [[DefineOwnProperty]] + // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then + // return false. + if (desc.has_get() || desc.has_set()) { + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "TestObject"); + exceptionState.ThrowTypeError("Accessor properties are not allowed."); + } + return; + } + + // Return nothing and fall back to indexedPropertySetterCallback. +} + // Suppress warning: global constructors, because AttributeConfiguration is trivial // and does not depend on another global objects. #if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__) @@ -12874,7 +12896,15 @@ signature, V8TestObjectMethods, WTF_ARRAY_LENGTH(V8TestObjectMethods)); // Indexed properties - v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(V8TestObject::indexedPropertyGetterCallback, V8TestObject::indexedPropertySetterCallback, nullptr, V8TestObject::indexedPropertyDeleterCallback, IndexedPropertyEnumerator<TestObject>, v8::Local<v8::Value>(), v8::PropertyHandlerFlags::kNone); + v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig( + V8TestObject::indexedPropertyGetterCallback, + V8TestObject::indexedPropertySetterCallback, + nullptr, + V8TestObject::indexedPropertyDeleterCallback, + IndexedPropertyEnumerator<TestObject>, + V8TestObject::indexedPropertyDefinerCallback, + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone); instanceTemplate->SetHandler(indexedPropertyHandlerConfig); // Named properties v8::NamedPropertyHandlerConfiguration namedPropertyHandlerConfig(V8TestObject::namedPropertyGetterCallback, V8TestObject::namedPropertySetterCallback, V8TestObject::namedPropertyQueryCallback, V8TestObject::namedPropertyDeleterCallback, V8TestObject::namedPropertyEnumeratorCallback, v8::Local<v8::Value>(), static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kOnlyInterceptStrings) | int(v8::PropertyHandlerFlags::kNonMasking)));
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.h index 0b6ea49..9edbb10 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.h
@@ -641,6 +641,7 @@ CORE_EXPORT static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>&); + CORE_EXPORT static void indexedPropertyDefinerCallback(uint32_t index, const v8::PropertyDescriptor&, const v8::PropertyCallbackInfo<v8::Value>&); static void InstallRuntimeEnabledFeaturesOnTemplate( v8::Isolate*,
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp index 99da49e..5dd7fff 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
@@ -206,7 +206,15 @@ signature, V8TestSpecialOperationsMethods, WTF_ARRAY_LENGTH(V8TestSpecialOperationsMethods)); // Indexed properties - v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(V8TestSpecialOperations::indexedPropertyGetterCallback, V8TestSpecialOperations::indexedPropertySetterCallback, nullptr, nullptr, nullptr, v8::Local<v8::Value>(), v8::PropertyHandlerFlags::kNone); + v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig( + V8TestSpecialOperations::indexedPropertyGetterCallback, + V8TestSpecialOperations::indexedPropertySetterCallback, + nullptr, + nullptr, + nullptr, + nullptr, + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone); instanceTemplate->SetHandler(indexedPropertyHandlerConfig); // Named properties v8::NamedPropertyHandlerConfiguration namedPropertyHandlerConfig(V8TestSpecialOperations::namedPropertyGetterCallback, V8TestSpecialOperations::namedPropertySetterCallback, V8TestSpecialOperations::namedPropertyQueryCallback, nullptr, V8TestSpecialOperations::namedPropertyEnumeratorCallback, v8::Local<v8::Value>(), static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kOnlyInterceptStrings)));
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp index 567dea7d..7964949 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp
@@ -101,6 +101,39 @@ TestSpecialOperationsNotEnumerableV8Internal::indexedPropertyGetter(index, info); } +void V8TestSpecialOperationsNotEnumerable::indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) { + // No indexed property setter defined. Do not fall back to the default + // setter. + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "TestSpecialOperationsNotEnumerable"); + exceptionState.ThrowTypeError("Index property setter is not supported."); + } +} + +void V8TestSpecialOperationsNotEnumerable::indexedPropertyDefinerCallback( + uint32_t index, + const v8::PropertyDescriptor& desc, + const v8::PropertyCallbackInfo<v8::Value>& info) { + // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty + // 3.9.3. [[DefineOwnProperty]] + // step 1.2. If O does not implement an interface with an indexed property + // setter, then return false. + // + // https://html.spec.whatwg.org/C/window-object.html#windowproxy-defineownproperty + // 7.4.6 [[DefineOwnProperty]] (P, Desc) + // step 2.1. If P is an array index property name, return false. + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "TestSpecialOperationsNotEnumerable"); + exceptionState.ThrowTypeError("Index property setter is not supported."); + } +} + static void installV8TestSpecialOperationsNotEnumerableTemplate( v8::Isolate* isolate, const DOMWrapperWorld& world, @@ -118,7 +151,15 @@ // Register IDL constants, attributes and operations. // Indexed properties - v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(V8TestSpecialOperationsNotEnumerable::indexedPropertyGetterCallback, nullptr, nullptr, nullptr, nullptr, v8::Local<v8::Value>(), v8::PropertyHandlerFlags::kNone); + v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig( + V8TestSpecialOperationsNotEnumerable::indexedPropertyGetterCallback, + V8TestSpecialOperationsNotEnumerable::indexedPropertySetterCallback, + nullptr, + nullptr, + nullptr, + V8TestSpecialOperationsNotEnumerable::indexedPropertyDefinerCallback, + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone); instanceTemplate->SetHandler(indexedPropertyHandlerConfig); // Named properties v8::NamedPropertyHandlerConfiguration namedPropertyHandlerConfig(V8TestSpecialOperationsNotEnumerable::namedPropertyGetterCallback, nullptr, nullptr, nullptr, nullptr, v8::Local<v8::Value>(), static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kOnlyInterceptStrings) | int(v8::PropertyHandlerFlags::kNonMasking)));
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.h index 2e58dfe..628a774 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.h +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.h
@@ -48,6 +48,8 @@ CORE_EXPORT static void namedPropertyGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&); + CORE_EXPORT static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&); + CORE_EXPORT static void indexedPropertyDefinerCallback(uint32_t index, const v8::PropertyDescriptor&, const v8::PropertyCallbackInfo<v8::Value>&); static void InstallRuntimeEnabledFeaturesOnTemplate( v8::Isolate*,
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp index 2e5a6e3b..271f472 100644 --- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
@@ -809,6 +809,28 @@ TestInterface5ImplementationV8Internal::indexedPropertyDeleter(index, info); } +void V8TestInterface5::indexedPropertyDefinerCallback( + uint32_t index, + const v8::PropertyDescriptor& desc, + const v8::PropertyCallbackInfo<v8::Value>& info) { + // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty + // 3.9.3. [[DefineOwnProperty]] + // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then + // return false. + if (desc.has_get() || desc.has_set()) { + V8SetReturnValue(info, v8::Null(info.GetIsolate())); + if (info.ShouldThrowOnError()) { + ExceptionState exceptionState(info.GetIsolate(), + ExceptionState::kIndexedSetterContext, + "TestInterface5"); + exceptionState.ThrowTypeError("Accessor properties are not allowed."); + } + return; + } + + // Return nothing and fall back to indexedPropertySetterCallback. +} + // Suppress warning: global constructors, because AttributeConfiguration is trivial // and does not depend on another global objects. #if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__) @@ -892,7 +914,15 @@ signature, V8TestInterface5Methods, WTF_ARRAY_LENGTH(V8TestInterface5Methods)); // Indexed properties - v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(V8TestInterface5::indexedPropertyGetterCallback, V8TestInterface5::indexedPropertySetterCallback, nullptr, V8TestInterface5::indexedPropertyDeleterCallback, IndexedPropertyEnumerator<TestInterface5Implementation>, v8::Local<v8::Value>(), v8::PropertyHandlerFlags::kNone); + v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig( + V8TestInterface5::indexedPropertyGetterCallback, + V8TestInterface5::indexedPropertySetterCallback, + nullptr, + V8TestInterface5::indexedPropertyDeleterCallback, + IndexedPropertyEnumerator<TestInterface5Implementation>, + V8TestInterface5::indexedPropertyDefinerCallback, + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone); instanceTemplate->SetHandler(indexedPropertyHandlerConfig); // Named properties v8::NamedPropertyHandlerConfiguration namedPropertyHandlerConfig(V8TestInterface5::namedPropertyGetterCallback, V8TestInterface5::namedPropertySetterCallback, V8TestInterface5::namedPropertyQueryCallback, V8TestInterface5::namedPropertyDeleterCallback, V8TestInterface5::namedPropertyEnumeratorCallback, v8::Local<v8::Value>(), static_cast<v8::PropertyHandlerFlags>(int(v8::PropertyHandlerFlags::kOnlyInterceptStrings) | int(v8::PropertyHandlerFlags::kNonMasking)));
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.h b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.h index 80019b5..e7783c5 100644 --- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.h +++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.h
@@ -97,6 +97,7 @@ MODULES_EXPORT static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>&); MODULES_EXPORT static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&); MODULES_EXPORT static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>&); + MODULES_EXPORT static void indexedPropertyDefinerCallback(uint32_t index, const v8::PropertyDescriptor&, const v8::PropertyCallbackInfo<v8::Value>&); static void InstallRuntimeEnabledFeaturesOnTemplate( v8::Isolate*,
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp index c70683b..a80dfd1 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp +++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -963,34 +963,39 @@ // Calculation of absolute caret bounds requires clean layout. GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets(); - LayoutRect rect; + const VisibleSelection& selection = ComputeVisibleSelectionInDOMTree(); + if (selection.GetSelectionType() == kNoSelection) + return; - switch (ComputeVisibleSelectionInDOMTree().GetSelectionType()) { - case kNoSelection: - return; + LayoutRect rect; + switch (selection.GetSelectionType()) { case kCaretSelection: rect = LayoutRect(AbsoluteCaretBounds()); break; - case kRangeSelection: + case kRangeSelection: { rect = LayoutRect( reveal_extent_option == kRevealExtent - ? AbsoluteCaretBoundsOf(CreateVisiblePosition( - ComputeVisibleSelectionInDOMTree().Extent())) + ? AbsoluteCaretBoundsOf(CreateVisiblePosition(selection.Extent())) : AbsoluteSelectionBoundsOf(ComputeVisibleSelectionInFlatTree())); break; + } + default: + NOTREACHED(); + break; } - Position start = ComputeVisibleSelectionInDOMTree().Start(); + // FIXME: This code only handles scrolling the startContainer's layer, but + // the selection rect could intersect more than just that. + if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) + document_loader->GetInitialScrollState().was_scrolled_by_user = true; + const Position& start = selection.Start(); DCHECK(start.AnchorNode()); - if (start.AnchorNode() && start.AnchorNode()->GetLayoutObject()) { - // FIXME: This code only handles scrolling the startContainer's layer, but - // the selection rect could intersect more than just that. - if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) - document_loader->GetInitialScrollState().was_scrolled_by_user = true; - if (start.AnchorNode()->GetLayoutObject()->ScrollRectToVisible( - rect, alignment, alignment)) - UpdateAppearance(); - } + DCHECK(start.AnchorNode()->GetLayoutObject()); + if (!start.AnchorNode()->GetLayoutObject()->ScrollRectToVisible( + rect, alignment, alignment)) + return; + + UpdateAppearance(); } void FrameSelection::SetSelectionFromNone() {
diff --git a/third_party/WebKit/Source/core/editing/SelectionModifier.cpp b/third_party/WebKit/Source/core/editing/SelectionModifier.cpp index 8f61fe1..36b7d35 100644 --- a/third_party/WebKit/Source/core/editing/SelectionModifier.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionModifier.cpp
@@ -178,17 +178,24 @@ SkipWhitespace(position_after_current_word.DeepEquivalent())); } -static void AdjustPositionForUserSelectAll(VisiblePosition& pos, - bool is_forward) { - if (Node* root_user_select_all = EditingStrategy::RootUserSelectAllForNode( - pos.DeepEquivalent().AnchorNode())) - pos = CreateVisiblePosition( - is_forward ? MostForwardCaretPosition( - Position::AfterNode(*root_user_select_all), - kCanCrossEditingBoundary) - : MostBackwardCaretPosition( - Position::BeforeNode(*root_user_select_all), - kCanCrossEditingBoundary)); +static VisiblePosition AdjustForwardPositionForUserSelectAll( + VisiblePosition& position) { + Node* const root_user_select_all = EditingStrategy::RootUserSelectAllForNode( + position.DeepEquivalent().AnchorNode()); + if (!root_user_select_all) + return position; + return CreateVisiblePosition(MostForwardCaretPosition( + Position::AfterNode(*root_user_select_all), kCanCrossEditingBoundary)); +} + +static VisiblePosition AdjustBackwardPositionForUserSelectAll( + VisiblePosition& position) { + Node* const root_user_select_all = EditingStrategy::RootUserSelectAllForNode( + position.DeepEquivalent().AnchorNode()); + if (!root_user_select_all) + return position; + return CreateVisiblePosition(MostBackwardCaretPosition( + Position::BeforeNode(*root_user_select_all), kCanCrossEditingBoundary)); } VisiblePosition SelectionModifier::ModifyExtendingRight( @@ -231,9 +238,9 @@ pos = ModifyExtendingForward(granularity); break; } - AdjustPositionForUserSelectAll( - pos, DirectionOfEnclosingBlock() == TextDirection::kLtr); - return pos; + if (DirectionOfEnclosingBlock() == TextDirection::kLtr) + return AdjustForwardPositionForUserSelectAll(pos); + return AdjustBackwardPositionForUserSelectAll(pos); } VisiblePosition SelectionModifier::ModifyExtendingForward( @@ -275,9 +282,9 @@ pos = EndOfDocument(pos); break; } - AdjustPositionForUserSelectAll( - pos, DirectionOfEnclosingBlock() == TextDirection::kLtr); - return pos; + if (DirectionOfEnclosingBlock() == TextDirection::kLtr) + return AdjustForwardPositionForUserSelectAll(pos); + return AdjustBackwardPositionForUserSelectAll(pos); } VisiblePosition SelectionModifier::ModifyMovingRight( @@ -410,9 +417,9 @@ pos = ModifyExtendingBackward(granularity); break; } - AdjustPositionForUserSelectAll( - pos, !(DirectionOfEnclosingBlock() == TextDirection::kLtr)); - return pos; + if (DirectionOfEnclosingBlock() == TextDirection::kLtr) + return AdjustBackwardPositionForUserSelectAll(pos); + return AdjustForwardPositionForUserSelectAll(pos); } VisiblePosition SelectionModifier::ModifyExtendingBackward( @@ -459,9 +466,9 @@ pos = StartOfDocument(pos); break; } - AdjustPositionForUserSelectAll( - pos, !(DirectionOfEnclosingBlock() == TextDirection::kLtr)); - return pos; + if (DirectionOfEnclosingBlock() == TextDirection::kLtr) + return AdjustBackwardPositionForUserSelectAll(pos); + return AdjustForwardPositionForUserSelectAll(pos); } VisiblePosition SelectionModifier::ModifyMovingLeft(
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.cpp b/third_party/WebKit/Source/core/frame/DOMWindow.cpp index 0f86edb..6d83f2a 100644 --- a/third_party/WebKit/Source/core/frame/DOMWindow.cpp +++ b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
@@ -118,18 +118,6 @@ return child ? child->DomWindow() : nullptr; } -bool DOMWindow::AnonymousIndexedSetter(uint32_t index, - const ScriptValue& value) { - // https://html.spec.whatwg.org/C/browsers.html#windowproxy-defineownproperty - // step 2 - 1. If P is an array index property name, return false. - // - // As an alternative way to implement WindowProxy.[[DefineOwnProperty]] for - // array index property names, we always intercept and ignore the set - // operation for indexed properties, i.e. [[DefineOwnProperty]] for array - // index property names has always no effect. - return true; // Intercept unconditionally but do nothing. -} - bool DOMWindow::IsCurrentlyDisplayedInFrame() const { if (GetFrame()) SECURITY_CHECK(GetFrame()->DomWindow() == this);
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.h b/third_party/WebKit/Source/core/frame/DOMWindow.h index 0312de7..3146b000 100644 --- a/third_party/WebKit/Source/core/frame/DOMWindow.h +++ b/third_party/WebKit/Source/core/frame/DOMWindow.h
@@ -22,7 +22,6 @@ class LocalDOMWindow; class Location; class MessageEvent; -class ScriptValue; class SerializedScriptValue; class WindowProxyManager; @@ -89,7 +88,6 @@ // Indexed properties DOMWindow* AnonymousIndexedGetter(uint32_t index) const; - bool AnonymousIndexedSetter(uint32_t index, const ScriptValue&); void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray&,
diff --git a/third_party/WebKit/Source/core/frame/Window.idl b/third_party/WebKit/Source/core/frame/Window.idl index b251a243..f1b8629 100644 --- a/third_party/WebKit/Source/core/frame/Window.idl +++ b/third_party/WebKit/Source/core/frame/Window.idl
@@ -68,8 +68,6 @@ // indexed properties // https://html.spec.whatwg.org/C/browsers.html#windowproxy-getownproperty [NotEnumerable, CrossOrigin] getter Window (unsigned long index); - // https://html.spec.whatwg.org/C/browsers.html#windowproxy-defineownproperty - setter void (unsigned long index, any value); // named properties [Custom, NotEnumerable, CrossOrigin] getter object (DOMString name);
diff --git a/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp b/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp index e1dc576..de64a5b 100644 --- a/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp +++ b/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
@@ -227,10 +227,7 @@ } if (type == Resource::kScript || type == Resource::kImportResource) { - if (GetContentSettingsClient() && - !GetContentSettingsClient()->AllowScriptFromSource( - !GetSettings() || GetSettings()->GetScriptEnabled(), url)) { - GetContentSettingsClient()->DidNotAllowScript(); + if (!AllowScriptFromSource(url)) { // TODO(estark): Use a different ResourceRequestBlockedReason here, since // this check has nothing to do with CSP. https://crbug.com/600795 return ResourceRequestBlockedReason::CSP;
diff --git a/third_party/WebKit/Source/core/loader/BaseFetchContext.h b/third_party/WebKit/Source/core/loader/BaseFetchContext.h index 8015dc5..d843291 100644 --- a/third_party/WebKit/Source/core/loader/BaseFetchContext.h +++ b/third_party/WebKit/Source/core/loader/BaseFetchContext.h
@@ -18,10 +18,8 @@ namespace blink { class ConsoleMessage; -class ContentSettingsClient; class KURL; class SecurityOrigin; -class Settings; class SubresourceFilter; // A core-level implementaiton of FetchContext that does not depend on @@ -57,10 +55,8 @@ virtual void CountDeprecation(WebFeature) const = 0; protected: - // Used for security checks. It is valid that they return nullptr, - // while returning nullptr may result in disable some security checks. - virtual ContentSettingsClient* GetContentSettingsClient() const = 0; - virtual Settings* GetSettings() const = 0; + // Used for security checks. + virtual bool AllowScriptFromSource(const KURL&) const = 0; virtual SubresourceFilter* GetSubresourceFilter() const = 0; // Note: subclasses are expected to override following methods.
diff --git a/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp index 0dda279..eef0b19 100644 --- a/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp +++ b/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp
@@ -45,10 +45,7 @@ // BaseFetchContext overrides: KURL GetFirstPartyForCookies() const override { return KURL(); } - ContentSettingsClient* GetContentSettingsClient() const override { - return nullptr; - } - Settings* GetSettings() const override { return nullptr; } + bool AllowScriptFromSource(const KURL&) const { return false; } SubresourceFilter* GetSubresourceFilter() const override { return nullptr; } bool ShouldBlockRequestByInspector(const ResourceRequest&) const override { return false;
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp index 16c4ab0..811342a 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -298,8 +298,7 @@ if (IsReloadLoadType(MasterDocumentLoader()->LoadType())) request.ClearHTTPHeaderField("Save-Data"); - if (GetFrame()->GetSettings() && - GetFrame()->GetSettings()->GetDataSaverEnabled()) + if (GetSettings() && GetSettings()->GetDataSaverEnabled()) request.SetHTTPHeaderField("Save-Data", "on"); if (GetLocalFrameClient()->IsClientLoFiActiveForFrame()) { @@ -889,17 +888,15 @@ ->Archive(); } -ContentSettingsClient* FrameFetchContext::GetContentSettingsClient() const { - if (IsDetached()) - return nullptr; - return GetFrame()->GetContentSettingsClient(); -} - -Settings* FrameFetchContext::GetSettings() const { - if (IsDetached()) - return nullptr; - DCHECK(GetFrame()); - return GetFrame()->GetSettings(); +bool FrameFetchContext::AllowScriptFromSource(const KURL& url) const { + ContentSettingsClient* settings_client = GetContentSettingsClient(); + Settings* settings = GetSettings(); + if (settings_client && !settings_client->AllowScriptFromSource( + !settings || settings->GetScriptEnabled(), url)) { + settings_client->DidNotAllowScript(); + return false; + } + return true; } SubresourceFilter* FrameFetchContext::GetSubresourceFilter() const { @@ -1039,6 +1036,19 @@ document_->AddConsoleMessage(message); } +ContentSettingsClient* FrameFetchContext::GetContentSettingsClient() const { + if (IsDetached()) + return nullptr; + return GetFrame()->GetContentSettingsClient(); +} + +Settings* FrameFetchContext::GetSettings() const { + if (IsDetached()) + return nullptr; + DCHECK(GetFrame()); + return GetFrame()->GetSettings(); +} + String FrameFetchContext::GetUserAgent() const { if (IsDetached()) return frozen_state_->user_agent; @@ -1098,6 +1108,17 @@ } else { task_runner = GetTaskRunner(); } + + if (MasterDocumentLoader()->GetServiceWorkerNetworkProvider()) { + WrappedResourceRequest webreq(request); + auto loader = + MasterDocumentLoader() + ->GetServiceWorkerNetworkProvider() + ->CreateURLLoader(webreq, task_runner->ToSingleThreadTaskRunner()); + if (loader) + return loader; + } + return GetFrame()->CreateURLLoader(request, task_runner.Get()); }
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.h b/third_party/WebKit/Source/core/loader/FrameFetchContext.h index d59f33e3..a9d3315 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContext.h +++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
@@ -52,6 +52,7 @@ class LocalFrameClient; class ResourceError; class ResourceResponse; +class Settings; class WebTaskRunner; class CORE_EXPORT FrameFetchContext final : public BaseFetchContext { @@ -184,8 +185,7 @@ // BaseFetchContext overrides: KURL GetFirstPartyForCookies() const override; - ContentSettingsClient* GetContentSettingsClient() const override; - Settings* GetSettings() const override; + bool AllowScriptFromSource(const KURL&) const override; SubresourceFilter* GetSubresourceFilter() const override; bool ShouldBlockRequestByInspector(const ResourceRequest&) const override; void DispatchDidBlockRequest(const ResourceRequest&, @@ -210,6 +210,8 @@ const ContentSecurityPolicy* GetContentSecurityPolicy() const override; void AddConsoleMessage(ConsoleMessage*) const override; + ContentSettingsClient* GetContentSettingsClient() const; + Settings* GetSettings() const; String GetUserAgent() const; RefPtr<SecurityOrigin> GetRequestorOrigin(); RefPtr<SecurityOrigin> GetRequestorOriginForFrameLoading();
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp index 8dd557a..4160cfa2 100644 --- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp +++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
@@ -93,14 +93,14 @@ return web_context_->FirstPartyForCookies(); } -ContentSettingsClient* WorkerFetchContext::GetContentSettingsClient() const { - // TODO(horo): Implement this. - return nullptr; -} - -Settings* WorkerFetchContext::GetSettings() const { - // TODO(horo): Implement this. - return nullptr; +bool WorkerFetchContext::AllowScriptFromSource(const KURL&) const { + // Currently we don't use WorkerFetchContext for loading scripts. So this + // method must not be called. + // TODO(horo): When we will use WorkerFetchContext for loading scripts, we + // need to have a copy the script rules of RendererContentSettingRules on the + // worker thread. + NOTREACHED(); + return false; } SubresourceFilter* WorkerFetchContext::GetSubresourceFilter() const {
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.h b/third_party/WebKit/Source/core/loader/WorkerFetchContext.h index 4ef5bba4..6cd9bea4 100644 --- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.h +++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
@@ -37,8 +37,7 @@ // BaseFetchContext implementation: KURL GetFirstPartyForCookies() const override; - ContentSettingsClient* GetContentSettingsClient() const override; - Settings* GetSettings() const override; + bool AllowScriptFromSource(const KURL&) const override; SubresourceFilter* GetSubresourceFilter() const override; bool ShouldBlockRequestByInspector(const ResourceRequest&) const override; void DispatchDidBlockRequest(const ResourceRequest&,
diff --git a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp index b3075646..75aaa58 100644 --- a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp +++ b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
@@ -50,6 +50,12 @@ // that we would ever need. The current UMA stats indicates that this is, in // fact, probably too small. There are Android devices out there with a size of // 8000 or so. We might need to make this larger. See: crbug.com/670747 +// TODO(andrew.macpherson): This either needs to be bigger since some OSes allow +// buffer sizes of 8192 via latencyHint now or else we need to do some +// validation of the latencyHint 'exact' size before passing it to +// CreateAudioDevice. Clamping may be tricky though as the buffer size is +// dependent on the sample rate for some platforms and we're passing in a time +// value and not a buffer size in the latencyHint. See: crbug.com/737047 const size_t kFIFOSize = 8192; std::unique_ptr<AudioDestination> AudioDestination::Create(
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h index 3092806..dc2a9d3 100644 --- a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h +++ b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h
@@ -31,6 +31,10 @@ #ifndef WebServiceWorkerNetworkProvider_h #define WebServiceWorkerNetworkProvider_h +#include <memory> + +#include "public/platform/WebURLLoader.h" + namespace blink { class WebURLRequest; @@ -61,6 +65,16 @@ // Returns an identifier of the service worker controlling the document // associated with the WebDataSource. virtual int64_t ServiceWorkerID() { return -1; } + + // Returns a URLLoader for the associated context. May return nullptr + // if this doesn't provide a ServiceWorker specific URLLoader. + // Currently this returns non-null only for a controller worker case + // and only if servicification is enabled. + virtual std::unique_ptr<WebURLLoader> CreateURLLoader( + const WebURLRequest& request, + base::SingleThreadTaskRunner* task_runner) { + return nullptr; + } }; } // namespace blink
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 8b6c8a6..32fb755 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-8-61 -Revision: c56d8851ea987023cc73981a70d261b3f6427545 +Version: VER-2-8-64 +Revision: cf8d9b4ce3fa2c6cd9ccb25585bc17a355c987b0 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses" License File: src/docs/FTL.TXT
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 31c5963..d0fcbaf 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -36138,6 +36138,12 @@ <int value="3" label="CUSTOM_PASSPHRASE"/> </enum> +<enum name="SyncPasswordHashChange"> + <int value="0" label="Saved on Chrome sign-in"/> + <int value="1" label="Saved in the content area"/> + <int value="2" label="Cleared on Chrome sign-out"/> +</enum> + <enum name="SyncPromoAction"> <int value="0" label="The promo was shown to the user"/> <int value="1" label="The user clicked the promo to sign in"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index f2805470..6c1a5189 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -52829,6 +52829,16 @@ </summary> </histogram> +<histogram name="PasswordManager.SyncPasswordHashChange" + enum="SyncPasswordHashChange"> + <owner>dvadym@chromium.org</owner> + <owner>nparker@chromium.org</owner> + <summary> + This metric reports a type of a sync password hash change event. Recorded + when a sync password hash is saved or cleared. + </summary> +</histogram> + <histogram name="PasswordManager.TimesGeneratedPasswordUsed"> <obsolete> Deprecated as of 11/11/14. New statistic is @@ -71261,6 +71271,14 @@ </summary> </histogram> +<histogram name="Signin.AndroidGetAccountsTimeUiThread" units="ms"> + <owner>bsazonov@chromium.org</owner> + <summary> + The time it takes to retrieve the list of accounts from the system on the UI + thread. + </summary> +</histogram> + <histogram name="Signin.AndroidSigninPromoAction" enum="AndroidSigninPromoAction"> <obsolete> @@ -88238,6 +88256,7 @@ <suffix name="AccountManager" label="Using Android AccountManager API"/> <suffix name="GoogleAuthUtil" label="Using GoogleAuthUtil API"/> <affected-histogram name="Signin.AndroidGetAccountsTime"/> + <affected-histogram name="Signin.AndroidGetAccountsTimeUiThread"/> </histogram_suffixes> <histogram_suffixes name="AndroidTabPersistentStoreTime" separator="."> @@ -94438,6 +94457,8 @@ name="PageLoad.Clients.ServiceWorker.PaintTiming.NavigationToFirstContentfulPaint"/> <affected-histogram name="PageLoad.Clients.ServiceWorker.PaintTiming.ParseStartToFirstContentfulPaint"/> + <affected-histogram + name="PageLoad.Clients.ServiceWorker.ParseTiming.NavigationToParseStart"/> </histogram_suffixes> <histogram_suffixes name="PageLoadMetricsClientsSubresourceFilter"
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn index 99940ddeb..377026c 100644 --- a/ui/message_center/BUILD.gn +++ b/ui/message_center/BUILD.gn
@@ -268,7 +268,6 @@ "views/message_center_view_unittest.cc", "views/message_list_view_unittest.cc", "views/message_popup_collection_unittest.cc", - "views/notification_view_md_unittest.cc", "views/notification_view_unittest.cc", "views/notifier_settings_view_unittest.cc", ]
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc index 93c99752c..5426c6f 100644 --- a/ui/message_center/views/notification_view_md.cc +++ b/ui/message_center/views/notification_view_md.cc
@@ -117,8 +117,6 @@ explicit ItemView(const message_center::NotificationItem& item); ~ItemView() override; - const char* GetClassName() const override; - private: DISALLOW_COPY_AND_ASSIGN(ItemView); }; @@ -145,10 +143,6 @@ ItemView::~ItemView() = default; -const char* ItemView::GetClassName() const { - return "ItemView"; -} - // CompactTitleMessageView ///////////////////////////////////////////////////// // CompactTitleMessageView shows notification title and message in a single @@ -158,8 +152,6 @@ explicit CompactTitleMessageView(); ~CompactTitleMessageView() override; - const char* GetClassName() const override; - void OnPaint(gfx::Canvas* canvas) override; void set_title(const base::string16& title) { title_ = title; } @@ -175,11 +167,7 @@ views::Label* message_view_ = nullptr; }; -CompactTitleMessageView::~CompactTitleMessageView() = default; - -const char* CompactTitleMessageView::GetClassName() const { - return "CompactTitleMessageView"; -} +CompactTitleMessageView::~CompactTitleMessageView() {} CompactTitleMessageView::CompactTitleMessageView() { SetLayoutManager(new views::FillLayout()); @@ -242,7 +230,6 @@ ~NotificationButtonMD() override; void SetText(const base::string16& text) override; - const char* GetClassName() const override; std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight() const override; @@ -273,10 +260,6 @@ views::LabelButton::SetText(base::i18n::ToUpper(text)); } -const char* NotificationButtonMD::GetClassName() const { - return "NotificationButtonMD"; -} - std::unique_ptr<views::InkDropHighlight> NotificationButtonMD::CreateInkDropHighlight() const { std::unique_ptr<views::InkDropHighlight> highlight = @@ -332,12 +315,10 @@ CreateOrUpdateIconView(notification); CreateOrUpdateSmallIconView(notification); CreateOrUpdateImageView(notification); + CreateOrUpdateActionButtonViews(notification); CreateOrUpdateCloseButtonView(notification); CreateOrUpdateSettingsButtonView(notification); UpdateViewForExpandedState(expanded_); - // Should be called at the last because SynthesizeMouseMoveEvent() requires - // everything is in the right location when called. - CreateOrUpdateActionButtonViews(notification); } NotificationViewMD::NotificationViewMD(MessageCenterController* controller, @@ -502,10 +483,8 @@ void NotificationViewMD::CreateOrUpdateTitleView( const Notification& notification) { - if (notification.title().empty() || - notification.type() == NOTIFICATION_TYPE_PROGRESS) { - if (title_view_) - left_content_->RemoveChildView(title_view_); + if (notification.type() == NOTIFICATION_TYPE_PROGRESS) { + left_content_->RemoveChildView(title_view_); title_view_ = nullptr; return; } @@ -560,8 +539,7 @@ void NotificationViewMD::CreateOrUpdateCompactTitleMessageView( const Notification& notification) { if (notification.type() != NOTIFICATION_TYPE_PROGRESS) { - if (compact_title_message_view_) - left_content_->RemoveChildView(compact_title_message_view_); + left_content_->RemoveChildView(compact_title_message_view_); compact_title_message_view_ = nullptr; return; } @@ -578,8 +556,7 @@ void NotificationViewMD::CreateOrUpdateProgressBarView( const Notification& notification) { if (notification.type() != NOTIFICATION_TYPE_PROGRESS) { - if (progress_bar_view_) - left_content_->RemoveChildView(progress_bar_view_); + left_content_->RemoveChildView(progress_bar_view_); progress_bar_view_ = nullptr; header_row_->ClearProgress(); return; @@ -627,8 +604,7 @@ const Notification& notification) { if (notification.type() == NOTIFICATION_TYPE_PROGRESS || notification.type() == NOTIFICATION_TYPE_MULTIPLE) { - if (icon_view_) - right_content_->RemoveChildView(icon_view_); + right_content_->RemoveChildView(icon_view_); icon_view_ = nullptr; return; } @@ -720,14 +696,11 @@ } } - // Inherit mouse hover state when action button views reset. - // If the view is not expanded, there should be no hover state. - if (new_buttons && expanded_) { + if (new_buttons) { + // TODO(fukino): Investigate if this Layout() is necessary. + Layout(); views::Widget* widget = GetWidget(); - if (widget) { - // This Layout() is needed because button should be in the right location - // in the view hierarchy when SynthesizeMouseMoveEvent() is called. - Layout(); + if (widget != NULL) { widget->SetSize(widget->GetContentsView()->GetPreferredSize()); GetWidget()->SynthesizeMouseMoveEvent(); }
diff --git a/ui/message_center/views/notification_view_md.h b/ui/message_center/views/notification_view_md.h index 547d112d..890165a 100644 --- a/ui/message_center/views/notification_view_md.h +++ b/ui/message_center/views/notification_view_md.h
@@ -64,13 +64,6 @@ views::View* TargetForRect(views::View* root, const gfx::Rect& rect) override; private: - FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, CreateOrUpdateTest); - FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, TestIconSizing); - FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UpdateButtonsStateTest); - FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UpdateButtonCountTest); - - friend class NotificationViewMDTest; - void CreateOrUpdateViews(const Notification& notification); void CreateOrUpdateContextTitleView(const Notification& notification);
diff --git a/ui/message_center/views/notification_view_md_unittest.cc b/ui/message_center/views/notification_view_md_unittest.cc deleted file mode 100644 index 9baa68c..0000000 --- a/ui/message_center/views/notification_view_md_unittest.cc +++ /dev/null
@@ -1,501 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/message_center/views/notification_view_md.h" - -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/compositor/scoped_animation_duration_scale_mode.h" -#include "ui/events/event_processor.h" -#include "ui/events/event_utils.h" -#include "ui/events/test/event_generator.h" -#include "ui/gfx/canvas.h" -#include "ui/message_center/message_center_style.h" -#include "ui/message_center/views/message_center_controller.h" -#include "ui/message_center/views/notification_header_view.h" -#include "ui/message_center/views/proportional_image_view.h" -#include "ui/views/controls/button/image_button.h" -#include "ui/views/controls/button/label_button.h" -#include "ui/views/test/views_test_base.h" -#include "ui/views/test/widget_test.h" - -namespace message_center { - -/* Test fixture ***************************************************************/ - -// Used to fill bitmaps returned by CreateBitmap(). -static const SkColor kBitmapColor = SK_ColorGREEN; - -class NotificationViewMDTest : public views::ViewsTestBase, - public MessageCenterController { - public: - NotificationViewMDTest(); - ~NotificationViewMDTest() override; - - // Overridden from ViewsTestBase: - void SetUp() override; - void TearDown() override; - - // Overridden from MessageCenterController: - void ClickOnNotification(const std::string& notification_id) override; - void RemoveNotification(const std::string& notification_id, - bool by_user) override; - std::unique_ptr<ui::MenuModel> CreateMenuModel( - const NotifierId& notifier_id, - const base::string16& display_source) override; - bool HasClickedListener(const std::string& notification_id) override; - void ClickOnNotificationButton(const std::string& notification_id, - int button_index) override; - void ClickOnSettingsButton(const std::string& notification_id) override; - void UpdateNotificationSize(const std::string& notification_id) override; - - NotificationViewMD* notification_view() const { - return notification_view_.get(); - } - Notification* notification() const { return notification_.get(); } - views::Widget* widget() const { - DCHECK_EQ(widget_, notification_view()->GetWidget()); - return widget_; - } - - protected: - const gfx::Image CreateTestImage(int width, int height); - const SkBitmap CreateBitmap(int width, int height); - std::vector<ButtonInfo> CreateButtons(int number); - - // Paints |view| and returns the size that the original image (which must have - // been created by CreateBitmap()) was scaled to. - gfx::Size GetImagePaintSize(ProportionalImageView* view); - - void UpdateNotificationViews(); - float GetNotificationSlideAmount() const; - bool IsRemoved(const std::string& notification_id) const; - void DispatchGesture(const ui::GestureEventDetails& details); - void BeginScroll(); - void EndScroll(); - void ScrollBy(int dx); - views::ImageButton* GetCloseButton(); - - private: - std::set<std::string> removed_ids_; - - std::unique_ptr<RichNotificationData> data_; - std::unique_ptr<Notification> notification_; - std::unique_ptr<NotificationViewMD> notification_view_; - views::Widget* widget_; - - DISALLOW_COPY_AND_ASSIGN(NotificationViewMDTest); -}; - -NotificationViewMDTest::NotificationViewMDTest() = default; -NotificationViewMDTest::~NotificationViewMDTest() = default; - -void NotificationViewMDTest::SetUp() { - views::ViewsTestBase::SetUp(); - // Create a dummy notification. - data_.reset(new RichNotificationData()); - notification_.reset(new Notification( - NOTIFICATION_TYPE_BASE_FORMAT, std::string("notification id"), - base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message"), - CreateTestImage(80, 80), base::UTF8ToUTF16("display source"), GURL(), - NotifierId(NotifierId::APPLICATION, "extension_id"), *data_, nullptr)); - notification_->set_small_image(CreateTestImage(16, 16)); - notification_->set_image(CreateTestImage(320, 240)); - - // Then create a new NotificationView with that single notification. - // In the actual code path, this is instantiated by - // MessageViewFactory::Create. - // TODO(tetsui): Confirm that NotificationViewMD options are same as one - // created by the method. - notification_view_.reset(new NotificationViewMD(this, *notification_)); - notification_view_->SetIsNested(); - notification_view_->set_owned_by_client(); - - views::Widget::InitParams init_params( - CreateParams(views::Widget::InitParams::TYPE_POPUP)); - widget_ = new views::Widget(); - widget_->Init(init_params); - widget_->SetContentsView(notification_view_.get()); - widget_->SetSize(notification_view_->GetPreferredSize()); - widget_->Show(); -} - -void NotificationViewMDTest::TearDown() { - widget()->Close(); - notification_view_.reset(); - views::ViewsTestBase::TearDown(); -} - -void NotificationViewMDTest::ClickOnNotification( - const std::string& notification_id) { - // For this test, this method should not be invoked. - NOTREACHED(); -} - -void NotificationViewMDTest::RemoveNotification( - const std::string& notification_id, - bool by_user) { - removed_ids_.insert(notification_id); -} - -std::unique_ptr<ui::MenuModel> NotificationViewMDTest::CreateMenuModel( - const NotifierId& notifier_id, - const base::string16& display_source) { - // For this test, this method should not be invoked. - NOTREACHED(); - return nullptr; -} - -bool NotificationViewMDTest::HasClickedListener( - const std::string& notification_id) { - return true; -} - -void NotificationViewMDTest::ClickOnNotificationButton( - const std::string& notification_id, - int button_index) { - // For this test, this method should not be invoked. - NOTREACHED(); -} - -void NotificationViewMDTest::ClickOnSettingsButton( - const std::string& notification_id) { - // For this test, this method should not be invoked. - NOTREACHED(); -} - -void NotificationViewMDTest::UpdateNotificationSize( - const std::string& notification_id) { - widget()->SetSize(notification_view()->GetPreferredSize()); -} - -const gfx::Image NotificationViewMDTest::CreateTestImage(int width, - int height) { - return gfx::Image::CreateFrom1xBitmap(CreateBitmap(width, height)); -} - -const SkBitmap NotificationViewMDTest::CreateBitmap(int width, int height) { - SkBitmap bitmap; - bitmap.allocN32Pixels(width, height); - bitmap.eraseColor(kBitmapColor); - return bitmap; -} - -std::vector<ButtonInfo> NotificationViewMDTest::CreateButtons(int number) { - ButtonInfo info(base::ASCIIToUTF16("Test button.")); - info.icon = CreateTestImage(4, 4); - return std::vector<ButtonInfo>(number, info); -} - -gfx::Size NotificationViewMDTest::GetImagePaintSize( - ProportionalImageView* view) { - CHECK(view); - if (view->bounds().IsEmpty()) - return gfx::Size(); - - gfx::Size canvas_size = view->bounds().size(); - gfx::Canvas canvas(canvas_size, 1.0 /* image_scale */, true /* is_opaque */); - static_assert(kBitmapColor != SK_ColorBLACK, - "The bitmap color must match the background color"); - canvas.DrawColor(SK_ColorBLACK); - view->OnPaint(&canvas); - - SkBitmap bitmap = canvas.GetBitmap(); - // Incrementally inset each edge at its midpoint to find the bounds of the - // rect containing the image's color. This assumes that the image is - // centered in the canvas. - const int kHalfWidth = canvas_size.width() / 2; - const int kHalfHeight = canvas_size.height() / 2; - gfx::Rect rect(canvas_size); - while (rect.width() > 0 && - bitmap.getColor(rect.x(), kHalfHeight) != kBitmapColor) - rect.Inset(1, 0, 0, 0); - while (rect.height() > 0 && - bitmap.getColor(kHalfWidth, rect.y()) != kBitmapColor) - rect.Inset(0, 1, 0, 0); - while (rect.width() > 0 && - bitmap.getColor(rect.right() - 1, kHalfHeight) != kBitmapColor) - rect.Inset(0, 0, 1, 0); - while (rect.height() > 0 && - bitmap.getColor(kHalfWidth, rect.bottom() - 1) != kBitmapColor) - rect.Inset(0, 0, 0, 1); - - return rect.size(); -} - -void NotificationViewMDTest::UpdateNotificationViews() { - notification_view()->UpdateWithNotification(*notification()); -} - -float NotificationViewMDTest::GetNotificationSlideAmount() const { - return notification_view_->GetSlideOutLayer() - ->transform() - .To2dTranslation() - .x(); -} - -bool NotificationViewMDTest::IsRemoved( - const std::string& notification_id) const { - return (removed_ids_.find(notification_id) != removed_ids_.end()); -} - -void NotificationViewMDTest::DispatchGesture( - const ui::GestureEventDetails& details) { - ui::test::EventGenerator generator( - notification_view()->GetWidget()->GetNativeWindow()); - ui::GestureEvent event(0, 0, 0, ui::EventTimeForNow(), details); - generator.Dispatch(&event); -} - -void NotificationViewMDTest::BeginScroll() { - DispatchGesture(ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN)); -} - -void NotificationViewMDTest::EndScroll() { - DispatchGesture(ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END)); -} - -void NotificationViewMDTest::ScrollBy(int dx) { - DispatchGesture(ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, dx, 0)); -} - -views::ImageButton* NotificationViewMDTest::GetCloseButton() { - return notification_view()->header_row_->close_button(); -} - -/* Unit tests *****************************************************************/ - -// TODO(tetsui): Following tests are not yet ported from NotificationViewTest. -// * CreateOrUpdateTestSettingsButton -// * TestLineLimits -// * TestImageSizing -// * SettingsButtonTest -// * ViewOrderingTest -// * FormatContextMessageTest - -TEST_F(NotificationViewMDTest, CreateOrUpdateTest) { - EXPECT_NE(nullptr, notification_view()->title_view_); - EXPECT_NE(nullptr, notification_view()->message_view_); - EXPECT_NE(nullptr, notification_view()->icon_view_); - EXPECT_NE(nullptr, notification_view()->image_view_); - - notification()->set_image(gfx::Image()); - notification()->set_title(base::string16()); - notification()->set_message(base::string16()); - notification()->set_icon(gfx::Image()); - - notification_view()->CreateOrUpdateViews(*notification()); - - EXPECT_EQ(nullptr, notification_view()->title_view_); - EXPECT_EQ(nullptr, notification_view()->message_view_); - EXPECT_EQ(nullptr, notification_view()->image_view_); - // We still expect an icon view for all layouts. - EXPECT_NE(nullptr, notification_view()->icon_view_); -} - -TEST_F(NotificationViewMDTest, TestIconSizing) { - // TODO(tetsui): Remove duplicated integer literal in CreateOrUpdateIconView. - const int kNotificationIconSize = 30; - - notification()->set_type(NOTIFICATION_TYPE_SIMPLE); - ProportionalImageView* view = notification_view()->icon_view_; - - // Icons smaller than the maximum size should remain unscaled. - notification()->set_icon( - CreateTestImage(kNotificationIconSize / 2, kNotificationIconSize / 4)); - UpdateNotificationViews(); - EXPECT_EQ(gfx::Size(kNotificationIconSize / 2, kNotificationIconSize / 4) - .ToString(), - GetImagePaintSize(view).ToString()); - - // Icons of exactly the intended icon size should remain unscaled. - notification()->set_icon( - CreateTestImage(kNotificationIconSize, kNotificationIconSize)); - UpdateNotificationViews(); - EXPECT_EQ(gfx::Size(kNotificationIconSize, kNotificationIconSize).ToString(), - GetImagePaintSize(view).ToString()); - - // Icons over the maximum size should be scaled down, maintaining proportions. - notification()->set_icon( - CreateTestImage(2 * kNotificationIconSize, 2 * kNotificationIconSize)); - UpdateNotificationViews(); - EXPECT_EQ(gfx::Size(kNotificationIconSize, kNotificationIconSize).ToString(), - GetImagePaintSize(view).ToString()); - - notification()->set_icon( - CreateTestImage(4 * kNotificationIconSize, 2 * kNotificationIconSize)); - UpdateNotificationViews(); - EXPECT_EQ( - gfx::Size(kNotificationIconSize, kNotificationIconSize / 2).ToString(), - GetImagePaintSize(view).ToString()); -} - -TEST_F(NotificationViewMDTest, UpdateButtonsStateTest) { - notification()->set_buttons(CreateButtons(2)); - notification_view()->CreateOrUpdateViews(*notification()); - widget()->Show(); - - // Action buttons are hidden by collapsed state. - if (!notification_view()->expanded_) - notification_view()->ToggleExpanded(); - EXPECT_TRUE(notification_view()->actions_row_->visible()); - - EXPECT_EQ(views::CustomButton::STATE_NORMAL, - notification_view()->action_buttons_[0]->state()); - - // Now construct a mouse move event 1 pixel inside the boundary of the action - // button. - gfx::Point cursor_location(1, 1); - views::View::ConvertPointToWidget(notification_view()->action_buttons_[0], - &cursor_location); - ui::MouseEvent move(ui::ET_MOUSE_MOVED, cursor_location, cursor_location, - ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); - widget()->OnMouseEvent(&move); - - EXPECT_EQ(views::CustomButton::STATE_HOVERED, - notification_view()->action_buttons_[0]->state()); - - notification_view()->CreateOrUpdateViews(*notification()); - - EXPECT_EQ(views::CustomButton::STATE_HOVERED, - notification_view()->action_buttons_[0]->state()); - - // Now construct a mouse move event 1 pixel outside the boundary of the - // widget. - cursor_location = gfx::Point(-1, -1); - move = ui::MouseEvent(ui::ET_MOUSE_MOVED, cursor_location, cursor_location, - ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); - widget()->OnMouseEvent(&move); - - EXPECT_EQ(views::CustomButton::STATE_NORMAL, - notification_view()->action_buttons_[0]->state()); -} - -TEST_F(NotificationViewMDTest, UpdateButtonCountTest) { - notification()->set_buttons(CreateButtons(2)); - notification_view()->UpdateWithNotification(*notification()); - widget()->Show(); - - // Action buttons are hidden by collapsed state. - if (!notification_view()->expanded_) - notification_view()->ToggleExpanded(); - EXPECT_TRUE(notification_view()->actions_row_->visible()); - - EXPECT_EQ(views::CustomButton::STATE_NORMAL, - notification_view()->action_buttons_[0]->state()); - EXPECT_EQ(views::CustomButton::STATE_NORMAL, - notification_view()->action_buttons_[1]->state()); - - // Now construct a mouse move event 1 pixel inside the boundary of the action - // button. - gfx::Point cursor_location(1, 1); - views::View::ConvertPointToScreen(notification_view()->action_buttons_[0], - &cursor_location); - ui::MouseEvent move(ui::ET_MOUSE_MOVED, cursor_location, cursor_location, - ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); - ui::EventDispatchDetails details = - views::test::WidgetTest::GetEventSink(widget())->OnEventFromSource(&move); - EXPECT_FALSE(details.dispatcher_destroyed); - - EXPECT_EQ(views::CustomButton::STATE_HOVERED, - notification_view()->action_buttons_[0]->state()); - EXPECT_EQ(views::CustomButton::STATE_NORMAL, - notification_view()->action_buttons_[1]->state()); - - notification()->set_buttons(CreateButtons(1)); - notification_view()->UpdateWithNotification(*notification()); - - EXPECT_EQ(views::CustomButton::STATE_HOVERED, - notification_view()->action_buttons_[0]->state()); - EXPECT_EQ(1u, notification_view()->action_buttons_.size()); - - // Now construct a mouse move event 1 pixel outside the boundary of the - // widget. - cursor_location = gfx::Point(-1, -1); - move = ui::MouseEvent(ui::ET_MOUSE_MOVED, cursor_location, cursor_location, - ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); - widget()->OnMouseEvent(&move); - - EXPECT_EQ(views::CustomButton::STATE_NORMAL, - notification_view()->action_buttons_[0]->state()); -} - -TEST_F(NotificationViewMDTest, SlideOut) { - ui::ScopedAnimationDurationScaleMode zero_duration_scope( - ui::ScopedAnimationDurationScaleMode::ZERO_DURATION); - - UpdateNotificationViews(); - std::string notification_id = notification()->id(); - - BeginScroll(); - ScrollBy(-10); - EXPECT_FALSE(IsRemoved(notification_id)); - EXPECT_EQ(-10.f, GetNotificationSlideAmount()); - EndScroll(); - EXPECT_FALSE(IsRemoved(notification_id)); - EXPECT_EQ(0.f, GetNotificationSlideAmount()); - - BeginScroll(); - ScrollBy(-200); - EXPECT_FALSE(IsRemoved(notification_id)); - EXPECT_EQ(-200.f, GetNotificationSlideAmount()); - EndScroll(); - EXPECT_TRUE(IsRemoved(notification_id)); -} - -TEST_F(NotificationViewMDTest, SlideOutNested) { - ui::ScopedAnimationDurationScaleMode zero_duration_scope( - ui::ScopedAnimationDurationScaleMode::ZERO_DURATION); - - UpdateNotificationViews(); - notification_view()->SetIsNested(); - std::string notification_id = notification()->id(); - - BeginScroll(); - ScrollBy(-10); - EXPECT_FALSE(IsRemoved(notification_id)); - EXPECT_EQ(-10.f, GetNotificationSlideAmount()); - EndScroll(); - EXPECT_FALSE(IsRemoved(notification_id)); - EXPECT_EQ(0.f, GetNotificationSlideAmount()); - - BeginScroll(); - ScrollBy(-200); - EXPECT_FALSE(IsRemoved(notification_id)); - EXPECT_EQ(-200.f, GetNotificationSlideAmount()); - EndScroll(); - EXPECT_TRUE(IsRemoved(notification_id)); -} - -// Pinning notification is ChromeOS only feature. -#if defined(OS_CHROMEOS) - -TEST_F(NotificationViewMDTest, SlideOutPinned) { - ui::ScopedAnimationDurationScaleMode zero_duration_scope( - ui::ScopedAnimationDurationScaleMode::ZERO_DURATION); - - notification()->set_pinned(true); - UpdateNotificationViews(); - std::string notification_id = notification()->id(); - - BeginScroll(); - ScrollBy(-200); - EXPECT_FALSE(IsRemoved(notification_id)); - EXPECT_LT(-200.f, GetNotificationSlideAmount()); - EndScroll(); - EXPECT_FALSE(IsRemoved(notification_id)); -} - -TEST_F(NotificationViewMDTest, Pinned) { - notification()->set_pinned(true); - - UpdateNotificationViews(); - EXPECT_FALSE(GetCloseButton()->visible()); -} - -#endif // defined(OS_CHROMEOS) - -} // namespace message_center